Repository navigation
feat(layers): blend a layer with what is beneath it - #900
Merged
Merged
Conversation
Adds Layer.blendMode, a Flutter BlendMode the layer is drawn onto the image and the layers before it with: multiply to tint them with a colored layer, screen to add only the light of a layer shot against black, and so on. The canvas draws it through LayerBlendModeBox, a BackdropFilter whose filter clears the backdrop and whose blendMode composites the child alone onto what is beneath. A save layer with a blend mode cannot do that over a video Texture, which is a compositing layer of its own. The box sits outside the layer's opacity and timeline fades, so it blends with the canvas rather than inside their offscreen layers; the selection overlay is drawn in an overlay of its own and stays unblended. The mode survives copies, text edits, history steps and import/export (minified key bm), and a later step that removes it is recorded too. The generated image honors it. captureAsPng leaves it out: the captured image is the layer's own content, which a renderer that composites the layers itself, such as a video exporter, draws with the mode. A blended drawing is neither merged with other drawings nor raster-cached, since both draw their members over each other.
1 of 7 tasks
A censor area blurs or pixelates its backdrop, and inside a LayerBlendModeBox that backdrop is cleared, so a censor layer with a blend mode hid nothing. LayerWidget now leaves censor areas unblended. Documents that modes which change the destination where the layer is transparent, such as dstIn, act across the whole canvas, and shortens the changelog entry.
hm21
marked this pull request as ready for review
October 22, 2026 10:05
saif-ellafi
added a commit
to saif-ellafi/pro_image_editor
that referenced
this pull request
Oct 23, 2026
Resolve conflicts with Layer.blendMode (hm21#900): keep both CHANGELOG entries and copy blendMode in _keepTextLayerPlacement. Inline edits also carry blendMode in buildResult, with a test that typing on a layer keeps its blend mode. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 of 7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Problem. A layer can only be drawn over the image and the layers before it. Opacity makes it see-through, but it never interacts with what is beneath: a host cannot tint the picture with a colored shape, add only the light of a flame or a light leak shot against black, or overlay a texture, which are standard tools in other editors.
Approach.
Layer.blendModeis a FlutterBlendModethe layer is drawn onto what is beneath it with;BlendMode.srcOver(the default) is the old behaviour.LayerBlendModeBox. The obvious way, asaveLayerwith a blend-mode paint, cannot reach a videoTexture, which is a compositing layer of its own, so a host previewing a video under its layers would see the blend only over images. ABackdropFilteris the one compositing layer that composites its content onto the backdrop with a blend mode; its filter here clears the backdrop, so the child alone is blended. Verified pixel for pixel against the W3C formulas on Skia and Impeller.OverlayPortal, so it is not blended.bm), and removing it in a later history step is recorded too (toMapFromReferencewritessrcOver).dstIn, acts across the whole canvas, as asaveLayerwould; the docs say so.captureAsPngleaves it out: the captured image is the layer's own content, which a renderer that composites the layers itself (for examplepro_video_editor, whoseLayerBlendModemaps onto these modes) draws with the mode.Not changed. Layers without a blend mode paint, capture and export exactly as before. A blended drawing is neither merged with other drawings nor raster-cached, since both draw their members over each other rather than blended onto the canvas.
CHANGELOG 14.16.0.
Related Issue: Closes #none; requested in divinevideo/divine-mobile#10256.
Verification
copyWithand equality; copies and text edits keep the mode; import/export across history steps, minified and not; merge and raster-cache exclusion; a censor layer stays unblended;LayerBlendModeBoxpixels for multiply and for a child faded inside it; the editor places the box outside the layer's opacity; the generated image is blended (multiply comes out at 48/40/24 over 0x8040C0) whilecaptureAsPngstays unblended.flutter test: 1074 passed on Flutter 3.47.2 and 1072 on 3.44.0 before the generated-image test was added;flutter analyzeclean on both;dart formatclean.Type of Change