Move Skia conversion utilities to own TU (flutter/engine#40997)

Move Skia conversion utilities to own TU
This commit is contained in:
Dan Field 2023-04-10 09:46:04 -07:00 committed by GitHub
parent 418c28e09a
commit e92e4daa76
8 changed files with 291 additions and 207 deletions

View File

@ -1152,6 +1152,8 @@ ORIGIN: ../../../flutter/impeller/display_list/display_list_vertices_geometry.cc
ORIGIN: ../../../flutter/impeller/display_list/display_list_vertices_geometry.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/display_list/nine_patch_converter.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/display_list/nine_patch_converter.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/display_list/skia_conversions.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/display_list/skia_conversions.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/anonymous_contents.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/anonymous_contents.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/entity/contents/atlas_contents.cc + ../../../flutter/LICENSE
@ -3732,6 +3734,8 @@ FILE: ../../../flutter/impeller/display_list/display_list_vertices_geometry.cc
FILE: ../../../flutter/impeller/display_list/display_list_vertices_geometry.h
FILE: ../../../flutter/impeller/display_list/nine_patch_converter.cc
FILE: ../../../flutter/impeller/display_list/nine_patch_converter.h
FILE: ../../../flutter/impeller/display_list/skia_conversions.cc
FILE: ../../../flutter/impeller/display_list/skia_conversions.h
FILE: ../../../flutter/impeller/entity/contents/anonymous_contents.cc
FILE: ../../../flutter/impeller/entity/contents/anonymous_contents.h
FILE: ../../../flutter/impeller/entity/contents/atlas_contents.cc

View File

@ -4,6 +4,20 @@
import("//flutter/impeller/tools/impeller.gni")
impeller_component("skia_conversions") {
sources = [
"skia_conversions.cc",
"skia_conversions.h",
]
public_deps = [
"../core",
"../geometry",
"//flutter/fml",
"//third_party/skia",
]
}
impeller_component("display_list") {
sources = [
"display_list_dispatcher.cc",
@ -17,6 +31,7 @@ impeller_component("display_list") {
]
public_deps = [
":skia_conversions",
"../aiks",
"//flutter/display_list",
"//flutter/fml",

View File

@ -18,6 +18,7 @@
#include "impeller/display_list/display_list_image_impeller.h"
#include "impeller/display_list/display_list_vertices_geometry.h"
#include "impeller/display_list/nine_patch_converter.h"
#include "impeller/display_list/skia_conversions.h"
#include "impeller/entity/contents/conical_gradient_contents.h"
#include "impeller/entity/contents/filters/filter_contents.h"
#include "impeller/entity/contents/filters/inputs/filter_input.h"
@ -35,8 +36,6 @@
#include "impeller/geometry/sigma.h"
#include "impeller/typographer/backends/skia/text_frame_skia.h"
#include "third_party/skia/include/core/SkColor.h"
namespace impeller {
#define UNIMPLEMENTED \
@ -252,43 +251,13 @@ void DisplayListDispatcher::setStrokeJoin(flutter::DlStrokeJoin join) {
}
}
static Point ToPoint(const SkPoint& point) {
return Point::MakeXY(point.fX, point.fY);
}
static Color ToColor(const SkColor& color) {
return {
static_cast<Scalar>(SkColorGetR(color) / 255.0), //
static_cast<Scalar>(SkColorGetG(color) / 255.0), //
static_cast<Scalar>(SkColorGetB(color) / 255.0), //
static_cast<Scalar>(SkColorGetA(color) / 255.0) //
};
}
static std::vector<Color> ToColors(const flutter::DlColor colors[], int count) {
auto result = std::vector<Color>();
if (colors == nullptr) {
return result;
}
for (int i = 0; i < count; i++) {
result.push_back(ToColor(colors[i]));
}
return result;
}
static std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count) {
auto result = std::vector<Matrix>();
for (int i = 0; i < count; i++) {
auto form = xform[i];
// clang-format off
auto matrix = Matrix{
form.fSCos, form.fSSin, 0, 0,
-form.fSSin, form.fSCos, 0, 0,
0, 0, 1, 0,
form.fTx, form.fTy, 0, 1
};
// clang-format on
result.push_back(matrix);
result.push_back(skia_conversions::ToColor(colors[i]));
}
return result;
}
@ -304,11 +273,11 @@ static void ConvertStops(T* gradient,
auto* dl_colors = gradient->colors();
auto* dl_stops = gradient->stops();
if (dl_stops[0] != 0.0) {
colors->emplace_back(ToColor(dl_colors[0]));
colors->emplace_back(skia_conversions::ToColor(dl_colors[0]));
stops->emplace_back(0);
}
for (auto i = 0; i < gradient->stop_count(); i++) {
colors->emplace_back(ToColor(dl_colors[i]));
colors->emplace_back(skia_conversions::ToColor(dl_colors[i]));
stops->emplace_back(dl_stops[i]);
}
if (stops->back() != 1.0) {
@ -374,8 +343,8 @@ void DisplayListDispatcher::setColorSource(
const flutter::DlLinearGradientColorSource* linear =
source->asLinearGradient();
FML_DCHECK(linear);
auto start_point = ToPoint(linear->start_point());
auto end_point = ToPoint(linear->end_point());
auto start_point = skia_conversions::ToPoint(linear->start_point());
auto end_point = skia_conversions::ToPoint(linear->end_point());
std::vector<Color> colors;
std::vector<float> stops;
ConvertStops(linear, &colors, &stops);
@ -405,9 +374,10 @@ void DisplayListDispatcher::setColorSource(
const flutter::DlConicalGradientColorSource* conical_gradient =
source->asConicalGradient();
FML_DCHECK(conical_gradient);
Point center = ToPoint(conical_gradient->end_center());
Point center = skia_conversions::ToPoint(conical_gradient->end_center());
SkScalar radius = conical_gradient->end_radius();
Point focus_center = ToPoint(conical_gradient->start_center());
Point focus_center =
skia_conversions::ToPoint(conical_gradient->start_center());
SkScalar focus_radius = conical_gradient->start_radius();
std::vector<Color> colors;
std::vector<float> stops;
@ -442,7 +412,7 @@ void DisplayListDispatcher::setColorSource(
const flutter::DlRadialGradientColorSource* radialGradient =
source->asRadialGradient();
FML_DCHECK(radialGradient);
auto center = ToPoint(radialGradient->center());
auto center = skia_conversions::ToPoint(radialGradient->center());
auto radius = radialGradient->radius();
std::vector<Color> colors;
std::vector<float> stops;
@ -475,7 +445,7 @@ void DisplayListDispatcher::setColorSource(
source->asSweepGradient();
FML_DCHECK(sweepGradient);
auto center = ToPoint(sweepGradient->center());
auto center = skia_conversions::ToPoint(sweepGradient->center());
auto start_angle = Degrees(sweepGradient->start());
auto end_angle = Degrees(sweepGradient->end());
std::vector<Color> colors;
@ -586,7 +556,7 @@ static std::optional<Paint::ColorFilterProc> ToColorFilterProc(
case flutter::DlColorFilterType::kBlend: {
auto dl_blend = filter->asBlend();
auto blend_mode = ToBlendMode(dl_blend->mode());
auto color = ToColor(dl_blend->color());
auto color = skia_conversions::ToColor(dl_blend->color());
return [blend_mode, color](FilterInput::Ref input) {
return ColorFilterContents::MakeBlend(blend_mode, {std::move(input)},
color);
@ -814,27 +784,13 @@ void DisplayListDispatcher::save() {
canvas_.Save();
}
static std::optional<Rect> ToRect(const SkRect* rect) {
if (rect == nullptr) {
return std::nullopt;
}
return Rect::MakeLTRB(rect->fLeft, rect->fTop, rect->fRight, rect->fBottom);
}
static std::vector<Rect> ToRects(const SkRect tex[], int count) {
auto result = std::vector<Rect>();
for (int i = 0; i < count; i++) {
result.push_back(ToRect(&tex[i]).value());
}
return result;
}
// |flutter::DlOpReceiver|
void DisplayListDispatcher::saveLayer(const SkRect* bounds,
const flutter::SaveLayerOptions options,
const flutter::DlImageFilter* backdrop) {
auto paint = options.renders_with_attributes() ? paint_ : Paint{};
canvas_.SaveLayer(paint, ToRect(bounds), ToImageFilterProc(backdrop));
canvas_.SaveLayer(paint, skia_conversions::ToRect(bounds),
ToImageFilterProc(backdrop));
}
// |flutter::DlOpReceiver|
@ -915,10 +871,6 @@ void DisplayListDispatcher::transformReset() {
canvas_.Transform(initial_matrix_);
}
static Rect ToRect(const SkRect& rect) {
return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
}
static Entity::ClipOperation ToClipOperation(
flutter::DlCanvas::ClipOp clip_op) {
switch (clip_op) {
@ -933,99 +885,7 @@ static Entity::ClipOperation ToClipOperation(
void DisplayListDispatcher::clipRect(const SkRect& rect,
ClipOp clip_op,
bool is_aa) {
canvas_.ClipRect(ToRect(rect), ToClipOperation(clip_op));
}
static PathBuilder::RoundingRadii ToRoundingRadii(const SkRRect& rrect) {
using Corner = SkRRect::Corner;
PathBuilder::RoundingRadii radii;
radii.bottom_left = ToPoint(rrect.radii(Corner::kLowerLeft_Corner));
radii.bottom_right = ToPoint(rrect.radii(Corner::kLowerRight_Corner));
radii.top_left = ToPoint(rrect.radii(Corner::kUpperLeft_Corner));
radii.top_right = ToPoint(rrect.radii(Corner::kUpperRight_Corner));
return radii;
}
static Path ToPath(const SkPath& path) {
auto iterator = SkPath::Iter(path, false);
struct PathData {
union {
SkPoint points[4];
};
};
PathBuilder builder;
PathData data;
auto verb = SkPath::Verb::kDone_Verb;
do {
verb = iterator.next(data.points);
switch (verb) {
case SkPath::kMove_Verb:
builder.MoveTo(ToPoint(data.points[0]));
break;
case SkPath::kLine_Verb:
builder.LineTo(ToPoint(data.points[1]));
break;
case SkPath::kQuad_Verb:
builder.QuadraticCurveTo(ToPoint(data.points[1]),
ToPoint(data.points[2]));
break;
case SkPath::kConic_Verb: {
constexpr auto kPow2 = 1; // Only works for sweeps up to 90 degrees.
constexpr auto kQuadCount = 1 + (2 * (1 << kPow2));
SkPoint points[kQuadCount];
const auto curve_count =
SkPath::ConvertConicToQuads(data.points[0], //
data.points[1], //
data.points[2], //
iterator.conicWeight(), //
points, //
kPow2 //
);
for (int curve_index = 0, point_index = 0; //
curve_index < curve_count; //
curve_index++, point_index += 2 //
) {
builder.QuadraticCurveTo(ToPoint(points[point_index + 1]),
ToPoint(points[point_index + 2]));
}
} break;
case SkPath::kCubic_Verb:
builder.CubicCurveTo(ToPoint(data.points[1]), ToPoint(data.points[2]),
ToPoint(data.points[3]));
break;
case SkPath::kClose_Verb:
builder.Close();
break;
case SkPath::kDone_Verb:
break;
}
} while (verb != SkPath::Verb::kDone_Verb);
FillType fill_type;
switch (path.getFillType()) {
case SkPathFillType::kWinding:
fill_type = FillType::kNonZero;
break;
case SkPathFillType::kEvenOdd:
fill_type = FillType::kOdd;
break;
case SkPathFillType::kInverseWinding:
case SkPathFillType::kInverseEvenOdd:
// Flutter doesn't expose these path fill types. These are only visible
// via the receiver interface. We should never get here.
fill_type = FillType::kNonZero;
break;
}
return builder.TakePath(fill_type);
}
static Path ToPath(const SkRRect& rrect) {
return PathBuilder{}
.AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
.TakePath();
canvas_.ClipRect(skia_conversions::ToRect(rect), ToClipOperation(clip_op));
}
// |flutter::DlOpReceiver|
@ -1033,10 +893,10 @@ void DisplayListDispatcher::clipRRect(const SkRRect& rrect,
ClipOp clip_op,
bool is_aa) {
if (rrect.isSimple()) {
canvas_.ClipRRect(ToRect(rrect.rect()), rrect.getSimpleRadii().fX,
ToClipOperation(clip_op));
canvas_.ClipRRect(skia_conversions::ToRect(rrect.rect()),
rrect.getSimpleRadii().fX, ToClipOperation(clip_op));
} else {
canvas_.ClipPath(ToPath(rrect), ToClipOperation(clip_op));
canvas_.ClipPath(skia_conversions::ToPath(rrect), ToClipOperation(clip_op));
}
}
@ -1044,14 +904,14 @@ void DisplayListDispatcher::clipRRect(const SkRRect& rrect,
void DisplayListDispatcher::clipPath(const SkPath& path,
ClipOp clip_op,
bool is_aa) {
canvas_.ClipPath(ToPath(path), ToClipOperation(clip_op));
canvas_.ClipPath(skia_conversions::ToPath(path), ToClipOperation(clip_op));
}
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawColor(flutter::DlColor color,
flutter::DlBlendMode dl_mode) {
Paint paint;
paint.color = ToColor(color);
paint.color = skia_conversions::ToColor(color);
paint.blend_mode = ToBlendMode(dl_mode);
canvas_.DrawPaint(paint);
}
@ -1063,7 +923,10 @@ void DisplayListDispatcher::drawPaint() {
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
auto path = PathBuilder{}.AddLine(ToPoint(p0), ToPoint(p1)).TakePath();
auto path =
PathBuilder{}
.AddLine(skia_conversions::ToPoint(p0), skia_conversions::ToPoint(p1))
.TakePath();
Paint paint = paint_;
paint.style = Paint::Style::kStroke;
canvas_.DrawPath(path, paint);
@ -1071,30 +934,33 @@ void DisplayListDispatcher::drawLine(const SkPoint& p0, const SkPoint& p1) {
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawRect(const SkRect& rect) {
canvas_.DrawRect(ToRect(rect), paint_);
canvas_.DrawRect(skia_conversions::ToRect(rect), paint_);
}
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawOval(const SkRect& bounds) {
if (bounds.width() == bounds.height()) {
canvas_.DrawCircle(ToPoint(bounds.center()), bounds.width() * 0.5, paint_);
canvas_.DrawCircle(skia_conversions::ToPoint(bounds.center()),
bounds.width() * 0.5, paint_);
} else {
auto path = PathBuilder{}.AddOval(ToRect(bounds)).TakePath();
auto path =
PathBuilder{}.AddOval(skia_conversions::ToRect(bounds)).TakePath();
canvas_.DrawPath(path, paint_);
}
}
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawCircle(const SkPoint& center, SkScalar radius) {
canvas_.DrawCircle(ToPoint(center), radius, paint_);
canvas_.DrawCircle(skia_conversions::ToPoint(center), radius, paint_);
}
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawRRect(const SkRRect& rrect) {
if (rrect.isSimple()) {
canvas_.DrawRRect(ToRect(rrect.rect()), rrect.getSimpleRadii().fX, paint_);
canvas_.DrawRRect(skia_conversions::ToRect(rrect.rect()),
rrect.getSimpleRadii().fX, paint_);
} else {
canvas_.DrawPath(ToPath(rrect), paint_);
canvas_.DrawPath(skia_conversions::ToPath(rrect), paint_);
}
}
@ -1102,14 +968,14 @@ void DisplayListDispatcher::drawRRect(const SkRRect& rrect) {
void DisplayListDispatcher::drawDRRect(const SkRRect& outer,
const SkRRect& inner) {
PathBuilder builder;
builder.AddPath(ToPath(outer));
builder.AddPath(ToPath(inner));
builder.AddPath(skia_conversions::ToPath(outer));
builder.AddPath(skia_conversions::ToPath(inner));
canvas_.DrawPath(builder.TakePath(FillType::kOdd), paint_);
}
// |flutter::DlOpReceiver|
void DisplayListDispatcher::drawPath(const SkPath& path) {
canvas_.DrawPath(ToPath(path), paint_);
canvas_.DrawPath(skia_conversions::ToPath(path), paint_);
}
// |flutter::DlOpReceiver|
@ -1118,7 +984,7 @@ void DisplayListDispatcher::drawArc(const SkRect& oval_bounds,
SkScalar sweep_degrees,
bool use_center) {
PathBuilder builder;
builder.AddArc(ToRect(oval_bounds), Degrees(start_degrees),
builder.AddArc(skia_conversions::ToRect(oval_bounds), Degrees(start_degrees),
Degrees(sweep_degrees), use_center);
canvas_.DrawPath(builder.TakePath(), paint_);
}
@ -1135,24 +1001,24 @@ void DisplayListDispatcher::drawPoints(PointMode mode,
paint.stroke_cap = Cap::kSquare;
}
for (uint32_t i = 0; i < count; i++) {
Point p0 = ToPoint(points[i]);
Point p0 = skia_conversions::ToPoint(points[i]);
auto path = PathBuilder{}.AddLine(p0, p0).TakePath();
canvas_.DrawPath(path, paint);
}
break;
case flutter::DlCanvas::PointMode::kLines:
for (uint32_t i = 1; i < count; i += 2) {
Point p0 = ToPoint(points[i - 1]);
Point p1 = ToPoint(points[i]);
Point p0 = skia_conversions::ToPoint(points[i - 1]);
Point p1 = skia_conversions::ToPoint(points[i]);
auto path = PathBuilder{}.AddLine(p0, p1).TakePath();
canvas_.DrawPath(path, paint);
}
break;
case flutter::DlCanvas::PointMode::kPolygon:
if (count > 1) {
Point p0 = ToPoint(points[0]);
Point p0 = skia_conversions::ToPoint(points[0]);
for (uint32_t i = 1; i < count; i++) {
Point p1 = ToPoint(points[i]);
Point p1 = skia_conversions::ToPoint(points[i]);
auto path = PathBuilder{}.AddLine(p0, p1).TakePath();
canvas_.DrawPath(path, paint);
p0 = p1;
@ -1207,8 +1073,8 @@ void DisplayListDispatcher::drawImageRect(
SrcRectConstraint constraint = SrcRectConstraint::kFast) {
canvas_.DrawImageRect(
std::make_shared<Image>(image->impeller_texture()), // image
ToRect(src), // source rect
ToRect(dst), // destination rect
skia_conversions::ToRect(src), // source rect
skia_conversions::ToRect(dst), // destination rect
render_with_attributes ? paint_ : Paint(), // paint
ToSamplerDescriptor(sampling) // sampling
);
@ -1224,7 +1090,8 @@ void DisplayListDispatcher::drawImageNine(const sk_sp<flutter::DlImage> image,
converter.DrawNinePatch(
std::make_shared<Image>(image->impeller_texture()),
Rect::MakeLTRB(center.fLeft, center.fTop, center.fRight, center.fBottom),
ToRect(dst), ToSamplerDescriptor(filter), &canvas_, &paint_);
skia_conversions::ToRect(dst), ToSamplerDescriptor(filter), &canvas_,
&paint_);
}
// |flutter::DlOpReceiver|
@ -1238,9 +1105,11 @@ void DisplayListDispatcher::drawAtlas(const sk_sp<flutter::DlImage> atlas,
const SkRect* cull_rect,
bool render_with_attributes) {
canvas_.DrawAtlas(std::make_shared<Image>(atlas->impeller_texture()),
ToRSXForms(xform, count), ToRects(tex, count),
skia_conversions::ToRSXForms(xform, count),
skia_conversions::ToRects(tex, count),
ToColors(colors, count), ToBlendMode(mode),
ToSamplerDescriptor(sampling), ToRect(cull_rect), paint_);
ToSamplerDescriptor(sampling),
skia_conversions::ToRect(cull_rect), paint_);
}
// |flutter::DlOpReceiver|
@ -1296,7 +1165,7 @@ void DisplayListDispatcher::drawShadow(const SkPath& path,
const SkScalar elevation,
bool transparent_occluder,
SkScalar dpr) {
Color spot_color = ToColor(color);
Color spot_color = skia_conversions::ToColor(color);
spot_color.alpha *= 0.25;
// Compute the spot color -- ported from SkShadowUtils::ComputeTonalColors.
@ -1348,13 +1217,15 @@ void DisplayListDispatcher::drawShadow(const SkPath& path,
SkRRect rrect;
SkRect oval;
if (path.isRect(&rect)) {
canvas_.DrawRect(ToRect(rect), paint);
canvas_.DrawRect(skia_conversions::ToRect(rect), paint);
} else if (path.isRRect(&rrect) && rrect.isSimple()) {
canvas_.DrawRRect(ToRect(rrect.rect()), rrect.getSimpleRadii().fX, paint);
canvas_.DrawRRect(skia_conversions::ToRect(rrect.rect()),
rrect.getSimpleRadii().fX, paint);
} else if (path.isOval(&oval) && oval.width() == oval.height()) {
canvas_.DrawCircle(ToPoint(oval.center()), oval.width() * 0.5, paint);
canvas_.DrawCircle(skia_conversions::ToPoint(oval.center()),
oval.width() * 0.5, paint);
} else {
canvas_.DrawPath(ToPath(path), paint);
canvas_.DrawPath(skia_conversions::ToPath(path), paint);
}
canvas_.Restore();

View File

@ -0,0 +1,168 @@
// 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 "impeller/display_list/skia_conversions.h"
namespace impeller {
namespace skia_conversions {
Rect ToRect(const SkRect& rect) {
return Rect::MakeLTRB(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
}
std::optional<Rect> ToRect(const SkRect* rect) {
if (rect == nullptr) {
return std::nullopt;
}
return Rect::MakeLTRB(rect->fLeft, rect->fTop, rect->fRight, rect->fBottom);
}
std::vector<Rect> ToRects(const SkRect tex[], int count) {
auto result = std::vector<Rect>();
for (int i = 0; i < count; i++) {
result.push_back(ToRect(&tex[i]).value());
}
return result;
}
PathBuilder::RoundingRadii ToRoundingRadii(const SkRRect& rrect) {
using Corner = SkRRect::Corner;
PathBuilder::RoundingRadii radii;
radii.bottom_left = ToPoint(rrect.radii(Corner::kLowerLeft_Corner));
radii.bottom_right = ToPoint(rrect.radii(Corner::kLowerRight_Corner));
radii.top_left = ToPoint(rrect.radii(Corner::kUpperLeft_Corner));
radii.top_right = ToPoint(rrect.radii(Corner::kUpperRight_Corner));
return radii;
}
Path ToPath(const SkPath& path) {
auto iterator = SkPath::Iter(path, false);
struct PathData {
union {
SkPoint points[4];
};
};
PathBuilder builder;
PathData data;
auto verb = SkPath::Verb::kDone_Verb;
do {
verb = iterator.next(data.points);
switch (verb) {
case SkPath::kMove_Verb:
builder.MoveTo(ToPoint(data.points[0]));
break;
case SkPath::kLine_Verb:
builder.LineTo(ToPoint(data.points[1]));
break;
case SkPath::kQuad_Verb:
builder.QuadraticCurveTo(ToPoint(data.points[1]),
ToPoint(data.points[2]));
break;
case SkPath::kConic_Verb: {
constexpr auto kPow2 = 1; // Only works for sweeps up to 90 degrees.
constexpr auto kQuadCount = 1 + (2 * (1 << kPow2));
SkPoint points[kQuadCount];
const auto curve_count =
SkPath::ConvertConicToQuads(data.points[0], //
data.points[1], //
data.points[2], //
iterator.conicWeight(), //
points, //
kPow2 //
);
for (int curve_index = 0, point_index = 0; //
curve_index < curve_count; //
curve_index++, point_index += 2 //
) {
builder.QuadraticCurveTo(ToPoint(points[point_index + 1]),
ToPoint(points[point_index + 2]));
}
} break;
case SkPath::kCubic_Verb:
builder.CubicCurveTo(ToPoint(data.points[1]), ToPoint(data.points[2]),
ToPoint(data.points[3]));
break;
case SkPath::kClose_Verb:
builder.Close();
break;
case SkPath::kDone_Verb:
break;
}
} while (verb != SkPath::Verb::kDone_Verb);
FillType fill_type;
switch (path.getFillType()) {
case SkPathFillType::kWinding:
fill_type = FillType::kNonZero;
break;
case SkPathFillType::kEvenOdd:
fill_type = FillType::kOdd;
break;
case SkPathFillType::kInverseWinding:
case SkPathFillType::kInverseEvenOdd:
// Flutter doesn't expose these path fill types. These are only visible
// via the receiver interface. We should never get here.
fill_type = FillType::kNonZero;
break;
}
return builder.TakePath(fill_type);
}
Path ToPath(const SkRRect& rrect) {
return PathBuilder{}
.AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
.TakePath();
}
Point ToPoint(const SkPoint& point) {
return Point::MakeXY(point.fX, point.fY);
}
Color ToColor(const SkColor& color) {
return {
static_cast<Scalar>(SkColorGetR(color) / 255.0), //
static_cast<Scalar>(SkColorGetG(color) / 255.0), //
static_cast<Scalar>(SkColorGetB(color) / 255.0), //
static_cast<Scalar>(SkColorGetA(color) / 255.0) //
};
}
std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count) {
auto result = std::vector<Matrix>();
for (int i = 0; i < count; i++) {
auto form = xform[i];
// clang-format off
auto matrix = Matrix{
form.fSCos, form.fSSin, 0, 0,
-form.fSSin, form.fSCos, 0, 0,
0, 0, 1, 0,
form.fTx, form.fTy, 0, 1
};
// clang-format on
result.push_back(matrix);
}
return result;
}
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type) {
switch (type) {
case kRGBA_8888_SkColorType:
return impeller::PixelFormat::kR8G8B8A8UNormInt;
case kBGRA_8888_SkColorType:
return impeller::PixelFormat::kB8G8R8A8UNormInt;
case kRGBA_F16_SkColorType:
return impeller::PixelFormat::kR16G16B16A16Float;
case kBGR_101010x_XR_SkColorType:
return impeller::PixelFormat::kB10G10R10XR;
default:
return std::nullopt;
}
return std::nullopt;
}
} // namespace skia_conversions
} // namespace impeller

View File

@ -0,0 +1,35 @@
// 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.
#pragma once
#include "impeller/core/formats.h"
#include "impeller/geometry/color.h"
#include "impeller/geometry/path.h"
#include "impeller/geometry/path_builder.h"
#include "impeller/geometry/point.h"
#include "impeller/geometry/rect.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkColorType.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPoint.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRSXform.h"
namespace impeller {
namespace skia_conversions {
Rect ToRect(const SkRect& rect);
std::optional<Rect> ToRect(const SkRect* rect);
std::vector<Rect> ToRects(const SkRect tex[], int count);
Point ToPoint(const SkPoint& point);
Color ToColor(const SkColor& color);
std::vector<Matrix> ToRSXForms(const SkRSXform xform[], int count);
PathBuilder::RoundingRadii ToRoundingRadii(const SkRRect& rrect);
Path ToPath(const SkPath& path);
Path ToPath(const SkRRect& rrect);
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type);
} // namespace skia_conversions
} // namespace impeller

View File

@ -19,7 +19,7 @@ class PathBuilder {
/// the angle. However, accuracy rapidly diminishes if magnified for obtuse
/// angle arcs, and so multiple cubic curves should be used when approximating
/// arcs greater than 90 degrees.
constexpr static const Scalar kArcApproximationMagic = 0.551915024494;
constexpr static const Scalar kArcApproximationMagic = 0.551915024494f;
PathBuilder();

View File

@ -193,7 +193,10 @@ source_set("ui") {
"painting/image_encoding_impeller.h",
]
deps += [ "//flutter/impeller" ]
deps += [
"//flutter/impeller",
"//flutter/impeller/display_list:skia_conversions",
]
}
if (!defined(defines)) {

View File

@ -16,6 +16,7 @@
#include "flutter/impeller/renderer/context.h"
#include "flutter/lib/ui/painting/image_decoder_skia.h"
#include "impeller/base/strings.h"
#include "impeller/display_list/skia_conversions.h"
#include "impeller/geometry/size.h"
#include "third_party/skia/include/core/SkAlphaType.h"
#include "third_party/skia/include/core/SkBitmap.h"
@ -106,22 +107,6 @@ static SkAlphaType ChooseCompatibleAlphaType(SkAlphaType type) {
return type;
}
static std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type) {
switch (type) {
case kRGBA_8888_SkColorType:
return impeller::PixelFormat::kR8G8B8A8UNormInt;
case kBGRA_8888_SkColorType:
return impeller::PixelFormat::kB8G8R8A8UNormInt;
case kRGBA_F16_SkColorType:
return impeller::PixelFormat::kR16G16B16A16Float;
case kBGR_101010x_XR_SkColorType:
return impeller::PixelFormat::kB10G10R10XR;
default:
return std::nullopt;
}
return std::nullopt;
}
std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
ImageDescriptor* descriptor,
SkISize target_size,
@ -174,7 +159,8 @@ std::optional<DecompressResult> ImageDecoderImpeller::DecompressTexture(
.makeAlphaType(alpha_type);
}
const auto pixel_format = ToPixelFormat(image_info.colorType());
const auto pixel_format =
impeller::skia_conversions::ToPixelFormat(image_info.colorType());
if (!pixel_format.has_value()) {
FML_DLOG(ERROR) << "Codec pixel format not supported by Impeller.";
return std::nullopt;
@ -260,7 +246,8 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToPrivate(
if (!context || !buffer) {
return nullptr;
}
const auto pixel_format = ToPixelFormat(image_info.colorType());
const auto pixel_format =
impeller::skia_conversions::ToPixelFormat(image_info.colorType());
if (!pixel_format) {
FML_DLOG(ERROR) << "Pixel format unsupported by Impeller.";
return nullptr;
@ -319,7 +306,8 @@ sk_sp<DlImage> ImageDecoderImpeller::UploadTextureToShared(
return nullptr;
}
const auto image_info = bitmap->info();
const auto pixel_format = ToPixelFormat(image_info.colorType());
const auto pixel_format =
impeller::skia_conversions::ToPixelFormat(image_info.colorType());
if (!pixel_format) {
FML_DLOG(ERROR) << "Pixel format unsupported by Impeller.";
return nullptr;