LibGfx: Remove a bunch of unused classes

This commit is contained in:
Andreas Kling 2024-06-04 14:13:03 +02:00
commit 1b2d08ee7e
Notes: sideshowbarker 2024-07-17 09:56:35 +09:00
22 changed files with 0 additions and 1453 deletions

View file

@ -27,12 +27,8 @@ shared_library("LibGfx") {
"AffineTransform.cpp",
"AntiAliasingPainter.cpp",
"Bitmap.cpp",
"BitmapMixer.cpp",
"CMYKBitmap.cpp",
"ClassicStylePainter.cpp",
"ClassicWindowTheme.cpp",
"Color.cpp",
"CursorParams.cpp",
"DeltaE.cpp",
"EdgeFlagPathRasterizer.cpp",
"Filters/ColorBlindnessFilter.cpp",
@ -107,13 +103,11 @@ shared_library("LibGfx") {
"Rect.cpp",
"ShareableBitmap.cpp",
"Size.cpp",
"StylePainter.cpp",
"SystemTheme.cpp",
"TextDirection.cpp",
"TextLayout.cpp",
"Triangle.cpp",
"VectorGraphic.cpp",
"WindowTheme.cpp",
]
sources += get_target_outputs(":generate_tiff_sources")

View file

@ -1,48 +0,0 @@
/*
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "BitmapMixer.h"
namespace Gfx {
void BitmapMixer::mix_with(Bitmap& other_bitmap, MixingMethod mixing_method)
{
VERIFY(m_bitmap.size() == other_bitmap.size());
int height = m_bitmap.height();
int width = m_bitmap.width();
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
auto original_color = m_bitmap.get_pixel(x, y);
auto other_color = other_bitmap.get_pixel(x, y);
Color output_color = { 0, 0, 0, original_color.alpha() };
switch (mixing_method) {
case MixingMethod::Add:
output_color.set_red(original_color.red() + other_color.red());
output_color.set_green(original_color.green() + other_color.green());
output_color.set_blue(original_color.blue() + other_color.blue());
break;
case MixingMethod::Lightest:
auto original_lightness = original_color.red() + original_color.green() + original_color.blue();
auto other_lightness = other_color.red() + other_color.green() + other_color.blue();
if (original_lightness > other_lightness) {
output_color = original_color;
} else {
output_color.set_red(other_color.red());
output_color.set_green(other_color.green());
output_color.set_blue(other_color.blue());
}
break;
}
if (original_color != output_color)
m_bitmap.set_pixel(x, y, output_color);
}
}
}
}

View file

@ -1,29 +0,0 @@
/*
* Copyright (c) 2022, Tobias Christiansen <tobyase@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include "Bitmap.h"
namespace Gfx {
class BitmapMixer {
public:
enum class MixingMethod {
Add,
Lightest,
};
BitmapMixer(Bitmap& bitmap)
: m_bitmap(bitmap) {};
void mix_with(Bitmap&, MixingMethod);
private:
Bitmap& m_bitmap;
};
}

View file

@ -2,12 +2,8 @@ set(SOURCES
AffineTransform.cpp
AntiAliasingPainter.cpp
Bitmap.cpp
BitmapMixer.cpp
CMYKBitmap.cpp
ClassicStylePainter.cpp
ClassicWindowTheme.cpp
Color.cpp
CursorParams.cpp
DeltaE.cpp
EdgeFlagPathRasterizer.cpp
Filters/ColorBlindnessFilter.cpp
@ -84,13 +80,11 @@ set(SOURCES
Rect.cpp
ShareableBitmap.cpp
Size.cpp
StylePainter.cpp
SystemTheme.cpp
TextDirection.cpp
TextLayout.cpp
Triangle.cpp
VectorGraphic.cpp
WindowTheme.cpp
)
serenity_lib(LibGfx gfx)

View file

@ -1,671 +0,0 @@
/*
* Copyright (c) 2018-2023, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020, Sarah Taube <metalflakecobaltpaint@gmail.com>
* Copyright (c) 2021, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
* Copyright (c) 2022, Cameron Youell <cameronyouell@gmail.com>
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/StringView.h>
#include <LibGfx/AntiAliasingPainter.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/CharacterBitmap.h>
#include <LibGfx/ClassicStylePainter.h>
#include <LibGfx/Painter.h>
#include <LibGfx/Palette.h>
namespace Gfx {
void ClassicStylePainter::paint_tab_button(Painter& painter, IntRect const& rect, Palette const& palette, bool active, bool hovered, bool enabled, TabPosition position, bool in_active_window, bool accented)
{
Color base_color = palette.button();
Color highlight_color2 = palette.threed_highlight();
Color shadow_color1 = palette.threed_shadow1();
Color shadow_color2 = palette.threed_shadow2();
if (hovered && enabled && !active)
base_color = palette.hover_highlight();
PainterStateSaver saver(painter);
painter.translate(rect.location());
auto accent = palette.accent();
if (!in_active_window)
accent = accent.to_grayscale();
switch (position) {
case TabPosition::Top:
// Base
painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 1 }, base_color);
// Top line
if (active && accented) {
painter.draw_line({ 3, 0 }, { rect.width() - 3, 0 }, accent.darkened());
painter.fill_rect_with_gradient({ 1, 1, rect.width() - 2, 2 }, accent, accent.lightened(1.5f));
painter.set_pixel({ 2, 0 }, highlight_color2);
} else {
painter.draw_line({ 2, 0 }, { rect.width() - 3, 0 }, highlight_color2);
}
// Left side
painter.draw_line({ 0, 2 }, { 0, rect.height() - 1 }, highlight_color2);
painter.set_pixel({ 1, 1 }, highlight_color2);
// Right side
painter.draw_line({ rect.width() - 1, 2 }, { rect.width() - 1, rect.height() - 1 }, shadow_color2);
painter.draw_line({ rect.width() - 2, 2 }, { rect.width() - 2, rect.height() - 1 }, shadow_color1);
painter.set_pixel(rect.width() - 2, 1, shadow_color2);
break;
case TabPosition::Bottom:
// Base
painter.fill_rect({ 0, 0, rect.width() - 1, rect.height() }, base_color);
// Bottom line
if (active && accented) {
painter.fill_rect_with_gradient({ 1, rect.height() - 3, rect.width() - 2, 2 }, accent, accent.lightened(1.5f));
painter.draw_line({ 2, rect.height() - 1 }, { rect.width() - 3, rect.height() - 1 }, accent.darkened());
} else {
painter.draw_line({ 2, rect.height() - 1 }, { rect.width() - 3, rect.height() - 1 }, shadow_color2);
}
// Left side
painter.draw_line({ 0, 0 }, { 0, rect.height() - 3 }, highlight_color2);
painter.set_pixel({ 1, rect.height() - 2 }, highlight_color2);
// Right side
painter.draw_line({ rect.width() - 1, 0 }, { rect.width() - 1, rect.height() - 3 }, shadow_color2);
painter.draw_line({ rect.width() - 2, 0 }, { rect.width() - 2, rect.height() - 3 }, shadow_color1);
painter.set_pixel({ rect.width() - 2, rect.height() - 2 }, shadow_color2);
break;
case TabPosition::Left:
// Base tab
painter.fill_rect({ 1, 1, rect.width(), rect.height() - 1 }, base_color);
painter.draw_line({ 2, 0 }, { rect.width(), 0 }, highlight_color2);
painter.draw_line({ 2, rect.height() - 1 }, { rect.width(), rect.height() - 1 }, shadow_color2);
// If the tab is active, draw the accent line
if (active && accented) {
painter.fill_rect_with_gradient({ 1, 1, 2, rect.height() - 2 }, accent, accent.lightened(1.5f));
painter.draw_line({ 0, 2 }, { 0, rect.height() - 3 }, accent.darkened());
} else {
painter.draw_line({ 0, 2 }, { 0, rect.height() - 3 }, highlight_color2);
painter.draw_line({ rect.width(), 1 }, { rect.width(), rect.height() - 1 }, shadow_color1);
}
// Make appear as if the tab is rounded
painter.set_pixel({ 1, 1 }, highlight_color2);
painter.set_pixel({ 1, rect.height() - 2 }, shadow_color2);
break;
case TabPosition::Right:
// Base tab
painter.fill_rect({ 0, 1, rect.width() - 1, rect.height() - 1 }, base_color);
painter.draw_line({ 0, 0 }, { rect.width() - 2, 0 }, highlight_color2);
painter.draw_line({ 0, rect.height() - 1 }, { rect.width() - 2, rect.height() - 1 }, shadow_color2);
// If the tab is active, draw the accent line
if (active && accented) {
painter.fill_rect_with_gradient({ rect.width() - 2, 1, 2, rect.height() - 2 }, accent.lightened(1.5f), accent);
painter.draw_line({ rect.width(), 2 }, { rect.width(), rect.height() - 3 }, accent.darkened());
} else {
painter.draw_line({ rect.width(), 2 }, { rect.width(), rect.height() - 3 }, shadow_color2);
painter.draw_line({ 0, 0 }, { 0, rect.height() - 1 }, shadow_color1);
}
// Make appear as if the tab is rounded
painter.set_pixel({ rect.width() - 1, 1 }, shadow_color1);
painter.set_pixel({ rect.width() - 1, rect.height() - 2 }, shadow_color2);
break;
}
}
static void paint_button_new(Painter& painter, IntRect const& a_rect, Palette const& palette, ButtonStyle style, bool pressed, bool checked, bool hovered, bool enabled, bool focused, bool default_button)
{
Color button_color = palette.button();
Color highlight_color = palette.threed_highlight();
Color shadow_color1 = palette.threed_shadow1();
Color shadow_color2 = palette.threed_shadow2();
if (checked && enabled) {
if (hovered)
button_color = palette.hover_highlight();
else
button_color = palette.button();
} else if (hovered && enabled)
button_color = palette.hover_highlight();
PainterStateSaver saver(painter);
auto rect = a_rect;
if (focused || default_button) {
painter.draw_rect(a_rect, palette.threed_shadow2());
rect.shrink(2, 2);
}
painter.translate(rect.location());
if (pressed || checked) {
// Base
Gfx::IntRect base_rect { 1, 1, rect.width() - 2, rect.height() - 2 };
if (checked && !pressed)
painter.fill_rect_with_dither_pattern(base_rect, palette.button().lightened(1.3f), palette.button());
else
painter.fill_rect(base_rect, button_color);
// Top shadow
painter.draw_line({ 0, 0 }, { rect.width() - 2, 0 }, shadow_color2);
painter.draw_line({ 0, 0 }, { 0, rect.height() - 2 }, shadow_color2);
// Sunken shadow
painter.draw_line({ 1, 1 }, { rect.width() - 3, 1 }, shadow_color1);
painter.draw_line({ 1, 2 }, { 1, rect.height() - 3 }, shadow_color1);
// Outer highlight
painter.draw_line({ 0, rect.height() - 1 }, { rect.width() - 1, rect.height() - 1 }, highlight_color);
painter.draw_line({ rect.width() - 1, 0 }, { rect.width() - 1, rect.height() - 2 }, highlight_color);
// Inner highlight
painter.draw_line({ 1, rect.height() - 2 }, { rect.width() - 2, rect.height() - 2 }, palette.button());
painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, palette.button());
} else {
// Base
painter.fill_rect({ 0, 0, rect.width(), rect.height() }, button_color);
// Top highlight
if (style == ButtonStyle::Normal) {
painter.draw_line({ 0, 0 }, { rect.width() - 2, 0 }, highlight_color);
painter.draw_line({ 0, 0 }, { 0, rect.height() - 2 }, highlight_color);
} else if (style == ButtonStyle::ThickCap) {
painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, highlight_color);
painter.draw_line({ 1, 1 }, { 1, rect.height() - 2 }, highlight_color);
}
// Outer shadow
painter.draw_line({ 0, rect.height() - 1 }, { rect.width() - 1, rect.height() - 1 }, shadow_color2);
painter.draw_line({ rect.width() - 1, 0 }, { rect.width() - 1, rect.height() - 2 }, shadow_color2);
// Inner shadow
painter.draw_line({ 1, rect.height() - 2 }, { rect.width() - 2, rect.height() - 2 }, shadow_color1);
painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, shadow_color1);
}
}
void ClassicStylePainter::paint_button(Painter& painter, IntRect const& rect, Palette const& palette, ButtonStyle button_style, bool pressed, bool hovered, bool checked, bool enabled, bool focused, bool default_button)
{
if (button_style == ButtonStyle::Normal || button_style == ButtonStyle::ThickCap)
return paint_button_new(painter, rect, palette, button_style, pressed, checked, hovered, enabled, focused, default_button);
if (button_style == ButtonStyle::Coolbar && !enabled)
return;
Color button_color = palette.button();
Color highlight_color = palette.threed_highlight();
Color shadow_color = button_style == ButtonStyle::Coolbar ? palette.threed_shadow1() : palette.threed_shadow2();
PainterStateSaver saver(painter);
painter.translate(rect.location());
if (pressed || checked) {
// Base
IntRect base_rect { 1, 1, rect.width() - 2, rect.height() - 2 };
if (button_style == ButtonStyle::Coolbar) {
if (checked && !pressed) {
painter.fill_rect_with_dither_pattern(base_rect, palette.button().lightened(1.3f), Color());
} else {
painter.fill_rect(base_rect, button_color);
}
}
// Sunken shadow
painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, shadow_color);
painter.draw_line({ 1, 2 }, { 1, rect.height() - 2 }, shadow_color);
// Bottom highlight
painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, highlight_color);
painter.draw_line({ 1, rect.height() - 2 }, { rect.width() - 2, rect.height() - 2 }, highlight_color);
} else if (hovered) {
if (button_style == ButtonStyle::Coolbar) {
// Base
painter.fill_rect({ 1, 1, rect.width() - 2, rect.height() - 2 }, button_color);
}
// Top highlight
painter.draw_line({ 1, 1 }, { rect.width() - 2, 1 }, highlight_color);
painter.draw_line({ 1, 2 }, { 1, rect.height() - 2 }, highlight_color);
// Bottom shadow
painter.draw_line({ rect.width() - 2, 1 }, { rect.width() - 2, rect.height() - 3 }, shadow_color);
painter.draw_line({ 1, rect.height() - 2 }, { rect.width() - 2, rect.height() - 2 }, shadow_color);
}
}
void ClassicStylePainter::paint_frame(Painter& painter, IntRect const& rect, Palette const& palette, FrameStyle style, bool skip_vertical_lines)
{
if (style == Gfx::FrameStyle::NoFrame)
return;
if (style == FrameStyle::Window) {
StylePainter::paint_window_frame(painter, rect, palette);
return;
}
Color top_left_color;
Color bottom_right_color;
Color dark_shade = palette.threed_shadow1();
Color light_shade = palette.threed_highlight();
if (style == FrameStyle::RaisedContainer)
dark_shade = palette.threed_shadow2();
switch (style) {
case FrameStyle::RaisedContainer:
case FrameStyle::RaisedBox:
case FrameStyle::RaisedPanel:
top_left_color = light_shade;
bottom_right_color = dark_shade;
break;
case FrameStyle::SunkenContainer:
case FrameStyle::SunkenBox:
case FrameStyle::SunkenPanel:
top_left_color = dark_shade;
bottom_right_color = light_shade;
break;
case FrameStyle::Plain:
top_left_color = dark_shade;
bottom_right_color = dark_shade;
break;
default:
VERIFY_NOT_REACHED();
}
painter.draw_line(rect.top_left(), rect.top_right().moved_left(1), top_left_color);
painter.draw_line(rect.bottom_left().moved_up(1), rect.bottom_right().translated(-1), bottom_right_color);
if ((style != FrameStyle::SunkenPanel && style != FrameStyle::RaisedPanel) || !skip_vertical_lines) {
painter.draw_line(rect.top_left().moved_down(1), rect.bottom_left().moved_up(2), top_left_color);
painter.draw_line(rect.top_right().moved_left(1), rect.bottom_right().translated(-1, -2), bottom_right_color);
}
if (style == FrameStyle::RaisedContainer || style == FrameStyle::SunkenContainer) {
Color top_left_color;
Color bottom_right_color;
Color dark_shade = palette.threed_shadow2();
Color light_shade = palette.button();
if (style == FrameStyle::RaisedContainer) {
dark_shade = palette.threed_shadow1();
top_left_color = light_shade;
bottom_right_color = dark_shade;
} else if (style == FrameStyle::SunkenContainer) {
top_left_color = dark_shade;
bottom_right_color = light_shade;
}
IntRect inner_container_frame_rect = rect.shrunken(2, 2);
painter.draw_line(inner_container_frame_rect.top_left(), inner_container_frame_rect.top_right().moved_left(1), top_left_color);
painter.draw_line(inner_container_frame_rect.bottom_left().moved_up(1), inner_container_frame_rect.bottom_right().translated(-1), bottom_right_color);
painter.draw_line(inner_container_frame_rect.top_left().moved_down(1), inner_container_frame_rect.bottom_left().moved_up(2), top_left_color);
painter.draw_line(inner_container_frame_rect.top_right().moved_left(1), inner_container_frame_rect.bottom_right().translated(-1, -2), bottom_right_color);
}
if (style == FrameStyle::RaisedBox || style == FrameStyle::SunkenBox) {
swap(top_left_color, bottom_right_color);
IntRect inner_rect = rect.shrunken(2, 2);
painter.draw_line(inner_rect.top_left(), inner_rect.top_right().moved_left(1), top_left_color);
painter.draw_line(inner_rect.bottom_left().moved_up(1), inner_rect.bottom_right().translated(-1), bottom_right_color);
painter.draw_line(inner_rect.top_left().moved_down(1), inner_rect.bottom_left().moved_up(2), top_left_color);
painter.draw_line(inner_rect.top_right().moved_left(1), inner_rect.bottom_right().translated(-1, -2), bottom_right_color);
}
}
void ClassicStylePainter::paint_window_frame(Painter& painter, IntRect const& rect, Palette const& palette)
{
Color base_color = palette.button();
Color dark_shade = palette.threed_shadow2();
Color mid_shade = palette.threed_shadow1();
Color light_shade = palette.threed_highlight();
auto border_thickness = palette.window_border_thickness();
auto border_radius = palette.window_border_radius();
if (border_radius > 0) {
// FIXME: This will draw "useless" pixels that'll get drawn over by the window contents.
// preferably we should just remove the corner pixels from the completely drawn window
// but I don't know how to do that yet. :^)
AntiAliasingPainter aa_painter { painter };
aa_painter.fill_rect_with_rounded_corners(rect, base_color, border_radius);
return;
}
painter.draw_rect_with_thickness({ rect.x() + border_thickness / 2,
rect.y() + border_thickness / 2,
rect.width() - border_thickness,
rect.height() - border_thickness },
base_color, border_thickness);
painter.draw_line(rect.top_left().translated(0, 1), rect.bottom_left().translated(0, -1), base_color);
painter.draw_line(rect.top_left().translated(1, 1), rect.top_right().translated(-2, 1), light_shade);
painter.draw_line(rect.top_left().translated(1, 1), rect.bottom_left().translated(1, -2), light_shade);
painter.draw_line(rect.top_left().translated(2, 2), rect.top_right().translated(-3, 2), base_color);
painter.draw_line(rect.top_left().translated(2, 2), rect.bottom_left().translated(2, -3), base_color);
painter.draw_line(rect.top_left().translated(3, 3), rect.top_right().translated(-4, 3), base_color);
painter.draw_line(rect.top_left().translated(3, 3), rect.bottom_left().translated(3, -4), base_color);
painter.draw_line(rect.top_right().translated(-1, 0), rect.bottom_right().translated(-1, -1), dark_shade);
painter.draw_line(rect.top_right().translated(-2, 1), rect.bottom_right().translated(-2, -2), mid_shade);
painter.draw_line(rect.top_right().translated(-3, 2), rect.bottom_right().translated(-3, -3), base_color);
painter.draw_line(rect.top_right().translated(-4, 3), rect.bottom_right().translated(-4, -4), base_color);
painter.draw_line(rect.bottom_left().translated(0, -1), rect.bottom_right().translated(-1, -1), dark_shade);
painter.draw_line(rect.bottom_left().translated(1, -2), rect.bottom_right().translated(-2, -2), mid_shade);
painter.draw_line(rect.bottom_left().translated(2, -3), rect.bottom_right().translated(-3, -3), base_color);
painter.draw_line(rect.bottom_left().translated(3, -4), rect.bottom_right().translated(-4, -4), base_color);
}
void ClassicStylePainter::paint_progressbar(Painter& painter, IntRect const& rect, Palette const& palette, int min, int max, int value, StringView text, Orientation orientation)
{
// First we fill the entire widget with the gradient. This incurs a bit of
// overdraw but ensures a consistent look throughout the progression.
Color start_color = palette.active_window_border1();
Color end_color = palette.active_window_border2();
painter.fill_rect_with_gradient(orientation, rect, start_color, end_color);
if (!text.is_null()) {
painter.draw_text(rect.translated(1, 1), text, TextAlignment::Center, palette.base_text());
painter.draw_text(rect, text, TextAlignment::Center, palette.base_text().inverted());
}
float range_size = max - min;
float progress = (value - min) / range_size;
// Then we carve out a hole in the remaining part of the widget.
// We draw the text a third time, clipped and inverse, for sharp contrast.
IntRect hole_rect;
if (orientation == Orientation::Horizontal) {
float progress_width = progress * rect.width();
hole_rect = { (int)progress_width, 0, (int)(rect.width() - progress_width), rect.height() };
} else {
float progress_height = progress * rect.height();
hole_rect = { 0, 0, rect.width(), (int)(rect.height() - progress_height) };
}
hole_rect.translate_by(rect.location());
hole_rect.set_right_without_resize(rect.right());
PainterStateSaver saver(painter);
painter.fill_rect(hole_rect, palette.base());
painter.add_clip_rect(hole_rect);
if (!text.is_null())
painter.draw_text(rect.translated(0, 0), text, TextAlignment::Center, palette.base_text());
}
void ClassicStylePainter::paint_radio_button(Painter& painter, IntRect const& a_rect, Palette const& palette, bool is_checked, bool is_being_pressed)
{
// Outer top left arc, starting at bottom left point.
constexpr Gfx::IntPoint outer_top_left_arc[] = {
{ 1, 9 },
{ 1, 8 },
{ 0, 7 },
{ 0, 6 },
{ 0, 5 },
{ 0, 4 },
{ 1, 3 },
{ 1, 2 },
{ 2, 1 },
{ 3, 1 },
{ 4, 0 },
{ 5, 0 },
{ 6, 0 },
{ 7, 0 },
{ 8, 1 },
{ 9, 1 },
};
// Outer bottom right arc, starting at top right point.
constexpr Gfx::IntPoint outer_bottom_right_arc[] = {
{ 10, 2 },
{ 10, 3 },
{ 11, 4 },
{ 11, 5 },
{ 11, 6 },
{ 11, 7 },
{ 10, 8 },
{ 10, 9 },
{ 9, 10 },
{ 8, 10 },
{ 7, 11 },
{ 6, 11 },
{ 5, 11 },
{ 4, 11 },
{ 3, 10 },
{ 2, 10 },
};
// Inner top left arc, starting at bottom left point.
constexpr Gfx::IntPoint inner_top_left_arc[] = {
{ 2, 8 },
{ 1, 7 },
{ 1, 6 },
{ 1, 5 },
{ 1, 4 },
{ 2, 3 },
{ 2, 2 },
{ 3, 2 },
{ 3, 2 },
{ 3, 2 },
{ 3, 2 },
{ 4, 1 },
{ 5, 1 },
{ 6, 1 },
{ 7, 1 },
{ 8, 2 },
{ 9, 2 },
};
// Inner bottom right arc, starting at top right point.
constexpr Gfx::IntPoint inner_bottom_right_arc[] = {
{ 9, 3 },
{ 10, 4 },
{ 10, 5 },
{ 10, 6 },
{ 10, 7 },
{ 9, 8 },
{ 9, 9 },
{ 8, 9 },
{ 7, 10 },
{ 6, 10 },
{ 5, 10 },
{ 4, 10 },
{ 3, 9 },
{ 2, 9 },
};
// Inner "being pressed" circle, starting at top left corner point.
constexpr Gfx::IntPoint inner_being_pressed_circle[] = {
{ 3, 3 },
{ 4, 2 },
{ 5, 2 },
{ 6, 2 },
{ 7, 2 },
{ 8, 3 },
{ 9, 4 },
{ 9, 5 },
{ 9, 6 },
{ 9, 7 },
{ 8, 8 },
{ 7, 9 },
{ 6, 9 },
{ 5, 9 },
{ 4, 9 },
{ 3, 8 },
{ 2, 7 },
{ 2, 6 },
{ 2, 5 },
{ 2, 4 },
};
// Inner "checked" circle, starting at top left.
constexpr Gfx::IntPoint checked_circle[] = {
{ 5, 4 },
{ 6, 4 },
{ 4, 5 },
{ 5, 5 },
{ 6, 5 },
{ 7, 5 },
{ 4, 6 },
{ 5, 6 },
{ 6, 6 },
{ 7, 6 },
{ 5, 7 },
{ 6, 7 },
};
// FIXME: Support radio buttons at any size.
Gfx::IntRect rect { a_rect.x(), a_rect.y(), 12, 12 };
auto set_pixels = [&](auto const& points, Gfx::Color color) {
for (auto const& p : points) {
painter.set_pixel(rect.location().translated(p), color);
}
};
// Fill center with base color
painter.fill_rect(rect.shrunken(4, 4), palette.base());
set_pixels(outer_top_left_arc, palette.threed_shadow1());
set_pixels(outer_bottom_right_arc, palette.threed_highlight());
set_pixels(inner_top_left_arc, palette.threed_shadow2());
set_pixels(inner_bottom_right_arc, palette.button());
if (is_being_pressed) {
set_pixels(inner_being_pressed_circle, palette.threed_shadow1());
}
if (is_checked) {
set_pixels(checked_circle, palette.base_text());
}
}
static constexpr Gfx::CharacterBitmap s_checked_bitmap {
" "
" # "
" ## "
" ### "
" ## ### "
" ##### "
" ### "
" # "
" "sv,
9, 9
};
void ClassicStylePainter::paint_check_box(Painter& painter, IntRect const& rect, Palette const& palette, bool is_enabled, bool is_checked, bool is_being_pressed)
{
painter.fill_rect(rect, is_enabled ? palette.base() : palette.window());
paint_frame(painter, rect, palette, Gfx::FrameStyle::SunkenContainer);
if (is_being_pressed) {
// FIXME: This color should not be hard-coded.
painter.draw_rect(rect.shrunken(4, 4), Color::MidGray);
}
if (is_checked) {
auto check_rect = Gfx::IntRect({}, s_checked_bitmap.size()).centered_within(rect);
painter.draw_bitmap(check_rect.location(), s_checked_bitmap, is_enabled ? palette.base_text() : palette.threed_shadow1());
}
}
void ClassicStylePainter::paint_transparency_grid(Painter& painter, IntRect const& rect, Palette const& palette)
{
painter.fill_rect_with_checkerboard(rect, { 8, 8 }, palette.base().darkened(0.9), palette.base());
}
void ClassicStylePainter::paint_simple_rect_shadow(Painter& painter, IntRect const& containing_rect, Bitmap const& shadow_bitmap, bool shadow_includes_frame, bool fill_content)
{
// The layout of the shadow_bitmap is defined like this:
// +---------+----+---------+----+----+----+
// | TL | T | TR | LT | L | LB |
// +---------+----+---------+----+----+----+
// | BL | B | BR | RT | R | RB |
// +---------+----+---------+----+----+----+
// Located strictly on the top or bottom of the rectangle, above or below of the content:
// TL = top-left T = top TR = top-right
// BL = bottom-left B = bottom BR = bottom-right
// Located on the left or right of the rectangle, but not above or below of the content:
// LT = left-top L = left LB = left-bottom
// RT = right-top R = right RB = right-bottom
// So, the bitmap has two rows and 6 column, two of which are twice as wide.
// The height divided by two defines a cell size, and width of each
// column must be the same as the height of the cell, except for the
// first and third column, which are twice as wide.
// If fill_content is true, it will use the RGBA color of right-bottom pixel of TL to fill the rectangle enclosed
if (shadow_bitmap.height() % 2 != 0) {
dbgln("Can't paint simple rect shadow, shadow bitmap height {} is not even", shadow_bitmap.height());
return;
}
auto base_size = shadow_bitmap.height() / 2;
if (shadow_bitmap.width() != base_size * (6 + 2)) {
if (shadow_bitmap.width() % base_size != 0)
dbgln("Can't paint simple rect shadow, shadow bitmap width {} is not a multiple of {}", shadow_bitmap.width(), base_size);
else
dbgln("Can't paint simple rect shadow, shadow bitmap width {} but expected {}", shadow_bitmap.width(), base_size * (6 + 2));
return;
}
// The containing_rect should have been inflated appropriately
VERIFY(containing_rect.size().contains(Gfx::IntSize { base_size, base_size }));
auto sides_height = containing_rect.height() - 2 * base_size;
auto half_height = sides_height / 2;
auto containing_horizontal_rect = containing_rect;
int horizontal_shift = 0;
if (half_height < base_size && !shadow_includes_frame) {
// If the height is too small we need to shift the left/right accordingly, unless the shadow includes portions of the frame
horizontal_shift = base_size - half_height;
containing_horizontal_rect.set_left(containing_horizontal_rect.left() + horizontal_shift);
containing_horizontal_rect.set_right(containing_horizontal_rect.right() - 2 * horizontal_shift);
}
auto half_width = containing_horizontal_rect.width() / 2;
int corner_piece_width = min(containing_horizontal_rect.width() / 2, base_size * 2);
int left_corners_right = containing_horizontal_rect.left() + corner_piece_width;
int right_corners_left = max(containing_horizontal_rect.right() - corner_piece_width, left_corners_right + 1);
auto paint_horizontal = [&](int y, int src_row) {
if (half_width <= 0)
return;
Gfx::PainterStateSaver save(painter);
painter.add_clip_rect({ containing_horizontal_rect.left(), y, containing_horizontal_rect.width(), base_size });
painter.blit({ containing_horizontal_rect.left(), y }, shadow_bitmap, { 0, src_row * base_size, corner_piece_width, base_size });
painter.blit({ right_corners_left, y }, shadow_bitmap, { 5 * base_size - corner_piece_width, src_row * base_size, corner_piece_width, base_size });
for (int x = left_corners_right; x < right_corners_left; x += base_size) {
auto width = min(right_corners_left - x, base_size);
painter.blit({ x, y }, shadow_bitmap, { corner_piece_width, src_row * base_size, width, base_size });
}
};
paint_horizontal(containing_rect.top(), 0);
paint_horizontal(containing_rect.bottom() - base_size, 1);
int corner_piece_height = min(half_height, base_size);
int top_corners_bottom = base_size + corner_piece_height;
int bottom_corners_top = base_size + max(half_height, sides_height - corner_piece_height);
auto paint_vertical = [&](int x, int src_row, int hshift, int hsrcshift) {
Gfx::PainterStateSaver save(painter);
painter.add_clip_rect({ x, containing_rect.y() + base_size, base_size, containing_rect.height() - 2 * base_size });
painter.blit({ x + hshift, containing_rect.top() + top_corners_bottom - corner_piece_height }, shadow_bitmap, { base_size * 5 + hsrcshift, src_row * base_size, base_size - hsrcshift, corner_piece_height });
painter.blit({ x + hshift, containing_rect.top() + bottom_corners_top }, shadow_bitmap, { base_size * 7 + hsrcshift, src_row * base_size + base_size - corner_piece_height, base_size - hsrcshift, corner_piece_height });
for (int y = top_corners_bottom; y < bottom_corners_top; y += base_size) {
auto height = min(bottom_corners_top - y, base_size);
painter.blit({ x, containing_rect.top() + y }, shadow_bitmap, { base_size * 6, src_row * base_size, base_size, height });
}
};
paint_vertical(containing_rect.left(), 0, horizontal_shift, 0);
if (shadow_includes_frame)
horizontal_shift = 0; // TODO: fix off-by-one on rectangles barely wide enough
paint_vertical(containing_rect.right() - base_size, 1, 0, horizontal_shift);
if (fill_content) {
// Fill the enclosed rectangle with the RGBA color of the right-bottom pixel of the TL tile
auto inner_rect = containing_rect.shrunken(2 * base_size, 2 * base_size);
if (!inner_rect.is_empty())
painter.fill_rect(inner_rect, shadow_bitmap.get_pixel(2 * base_size - 1, base_size - 1));
}
}
}

View file

@ -1,29 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020, Sarah Taube <metalflakecobaltpaint@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Forward.h>
#include <LibGfx/Forward.h>
#include <LibGfx/StylePainter.h>
namespace Gfx {
class ClassicStylePainter : public BaseStylePainter {
public:
virtual void paint_button(Painter&, IntRect const&, Palette const&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true, bool focused = false, bool default_button = false) override;
virtual void paint_tab_button(Painter&, IntRect const&, Palette const&, bool active, bool hovered, bool enabled, TabPosition position, bool in_active_window, bool accented) override;
virtual void paint_frame(Painter&, IntRect const&, Palette const&, FrameStyle, bool skip_vertical_lines = false) override;
virtual void paint_window_frame(Painter&, IntRect const&, Palette const&) override;
virtual void paint_progressbar(Painter&, IntRect const&, Palette const&, int min, int max, int value, StringView text, Orientation = Orientation::Horizontal) override;
virtual void paint_radio_button(Painter&, IntRect const&, Palette const&, bool is_checked, bool is_being_pressed) override;
virtual void paint_check_box(Painter&, IntRect const&, Palette const&, bool is_enabled, bool is_checked, bool is_being_pressed) override;
virtual void paint_transparency_grid(Painter&, IntRect const&, Palette const&) override;
virtual void paint_simple_rect_shadow(Painter&, IntRect const&, Bitmap const& shadow_bitmap, bool shadow_includes_frame, bool fill_content) override;
};
}

View file

@ -1,245 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021-2022, Filiph Sandström <filiph.sandstrom@filfatstudios.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Bitmap.h>
#include <LibGfx/ClassicWindowTheme.h>
#include <LibGfx/Font/FontDatabase.h>
#include <LibGfx/Painter.h>
#include <LibGfx/Palette.h>
#include <LibGfx/StylePainter.h>
namespace Gfx {
int ClassicWindowTheme::menubar_height() const
{
return max(20, FontDatabase::default_font().pixel_size_rounded_up() + 6);
}
Gfx::IntRect ClassicWindowTheme::titlebar_icon_rect(WindowType window_type, WindowMode window_mode, IntRect const& window_rect, Palette const& palette) const
{
if (window_mode == WindowMode::RenderAbove)
return {};
auto titlebar_rect = this->titlebar_rect(window_type, window_mode, window_rect, palette);
Gfx::IntRect icon_rect {
titlebar_rect.x() + 2,
titlebar_rect.y(),
16,
16,
};
icon_rect.center_vertically_within(titlebar_rect);
icon_rect.translate_by(0, 1);
return icon_rect;
}
Gfx::IntRect ClassicWindowTheme::titlebar_text_rect(WindowType window_type, WindowMode window_mode, IntRect const& window_rect, Palette const& palette) const
{
auto titlebar_rect = this->titlebar_rect(window_type, window_mode, window_rect, palette);
auto titlebar_icon_rect = this->titlebar_icon_rect(window_type, window_mode, window_rect, palette);
return {
titlebar_rect.x() + 3 + (titlebar_icon_rect.is_empty() ? 0 : (titlebar_icon_rect.width() + 2)),
titlebar_rect.y(),
titlebar_rect.width() - 5 - (titlebar_icon_rect.is_empty() ? 0 : (titlebar_icon_rect.width() + 2)),
titlebar_rect.height()
};
}
void ClassicWindowTheme::paint_normal_frame(Painter& painter, WindowState window_state, WindowMode window_mode, IntRect const& window_rect, StringView window_title, Bitmap const& icon, Palette const& palette, IntRect const& leftmost_button_rect, int menu_row_count, [[maybe_unused]] bool window_modified) const
{
auto frame_rect = frame_rect_for_window(WindowType::Normal, window_mode, window_rect, palette, menu_row_count);
frame_rect.set_location({ 0, 0 });
Gfx::StylePainter::paint_window_frame(painter, frame_rect, palette);
auto& title_font = FontDatabase::window_title_font();
auto titlebar_rect = this->titlebar_rect(WindowType::Normal, window_mode, window_rect, palette);
auto titlebar_icon_rect = this->titlebar_icon_rect(WindowType::Normal, window_mode, window_rect, palette);
auto titlebar_inner_rect = titlebar_text_rect(WindowType::Normal, window_mode, window_rect, palette);
auto titlebar_title_rect = titlebar_inner_rect;
titlebar_title_rect.set_width(title_font.width(window_title));
auto [title_color, border_color, border_color2, stripes_color, shadow_color] = compute_frame_colors(window_state, palette);
painter.draw_line(titlebar_rect.bottom_left(), titlebar_rect.bottom_right().moved_left(1), palette.button());
painter.draw_line(titlebar_rect.bottom_left().moved_down(1), titlebar_rect.bottom_right().translated(-1, 1), palette.button());
painter.fill_rect_with_gradient(titlebar_rect, border_color, border_color2);
auto title_alignment = palette.title_alignment();
int stripe_right = leftmost_button_rect.left() - 3;
auto clipped_title_rect = titlebar_title_rect;
clipped_title_rect.set_width(stripe_right - clipped_title_rect.x());
if (!clipped_title_rect.is_empty()) {
painter.draw_text(clipped_title_rect.translated(1, 2), window_title, title_font, title_alignment, shadow_color, Gfx::TextElision::Right);
// FIXME: The translated(0, 1) wouldn't be necessary if we could center text based on its baseline.
painter.draw_text(clipped_title_rect.translated(0, 1), window_title, title_font, title_alignment, title_color, Gfx::TextElision::Right);
}
if (window_mode == WindowMode::RenderAbove)
return;
if (stripes_color.alpha() > 0) {
switch (title_alignment) {
case Gfx::TextAlignment::CenterLeft: {
int stripe_left = titlebar_title_rect.right() + 4;
if (stripe_left && stripe_right && stripe_left < stripe_right) {
for (int i = 2; i <= titlebar_inner_rect.height() - 2; i += 2) {
painter.draw_line({ stripe_left, titlebar_inner_rect.y() + i }, { stripe_right, titlebar_inner_rect.y() + i }, stripes_color);
}
}
break;
}
case Gfx::TextAlignment::CenterRight: {
for (int i = 2; i <= titlebar_inner_rect.height() - 2; i += 2) {
painter.draw_line({ titlebar_inner_rect.left(), titlebar_inner_rect.y() + i }, { stripe_right - titlebar_title_rect.width() - 3, titlebar_inner_rect.y() + i }, stripes_color);
}
break;
}
case Gfx::TextAlignment::Center: {
auto stripe_width = (leftmost_button_rect.left() / 2 - titlebar_title_rect.width() / 2) - titlebar_icon_rect.width() - 3;
for (int i = 2; i <= titlebar_inner_rect.height() - 2; i += 2) {
painter.draw_line({ titlebar_inner_rect.left(), titlebar_inner_rect.y() + i }, { titlebar_inner_rect.left() + stripe_width, titlebar_inner_rect.y() + i }, stripes_color);
painter.draw_line({ stripe_right - stripe_width, titlebar_inner_rect.y() + i }, { stripe_right, titlebar_inner_rect.y() + i }, stripes_color);
}
break;
}
default:
dbgln("Unhandled title alignment!");
}
}
painter.draw_scaled_bitmap(titlebar_icon_rect, icon, icon.rect());
}
IntRect ClassicWindowTheme::menubar_rect(WindowType window_type, WindowMode window_mode, IntRect const& window_rect, Palette const& palette, int menu_row_count) const
{
if (window_type != WindowType::Normal)
return {};
return { palette.window_border_thickness(), palette.window_border_thickness() - 1 + titlebar_height(window_type, window_mode, palette) + 2, window_rect.width(), menubar_height() * menu_row_count };
}
IntRect ClassicWindowTheme::titlebar_rect(WindowType window_type, WindowMode window_mode, IntRect const& window_rect, Palette const& palette) const
{
auto& title_font = FontDatabase::window_title_font();
auto window_titlebar_height = titlebar_height(window_type, window_mode, palette);
// FIXME: The top of the titlebar doesn't get redrawn properly if this padding is different
int total_vertical_padding = title_font.pixel_size_rounded_up() - 1;
if (window_type == WindowType::Notification)
return { window_rect.width() + 3, total_vertical_padding / 2 - 1, window_titlebar_height, window_rect.height() };
return { palette.window_border_thickness(), palette.window_border_thickness(), window_rect.width(), window_titlebar_height };
}
ClassicWindowTheme::FrameColors ClassicWindowTheme::compute_frame_colors(WindowState state, Palette const& palette) const
{
switch (state) {
case WindowState::Highlighted:
return { palette.highlight_window_title(), palette.highlight_window_border1(), palette.highlight_window_border2(), palette.highlight_window_title_stripes(), palette.highlight_window_title_shadow() };
case WindowState::Moving:
return { palette.moving_window_title(), palette.moving_window_border1(), palette.moving_window_border2(), palette.moving_window_title_stripes(), palette.moving_window_title_shadow() };
case WindowState::Active:
return { palette.active_window_title(), palette.active_window_border1(), palette.active_window_border2(), palette.active_window_title_stripes(), palette.active_window_title_shadow() };
case WindowState::Inactive:
return { palette.inactive_window_title(), palette.inactive_window_border1(), palette.inactive_window_border2(), palette.inactive_window_title_stripes(), palette.inactive_window_title_shadow() };
default:
VERIFY_NOT_REACHED();
}
}
void ClassicWindowTheme::paint_notification_frame(Painter& painter, WindowMode window_mode, IntRect const& window_rect, Palette const& palette, IntRect const& close_button_rect) const
{
auto frame_rect = frame_rect_for_window(WindowType::Notification, window_mode, window_rect, palette, 0);
frame_rect.set_location({ 0, 0 });
Gfx::StylePainter::paint_window_frame(painter, frame_rect, palette);
auto titlebar_rect = this->titlebar_rect(WindowType::Notification, window_mode, window_rect, palette);
painter.fill_rect_with_gradient(Gfx::Orientation::Vertical, titlebar_rect, palette.active_window_border1(), palette.active_window_border2());
if (palette.active_window_title_stripes().alpha() > 0) {
int stripe_top = close_button_rect.bottom() + 3;
int stripe_bottom = window_rect.height() - 3;
if (stripe_top && stripe_bottom && stripe_top < stripe_bottom) {
for (int i = 2; i <= palette.window_title_height() - 2; i += 2)
painter.draw_line({ titlebar_rect.x() + i, stripe_top }, { titlebar_rect.x() + i, stripe_bottom }, palette.active_window_title_stripes());
}
}
}
IntRect ClassicWindowTheme::frame_rect_for_window(WindowType window_type, WindowMode window_mode, IntRect const& window_rect, Gfx::Palette const& palette, int menu_row_count) const
{
auto window_titlebar_height = titlebar_height(window_type, window_mode, palette);
auto border_thickness = palette.window_border_thickness();
switch (window_type) {
case WindowType::Normal:
return {
window_rect.x() - border_thickness,
window_rect.y() - window_titlebar_height - border_thickness - 1 - menu_row_count * menubar_height(),
window_rect.width() + (border_thickness * 2),
window_rect.height() + (border_thickness * 2) + 1 + window_titlebar_height + menu_row_count * menubar_height(),
};
case WindowType::Notification:
return {
window_rect.x() - 3,
window_rect.y() - 3,
window_rect.width() + 6 + window_titlebar_height,
window_rect.height() + 6
};
default:
return window_rect;
}
}
Vector<IntRect> ClassicWindowTheme::layout_buttons(WindowType window_type, WindowMode window_mode, IntRect const& window_rect, Palette const& palette, size_t buttons) const
{
int window_button_width = palette.window_title_button_width();
int window_button_height = palette.window_title_button_height();
int pos;
Vector<IntRect> button_rects;
if (window_type == WindowType::Notification)
pos = titlebar_rect(window_type, window_mode, window_rect, palette).top() + 2;
else
pos = titlebar_text_rect(window_type, window_mode, window_rect, palette).right();
for (size_t i = 0; i < buttons; i++) {
if (window_type == WindowType::Notification) {
// The button height & width have to be equal or it leaks out of its area
Gfx::IntRect rect { 0, pos, window_button_height, window_button_height };
rect.center_horizontally_within(titlebar_rect(window_type, window_mode, window_rect, palette));
button_rects.append(rect);
pos += window_button_height;
} else {
pos -= window_button_width;
Gfx::IntRect rect { pos, 0, window_button_width, window_button_height };
rect.center_vertically_within(titlebar_text_rect(window_type, window_mode, window_rect, palette));
button_rects.append(rect);
}
}
return button_rects;
}
int ClassicWindowTheme::titlebar_height(WindowType window_type, WindowMode window_mode, Palette const& palette) const
{
auto& title_font = FontDatabase::window_title_font();
switch (window_type) {
case WindowType::Normal:
case WindowType::Notification: {
if (window_mode == WindowMode::RenderAbove)
return max(palette.window_title_height() - 4, title_font.pixel_size() + 2);
else
return max(palette.window_title_height(), title_font.pixel_size() + 6);
}
default:
return 0;
}
}
}

View file

@ -1,61 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGfx/Color.h>
#include <LibGfx/WindowTheme.h>
namespace Gfx {
class ClassicWindowTheme final : public WindowTheme {
public:
ClassicWindowTheme() = default;
virtual ~ClassicWindowTheme() override = default;
virtual void paint_normal_frame(Painter& painter, WindowState window_state, WindowMode window_mode, IntRect const& window_rect, StringView window_title, Bitmap const& icon, Palette const& palette, IntRect const& leftmost_button_rect, int menu_row_count, bool window_modified) const override;
virtual void paint_notification_frame(Painter&, WindowMode, IntRect const& window_rect, Palette const&, IntRect const& close_button_rect) const override;
virtual int titlebar_height(WindowType, WindowMode, Palette const&) const override;
virtual IntRect titlebar_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&) const override;
virtual IntRect titlebar_icon_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&) const override;
virtual IntRect titlebar_text_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&) const override;
virtual IntRect menubar_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&, int menu_row_count) const override;
virtual IntRect frame_rect_for_window(WindowType, WindowMode, IntRect const& window_rect, Palette const&, int menu_row_count) const override;
virtual Vector<IntRect> layout_buttons(WindowType, WindowMode, IntRect const& window_rect, Palette const&, size_t buttons) const override;
virtual bool is_simple_rect_frame() const override { return true; }
virtual bool frame_uses_alpha(WindowState state, Palette const& palette) const override
{
return compute_frame_colors(state, palette).uses_alpha();
}
virtual float frame_alpha_hit_threshold(WindowState) const override { return 1.0f; }
private:
int menubar_height() const;
struct FrameColors {
Color title_color;
Color border_color;
Color border_color2;
Color title_stripes_color;
Color title_shadow_color;
bool uses_alpha() const
{
// We don't care about the title_stripes_color or title_shadow_color alpha channels because they are
// effectively rendered on top of the borders and don't mean whether the frame itself actually has
// any alpha channels that would require the entire frame to be rendered as transparency.
return title_color.alpha() != 0xff || border_color.alpha() != 0xff || border_color2.alpha() != 0xff;
}
};
FrameColors compute_frame_colors(WindowState, Palette const&) const;
};
}

View file

@ -1,100 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/Format.h>
#include <AK/LexicalPath.h>
#include <LibGfx/Bitmap.h>
#include <LibGfx/CursorParams.h>
namespace Gfx {
CursorParams CursorParams::parse_from_filename(StringView cursor_path, Gfx::IntPoint default_hotspot)
{
LexicalPath path(cursor_path);
auto file_title = path.title();
auto last_dot_in_title = file_title.find_last('.');
if (!last_dot_in_title.has_value() || last_dot_in_title.value() == 0) {
// No encoded params in filename. Not an error, we'll just use defaults
return { default_hotspot };
}
auto params_str = file_title.substring_view(last_dot_in_title.value() + 1);
CursorParams params(default_hotspot);
bool in_display_scale_part = false;
for (size_t i = 0; i + 1 < params_str.length() && !in_display_scale_part;) {
auto property = params_str[i++];
auto value = [&]() -> Optional<size_t> {
size_t k = i;
while (k < params_str.length()) {
auto ch = params_str[k];
if (ch < '0' || ch > '9')
break;
k++;
}
if (k == i)
return {};
auto parsed_number = params_str.substring_view(i, k - i).to_number<unsigned>();
if (!parsed_number.has_value())
return {};
i = k;
return parsed_number.value();
}();
if (!value.has_value()) {
dbgln("Failed to parse value for property '{}' from parsed cursor path: {}", property, cursor_path);
return { default_hotspot };
}
switch (property) {
case 'x':
params.m_hotspot.set_x(value.value());
params.m_have_hotspot = true;
break;
case 'y':
params.m_hotspot.set_y(value.value());
params.m_have_hotspot = true;
break;
case 'f':
if (value.value() > 1)
params.m_frames = value.value();
break;
case 't':
if (value.value() >= 100 && value.value() <= 1000)
params.m_frame_ms = value.value();
else
dbgln("Cursor frame rate outside of valid range (100-1000ms)");
break;
case '-':
in_display_scale_part = true;
break;
default:
dbgln("Ignore unknown property '{}' with value {} parsed from cursor path: {}", property, value.value(), cursor_path);
return { default_hotspot };
}
}
return params;
}
CursorParams CursorParams::constrained(Gfx::Bitmap const& bitmap) const
{
CursorParams params(*this);
auto rect = bitmap.rect();
if (params.m_frames > 1) {
if (rect.width() % params.m_frames == 0) {
rect.set_width(rect.width() / (int)params.m_frames);
} else {
dbgln("Cannot divide cursor dimensions {} into {} frames", rect, params.m_frames);
params.m_frames = 1;
}
}
if (params.m_have_hotspot)
params.m_hotspot.constrain(rect);
else
params.m_hotspot = rect.center();
return params;
}
}

View file

@ -1,37 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/StringView.h>
#include <LibGfx/Point.h>
namespace Gfx {
class CursorParams {
public:
static CursorParams parse_from_filename(StringView, Gfx::IntPoint);
CursorParams() = default;
CursorParams(Gfx::IntPoint hotspot)
: m_hotspot(hotspot)
{
}
CursorParams constrained(Gfx::Bitmap const&) const;
Gfx::IntPoint hotspot() const { return m_hotspot; }
unsigned frames() const { return m_frames; }
unsigned frame_ms() const { return m_frame_ms; }
private:
Gfx::IntPoint m_hotspot;
unsigned m_frames { 1 };
unsigned m_frame_ms { 0 };
bool m_have_hotspot { false };
};
}

View file

@ -33,7 +33,6 @@ class Palette;
class PaletteImpl;
class Path;
class ShareableBitmap;
class StylePainter;
struct SystemTheme;
template<typename T>

View file

@ -1,66 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/Bitmap.h>
#include <LibGfx/ClassicStylePainter.h>
#include <LibGfx/Painter.h>
#include <LibGfx/Palette.h>
#include <LibGfx/StylePainter.h>
namespace Gfx {
BaseStylePainter& StylePainter::current()
{
static ClassicStylePainter style;
return style;
}
void StylePainter::paint_tab_button(Painter& painter, IntRect const& rect, Palette const& palette, bool active, bool hovered, bool enabled, TabPosition position, bool in_active_window, bool accented)
{
current().paint_tab_button(painter, rect, palette, active, hovered, enabled, position, in_active_window, accented);
}
void StylePainter::paint_button(Painter& painter, IntRect const& rect, Palette const& palette, ButtonStyle button_style, bool pressed, bool hovered, bool checked, bool enabled, bool focused, bool default_button)
{
current().paint_button(painter, rect, palette, button_style, pressed, hovered, checked, enabled, focused, default_button);
}
void StylePainter::paint_frame(Painter& painter, IntRect const& rect, Palette const& palette, FrameStyle style, bool skip_vertical_lines)
{
current().paint_frame(painter, rect, palette, style, skip_vertical_lines);
}
void StylePainter::paint_window_frame(Painter& painter, IntRect const& rect, Palette const& palette)
{
current().paint_window_frame(painter, rect, palette);
}
void StylePainter::paint_progressbar(Painter& painter, IntRect const& rect, Palette const& palette, int min, int max, int value, StringView text, Orientation orientation)
{
current().paint_progressbar(painter, rect, palette, min, max, value, text, orientation);
}
void StylePainter::paint_radio_button(Painter& painter, IntRect const& rect, Palette const& palette, bool is_checked, bool is_being_pressed)
{
current().paint_radio_button(painter, rect, palette, is_checked, is_being_pressed);
}
void StylePainter::paint_check_box(Painter& painter, IntRect const& rect, Palette const& palette, bool is_enabled, bool is_checked, bool is_being_pressed)
{
current().paint_check_box(painter, rect, palette, is_enabled, is_checked, is_being_pressed);
}
void StylePainter::paint_transparency_grid(Painter& painter, IntRect const& rect, Palette const& palette)
{
current().paint_transparency_grid(painter, rect, palette);
}
void StylePainter::paint_simple_rect_shadow(Painter& painter, IntRect const& rect, Bitmap const& shadow_bitmap, bool shadow_includes_frame, bool fill_content)
{
current().paint_simple_rect_shadow(painter, rect, shadow_bitmap, shadow_includes_frame, fill_content);
}
}

View file

@ -1,70 +0,0 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Forward.h>
#include <LibGfx/Forward.h>
#include <LibGfx/Orientation.h>
#include <LibGfx/TabPosition.h>
namespace Gfx {
enum class ButtonStyle {
Normal,
ThickCap,
Coolbar,
Tray,
};
enum class FrameStyle {
NoFrame,
Window,
Plain,
RaisedBox,
SunkenBox,
RaisedContainer,
SunkenContainer,
RaisedPanel,
SunkenPanel,
};
// FIXME: should this be in its own header?
class BaseStylePainter {
public:
virtual ~BaseStylePainter() = default;
virtual void paint_button(Painter&, IntRect const&, Palette const&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true, bool focused = false, bool default_button = false) = 0;
virtual void paint_tab_button(Painter&, IntRect const&, Palette const&, bool active, bool hovered, bool enabled, TabPosition position, bool in_active_window, bool accented) = 0;
virtual void paint_frame(Painter&, IntRect const&, Palette const&, FrameStyle, bool skip_vertical_lines = false) = 0;
virtual void paint_window_frame(Painter&, IntRect const&, Palette const&) = 0;
virtual void paint_progressbar(Painter&, IntRect const&, Palette const&, int min, int max, int value, StringView text, Orientation = Orientation::Horizontal) = 0;
virtual void paint_radio_button(Painter&, IntRect const&, Palette const&, bool is_checked, bool is_being_pressed) = 0;
virtual void paint_check_box(Painter&, IntRect const&, Palette const&, bool is_enabled, bool is_checked, bool is_being_pressed) = 0;
virtual void paint_transparency_grid(Painter&, IntRect const&, Palette const&) = 0;
virtual void paint_simple_rect_shadow(Painter&, IntRect const&, Bitmap const& shadow_bitmap, bool shadow_includes_frame = false, bool fill_content = false) = 0;
protected:
BaseStylePainter() = default;
};
class StylePainter {
public:
static BaseStylePainter& current();
// FIXME: These are here for API compatibility, we should probably remove them and move BaseStylePainter into here
static void paint_button(Painter&, IntRect const&, Palette const&, ButtonStyle, bool pressed, bool hovered = false, bool checked = false, bool enabled = true, bool focused = false, bool default_button = false);
static void paint_tab_button(Painter&, IntRect const&, Palette const&, bool active, bool hovered, bool enabled, TabPosition position, bool in_active_window, bool accented);
static void paint_frame(Painter&, IntRect const&, Palette const&, FrameStyle, bool skip_vertical_lines = false);
static void paint_window_frame(Painter&, IntRect const&, Palette const&);
static void paint_progressbar(Painter&, IntRect const&, Palette const&, int min, int max, int value, StringView text, Orientation = Orientation::Horizontal);
static void paint_radio_button(Painter&, IntRect const&, Palette const&, bool is_checked, bool is_being_pressed);
static void paint_check_box(Painter&, IntRect const&, Palette const&, bool is_enabled, bool is_checked, bool is_being_pressed);
static void paint_transparency_grid(Painter&, IntRect const&, Palette const&);
static void paint_simple_rect_shadow(Painter&, IntRect const&, Bitmap const& shadow_bitmap, bool shadow_includes_frame = false, bool fill_content = false);
};
}

View file

@ -1,18 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/ClassicWindowTheme.h>
#include <LibGfx/WindowTheme.h>
namespace Gfx {
WindowTheme& WindowTheme::current()
{
static ClassicWindowTheme theme;
return theme;
}
}

View file

@ -1,59 +0,0 @@
/*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Forward.h>
#include <LibGfx/Forward.h>
namespace Gfx {
class WindowTheme {
public:
enum class WindowMode {
RenderAbove,
Other,
};
enum class WindowType {
Normal,
Notification,
Other,
};
enum class WindowState {
Active,
Inactive,
Highlighted,
Moving,
};
virtual ~WindowTheme() = default;
static WindowTheme& current();
virtual void paint_normal_frame(Painter&, WindowState, WindowMode, IntRect const& window_rect, StringView title, Bitmap const& icon, Palette const&, IntRect const& leftmost_button_rect, int menu_row_count, bool window_modified) const = 0;
virtual void paint_notification_frame(Painter&, WindowMode, IntRect const& window_rect, Palette const&, IntRect const& close_button_rect) const = 0;
virtual int titlebar_height(WindowType, WindowMode, Palette const&) const = 0;
virtual IntRect titlebar_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&) const = 0;
virtual IntRect titlebar_icon_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&) const = 0;
virtual IntRect titlebar_text_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&) const = 0;
virtual IntRect menubar_rect(WindowType, WindowMode, IntRect const& window_rect, Palette const&, int menu_row_count) const = 0;
virtual IntRect frame_rect_for_window(WindowType, WindowMode, IntRect const& window_rect, Palette const&, int menu_row_count) const = 0;
virtual Vector<IntRect> layout_buttons(WindowType, WindowMode, IntRect const& window_rect, Palette const&, size_t buttons) const = 0;
virtual bool is_simple_rect_frame() const = 0;
virtual bool frame_uses_alpha(WindowState, Palette const&) const = 0;
virtual float frame_alpha_hit_threshold(WindowState) const = 0;
protected:
WindowTheme() = default;
};
}

View file

@ -23,7 +23,6 @@
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/Size.h>
#include <LibGfx/StylePainter.h>
#include <LibGfx/TextAlignment.h>
#include <LibGfx/TextDirection.h>
#include <LibGfx/TextElision.h>

View file

@ -5,7 +5,6 @@
*/
#include <LibGfx/Filters/StackBlurFilter.h>
#include <LibGfx/StylePainter.h>
#include <LibWeb/CSS/ComputedValues.h>
#include <LibWeb/Painting/BorderRadiusCornerClipper.h>
#include <LibWeb/Painting/CommandExecutorCPU.h>

View file

@ -23,7 +23,6 @@
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/Size.h>
#include <LibGfx/StylePainter.h>
#include <LibGfx/TextAlignment.h>
#include <LibGfx/TextDirection.h>
#include <LibGfx/TextElision.h>

View file

@ -4,7 +4,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/StylePainter.h>
#include <LibWeb/CSS/StyleValues/EdgeStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/PositionStyleValue.h>

View file

@ -5,7 +5,6 @@
*/
#include <LibGfx/AntiAliasingPainter.h>
#include <LibGfx/StylePainter.h>
#include <LibJS/Heap/Heap.h>
#include <LibWeb/Layout/ListItemMarkerBox.h>
#include <LibWeb/Painting/MarkerPaintable.h>

View file

@ -5,7 +5,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGfx/StylePainter.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/HTML/BrowsingContext.h>
#include <LibWeb/HTML/HTMLInputElement.h>

View file

@ -23,7 +23,6 @@
#include <LibGfx/Point.h>
#include <LibGfx/Rect.h>
#include <LibGfx/Size.h>
#include <LibGfx/StylePainter.h>
#include <LibGfx/TextAlignment.h>
#include <LibGfx/TextDirection.h>
#include <LibGfx/TextElision.h>