aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental/skottie/SkottieAdapter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'experimental/skottie/SkottieAdapter.cpp')
-rw-r--r--experimental/skottie/SkottieAdapter.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/experimental/skottie/SkottieAdapter.cpp b/experimental/skottie/SkottieAdapter.cpp
new file mode 100644
index 0000000000..5186e2c2f8
--- /dev/null
+++ b/experimental/skottie/SkottieAdapter.cpp
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkottieAdapter.h"
+
+#include "SkMatrix.h"
+#include "SkottieValue.h"
+#include "SkPath.h"
+#include "SkRRect.h"
+#include "SkSGGradient.h"
+#include "SkSGPath.h"
+#include "SkSGRect.h"
+#include "SkSGTransform.h"
+#include "SkSGTrimEffect.h"
+
+#include <cmath>
+
+namespace skottie {
+
+RRectAdapter::RRectAdapter(sk_sp<sksg::RRect> wrapped_node)
+ : fRRectNode(std::move(wrapped_node)) {}
+
+void RRectAdapter::apply() {
+ // BM "position" == "center position"
+ auto rr = SkRRect::MakeRectXY(SkRect::MakeXYWH(fPosition.x() - fSize.width() / 2,
+ fPosition.y() - fSize.height() / 2,
+ fSize.width(), fSize.height()),
+ fRadius.width(),
+ fRadius.height());
+ fRRectNode->setRRect(rr);
+}
+
+TransformAdapter::TransformAdapter(sk_sp<sksg::Matrix> matrix)
+ : fMatrixNode(std::move(matrix)) {}
+
+void TransformAdapter::apply() {
+ SkMatrix t = SkMatrix::MakeTrans(-fAnchorPoint.x(), -fAnchorPoint.y());
+
+ t.postScale(fScale.x() / 100, fScale.y() / 100); // 100% based
+ t.postRotate(fRotation);
+ t.postTranslate(fPosition.x(), fPosition.y());
+ // TODO: skew
+
+ fMatrixNode->setMatrix(t);
+}
+
+PolyStarAdapter::PolyStarAdapter(sk_sp<sksg::Path> wrapped_node, Type t)
+ : fPathNode(std::move(wrapped_node))
+ , fType(t) {}
+
+void PolyStarAdapter::apply() {
+ const auto count = SkScalarTruncToInt(fPointCount);
+ const auto arc = SK_ScalarPI * 2 / count;
+
+ const auto pt_on_circle = [](const SkPoint& c, SkScalar r, SkScalar a) {
+ return SkPoint::Make(c.x() + r * std::cos(a),
+ c.y() + r * std::sin(a));
+ };
+
+ // TODO: inner/outer "roundness"?
+
+ SkPath poly;
+
+ auto angle = SkDegreesToRadians(fRotation);
+ poly.moveTo(pt_on_circle(fPosition, fOuterRadius, angle));
+
+ for (int i = 0; i < count; ++i) {
+ if (fType == Type::kStar) {
+ poly.lineTo(pt_on_circle(fPosition, fInnerRadius, angle + arc * 0.5f));
+ }
+ angle += arc;
+ poly.lineTo(pt_on_circle(fPosition, fOuterRadius, angle));
+ }
+
+ poly.close();
+ fPathNode->setPath(poly);
+}
+
+GradientAdapter::GradientAdapter(sk_sp<sksg::Gradient> grad, size_t stopCount)
+ : fGradient(std::move(grad))
+ , fStopCount(stopCount) {}
+
+void GradientAdapter::apply() {
+ this->onApply();
+
+ // |fColorStops| holds |fStopCount| x [ pos, r, g, g ] + ? x [ pos, alpha ]
+
+ if (fColorStops.size() < fStopCount * 4 || ((fColorStops.size() - fStopCount * 4) % 2)) {
+ SkDebugf("!! Invalid gradient stop array size: %zu", fColorStops.size());
+ return;
+ }
+
+ std::vector<sksg::Gradient::ColorStop> stops;
+
+ // TODO: merge/lerp opacity stops
+ const auto csEnd = fColorStops.cbegin() + fStopCount * 4;
+ for (auto cs = fColorStops.cbegin(); cs != csEnd; cs += 4) {
+ const auto pos = cs[0];
+ const VectorValue rgb({ cs[1], cs[2], cs[3] });
+
+ stops.push_back({ pos, ValueTraits<VectorValue>::As<SkColor>(rgb) });
+ }
+
+ fGradient->setColorStops(std::move(stops));
+}
+
+LinearGradientAdapter::LinearGradientAdapter(sk_sp<sksg::LinearGradient> grad, size_t stopCount)
+ : INHERITED(std::move(grad), stopCount) {}
+
+void LinearGradientAdapter::onApply() {
+ auto* grad = static_cast<sksg::LinearGradient*>(fGradient.get());
+ grad->setStartPoint(this->startPoint());
+ grad->setEndPoint(this->endPoint());
+}
+
+RadialGradientAdapter::RadialGradientAdapter(sk_sp<sksg::RadialGradient> grad, size_t stopCount)
+ : INHERITED(std::move(grad), stopCount) {}
+
+void RadialGradientAdapter::onApply() {
+ auto* grad = static_cast<sksg::RadialGradient*>(fGradient.get());
+ grad->setStartCenter(this->startPoint());
+ grad->setEndCenter(this->startPoint());
+ grad->setStartRadius(0);
+ grad->setEndRadius(SkPoint::Distance(this->startPoint(), this->endPoint()));
+}
+
+TrimEffectAdapter::TrimEffectAdapter(sk_sp<sksg::TrimEffect> trimEffect)
+ : fTrimEffect(std::move(trimEffect)) {
+ SkASSERT(fTrimEffect);
+}
+
+void TrimEffectAdapter::apply() {
+ // BM semantics: start/end are percentages, offset is "degrees" (?!).
+ const auto start = fStart / 100,
+ end = fEnd / 100,
+ offset = fOffset / 360;
+
+ auto startT = SkTMin(start, end) + offset,
+ stopT = SkTMax(start, end) + offset;
+ auto mode = SkTrimPathEffect::Mode::kNormal;
+
+ if (stopT - startT < 1) {
+ startT -= SkScalarFloorToScalar(startT);
+ stopT -= SkScalarFloorToScalar(stopT);
+
+ if (startT > stopT) {
+ SkTSwap(startT, stopT);
+ mode = SkTrimPathEffect::Mode::kInverted;
+ }
+ } else {
+ startT = 0;
+ stopT = 1;
+ }
+
+ fTrimEffect->setStart(startT);
+ fTrimEffect->setStop(stopT);
+ fTrimEffect->setMode(mode);
+}
+
+} // namespace skottie