| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/foundation.dart'; |
| import 'package:flutter/rendering.dart'; |
| import '../flutter_test_alternative.dart'; |
| |
| import 'rendering_tester.dart'; |
| |
| void main() { |
| test('nested repaint boundaries - smoke test', () { |
| RenderOpacity a, b, c; |
| a = RenderOpacity( |
| opacity: 1.0, |
| child: RenderRepaintBoundary( |
| child: b = RenderOpacity( |
| opacity: 1.0, |
| child: RenderRepaintBoundary( |
| child: c = RenderOpacity( |
| opacity: 1.0 |
| ) |
| ), |
| ), |
| ), |
| ); |
| layout(a, phase: EnginePhase.flushSemantics); |
| c.opacity = 0.9; |
| pumpFrame(phase: EnginePhase.flushSemantics); |
| a.opacity = 0.8; |
| c.opacity = 0.8; |
| pumpFrame(phase: EnginePhase.flushSemantics); |
| a.opacity = 0.7; |
| b.opacity = 0.7; |
| c.opacity = 0.7; |
| pumpFrame(phase: EnginePhase.flushSemantics); |
| }); |
| |
| test('Repaint boundary can get new parent after markNeedsCompositingBitsUpdate', () { |
| // Regression test for https://github.com/flutter/flutter/issues/24029. |
| |
| final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary(); |
| layout(repaintBoundary, phase: EnginePhase.flushSemantics); |
| |
| repaintBoundary.markNeedsCompositingBitsUpdate(); |
| |
| renderer.renderView.child = null; |
| final RenderPadding padding = RenderPadding( |
| padding: const EdgeInsets.all(50), |
| ); |
| renderer.renderView.child = padding; |
| padding.child = repaintBoundary; |
| pumpFrame(phase: EnginePhase.flushSemantics); |
| }); |
| |
| test('Framework creates an OffsetLayer for a repaint boundary', () { |
| final _TestRepaintBoundary repaintBoundary = _TestRepaintBoundary(); |
| final RenderOpacity opacity = RenderOpacity( |
| opacity: 1.0, |
| child: repaintBoundary, |
| ); |
| layout(opacity, phase: EnginePhase.flushSemantics); |
| expect(repaintBoundary.debugLayer, isA<OffsetLayer>()); |
| }); |
| |
| test('Framework does not create an OffsetLayer for a non-repaint boundary', () { |
| final _TestNonCompositedBox nonCompositedBox = _TestNonCompositedBox(); |
| final RenderOpacity opacity = RenderOpacity( |
| opacity: 1.0, |
| child: nonCompositedBox, |
| ); |
| layout(opacity, phase: EnginePhase.flushSemantics); |
| expect(nonCompositedBox.debugLayer, null); |
| }); |
| |
| test('Framework allows a non-repaint boundary to create own layer', () { |
| final _TestCompositedBox compositedBox = _TestCompositedBox(); |
| final RenderOpacity opacity = RenderOpacity( |
| opacity: 1.0, |
| child: compositedBox, |
| ); |
| layout(opacity, phase: EnginePhase.flushSemantics); |
| expect(compositedBox.debugLayer, isA<OpacityLayer>()); |
| }); |
| |
| test('Framework ensures repaint boundary layer is not overwritten', () { |
| final _TestRepaintBoundaryThatOverwritesItsLayer faultyRenderObject = _TestRepaintBoundaryThatOverwritesItsLayer(); |
| final RenderOpacity opacity = RenderOpacity( |
| opacity: 1.0, |
| child: faultyRenderObject, |
| ); |
| |
| FlutterErrorDetails error; |
| layout(opacity, phase: EnginePhase.flushSemantics, onErrors: () { |
| error = renderer.takeFlutterErrorDetails(); |
| }); |
| expect('${error.exception}', contains('Attempted to set a layer to a repaint boundary render object.')); |
| }); |
| } |
| |
| // A plain render object that's a repaint boundary. |
| class _TestRepaintBoundary extends RenderBox { |
| @override |
| bool get isRepaintBoundary => true; |
| |
| @override |
| void performLayout() { |
| size = constraints.smallest; |
| } |
| } |
| |
| // A render object that's a repaint boundary and (incorrectly) creates its own layer. |
| class _TestRepaintBoundaryThatOverwritesItsLayer extends RenderBox { |
| @override |
| bool get isRepaintBoundary => true; |
| |
| @override |
| void performLayout() { |
| size = constraints.smallest; |
| } |
| |
| @override |
| void paint(PaintingContext context, Offset offset) { |
| layer = OpacityLayer(alpha: 50); |
| } |
| } |
| |
| // A render object that's neither a repaint boundary nor creates its own layer. |
| class _TestNonCompositedBox extends RenderBox { |
| @override |
| bool get isRepaintBoundary => false; |
| |
| @override |
| void performLayout() { |
| size = constraints.smallest; |
| } |
| } |
| |
| // A render object that's not a repaint boundary but creates its own layer. |
| class _TestCompositedBox extends RenderBox { |
| @override |
| bool get isRepaintBoundary => false; |
| |
| @override |
| void performLayout() { |
| size = constraints.smallest; |
| } |
| |
| @override |
| void paint(PaintingContext context, Offset offset) { |
| layer = OpacityLayer(alpha: 50); |
| } |
| } |