mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #1182 from abarth/composite_blends
Always using OpacityLayer for blending
This commit is contained in:
commit
24c0645d93
@ -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<String> settings) {
|
||||
super.debugDescribeSettings(settings);
|
||||
settings.add('bounds: $bounds');
|
||||
settings.add('alpha: $alpha');
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user