Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class DlGradientColorSourceBase : public DlMatrixColorSourceBase {
const DlColor* color_data,
const float* stop_data);

void store_color_stops(void* pod,
const DlScalar* color_data_argb,
const float* stop_data);

private:
DlTileMode mode_;
uint32_t stop_count_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ DlLinearGradientColorSource::DlLinearGradientColorSource(
store_color_stops(this + 1, colors, stops);
}

DlLinearGradientColorSource::DlLinearGradientColorSource(
const DlPoint start_point,
const DlPoint end_point,
uint32_t stop_count,
const DlScalar* colors,
const float* stops,
DlTileMode tile_mode,
const DlMatrix* matrix)
: DlGradientColorSourceBase(stop_count, tile_mode, matrix),
start_point_(start_point),
end_point_(end_point) {
store_color_stops(this + 1, colors, stops);
}

DlLinearGradientColorSource::DlLinearGradientColorSource(
const DlLinearGradientColorSource* source)
: DlGradientColorSourceBase(source->stop_count(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ class DlLinearGradientColorSource final : public DlGradientColorSourceBase {
DlTileMode tile_mode,
const DlMatrix* matrix = nullptr);

DlLinearGradientColorSource(const DlPoint start_point,
const DlPoint end_point,
uint32_t stop_count,
const DlScalar* colors,
const float* stops,
DlTileMode tile_mode,
const DlMatrix* matrix = nullptr);

explicit DlLinearGradientColorSource(
const DlLinearGradientColorSource* source);

Expand Down
95 changes: 84 additions & 11 deletions display_list/effects/dl_color_source.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeImage(
image, horizontal_tile_mode, vertical_tile_mode, sampling, matrix);
}

namespace {
size_t CalculateLinearGradientSize(uint32_t stop_count) {
return sizeof(DlLinearGradientColorSource) +
(stop_count * (sizeof(DlColor) + sizeof(float)));
}
} // namespace

std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
const DlPoint start_point,
const DlPoint end_point,
Expand All @@ -38,9 +45,7 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
const float* stops,
DlTileMode tile_mode,
const DlMatrix* matrix) {
size_t needed = sizeof(DlLinearGradientColorSource) +
(stop_count * (sizeof(DlColor) + sizeof(float)));

size_t needed = CalculateLinearGradientSize(stop_count);
void* storage = ::operator new(needed);

std::shared_ptr<DlLinearGradientColorSource> ret;
Expand All @@ -51,6 +56,25 @@ std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
return ret;
}

std::shared_ptr<DlColorSource> DlColorSource::MakeLinear(
const DlPoint start_point,
const DlPoint end_point,
uint32_t stop_count,
const DlScalar* colors_argb,
const float* stops,
DlTileMode tile_mode,
const DlMatrix* matrix) {
size_t needed = CalculateLinearGradientSize(stop_count);
void* storage = ::operator new(needed);

std::shared_ptr<DlLinearGradientColorSource> ret;
ret.reset(new (storage) DlLinearGradientColorSource(start_point, end_point,
stop_count, colors_argb,
stops, tile_mode, matrix),
DlGradientDeleter);
return ret;
}

std::shared_ptr<DlColorSource> DlColorSource::MakeRadial(
DlPoint center,
DlScalar radius,
Expand Down Expand Up @@ -157,23 +181,72 @@ bool DlGradientColorSourceBase::base_equals_(
stop_count_ * sizeof(stops()[0])) == 0);
}

void DlGradientColorSourceBase::store_color_stops(void* pod,
const DlColor* color_data,
const float* stop_data) {
namespace {
template <typename DlColorIt>
void do_store_color_stops(void* pod,
DlColorIt color_data_argb_begin,
DlColorIt color_data_argb_end,
const float* stop_data) {
DlColor* color_storage = reinterpret_cast<DlColor*>(pod);
memcpy(color_storage, color_data, stop_count_ * sizeof(*color_data));
float* stop_storage = reinterpret_cast<float*>(color_storage + stop_count_);
uint32_t stop_count = 0;
while (color_data_argb_begin < color_data_argb_end) {
*color_storage++ = *color_data_argb_begin++;
stop_count += 1;
}
float* stop_storage = reinterpret_cast<float*>(color_storage);
if (stop_data) {
memcpy(stop_storage, stop_data, stop_count_ * sizeof(*stop_data));
memcpy(stop_storage, stop_data, stop_count * sizeof(*stop_data));
} else {
float div = stop_count_ - 1;
float div = stop_count - 1;
if (div <= 0) {
div = 1;
}
for (uint32_t i = 0; i < stop_count_; i++) {
for (uint32_t i = 0; i < stop_count; i++) {
stop_storage[i] = i / div;
}
}
}

class DlScalerToDlColorIterator {
public:
explicit DlScalerToDlColorIterator(const DlScalar* ptr) : ptr_(ptr) {}
DlScalerToDlColorIterator(DlScalerToDlColorIterator&&) = default;
DlScalerToDlColorIterator(const DlScalerToDlColorIterator&) = delete;
DlScalerToDlColorIterator& operator=(const DlScalerToDlColorIterator&) =
delete;

DlColor operator*() {
return DlColor(ptr_[0], ptr_[1], ptr_[2], ptr_[3],
DlColorSpace::kExtendedSRGB);
}
DlScalerToDlColorIterator operator++(int) {
auto result = DlScalerToDlColorIterator(ptr_);
ptr_ += 4;
return result;
}
bool operator<(const DlScalerToDlColorIterator& that) const {
return ptr_ < that.ptr_;
}

private:
const DlScalar* ptr_;
};

} // namespace

void DlGradientColorSourceBase::store_color_stops(void* pod,
const DlColor* color_data,
const float* stop_data) {
do_store_color_stops(pod, color_data, color_data + stop_count_, stop_data);
}

void DlGradientColorSourceBase::store_color_stops(
void* pod,
const DlScalar* color_data_argb,
const float* stop_data) {
do_store_color_stops(
pod, DlScalerToDlColorIterator(color_data_argb),
DlScalerToDlColorIterator(color_data_argb + stop_count_ * 4), stop_data);
}

} // namespace flutter
11 changes: 11 additions & 0 deletions display_list/effects/dl_color_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ class DlColorSource : public DlAttribute<DlColorSource, DlColorSourceType> {
DlTileMode tile_mode,
const DlMatrix* matrix = nullptr);

/// @brief Make a linear gradient.
/// @param colors_argb Array of DlScalars that represents colors in the ARGB.
static std::shared_ptr<DlColorSource> MakeLinear(
const DlPoint start_point,
const DlPoint end_point,
uint32_t stop_count,
const DlScalar* colors_argb,
const float* stops,
DlTileMode tile_mode,
const DlMatrix* matrix = nullptr);

static std::shared_ptr<DlColorSource> MakeRadial(
DlPoint center,
DlScalar radius,
Expand Down
26 changes: 26 additions & 0 deletions display_list/effects/dl_color_source_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,32 @@ TEST(DisplayListColorSource, LinearGradientConstructor) {
DlTileMode::kClamp, &kTestMatrix1);
}

TEST(DisplayListColorSource, LinearGradientARGBConstructor) {
std::array<DlScalar, kTestStopCount * 4> colors;
for (int i = 0; i < kTestStopCount; ++i) {
colors[i * 4 + 0] = kTestColors[i].getAlphaF(); //
colors[i * 4 + 1] = kTestColors[i].getRedF(); //
colors[i * 4 + 2] = kTestColors[i].getGreenF(); //
colors[i * 4 + 3] = kTestColors[i].getBlueF();
}
std::shared_ptr<DlColorSource> source = DlColorSource::MakeLinear(
kTestPoints[0], kTestPoints[1], kTestStopCount, colors.data(), kTestStops,
DlTileMode::kClamp, &kTestMatrix1);
ASSERT_TRUE(source);
ASSERT_TRUE(source->asLinearGradient());
EXPECT_EQ(source->asLinearGradient()->start_point(), kTestPoints[0]);
EXPECT_EQ(source->asLinearGradient()->end_point(), kTestPoints[1]);
EXPECT_EQ(source->asLinearGradient()->stop_count(), kTestStopCount);
for (int i = 0; i < kTestStopCount; i++) {
EXPECT_EQ(source->asLinearGradient()->colors()[i],
kTestColors[i].withColorSpace(DlColorSpace::kExtendedSRGB));
EXPECT_EQ(source->asLinearGradient()->stops()[i], kTestStops[i]);
}
EXPECT_EQ(source->asLinearGradient()->tile_mode(), DlTileMode::kClamp);
EXPECT_EQ(source->asLinearGradient()->matrix(), kTestMatrix1);
EXPECT_EQ(source->is_opaque(), true);
}

TEST(DisplayListColorSource, LinearGradientShared) {
std::shared_ptr<DlColorSource> source = DlColorSource::MakeLinear(
kTestPoints[0], kTestPoints[1], kTestStopCount, kTestColors, kTestStops,
Expand Down
3 changes: 2 additions & 1 deletion display_list/skia/dl_sk_conversions_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,8 @@ TEST(DisplayListSkConversions, ToSkDitheringEnabledForGradients) {

// Set the paint to be a gradient.
dl_paint.setColorSource(DlColorSource::MakeLinear(
DlPoint(0, 0), DlPoint(100, 100), 0, 0, 0, DlTileMode::kClamp));
DlPoint(0, 0), DlPoint(100, 100), 0,
std::array<DlColor, 1>{DlColor(0)}.data(), 0, DlTileMode::kClamp));

{
SkPaint sk_paint = ToSk(dl_paint);
Expand Down
12 changes: 1 addition & 11 deletions lib/ui/painting/gradient.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,7 @@ void CanvasGradient::initLinear(const tonic::Float32List& end_points,

DlPoint p0 = DlPoint(end_points[0], end_points[1]);
DlPoint p1 = DlPoint(end_points[2], end_points[3]);
std::vector<DlColor> dl_colors;
dl_colors.reserve(num_colors);
for (int i = 0; i < colors.num_elements(); i += 4) {
DlScalar a = colors[i + 0];
DlScalar r = colors[i + 1];
DlScalar g = colors[i + 2];
DlScalar b = colors[i + 3];
dl_colors.emplace_back(DlColor(a, r, g, b, DlColorSpace::kExtendedSRGB));
}

dl_shader_ = DlColorSource::MakeLinear(p0, p1, num_colors, dl_colors.data(),
dl_shader_ = DlColorSource::MakeLinear(p0, p1, num_colors, colors.data(),
color_stops.data(), tile_mode,
has_matrix ? &dl_matrix : nullptr);
// Just a sanity check, all gradient shaders should be thread-safe
Expand Down
Loading