diff --git a/packages/flutter/lib/src/painting/shader_warm_up.dart b/packages/flutter/lib/src/painting/shader_warm_up.dart index 9c7f308964b..33334a69d09 100644 --- a/packages/flutter/lib/src/painting/shader_warm_up.dart +++ b/packages/flutter/lib/src/painting/shader_warm_up.dart @@ -192,5 +192,22 @@ class DefaultShaderWarmUp extends ShaderWarmUp { final ui.Paragraph paragraph = paragraphBuilder.build() ..layout(const ui.ParagraphConstraints(width: 60.0)); canvas.drawParagraph(paragraph, const ui.Offset(20.0, 20.0)); + + // Draw a rect inside a rrect with a non-trivial intersection. If the + // intersection is trivial (e.g., equals the rrect clip), Skia will optimize + // the clip out. + // + // Add an integral or fractional translation to trigger Skia's non-AA or AA + // optimizations (as did before in normal FillRectOp in rrect clip cases). + for (double fraction in [0.0, 0.5]) { + canvas + ..save() + ..translate(fraction, fraction) + ..clipRRect(ui.RRect.fromLTRBR(8, 8, 328, 248, const ui.Radius.circular(16))) + ..drawRect(const ui.Rect.fromLTRB(10, 10, 320, 240), ui.Paint()) + ..restore(); + canvas.translate(drawCallSpacing, 0.0); + } + canvas.translate(0.0, drawCallSpacing); } } diff --git a/packages/flutter/test/painting/shader_warm_up_test.dart b/packages/flutter/test/painting/shader_warm_up_test.dart new file mode 100644 index 00000000000..5f8eebe43e3 --- /dev/null +++ b/packages/flutter/test/painting/shader_warm_up_test.dart @@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium 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/painting.dart'; +import 'package:flutter_test/flutter_test.dart'; + +class TestCanvas implements Canvas { + TestCanvas([this.invocations]); + + final List invocations; + + @override + void noSuchMethod(Invocation invocation) { + invocations?.add(invocation); + } +} + +void main() { + test('DefaultShaderWarmUp has expected canvas invocations', () { + final List invocations = []; + final TestCanvas canvas = TestCanvas(invocations); + const DefaultShaderWarmUp s = DefaultShaderWarmUp(); + s.warmUpOnCanvas(canvas); + + bool hasDrawRectAfterClipRRect = false; + for (int i = 0; i < invocations.length - 1; i += 1) { + if (invocations[i].memberName == #clipRRect && invocations[i + 1].memberName == #drawRect) { + hasDrawRectAfterClipRRect = true; + break; + } + } + + expect(hasDrawRectAfterClipRRect, true); + }); +}