diff --git a/packages/flutter/lib/src/rendering/layer.dart b/packages/flutter/lib/src/rendering/layer.dart index 279ddcbae60..d2e9082fa6c 100644 --- a/packages/flutter/lib/src/rendering/layer.dart +++ b/packages/flutter/lib/src/rendering/layer.dart @@ -372,11 +372,7 @@ class TransformLayer extends ContainerLayer { /// A composited layer that makes its children partially transparent class OpacityLayer extends ContainerLayer { - OpacityLayer({ Offset offset: Offset.zero, this.bounds, this.alpha }) : super(offset: offset); - - /// Unused - Rect bounds; - // TODO(abarth): Remove. + OpacityLayer({ Offset offset: Offset.zero, this.alpha }) : super(offset: offset); /// The amount to multiply into the alpha channel /// @@ -386,14 +382,13 @@ class OpacityLayer extends ContainerLayer { void addToScene(ui.SceneBuilder builder, Offset layerOffset) { Offset childOffset = offset + layerOffset; - builder.pushOpacity(alpha, bounds?.shift(childOffset)); + builder.pushOpacity(alpha, null); addChildrenToScene(builder, childOffset); builder.pop(); } void debugDescribeSettings(List settings) { super.debugDescribeSettings(settings); - settings.add('bounds: $bounds'); settings.add('alpha: $alpha'); } } diff --git a/packages/flutter/lib/src/rendering/object.dart b/packages/flutter/lib/src/rendering/object.dart index 6877a087815..fb16aa0ebe7 100644 --- a/packages/flutter/lib/src/rendering/object.dart +++ b/packages/flutter/lib/src/rendering/object.dart @@ -285,31 +285,17 @@ class PaintingContext { } } - static Paint _getPaintForAlpha(int alpha) { - return new Paint() - ..color = new Color.fromARGB(alpha, 0, 0, 0) - ..transferMode = TransferMode.srcOver - ..isAntiAlias = false; - } - /// Push an opacity layer. /// /// This function will call painter synchronously with a painting context that /// will be blended with the given alpha value. - void pushOpacity(bool needsCompositing, Offset offset, Rect bounds, int alpha, PaintingContextCallback painter) { - if (needsCompositing) { - _stopRecordingIfNeeded(); - OpacityLayer opacityLayer = new OpacityLayer(bounds: bounds, alpha: alpha); - _appendLayer(opacityLayer, offset); - PaintingContext childContext = new PaintingContext._(opacityLayer, _paintBounds); - painter(childContext, Offset.zero); - childContext._stopRecordingIfNeeded(); - } else { - // TODO(abarth): pushOpacity should require bounds. - canvas.saveLayer(bounds?.shift(offset), _getPaintForAlpha(alpha)); - painter(this, offset); - canvas.restore(); - } + void pushOpacity(Offset offset, int alpha, PaintingContextCallback painter) { + _stopRecordingIfNeeded(); + OpacityLayer opacityLayer = new OpacityLayer(alpha: alpha); + _appendLayer(opacityLayer, offset); + PaintingContext childContext = new PaintingContext._(opacityLayer, _paintBounds); + painter(childContext, Offset.zero); + childContext._stopRecordingIfNeeded(); } static Paint _getPaintForShaderMask(Rect bounds, @@ -435,7 +421,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { setupParentData(child); super.adoptChild(child); markNeedsLayout(); - _markNeedsCompositingBitsUpdate(); + markNeedsCompositingBitsUpdate(); } /// Called by subclasses when they decide a render object is no longer a child. @@ -451,7 +437,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { child.parentData = null; super.dropChild(child); markNeedsLayout(); - _markNeedsCompositingBitsUpdate(); + markNeedsCompositingBitsUpdate(); } /// Calls visitor for each immediate child of this render object. @@ -854,7 +840,8 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// creates at least one composited layer. For example, videos should return /// true if they use hardware decoders. /// - /// Warning: This getter must not change value over the lifetime of this object. + /// You must call markNeedsCompositingBitsUpdate() if the value of this + /// getter changes. bool get alwaysNeedsCompositing => false; ContainerLayer _layer; @@ -880,7 +867,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { /// This method does not schedule a rendering frame, because since /// it cannot be the case that _only_ the compositing bits changed, /// something else will have scheduled a frame for us. - void _markNeedsCompositingBitsUpdate() { + void markNeedsCompositingBitsUpdate() { if (_needsCompositingBitsUpdate) return; _needsCompositingBitsUpdate = true; @@ -889,7 +876,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget { if (parent._needsCompositingBitsUpdate) return; if (!isRepaintBoundary && !parent.isRepaintBoundary) { - parent._markNeedsCompositingBitsUpdate(); + parent.markNeedsCompositingBitsUpdate(); return; } } diff --git a/packages/flutter/lib/src/rendering/proxy_box.dart b/packages/flutter/lib/src/rendering/proxy_box.dart index a24a69dacca..abf1d0eab51 100644 --- a/packages/flutter/lib/src/rendering/proxy_box.dart +++ b/packages/flutter/lib/src/rendering/proxy_box.dart @@ -525,6 +525,8 @@ class RenderIntrinsicHeight extends RenderProxyBox { } +int _getAlphaFromOpacity(double opacity) => (opacity * 255).round(); + /// Makes its child partially transparent. /// /// This class paints its child into an intermediate buffer and then blends the @@ -534,10 +536,12 @@ class RenderIntrinsicHeight extends RenderProxyBox { /// into an intermediate buffer. class RenderOpacity extends RenderProxyBox { RenderOpacity({ RenderBox child, double opacity }) - : this._opacity = opacity, super(child) { + : _opacity = opacity, _alpha = _getAlphaFromOpacity(opacity), super(child) { assert(opacity >= 0.0 && opacity <= 1.0); } + bool get alwaysNeedsCompositing => _alpha != 0 && _alpha != 255; + /// The fraction to scale the child's alpha value. /// /// An opacity of 1.0 is fully opaque. An opacity of 0.0 is fully transparent @@ -550,22 +554,23 @@ class RenderOpacity extends RenderProxyBox { if (_opacity == newOpacity) return; _opacity = newOpacity; + _alpha = _getAlphaFromOpacity(_opacity); + markNeedsCompositingBitsUpdate(); markNeedsPaint(); } - int get _alpha => (_opacity * 255).round(); + int _alpha; void paint(PaintingContext context, Offset offset) { if (child != null) { - int a = _alpha; - if (a == 0) + if (_alpha == 0) return; - if (a == 255) { + if (_alpha == 255) { context.paintChild(child, offset); return; } - // TODO(abarth): We should pass bounds here. - context.pushOpacity(needsCompositing, offset, null, a, super.paint); + assert(needsCompositing); + context.pushOpacity(offset, _alpha, super.paint); } }