1094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita/*
2094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita * Copyright 2017 Google Inc.
3094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita *
4094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita * Use of this source code is governed by a BSD-style license that can be
5094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita * found in the LICENSE file.
6094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita */
7094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
854f65c473fd6bf6919dfcbad22e924dff7586568Florin Malita#include "SkottieProperties.h"
9094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
10094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita#include "SkColor.h"
11cf8ed52895239d59341c1ec555d51749531298b4Florin Malita#include "SkJSONCPP.h"
12094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita#include "SkPath.h"
13dcbb2db6d9ceb7b38a8842121a9163ff86cfa8b5Florin Malita#include "SkSGColor.h"
146aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita#include "SkSGGradient.h"
1502a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita#include "SkSGPath.h"
162e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita#include "SkSGRect.h"
17094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita#include "SkSGTransform.h"
18094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
1902a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita#include <cmath>
2002a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
2154f65c473fd6bf6919dfcbad22e924dff7586568Florin Malitanamespace  skottie {
22094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
23094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malitanamespace {
24094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
256aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin MalitaSkColor VecToColor(const float* v, size_t size) {
266aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    // best effort to turn this into a color
276aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    const auto r = size > 0 ? v[0] : 0,
286aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita               g = size > 1 ? v[1] : 0,
296aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita               b = size > 2 ? v[2] : 0,
306aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita               a = size > 3 ? v[3] : 1;
316aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
326aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    return SkColorSetARGB(SkTPin<SkScalar>(a, 0, 1) * 255,
336aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita                          SkTPin<SkScalar>(r, 0, 1) * 255,
346aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita                          SkTPin<SkScalar>(g, 0, 1) * 255,
356aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita                          SkTPin<SkScalar>(b, 0, 1) * 255);
366aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita}
376aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
38094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita} // namespace
39094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
409e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
419e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitasize_t ValueTraits<ScalarValue>::Cardinality(const ScalarValue&) {
429e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    return 1;
439e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita}
449e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita
459e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
469e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
479e1c58cb6adda1a5f7276538c78626d51407f694Florin MalitaSkScalar ValueTraits<ScalarValue>::As<SkScalar>(const ScalarValue& v) {
489e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    return v;
499e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita}
509e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita
519e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
529e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitasize_t ValueTraits<VectorValue>::Cardinality(const VectorValue& vec) {
539e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    return vec.size();
549e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita}
559e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita
569e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
579e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
589e1c58cb6adda1a5f7276538c78626d51407f694Florin MalitaSkColor ValueTraits<VectorValue>::As<SkColor>(const VectorValue& vec) {
596aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    return VecToColor(vec.data(), vec.size());
609e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita}
619e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita
629e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
639e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
649e1c58cb6adda1a5f7276538c78626d51407f694Florin MalitaSkPoint ValueTraits<VectorValue>::As<SkPoint>(const VectorValue& vec) {
659e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    // best effort to turn this into a point
669e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    const auto x = vec.size() > 0 ? vec[0] : 0,
679e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita               y = vec.size() > 1 ? vec[1] : 0;
689e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    return SkPoint::Make(x, y);
699e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita}
709e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita
719e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
729e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitatemplate <>
739e1c58cb6adda1a5f7276538c78626d51407f694Florin MalitaSkSize ValueTraits<VectorValue>::As<SkSize>(const VectorValue& vec) {
749e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    const auto pt = ValueTraits::As<SkPoint>(vec);
759e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    return SkSize::Make(pt.x(), pt.y());
769e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita}
779e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita
78094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malitatemplate <>
799e1c58cb6adda1a5f7276538c78626d51407f694Florin Malitasize_t ValueTraits<ShapeValue>::Cardinality(const ShapeValue& path) {
809e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    return SkTo<size_t>(path.countVerbs());
81094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita}
82094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
83094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malitatemplate <>
842e1d7e234241328154a93b6ddb19f573abc29c15Florin Malitatemplate <>
859e1c58cb6adda1a5f7276538c78626d51407f694Florin MalitaSkPath ValueTraits<ShapeValue>::As<SkPath>(const ShapeValue& path) {
869e1c58cb6adda1a5f7276538c78626d51407f694Florin Malita    return path;
87094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita}
88094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
892e1d7e234241328154a93b6ddb19f573abc29c15Florin MalitaCompositeRRect::CompositeRRect(sk_sp<sksg::RRect> wrapped_node)
902e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita    : fRRectNode(std::move(wrapped_node)) {}
912e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita
922e1d7e234241328154a93b6ddb19f573abc29c15Florin Malitavoid CompositeRRect::apply() {
932e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita    // BM "position" == "center position"
942e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita    auto rr = SkRRect::MakeRectXY(SkRect::MakeXYWH(fPosition.x() - fSize.width() / 2,
952e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita                                                   fPosition.y() - fSize.height() / 2,
962e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita                                                   fSize.width(), fSize.height()),
97fbc13f14340af13ee4c8762d26acec47819f07bcFlorin Malita                                  fRadius.width(),
98fbc13f14340af13ee4c8762d26acec47819f07bcFlorin Malita                                  fRadius.height());
992e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita   fRRectNode->setRRect(rr);
1002e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita}
1012e1d7e234241328154a93b6ddb19f573abc29c15Florin Malita
10218eafd922d911606dfe991efad8ec5eaafbc2704Florin MalitaCompositeTransform::CompositeTransform(sk_sp<sksg::Matrix> matrix)
10318eafd922d911606dfe991efad8ec5eaafbc2704Florin Malita    : fMatrixNode(std::move(matrix)) {}
104094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
105094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malitavoid CompositeTransform::apply() {
106094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita    SkMatrix t = SkMatrix::MakeTrans(-fAnchorPoint.x(), -fAnchorPoint.y());
107094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
108094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita    t.postScale(fScale.x() / 100, fScale.y() / 100); // 100% based
109094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita    t.postRotate(fRotation);
110094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita    t.postTranslate(fPosition.x(), fPosition.y());
111094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita    // TODO: skew
112094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
11318eafd922d911606dfe991efad8ec5eaafbc2704Florin Malita    fMatrixNode->setMatrix(t);
114094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita}
115094ccde2380bfbb615e25d0d80208148fcd47f17Florin Malita
11602a32b0fa432a720d7b41c263756a7bac53b020bFlorin MalitaCompositePolyStar::CompositePolyStar(sk_sp<sksg::Path> wrapped_node, Type t)
11702a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    : fPathNode(std::move(wrapped_node))
11802a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    , fType(t) {}
11902a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
12002a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malitavoid CompositePolyStar::apply() {
12102a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    const auto count = SkScalarTruncToInt(fPointCount);
12202a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    const auto arc   = SK_ScalarPI * 2 / count;
12302a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
12402a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    const auto pt_on_circle = [](const SkPoint& c, SkScalar r, SkScalar a) {
12502a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita        return SkPoint::Make(c.x() + r * std::cos(a),
12602a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita                             c.y() + r * std::sin(a));
12702a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    };
12802a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
12902a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    // TODO: inner/outer "roundness"?
13002a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
13102a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    SkPath poly;
13202a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
13302a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    auto angle = SkDegreesToRadians(fRotation);
13402a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    poly.moveTo(pt_on_circle(fPosition, fOuterRadius, angle));
13502a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
13602a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    for (int i = 0; i < count; ++i) {
13702a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita        if (fType == Type::kStar) {
13802a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita            poly.lineTo(pt_on_circle(fPosition, fInnerRadius, angle + arc * 0.5f));
13902a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita        }
14002a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita        angle += arc;
14102a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita        poly.lineTo(pt_on_circle(fPosition, fOuterRadius, angle));
14202a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    }
14302a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
14402a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    poly.close();
14502a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita    fPathNode->setPath(poly);
14602a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita}
14702a32b0fa432a720d7b41c263756a7bac53b020bFlorin Malita
1486aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin MalitaCompositeGradient::CompositeGradient(sk_sp<sksg::Gradient> grad, size_t stopCount)
1496aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    : fGradient(std::move(grad))
1506aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    , fStopCount(stopCount) {}
1516aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1526aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malitavoid CompositeGradient::apply() {
1536aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    this->onApply();
1546aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1556aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    // |fColorStops| holds |fStopCount| x [ pos, r, g, g ] + ? x [ pos, alpha ]
1566aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1576aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    if (fColorStops.size() < fStopCount * 4 || ((fColorStops.size() - fStopCount * 4) % 2)) {
158cf8ed52895239d59341c1ec555d51749531298b4Florin Malita        SkDebugf("!! Invalid gradient stop array size: %zu", fColorStops.size());
1596aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita        return;
1606aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    }
1616aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1626aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    std::vector<sksg::Gradient::ColorStop> stops;
1636aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1646aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    // TODO: merge/lerp opacity stops
1656aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    const auto csEnd = fColorStops.cbegin() + fStopCount * 4;
1666aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    for (auto cs = fColorStops.cbegin(); cs != csEnd; cs += 4) {
1676aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita        stops.push_back({ *cs, VecToColor(&*(cs + 1), 3) });
1686aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    }
1696aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1706aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    fGradient->setColorStops(std::move(stops));
1716aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita}
1726aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1736aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin MalitaCompositeLinearGradient::CompositeLinearGradient(sk_sp<sksg::LinearGradient> grad, size_t stopCount)
1746aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    : INHERITED(std::move(grad), stopCount) {}
1756aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1766aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malitavoid CompositeLinearGradient::onApply() {
1776aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    auto* grad = static_cast<sksg::LinearGradient*>(fGradient.get());
1786aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    grad->setStartPoint(this->startPoint());
1796aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    grad->setEndPoint(this->endPoint());
1806aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita}
1816aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1826aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin MalitaCompositeRadialGradient::CompositeRadialGradient(sk_sp<sksg::RadialGradient> grad, size_t stopCount)
1836aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    : INHERITED(std::move(grad), stopCount) {}
1846aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
1856aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malitavoid CompositeRadialGradient::onApply() {
1866aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    auto* grad = static_cast<sksg::RadialGradient*>(fGradient.get());
1876aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    grad->setStartCenter(this->startPoint());
1886aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    grad->setEndCenter(this->startPoint());
1896aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    grad->setStartRadius(0);
1906aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita    grad->setEndRadius(SkPoint::Distance(this->startPoint(), this->endPoint()));
1916aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita}
1926aaee59c041ce86d88954b32ba14c6fc29410e9cFlorin Malita
19354f65c473fd6bf6919dfcbad22e924dff7586568Florin Malita} // namespace skottie
194