17#include "gtest/gtest.h"
33 const std::vector<std::unique_ptr<DlImage>>&
images) {
34 canvas->
Scale(0.2, 0.2);
43 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
47 auto draw = [](
DlCanvas* canvas,
const std::vector<sk_sp<DlImage>>&
images) {
56 std::vector<sk_sp<DlImage>>
images;
57 images.emplace_back(CreateDlImageForFixture(
"kalimba.jpg"));
60 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
66 Point content_scale = GetContentScale();
67 auto draw = [content_scale](
DlCanvas* canvas,
68 const std::vector<sk_sp<DlImage>>&
images) {
69 canvas->
Scale(content_scale.
x, content_scale.
y);
94 canvas->
SaveLayer(save_layer_bounds,
nullptr, backdrop.get());
110 std::vector<sk_sp<DlImage>>
images;
113 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
121 canvas->SaveLayer(rect.
Expand(8.0f), &layer_paint);
128 builder.
Scale(GetContentScale().
x, GetContentScale().
y);
134 builder.
Scale(1.3f, 1.3f);
137 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
141void DrawBlurGrid(
DlCanvas* canvas) {
147 std::vector<Scalar> blur_radii = {10, 30, 50};
148 for (
size_t i = 0;
i < blur_radii.size(); ++
i) {
150 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
153 Scalar yval = gap +
i * (gap +
height);
168 Point content_scale = GetContentScale();
169 auto draw = [content_scale](
DlCanvas* canvas,
170 const std::vector<sk_sp<DlImage>>&
images) {
171 canvas->
Scale(content_scale.
x, content_scale.
y);
173 DrawBlurGrid(canvas);
177 std::vector<sk_sp<DlImage>>
images;
180 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
184 Point content_scale = GetContentScale();
185 auto draw = [content_scale](
DlCanvas* canvas,
186 const std::vector<sk_sp<DlImage>>&
images) {
187 canvas->
Scale(content_scale.
x, content_scale.
y);
189 canvas->
Scale(0.33, 0.33);
190 DrawBlurGrid(canvas);
194 std::vector<sk_sp<DlImage>>
images;
197 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
201 Point content_scale = GetContentScale();
202 auto draw = [content_scale](
DlCanvas* canvas,
203 const std::vector<sk_sp<DlImage>>&
images) {
204 canvas->
Scale(content_scale.
x, content_scale.
y);
207 canvas->
Scale(0.33, 0.33);
211 DrawBlurGrid(canvas);
215 std::vector<sk_sp<DlImage>>
images;
218 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
223 builder.
Scale(GetContentScale().
x, GetContentScale().
y);
226 auto blur_sigmas = std::array{5.0f, 10.0f, 20.0f};
227 auto blur_colors = std::array{
241 path_builder.
MoveTo(corner + relative_from);
243 path_builder.
LineTo(corner + relative_from);
251 path_builder.
CubicCurveTo(corner + relative_from * magic,
252 corner + relative_to * magic,
253 corner + relative_to);
268 for (
size_t i = 0;
i < blur_sigmas.size();
i++) {
276 rect = rect.
Shift(150.0f, 0.0f);
277 builder.
DrawPath(make_rrect_path(rect, 10.0f, 10.0f), paint);
278 rect = rect.
Shift(-150.0f, 0.0f);
280 rect = rect.
Shift(0.0f, 200.0f);
282 rect = rect.
Shift(150.0f, 0.0f);
283 builder.
DrawPath(make_rrect_path(rect, 10.0f, 20.0f), paint);
284 rect = rect.
Shift(-150.0f, 0.0f);
286 rect = rect.
Shift(0.0f, 200.0f);
288 rect = rect.
Shift(150.0f, 0.0f);
289 builder.
DrawPath(make_rrect_path(rect, 20.0f, 10.0f), paint);
290 rect = rect.
Shift(-150.0f, 0.0f);
293 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
297 Point content_scale = GetContentScale();
298 auto draw = [content_scale](
DlCanvas* canvas,
299 const std::vector<sk_sp<DlImage>>&
images) {
300 canvas->
Scale(content_scale.
x, content_scale.
y);
320 for (
int degrees = 0; degrees < 360; degrees += 30) {
322 canvas->
DrawDashedLine(center + inner * delta, center + outer * delta,
323 dash_on, dash_off, thick_paint);
324 canvas->
DrawDashedLine(center + inner * delta, center + outer * delta,
325 dash_on, dash_off, middle_paint);
326 canvas->
DrawDashedLine(center + inner * delta, center + outer * delta,
327 dash_on, dash_off, thin_paint);
350 std::vector<sk_sp<DlImage>>
images;
353 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
363 builder.
SaveLayer(std::nullopt, &save_paint);
378 ASSERT_TRUE(OpenPlaygroundHere(builder.
Build()));
383 const uint32_t* ptr =
reinterpret_cast<const uint32_t*
>(img->
GetBytes());
386 for (uint32_t j = 0; j < img->
GetWidth(); ++j) {
387 uint32_t pixel = *ptr++;
388 if ((pixel & 0x00ffffff) != 0) {
389 max_y = std::max(max_y,
static_cast<int32_t
>(
i));
396std::optional<int32_t> CalculateSpaceBetweenUI(
399 if (
y < 0 || std::cmp_greater_equal(
y, img->
GetHeight())) {
402 const uint32_t* ptr =
reinterpret_cast<const uint32_t*
>(img->
GetBytes());
404 std::vector<size_t> boundaries;
405 uint32_t
value = *ptr++;
407 if (((*ptr & 0x00ffffff) != 0) != ((
value & 0x00ffffff) != 0)) {
408 boundaries.push_back(
i);
413 if (boundaries.size() != 6) {
416 return boundaries[4] - boundaries[3];
429 builder.
Scale(scale, scale);
438 return builder.
Build();
441 std::unique_ptr<impeller::testing::Screenshot> right =
442 MakeScreenshot(
callback(
"h", 0.444));
444 GTEST_SKIP() <<
"making screenshots not supported.";
446 std::unique_ptr<impeller::testing::Screenshot> left =
447 MakeScreenshot(
callback(
"e", 0.444));
449 int32_t left_max_y = CalculateMaxY(left.get());
450 int32_t right_max_y = CalculateMaxY(right.get());
451 int32_t y_diff = std::abs(left_max_y - right_max_y);
452 EXPECT_TRUE(y_diff <= 2) <<
"y diff: " << y_diff;
460 std::optional<int32_t> last_space;
461 for (
int i = 0;
i <= 100; ++
i) {
462 Scalar scale = 0.440 +
i / 1000.0;
463 absl::StatusOr<DlRect> text_bounds_or;
464 sk_sp<DisplayList> display_list;
470 builder.
Scale(scale, scale);
476 display_list = builder.
Build();
478 ASSERT_TRUE(text_bounds_or.ok());
479 ASSERT_TRUE(display_list);
480 std::unique_ptr<impeller::testing::Screenshot> right =
481 MakeScreenshot(display_list);
483 GTEST_SKIP() <<
"making screenshots not supported.";
485 middle = std::rint(scale * text_bounds_or->GetCenter().y);
487 std::optional<int32_t> space = CalculateSpaceBetweenUI(right.get(), middle);
488 ASSERT_TRUE(space.has_value());
489 if (space.has_value() && last_space.has_value()) {
490 int32_t diff = abs(*space - *last_space);
491 EXPECT_TRUE(diff <= 1)
492 <<
"i:" <<
i <<
" space:" << *space <<
" last_space:" << *last_space;
499struct LeftmostIntensity {
506LeftmostIntensity CalculateLeftmostIntensity(
508 LeftmostIntensity result = {.x =
static_cast<int32_t
>(img->
GetWidth()),
510 const uint32_t* ptr =
reinterpret_cast<const uint32_t*
>(img->
GetBytes());
512 for (int32_t j = 0; j < static_cast<int32_t>(img->
GetWidth()); ++j) {
513 if (((*ptr & 0x00ffffff) != 0)) {
516 result.value = (*ptr & 0xff00) >> 8;
517 }
else if (j == result.x) {
519 std::max(
static_cast<int32_t
>(*ptr & 0xff), result.value);
546 return builder.
Build();
549 LeftmostIntensity intensity[5];
550 for (
int i = 0;
i <= 4; ++
i) {
551 Scalar offset = 10 + (
i / 4.0);
552 std::unique_ptr<impeller::testing::Screenshot> right =
555 GTEST_SKIP() <<
"making screenshots not supported.";
557 intensity[
i] = CalculateLeftmostIntensity(right.get());
558 ASSERT_NE(intensity[
i].
value, 0);
560 for (
int i = 1;
i < 5; ++
i) {
561 EXPECT_TRUE(intensity[
i].
x - intensity[
i - 1].
x == 1 ||
565 EXPECT_EQ(intensity[4].
x - intensity[0].
x, 1);
576 builder.
Scale(scalar, scalar);
587 return builder.
Build();
590 LeftmostIntensity intensity[5];
591 Scalar offset_fraction = 0.25 / scalar;
592 for (
int i = 0;
i <= 4; ++
i) {
593 Scalar offset = 10 + (offset_fraction *
i);
594 std::unique_ptr<impeller::testing::Screenshot> right =
597 GTEST_SKIP() <<
"making screenshots not supported.";
599 intensity[
i] = CalculateLeftmostIntensity(right.get());
600 ASSERT_NE(intensity[
i].
value, 0);
602 for (
int i = 1;
i < 5; ++
i) {
603 EXPECT_TRUE(intensity[
i].
x - intensity[
i - 1].
x == 1 ||
607 EXPECT_EQ(intensity[4].
x - intensity[0].
x, 1);
618 builder.
Scale(scalar, scalar);
630 return builder.
Build();
633 LeftmostIntensity intensity[5];
634 Scalar offset_fraction = 0.25 / scalar;
635 for (
int i = 0;
i <= 4; ++
i) {
636 Scalar offset = 10 + (offset_fraction *
i);
637 std::unique_ptr<impeller::testing::Screenshot> right =
640 GTEST_SKIP() <<
"making screenshots not supported.";
642 intensity[
i] = CalculateLeftmostIntensity(right.get());
643 ASSERT_NE(intensity[
i].
value, 0);
645 for (
int i = 1;
i < 5; ++
i) {
646 EXPECT_TRUE(intensity[
i].
x - intensity[
i - 1].
x == 1 ||
650 EXPECT_EQ(intensity[4].
x - intensity[0].
x, 1);
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void DrawColor(DlColor color, DlBlendMode mode) override
void DrawCircle(const DlPoint ¢er, DlScalar radius, const DlPaint &paint) override
void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) override
void Scale(DlScalar sx, DlScalar sy) override
void Translate(DlScalar tx, DlScalar ty) override
void DrawPaint(const DlPaint &paint) override
sk_sp< DisplayList > Build()
void DrawPath(const DlPath &path, const DlPaint &paint) override
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
Developer-facing API for rendering anything within the engine.
virtual void DrawPaint(const DlPaint &paint)=0
virtual void DrawCircle(const DlPoint ¢er, DlScalar radius, const DlPaint &paint)=0
virtual void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint)=0
virtual void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt)=0
virtual void DrawRect(const DlRect &rect, const DlPaint &paint)=0
virtual void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr)=0
virtual void Translate(DlScalar tx, DlScalar ty)=0
virtual void DrawColor(DlColor color, DlBlendMode mode=DlBlendMode::kSrcOver)=0
virtual void Rotate(DlScalar degrees)=0
virtual void DrawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length, const DlPaint &paint)=0
virtual void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void Scale(DlScalar sx, DlScalar sy)=0
static std::shared_ptr< DlImageFilter > MakeDilate(DlScalar radius_x, DlScalar radius_y)
static std::shared_ptr< DlImageFilter > MakeMatrix(const DlMatrix &matrix, DlImageSampling sampling)
DlPaint & setColor(DlColor color)
DlPaint & setAntiAlias(bool isAntiAlias)
DlPaint & setStrokeCap(DlStrokeCap cap)
DlPaint & setStrokeWidth(float width)
DlPaint & setAlpha(uint8_t alpha)
DlPaint & setImageFilter(std::nullptr_t filter)
DlPaint & setMaskFilter(std::nullptr_t filter)
DlPaint & setDrawStyle(DlDrawStyle style)
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
static constexpr const DlScalar kArcApproximationMagic
DlPathBuilder & MoveTo(DlPoint p2)
Start a new contour that will originate at the indicated point p2.
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & CubicCurveTo(DlPoint cp1, DlPoint cp2, DlPoint p2)
Draw a cubic bezier curve from the current point to the indicated point p2, using the indicated point...
virtual const uint8_t * GetBytes() const =0
Access raw data of the screenshot.
virtual size_t GetHeight() const =0
Returns the height of the image in pixels.
virtual size_t GetWidth() const =0
Returns the width of the image in pixels.
FlutterDesktopBinaryReply callback
#define FML_CHECK(condition)
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
std::array< MockImage, 3 > images
TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM)
absl::StatusOr< DlRect > RenderTextInCanvasSkia(DlCanvas *canvas, const std::string &text, const std::string_view &font_fixture, DlPoint position, const TextRenderOptions &options)
impeller::Scalar DlScalar
@ kButt
no stroke extension
@ kStroke
strokes boundary of shapes
@ kNormal
fuzzy inside and outside
impeller::Vector2 DlVector2
#define INSTANTIATE_PLAYGROUND_SUITE(playground)
static constexpr DlColor kMagenta()
static constexpr DlColor kWhite()
static constexpr DlColor kBlue()
static constexpr DlColor kBlack()
static constexpr DlColor kMaroon()
static constexpr DlColor ARGB(DlScalar a, DlScalar r, DlScalar g, DlScalar b)
Construct a 32 bit color from floating point A, R, G, and B color channels.
static constexpr DlColor kAqua()
static constexpr DlColor kYellow()
static constexpr DlColor kRed()
static constexpr DlColor kGreen()
static constexpr DlColor kCyan()
static constexpr Matrix MakeRow(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
static RoundRect MakeRectRadius(const Rect &rect, Scalar radius)
static RoundRect MakeNinePatch(const Rect &rect, Scalar left, Scalar top, Scalar right, Scalar bottom)
static RoundRect MakeOval(const Rect &rect)
static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
static constexpr TPoint< Type > MakeXY(Type x, Type y)
constexpr TPoint< T > GetLeftTop() const
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr TPoint< T > GetRightBottom() const
constexpr TPoint< T > GetLeftBottom() const
constexpr TPoint< T > GetRightTop() const
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)