blob: 2116cf9eb8337c105ce4a46941ad54813111ffa1 [file] [log] [blame]
// Copyright 2013 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.
#include "flutter/display_list/testing/dl_test_snippets.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/dl_op_receiver.h"
namespace flutter {
namespace testing {
sk_sp<DisplayList> GetSampleDisplayList() {
DisplayListBuilder builder(SkRect::MakeWH(150, 100));
builder.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80), DlPaint(DlColor::kRed()));
return builder.Build();
}
sk_sp<DisplayList> GetSampleNestedDisplayList() {
DisplayListBuilder builder(SkRect::MakeWH(150, 100));
DlPaint paint;
for (int y = 10; y <= 60; y += 10) {
for (int x = 10; x <= 60; x += 10) {
paint.setColor(((x + y) % 20) == 10 ? SK_ColorRED : SK_ColorBLUE);
builder.DrawRect(SkRect::MakeXYWH(x, y, 80, 80), paint);
}
}
DisplayListBuilder outer_builder(SkRect::MakeWH(150, 100));
outer_builder.DrawDisplayList(builder.Build());
return outer_builder.Build();
}
sk_sp<DisplayList> GetSampleDisplayList(int ops) {
DisplayListBuilder builder(SkRect::MakeWH(150, 100));
for (int i = 0; i < ops; i++) {
builder.DrawColor(DlColor::kRed(), DlBlendMode::kSrc);
}
return builder.Build();
}
// ---------------
// Test Suite data
// ---------------
std::vector<DisplayListInvocationGroup> CreateAllAttributesOps() {
return {
{"SetAntiAlias",
{
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setAntiAlias(true); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setAntiAlias(false); }},
}},
{"SetDither",
{
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setDither(true); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setDither(false); }},
}},
{"SetInvertColors",
{
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setInvertColors(true); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setInvertColors(false); }},
}},
{"SetStrokeCap",
{
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kRound); }},
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kSquare); }},
{0, 0, 0, 0,
[](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kButt); }},
}},
{"SetStrokeJoin",
{
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kBevel); }},
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kRound); }},
{0, 0, 0, 0,
[](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kMiter); }},
}},
{"SetStyle",
{
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setStyle(DlDrawStyle::kStroke); }},
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setStyle(DlDrawStyle::kStrokeAndFill); }},
{0, 0, 0, 0,
[](DlOpReceiver& r) { r.setStyle(DlDrawStyle::kFill); }},
}},
{"SetStrokeWidth",
{
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(1.0); }},
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(5.0); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(0.0); }},
}},
{"SetStrokeMiter",
{
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(0.0); }},
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(5.0); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(4.0); }},
}},
{"SetColor",
{
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setColor(SK_ColorGREEN); }},
{0, 8, 0, 0, [](DlOpReceiver& r) { r.setColor(SK_ColorBLUE); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setColor(SK_ColorBLACK); }},
}},
{"SetBlendMode",
{
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcIn); }},
{0, 8, 0, 0,
[](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kDstIn); }},
{0, 0, 0, 0,
[](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcOver); }},
}},
{"SetColorSource",
{
{0, 96, 0, 0,
[](DlOpReceiver& r) { r.setColorSource(&kTestSource1); }},
// stop_count * (sizeof(float) + sizeof(uint32_t)) = 80
{0, 80 + 6 * 4, 0, 0,
[](DlOpReceiver& r) { r.setColorSource(kTestSource2.get()); }},
{0, 80 + 6 * 4, 0, 0,
[](DlOpReceiver& r) { r.setColorSource(kTestSource3.get()); }},
{0, 88 + 6 * 4, 0, 0,
[](DlOpReceiver& r) { r.setColorSource(kTestSource4.get()); }},
{0, 80 + 6 * 4, 0, 0,
[](DlOpReceiver& r) { r.setColorSource(kTestSource5.get()); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setColorSource(nullptr); }},
}},
{"SetImageFilter",
{
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter1); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter2); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter3); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter4); }},
{0, 24, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestDilateImageFilter1);
}},
{0, 24, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestDilateImageFilter2);
}},
{0, 24, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestDilateImageFilter3);
}},
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter1); }},
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter2); }},
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter3); }},
{0, 64, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestMatrixImageFilter1);
}},
{0, 64, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestMatrixImageFilter2);
}},
{0, 64, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestMatrixImageFilter3);
}},
{0, 24, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestComposeImageFilter1);
}},
{0, 24, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestComposeImageFilter2);
}},
{0, 24, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(&kTestComposeImageFilter3);
}},
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter1); }},
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter2); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setImageFilter(nullptr); }},
{0, 24, 0, 0,
[](DlOpReceiver& r) {
r.setImageFilter(
kTestBlurImageFilter1
.makeWithLocalMatrix(SkMatrix::Translate(2, 2))
.get());
}},
}},
{"SetColorFilter",
{
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter1); }},
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter2); }},
{0, 24, 0, 0,
[](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter3); }},
{0, 96, 0, 0,
[](DlOpReceiver& r) {
r.setColorFilter(&kTestMatrixColorFilter1);
}},
{0, 96, 0, 0,
[](DlOpReceiver& r) {
r.setColorFilter(&kTestMatrixColorFilter2);
}},
{0, 16, 0, 0,
[](DlOpReceiver& r) {
r.setColorFilter(DlSrgbToLinearGammaColorFilter::instance.get());
}},
{0, 16, 0, 0,
[](DlOpReceiver& r) {
r.setColorFilter(DlLinearToSrgbGammaColorFilter::instance.get());
}},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setColorFilter(nullptr); }},
}},
{"SetPathEffect",
{
// sizeof(DlDashPathEffect) + 2 * sizeof(SkScalar)
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setPathEffect(kTestPathEffect1.get()); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setPathEffect(kTestPathEffect2.get()); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setPathEffect(nullptr); }},
}},
{"SetMaskFilter",
{
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter1); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter2); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter3); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter4); }},
{0, 32, 0, 0,
[](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter5); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.setMaskFilter(nullptr); }},
}},
};
}
std::vector<DisplayListInvocationGroup> CreateAllSaveRestoreOps() {
return {
{"Save(Layer)+Restore",
{
{5, 112, 5, 112,
[](DlOpReceiver& r) {
r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes,
&kTestCFImageFilter1);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
// There are many reasons that save and restore can elide content,
// including whether or not there are any draw operations between
// them, whether or not there are any state changes to restore, and
// whether group rendering (opacity) optimizations can allow
// attributes to be distributed to the children. To prevent those
// cases we include at least one clip operation and 2 overlapping
// rendering primitives between each save/restore pair.
{5, 96, 5, 96,
[](DlOpReceiver& r) {
r.save();
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
{5, 96, 5, 96,
[](DlOpReceiver& r) {
r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
{5, 96, 5, 96,
[](DlOpReceiver& r) {
r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
{5, 112, 5, 112,
[](DlOpReceiver& r) {
r.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
{5, 112, 5, 112,
[](DlOpReceiver& r) {
r.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
// backdrop variants - using the TestCFImageFilter because it can be
// reconstituted in the DL->SkCanvas->DL stream
// {5, 104, 5, 104, [](DlOpReceiver& r) {
// r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes,
// &kTestCFImageFilter1); r.clipRect({0, 0, 25, 25},
// SkClipOp::kIntersect, true); r.drawRect({5, 5, 15, 15});
// r.drawRect({10, 10, 20, 20});
// r.restore();
// }},
{5, 112, 5, 112,
[](DlOpReceiver& r) {
r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes,
&kTestCFImageFilter1);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
{5, 128, 5, 128,
[](DlOpReceiver& r) {
r.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes,
&kTestCFImageFilter1);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
{5, 128, 5, 128,
[](DlOpReceiver& r) {
r.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes,
&kTestCFImageFilter1);
r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
r.drawRect({5, 5, 15, 15});
r.drawRect({10, 10, 20, 20});
r.restore();
}},
}},
};
}
std::vector<DisplayListInvocationGroup> CreateAllTransformOps() {
return {
{"Translate",
{
// cv.translate(0, 0) is ignored
{1, 16, 1, 16, [](DlOpReceiver& r) { r.translate(10, 10); }},
{1, 16, 1, 16, [](DlOpReceiver& r) { r.translate(10, 15); }},
{1, 16, 1, 16, [](DlOpReceiver& r) { r.translate(15, 10); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.translate(0, 0); }},
}},
{"Scale",
{
// cv.scale(1, 1) is ignored
{1, 16, 1, 16, [](DlOpReceiver& r) { r.scale(2, 2); }},
{1, 16, 1, 16, [](DlOpReceiver& r) { r.scale(2, 3); }},
{1, 16, 1, 16, [](DlOpReceiver& r) { r.scale(3, 2); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.scale(1, 1); }},
}},
{"Rotate",
{
// cv.rotate(0) is ignored, otherwise expressed as concat(rotmatrix)
{1, 8, 1, 32, [](DlOpReceiver& r) { r.rotate(30); }},
{1, 8, 1, 32, [](DlOpReceiver& r) { r.rotate(45); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.rotate(0); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.rotate(360); }},
}},
{"Skew",
{
// cv.skew(0, 0) is ignored, otherwise expressed as
// concat(skewmatrix)
{1, 16, 1, 32, [](DlOpReceiver& r) { r.skew(0.1, 0.1); }},
{1, 16, 1, 32, [](DlOpReceiver& r) { r.skew(0.1, 0.2); }},
{1, 16, 1, 32, [](DlOpReceiver& r) { r.skew(0.2, 0.1); }},
{0, 0, 0, 0, [](DlOpReceiver& r) { r.skew(0, 0); }},
}},
{"Transform2DAffine",
{
{1, 32, 1, 32,
[](DlOpReceiver& r) { r.transform2DAffine(0, 1, 12, 1, 0, 33); }},
// r.transform(identity) is ignored
{0, 0, 0, 0,
[](DlOpReceiver& r) { r.transform2DAffine(1, 0, 0, 0, 1, 0); }},
}},
{"TransformFullPerspective",
{
{1, 72, 1, 72,
[](DlOpReceiver& r) {
r.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29,
0, 0, 0, 12);
}},
// r.transform(2D affine) is reduced to 2x3
{1, 32, 1, 32,
[](DlOpReceiver& r) {
r.transformFullPerspective(2, 1, 0, 4, 1, 3, 0, 5, 0, 0, 1, 0, 0,
0, 0, 1);
}},
// r.transform(identity) is ignored
{0, 0, 0, 0,
[](DlOpReceiver& r) {
r.transformFullPerspective(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1);
}},
}},
};
}
std::vector<DisplayListInvocationGroup> CreateAllClipOps() {
return {
{"ClipRect",
{
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, true);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipRect(kTestBounds.makeOffset(1, 1),
DlCanvas::ClipOp::kIntersect, true);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, false);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, true);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, false);
}},
}},
{"ClipRRect",
{
{1, 64, 1, 64,
[](DlOpReceiver& r) {
r.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, true);
}},
{1, 64, 1, 64,
[](DlOpReceiver& r) {
r.clipRRect(kTestRRect.makeOffset(1, 1),
DlCanvas::ClipOp::kIntersect, true);
}},
{1, 64, 1, 64,
[](DlOpReceiver& r) {
r.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, false);
}},
{1, 64, 1, 64,
[](DlOpReceiver& r) {
r.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, true);
}},
{1, 64, 1, 64,
[](DlOpReceiver& r) {
r.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, false);
}},
}},
{"ClipPath",
{
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, true);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipPath(kTestPath2, DlCanvas::ClipOp::kIntersect, true);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipPath(kTestPath3, DlCanvas::ClipOp::kIntersect, true);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, false);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, true);
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, false);
}},
// clipPath(rect) becomes clipRect
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.clipPath(kTestPathRect, DlCanvas::ClipOp::kIntersect, true);
}},
// clipPath(oval) becomes clipRRect
{1, 64, 1, 64,
[](DlOpReceiver& r) {
r.clipPath(kTestPathOval, DlCanvas::ClipOp::kIntersect, true);
}},
}},
};
}
std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
return {
{"DrawPaint",
{
{1, 8, 1, 8, [](DlOpReceiver& r) { r.drawPaint(); }},
}},
{"DrawColor",
{
// cv.drawColor becomes cv.drawPaint(paint)
{1, 16, 1, 24,
[](DlOpReceiver& r) {
r.drawColor(SK_ColorBLUE, DlBlendMode::kSrcIn);
}},
{1, 16, 1, 24,
[](DlOpReceiver& r) {
r.drawColor(SK_ColorBLUE, DlBlendMode::kDstIn);
}},
{1, 16, 1, 24,
[](DlOpReceiver& r) {
r.drawColor(SK_ColorCYAN, DlBlendMode::kSrcIn);
}},
}},
{"DrawLine",
{
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawLine({0, 0}, {10, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawLine({0, 1}, {10, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawLine({0, 0}, {20, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawLine({0, 0}, {10, 20});
}},
}},
{"DrawRect",
{
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawRect({0, 0, 10, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawRect({0, 1, 10, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawRect({0, 0, 20, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawRect({0, 0, 10, 20});
}},
}},
{"DrawOval",
{
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawOval({0, 0, 10, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawOval({0, 1, 10, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawOval({0, 0, 20, 10});
}},
{1, 24, 1, 24,
[](DlOpReceiver& r) {
r.drawOval({0, 0, 10, 20});
}},
}},
{"DrawCircle",
{
// cv.drawCircle becomes cv.drawOval
{1, 16, 1, 24,
[](DlOpReceiver& r) {
r.drawCircle({0, 0}, 10);
}},
{1, 16, 1, 24,
[](DlOpReceiver& r) {
r.drawCircle({0, 5}, 10);
}},
{1, 16, 1, 24,
[](DlOpReceiver& r) {
r.drawCircle({0, 0}, 20);
}},
}},
{"DrawRRect",
{
{1, 56, 1, 56, [](DlOpReceiver& r) { r.drawRRect(kTestRRect); }},
{1, 56, 1, 56,
[](DlOpReceiver& r) { r.drawRRect(kTestRRect.makeOffset(5, 5)); }},
}},
{"DrawDRRect",
{
{1, 112, 1, 112,
[](DlOpReceiver& r) { r.drawDRRect(kTestRRect, kTestInnerRRect); }},
{1, 112, 1, 112,
[](DlOpReceiver& r) {
r.drawDRRect(kTestRRect.makeOffset(5, 5),
kTestInnerRRect.makeOffset(4, 4));
}},
}},
{"DrawPath",
{
{1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPath1); }},
{1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPath2); }},
{1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPath3); }},
{1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPathRect); }},
{1, 24, 1, 24, [](DlOpReceiver& r) { r.drawPath(kTestPathOval); }},
}},
{"DrawArc",
{
{1, 32, 1, 32,
[](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 270, false); }},
{1, 32, 1, 32,
[](DlOpReceiver& r) {
r.drawArc(kTestBounds.makeOffset(1, 1), 45, 270, false);
}},
{1, 32, 1, 32,
[](DlOpReceiver& r) { r.drawArc(kTestBounds, 30, 270, false); }},
{1, 32, 1, 32,
[](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 260, false); }},
{1, 32, 1, 32,
[](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 270, true); }},
}},
{"DrawPoints",
{
{1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8,
[](DlOpReceiver& r) {
r.drawPoints(DlCanvas::PointMode::kPoints, TestPointCount,
TestPoints);
}},
{1, 8 + (TestPointCount - 1) * 8, 1, 8 + (TestPointCount - 1) * 8,
[](DlOpReceiver& r) {
r.drawPoints(DlCanvas::PointMode::kPoints, TestPointCount - 1,
TestPoints);
}},
{1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8,
[](DlOpReceiver& r) {
r.drawPoints(DlCanvas::PointMode::kLines, TestPointCount,
TestPoints);
}},
{1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8,
[](DlOpReceiver& r) {
r.drawPoints(DlCanvas::PointMode::kPolygon, TestPointCount,
TestPoints);
}},
}},
{"DrawVertices",
{
{1, 112, 1, 16,
[](DlOpReceiver& r) {
r.drawVertices(TestVertices1.get(), DlBlendMode::kSrcIn);
}},
{1, 112, 1, 16,
[](DlOpReceiver& r) {
r.drawVertices(TestVertices1.get(), DlBlendMode::kDstIn);
}},
{1, 112, 1, 16,
[](DlOpReceiver& r) {
r.drawVertices(TestVertices2.get(), DlBlendMode::kSrcIn);
}},
}},
{"DrawImage",
{
{1, 24, -1, 48,
[](DlOpReceiver& r) {
r.drawImage(TestImage1, {10, 10}, kNearestSampling, false);
}},
{1, 24, -1, 48,
[](DlOpReceiver& r) {
r.drawImage(TestImage1, {10, 10}, kNearestSampling, true);
}},
{1, 24, -1, 48,
[](DlOpReceiver& r) {
r.drawImage(TestImage1, {20, 10}, kNearestSampling, false);
}},
{1, 24, -1, 48,
[](DlOpReceiver& r) {
r.drawImage(TestImage1, {10, 20}, kNearestSampling, false);
}},
{1, 24, -1, 48,
[](DlOpReceiver& r) {
r.drawImage(TestImage1, {10, 10}, kLinearSampling, false);
}},
{1, 24, -1, 48,
[](DlOpReceiver& r) {
r.drawImage(TestImage2, {10, 10}, kNearestSampling, false);
}},
{1, 24, -1, 48,
[](DlOpReceiver& r) {
auto dl_image = DlImage::Make(TestSkImage);
r.drawImage(dl_image, {10, 10}, kNearestSampling, false);
}},
}},
{"DrawImageRect",
{
{1, 56, -1, 80,
[](DlOpReceiver& r) {
r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
kNearestSampling, false,
DlCanvas::SrcRectConstraint::kFast);
}},
{1, 56, -1, 80,
[](DlOpReceiver& r) {
r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
kNearestSampling, true,
DlCanvas::SrcRectConstraint::kFast);
}},
{1, 56, -1, 80,
[](DlOpReceiver& r) {
r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
kNearestSampling, false,
DlCanvas::SrcRectConstraint::kStrict);
}},
{1, 56, -1, 80,
[](DlOpReceiver& r) {
r.drawImageRect(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80},
kNearestSampling, false,
DlCanvas::SrcRectConstraint::kFast);
}},
{1, 56, -1, 80,
[](DlOpReceiver& r) {
r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80},
kNearestSampling, false,
DlCanvas::SrcRectConstraint::kFast);
}},
{1, 56, -1, 80,
[](DlOpReceiver& r) {
r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
kLinearSampling, false,
DlCanvas::SrcRectConstraint::kFast);
}},
{1, 56, -1, 80,
[](DlOpReceiver& r) {
r.drawImageRect(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80},
kNearestSampling, false,
DlCanvas::SrcRectConstraint::kFast);
}},
{1, 56, -1, 80,
[](DlOpReceiver& r) {
auto dl_image = DlImage::Make(TestSkImage);
r.drawImageRect(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80},
kNearestSampling, false,
DlCanvas::SrcRectConstraint::kFast);
}},
}},
{"DrawImageNine",
{
// SkCanvas::drawImageNine is immediately converted to
// drawImageLattice
{1, 48, -1, 80,
[](DlOpReceiver& r) {
r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
DlFilterMode::kNearest, false);
}},
{1, 48, -1, 80,
[](DlOpReceiver& r) {
r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
DlFilterMode::kNearest, true);
}},
{1, 48, -1, 80,
[](DlOpReceiver& r) {
r.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80},
DlFilterMode::kNearest, false);
}},
{1, 48, -1, 80,
[](DlOpReceiver& r) {
r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80},
DlFilterMode::kNearest, false);
}},
{1, 48, -1, 80,
[](DlOpReceiver& r) {
r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
DlFilterMode::kLinear, false);
}},
{1, 48, -1, 80,
[](DlOpReceiver& r) {
r.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80},
DlFilterMode::kNearest, false);
}},
{1, 48, -1, 80,
[](DlOpReceiver& r) {
auto dl_image = DlImage::Make(TestSkImage);
r.drawImageNine(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80},
DlFilterMode::kNearest, false);
}},
}},
{"DrawAtlas",
{
{1, 48 + 32 + 8, -1, 48 + 32 + 32,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
DlBlendMode::kSrcIn, kNearestSampling, nullptr,
false);
}},
{1, 48 + 32 + 8, -1, 48 + 32 + 32,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
DlBlendMode::kSrcIn, kNearestSampling, nullptr, true);
}},
{1, 48 + 32 + 8, -1, 48 + 32 + 32,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{0, 1, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
DlBlendMode::kSrcIn, kNearestSampling, nullptr,
false);
}},
{1, 48 + 32 + 8, -1, 48 + 32 + 32,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 25, 30, 30}};
r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
DlBlendMode::kSrcIn, kNearestSampling, nullptr,
false);
}},
{1, 48 + 32 + 8, -1, 48 + 32 + 32,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
DlBlendMode::kSrcIn, kLinearSampling, nullptr, false);
}},
{1, 48 + 32 + 8, -1, 48 + 32 + 32,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
DlBlendMode::kDstIn, kNearestSampling, nullptr,
false);
}},
{1, 64 + 32 + 8, -1, 64 + 32 + 32,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
static SkRect cull_rect = {0, 0, 200, 200};
r.drawAtlas(TestImage2, xforms, texs, nullptr, 2,
DlBlendMode::kSrcIn, kNearestSampling, &cull_rect,
false);
}},
{1, 48 + 32 + 8 + 8, -1, 48 + 32 + 32 + 8,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()};
r.drawAtlas(TestImage1, xforms, texs, colors, 2,
DlBlendMode::kSrcIn, kNearestSampling, nullptr,
false);
}},
{1, 64 + 32 + 8 + 8, -1, 64 + 32 + 32 + 8,
[](DlOpReceiver& r) {
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()};
static SkRect cull_rect = {0, 0, 200, 200};
r.drawAtlas(TestImage1, xforms, texs, colors, 2,
DlBlendMode::kSrcIn, kNearestSampling, &cull_rect,
false);
}},
{1, 48 + 32 + 8, -1, 48 + 32 + 32,
[](DlOpReceiver& r) {
auto dl_image = DlImage::Make(TestSkImage);
static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
r.drawAtlas(dl_image, xforms, texs, nullptr, 2,
DlBlendMode::kSrcIn, kNearestSampling, nullptr,
false);
}},
}},
{"DrawDisplayList",
{
// cv.drawDL does not exist
{1, 16, -1, 16,
[](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList1, 1.0); }},
{1, 16, -1, 16,
[](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList1, 0.5); }},
{1, 16, -1, 16,
[](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList2, 1.0); }},
{1, 16, -1, 16,
[](DlOpReceiver& r) {
r.drawDisplayList(MakeTestDisplayList(10, 10, SK_ColorRED), 1.0);
}},
}},
{"DrawTextBlob",
{
{1, 24, 1, 24,
[](DlOpReceiver& r) { r.drawTextBlob(TestBlob1, 10, 10); }},
{1, 24, 1, 24,
[](DlOpReceiver& r) { r.drawTextBlob(TestBlob1, 20, 10); }},
{1, 24, 1, 24,
[](DlOpReceiver& r) { r.drawTextBlob(TestBlob1, 10, 20); }},
{1, 24, 1, 24,
[](DlOpReceiver& r) { r.drawTextBlob(TestBlob2, 10, 10); }},
}},
// The -1 op counts below are to indicate to the framework not to test
// SkCanvas conversion of these ops as it converts the operation into a
// format that is not exposed publicly and so we cannot recapture the
// operation.
// See: https://bugs.chromium.org/p/skia/issues/detail?id=12125
{"DrawShadow",
{
// cv shadows are turned into an opaque ShadowRec which is not
// exposed
{1, 32, -1, 32,
[](DlOpReceiver& r) {
r.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 1.0);
}},
{1, 32, -1, 32,
[](DlOpReceiver& r) {
r.drawShadow(kTestPath2, SK_ColorGREEN, 1.0, false, 1.0);
}},
{1, 32, -1, 32,
[](DlOpReceiver& r) {
r.drawShadow(kTestPath1, SK_ColorBLUE, 1.0, false, 1.0);
}},
{1, 32, -1, 32,
[](DlOpReceiver& r) {
r.drawShadow(kTestPath1, SK_ColorGREEN, 2.0, false, 1.0);
}},
{1, 32, -1, 32,
[](DlOpReceiver& r) {
r.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, true, 1.0);
}},
{1, 32, -1, 32,
[](DlOpReceiver& r) {
r.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 2.5);
}},
}},
};
}
std::vector<DisplayListInvocationGroup> CreateAllGroups() {
std::vector<DisplayListInvocationGroup> result;
auto all_attribute_ops = CreateAllAttributesOps();
std::move(all_attribute_ops.begin(), all_attribute_ops.end(),
std::back_inserter(result));
auto all_save_restore_ops = CreateAllSaveRestoreOps();
std::move(all_save_restore_ops.begin(), all_save_restore_ops.end(),
std::back_inserter(result));
auto all_transform_ops = CreateAllTransformOps();
std::move(all_transform_ops.begin(), all_transform_ops.end(),
std::back_inserter(result));
auto all_clip_ops = CreateAllClipOps();
std::move(all_clip_ops.begin(), all_clip_ops.end(),
std::back_inserter(result));
auto all_rendering_ops = CreateAllRenderingOps();
std::move(all_rendering_ops.begin(), all_rendering_ops.end(),
std::back_inserter(result));
return result;
}
} // namespace testing
} // namespace flutter