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