• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkottieProperties.h"
9 
10 #include "SkColor.h"
11 #include "SkJSONCPP.h"
12 #include "SkPath.h"
13 #include "SkSGColor.h"
14 #include "SkSGGradient.h"
15 #include "SkSGPath.h"
16 #include "SkSGRect.h"
17 #include "SkSGTransform.h"
18 
19 #include <cmath>
20 
21 namespace  skottie {
22 
23 namespace {
24 
VecToColor(const float * v,size_t size)25 SkColor VecToColor(const float* v, size_t size) {
26     // best effort to turn this into a color
27     const auto r = size > 0 ? v[0] : 0,
28                g = size > 1 ? v[1] : 0,
29                b = size > 2 ? v[2] : 0,
30                a = size > 3 ? v[3] : 1;
31 
32     return SkColorSetARGB(SkTPin<SkScalar>(a, 0, 1) * 255,
33                           SkTPin<SkScalar>(r, 0, 1) * 255,
34                           SkTPin<SkScalar>(g, 0, 1) * 255,
35                           SkTPin<SkScalar>(b, 0, 1) * 255);
36 }
37 
38 } // namespace
39 
40 template <>
Cardinality(const ScalarValue &)41 size_t ValueTraits<ScalarValue>::Cardinality(const ScalarValue&) {
42     return 1;
43 }
44 
45 template <>
46 template <>
As(const ScalarValue & v)47 SkScalar ValueTraits<ScalarValue>::As<SkScalar>(const ScalarValue& v) {
48     return v;
49 }
50 
51 template <>
Cardinality(const VectorValue & vec)52 size_t ValueTraits<VectorValue>::Cardinality(const VectorValue& vec) {
53     return vec.size();
54 }
55 
56 template <>
57 template <>
As(const VectorValue & vec)58 SkColor ValueTraits<VectorValue>::As<SkColor>(const VectorValue& vec) {
59     return VecToColor(vec.data(), vec.size());
60 }
61 
62 template <>
63 template <>
As(const VectorValue & vec)64 SkPoint ValueTraits<VectorValue>::As<SkPoint>(const VectorValue& vec) {
65     // best effort to turn this into a point
66     const auto x = vec.size() > 0 ? vec[0] : 0,
67                y = vec.size() > 1 ? vec[1] : 0;
68     return SkPoint::Make(x, y);
69 }
70 
71 template <>
72 template <>
As(const VectorValue & vec)73 SkSize ValueTraits<VectorValue>::As<SkSize>(const VectorValue& vec) {
74     const auto pt = ValueTraits::As<SkPoint>(vec);
75     return SkSize::Make(pt.x(), pt.y());
76 }
77 
78 template <>
Cardinality(const ShapeValue & path)79 size_t ValueTraits<ShapeValue>::Cardinality(const ShapeValue& path) {
80     return SkTo<size_t>(path.countVerbs());
81 }
82 
83 template <>
84 template <>
As(const ShapeValue & path)85 SkPath ValueTraits<ShapeValue>::As<SkPath>(const ShapeValue& path) {
86     return path;
87 }
88 
CompositeRRect(sk_sp<sksg::RRect> wrapped_node)89 CompositeRRect::CompositeRRect(sk_sp<sksg::RRect> wrapped_node)
90     : fRRectNode(std::move(wrapped_node)) {}
91 
apply()92 void CompositeRRect::apply() {
93     // BM "position" == "center position"
94     auto rr = SkRRect::MakeRectXY(SkRect::MakeXYWH(fPosition.x() - fSize.width() / 2,
95                                                    fPosition.y() - fSize.height() / 2,
96                                                    fSize.width(), fSize.height()),
97                                   fRadius.width(),
98                                   fRadius.height());
99    fRRectNode->setRRect(rr);
100 }
101 
CompositeTransform(sk_sp<sksg::Matrix> matrix)102 CompositeTransform::CompositeTransform(sk_sp<sksg::Matrix> matrix)
103     : fMatrixNode(std::move(matrix)) {}
104 
apply()105 void CompositeTransform::apply() {
106     SkMatrix t = SkMatrix::MakeTrans(-fAnchorPoint.x(), -fAnchorPoint.y());
107 
108     t.postScale(fScale.x() / 100, fScale.y() / 100); // 100% based
109     t.postRotate(fRotation);
110     t.postTranslate(fPosition.x(), fPosition.y());
111     // TODO: skew
112 
113     fMatrixNode->setMatrix(t);
114 }
115 
CompositePolyStar(sk_sp<sksg::Path> wrapped_node,Type t)116 CompositePolyStar::CompositePolyStar(sk_sp<sksg::Path> wrapped_node, Type t)
117     : fPathNode(std::move(wrapped_node))
118     , fType(t) {}
119 
apply()120 void CompositePolyStar::apply() {
121     const auto count = SkScalarTruncToInt(fPointCount);
122     const auto arc   = SK_ScalarPI * 2 / count;
123 
124     const auto pt_on_circle = [](const SkPoint& c, SkScalar r, SkScalar a) {
125         return SkPoint::Make(c.x() + r * std::cos(a),
126                              c.y() + r * std::sin(a));
127     };
128 
129     // TODO: inner/outer "roundness"?
130 
131     SkPath poly;
132 
133     auto angle = SkDegreesToRadians(fRotation);
134     poly.moveTo(pt_on_circle(fPosition, fOuterRadius, angle));
135 
136     for (int i = 0; i < count; ++i) {
137         if (fType == Type::kStar) {
138             poly.lineTo(pt_on_circle(fPosition, fInnerRadius, angle + arc * 0.5f));
139         }
140         angle += arc;
141         poly.lineTo(pt_on_circle(fPosition, fOuterRadius, angle));
142     }
143 
144     poly.close();
145     fPathNode->setPath(poly);
146 }
147 
CompositeGradient(sk_sp<sksg::Gradient> grad,size_t stopCount)148 CompositeGradient::CompositeGradient(sk_sp<sksg::Gradient> grad, size_t stopCount)
149     : fGradient(std::move(grad))
150     , fStopCount(stopCount) {}
151 
apply()152 void CompositeGradient::apply() {
153     this->onApply();
154 
155     // |fColorStops| holds |fStopCount| x [ pos, r, g, g ] + ? x [ pos, alpha ]
156 
157     if (fColorStops.size() < fStopCount * 4 || ((fColorStops.size() - fStopCount * 4) % 2)) {
158         SkDebugf("!! Invalid gradient stop array size: %zu", fColorStops.size());
159         return;
160     }
161 
162     std::vector<sksg::Gradient::ColorStop> stops;
163 
164     // TODO: merge/lerp opacity stops
165     const auto csEnd = fColorStops.cbegin() + fStopCount * 4;
166     for (auto cs = fColorStops.cbegin(); cs != csEnd; cs += 4) {
167         stops.push_back({ *cs, VecToColor(&*(cs + 1), 3) });
168     }
169 
170     fGradient->setColorStops(std::move(stops));
171 }
172 
CompositeLinearGradient(sk_sp<sksg::LinearGradient> grad,size_t stopCount)173 CompositeLinearGradient::CompositeLinearGradient(sk_sp<sksg::LinearGradient> grad, size_t stopCount)
174     : INHERITED(std::move(grad), stopCount) {}
175 
onApply()176 void CompositeLinearGradient::onApply() {
177     auto* grad = static_cast<sksg::LinearGradient*>(fGradient.get());
178     grad->setStartPoint(this->startPoint());
179     grad->setEndPoint(this->endPoint());
180 }
181 
CompositeRadialGradient(sk_sp<sksg::RadialGradient> grad,size_t stopCount)182 CompositeRadialGradient::CompositeRadialGradient(sk_sp<sksg::RadialGradient> grad, size_t stopCount)
183     : INHERITED(std::move(grad), stopCount) {}
184 
onApply()185 void CompositeRadialGradient::onApply() {
186     auto* grad = static_cast<sksg::RadialGradient*>(fGradient.get());
187     grad->setStartCenter(this->startPoint());
188     grad->setEndCenter(this->startPoint());
189     grad->setStartRadius(0);
190     grad->setEndRadius(SkPoint::Distance(this->startPoint(), this->endPoint()));
191 }
192 
193 } // namespace skottie
194