diff options
author | Andreas Kling <kling@serenityos.org> | 2020-12-04 16:11:55 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-04 16:11:55 +0100 |
commit | 2cbbab8f73c34dcedf95cb236adcc9e6fb31cb56 (patch) | |
tree | 84bd38b30f8de63660cd82b5a0a62e653fa31374 | |
parent | 88ca932fac84e7e349a4f64f57e4d303df9e8397 (diff) | |
download | serenity-2cbbab8f73c34dcedf95cb236adcc9e6fb31cb56.zip |
LibWeb: Compute the final border-style property before painting
Instead of doing a CSS property lookup for the line style of each
border edge during paint, we now cache the final CSS::LineStyle to use
in the Layout::BorderData.
-rw-r--r-- | Libraries/LibWeb/CSS/StyleProperties.cpp | 29 | ||||
-rw-r--r-- | Libraries/LibWeb/CSS/StyleProperties.h | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/CSS/StyleValue.h | 13 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Box.cpp | 65 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Box.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/LayoutStyle.h | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Node.cpp | 19 |
7 files changed, 81 insertions, 49 deletions
diff --git a/Libraries/LibWeb/CSS/StyleProperties.cpp b/Libraries/LibWeb/CSS/StyleProperties.cpp index 0f1db911bf..386cf101f4 100644 --- a/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -259,6 +259,35 @@ Optional<CSS::WhiteSpace> StyleProperties::white_space() const return {}; } +Optional<CSS::LineStyle> StyleProperties::line_style(CSS::PropertyID property_id) const +{ + auto value = property(property_id); + if (!value.has_value() || !value.value()->is_string()) + return {}; + auto string = value.value()->to_string(); + if (string == "none") + return CSS::LineStyle::None; + if (string == "hidden") + return CSS::LineStyle::Hidden; + if (string == "dotted") + return CSS::LineStyle::Dotted; + if (string == "dashed") + return CSS::LineStyle::Dashed; + if (string == "solid") + return CSS::LineStyle::Solid; + if (string == "double") + return CSS::LineStyle::Double; + if (string == "groove") + return CSS::LineStyle::Groove; + if (string == "ridge") + return CSS::LineStyle::Ridge; + if (string == "inset") + return CSS::LineStyle::Inset; + if (string == "outset") + return CSS::LineStyle::Outset; + return {}; +} + Optional<CSS::Float> StyleProperties::float_() const { auto value = property(CSS::PropertyID::Float); diff --git a/Libraries/LibWeb/CSS/StyleProperties.h b/Libraries/LibWeb/CSS/StyleProperties.h index 8622fea9ca..924575e6e3 100644 --- a/Libraries/LibWeb/CSS/StyleProperties.h +++ b/Libraries/LibWeb/CSS/StyleProperties.h @@ -64,6 +64,7 @@ public: CSS::Display display() const; Optional<CSS::Float> float_() const; Optional<CSS::WhiteSpace> white_space() const; + Optional<CSS::LineStyle> line_style(CSS::PropertyID) const; const Gfx::Font& font() const { diff --git a/Libraries/LibWeb/CSS/StyleValue.h b/Libraries/LibWeb/CSS/StyleValue.h index b21e57d8cc..6d4d8cb953 100644 --- a/Libraries/LibWeb/CSS/StyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValue.h @@ -149,6 +149,19 @@ enum class Float { Right, }; +enum class LineStyle { + None, + Hidden, + Dotted, + Dashed, + Solid, + Double, + Groove, + Ridge, + Inset, + Outset, +}; + class StyleValue : public RefCounted<StyleValue> { public: virtual ~StyleValue(); diff --git a/Libraries/LibWeb/Layout/Box.cpp b/Libraries/LibWeb/Layout/Box.cpp index 09d3ea4bbe..3c0b151da0 100644 --- a/Libraries/LibWeb/Layout/Box.cpp +++ b/Libraries/LibWeb/Layout/Box.cpp @@ -33,66 +33,53 @@ namespace Web::Layout { -void Box::paint_border(PaintContext& context, Edge edge, const Gfx::FloatRect& rect, CSS::PropertyID style_property_id, const BorderData& border_data) +void Box::paint_border(PaintContext& context, Edge edge, const Gfx::FloatRect& rect, const BorderData& border_data) { float width = border_data.width; if (width <= 0) return; auto color = border_data.color; - auto border_style = specified_style().property(style_property_id); + auto border_style = border_data.line_style; int int_width = max((int)width, 1); - auto first_point_for_edge = [](Edge edge, const Gfx::FloatRect& rect) { - switch (edge) { - case Edge::Top: - return rect.top_left(); - case Edge::Right: - return rect.top_right(); - case Edge::Bottom: - return rect.bottom_left(); - case Edge::Left: - default: - return rect.top_left(); - } + struct Points { + Gfx::FloatPoint p1; + Gfx::FloatPoint p2; }; - auto second_point_for_edge = [](Edge edge, const Gfx::FloatRect& rect) { + auto points_for_edge = [](Edge edge, const Gfx::FloatRect& rect) -> Points { switch (edge) { case Edge::Top: - return rect.top_right(); + return { rect.top_left(), rect.top_right() }; case Edge::Right: - return rect.bottom_right(); + return { rect.top_right(), rect.bottom_right() }; case Edge::Bottom: - return rect.bottom_right(); - case Edge::Left: - default: - return rect.bottom_left(); + return { rect.bottom_left(), rect.bottom_right() }; + default: // Edge::Left + return { rect.top_left(), rect.bottom_left() }; } }; - auto p1 = first_point_for_edge(edge, rect); - auto p2 = second_point_for_edge(edge, rect); + auto [p1, p2] = points_for_edge(edge, rect); - if (border_style.has_value() && border_style.value()->to_string() == "inset") { + if (border_style == CSS::LineStyle::Inset) { auto top_left_color = Color::from_rgb(0x5a5a5a); auto bottom_right_color = Color::from_rgb(0x888888); color = (edge == Edge::Left || edge == Edge::Top) ? top_left_color : bottom_right_color; - } else if (border_style.has_value() && border_style.value()->to_string() == "outset") { + } else if (border_style == CSS::LineStyle::Outset) { auto top_left_color = Color::from_rgb(0x888888); auto bottom_right_color = Color::from_rgb(0x5a5a5a); color = (edge == Edge::Left || edge == Edge::Top) ? top_left_color : bottom_right_color; } - auto line_style = Gfx::Painter::LineStyle::Solid; - if (border_style.has_value()) { - if (border_style.value()->to_string() == "dotted") - line_style = Gfx::Painter::LineStyle::Dotted; - if (border_style.value()->to_string() == "dashed") - line_style = Gfx::Painter::LineStyle::Dashed; - } + auto gfx_line_style = Gfx::Painter::LineStyle::Solid; + if (border_style == CSS::LineStyle::Dotted) + gfx_line_style = Gfx::Painter::LineStyle::Dotted; + if (border_style == CSS::LineStyle::Dashed) + gfx_line_style = Gfx::Painter::LineStyle::Dashed; - if (line_style != Gfx::Painter::LineStyle::Solid) { + if (gfx_line_style != Gfx::Painter::LineStyle::Solid) { switch (edge) { case Edge::Top: p1.move_by(int_width / 2, int_width / 2); @@ -111,12 +98,12 @@ void Box::paint_border(PaintContext& context, Edge edge, const Gfx::FloatRect& r p2.move_by(int_width / 2, -int_width / 2); break; } - context.painter().draw_line({ (int)p1.x(), (int)p1.y() }, { (int)p2.x(), (int)p2.y() }, color, int_width, line_style); + context.painter().draw_line({ (int)p1.x(), (int)p1.y() }, { (int)p2.x(), (int)p2.y() }, color, int_width, gfx_line_style); return; } auto draw_line = [&](auto& p1, auto& p2) { - context.painter().draw_line({ (int)p1.x(), (int)p1.y() }, { (int)p2.x(), (int)p2.y() }, color, 1, line_style); + context.painter().draw_line({ (int)p1.x(), (int)p1.y() }, { (int)p2.x(), (int)p2.y() }, color, 1, gfx_line_style); }; float p1_step = 0; @@ -200,10 +187,10 @@ void Box::paint(PaintContext& context, PaintPhase phase) bordered_rect.set_y(padded_rect.y() - box_model().border.top.to_px(*this)); bordered_rect.set_height(padded_rect.height() + box_model().border.top.to_px(*this) + box_model().border.bottom.to_px(*this)); - paint_border(context, Edge::Left, bordered_rect, CSS::PropertyID::BorderLeftStyle, style().border_left()); - paint_border(context, Edge::Right, bordered_rect, CSS::PropertyID::BorderRightStyle, style().border_right()); - paint_border(context, Edge::Top, bordered_rect, CSS::PropertyID::BorderTopStyle, style().border_top()); - paint_border(context, Edge::Bottom, bordered_rect, CSS::PropertyID::BorderBottomStyle, style().border_bottom()); + paint_border(context, Edge::Left, bordered_rect, style().border_left()); + paint_border(context, Edge::Right, bordered_rect, style().border_right()); + paint_border(context, Edge::Top, bordered_rect, style().border_top()); + paint_border(context, Edge::Bottom, bordered_rect, style().border_bottom()); } Layout::NodeWithStyleAndBoxModelMetrics::paint(context, phase); diff --git a/Libraries/LibWeb/Layout/Box.h b/Libraries/LibWeb/Layout/Box.h index 0354938e05..0fa084ec7b 100644 --- a/Libraries/LibWeb/Layout/Box.h +++ b/Libraries/LibWeb/Layout/Box.h @@ -98,7 +98,7 @@ private: Bottom, Left, }; - void paint_border(PaintContext&, Edge, const Gfx::FloatRect&, CSS::PropertyID style_property_id, const BorderData&); + void paint_border(PaintContext&, Edge, const Gfx::FloatRect&, const BorderData&); Gfx::FloatPoint m_offset; Gfx::FloatSize m_size; diff --git a/Libraries/LibWeb/Layout/LayoutStyle.h b/Libraries/LibWeb/Layout/LayoutStyle.h index 2c0c4bb96e..dba8290de4 100644 --- a/Libraries/LibWeb/Layout/LayoutStyle.h +++ b/Libraries/LibWeb/Layout/LayoutStyle.h @@ -41,6 +41,7 @@ public: struct BorderData { public: Color color { Color::Transparent }; + CSS::LineStyle line_style { CSS::LineStyle::None }; float width { 0 }; }; diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index fa196022b3..1014c05ea8 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -241,15 +241,16 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& specified_style) style.set_margin(specified_style.length_box(CSS::PropertyID::MarginLeft, CSS::PropertyID::MarginTop, CSS::PropertyID::MarginRight, CSS::PropertyID::MarginBottom)); style.set_padding(specified_style.length_box(CSS::PropertyID::PaddingLeft, CSS::PropertyID::PaddingTop, CSS::PropertyID::PaddingRight, CSS::PropertyID::PaddingBottom)); - style.border_left().width = specified_style.length_or_fallback(CSS::PropertyID::BorderLeftWidth, {}).resolved_or_zero(*this, 0).to_px(*this); - style.border_top().width = specified_style.length_or_fallback(CSS::PropertyID::BorderTopWidth, {}).resolved_or_zero(*this, 0).to_px(*this); - style.border_right().width = specified_style.length_or_fallback(CSS::PropertyID::BorderRightWidth, {}).resolved_or_zero(*this, 0).to_px(*this); - style.border_bottom().width = specified_style.length_or_fallback(CSS::PropertyID::BorderBottomWidth, {}).resolved_or_zero(*this, 0).to_px(*this); - - style.border_left().color = specified_style.color_or_fallback(CSS::PropertyID::BorderLeftColor, document(), Color::Transparent); - style.border_top().color = specified_style.color_or_fallback(CSS::PropertyID::BorderTopColor, document(), Color::Transparent); - style.border_right().color = specified_style.color_or_fallback(CSS::PropertyID::BorderRightColor, document(), Color::Transparent); - style.border_bottom().color = specified_style.color_or_fallback(CSS::PropertyID::BorderBottomColor, document(), Color::Transparent); + auto do_border_style = [&](BorderData& border, CSS::PropertyID width_property, CSS::PropertyID color_property, CSS::PropertyID style_property) { + border.width = specified_style.length_or_fallback(width_property, {}).resolved_or_zero(*this, 0).to_px(*this); + border.color = specified_style.color_or_fallback(color_property, document(), Color::Transparent); + border.line_style = specified_style.line_style(style_property).value_or(CSS::LineStyle::None); + }; + + do_border_style(style.border_left(), CSS::PropertyID::BorderLeftWidth, CSS::PropertyID::BorderLeftColor, CSS::PropertyID::BorderLeftStyle); + do_border_style(style.border_top(), CSS::PropertyID::BorderTopWidth, CSS::PropertyID::BorderTopColor, CSS::PropertyID::BorderTopStyle); + do_border_style(style.border_right(), CSS::PropertyID::BorderRightWidth, CSS::PropertyID::BorderRightColor, CSS::PropertyID::BorderRightStyle); + do_border_style(style.border_bottom(), CSS::PropertyID::BorderBottomWidth, CSS::PropertyID::BorderBottomColor, CSS::PropertyID::BorderBottomStyle); } void Node::handle_mousedown(Badge<EventHandler>, const Gfx::IntPoint&, unsigned, unsigned) |