32class AnimationBuilder;
39 const AnimationBuilder& abuilder) {
44 const auto stopCount = ParseDefault<int>((*jstops)[
"p"], -1);
48 const auto type = (ParseDefault<int>(jgrad[
"t"], 1) == 1) ? Type::kLinear
50 auto gradient_node = (
type == Type::kLinear)
57 jgrad, *jstops, abuilder));
70 const AnimationBuilder& abuilder)
71 : fGradient(
std::move(gradient))
73 , fStopCount(stop_count) {
74 this->bind(abuilder, jgrad[
"s"], fStartPoint);
75 this->bind(abuilder, jgrad[
"e"], fEndPoint );
76 this->bind(abuilder, jstops[
"k"], fStops );
79 void onSync()
override {
80 const auto s_point =
SkPoint{fStartPoint.x, fStartPoint.y},
81 e_point =
SkPoint{ fEndPoint.x, fEndPoint.y};
86 grad->setStartPoint(s_point);
87 grad->setEndPoint(e_point);
93 grad->setStartCenter(s_point);
94 grad->setEndCenter(s_point);
95 grad->setStartRadius(0);
111 struct OpacityRec {
float t,
a; };
117 const auto c_count = fStopCount,
118 c_size = c_count * 4,
119 o_count = (fStops.size() - c_size) / 2;
120 if (fStops.size() < c_size || fStops.size() != (c_count * 4 + o_count * 2)) {
122 if (!fStops.empty()) {
123 SkDebugf(
"!! Invalid gradient stop array size: %zu\n", fStops.size());
128 const auto* c_rec = c_count > 0
129 ?
reinterpret_cast<const ColorRec*
>(fStops.data())
131 const auto* o_rec = o_count > 0
132 ?
reinterpret_cast<const OpacityRec*
>(fStops.data() + c_size)
134 const auto* c_end = c_rec + c_count;
135 const auto* o_end = o_rec + o_count;
139 c_rec ? c_rec->r : 0,
140 c_rec ? c_rec->g : 0,
141 c_rec ? c_rec->b : 0,
142 o_rec ? o_rec->a : 1,
145 std::vector<sksg::Gradient::ColorStop> stops;
146 stops.reserve(c_count);
149 while (c_rec || o_rec) {
152 const auto& cs = c_rec
158 const auto& os = o_rec
160 : OpacityRec{ c_rec->t, current_stop.
fColor.fA };
166 const auto c_pos = std::max(cs.t, current_stop.
fPosition),
167 o_pos = std::max(os.t, current_stop.
fPosition),
168 c_pos_rel = c_pos - current_stop.
fPosition,
169 o_pos_rel = o_pos - current_stop.
fPosition,
173 auto lerp = [](
float a,
float b,
float t) {
return a + t * (
b -
a); };
176 std::min(c_pos, o_pos),
184 stops.push_back(current_stop);
187 if (c_pos <= o_pos) {
188 c_rec = next_rec<ColorRec>(c_rec, c_end);
190 if (o_pos <= c_pos) {
191 o_rec = next_rec<OpacityRec>(o_rec, o_end);
195 stops.shrink_to_fit();
196 fGradient->setColorStops(std::move(stops));
200 template <
typename T>
201 const T* next_rec(
const T* rec,
const T* end_rec)
const {
202 if (!rec)
return nullptr;
207 return rec < end_rec ? rec :
nullptr;
212 const size_t fStopCount;
223 auto adapter = GradientAdapter::Make(jgrad, *abuilder);
232 auto adapter = GradientAdapter::Make(jgrad, *abuilder);
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr float sk_ieee_float_divide(float numer, float denom)
static std::unique_ptr< SkEncoder > Make(SkWStream *dst, const SkPixmap *src, const SkYUVAPixmaps *srcYUVA, const SkColorSpace *srcYUVAColorSpace, const SkJpegEncoder::Options &options)
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
constexpr size_t SkToSizeT(S x)
friend class AnimatablePropertyContainer
static sk_sp< sksg::PaintNode > AttachGradientStroke(const skjson::ObjectValue &, const AnimationBuilder *)
static sk_sp< sksg::PaintNode > AttachGradientFill(const skjson::ObjectValue &, const AnimationBuilder *)
static sk_sp< LinearGradient > Make()
static sk_sp< ShaderPaint > Make(sk_sp< Shader >)
SK_API sk_sp< PrecompileShader > RadialGradient()
static float Distance(const SkPoint &a, const SkPoint &b)
static SkPoint lerp(const SkPoint &a, const SkPoint &b, float T)