[Impeller] Move skia_conversions towards retirement (#165408)
The skia_conversions sources and namespace have been filled with methods that are no longer used now that the DisplayList has its own complete set of APIs and is now mostly obsolete.
This commit is contained in:
@@ -151,6 +151,7 @@
|
||||
../../../flutter/impeller/display_list/dl_golden_unittests.cc
|
||||
../../../flutter/impeller/display_list/dl_golden_unittests.h
|
||||
../../../flutter/impeller/display_list/dl_unittests.cc
|
||||
../../../flutter/impeller/display_list/paint_unittests.cc
|
||||
../../../flutter/impeller/display_list/skia_conversions_unittests.cc
|
||||
../../../flutter/impeller/display_list/testing
|
||||
../../../flutter/impeller/docs
|
||||
|
||||
@@ -78,6 +78,7 @@ template("display_list_unittests_component") {
|
||||
"dl_playground.cc",
|
||||
"dl_playground.h",
|
||||
"dl_unittests.cc",
|
||||
"paint_unittests.cc",
|
||||
"testing/render_text_in_canvas.cc",
|
||||
"testing/render_text_in_canvas.h",
|
||||
"testing/rmse.cc",
|
||||
|
||||
@@ -137,6 +137,13 @@ static impeller::SamplerDescriptor ToSamplerDescriptor(
|
||||
return desc;
|
||||
}
|
||||
|
||||
static std::optional<const Rect> ToOptRect(const flutter::DlRect* rect) {
|
||||
if (rect == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return *rect;
|
||||
}
|
||||
|
||||
// |flutter::DlOpReceiver|
|
||||
void DlDispatcherBase::setAntiAlias(bool aa) {
|
||||
AUTO_DEPTH_WATCHER(0u);
|
||||
@@ -506,8 +513,8 @@ void DlDispatcherBase::clipPath(const DlPath& path,
|
||||
} else {
|
||||
SkRRect rrect;
|
||||
if (path.IsSkRRect(&rrect) && rrect.isSimple()) {
|
||||
RoundRectGeometry geom(skia_conversions::ToRect(rrect.rect()),
|
||||
skia_conversions::ToSize(rrect.getSimpleRadii()));
|
||||
RoundRectGeometry geom(flutter::ToDlRect(rrect.rect()),
|
||||
flutter::ToDlSize(rrect.getSimpleRadii()));
|
||||
GetCanvas().ClipGeometry(geom, clip_op);
|
||||
} else {
|
||||
FillPathGeometry geom(path.GetPath());
|
||||
@@ -820,7 +827,7 @@ void DlDispatcherBase::drawAtlas(const sk_sp<flutter::DlImage> atlas,
|
||||
static_cast<size_t>(count), //
|
||||
skia_conversions::ToBlendMode(mode), //
|
||||
skia_conversions::ToSamplerDescriptor(sampling), //
|
||||
skia_conversions::ToRect(cull_rect) //
|
||||
ToOptRect(cull_rect) //
|
||||
);
|
||||
auto atlas_contents = std::make_shared<AtlasContents>();
|
||||
atlas_contents->SetGeometry(&geometry);
|
||||
@@ -854,10 +861,10 @@ void DlDispatcherBase::drawDisplayList(
|
||||
if (opacity < SK_Scalar1) {
|
||||
Paint save_paint;
|
||||
save_paint.color = Color(0, 0, 0, opacity);
|
||||
GetCanvas().SaveLayer(
|
||||
save_paint, skia_conversions::ToRect(display_list->bounds()), nullptr,
|
||||
ContentBoundsPromise::kContainsContents, display_list->total_depth(),
|
||||
display_list->can_apply_group_opacity());
|
||||
GetCanvas().SaveLayer(save_paint, display_list->GetBounds(), nullptr,
|
||||
ContentBoundsPromise::kContainsContents,
|
||||
display_list->total_depth(),
|
||||
display_list->can_apply_group_opacity());
|
||||
} else {
|
||||
// The display list may alter the clip, which must be restored to the
|
||||
// current clip at the end of playback.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "impeller/display_list/image_filter.h"
|
||||
|
||||
#include "flutter/display_list/effects/dl_color_sources.h"
|
||||
#include "flutter/display_list/effects/dl_image_filters.h"
|
||||
#include "fml/logging.h"
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
|
||||
@@ -34,6 +34,31 @@ using DlRect = flutter::DlRect;
|
||||
using DlIRect = flutter::DlIRect;
|
||||
using DlPath = flutter::DlPath;
|
||||
|
||||
void Paint::ConvertStops(const flutter::DlGradientColorSourceBase* gradient,
|
||||
std::vector<Color>& colors,
|
||||
std::vector<float>& stops) {
|
||||
FML_DCHECK(gradient->stop_count() >= 2)
|
||||
<< "stop_count:" << gradient->stop_count();
|
||||
|
||||
auto* dl_colors = gradient->colors();
|
||||
auto* dl_stops = gradient->stops();
|
||||
if (dl_stops[0] != 0.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(skia_conversions::ToColor(dl_colors[i]));
|
||||
stops.emplace_back(std::clamp(dl_stops[i], 0.0f, 1.0f));
|
||||
}
|
||||
if (dl_stops[gradient->stop_count() - 1] != 1.0) {
|
||||
colors.emplace_back(colors.back());
|
||||
stops.emplace_back(1.0);
|
||||
}
|
||||
for (auto i = 1; i < gradient->stop_count(); i++) {
|
||||
stops[i] = std::clamp(stops[i], stops[i - 1], stops[i]);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
if (color_source == nullptr) {
|
||||
auto contents = std::make_shared<SolidColorContents>();
|
||||
@@ -50,7 +75,7 @@ std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
auto end_point = linear->end_point();
|
||||
std::vector<Color> colors;
|
||||
std::vector<float> stops;
|
||||
skia_conversions::ConvertStops(linear, colors, stops);
|
||||
ConvertStops(linear, colors, stops);
|
||||
|
||||
auto tile_mode = static_cast<Entity::TileMode>(linear->tile_mode());
|
||||
auto effect_transform = linear->matrix();
|
||||
@@ -78,7 +103,7 @@ std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
auto radius = radialGradient->radius();
|
||||
std::vector<Color> colors;
|
||||
std::vector<float> stops;
|
||||
skia_conversions::ConvertStops(radialGradient, colors, stops);
|
||||
ConvertStops(radialGradient, colors, stops);
|
||||
|
||||
auto tile_mode =
|
||||
static_cast<Entity::TileMode>(radialGradient->tile_mode());
|
||||
@@ -110,7 +135,7 @@ std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
DlScalar focus_radius = conical_gradient->start_radius();
|
||||
std::vector<Color> colors;
|
||||
std::vector<float> stops;
|
||||
skia_conversions::ConvertStops(conical_gradient, colors, stops);
|
||||
ConvertStops(conical_gradient, colors, stops);
|
||||
|
||||
auto tile_mode =
|
||||
static_cast<Entity::TileMode>(conical_gradient->tile_mode());
|
||||
@@ -144,7 +169,7 @@ std::shared_ptr<ColorSourceContents> Paint::CreateContents() const {
|
||||
auto end_angle = Degrees(sweepGradient->end());
|
||||
std::vector<Color> colors;
|
||||
std::vector<float> stops;
|
||||
skia_conversions::ConvertStops(sweepGradient, colors, stops);
|
||||
ConvertStops(sweepGradient, colors, stops);
|
||||
|
||||
auto tile_mode =
|
||||
static_cast<Entity::TileMode>(sweepGradient->tile_mode());
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "display_list/effects/dl_color_filter.h"
|
||||
#include "display_list/effects/dl_color_source.h"
|
||||
#include "display_list/effects/dl_color_sources.h"
|
||||
#include "display_list/effects/dl_image_filter.h"
|
||||
#include "impeller/display_list/color_filter.h"
|
||||
#include "impeller/display_list/image_filter.h"
|
||||
@@ -119,6 +119,25 @@ struct Paint {
|
||||
const Matrix& effect_transform,
|
||||
Entity::RenderingMode rendering_mode) const;
|
||||
|
||||
/// @brief Convert display list colors + stops into impeller colors and
|
||||
/// stops, taking care to ensure that the stops monotonically
|
||||
/// increase from 0.0 to 1.0.
|
||||
///
|
||||
/// The general process is:
|
||||
/// * Ensure that the first gradient stop value is 0.0. If not, insert a
|
||||
/// new stop with a value of 0.0 and use the first gradient color as this
|
||||
/// new stops color.
|
||||
/// * Ensure the last gradient stop value is 1.0. If not, insert a new stop
|
||||
/// with a value of 1.0 and use the last gradient color as this stops color.
|
||||
/// * Clamp all gradient values between the values of 0.0 and 1.0.
|
||||
/// * For all stop values, ensure that the values are monotonically
|
||||
/// increasing by clamping each value to a minimum of the previous stop
|
||||
/// value and itself. For example, with stop values of 0.0, 0.5, 0.4, 1.0,
|
||||
/// we would clamp such that the values were 0.0, 0.5, 0.5, 1.0.
|
||||
static void ConvertStops(const flutter::DlGradientColorSourceBase* gradient,
|
||||
std::vector<Color>& colors,
|
||||
std::vector<float>& stops);
|
||||
|
||||
private:
|
||||
std::shared_ptr<Contents> WithColorFilter(
|
||||
std::shared_ptr<Contents> input,
|
||||
|
||||
149
engine/src/flutter/impeller/display_list/paint_unittests.cc
Normal file
149
engine/src/flutter/impeller/display_list/paint_unittests.cc
Normal file
@@ -0,0 +1,149 @@
|
||||
// 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 "flutter/impeller/display_list/paint.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "flutter/display_list/dl_color.h"
|
||||
#include "flutter/display_list/dl_tile_mode.h"
|
||||
#include "flutter/display_list/effects/dl_color_source.h"
|
||||
#include "flutter/impeller/geometry/scalar.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
|
||||
TEST(PaintTest, GradientStopConversion) {
|
||||
// Typical gradient.
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kRed(),
|
||||
flutter::DlColor::kGreen()};
|
||||
std::vector<float> stops = {0.0, 0.5, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
3, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(PaintTest, GradientMissing0) {
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.5, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
2, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// First color is inserted as blue.
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(PaintTest, GradientMissingLastValue) {
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.0, .5};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
2, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// Last color is inserted as red.
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(PaintTest, GradientStopGreaterThan1) {
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kGreen(),
|
||||
flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.0, 100, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
3, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// Value is clamped to 1.0
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(PaintTest, GradientConversionNonMonotonic) {
|
||||
std::vector<flutter::DlColor> colors = {
|
||||
flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
|
||||
flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
4, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
Paint::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// Value is clamped to 0.5
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace impeller
|
||||
@@ -10,82 +10,6 @@
|
||||
namespace impeller {
|
||||
namespace skia_conversions {
|
||||
|
||||
static inline bool SkScalarsNearlyEqual(SkScalar a,
|
||||
SkScalar b,
|
||||
SkScalar c,
|
||||
SkScalar d) {
|
||||
return SkScalarNearlyEqual(a, b, kEhCloseEnough) &&
|
||||
SkScalarNearlyEqual(a, c, kEhCloseEnough) &&
|
||||
SkScalarNearlyEqual(a, d, kEhCloseEnough);
|
||||
}
|
||||
|
||||
bool IsNearlySimpleRRect(const SkRRect& rr) {
|
||||
auto [xa, ya] = rr.radii(SkRRect::kUpperLeft_Corner);
|
||||
auto [xb, yb] = rr.radii(SkRRect::kLowerLeft_Corner);
|
||||
auto [xc, yc] = rr.radii(SkRRect::kUpperRight_Corner);
|
||||
auto [xd, yd] = rr.radii(SkRRect::kLowerRight_Corner);
|
||||
return SkScalarsNearlyEqual(xa, xb, xc, xd) &&
|
||||
SkScalarsNearlyEqual(ya, yb, yc, yd);
|
||||
}
|
||||
|
||||
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::optional<const Rect> ToRect(const flutter::DlRect* rect) {
|
||||
if (rect == nullptr) {
|
||||
return std::nullopt;
|
||||
}
|
||||
return *rect;
|
||||
}
|
||||
|
||||
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]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Rect> ToRects(const flutter::DlRect tex[], int count) {
|
||||
auto result = std::vector<Rect>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
result.push_back(tex[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Point> ToPoints(const SkPoint points[], int count) {
|
||||
std::vector<Point> result(count);
|
||||
for (auto i = 0; i < count; i++) {
|
||||
result[i] = ToPoint(points[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Point> ToPoints(const flutter::DlPoint points[], int count) {
|
||||
std::vector<Point> result(count);
|
||||
for (auto i = 0; i < count; i++) {
|
||||
result[i] = points[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Point ToPoint(const SkPoint& point) {
|
||||
return Point::MakeXY(point.fX, point.fY);
|
||||
}
|
||||
|
||||
Size ToSize(const SkPoint& point) {
|
||||
return Size(point.fX, point.fY);
|
||||
}
|
||||
|
||||
Color ToColor(const flutter::DlColor& color) {
|
||||
FML_DCHECK(color.getColorSpace() == flutter::DlColorSpace::kExtendedSRGB ||
|
||||
color.getColorSpace() == flutter::DlColorSpace::kSRGB);
|
||||
@@ -97,47 +21,6 @@ Color ToColor(const flutter::DlColor& color) {
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void ConvertStops(const flutter::DlGradientColorSourceBase* gradient,
|
||||
std::vector<Color>& colors,
|
||||
std::vector<float>& stops) {
|
||||
FML_DCHECK(gradient->stop_count() >= 2)
|
||||
<< "stop_count:" << gradient->stop_count();
|
||||
|
||||
auto* dl_colors = gradient->colors();
|
||||
auto* dl_stops = gradient->stops();
|
||||
if (dl_stops[0] != 0.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(skia_conversions::ToColor(dl_colors[i]));
|
||||
stops.emplace_back(std::clamp(dl_stops[i], 0.0f, 1.0f));
|
||||
}
|
||||
if (dl_stops[gradient->stop_count() - 1] != 1.0) {
|
||||
colors.emplace_back(colors.back());
|
||||
stops.emplace_back(1.0);
|
||||
}
|
||||
for (auto i = 1; i < gradient->stop_count(); i++) {
|
||||
stops[i] = std::clamp(stops[i], stops[i - 1], stops[i]);
|
||||
}
|
||||
}
|
||||
|
||||
impeller::SamplerDescriptor ToSamplerDescriptor(
|
||||
const flutter::DlImageSampling options) {
|
||||
impeller::SamplerDescriptor desc;
|
||||
@@ -162,17 +45,6 @@ impeller::SamplerDescriptor ToSamplerDescriptor(
|
||||
return desc;
|
||||
}
|
||||
|
||||
Matrix ToMatrix(const SkMatrix& m) {
|
||||
return Matrix{
|
||||
// clang-format off
|
||||
m[0], m[3], 0, m[6],
|
||||
m[1], m[4], 0, m[7],
|
||||
0, 0, 1, 0,
|
||||
m[2], m[5], 0, m[8],
|
||||
// clang-format on
|
||||
};
|
||||
}
|
||||
|
||||
BlendMode ToBlendMode(flutter::DlBlendMode mode) {
|
||||
switch (mode) {
|
||||
case flutter::DlBlendMode::kClear:
|
||||
|
||||
@@ -7,73 +7,20 @@
|
||||
|
||||
#include "flutter/display_list/dl_blend_mode.h"
|
||||
#include "flutter/display_list/dl_color.h"
|
||||
#include "flutter/display_list/effects/dl_color_sources.h"
|
||||
#include "impeller/core/formats.h"
|
||||
#include "impeller/core/sampler_descriptor.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/SkColorType.h"
|
||||
#include "third_party/skia/include/core/SkPoint.h"
|
||||
#include "third_party/skia/include/core/SkRRect.h"
|
||||
#include "third_party/skia/include/core/SkTextBlob.h"
|
||||
#include "flutter/display_list/dl_sampling_options.h"
|
||||
#include "flutter/impeller/core/sampler_descriptor.h"
|
||||
#include "flutter/impeller/geometry/color.h"
|
||||
|
||||
namespace impeller {
|
||||
namespace skia_conversions {
|
||||
|
||||
/// @brief Like SkRRect.isSimple, but allows the corners to differ by
|
||||
/// kEhCloseEnough.
|
||||
///
|
||||
/// An RRect is simple if all corner radii are approximately
|
||||
/// equal.
|
||||
bool IsNearlySimpleRRect(const SkRRect& rr);
|
||||
|
||||
Rect ToRect(const SkRect& rect);
|
||||
|
||||
std::optional<Rect> ToRect(const SkRect* rect);
|
||||
std::optional<const Rect> ToRect(const flutter::DlRect* rect);
|
||||
|
||||
std::vector<Rect> ToRects(const SkRect tex[], int count);
|
||||
std::vector<Rect> ToRects(const flutter::DlRect tex[], int count);
|
||||
|
||||
std::vector<Point> ToPoints(const SkPoint points[], int count);
|
||||
std::vector<Point> ToPoints(const flutter::DlPoint points[], int count);
|
||||
|
||||
Point ToPoint(const SkPoint& point);
|
||||
|
||||
Size ToSize(const SkPoint& point);
|
||||
|
||||
Color ToColor(const flutter::DlColor& color);
|
||||
|
||||
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type);
|
||||
|
||||
impeller::SamplerDescriptor ToSamplerDescriptor(
|
||||
const flutter::DlImageSampling options);
|
||||
|
||||
Matrix ToMatrix(const SkMatrix& m);
|
||||
|
||||
BlendMode ToBlendMode(flutter::DlBlendMode mode);
|
||||
|
||||
/// @brief Convert display list colors + stops into impeller colors and stops,
|
||||
/// taking care to ensure that the stops monotonically increase from 0.0 to 1.0.
|
||||
///
|
||||
/// The general process is:
|
||||
/// * Ensure that the first gradient stop value is 0.0. If not, insert a new
|
||||
/// stop with a value of 0.0 and use the first gradient color as this new
|
||||
/// stops color.
|
||||
/// * Ensure the last gradient stop value is 1.0. If not, insert a new stop
|
||||
/// with a value of 1.0 and use the last gradient color as this stops color.
|
||||
/// * Clamp all gradient values between the values of 0.0 and 1.0.
|
||||
/// * For all stop values, ensure that the values are monotonically increasing
|
||||
/// by clamping each value to a minimum of the previous stop value and itself.
|
||||
/// For example, with stop values of 0.0, 0.5, 0.4, 1.0, we would clamp such
|
||||
/// that the values were 0.0, 0.5, 0.5, 1.0.
|
||||
void ConvertStops(const flutter::DlGradientColorSourceBase* gradient,
|
||||
std::vector<Color>& colors,
|
||||
std::vector<float>& stops);
|
||||
|
||||
} // namespace skia_conversions
|
||||
} // namespace impeller
|
||||
|
||||
|
||||
@@ -16,56 +16,6 @@
|
||||
namespace impeller {
|
||||
namespace testing {
|
||||
|
||||
TEST(SkiaConversionTest, ToMatrixTranslate) {
|
||||
SkMatrix sk_matrix = SkMatrix::Translate(100, 100);
|
||||
Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
|
||||
|
||||
EXPECT_EQ(matrix.m[12], 100);
|
||||
EXPECT_EQ(matrix.m[13], 100);
|
||||
EXPECT_TRUE(matrix.IsTranslationScaleOnly());
|
||||
|
||||
matrix.m[12] = 0;
|
||||
matrix.m[13] = 0;
|
||||
|
||||
EXPECT_TRUE(matrix.IsIdentity());
|
||||
}
|
||||
|
||||
TEST(SkiaConversionTest, ToMatrixScale) {
|
||||
SkMatrix sk_matrix = SkMatrix::Scale(2, 2);
|
||||
Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
|
||||
|
||||
EXPECT_EQ(matrix.m[0], 2);
|
||||
EXPECT_EQ(matrix.m[5], 2);
|
||||
EXPECT_TRUE(matrix.IsTranslationScaleOnly());
|
||||
|
||||
matrix.m[0] = 1;
|
||||
matrix.m[5] = 1;
|
||||
|
||||
EXPECT_TRUE(matrix.IsIdentity());
|
||||
}
|
||||
|
||||
TEST(SkiaConversionTest, ToMatrixRotate) {
|
||||
SkMatrix sk_matrix = SkMatrix::RotateDeg(90);
|
||||
Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
|
||||
|
||||
EXPECT_EQ(matrix.vec[0], Vector4(0, 1, 0, 0));
|
||||
EXPECT_EQ(matrix.vec[1], Vector4(-1, 0, 0, 0));
|
||||
EXPECT_EQ(matrix.vec[2], Vector4(0, 0, 1, 0));
|
||||
EXPECT_EQ(matrix.vec[3], Vector4(0, 0, 0, 1));
|
||||
EXPECT_FALSE(matrix.IsTranslationScaleOnly());
|
||||
}
|
||||
|
||||
TEST(SkiaConversionTest, ToMatrixSkew) {
|
||||
SkMatrix sk_matrix = SkMatrix::Skew(2, 2);
|
||||
Matrix matrix = skia_conversions::ToMatrix(sk_matrix);
|
||||
|
||||
EXPECT_EQ(matrix.vec[0], Vector4(1, 2, 0, 0));
|
||||
EXPECT_EQ(matrix.vec[1], Vector4(2, 1, 0, 0));
|
||||
EXPECT_EQ(matrix.vec[2], Vector4(0, 0, 1, 0));
|
||||
EXPECT_EQ(matrix.vec[3], Vector4(0, 0, 0, 1));
|
||||
EXPECT_FALSE(matrix.IsTranslationScaleOnly());
|
||||
}
|
||||
|
||||
TEST(SkiaConversionTest, ToSamplerDescriptor) {
|
||||
EXPECT_EQ(skia_conversions::ToSamplerDescriptor(
|
||||
flutter::DlImageSampling::kNearestNeighbor)
|
||||
@@ -95,24 +45,6 @@ TEST(SkiaConversionTest, ToSamplerDescriptor) {
|
||||
impeller::MipFilter::kLinear);
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, SkPointToPoint) {
|
||||
for (int x = -100; x < 100; x += 4) {
|
||||
for (int y = -100; y < 100; y += 4) {
|
||||
EXPECT_EQ(skia_conversions::ToPoint(SkPoint::Make(x * 0.25f, y * 0.25f)),
|
||||
Point(x * 0.25f, y * 0.25f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, SkPointToSize) {
|
||||
for (int x = -100; x < 100; x += 4) {
|
||||
for (int y = -100; y < 100; y += 4) {
|
||||
EXPECT_EQ(skia_conversions::ToSize(SkPoint::Make(x * 0.25f, y * 0.25f)),
|
||||
Size(x * 0.25f, y * 0.25f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, ToColor) {
|
||||
// Create a color with alpha, red, green, and blue values that are all
|
||||
// trivially divisible by 255 so that we can test the conversion results in
|
||||
@@ -127,173 +59,6 @@ TEST(SkiaConversionsTest, ToColor) {
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_color.blue, 0x20 * (1.0f / 255)));
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, GradientStopConversion) {
|
||||
// Typical gradient.
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kRed(),
|
||||
flutter::DlColor::kGreen()};
|
||||
std::vector<float> stops = {0.0, 0.5, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
3, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
skia_conversions::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, GradientMissing0) {
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.5, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
2, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
skia_conversions::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// First color is inserted as blue.
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_colors[0].blue, 1.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, GradientMissingLastValue) {
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.0, .5};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
2, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
skia_conversions::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// Last color is inserted as red.
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_colors[2].red, 1.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, GradientStopGreaterThan1) {
|
||||
std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
|
||||
flutter::DlColor::kGreen(),
|
||||
flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.0, 100, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
3, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
skia_conversions::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// Value is clamped to 1.0
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 1.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 1.0f));
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, GradientConversionNonMonotonic) {
|
||||
std::vector<flutter::DlColor> colors = {
|
||||
flutter::DlColor::kBlue(), flutter::DlColor::kGreen(),
|
||||
flutter::DlColor::kGreen(), flutter::DlColor::kRed()};
|
||||
std::vector<float> stops = {0.0, 0.5, 0.4, 1.0};
|
||||
const auto gradient =
|
||||
flutter::DlColorSource::MakeLinear(flutter::DlPoint(0, 0), //
|
||||
flutter::DlPoint(1.0, 1.0), //
|
||||
4, //
|
||||
colors.data(), //
|
||||
stops.data(), //
|
||||
flutter::DlTileMode::kClamp, //
|
||||
nullptr //
|
||||
);
|
||||
|
||||
std::vector<Color> converted_colors;
|
||||
std::vector<Scalar> converted_stops;
|
||||
skia_conversions::ConvertStops(gradient->asLinearGradient(), converted_colors,
|
||||
converted_stops);
|
||||
|
||||
// Value is clamped to 0.5
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[0], 0.0f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[1], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[2], 0.5f));
|
||||
ASSERT_TRUE(ScalarNearlyEqual(converted_stops[3], 1.0f));
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, IsNearlySimpleRRect) {
|
||||
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 10)));
|
||||
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9.999)));
|
||||
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 9)));
|
||||
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(
|
||||
SkRRect::MakeRectXY(SkRect::MakeLTRB(0, 0, 10, 10), 10, 5)));
|
||||
SkRect rect = SkRect::MakeLTRB(0, 0, 10, 10);
|
||||
SkRRect rrect;
|
||||
union {
|
||||
SkPoint radii[4] = {
|
||||
{10.0f, 9.0f},
|
||||
{10.0f, 9.0f},
|
||||
{10.0f, 9.0f},
|
||||
{10.0f, 9.0f},
|
||||
};
|
||||
SkScalar values[8];
|
||||
} test;
|
||||
rrect.setRectRadii(rect, test.radii);
|
||||
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect));
|
||||
for (int i = 0; i < 8; i++) {
|
||||
auto save = test.values[i];
|
||||
test.values[i] -= kEhCloseEnough * 0.5f;
|
||||
rrect.setRectRadii(rect, test.radii);
|
||||
EXPECT_TRUE(skia_conversions::IsNearlySimpleRRect(rrect))
|
||||
<< "values[" << i << "] == " << test.values[i];
|
||||
test.values[i] -= kEhCloseEnough * 2.0f;
|
||||
rrect.setRectRadii(rect, test.radii);
|
||||
EXPECT_FALSE(skia_conversions::IsNearlySimpleRRect(rrect))
|
||||
<< "values[" << i << "] == " << test.values[i];
|
||||
test.values[i] = save;
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SkiaConversionsTest, BlendMode) {
|
||||
for (auto i = 0; i < static_cast<int>(flutter::DlBlendMode::kLastMode); i++) {
|
||||
EXPECT_EQ(
|
||||
|
||||
@@ -74,6 +74,22 @@ bool IsWideGamut(const SkColorSpace* color_space) {
|
||||
float area = CalculateArea(rgb);
|
||||
return area > kSrgbGamutArea;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
ImageDecoderImpeller::ImageDecoderImpeller(
|
||||
@@ -163,8 +179,7 @@ DecompressResult ImageDecoderImpeller::DecompressTexture(
|
||||
.makeAlphaType(alpha_type);
|
||||
}
|
||||
|
||||
const auto pixel_format =
|
||||
impeller::skia_conversions::ToPixelFormat(image_info.colorType());
|
||||
const auto pixel_format = ToPixelFormat(image_info.colorType());
|
||||
if (!pixel_format.has_value()) {
|
||||
std::string decode_error(impeller::SPrintF(
|
||||
"Codec pixel format is not supported (SkColorType=%d)",
|
||||
@@ -289,8 +304,7 @@ ImageDecoderImpeller::UnsafeUploadTextureToPrivate(
|
||||
const std::shared_ptr<impeller::DeviceBuffer>& buffer,
|
||||
const SkImageInfo& image_info,
|
||||
const std::optional<SkImageInfo>& resize_info) {
|
||||
const auto pixel_format =
|
||||
impeller::skia_conversions::ToPixelFormat(image_info.colorType());
|
||||
const auto pixel_format = ToPixelFormat(image_info.colorType());
|
||||
if (!pixel_format) {
|
||||
std::string decode_error(impeller::SPrintF(
|
||||
"Unsupported pixel format (SkColorType=%d)", image_info.colorType()));
|
||||
@@ -456,8 +470,7 @@ ImageDecoderImpeller::UploadTextureToStorage(
|
||||
return std::make_pair(nullptr, "No texture bitmap is available");
|
||||
}
|
||||
const auto image_info = bitmap->info();
|
||||
const auto pixel_format =
|
||||
impeller::skia_conversions::ToPixelFormat(image_info.colorType());
|
||||
const auto pixel_format = ToPixelFormat(image_info.colorType());
|
||||
if (!pixel_format) {
|
||||
std::string decode_error(impeller::SPrintF(
|
||||
"Unsupported pixel format (SkColorType=%d)", image_info.colorType()));
|
||||
|
||||
Reference in New Issue
Block a user