Skip to content

Comments

Implement CSS-style Blend algebra for SVG backend#223

Open
arnavsharma990 wants to merge 2 commits intocreativescala:mainfrom
arnavsharma990:feature/192-svg-blend
Open

Implement CSS-style Blend algebra for SVG backend#223
arnavsharma990 wants to merge 2 commits intocreativescala:mainfrom
arnavsharma990:feature/192-svg-blend

Conversation

@arnavsharma990
Copy link
Contributor

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.

- Use mix-blend-mode for backdrop blending
- Align semantics with Canvas and Java2D
- Remove feBlend-based approach
- Add tests for blend modes
Copilot AI review requested due to automatic review settings February 20, 2026 12:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

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 BlendModule implementing screen, burn, dodge, lighten, and sourceOver via mix-blend-mode.
  • Wired BlendModule / Blend into the shared, JVM, JS, and test SVG algebra stacks.
  • Added an SVG rendering test suite that asserts blend modes produce the expected mix-blend-mode CSS.

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",
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
svgAttrs.style := s"mix-blend-mode: $mode",
svgAttrs.style := s"isolation: isolate; mix-blend-mode: $mode",

Copilot uses AI. Check for mistakes.
import b.{svgAttrs, svgTags}

val blendedTag = svgTags.g(
svgAttrs.style := s"mix-blend-mode: $mode",
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
svgAttrs.style := s"mix-blend-mode: $mode",
svgAttrs.style := s"mix-blend-mode: $mode;",

Copilot uses AI. Check for mistakes.
@arnavsharma990
Copy link
Contributor Author

arnavsharma990 commented Feb 20, 2026

Hi @noelwelsh , I’ve looked into the CI failure.

The MiMa check is failing because I added new abstract methods to Blend, which breaks binary compatibility with 0.33.0.

To address this, I can either:

  • Provide default implementations in Blend to preserve binary compatibility, or
  • Move these methods into an SVG specific trait if they’re intended to be backend specific.

Please let me know which direction you’d prefer.

@noelwelsh
Copy link
Contributor

Just increase the value of tlBaseVersion in build.sbt.

@arnavsharma990
Copy link
Contributor Author

Thanks! I’ve increased the tlBaseVersion in build.sbt

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement blending for SVG

2 participants