Flutter Impeller
skia_conversions_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "display_list/dl_blend_mode.h"
6 #include "display_list/dl_color.h"
7 #include "display_list/dl_tile_mode.h"
8 #include "flutter/testing/testing.h"
13 #include "include/core/SkMatrix.h"
14 #include "include/core/SkRRect.h"
15 
16 namespace impeller {
17 namespace testing {
18 
19 TEST(SkiaConversionTest, ToMatrixTranslate) {
20  SkMatrix sk_matrix = SkMatrix::Translate(100, 100);
21  Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
22 
23  EXPECT_EQ(matrix.m[12], 100);
24  EXPECT_EQ(matrix.m[13], 100);
25  EXPECT_TRUE(matrix.IsTranslationScaleOnly());
26 
27  matrix.m[12] = 0;
28  matrix.m[13] = 0;
29 
30  EXPECT_TRUE(matrix.IsIdentity());
31 }
32 
33 TEST(SkiaConversionTest, ToMatrixScale) {
34  SkMatrix sk_matrix = SkMatrix::Scale(2, 2);
35  Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
36 
37  EXPECT_EQ(matrix.m[0], 2);
38  EXPECT_EQ(matrix.m[5], 2);
39  EXPECT_TRUE(matrix.IsTranslationScaleOnly());
40 
41  matrix.m[0] = 1;
42  matrix.m[5] = 1;
43 
44  EXPECT_TRUE(matrix.IsIdentity());
45 }
46 
47 TEST(SkiaConversionTest, ToMatrixRotate) {
48  SkMatrix sk_matrix = SkMatrix::RotateDeg(90);
49  Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
50 
51  EXPECT_EQ(matrix.vec[0], Vector4(0, 1, 0, 0));
52  EXPECT_EQ(matrix.vec[1], Vector4(-1, 0, 0, 0));
53  EXPECT_EQ(matrix.vec[2], Vector4(0, 0, 1, 0));
54  EXPECT_EQ(matrix.vec[3], Vector4(0, 0, 0, 1));
55  EXPECT_FALSE(matrix.IsTranslationScaleOnly());
56 }
57 
58 TEST(SkiaConversionTest, ToMatrixSkew) {
59  SkMatrix sk_matrix = SkMatrix::Skew(2, 2);
60  Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
61 
62  EXPECT_EQ(matrix.vec[0], Vector4(1, 2, 0, 0));
63  EXPECT_EQ(matrix.vec[1], Vector4(2, 1, 0, 0));
64  EXPECT_EQ(matrix.vec[2], Vector4(0, 0, 1, 0));
65  EXPECT_EQ(matrix.vec[3], Vector4(0, 0, 0, 1));
66  EXPECT_FALSE(matrix.IsTranslationScaleOnly());
67 }
68 
69 TEST(SkiaConversionTest, ToSamplerDescriptor) {
71  flutter::DlImageSampling::kNearestNeighbor)
72  .min_filter,
75  flutter::DlImageSampling::kNearestNeighbor)
76  .mip_filter,
78 
79  EXPECT_EQ(
80  skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
81  .min_filter,
83  EXPECT_EQ(
84  skia_conversions::ToSamplerDescriptor(flutter::DlImageSampling::kLinear)
85  .mip_filter,
87 
89  flutter::DlImageSampling::kMipmapLinear)
90  .min_filter,
93  flutter::DlImageSampling::kMipmapLinear)
94  .mip_filter,
96 }
97 
98 TEST(SkiaConversionsTest, SkPointToPoint) {
99  for (int x = -100; x < 100; x += 4) {
100  for (int y = -100; y < 100; y += 4) {
101  EXPECT_EQ(skia_conversions::ToPoint(SkPoint::Make(x * 0.25f, y * 0.25f)),
102  Point(x * 0.25f, y * 0.25f));
103  }
104  }
105 }
106 
107 TEST(SkiaConversionsTest, SkPointToSize) {
108  for (int x = -100; x < 100; x += 4) {
109  for (int y = -100; y < 100; y += 4) {
110  EXPECT_EQ(skia_conversions::ToSize(SkPoint::Make(x * 0.25f, y * 0.25f)),
111  Size(x * 0.25f, y * 0.25f));
112  }
113  }
114 }
115 
116 TEST(SkiaConversionsTest, ToColor) {
117  // Create a color with alpha, red, green, and blue values that are all
118  // trivially divisible by 255 so that we can test the conversion results in
119  // correct scalar values.
120  // AARRGGBB
121  const flutter::DlColor color = flutter::DlColor(0x8040C020);
122  auto converted_color = skia_conversions::ToColor(color);
123 
124  ASSERT_TRUE(ScalarNearlyEqual(converted_color.alpha, 0x80 * (1.0f / 255)));
125  ASSERT_TRUE(ScalarNearlyEqual(converted_color.red, 0x40 * (1.0f / 255)));
126  ASSERT_TRUE(ScalarNearlyEqual(converted_color.green, 0xC0 * (1.0f / 255)));
127  ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
128 }
129 
130 TEST(SkiaConversionsTest, GradientStopConversion) {
131  // Typical gradient.
132  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
133  flutter::DlColor::kRed(),
134  flutter::DlColor::kGreen()};
135  std::vector<float> stops = {0.0, 0.5, 1.0};
136  const auto gradient =
137  flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
138  SkPoint::Make(1.0, 1.0), //
139  3, //
140  colors.data(), //
141  stops.data(), //
142  flutter::DlTileMode::kClamp, //
143  nullptr //
144  );
145 
146  std::vector<Color> converted_colors;
147  std::vector<Scalar> converted_stops;
148  skia_conversions::ConvertStops(gradient.get(), converted_colors,
149  converted_stops);
150 
151  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
152  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
153  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
154 }
155 
156 TEST(SkiaConversionsTest, GradientMissing0) {
157  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
158  flutter::DlColor::kRed()};
159  std::vector<float> stops = {0.5, 1.0};
160  const auto gradient =
161  flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
162  SkPoint::Make(1.0, 1.0), //
163  2, //
164  colors.data(), //
165  stops.data(), //
166  flutter::DlTileMode::kClamp, //
167  nullptr //
168  );
169 
170  std::vector<Color> converted_colors;
171  std::vector<Scalar> converted_stops;
172  skia_conversions::ConvertStops(gradient.get(), converted_colors,
173  converted_stops);
174 
175  // First color is inserted as blue.
176  ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
177  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
178  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
179  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
180 }
181 
182 TEST(SkiaConversionsTest, GradientMissingLastValue) {
183  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
184  flutter::DlColor::kRed()};
185  std::vector<float> stops = {0.0, .5};
186  const auto gradient =
187  flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
188  SkPoint::Make(1.0, 1.0), //
189  2, //
190  colors.data(), //
191  stops.data(), //
192  flutter::DlTileMode::kClamp, //
193  nullptr //
194  );
195 
196  std::vector<Color> converted_colors;
197  std::vector<Scalar> converted_stops;
198  skia_conversions::ConvertStops(gradient.get(), converted_colors,
199  converted_stops);
200 
201  // Last color is inserted as red.
202  ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
203  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
204  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
205  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
206 }
207 
208 TEST(SkiaConversionsTest, GradientStopGreaterThan1) {
209  std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
210  flutter::DlColor::kGreen(),
211  flutter::DlColor::kRed()};
212  std::vector<float> stops = {0.0, 100, 1.0};
213  const auto gradient =
214  flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
215  SkPoint::Make(1.0, 1.0), //
216  3, //
217  colors.data(), //
218  stops.data(), //
219  flutter::DlTileMode::kClamp, //
220  nullptr //
221  );
222 
223  std::vector<Color> converted_colors;
224  std::vector<Scalar> converted_stops;
225  skia_conversions::ConvertStops(gradient.get(), converted_colors,
226  converted_stops);
227 
228  // Value is clamped to 1.0
229  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
230  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
231  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
232 }
233 
234 TEST(SkiaConversionsTest, GradientConversionNonMonotonic) {
235  std::vector<flutter::DlColor> colors = {
236  flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
237  flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
238  std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
239  const auto gradient =
240  flutter::DlColorSource::MakeLinear(SkPoint::Make(0, 0), //
241  SkPoint::Make(1.0, 1.0), //
242  4, //
243  colors.data(), //
244  stops.data(), //
245  flutter::DlTileMode::kClamp, //
246  nullptr //
247  );
248 
249  std::vector<Color> converted_colors;
250  std::vector<Scalar> converted_stops;
251  skia_conversions::ConvertStops(gradient.get(), converted_colors,
252  converted_stops);
253 
254  // Value is clamped to 0.5
255  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
256  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
257  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
258  ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
259 }
260 
261 TEST(SkiaConversionsTest, IsNearlySimpleRRect) {
263  SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 10)));
265  SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9.999)));
267  SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9)));
269  SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 5)));
270  SkRect rect = SkRect::MakeLTRB(0, 0, 10, 10);
271  SkRRect rrect;
272  union {
273  SkPoint radii[4] = {
274  {10.0f, 9.0f},
275  {10.0f, 9.0f},
276  {10.0f, 9.0f},
277  {10.0f, 9.0f},
278  };
279  SkScalar values[8];
280  } test;
281  rrect.setRectRadii(rect, test.radii);
282  EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect));
283  for (int i = 0; i < 8; i++) {
284  auto save = test.values[i];
285  test.values[i] -= kEhCloseEnough * 0.5f;
286  rrect.setRectRadii(rect, test.radii);
287  EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect))
288  << "values[" << i << "] == " << test.values[i];
289  test.values[i] -= kEhCloseEnough * 2.0f;
290  rrect.setRectRadii(rect, test.radii);
291  EXPECT_FALSE(skia_conversions::IsNearlySimpleRRect(rrect))
292  << "values[" << i << "] == " << test.values[i];
293  test.values[i] = save;
294  }
295 }
296 
297 TEST(SkiaConversionsTest, BlendMode) {
298  for (auto i = 0; i < static_cast<int>(flutter::DlBlendMode::kLastMode); i++) {
299  EXPECT_EQ(
300  skia_conversions::ToBlendMode(static_cast<flutter::DlBlendMode>(i)),
301  static_cast<BlendMode>(i));
302  }
303 }
304 
305 } // namespace testing
306 } // namespace impeller
impeller::Matrix::m
Scalar m[16]
Definition: matrix.h:39
impeller::skia_conversions::IsNearlySimpleRRect
bool IsNearlySimpleRRect(const SkRRect &rr)
Like SkRRect.isSimple, but allows the corners to differ by kEhCloseEnough.
Definition: skia_conversions.cc:21
impeller::skia_conversions::ConvertStops
void ConvertStops(const flutter::DlGradientColorSourceBase *gradient, std::vector< Color > &colors, std::vector< float > &stops)
Convert display list colors + stops into impeller colors and stops, taking care to ensure that the st...
Definition: skia_conversions.cc:144
impeller::skia_conversions::ToSize
Size ToSize(const SkPoint &point)
Definition: skia_conversions.cc:102
impeller::BlendMode
BlendMode
Definition: color.h:58
impeller::skia_conversions::ToSamplerDescriptor
impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlImageSampling options)
Definition: skia_conversions.cc:169
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
impeller::Vector4
Definition: vector.h:232
impeller::skia_conversions::ToMatrix
Matrix ToMatrix(const SkMatrix &m)
Definition: skia_conversions.cc:193
formats.h
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:106
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::skia_conversions::ToBlendMode
BlendMode ToBlendMode(flutter::DlBlendMode mode)
Definition: skia_conversions.cc:204
impeller::Matrix::vec
Vector4 vec[4]
Definition: matrix.h:41
impeller::MinMagFilter::kNearest
@ kNearest
Select nearest to the sample point. Most widely supported.
impeller::ToSamplerDescriptor
static impeller::SamplerDescriptor ToSamplerDescriptor(const flutter::DlFilterMode options)
Definition: dl_dispatcher.cc:118
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
skia_conversions.h
impeller::MinMagFilter::kLinear
@ kLinear
impeller::Matrix::IsTranslationScaleOnly
constexpr bool IsTranslationScaleOnly() const
Returns true if the matrix has a scale-only basis and is non-projective. Note that an identity matrix...
Definition: matrix.h:397
impeller::skia_conversions::ToPoint
Point ToPoint(const SkPoint &point)
Definition: skia_conversions.cc:98
impeller::Matrix::IsIdentity
constexpr bool IsIdentity() const
Definition: matrix.h:384
scalar.h
impeller::MipFilter::kBase
@ kBase
The texture is sampled as if it only had a single mipmap level.
impeller::MipFilter::kLinear
@ kLinear
Sample from the two nearest mip levels and linearly interpolate.
impeller::ScalarNearlyEqual
constexpr bool ScalarNearlyEqual(Scalar x, Scalar y, Scalar tolerance=kEhCloseEnough)
Definition: scalar.h:35
color.h
color
DlColor color
Definition: dl_golden_blur_unittests.cc:24
impeller
Definition: allocation.cc:12
impeller::testing::TEST
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Definition: allocation_size_unittests.cc:10
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37