Browse Source

LibWeb: Implement `mask-type` CSS property

This property allows specifying if a mask is an alpha or luminance mask.

See: https://drafts.fxtf.org/css-masking/#the-mask-type
MacDue 1 year ago
parent
commit
479451498b

+ 1 - 0
Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt

@@ -104,6 +104,7 @@ margin-left: 8px
 margin-right: 8px
 margin-right: 8px
 margin-top: 8px
 margin-top: 8px
 mask: none
 mask: none
+mask-type: luminance
 math-depth: 0
 math-depth: 0
 math-shift: normal
 math-shift: normal
 math-style: normal
 math-style: normal

+ 4 - 0
Userland/Libraries/LibWeb/CSS/ComputedValues.h

@@ -131,6 +131,7 @@ public:
     static CSS::TableLayout table_layout() { return CSS::TableLayout::Auto; }
     static CSS::TableLayout table_layout() { return CSS::TableLayout::Auto; }
     static QuotesData quotes() { return QuotesData { .type = QuotesData::Type::Auto }; }
     static QuotesData quotes() { return QuotesData { .type = QuotesData::Type::Auto }; }
 
 
+    static CSS::MaskType mask_type() { return CSS::MaskType::Luminance; }
     static CSS::MathShift math_shift() { return CSS::MathShift::Normal; }
     static CSS::MathShift math_shift() { return CSS::MathShift::Normal; }
     static CSS::MathStyle math_style() { return CSS::MathStyle::Normal; }
     static CSS::MathStyle math_style() { return CSS::MathStyle::Normal; }
     static int math_depth() { return 0; }
     static int math_depth() { return 0; }
@@ -360,6 +361,7 @@ public:
     float stop_opacity() const { return m_noninherited.stop_opacity; }
     float stop_opacity() const { return m_noninherited.stop_opacity; }
     CSS::TextAnchor text_anchor() const { return m_inherited.text_anchor; }
     CSS::TextAnchor text_anchor() const { return m_inherited.text_anchor; }
     Optional<MaskReference> const& mask() const { return m_noninherited.mask; }
     Optional<MaskReference> const& mask() const { return m_noninherited.mask; }
+    CSS::MaskType mask_type() const { return m_noninherited.mask_type; }
 
 
     Vector<CSS::Transformation> const& transformations() const { return m_noninherited.transformations; }
     Vector<CSS::Transformation> const& transformations() const { return m_noninherited.transformations; }
     CSS::TransformOrigin const& transform_origin() const { return m_noninherited.transform_origin; }
     CSS::TransformOrigin const& transform_origin() const { return m_noninherited.transform_origin; }
@@ -506,6 +508,7 @@ protected:
         CSS::TableLayout table_layout { InitialValues::table_layout() };
         CSS::TableLayout table_layout { InitialValues::table_layout() };
 
 
         Optional<MaskReference> mask;
         Optional<MaskReference> mask;
+        CSS::MaskType mask_type { InitialValues::mask_type() };
     } m_noninherited;
     } m_noninherited;
 };
 };
 
 
@@ -624,6 +627,7 @@ public:
     void set_outline_style(CSS::OutlineStyle value) { m_noninherited.outline_style = value; }
     void set_outline_style(CSS::OutlineStyle value) { m_noninherited.outline_style = value; }
     void set_outline_width(CSS::Length value) { m_noninherited.outline_width = value; }
     void set_outline_width(CSS::Length value) { m_noninherited.outline_width = value; }
     void set_mask(MaskReference value) { m_noninherited.mask = value; }
     void set_mask(MaskReference value) { m_noninherited.mask = value; }
+    void set_mask_type(CSS::MaskType value) { m_noninherited.mask_type = value; }
 
 
     void set_math_shift(CSS::MathShift value) { m_inherited.math_shift = value; }
     void set_math_shift(CSS::MathShift value) { m_inherited.math_shift = value; }
     void set_math_style(CSS::MathStyle value) { m_inherited.math_style = value; }
     void set_math_style(CSS::MathStyle value) { m_inherited.math_style = value; }

+ 4 - 0
Userland/Libraries/LibWeb/CSS/Enums.json

@@ -276,6 +276,10 @@
     "inside",
     "inside",
     "outside"
     "outside"
   ],
   ],
+  "mask-type": [
+    "luminance",
+    "alpha"
+  ],
   "math-shift": [
   "math-shift": [
     "normal",
     "normal",
     "compact"
     "compact"

+ 2 - 0
Userland/Libraries/LibWeb/CSS/Identifiers.json

@@ -68,6 +68,7 @@
   "alias",
   "alias",
   "all",
   "all",
   "all-scroll",
   "all-scroll",
+  "alpha",
   "alternate",
   "alternate",
   "alternate-reverse",
   "alternate-reverse",
   "anywhere",
   "anywhere",
@@ -220,6 +221,7 @@
   "lowercase",
   "lowercase",
   "ltr",
   "ltr",
   "listbox",
   "listbox",
+  "luminance",
   "mark",
   "mark",
   "marktext",
   "marktext",
   "math",
   "math",

+ 8 - 0
Userland/Libraries/LibWeb/CSS/Properties.json

@@ -1502,6 +1502,14 @@
     ],
     ],
     "initial": "none"
     "initial": "none"
   },
   },
+  "mask-type": {
+    "inherited": false,
+    "affects-layout": false,
+    "valid-types": [
+      "mask-type"
+    ],
+    "initial": "luminance"
+  },
   "math-depth": {
   "math-depth": {
     "inherited": true,
     "inherited": true,
     "initial": "0",
     "initial": "0",

+ 6 - 0
Userland/Libraries/LibWeb/CSS/StyleProperties.cpp

@@ -1015,6 +1015,12 @@ Optional<CSS::TableLayout> StyleProperties::table_layout() const
     return value_id_to_table_layout(value->to_identifier());
     return value_id_to_table_layout(value->to_identifier());
 }
 }
 
 
+Optional<CSS::MaskType> StyleProperties::mask_type() const
+{
+    auto value = property(CSS::PropertyID::MaskType);
+    return value_id_to_mask_type(value->to_identifier());
+}
+
 Color StyleProperties::stop_color() const
 Color StyleProperties::stop_color() const
 {
 {
     auto value = property(CSS::PropertyID::StopColor);
     auto value = property(CSS::PropertyID::StopColor);

+ 1 - 0
Userland/Libraries/LibWeb/CSS/StyleProperties.h

@@ -122,6 +122,7 @@ public:
     Vector<CSS::Transformation> transformations() const;
     Vector<CSS::Transformation> transformations() const;
     CSS::TransformOrigin transform_origin() const;
     CSS::TransformOrigin transform_origin() const;
 
 
+    Optional<CSS::MaskType> mask_type() const;
     Color stop_color() const;
     Color stop_color() const;
     float stop_opacity() const;
     float stop_opacity() const;
     float fill_opacity() const;
     float fill_opacity() const;

+ 3 - 0
Userland/Libraries/LibWeb/Layout/Node.cpp

@@ -778,6 +778,9 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
     else if (stroke_width->is_percentage())
     else if (stroke_width->is_percentage())
         computed_values.set_stroke_width(CSS::LengthPercentage { stroke_width->as_percentage().percentage() });
         computed_values.set_stroke_width(CSS::LengthPercentage { stroke_width->as_percentage().percentage() });
 
 
+    if (auto mask_type = computed_style.mask_type(); mask_type.has_value())
+        computed_values.set_mask_type(*mask_type);
+
     if (auto mask = computed_style.property(CSS::PropertyID::Mask); mask->is_url())
     if (auto mask = computed_style.property(CSS::PropertyID::Mask); mask->is_url())
         computed_values.set_mask(mask->as_url().url());
         computed_values.set_mask(mask->as_url().url());
 
 

+ 14 - 2
Userland/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp

@@ -40,6 +40,18 @@ Optional<CSSPixelRect> SVGGraphicsPaintable::get_masking_area() const
     return {};
     return {};
 }
 }
 
 
+static Gfx::Bitmap::MaskKind mask_type_to_gfx_mask_kind(CSS::MaskType mask_type)
+{
+    switch (mask_type) {
+    case CSS::MaskType::Alpha:
+        return Gfx::Bitmap::MaskKind::Alpha;
+    case CSS::MaskType::Luminance:
+        return Gfx::Bitmap::MaskKind::Luminance;
+    default:
+        VERIFY_NOT_REACHED();
+    }
+}
+
 void SVGGraphicsPaintable::apply_mask(PaintContext& context, Gfx::Bitmap& target, CSSPixelRect const& masking_area) const
 void SVGGraphicsPaintable::apply_mask(PaintContext& context, Gfx::Bitmap& target, CSSPixelRect const& masking_area) const
 {
 {
     auto const& graphics_element = verify_cast<SVG::SVGGraphicsElement const>(*dom_node());
     auto const& graphics_element = verify_cast<SVG::SVGGraphicsElement const>(*dom_node());
@@ -65,9 +77,9 @@ void SVGGraphicsPaintable::apply_mask(PaintContext& context, Gfx::Bitmap& target
             StackingContext::paint_node_as_stacking_context(mask_paintable, paint_context);
             StackingContext::paint_node_as_stacking_context(mask_paintable, paint_context);
         }
         }
     }
     }
-    // TODO: Follow mask-type attribute to select between alpha/luminance masks.
     if (mask_bitmap)
     if (mask_bitmap)
-        target.apply_mask(*mask_bitmap, Gfx::Bitmap::MaskKind::Luminance);
+        target.apply_mask(*mask_bitmap,
+            mask_type_to_gfx_mask_kind(mask->layout_node()->computed_values().mask_type()));
     return;
     return;
 }
 }