Flutter Impeller
skia_conversions.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 
6 #include "display_list/dl_color.h"
7 #include "third_party/skia/modules/skparagraph/include/Paragraph.h"
8 
9 namespace impeller {
10 namespace skia_conversions {
11 
12 bool IsNearlySimpleRRect(const SkRRect& rr) {
13  auto [a, b] = rr.radii(SkRRect::kUpperLeft_Corner);
14  auto [c, d] = rr.radii(SkRRect::kLowerLeft_Corner);
15  auto [e, f] = rr.radii(SkRRect::kUpperRight_Corner);
16  auto [g, h] = rr.radii(SkRRect::kLowerRight_Corner);
17  return SkScalarNearlyEqual(a, b, kEhCloseEnough) &&
18  SkScalarNearlyEqual(a, c, kEhCloseEnough) &&
19  SkScalarNearlyEqual(a, d, kEhCloseEnough) &&
20  SkScalarNearlyEqual(a, e, kEhCloseEnough) &&
21  SkScalarNearlyEqual(a, f, kEhCloseEnough) &&
22  SkScalarNearlyEqual(a, g, kEhCloseEnough) &&
23  SkScalarNearlyEqual(a, h, kEhCloseEnough);
24 }
25 
26 Rect ToRect(const SkRect& rect) {
27  return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
28 }
29 
30 std::optional<Rect> ToRect(const SkRect* rect) {
31  if (rect == nullptr) {
32  return std::nullopt;
33  }
34  return Rect::MakeLTRB(rect->fLeft, rect->fTop, rect->fRight, rect->fBottom);
35 }
36 
37 std::vector<Rect> ToRects(const SkRect tex[], int count) {
38  auto result = std::vector<Rect>();
39  for (int i = 0; i < count; i++) {
40  result.push_back(ToRect(tex[i]));
41  }
42  return result;
43 }
44 
45 std::vector<Point> ToPoints(const SkPoint points[], int count) {
46  std::vector<Point> result(count);
47  for (auto i = 0; i < count; i++) {
48  result[i] = ToPoint(points[i]);
49  }
50  return result;
51 }
52 
54  using Corner = SkRRect::Corner;
56  radii.bottom_left = ToPoint(rrect.radii(Corner::kLowerLeft_Corner));
57  radii.bottom_right = ToPoint(rrect.radii(Corner::kLowerRight_Corner));
58  radii.top_left = ToPoint(rrect.radii(Corner::kUpperLeft_Corner));
59  radii.top_right = ToPoint(rrect.radii(Corner::kUpperRight_Corner));
60  return radii;
61 }
62 
63 Path ToPath(const SkPath& path, Point shift) {
64  auto iterator = SkPath::Iter(path, false);
65 
66  struct PathData {
67  union {
68  SkPoint points[4];
69  };
70  };
71 
72  PathBuilder builder;
73  PathData data;
74  // Reserve a path size with some arbitrarily additional padding.
75  builder.Reserve(path.countPoints() + 8, path.countVerbs() + 8);
76  auto verb = SkPath::Verb::kDone_Verb;
77  do {
78  verb = iterator.next(data.points);
79  switch (verb) {
80  case SkPath::kMove_Verb:
81  builder.MoveTo(ToPoint(data.points[0]));
82  break;
83  case SkPath::kLine_Verb:
84  builder.LineTo(ToPoint(data.points[1]));
85  break;
86  case SkPath::kQuad_Verb:
87  builder.QuadraticCurveTo(ToPoint(data.points[1]),
88  ToPoint(data.points[2]));
89  break;
90  case SkPath::kConic_Verb: {
91  constexpr auto kPow2 = 1; // Only works for sweeps up to 90 degrees.
92  constexpr auto kQuadCount = 1 + (2 * (1 << kPow2));
93  SkPoint points[kQuadCount];
94  const auto curve_count =
95  SkPath::ConvertConicToQuads(data.points[0], //
96  data.points[1], //
97  data.points[2], //
98  iterator.conicWeight(), //
99  points, //
100  kPow2 //
101  );
102 
103  for (int curve_index = 0, point_index = 0; //
104  curve_index < curve_count; //
105  curve_index++, point_index += 2 //
106  ) {
107  builder.QuadraticCurveTo(ToPoint(points[point_index + 1]),
108  ToPoint(points[point_index + 2]));
109  }
110  } break;
111  case SkPath::kCubic_Verb:
112  builder.CubicCurveTo(ToPoint(data.points[1]), ToPoint(data.points[2]),
113  ToPoint(data.points[3]));
114  break;
115  case SkPath::kClose_Verb:
116  builder.Close();
117  break;
118  case SkPath::kDone_Verb:
119  break;
120  }
121  } while (verb != SkPath::Verb::kDone_Verb);
122 
123  FillType fill_type;
124  switch (path.getFillType()) {
125  case SkPathFillType::kWinding:
126  fill_type = FillType::kNonZero;
127  break;
128  case SkPathFillType::kEvenOdd:
129  fill_type = FillType::kOdd;
130  break;
131  case SkPathFillType::kInverseWinding:
132  case SkPathFillType::kInverseEvenOdd:
133  // Flutter doesn't expose these path fill types. These are only visible
134  // via the receiver interface. We should never get here.
135  fill_type = FillType::kNonZero;
136  break;
137  }
138  builder.SetConvexity(path.isConvex() ? Convexity::kConvex
140  builder.Shift(shift);
141  auto sk_bounds = path.getBounds().makeOutset(shift.x, shift.y);
142  builder.SetBounds(ToRect(sk_bounds));
143  return builder.TakePath(fill_type);
144 }
145 
146 Path ToPath(const SkRRect& rrect) {
147  return PathBuilder{}
148  .AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
150  .SetBounds(ToRect(rrect.getBounds()))
151  .TakePath();
152 }
153 
154 Point ToPoint(const SkPoint& point) {
155  return Point::MakeXY(point.fX, point.fY);
156 }
157 
158 Size ToSize(const SkPoint& point) {
159  return Size(point.fX, point.fY);
160 }
161 
162 Color ToColor(const flutter::DlColor& color) {
163  return {
164  static_cast<Scalar>(color.getRedF()), //
165  static_cast<Scalar>(color.getGreenF()), //
166  static_cast<Scalar>(color.getBlueF()), //
167  static_cast<Scalar>(color.getAlphaF()) //
168  };
169 }
170 
171 std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count) {
172  auto result = std::vector<Matrix>();
173  for (int i = 0; i < count; i++) {
174  auto form = xform[i];
175  // clang-format off
176  auto matrix = Matrix{
177  form.fSCos, form.fSSin, 0, 0,
178  -form.fSSin, form.fSCos, 0, 0,
179  0, 0, 1, 0,
180  form.fTx, form.fTy, 0, 1
181  };
182  // clang-format on
183  result.push_back(matrix);
184  }
185  return result;
186 }
187 
188 Path PathDataFromTextBlob(const sk_sp<SkTextBlob>& blob, Point shift) {
189  if (!blob) {
190  return {};
191  }
192 
193  return ToPath(skia::textlayout::Paragraph::GetPath(blob.get()), shift);
194 }
195 
196 std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type) {
197  switch (type) {
198  case kRGBA_8888_SkColorType:
200  case kBGRA_8888_SkColorType:
202  case kRGBA_F16_SkColorType:
204  case kBGR_101010x_XR_SkColorType:
206  default:
207  return std::nullopt;
208  }
209  return std::nullopt;
210 }
211 
212 void ConvertStops(const flutter::DlGradientColorSourceBase* gradient,
213  std::vector<Color>& colors,
214  std::vector<float>& stops) {
215  FML_DCHECK(gradient->stop_count() >= 2);
216 
217  auto* dl_colors = gradient->colors();
218  auto* dl_stops = gradient->stops();
219  if (dl_stops[0] != 0.0) {
220  colors.emplace_back(skia_conversions::ToColor(dl_colors[0]));
221  stops.emplace_back(0);
222  }
223  for (auto i = 0; i < gradient->stop_count(); i++) {
224  colors.emplace_back(skia_conversions::ToColor(dl_colors[i]));
225  stops.emplace_back(std::clamp(dl_stops[i], 0.0f, 1.0f));
226  }
227  if (dl_stops[gradient->stop_count() - 1] != 1.0) {
228  colors.emplace_back(colors.back());
229  stops.emplace_back(1.0);
230  }
231  for (auto i = 1; i < gradient->stop_count(); i++) {
232  stops[i] = std::clamp(stops[i], stops[i - 1], stops[i]);
233  }
234 }
235 
236 } // namespace skia_conversions
237 } // namespace impeller
impeller::skia_conversions::PathDataFromTextBlob
Path PathDataFromTextBlob(const sk_sp< SkTextBlob > &blob, Point shift)
Definition: skia_conversions.cc:188
impeller::skia_conversions::ToPoints
std::vector< Point > ToPoints(const SkPoint points[], int count)
Definition: skia_conversions.cc:45
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::skia_conversions::IsNearlySimpleRRect
bool IsNearlySimpleRRect(const SkRRect &rr)
Like SkRRect.isSimple, but allows the corners to differ by kEhCloseEnough.
Definition: skia_conversions.cc:12
impeller::skia_conversions::ToPixelFormat
std::optional< impeller::PixelFormat > ToPixelFormat(SkColorType type)
Definition: skia_conversions.cc:196
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:212
impeller::FillType::kOdd
@ kOdd
impeller::skia_conversions::ToSize
Size ToSize(const SkPoint &point)
Definition: skia_conversions.cc:158
impeller::Color
Definition: color.h:124
impeller::PathBuilder::SetBounds
PathBuilder & SetBounds(Rect bounds)
Set the bounding box that will be used by Path.GetBoundingBox in place of performing the computation.
Definition: path_builder.cc:458
impeller::kEhCloseEnough
constexpr float kEhCloseEnough
Definition: constants.h:56
data
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::PathBuilder::CubicCurveTo
PathBuilder & CubicCurveTo(Point controlPoint1, Point controlPoint2, Point point, bool relative=false)
Insert a cubic curve from the curren position to point using the control points controlPoint1 and con...
Definition: path_builder.cc:90
impeller::PathBuilder
Definition: path_builder.h:14
impeller::skia_conversions::ToRects
std::vector< Rect > ToRects(const SkRect tex[], int count)
Definition: skia_conversions.cc:37
impeller::skia_conversions::ToColor
Color ToColor(const flutter::DlColor &color)
Definition: skia_conversions.cc:162
impeller::PathBuilder::AddRoundedRect
PathBuilder & AddRoundedRect(Rect rect, RoundingRadii radii)
Definition: path_builder.cc:150
impeller::Size
TSize< Scalar > Size
Definition: size.h:137
impeller::PathBuilder::SetConvexity
PathBuilder & SetConvexity(Convexity value)
Definition: path_builder.cc:85
impeller::PathBuilder::RoundingRadii::bottom_right
Point bottom_right
Definition: path_builder.h:109
impeller::skia_conversions::ToRect
Rect ToRect(const SkRect &rect)
Definition: skia_conversions.cc:26
impeller::PathBuilder::RoundingRadii
Definition: path_builder.h:105
impeller::Convexity::kUnknown
@ kUnknown
impeller::TSize< Scalar >
impeller::skia_conversions::ToRoundingRadii
PathBuilder::RoundingRadii ToRoundingRadii(const SkRRect &rrect)
Definition: skia_conversions.cc:53
impeller::PathBuilder::Shift
PathBuilder & Shift(Point offset)
Transform the existing path segments and contours by the given offset.
Definition: path_builder.cc:447
skia_conversions.h
impeller::PathBuilder::QuadraticCurveTo
PathBuilder & QuadraticCurveTo(Point controlPoint, Point point, bool relative=false)
Insert a quadradic curve from the current position to point using the control point controlPoint.
Definition: path_builder.cc:75
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:52
impeller::PixelFormat::kB10G10R10XR
@ kB10G10R10XR
impeller::PathBuilder::LineTo
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
Definition: path_builder.cc:52
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::PathBuilder::RoundingRadii::top_left
Point top_left
Definition: path_builder.h:106
impeller::FillType
FillType
Definition: path.h:30
impeller::PixelFormat::kR16G16B16A16Float
@ kR16G16B16A16Float
impeller::PathBuilder::TakePath
Path TakePath(FillType fill=FillType::kNonZero)
Definition: path_builder.cc:22
impeller::skia_conversions::ToPoint
Point ToPoint(const SkPoint &point)
Definition: skia_conversions.cc:154
impeller::FillType::kNonZero
@ kNonZero
impeller::TPoint::x
Type x
Definition: point.h:30
impeller::PathBuilder::Reserve
void Reserve(size_t point_size, size_t verb_size)
Reserve [point_size] points and [verb_size] verbs in the underlying path buffer.
Definition: path_builder.cc:28
impeller::PathBuilder::Close
PathBuilder & Close()
Definition: path_builder.cc:40
impeller::PathBuilder::RoundingRadii::top_right
Point top_right
Definition: path_builder.h:108
impeller::TPoint
Definition: point.h:27
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::PathBuilder::MoveTo
PathBuilder & MoveTo(Point point, bool relative=false)
Definition: path_builder.cc:33
impeller::skia_conversions::ToRSXForms
std::vector< Matrix > ToRSXForms(const SkRSXform xform[], int count)
Definition: skia_conversions.cc:171
impeller::PathBuilder::RoundingRadii::bottom_left
Point bottom_left
Definition: path_builder.h:107
color
DlColor color
Definition: dl_golden_blur_unittests.cc:23
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::Convexity::kConvex
@ kConvex
impeller::PixelFormat::kB8G8R8A8UNormInt
@ kB8G8R8A8UNormInt
impeller
Definition: aiks_blend_unittests.cc:18
impeller::skia_conversions::ToPath
Path ToPath(const SkPath &path, Point shift)
Definition: skia_conversions.cc:63
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::TPoint< Scalar >::MakeXY
static constexpr TPoint< Type > MakeXY(Type x, Type y)
Definition: point.h:46