34class AnimationBuilder;
46 const auto stopCount = ParseDefault<int>((*jstops)[
"p"], -1);
50 const auto type = (ParseDefault<int>(jgrad[
"t"], 1) == 1) ? Type::kLinear
52 auto gradient_node = (
type == Type::kLinear)
59 jgrad, *jstops, abuilder));
73 : fGradient(
std::move(gradient))
75 , fStopCount(stop_count) {
76 this->bind(abuilder, jgrad[
"s"], fStartPoint );
77 this->bind(abuilder, jgrad[
"e"], fEndPoint );
78 this->bind(abuilder, jgrad[
"h"], fHighlightLength);
79 this->bind(abuilder, jgrad[
"a"], fHighlightAngle );
80 this->bind(abuilder, jstops[
"k"], fStops );
83 void onSync()
override {
84 const auto s_point =
SkPoint{fStartPoint.x, fStartPoint.y},
85 e_point =
SkPoint{ fEndPoint.x, fEndPoint.y};
90 grad->setStartPoint(s_point);
91 grad->setEndPoint(e_point);
104 const SkPoint rotated_e_point =
115 h_len =
SkTPin(fHighlightLength * 0.01f, -1 + eps, 1 - eps);
117 const SkPoint focal_point = s_point + (rotated_e_point - s_point) * h_len;
120 grad->setStartCenter(focal_point);
121 grad->setEndCenter(s_point);
122 grad->setStartRadius(0);
138 struct OpacityRec {
float t,
a; };
144 const auto c_count = fStopCount,
145 c_size = c_count * 4,
146 o_count = (fStops.size() - c_size) / 2;
147 if (fStops.size() < c_size || fStops.size() != (c_count * 4 + o_count * 2)) {
149 if (!fStops.empty()) {
150 SkDebugf(
"!! Invalid gradient stop array size: %zu\n", fStops.size());
155 const auto* c_rec = c_count > 0
156 ?
reinterpret_cast<const ColorRec*
>(fStops.data())
158 const auto* o_rec = o_count > 0
159 ?
reinterpret_cast<const OpacityRec*
>(fStops.data() + c_size)
161 const auto* c_end = c_rec + c_count;
162 const auto* o_end = o_rec + o_count;
166 c_rec ? c_rec->r : 0,
167 c_rec ? c_rec->g : 0,
168 c_rec ? c_rec->b : 0,
169 o_rec ? o_rec->a : 1,
172 std::vector<sksg::Gradient::ColorStop> stops;
173 stops.reserve(c_count);
176 while (c_rec || o_rec) {
179 const auto& cs = c_rec
185 const auto& os = o_rec
187 : OpacityRec{ c_rec->t, current_stop.
fColor.fA };
195 c_pos_rel = c_pos - current_stop.
fPosition,
196 o_pos_rel = o_pos - current_stop.
fPosition,
200 auto lerp = [](
float a,
float b,
float t) {
return a + t * (
b -
a); };
211 stops.push_back(current_stop);
214 if (c_pos <= o_pos) {
215 c_rec = next_rec<ColorRec>(c_rec, c_end);
217 if (o_pos <= c_pos) {
218 o_rec = next_rec<OpacityRec>(o_rec, o_end);
222 stops.shrink_to_fit();
223 fGradient->setColorStops(std::move(stops));
227 template <
typename T>
228 const T* next_rec(
const T* rec,
const T* end_rec)
const {
229 if (!rec)
return nullptr;
234 return rec < end_rec ? rec :
nullptr;
239 const size_t fStopCount;
244 float fHighlightLength = 0,
SkPoint lerp(const SkPoint &a, const SkPoint &b, float t)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static constexpr float sk_ieee_float_divide(float numer, float denom)
#define SK_ScalarNearlyZero
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
constexpr size_t SkToSizeT(S x)
static SkMatrix RotateDeg(SkScalar deg)
SkPoint mapPoint(SkPoint pt) const
friend class AnimatablePropertyContainer
AnimationBuilder(sk_sp< ResourceProvider >, sk_sp< SkFontMgr >, sk_sp< PropertyObserver >, sk_sp< Logger >, sk_sp< MarkerObserver >, sk_sp< PrecompInterceptor >, sk_sp< ExpressionManager >, sk_sp< SkShapers::Factory >, Animation::Builder::Stats *, const SkSize &comp_size, float duration, float framerate, uint32_t flags)
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< RadialGradient > Make()
static sk_sp< ShaderPaint > Make(sk_sp< Shader >)
static float max(float r, float g, float b)
static float min(float r, float g, float b)
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
static float Distance(const SkPoint &a, const SkPoint &b)