Skip to content

Commit 19c4a4c

Browse files
committed
Blend Modes #6
1 parent b9d28de commit 19c4a4c

File tree

4 files changed

+66
-90
lines changed

4 files changed

+66
-90
lines changed

lib/src/transformers/node_transformers/passive_rectangle_transformer.dart

+61-74
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,44 @@ class PassiveRectangleWidget extends StatelessWidget {
125125
}
126126
}
127127

128+
Widget child = Stack(
129+
clipBehavior: Clip.none,
130+
alignment:
131+
stackAlignment.flutterAlignment ?? AlignmentDirectional.topStart,
132+
children: [
133+
...buildFills(
134+
node,
135+
useInk: false,
136+
obscureImages: settings.obscureImages,
137+
settings: settings,
138+
scopedValues: scopedValues,
139+
),
140+
...buildStrokes(node, scopedValues),
141+
...wrapWithInkWell(
142+
context,
143+
node,
144+
wrapWithPaddingAndScroll(
145+
node,
146+
[
147+
...children,
148+
if (portalWidget != null) portalWidget,
149+
],
150+
stackAlignment: stackAlignment,
151+
applyPadding: applyPadding,
152+
),
153+
),
154+
],
155+
);
156+
157+
bool hasComplexRendering = node is GeometryMixin &&
158+
(node as GeometryMixin).fills.any(
159+
(PaintModel fill) => fill.blendMode != BlendModeC.srcOver,
160+
);
161+
162+
if (hasComplexRendering) {
163+
child = BlendMask(child: child);
164+
}
165+
128166
Widget data = Container(
129167
key: ValueKey('Rectangle Transformer of ${node.debugLabel}'),
130168
clipBehavior: getClipBehavior(node),
@@ -134,34 +172,7 @@ class PassiveRectangleWidget extends StatelessWidget {
134172
boxShadow: retrieveBoxShadow(node, scopedValues),
135173
borderRadius: getBorderRadius(node),
136174
),
137-
child: Stack(
138-
clipBehavior: Clip.none,
139-
alignment:
140-
stackAlignment.flutterAlignment ?? AlignmentDirectional.topStart,
141-
children: [
142-
...buildFills(
143-
node,
144-
useInk: false,
145-
obscureImages: settings.obscureImages,
146-
settings: settings,
147-
scopedValues: scopedValues,
148-
),
149-
...buildStrokes(node, scopedValues),
150-
...wrapWithInkWell(
151-
context,
152-
node,
153-
wrapWithPaddingAndScroll(
154-
node,
155-
[
156-
...children,
157-
if (portalWidget != null) portalWidget,
158-
],
159-
stackAlignment: stackAlignment,
160-
applyPadding: applyPadding,
161-
),
162-
),
163-
],
164-
),
175+
child: child,
165176
);
166177

167178
return data;
@@ -599,32 +610,29 @@ List<Widget> buildFills(
599610
);
600611

601612
if (lastBlendTree.isNotEmpty) {
602-
fill = Stack(
603-
fit: StackFit.expand,
604-
children: [
605-
fill,
606-
for (final paint in lastBlendTree.reversed)
607-
if (paint.visible)
608-
Positioned.fill(
609-
child: BlendMask(
610-
key: ObjectKey(paint.blendMode),
611-
blendMode: paint.blendMode.flutterBlendMode,
612-
child: buildFill(
613-
node,
614-
index: node.fills.indexOf(paint),
615-
imageBytes: imageBytes,
616-
imageOpacity: imageOpacity,
617-
imageRotation: imageRotation,
618-
imageFillBuilder: imageFillBuilder,
619-
useInk: useInk,
620-
obscureImages: obscureImages,
621-
settings: settings,
622-
scopedValues: scopedValues,
623-
),
624-
),
613+
for (final paint in lastBlendTree) {
614+
if (!paint.visible) continue;
615+
raster.add(
616+
Positioned.fill(
617+
child: BlendMask(
618+
key: ObjectKey(paint.blendMode),
619+
blendMode: paint.blendMode.flutterBlendMode,
620+
child: buildFill(
621+
node,
622+
index: node.fills.indexOf(paint),
623+
imageBytes: imageBytes,
624+
imageOpacity: imageOpacity,
625+
imageRotation: imageRotation,
626+
imageFillBuilder: imageFillBuilder,
627+
useInk: useInk,
628+
obscureImages: obscureImages,
629+
settings: settings,
630+
scopedValues: scopedValues,
625631
),
626-
],
627-
);
632+
),
633+
),
634+
);
635+
}
628636
}
629637

630638
lastBlendTree.clear();
@@ -766,28 +774,7 @@ Widget buildFill(
766774
child: child,
767775
);
768776
}
769-
770-
if (node.isHorizontalWrap || node.isVerticalWrap) {
771-
// if the node is shrink-wrapping on one or both axes, then we
772-
// need to wrap the image in a Positioned widget so that it
773-
// doesn't expand to the size of the parent.
774-
return child;
775-
}
776-
777777
return child;
778-
779-
// if (node.childrenOrEmpty.isEmpty) {
780-
// // If we don't do this then shrink-wrapping images will not work.
781-
// // They will expand to the size of the parent.
782-
// return child;
783-
// } else {
784-
// // This was Positioned.fill before. If this is breaking something,
785-
// // then we need to figure out a way to make it work with
786-
// // Positioned.fill and Positioned because Positioned.fill breaks
787-
// // shrink-wrapping.
788-
// return Positioned(child: child);
789-
// }
790-
791778
case PaintType.emoji:
792779
return const SizedBox.shrink();
793780
}

lib/src/transformers/passive_transformer_manager.dart

-3
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ class PassiveNodeTransformerManager extends WidgetNodeTransformerManager {
7676
Widget widget =
7777
getTransformerByNode(node).buildWidget(node, context, settings);
7878

79-
if (settings.withBlendModes) {
80-
widget = applyWidgetBlendMode(node, widget);
81-
}
8279
if (settings.withOpacity) {
8380
widget = applyWidgetOpacity(node, widget);
8481
}

lib/src/transformers/utils/blend_mask.dart

+5-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class BlendMask extends SingleChildRenderObjectWidget {
3232
///
3333
/// The [blendMode] argument must not be null.
3434
const BlendMask({
35-
required this.blendMode,
35+
this.blendMode = BlendMode.srcOver,
3636
super.key,
3737
super.child,
3838
});
@@ -87,7 +87,10 @@ class RenderBlendMask extends RenderProxyBox {
8787
@override
8888
void paint(PaintingContext context, Offset offset) {
8989
// Complex blend modes can be raster cached incorrectly on the Skia backend.
90-
context.setWillChangeHint();
90+
if (blendMode != BlendMode.srcOver) {
91+
context.setWillChangeHint();
92+
}
93+
9194
context.canvas.saveLayer(offset & size, blender);
9295

9396
super.paint(context, offset);

lib/src/transformers/widget_node_transformer_manager.dart

-11
Original file line numberDiff line numberDiff line change
@@ -67,17 +67,6 @@ abstract class WidgetNodeTransformerManager extends NodeTransformerManager<
6767
);
6868
}
6969

70-
/// Applies a blending mask to the widget, which saves the widget's
71-
/// rendered layer to the canvas, allowing other blend masks to be applied
72-
/// on top of it.
73-
Widget applyWidgetBlendMode(
74-
BaseNode node,
75-
Widget widget,) =>
76-
BlendMask(
77-
blendMode: BlendMode.srcOver,
78-
child: widget,
79-
);
80-
8170
/// Convenience method to handle widget rotation.
8271
///
8372
/// Takes into account margin and padding to figure out the origin of

0 commit comments

Comments
 (0)