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