From a81edb3bdc462983d5f34335d69b6d87e364417d Mon Sep 17 00:00:00 2001 From: Yevhenii Reizner Date: Sun, 23 Apr 2023 17:25:37 +0300 Subject: [PATCH] Add `mask-type` property support. SVG2 Closes #582 --- CHANGELOG.md | 4 + Cargo.lock | 4 +- Cargo.toml | 2 +- docs/svg2-changelog.md | 2 +- rosvgtree/codegen/attributes.txt | 16 ++ rosvgtree/src/names.rs | 443 +++++++++++++++++-------------- src/mask.rs | 7 +- tests/integration/render.rs | 5 + tests/png/e-mask-032.png | Bin 0 -> 1512 bytes tests/png/e-mask-033.png | Bin 0 -> 877 bytes tests/png/e-mask-034.png | Bin 0 -> 877 bytes tests/png/e-mask-035.png | Bin 0 -> 1269 bytes tests/png/e-mask-036.png | Bin 0 -> 1056 bytes tests/svg/e-mask-032.svg | 15 ++ tests/svg/e-mask-033.svg | 15 ++ tests/svg/e-mask-034.svg | 15 ++ tests/svg/e-mask-035.svg | 22 ++ tests/svg/e-mask-036.svg | 22 ++ usvg-parser/src/mask.rs | 9 +- usvg-tree/src/lib.rs | 20 ++ usvg/docs/spec.adoc | 2 + usvg/src/writer.rs | 3 + 22 files changed, 396 insertions(+), 210 deletions(-) create mode 100644 tests/png/e-mask-032.png create mode 100644 tests/png/e-mask-033.png create mode 100644 tests/png/e-mask-034.png create mode 100644 tests/png/e-mask-035.png create mode 100644 tests/png/e-mask-036.png create mode 100644 tests/svg/e-mask-032.svg create mode 100644 tests/svg/e-mask-033.svg create mode 100644 tests/svg/e-mask-034.svg create mode 100644 tests/svg/e-mask-035.svg create mode 100644 tests/svg/e-mask-036.svg diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f5a6d02a..2997f0c03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ This changelog also contains important changes in dependencies. ## [Unreleased] ### Added - Clipping and masking is up to 20% faster. +- `mask-type` property support. SVG2 +- `usvg_tree::MaskType` +- `usvg_tree::Mask::kind` +- (rosvgtree) New SVG 2 mask attributes. ### Fixed - Improve rectangular clipping anti-aliasing quality. diff --git a/Cargo.lock b/Cargo.lock index db17490ad..30ba818e5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -354,7 +354,7 @@ dependencies = [ [[package]] name = "tiny-skia" version = "0.8.4" -source = "git+https://github.com/RazrFalcon/tiny-skia?rev=3690003#3690003615b67c952b7fe135b4d79015c29fe8e7" +source = "git+https://github.com/RazrFalcon/tiny-skia?rev=e4f4095#e4f4095c4b08f6264d836744483bb8492d5c6cbb" dependencies = [ "arrayref", "arrayvec", @@ -368,7 +368,7 @@ dependencies = [ [[package]] name = "tiny-skia-path" version = "0.8.4" -source = "git+https://github.com/RazrFalcon/tiny-skia?rev=3690003#3690003615b67c952b7fe135b4d79015c29fe8e7" +source = "git+https://github.com/RazrFalcon/tiny-skia?rev=e4f4095#e4f4095c4b08f6264d836744483bb8492d5c6cbb" dependencies = [ "arrayref", "bytemuck", diff --git a/Cargo.toml b/Cargo.toml index 2c50ceffb..bbc749216 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ png = { version = "0.17", optional = true } rgb = "0.8" svgfilters = { path = "svgfilters", version = "0.4", optional = true } svgtypes = "0.11" -tiny-skia = { git = "https://github.com/RazrFalcon/tiny-skia", rev = "3690003" } +tiny-skia = { git = "https://github.com/RazrFalcon/tiny-skia", rev = "e4f4095" } usvg = { path = "usvg", version = "0.31.0", default-features = false } [dev-dependencies] diff --git a/docs/svg2-changelog.md b/docs/svg2-changelog.md index aeb9cf5c2..a104007b5 100644 --- a/docs/svg2-changelog.md +++ b/docs/svg2-changelog.md @@ -227,7 +227,7 @@ Basically everything from [CSS Text Module Level 3](https://www.w3.org/TR/css-te - [ ] A [`mask-origin`](https://www.w3.org/TR/css-masking-1/#the-mask-origin) property. - [ ] A [`mask-size`](https://www.w3.org/TR/css-masking-1/#the-mask-size) property. - [ ] A [`mask-composite`](https://www.w3.org/TR/css-masking-1/#the-mask-composite) property. -- [ ] A [`mask-type`](https://www.w3.org/TR/css-masking-1/#the-mask-type) property. +- [x] A [`mask-type`](https://www.w3.org/TR/css-masking-1/#the-mask-type) property. - [ ] A [`mask-border-source`](https://www.w3.org/TR/css-masking-1/#the-mask-border-source) property. - [ ] A [`mask-border-mode`](https://www.w3.org/TR/css-masking-1/#the-mask-border-mode) property. - [ ] A [`mask-border-slice`](https://www.w3.org/TR/css-masking-1/#the-mask-border-slice) property. diff --git a/rosvgtree/codegen/attributes.txt b/rosvgtree/codegen/attributes.txt index 81a8192e2..97598a82a 100644 --- a/rosvgtree/codegen/attributes.txt +++ b/rosvgtree/codegen/attributes.txt @@ -51,6 +51,7 @@ font-variant-ligatures font-variant-numeric font-variant-position font-weight +fr fx fy glyph-orientation-horizontal @@ -85,6 +86,21 @@ markerHeight markerUnits markerWidth mask +mask-border +mask-border-mode +mask-border-outset +mask-border-repeat +mask-border-slice +mask-border-source +mask-border-width +mask-clip +mask-composite +mask-image +mask-mode +mask-origin +mask-position +mask-size +mask-type maskContentUnits maskUnits mix-blend-mode diff --git a/rosvgtree/src/names.rs b/rosvgtree/src/names.rs index 668a20d60..735cd96d3 100644 --- a/rosvgtree/src/names.rs +++ b/rosvgtree/src/names.rs @@ -213,6 +213,7 @@ pub enum AttributeId { FontVariantNumeric, FontVariantPosition, FontWeight, + Fr, Fx, Fy, GlyphOrientationHorizontal, @@ -247,6 +248,21 @@ pub enum AttributeId { MarkerUnits, MarkerWidth, Mask, + MaskBorder, + MaskBorderMode, + MaskBorderOutset, + MaskBorderRepeat, + MaskBorderSlice, + MaskBorderSource, + MaskBorderWidth, + MaskClip, + MaskComposite, + MaskImage, + MaskMode, + MaskOrigin, + MaskPosition, + MaskSize, + MaskType, MaskContentUnits, MaskUnits, MixBlendMode, @@ -357,239 +373,258 @@ pub enum AttributeId { static ATTRIBUTES: Map = Map { key: 732231254413039614, disps: &[ - (0, 103), - (1, 31), - (0, 1), - (0, 2), - (0, 31), - (3, 20), - (0, 164), - (0, 97), - (0, 2), - (0, 4), - (0, 12), - (0, 166), + (63, 17), (0, 1), - (4, 174), - (2, 158), - (0, 13), - (0, 18), + (0, 113), + (0, 21), + (0, 8), + (0, 23), + (0, 15), + (0, 3), + (40, 203), + (0, 3), + (0, 6), + (1, 31), + (0, 68), + (11, 161), + (0, 41), + (2, 58), + (7, 10), (0, 0), - (0, 138), - (7, 16), - (1, 100), - (5, 19), - (10, 59), + (0, 39), + (7, 73), (0, 5), - (0, 146), - (0, 44), - (0, 72), - (0, 26), - (0, 1), - (3, 147), + (65, 30), + (0, 71), + (0, 28), (0, 7), - (0, 11), - (0, 10), - (5, 91), - (0, 74), - (4, 37), - (0, 138), + (2, 99), + (0, 168), + (1, 79), + (0, 0), (0, 3), - (6, 164), + (0, 21), + (1, 9), + (0, 0), + (5, 171), + (0, 45), + (0, 18), + (99, 110), + (31, 206), + (5, 125), + (0, 14), + (0, 4), + (0, 83), ], entries: &[ - ("color-interpolation", AttributeId::ColorInterpolation), - ("id", AttributeId::Id), - ("inline-size", AttributeId::InlineSize), - ("flood-opacity", AttributeId::FloodOpacity), - ("kernelMatrix", AttributeId::KernelMatrix), - ("font-stretch", AttributeId::FontStretch), - ("mask", AttributeId::Mask), - ("order", AttributeId::Order), - ("kerning", AttributeId::Kerning), - ("font-size-adjust", AttributeId::FontSizeAdjust), - ("limitingConeAngle", AttributeId::LimitingConeAngle), - ("azimuth", AttributeId::Azimuth), - ("k4", AttributeId::K4), - ("fill", AttributeId::Fill), - ("intercept", AttributeId::Intercept), - ("text-align-last", AttributeId::TextAlignLast), - ("text-decoration-fill", AttributeId::TextDecorationFill), + ("mask-type", AttributeId::MaskType), + ("markerWidth", AttributeId::MarkerWidth), ("textLength", AttributeId::TextLength), - ("patternUnits", AttributeId::PatternUnits), - ("space", AttributeId::Space), - ("side", AttributeId::Side), - ("line-height", AttributeId::LineHeight), - ("stroke-linejoin", AttributeId::StrokeLinejoin), - ("xChannelSelector", AttributeId::XChannelSelector), - ("kernelUnitLength", AttributeId::KernelUnitLength), - ("k3", AttributeId::K3), - ("font-feature-settings", AttributeId::FontFeatureSettings), - ("fill-opacity", AttributeId::FillOpacity), - ("transform-box", AttributeId::TransformBox), - ("lengthAdjust", AttributeId::LengthAdjust), - ("marker-end", AttributeId::MarkerEnd), - ("y1", AttributeId::Y1), - ("specularExponent", AttributeId::SpecularExponent), - ("direction", AttributeId::Direction), - ("stroke-linecap", AttributeId::StrokeLinecap), - ("display", AttributeId::Display), - ("text-overflow", AttributeId::TextOverflow), - ("text-decoration-color", AttributeId::TextDecorationColor), - ("transform-origin", AttributeId::TransformOrigin), - ("lighting-color", AttributeId::LightingColor), - ("systemLanguage", AttributeId::SystemLanguage), - ("pointsAtZ", AttributeId::PointsAtZ), - ("cy", AttributeId::Cy), - ("k2", AttributeId::K2), - ("specularConstant", AttributeId::SpecularConstant), - ("tableValues", AttributeId::TableValues), + ("alignment-baseline", AttributeId::AlignmentBaseline), + ("unicode-bidi", AttributeId::UnicodeBidi), ("dominant-baseline", AttributeId::DominantBaseline), - ("stroke-width", AttributeId::StrokeWidth), - ("dx", AttributeId::Dx), - ("font-variant-caps", AttributeId::FontVariantCaps), - ("shape-subtract", AttributeId::ShapeSubtract), - ("shape-image-threshold", AttributeId::ShapeImageThreshold), - ("gradientTransform", AttributeId::GradientTransform), - ("pointsAtX", AttributeId::PointsAtX), + ("orient", AttributeId::Orient), + ("x", AttributeId::X), + ("font-style", AttributeId::FontStyle), + ("color-interpolation", AttributeId::ColorInterpolation), + ("style", AttributeId::Style), + ("clip-rule", AttributeId::ClipRule), + ("bias", AttributeId::Bias), + ("font-weight", AttributeId::FontWeight), + ("fill", AttributeId::Fill), + ("mask-border-outset", AttributeId::MaskBorderOutset), + ("x1", AttributeId::X1), + ("mask", AttributeId::Mask), + ("height", AttributeId::Height), + ("stroke", AttributeId::Stroke), + ("transform", AttributeId::Transform), + ("isolation", AttributeId::Isolation), + ("fy", AttributeId::Fy), + ("text-orientation", AttributeId::TextOrientation), + ("stop-opacity", AttributeId::StopOpacity), + ("fx", AttributeId::Fx), + ("font-kerning", AttributeId::FontKerning), ("cx", AttributeId::Cx), + ("maskContentUnits", AttributeId::MaskContentUnits), + ("opacity", AttributeId::Opacity), ("filterUnits", AttributeId::FilterUnits), - ("image-rendering", AttributeId::ImageRendering), - ("fx", AttributeId::Fx), - ("gradientUnits", AttributeId::GradientUnits), - ("text-orientation", AttributeId::TextOrientation), - ("exponent", AttributeId::Exponent), - ("rotate", AttributeId::Rotate), - ("d", AttributeId::D), - ("mix-blend-mode", AttributeId::MixBlendMode), - ("rx", AttributeId::Rx), - ("text-rendering", AttributeId::TextRendering), - ("glyph-orientation-horizontal", AttributeId::GlyphOrientationHorizontal), - ("enable-background", AttributeId::EnableBackground), - ("scale", AttributeId::Scale), - ("in", AttributeId::In), - ("font-variant-numeric", AttributeId::FontVariantNumeric), - ("font-variant-east-asian", AttributeId::FontVariantEastAsian), + ("lengthAdjust", AttributeId::LengthAdjust), ("text-anchor", AttributeId::TextAnchor), - ("glyph-orientation-vertical", AttributeId::GlyphOrientationVertical), - ("dy", AttributeId::Dy), - ("color-interpolation-filters", AttributeId::ColorInterpolationFilters), - ("clip-rule", AttributeId::ClipRule), ("stroke-miterlimit", AttributeId::StrokeMiterlimit), - ("isolation", AttributeId::Isolation), - ("transform", AttributeId::Transform), - ("stroke-dashoffset", AttributeId::StrokeDashoffset), - ("z", AttributeId::Z), - ("refX", AttributeId::RefX), - ("width", AttributeId::Width), - ("requiredExtensions", AttributeId::RequiredExtensions), - ("font-synthesis", AttributeId::FontSynthesis), - ("radius", AttributeId::Radius), - ("white-space", AttributeId::WhiteSpace), - ("patternTransform", AttributeId::PatternTransform), - ("maskContentUnits", AttributeId::MaskContentUnits), - ("stop-color", AttributeId::StopColor), - ("amplitude", AttributeId::Amplitude), + ("viewBox", AttributeId::ViewBox), ("visibility", AttributeId::Visibility), + ("ry", AttributeId::Ry), + ("glyph-orientation-horizontal", AttributeId::GlyphOrientationHorizontal), + ("gradientTransform", AttributeId::GradientTransform), + ("markerUnits", AttributeId::MarkerUnits), + ("shape-inside", AttributeId::ShapeInside), + ("font-size", AttributeId::FontSize), ("yChannelSelector", AttributeId::YChannelSelector), - ("color-rendering", AttributeId::ColorRendering), - ("diffuseConstant", AttributeId::DiffuseConstant), - ("stroke", AttributeId::Stroke), - ("text-decoration-style", AttributeId::TextDecorationStyle), - ("y2", AttributeId::Y2), - ("operator", AttributeId::Operator), - ("font-variant", AttributeId::FontVariant), ("clip-path", AttributeId::ClipPath), - ("edgeMode", AttributeId::EdgeMode), - ("text-indent", AttributeId::TextIndent), - ("numOctaves", AttributeId::NumOctaves), - ("font-size", AttributeId::FontSize), - ("alignment-baseline", AttributeId::AlignmentBaseline), - ("stroke-opacity", AttributeId::StrokeOpacity), + ("flood-color", AttributeId::FloodColor), + ("marker-mid", AttributeId::MarkerMid), + ("surfaceScale", AttributeId::SurfaceScale), + ("color-profile", AttributeId::ColorProfile), + ("requiredFeatures", AttributeId::RequiredFeatures), ("class", AttributeId::Class), + ("startOffset", AttributeId::StartOffset), + ("mask-origin", AttributeId::MaskOrigin), + ("stdDeviation", AttributeId::StdDeviation), + ("mode", AttributeId::Mode), + ("overflow", AttributeId::Overflow), + ("text-decoration-fill", AttributeId::TextDecorationFill), + ("mask-border-mode", AttributeId::MaskBorderMode), + ("divisor", AttributeId::Divisor), + ("marker-start", AttributeId::MarkerStart), + ("text-decoration-line", AttributeId::TextDecorationLine), + ("preserveAlpha", AttributeId::PreserveAlpha), + ("primitiveUnits", AttributeId::PrimitiveUnits), + ("in", AttributeId::In), + ("points", AttributeId::Points), + ("pointsAtY", AttributeId::PointsAtY), + ("specularExponent", AttributeId::SpecularExponent), + ("shape-rendering", AttributeId::ShapeRendering), ("refY", AttributeId::RefY), + ("clip", AttributeId::Clip), + ("white-space", AttributeId::WhiteSpace), + ("vector-effect", AttributeId::VectorEffect), + ("image-rendering", AttributeId::ImageRendering), ("stitchTiles", AttributeId::StitchTiles), - ("x2", AttributeId::X2), - ("unicode-bidi", AttributeId::UnicodeBidi), + ("stroke-opacity", AttributeId::StrokeOpacity), + ("shape-margin", AttributeId::ShapeMargin), + ("y2", AttributeId::Y2), + ("operator", AttributeId::Operator), + ("pathLength", AttributeId::PathLength), + ("order", AttributeId::Order), + ("text-rendering", AttributeId::TextRendering), + ("mask-border", AttributeId::MaskBorder), + ("exponent", AttributeId::Exponent), + ("color-interpolation-filters", AttributeId::ColorInterpolationFilters), + ("diffuseConstant", AttributeId::DiffuseConstant), + ("space", AttributeId::Space), + ("font-synthesis", AttributeId::FontSynthesis), + ("direction", AttributeId::Direction), + ("font-size-adjust", AttributeId::FontSizeAdjust), + ("kerning", AttributeId::Kerning), + ("flood-opacity", AttributeId::FloodOpacity), + ("mask-border-source", AttributeId::MaskBorderSource), + ("line-height", AttributeId::LineHeight), + ("mix-blend-mode", AttributeId::MixBlendMode), + ("scale", AttributeId::Scale), + ("mask-image", AttributeId::MaskImage), + ("dy", AttributeId::Dy), + ("xChannelSelector", AttributeId::XChannelSelector), + ("unicode-range", AttributeId::UnicodeRange), + ("y", AttributeId::Y), + ("fill-opacity", AttributeId::FillOpacity), + ("mask-composite", AttributeId::MaskComposite), ("targetY", AttributeId::TargetY), - ("vector-effect", AttributeId::VectorEffect), - ("fy", AttributeId::Fy), - ("clipPathUnits", AttributeId::ClipPathUnits), - ("href", AttributeId::Href), - ("x1", AttributeId::X1), - ("result", AttributeId::Result), + ("writing-mode", AttributeId::WritingMode), + ("transform-origin", AttributeId::TransformOrigin), + ("font-variant-caps", AttributeId::FontVariantCaps), + ("k2", AttributeId::K2), + ("transform-box", AttributeId::TransformBox), + ("text-decoration", AttributeId::TextDecoration), + ("filter", AttributeId::Filter), + ("enable-background", AttributeId::EnableBackground), + ("word-spacing", AttributeId::WordSpacing), + ("gradientUnits", AttributeId::GradientUnits), + ("font-feature-settings", AttributeId::FontFeatureSettings), + ("stroke-linecap", AttributeId::StrokeLinecap), + ("rx", AttributeId::Rx), + ("kernelUnitLength", AttributeId::KernelUnitLength), + ("shape-image-threshold", AttributeId::ShapeImageThreshold), + ("inline-size", AttributeId::InlineSize), + ("edgeMode", AttributeId::EdgeMode), + ("text-decoration-style", AttributeId::TextDecorationStyle), + ("pointsAtZ", AttributeId::PointsAtZ), + ("elevation", AttributeId::Elevation), + ("tableValues", AttributeId::TableValues), + ("kernelMatrix", AttributeId::KernelMatrix), + ("patternTransform", AttributeId::PatternTransform), ("fill-rule", AttributeId::FillRule), - ("color-profile", AttributeId::ColorProfile), + ("color", AttributeId::Color), + ("lighting-color", AttributeId::LightingColor), + ("cy", AttributeId::Cy), + ("fr", AttributeId::Fr), + ("systemLanguage", AttributeId::SystemLanguage), + ("text-indent", AttributeId::TextIndent), + ("slope", AttributeId::Slope), ("font", AttributeId::Font), - ("font-weight", AttributeId::FontWeight), - ("shape-padding", AttributeId::ShapePadding), - ("primitiveUnits", AttributeId::PrimitiveUnits), - ("height", AttributeId::Height), - ("bias", AttributeId::Bias), + ("requiredExtensions", AttributeId::RequiredExtensions), + ("href", AttributeId::Href), + ("baseFrequency", AttributeId::BaseFrequency), + ("stroke-dashoffset", AttributeId::StrokeDashoffset), + ("text-decoration-stroke", AttributeId::TextDecorationStroke), + ("display", AttributeId::Display), + ("amplitude", AttributeId::Amplitude), + ("mask-size", AttributeId::MaskSize), + ("font-variant-ligatures", AttributeId::FontVariantLigatures), + ("in2", AttributeId::In2), ("maskUnits", AttributeId::MaskUnits), - ("pointsAtY", AttributeId::PointsAtY), - ("paint-order", AttributeId::PaintOrder), - ("text-decoration-line", AttributeId::TextDecorationLine), - ("preserveAlpha", AttributeId::PreserveAlpha), - ("shape-rendering", AttributeId::ShapeRendering), + ("k4", AttributeId::K4), + ("shape-padding", AttributeId::ShapePadding), + ("r", AttributeId::R), ("text-underline-position", AttributeId::TextUnderlinePosition), + ("font-variant-east-asian", AttributeId::FontVariantEastAsian), + ("z", AttributeId::Z), + ("text-decoration-color", AttributeId::TextDecorationColor), + ("intercept", AttributeId::Intercept), + ("side", AttributeId::Side), + ("x2", AttributeId::X2), + ("mask-position", AttributeId::MaskPosition), + ("pointsAtX", AttributeId::PointsAtX), + ("patternUnits", AttributeId::PatternUnits), + ("result", AttributeId::Result), + ("baseline-shift", AttributeId::BaselineShift), + ("stop-color", AttributeId::StopColor), + ("k3", AttributeId::K3), ("stroke-dasharray", AttributeId::StrokeDasharray), - ("ry", AttributeId::Ry), - ("preserveAspectRatio", AttributeId::PreserveAspectRatio), - ("markerWidth", AttributeId::MarkerWidth), - ("letter-spacing", AttributeId::LetterSpacing), - ("font-variant-position", AttributeId::FontVariantPosition), - ("y", AttributeId::Y), - ("style", AttributeId::Style), - ("requiredFeatures", AttributeId::RequiredFeatures), - ("text-align", AttributeId::TextAlign), - ("divisor", AttributeId::Divisor), - ("offset", AttributeId::Offset), - ("overflow", AttributeId::Overflow), - ("font-kerning", AttributeId::FontKerning), - ("slope", AttributeId::Slope), - ("marker-mid", AttributeId::MarkerMid), - ("mode", AttributeId::Mode), - ("x", AttributeId::X), - ("elevation", AttributeId::Elevation), - ("k1", AttributeId::K1), - ("startOffset", AttributeId::StartOffset), - ("clip", AttributeId::Clip), - ("surfaceScale", AttributeId::SurfaceScale), - ("points", AttributeId::Points), + ("y1", AttributeId::Y1), ("targetX", AttributeId::TargetX), - ("text-decoration", AttributeId::TextDecoration), - ("font-style", AttributeId::FontStyle), + ("stroke-width", AttributeId::StrokeWidth), + ("limitingConeAngle", AttributeId::LimitingConeAngle), + ("id", AttributeId::Id), + ("mask-border-width", AttributeId::MaskBorderWidth), + ("shape-subtract", AttributeId::ShapeSubtract), + ("font-variant", AttributeId::FontVariant), + ("glyph-orientation-vertical", AttributeId::GlyphOrientationVertical), + ("offset", AttributeId::Offset), + ("type", AttributeId::Type), + ("numOctaves", AttributeId::NumOctaves), + ("font-stretch", AttributeId::FontStretch), + ("mask-clip", AttributeId::MaskClip), + ("clipPathUnits", AttributeId::ClipPathUnits), + ("path", AttributeId::Path), ("seed", AttributeId::Seed), - ("stop-opacity", AttributeId::StopOpacity), - ("values", AttributeId::Values), - ("stdDeviation", AttributeId::StdDeviation), + ("font-variant-position", AttributeId::FontVariantPosition), + ("rotate", AttributeId::Rotate), + ("text-overflow", AttributeId::TextOverflow), + ("mask-border-repeat", AttributeId::MaskBorderRepeat), + ("stroke-linejoin", AttributeId::StrokeLinejoin), + ("mask-mode", AttributeId::MaskMode), + ("specularConstant", AttributeId::SpecularConstant), ("spreadMethod", AttributeId::SpreadMethod), - ("flood-color", AttributeId::FloodColor), - ("color", AttributeId::Color), - ("shape-inside", AttributeId::ShapeInside), - ("marker-start", AttributeId::MarkerStart), - ("text-decoration-stroke", AttributeId::TextDecorationStroke), - ("patternContentUnits", AttributeId::PatternContentUnits), - ("word-spacing", AttributeId::WordSpacing), - ("orient", AttributeId::Orient), - ("in2", AttributeId::In2), - ("unicode-range", AttributeId::UnicodeRange), - ("opacity", AttributeId::Opacity), - ("baseFrequency", AttributeId::BaseFrequency), - ("path", AttributeId::Path), - ("markerHeight", AttributeId::MarkerHeight), - ("pathLength", AttributeId::PathLength), - ("r", AttributeId::R), - ("writing-mode", AttributeId::WritingMode), - ("shape-margin", AttributeId::ShapeMargin), - ("viewBox", AttributeId::ViewBox), + ("letter-spacing", AttributeId::LetterSpacing), ("font-family", AttributeId::FontFamily), - ("filter", AttributeId::Filter), - ("markerUnits", AttributeId::MarkerUnits), - ("type", AttributeId::Type), - ("baseline-shift", AttributeId::BaselineShift), - ("font-variant-ligatures", AttributeId::FontVariantLigatures), + ("azimuth", AttributeId::Azimuth), + ("refX", AttributeId::RefX), + ("color-rendering", AttributeId::ColorRendering), + ("values", AttributeId::Values), + ("marker-end", AttributeId::MarkerEnd), + ("font-variant-numeric", AttributeId::FontVariantNumeric), + ("markerHeight", AttributeId::MarkerHeight), + ("radius", AttributeId::Radius), + ("width", AttributeId::Width), + ("text-align-last", AttributeId::TextAlignLast), + ("preserveAspectRatio", AttributeId::PreserveAspectRatio), + ("patternContentUnits", AttributeId::PatternContentUnits), + ("k1", AttributeId::K1), + ("paint-order", AttributeId::PaintOrder), + ("d", AttributeId::D), + ("mask-border-slice", AttributeId::MaskBorderSlice), + ("dx", AttributeId::Dx), + ("text-align", AttributeId::TextAlign), ], }; diff --git a/src/mask.rs b/src/mask.rs index fd2431ee6..080cc2c53 100644 --- a/src/mask.rs +++ b/src/mask.rs @@ -60,7 +60,12 @@ pub fn mask( self::mask(tree, mask, bbox.to_path_bbox(), canvas); } - let mask = tiny_skia::Mask::from_pixmap(mask_pixmap.as_ref(), tiny_skia::MaskType::Luminosity); + let mask_type = match mask.kind { + usvg::MaskType::Luminance => tiny_skia::MaskType::Luminance, + usvg::MaskType::Alpha => tiny_skia::MaskType::Alpha, + }; + + let mask = tiny_skia::Mask::from_pixmap(mask_pixmap.as_ref(), mask_type); canvas.pixmap.apply_mask(&mask); Some(()) diff --git a/tests/integration/render.rs b/tests/integration/render.rs index a3294fa7a..55f79326b 100644 --- a/tests/integration/render.rs +++ b/tests/integration/render.rs @@ -1139,6 +1139,11 @@ use crate::render; #[test] fn e_mask_029() { assert_eq!(render("e-mask-029"), 0); } #[test] fn e_mask_030() { assert_eq!(render("e-mask-030"), 0); } #[test] fn e_mask_031() { assert_eq!(render("e-mask-031"), 0); } +#[test] fn e_mask_032() { assert_eq!(render("e-mask-032"), 0); } +#[test] fn e_mask_033() { assert_eq!(render("e-mask-033"), 0); } +#[test] fn e_mask_034() { assert_eq!(render("e-mask-034"), 0); } +#[test] fn e_mask_035() { assert_eq!(render("e-mask-035"), 0); } +#[test] fn e_mask_036() { assert_eq!(render("e-mask-036"), 0); } #[test] fn e_path_001() { assert_eq!(render("e-path-001"), 0); } #[test] fn e_path_002() { assert_eq!(render("e-path-002"), 0); } #[test] fn e_path_003() { assert_eq!(render("e-path-003"), 0); } diff --git a/tests/png/e-mask-032.png b/tests/png/e-mask-032.png new file mode 100644 index 0000000000000000000000000000000000000000..30d7e470788c87507c0225bb22f0a46a58c73413 GIT binary patch literal 1512 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxV1_q|50X`wFKrX|728IR(hE-s4 zCYYQACi}o-H<;`MlO13Zs0FCL4T)?8vms;)n2k&}GcW)VPzxs61Qy36fr>E&(L^B5 z0FsRi4E10V&H!pBh7Hk0q++0fKm<{YNiu+?fF!0GOvP{!AOnJcE`hV*46K4cS*+q% z1?jIC?)bsOU|>kwzZ&QqhHoW7e!&ckOw25-Z0sDIT--doeEb3eLc$`VV&W2#QqnTA za`Fm_$||aA>Kd9_+B&*=`UZwZCZ=ZQ7M51lHnw*5_6`n?PR_1w?jD|A-afv5{sDnO z!69Mc5s^{RF|l#+35iL`DXHlhnOWI6xq12d1qFpg#U-U>6_r)hHMMp14UJ9BEv;?s zon75My?y-?CQh0>W$Lu)GiJ@6Gk4zn1q&A~Ub1xA@)avruUWfp{f3R3HgDOwZTpU$ zyY}qexBtMwLx+zXJ$C%W$y2A#o;!cx;-$-1u3o!-o;%TfB5+6^OvvRzW@07>-V3(|K=@xdl#7h_jtNEhE&{ods&h1kb^+$!|T4XS^Sr@ zCtSRuTJkdvwPOrD?yv3PW}v7Z0xz#OL^}?w_BWIIuRQZ4qoDq zXkz6Cv01=m0!)0~`ds@XkcJi1tw>L z$w^?c4@`E0$xblY0VaW3fa=?j$W|~LLbia}KoY`e26J(dO<-BFNr+2;WFrtm!QUJ8 ze}PQbk|4ie21X`k7FITP4o)s^9$r3v0RbUl5m7O52}vnw8CiJ+MI~hwRW)@DO)YI5 zT|IpRLnC7oQ!{f5ODk&|TRVGu2M5Reg3J4_6fiI_v3j~VhE&{odwC=8Z3BU}i~l=x z7IgB6-Kt;MB7Qn3aS6wbC8vHnoL;Uie?&$s#=X35qmHT#2Us-eP;`NI8 ztK?#@ey=wAwfV$WiPyh+YrgATH!fRs*>kN|`J_5O`}(Ud-<{u*rK){?(ffthjMqnf z&wd`h>6dl@)o3bvco8|*gjX&@H@6+_5js_~yUIKVI2q;Fw2Rl5E` tJ`pt{P=n-JMedS`pvZhSWA@7*yume}Ebp~v0Mj!AgQu&X%Q~loCIAhS6_@}3 literal 0 HcmV?d00001 diff --git a/tests/png/e-mask-034.png b/tests/png/e-mask-034.png new file mode 100644 index 0000000000000000000000000000000000000000..27160c737ba05e3fb958c3c3087f1e59a78bbdab GIT binary patch literal 877 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxVAayCgC&U#@XkcJi1tw>L z$w^?c4@`E0$xblY0VaW3fa=?j$W|~LLbia}KoY`e26J(dO<-BFNr+2;WFrtm!QUJ8 ze}PQbk|4ie21X`k7FITP4o)s^9$r3v0RbUl5m7O52}vnw8CiJ+MI~hwRW)@DO)YI5 zT|IpRLnC7oQ!{f5ODk&|TRVGu2M5Reg3J4_6fiI_v3j~VhE&{odwC=8Z3BU}i~l=x z7IgB6-Kt;MB7Qn3aS6wbC8vHnoL;Uie?&$s#=X35qmHT#2Us-eP;`NI8 ztK?#@ey=wAwfV$WiPyh+YrgATH!fRs*>kN|`J_5O`}(Ud-<{u*rK){?(ffthjMqnf z&wd`h>6dl@)o3bvco8|*gjX&@H@6+_5js_~yUIKVI2q;Fw2Rl5E` tJ`pt{P=n-JMedS`pvZhSWA@7*yume}Ebp~v0Mj!AgQu&X%Q~loCIAhS6_@}3 literal 0 HcmV?d00001 diff --git a/tests/png/e-mask-035.png b/tests/png/e-mask-035.png new file mode 100644 index 0000000000000000000000000000000000000000..dc207da32b030be464dc62af2cbd53839dc92051 GIT binary patch literal 1269 zcmeAS@N?(olHy`uVBq!ia0y~yVAKI&4rZW;-{LxV1_ma>0G|+7AeZ4k149EC&4e-f z7#O<2>`n%T4lo0#45+3JjDU<*FoNi6f$3^yU;rYBAe_;}zyL%*K{x}MjV8zdRtY5Q z85kPD2*?1c2eRP|AR8hAVIZr-uLYtDNJ1D4V1Q;CL<&<7C=PJ|kO4txTucRUm2d`q zw7{*S1%rX%^si%v3=9mrN`m}?85o&ZSlKu@xp{c`1q6hIMa9G=rDSB~6cm+J)YLV! zv~~6L4UJ4p%`GggZS3sr9UPpTUEMr9y?lKA0|J9X!onk?qGRI{5|dI=(=)QNbMo@@ z3kr*hOUo)Mt7~fO8=9J1+S)t2dV2dNOq@Jr>hu}2X3w2Bf8nAfOP8%!xq8jI^&2*A z-nwo3&Ru)7+* zzJ34s>-XP(i%#W~0Q196PZ!6Kid%0lY~(#;AmDJZc)?eli@paLPHu_QiwN-$v1AO` z8~^{6YkcS$cRtb6om-c4z2#rSBkC2gA>m*X>udFcO{x&4H&}ps8c3L1Ob0?nfY}in zSb!oxWt?F0pwJpg5bt19X)k}4zwX;5PrvNgVqenzz51vSM1l-62eHQEjHCn(x<_gi r!C|#j=600F?Gv4$K9aWGEAKN3=t%`tCFH&VCPfBMS3j3^P6!PHfuRkIfa+Tr7`nhDklg}S2_%6C$ZZFcKt?lIF^~kJ zCa_{42^5ErKoj6>pa@Vegair#*$^pYL7*%U0F44l0YN(uBok~tEX>ZWMph&YG!U>VP$1)V{2z;Z|~sX;NE-R?>*pU37!(u|5*ijB5g8R76B8R37oU)rl$4y3nwFNHk&&5|m7SBDmzSSk zAi2I_^SU($yENp%EJr4mPpAHg00|2D7-Qf%x2FIuJ4f%#PT=0u%u%$71mYo0jZH)M_zdc*$ z#OHkul9%y5HDk-=mH#Bq-kp+cWUuNeefetey|_-&?Iqj6^wRkEq*8h8{7F uxyByCzx%iNlDiAb)`%~gwRE3>?)f7+YkJ>rT(Jn07(HG6T-G@yGywpzpDP6b literal 0 HcmV?d00001 diff --git a/tests/svg/e-mask-032.svg b/tests/svg/e-mask-032.svg new file mode 100644 index 000000000..1729b9f60 --- /dev/null +++ b/tests/svg/e-mask-032.svg @@ -0,0 +1,15 @@ + + mask-type=alpha (SVG 2) + + + + + + + + + + + + + diff --git a/tests/svg/e-mask-033.svg b/tests/svg/e-mask-033.svg new file mode 100644 index 000000000..d9707b24a --- /dev/null +++ b/tests/svg/e-mask-033.svg @@ -0,0 +1,15 @@ + + mask-type=luminance (SVG 2) + + + + + + + + + + + + + diff --git a/tests/svg/e-mask-034.svg b/tests/svg/e-mask-034.svg new file mode 100644 index 000000000..27854da42 --- /dev/null +++ b/tests/svg/e-mask-034.svg @@ -0,0 +1,15 @@ + + mask-type=invalid (SVG 2) + + + + + + + + + + + + + diff --git a/tests/svg/e-mask-035.svg b/tests/svg/e-mask-035.svg new file mode 100644 index 000000000..96975f077 --- /dev/null +++ b/tests/svg/e-mask-035.svg @@ -0,0 +1,22 @@ + + `mask` on self with mask-type=alpha (SVG 2) + + + + + + + + + + + + + + + + + + + + diff --git a/tests/svg/e-mask-036.svg b/tests/svg/e-mask-036.svg new file mode 100644 index 000000000..ae87befd8 --- /dev/null +++ b/tests/svg/e-mask-036.svg @@ -0,0 +1,22 @@ + + `mask` on self with mixed mask-type (SVG 2) + + + + + + + + + + + + + + + + + + + + diff --git a/usvg-parser/src/mask.rs b/usvg-parser/src/mask.rs index e55939330..592c8ae7d 100644 --- a/usvg-parser/src/mask.rs +++ b/usvg-parser/src/mask.rs @@ -6,7 +6,7 @@ use std::rc::Rc; use rosvgtree::{self, AttributeId as AId, ElementId as EId}; use svgtypes::{Length, LengthUnit as Unit}; -use usvg_tree::{Group, Mask, Node, NodeKind, Rect, Units}; +use usvg_tree::{Group, Mask, MaskType, Node, NodeKind, Rect, Units}; use crate::rosvgtree_ext::SvgNodeExt2; use crate::{converter, OptionLog, SvgNodeExt}; @@ -53,11 +53,18 @@ pub(crate) fn convert( } } + let kind = if node.attribute(AId::MaskType) == Some("alpha") { + MaskType::Alpha + } else { + MaskType::Luminance + }; + let mut mask = Mask { id: node.element_id().to_string(), units, content_units, rect, + kind, mask, root: Node::new(NodeKind::Group(Group::default())), }; diff --git a/usvg-tree/src/lib.rs b/usvg-tree/src/lib.rs index 5e6742f3a..cb194d711 100644 --- a/usvg-tree/src/lib.rs +++ b/usvg-tree/src/lib.rs @@ -655,6 +655,21 @@ impl Default for ClipPath { } } +/// A mask type. +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum MaskType { + /// Indicates that the luminance values of the mask should be used. + Luminance, + /// Indicates that the alpha values of the mask should be used. + Alpha, +} + +impl Default for MaskType { + fn default() -> Self { + Self::Luminance + } +} + /// A mask element. /// /// `mask` element in SVG. @@ -681,6 +696,11 @@ pub struct Mask { /// `x`, `y`, `width` and `height` in SVG. pub rect: Rect, + /// Mask type. + /// + /// `mask-type` in SVG. + pub kind: MaskType, + /// Additional mask. /// /// `mask` in SVG. diff --git a/usvg/docs/spec.adoc b/usvg/docs/spec.adoc index 9fe39f3c0..7f1b0f76d 100644 --- a/usvg/docs/spec.adoc +++ b/usvg/docs/spec.adoc @@ -208,6 +208,8 @@ Doesn't have a `xlink:href` attribute because all attributes and children will b * `y` = < >> * `width` = < >> * `height` = < >> +* `mask-type` = `alpha`? + + Default: luminance * `maskUnits` = `userSpaceOnUse`? + Default: objectBoundingBox * `maskContentUnits` = `objectBoundingBox`? + diff --git a/usvg/src/writer.rs b/usvg/src/writer.rs index 26d313a52..e195bd8bd 100644 --- a/usvg/src/writer.rs +++ b/usvg/src/writer.rs @@ -526,6 +526,9 @@ fn conv_defs(tree: &Tree, opt: &XmlOptions, xml: &mut XmlWriter) { for mask in masks { xml.start_svg_element(EId::Mask); xml.write_id_attribute(&mask.id, opt); + if mask.kind == MaskType::Alpha { + xml.write_svg_attribute(AId::MaskType, "alpha"); + } xml.write_units(AId::MaskUnits, mask.units, Units::ObjectBoundingBox); xml.write_units( AId::MaskContentUnits,