Skip to content

Support SVG filters (blur, offset, feMerge) and alpha masks#11909

Draft
edwin-hollen wants to merge 1 commit into
flutter:mainfrom
edwin-hollen:upstream-svg-filters-mask
Draft

Support SVG filters (blur, offset, feMerge) and alpha masks#11909
edwin-hollen wants to merge 1 commit into
flutter:mainfrom
edwin-hollen:upstream-svg-filters-mask

Conversation

@edwin-hollen

@edwin-hollen edwin-hollen commented Jun 15, 2026

Copy link
Copy Markdown

Support SVG filters (blur, offset, feMerge) and alpha masks

This PR introduces support for basic SVG filters and alpha masking to the vector_graphics ecosystem.

Key Features:

  • Added parsing, resolution, and encoding of SVG filters including feGaussianBlur, feOffset, and feMerge in vector_graphics_compiler.
  • Added support for alpha masks (mask-type=alpha).
  • Updated the binary format and vector_graphics_codec to support encoding and decoding paint blurs.
  • Updated vector_graphics to render paint blurs using Flutter's ui.ImageFilter.blur and alpha masks via BlendMode.dstIn.
  • Expanded the compiler's example app with a Filter Gallery showcasing drop shadows, glowing text, and blurred gradients.

Implementation Details:

  • Filter Chaining: Filters are parsed into a directed acyclic graph (DAG) of primitives. The resolver traces these primitives from the filter outputs back to SourceGraphic/SourceAlpha to determine the necessary rendering layers.
  • Multi-layer Filter Resolution: Handles multi-layer filters (e.g. from feMerge) by duplicating the target rendering nodes for each layer in the AST.
  • Text Filter Resolution: Resolves filters at the TextPositionNode level (rather than leaf TextNodes) to maintain correct text chunk alignment and cursor positioning.
  • Spec Compliance:
    • Supports both comma and space-separated stdDeviation values.
    • Defaults omitted stdDeviation attributes to 0.0 (as per SVG spec).
    • Automatically resolves default in attributes for feMergeNodes (falling back to the previous sibling primitive's result or SourceGraphic).
    • Preserves original fill/stroke opacity when applying SourceAlpha filters.
    • Handles self-closing <feMerge /> elements.
  • Robustness & Performance:
    • Added cycle detection during filter tracing to prevent stack overflow on circular filter references.
    • Skips rendering node recreation for filter layers that do not affect the paint (e.g. plain SourceGraphic branches in a merge).

TAG=agy
CONV=27cb188a-9ad9-4434-8918-8ef71bdba17c

@github-actions github-actions Bot added p: vector_graphics triage-engine Should be looked at in engine triage labels Jun 15, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters, specifically blur and offset, and alpha masks across the vector_graphics, vector_graphics_codec, and vector_graphics_compiler packages. It updates the parser to handle , feGaussianBlur, feOffset, and feMerge elements, adds encoding/decoding for paint blur commands, and implements rendering support via ImageFilter.blur. The review feedback highlights several areas for improvement: handling comma-separated values in stdDeviation, defaulting omitted in attributes on feMergeNode, preserving the original element's opacity when applying isSourceAlpha filters, and implementing cycle detection during recursive filter tracing to prevent stack overflows.

Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart Outdated
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch 2 times, most recently from 0453cc0 to 5955e54 Compare June 15, 2026 18:19
@edwin-hollen edwin-hollen marked this pull request as draft June 15, 2026 18:23
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from 5955e54 to 5b44d76 Compare June 15, 2026 18:23
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for SVG filters (specifically Gaussian blur) and alpha masks (mask-type=alpha) across the vector graphics packages, including updates to the codec, compiler, and renderer, along with an interactive gallery example. Feedback on the changes highlights a redundant check in the filter parser, a limitation in parsing filters where feMerge is not the final operation, and incomplete support for multi-layer filters on group nodes (ParentNode).

Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from 5b44d76 to a6f0287 Compare June 15, 2026 18:35
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from a6f0287 to ce01413 Compare June 15, 2026 18:36
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters (specifically Gaussian blur) and alpha masks across the vector graphics packages. Key changes include adding a paint blur command to the codec, parsing filter primitives (feGaussianBlur, feOffset, feMerge) in the compiler, resolving filter layers in the resolver visitor, and applying image filters to paints in the renderer. Additionally, the example app is updated with a filter and mask gallery. The review feedback highlights three areas for improvement: using the ui. prefix for ImageFilter to prevent compilation errors, resolving a transformation mismatch in visitTextPositionNode that could cause layout misalignment, and using ByteData.sublistView instead of asByteData() for safer byte buffer handling.

Comment thread packages/vector_graphics/lib/src/listener.dart
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart
Comment thread packages/vector_graphics/example/lib/main.dart Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for SVG filters (specifically Gaussian blur, offset, and merge) and alpha masks across the vector graphics packages, including the compiler, codec, and runtime renderer. It also updates the example application with a gallery demonstrating these features. The reviewer feedback suggests handling trailing delimiters in stdDeviation parsing to prevent invalidating the filter, and combining chained Gaussian blurs using the square root of the sum of squares rather than linear addition.

Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from ce01413 to 53a75e8 Compare June 15, 2026 18:40

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters, specifically blur and multi-layer filters, and alpha masks (mask-type=alpha) across the vector_graphics package, compiler, and codec. It also adds a filter and mask gallery to the example application along with corresponding tests. Review feedback points out three areas for improvement: handling single-layer filters with offsets at the TextPositionNode level to avoid text positioning bugs, ensuring single-layer filters with isSourceAlpha enabled are not ignored during parsing, and using the ui. prefix for ImageFilter.blur in the listener for import consistency.

Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart
Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
Comment thread packages/vector_graphics/lib/src/listener.dart
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch 2 times, most recently from f4e0eff to 98a6f03 Compare June 15, 2026 18:45
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for SVG filters (such as Gaussian blur and offset) and alpha masks across the vector graphics packages. It updates the compiler to parse and resolve these filters, adds encoding and decoding support in the codec, and implements paint blur rendering in the listener. An issue was identified in the resolver where multi-layer filters on text nodes only process the first layer, ignoring subsequent layers, and a fix was suggested to resolve all layers into a parent node.

Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from 98a6f03 to d02df90 Compare June 15, 2026 18:49
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from d02df90 to f51ca1b Compare June 15, 2026 18:54
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters (specifically Gaussian blur, offsets, and multi-layer merging) and alpha masks across the vector graphics packages. Key changes include codec updates to handle paint blur commands, XML parsing for filter and mask attributes, and resolving these filters into paint properties or layers during compilation. Feedback on these changes points out a missing dart:math import in the parser, opportunities to optimize performance by caching a regular expression and avoiding redundant node recreation when the current filter layer has no visual effect, and a suggestion to refactor duplicated paint-creation logic into a helper method.

Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/src/svg/resolver.dart Outdated

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters (such as blur and offset) and alpha masks across the vector_graphics, vector_graphics_codec, and vector_graphics_compiler packages. It adds the capability to parse, encode, decode, and render these filters and masks, along with corresponding tests and gallery examples. Feedback on the changes suggests defaulting parsedX and parsedY to 0.0 when stdDeviation is omitted on a <feGaussianBlur> element to comply with SVG specifications and avoid breaking the filter reference chain.

Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart Outdated
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from f51ca1b to c525511 Compare June 15, 2026 19:01
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for SVG filters, specifically Gaussian blur and offsets, and alpha masks across the vector_graphics, vector_graphics_codec, and vector_graphics_compiler packages. The compiler is updated to parse and resolve <filter> elements (including feGaussianBlur, feOffset, and feMerge) and mask-type="alpha" attributes. The binary codec is extended to encode and decode paint blur commands, and the Flutter listener is updated to apply ui.ImageFilter.blur to paints. Unit, end-to-end, and listener tests are added, and the example app is updated with a gallery demonstrating these features. There are no review comments, and I have no feedback to provide.

@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from c525511 to b5a7483 Compare June 15, 2026 19:07
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters (including blur, offset, and multi-layer merging) and alpha masks across the vector graphics compiler, codec, and listener packages, along with corresponding tests and example gallery updates. The review feedback highlights a potential parser state corruption issue when handling self-closing feMerge elements, as well as an issue where directional blurs with only one non-null axis are ignored during instruction encoding.

Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
Comment thread packages/vector_graphics_compiler/lib/vector_graphics_compiler.dart Outdated
Comment thread packages/vector_graphics_compiler/lib/vector_graphics_compiler.dart Outdated
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from b5a7483 to 32d9ccd Compare June 15, 2026 19:13
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters (specifically Gaussian blur via , offsets via , and merging via ) and alpha masks (mask-type="alpha") across the vector_graphics, vector_graphics_codec, and vector_graphics_compiler packages. The compiler is updated to parse, resolve, and encode these filter and mask attributes into the binary format. The codec and listener are updated to decode and apply the blur filter using Flutter's ui.ImageFilter.blur and handle alpha masking with BlendMode.dstIn. Additionally, the example application is expanded with a gallery demonstrating these new capabilities, and comprehensive unit and end-to-end tests are added. There are no review comments, so no further feedback is provided.

@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from 32d9ccd to 8b1e32e Compare June 15, 2026 20:55
@edwin-hollen edwin-hollen changed the title Support generic SVG multi-layer filters (feMerge) Support SVG filters (blur, offset, feMerge) and alpha masks Jun 15, 2026
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch 4 times, most recently from 4388215 to 230c537 Compare June 15, 2026 21:04
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces support for SVG filters (including blur, offset, and feMerge) and mask-type=alpha across the vector_graphics, vector_graphics_codec, and vector_graphics_compiler packages. It adds the ability to encode, decode, and compile paint blur commands, updates the resolving visitor to handle filter layers, and includes an example gallery showcasing these effects alongside comprehensive tests. Feedback on the changes suggests removing the redundant prefixed import of dart:ui and referencing ImageFilter.blur directly.

Comment thread packages/vector_graphics/lib/src/listener.dart Outdated
Comment thread packages/vector_graphics/lib/src/listener.dart
This PR introduces support for basic SVG filters and alpha masking to the vector_graphics ecosystem.

Key Features:
* Added parsing, resolution, and encoding of SVG filters including `feGaussianBlur`, `feOffset`, and `feMerge` in `vector_graphics_compiler`.
* Added support for alpha masks (`mask-type=alpha`).
* Updated the binary format and `vector_graphics_codec` to support encoding and decoding paint blurs.
* Updated `vector_graphics` to render paint blurs using Flutter's `ui.ImageFilter.blur` and alpha masks via `BlendMode.dstIn`.
* Expanded the compiler's example app with a Filter Gallery showcasing drop shadows, glowing text, and blurred gradients.

Implementation Details:
* **Filter Chaining**: Filters are parsed into a directed acyclic graph (DAG) of primitives. The resolver traces these primitives from the filter outputs back to `SourceGraphic`/`SourceAlpha` to determine the necessary rendering layers.
* **Multi-layer Filter Resolution**: Handles multi-layer filters (e.g. from `feMerge`) by duplicating the target rendering nodes for each layer in the AST.
* **Text Filter Resolution**: Resolves filters at the `TextPositionNode` level (rather than leaf `TextNode`s) to maintain correct text chunk alignment and cursor positioning.
* **Spec Compliance**:
  * Supports both comma and space-separated `stdDeviation` values.
  * Defaults omitted `stdDeviation` attributes to `0.0` (as per SVG spec).
  * Automatically resolves default `in` attributes for `feMergeNode`s (falling back to the previous sibling primitive's result or `SourceGraphic`).
  * Preserves original fill/stroke opacity when applying `SourceAlpha` filters.
  * Handles self-closing `<feMerge />` elements.
* **Robustness & Performance**:
  * Added cycle detection during filter tracing to prevent stack overflow on circular filter references.
  * Skips rendering node recreation for filter layers that do not affect the paint (e.g. plain `SourceGraphic` branches in a merge).

TAG=agy
CONV=27cb188a-9ad9-4434-8918-8ef71bdba17c
@edwin-hollen edwin-hollen force-pushed the upstream-svg-filters-mask branch from 230c537 to 260a3a8 Compare June 15, 2026 21:18
@edwin-hollen

Copy link
Copy Markdown
Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for SVG filters (such as blur, offset, and feMerge) and alpha masks (mask-type=alpha) across the vector_graphics, vector_graphics_codec, and vector_graphics_compiler packages. The changes include parsing, resolving, and encoding/decoding these new attributes, as well as updating tests and the example application. Feedback identifies two potential compilation issues: ImageFilter.blur in listener.dart is missing the ui. prefix, and math.sqrt is used in parser.dart without importing dart:math.

Comment thread packages/vector_graphics/lib/src/listener.dart
Comment thread packages/vector_graphics_compiler/lib/src/svg/parser.dart
@edwin-hollen edwin-hollen marked this pull request as ready for review June 15, 2026 21:37

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for SVG filters (including blur, offset, and merge primitives) and alpha masks (mask-type="alpha") across the vector_graphics, vector_graphics_codec, and vector_graphics_compiler packages. The changes include implementing filter parsing, resolving layers in the compiler, encoding and decoding paint blur commands in the codec, and applying image blurs during rendering. Additionally, the example application is updated with a gallery demonstrating these effects, and comprehensive tests are added. There are no review comments to evaluate, and no further feedback is provided.

@stuartmorgan-g

Copy link
Copy Markdown
Collaborator

Thanks for the contribution!

In the future, please do not delete the checklist that is in the PR template; it is there for a reason. This PR is missing required elements described in the checklist, which need to be addressed before it moves forward with review.

I am marking the PR as a Draft. Please re-add and complete the checklist, updating the PR as appropriate, and when that’s complete please feel free to mark the PR as ready for review.

@stuartmorgan-g stuartmorgan-g marked this pull request as draft June 16, 2026 10:08
@stuartmorgan-g

Copy link
Copy Markdown
Collaborator

Also, as an initial note from glancing over the PR: please don't make the example code five times longer just to show this specific feature. The point of the example is to demonstrate how to use the package, not to serve as a comprehensive showcase of SVG features.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

p: vector_graphics triage-engine Should be looked at in engine triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants