Implement CSS-style Blend algebra for SVG backend#223
Implement CSS-style Blend algebra for SVG backend#223arnavsharma990 wants to merge 2 commits intocreativescala:mainfrom
Conversation
- Use mix-blend-mode for backdrop blending - Align semantics with Canvas and Java2D - Remove feBlend-based approach - Add tests for blend modes
There was a problem hiding this comment.
Pull request overview
Implements the doodle.algebra.Blend operations for the SVG backend by emitting CSS mix-blend-mode on a wrapper <g> element, enabling blend-mode portability aligned with Canvas/Java2D-style backdrop blending semantics.
Changes:
- Added a new SVG
BlendModuleimplementingscreen,burn,dodge,lighten, andsourceOverviamix-blend-mode. - Wired
BlendModule/Blendinto the shared, JVM, JS, and test SVG algebra stacks. - Added an SVG rendering test suite that asserts blend modes produce the expected
mix-blend-modeCSS.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| svg/shared/src/main/scala/doodle/svg/algebra/Blend.scala | New SVG implementation of the Blend algebra using mix-blend-mode on a <g> wrapper. |
| svg/shared/src/main/scala/doodle/svg/algebra/BaseAlgebra.scala | Adds BlendModule and Blend to the shared SVG algebra composition. |
| svg/jvm/src/main/scala/doodle/svg/algebra/Algebra.scala | Mixes BlendModule/Blend into the JVM SVG algebra implementation. |
| svg/js/src/main/scala/doodle/svg/algebra/Algebra.scala | Mixes BlendModule/Blend into the JS SVG algebra implementation. |
| svg/shared/src/test/scala/doodle/svg/algebra/TestAlgebra.scala | Enables Blend in the test algebra so pictures can use .screen, .burn, etc. |
| svg/shared/src/test/scala/doodle/svg/BlendSpec.scala | New tests asserting rendered SVG contains the expected mix-blend-mode values. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import b.{svgAttrs, svgTags} | ||
|
|
||
| val blendedTag = svgTags.g( | ||
| svgAttrs.style := s"mix-blend-mode: $mode", |
There was a problem hiding this comment.
mix-blend-mode blends against the element’s backdrop in the surrounding DOM stacking context; without an isolated stacking context on the generated SVG, the rendered output can unintentionally blend with content outside the SVG when embedded in HTML. To match Canvas/backdrop semantics (blend only within the drawing), consider ensuring the root <svg> (or an outer wrapper created by the renderer) sets isolation: isolate (e.g., in Svg.svgTag style) so blending is confined to the SVG.
| svgAttrs.style := s"mix-blend-mode: $mode", | |
| svgAttrs.style := s"isolation: isolate; mix-blend-mode: $mode", |
| import b.{svgAttrs, svgTags} | ||
|
|
||
| val blendedTag = svgTags.g( | ||
| svgAttrs.style := s"mix-blend-mode: $mode", |
There was a problem hiding this comment.
The inline style value is currently emitted as mix-blend-mode: <mode> without a trailing semicolon. The SVG backend’s style strings elsewhere consistently terminate declarations with ; (e.g., Svg.toStyle returns strings like stroke: ...; / fill: ...; in svg/shared/src/main/scala/doodle/svg/algebra/Svg.scala:173-199). Adding ; here would keep formatting consistent and avoid edge cases if additional declarations are appended later.
| svgAttrs.style := s"mix-blend-mode: $mode", | |
| svgAttrs.style := s"mix-blend-mode: $mode;", |
|
Hi @noelwelsh , I’ve looked into the CI failure. The MiMa check is failing because I added new abstract methods to To address this, I can either:
Please let me know which direction you’d prefer. |
|
Just increase the value of |
|
Thanks! I’ve increased the tlBaseVersion in build.sbt |
Implements the Blend algebra for the SVG backend using CSS
mix-blend-mode.Following maintainer clarification, this approach aligns semantics with Canvas and Java2D-style backdrop blending for portability across backends.
BlendModuleto SVG backendmix-blend-modefor blending