SkShadowTessellator.cpp revision 060d9820364b0cf09c7eb3bda449f24c3dcba2e2
1bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth/* 2bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth * Copyright 2017 Google Inc. 3bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth * 4bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth * Use of this source code is governed by a BSD-style license that can be 5bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth * found in the LICENSE file. 6bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth */ 7bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 8efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verth#include "SkShadowTessellator.h" 966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon#include "SkColorPriv.h" 1058abc9e2c56464336472493745e91133819deb96Jim Van Verth#include "SkGeometry.h" 11ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon#include "SkInsetConvexPolygon.h" 1285dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#include "SkPath.h" 13aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon#include "SkVertices.h" 1485dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth 1585dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#if SK_SUPPORT_GPU 1685dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#include "GrPathUtils.h" 1785dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#endif 1858abc9e2c56464336472493745e91133819deb96Jim Van Verth 19958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 20a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth/** 21a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth * Base class 22a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth */ 23aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkBaseShadowTessellator { 24958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonpublic: 25b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkBaseShadowTessellator(SkShadowTessellator::HeightFunc, bool transparent); 26aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon virtual ~SkBaseShadowTessellator() {} 270dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 28aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon sk_sp<SkVertices> releaseVertices() { 29aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon if (!fSucceeded) { 30aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return nullptr; 31aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon } 32887cdf112809727c51890ba8b98b3ddce22249f0Mike Reed return SkVertices::MakeCopy(SkVertices::kTriangles_VertexMode, this->vertexCount(), 3397eb4feb112967ba7fcb00d6995adda1002873c2Mike Reed fPositions.begin(), nullptr, fColors.begin(), 3497eb4feb112967ba7fcb00d6995adda1002873c2Mike Reed this->indexCount(), fIndices.begin()); 351a8b79a79e8aa6d4723588fd1125cb3b08886af8Brian Salomon } 36958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 37a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthprotected: 38da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth static constexpr auto kMinHeight = 0.1f; 39da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 40aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon int vertexCount() const { return fPositions.count(); } 41aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon int indexCount() const { return fIndices.count(); } 42aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon 43da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth bool setZOffset(const SkRect& bounds, bool perspective); 44da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 45a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth virtual void handleLine(const SkPoint& p) = 0; 46a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkMatrix& m, SkPoint* p); 47958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 48958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon void handleQuad(const SkPoint pts[3]); 49a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleQuad(const SkMatrix& m, SkPoint pts[3]); 50958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 51a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleCubic(const SkMatrix& m, SkPoint pts[4]); 52958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 53a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleConic(const SkMatrix& m, SkPoint pts[3], SkScalar w); 54958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 55da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth bool setTransformedHeightFunc(const SkMatrix& ctm); 56da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 57e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth bool addArc(const SkVector& nextNormal, bool finishArc); 58958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 59da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkShadowTessellator::HeightFunc fHeightFunc; 60da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth std::function<SkScalar(const SkPoint&)> fTransformedHeightFunc; 61da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fZOffset; 62da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // members for perspective height function 63da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fZParams[3]; 64da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fPartialDeterminants[3]; 65b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 66da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // first two points 67a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkTDArray<SkPoint> fInitPoints; 68a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // temporary buffer 69a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkTDArray<SkPoint> fPointBuffer; 70958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 71958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<SkPoint> fPositions; 72958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<SkColor> fColors; 73958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<uint16_t> fIndices; 74958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 75958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon int fFirstVertex; 76958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkVector fFirstNormal; 77a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fFirstPoint; 780dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 790dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon bool fSucceeded; 80a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth bool fTransparent; 81a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 82a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkColor fUmbraColor; 83a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkColor fPenumbraColor; 84a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 85a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar fRadius; 86a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar fDirection; 87a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int fPrevUmbraIndex; 88a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkVector fPrevNormal; 89a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fPrevPoint; 90958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon}; 91958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 92da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verthstatic bool compute_normal(const SkPoint& p0, const SkPoint& p1, SkScalar dir, 93bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector* newNormal) { 94bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 95bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // compute perpendicular 96bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth normal.fX = p0.fY - p1.fY; 97bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth normal.fY = p1.fX - p0.fX; 98da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= dir; 99bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (!normal.normalize()) { 100bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return false; 101bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 102bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *newNormal = normal; 103bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return true; 104bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 105bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 106bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verthstatic void compute_radial_steps(const SkVector& v1, const SkVector& v2, SkScalar r, 107bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar* rotSin, SkScalar* rotCos, int* n) { 108e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth const SkScalar kRecipPixelsPerArcSegment = 0.125f; 109bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 110bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar rCos = v1.dot(v2); 111bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar rSin = v1.cross(v2); 112bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar theta = SkScalarATan2(rSin, rCos); 113bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 114e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth int steps = SkScalarFloorToInt(r*theta*kRecipPixelsPerArcSegment); 115bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 116bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar dTheta = theta / steps; 117bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *rotSin = SkScalarSinCos(dTheta, rotCos); 118e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *n = steps; 119bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 120bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 121b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van VerthSkBaseShadowTessellator::SkBaseShadowTessellator(SkShadowTessellator::HeightFunc heightFunc, 122b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth bool transparent) 123b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth : fHeightFunc(heightFunc) 124da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fZOffset(0) 125b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth , fFirstVertex(-1) 126aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fSucceeded(false) 127aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fTransparent(transparent) 128aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fDirection(1) 129aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fPrevUmbraIndex(-1) { 130a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fInitPoints.setReserve(3); 131a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 132a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // child classes will set reserve for positions, colors and indices 133a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 134a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 135da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verthbool SkBaseShadowTessellator::setZOffset(const SkRect& bounds, bool perspective) { 136da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar minZ = fHeightFunc(bounds.fLeft, bounds.fTop); 137da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (perspective) { 138da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar z = fHeightFunc(bounds.fLeft, bounds.fBottom); 139da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (z < minZ) { 140da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth minZ = z; 141da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 142da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth z = fHeightFunc(bounds.fRight, bounds.fTop); 143da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (z < minZ) { 144da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth minZ = z; 145da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 146da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth z = fHeightFunc(bounds.fRight, bounds.fBottom); 147da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (z < minZ) { 148da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth minZ = z; 149da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 150da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 151da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 152da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (minZ < kMinHeight) { 153da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZOffset = -minZ + kMinHeight; 154da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return true; 155da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 156da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 157da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return false; 158da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth} 159da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 160a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth// tesselation tolerance values, in device space pixels 161b8b51e6b2f431c89907139bec52ed64b7ed303edMike Klein#if SK_SUPPORT_GPU 162a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kQuadTolerance = 0.2f; 163a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kCubicTolerance = 0.2f; 164b8b51e6b2f431c89907139bec52ed64b7ed303edMike Klein#endif 165a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kConicTolerance = 0.5f; 166a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 167aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleLine(const SkMatrix& m, SkPoint* p) { 168a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(p, 1); 169a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(*p); 170a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 171a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 172aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleQuad(const SkPoint pts[3]) { 173a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#if SK_SUPPORT_GPU 174a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // TODO: Pull PathUtils out of Ganesh? 175a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); 176a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setReserve(maxCount); 177a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint* target = fPointBuffer.begin(); 178a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], 179a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth kQuadTolerance, &target, maxCount); 180a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setCount(count); 181a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; i++) { 182a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(fPointBuffer[i]); 183a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 184a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#else 185a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // for now, just to draw something 186a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[1]); 187a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[2]); 188a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#endif 189a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 190a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 191aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleQuad(const SkMatrix& m, SkPoint pts[3]) { 192a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 3); 193a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(pts); 194a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 195a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 196aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleCubic(const SkMatrix& m, SkPoint pts[4]) { 197a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 4); 198a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#if SK_SUPPORT_GPU 199a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // TODO: Pull PathUtils out of Ganesh? 200a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance); 201a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setReserve(maxCount); 202a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint* target = fPointBuffer.begin(); 203a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], 204a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth kCubicTolerance, &target, maxCount); 205a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setCount(count); 206a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; i++) { 207a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(fPointBuffer[i]); 208a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 209a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#else 210a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // for now, just to draw something 211a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[1]); 212a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[2]); 213a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[3]); 214a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#endif 215a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 216a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 217aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleConic(const SkMatrix& m, SkPoint pts[3], SkScalar w) { 218da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (m.hasPerspective()) { 219da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth w = SkConic::TransformW(pts, w, m); 220da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 221a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 3); 222a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkAutoConicToQuads quadder; 223a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance); 224a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint lastPoint = *(quads++); 225a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = quadder.countQuads(); 226a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; ++i) { 227a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint quadPts[3]; 228a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[0] = lastPoint; 229a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[1] = quads[0]; 230a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[2] = i == count - 1 ? pts[2] : quads[1]; 231a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(quadPts); 232a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth lastPoint = quadPts[2]; 233a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quads += 2; 234a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 235a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 236a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 237e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verthbool SkBaseShadowTessellator::addArc(const SkVector& nextNormal, bool finishArc) { 238a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // fill in fan from previous quad 239a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar rotSin, rotCos; 240a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int numSteps; 241a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth compute_radial_steps(fPrevNormal, nextNormal, fRadius, &rotSin, &rotCos, &numSteps); 242a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkVector prevNormal = fPrevNormal; 243e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth for (int i = 0; i < numSteps-1; ++i) { 244da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector currNormal; 245da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth currNormal.fX = prevNormal.fX*rotCos - prevNormal.fY*rotSin; 246da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth currNormal.fY = prevNormal.fY*rotCos + prevNormal.fX*rotSin; 247da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fPrevPoint + currNormal; 248a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fColors.push() = fPenumbraColor; 249a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPrevUmbraIndex; 250a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPositions.count() - 1; 251e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 2; 252a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 253da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth prevNormal = currNormal; 254a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 255e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (finishArc && numSteps) { 256da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fPrevPoint + nextNormal; 257da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = fPenumbraColor; 258da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 259da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 260e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 2; 261da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 262da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPrevNormal = nextNormal; 263e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth 264e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth return (numSteps > 0); 265a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 266a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 267da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verthbool SkBaseShadowTessellator::setTransformedHeightFunc(const SkMatrix& ctm) { 268da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!ctm.hasPerspective()) { 269da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fTransformedHeightFunc = [this](const SkPoint& p) { 270da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return this->fHeightFunc(0, 0); 271da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth }; 272da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 273da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkMatrix ctmInverse; 274da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!ctm.invert(&ctmInverse)) { 275da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return false; 276da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 277da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar C = fHeightFunc(0, 0); 278da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar A = fHeightFunc(1, 0) - C; 279da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar B = fHeightFunc(0, 1) - C; 280da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 281da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // multiply by transpose 282da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZParams[0] = ctmInverse[SkMatrix::kMScaleX] * A + 283da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctmInverse[SkMatrix::kMSkewY] * B + 284da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctmInverse[SkMatrix::kMPersp0] * C; 285da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZParams[1] = ctmInverse[SkMatrix::kMSkewX] * A + 286da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctmInverse[SkMatrix::kMScaleY] * B + 287da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctmInverse[SkMatrix::kMPersp1] * C; 288da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZParams[2] = ctmInverse[SkMatrix::kMTransX] * A + 289da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctmInverse[SkMatrix::kMTransY] * B + 290da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctmInverse[SkMatrix::kMPersp2] * C; 291da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 292da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // We use Cramer's rule to solve for the W value for a given post-divide X and Y, 293da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // so pre-compute those values that are independent of X and Y. 294da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // W is det(ctmInverse)/(PD[0]*X + PD[1]*Y + PD[2]) 295da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPartialDeterminants[0] = ctm[SkMatrix::kMSkewY] * ctm[SkMatrix::kMPersp1] - 296da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctm[SkMatrix::kMScaleY] * ctm[SkMatrix::kMPersp0]; 297da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPartialDeterminants[1] = ctm[SkMatrix::kMPersp0] * ctm[SkMatrix::kMSkewX] - 298da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctm[SkMatrix::kMPersp1] * ctm[SkMatrix::kMScaleX]; 299da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPartialDeterminants[2] = ctm[SkMatrix::kMScaleX] * ctm[SkMatrix::kMScaleY] - 300da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctm[SkMatrix::kMSkewX] * ctm[SkMatrix::kMSkewY]; 301da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar ctmDeterminant = ctm[SkMatrix::kMTransX] * fPartialDeterminants[0] + 302da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctm[SkMatrix::kMTransY] * fPartialDeterminants[1] + 303da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth ctm[SkMatrix::kMPersp2] * fPartialDeterminants[2]; 304da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 305da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Pre-bake the numerator of Cramer's rule into the zParams to avoid another multiply. 306da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // TODO: this may introduce numerical instability, but I haven't seen any issues yet. 307da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZParams[0] *= ctmDeterminant; 308da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZParams[1] *= ctmDeterminant; 309da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZParams[2] *= ctmDeterminant; 310da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 311da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fTransformedHeightFunc = [this](const SkPoint& p) { 312da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar denom = p.fX * this->fPartialDeterminants[0] + 313da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth p.fY * this->fPartialDeterminants[1] + 314da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->fPartialDeterminants[2]; 315da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar w = SkScalarFastInvert(denom); 316da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return (this->fZParams[0] * p.fX + this->fZParams[1] * p.fY + this->fZParams[2])*w + 317da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->fZOffset; 318da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth }; 319da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 320a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 321da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return true; 322a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 323a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 324a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 325a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth////////////////////////////////////////////////////////////////////////////////////////////////// 326a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 327aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkAmbientShadowTessellator : public SkBaseShadowTessellator { 328a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthpublic: 329a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm, 330060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkShadowTessellator::HeightFunc heightFunc, bool transparent); 331a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 332a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthprivate: 333a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkPoint& p) override; 334da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth void addEdge(const SkVector& nextPoint, const SkVector& nextNormal); 335da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 336da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth static constexpr auto kHeightFactor = 1.0f / 128.0f; 337da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth static constexpr auto kGeomFactor = 64.0f; 338da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth static constexpr auto kMaxEdgeLenSqr = 20 * 20; 339a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 340da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar offset(SkScalar z) { 341da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return z * kHeightFactor * kGeomFactor; 342da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 343da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkColor umbraColor(SkScalar z) { 344da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(z*kHeightFactor, 0.0f))); 345060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth return SkColorSetARGB(umbraAlpha * 255.9999f, 0, 0, 0); 346da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 347da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 348a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int fCentroidCount; 349a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 350aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon typedef SkBaseShadowTessellator INHERITED; 351a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth}; 352a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 353efe3dedbb3493b738abdb56041b093245e4e8711Jim Van VerthSkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, 354a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth const SkMatrix& ctm, 355b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkShadowTessellator::HeightFunc heightFunc, 356bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth bool transparent) 357060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth : INHERITED(heightFunc, transparent) { 358da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Set base colors 359b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkScalar occluderHeight = heightFunc(0, 0); 360b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(occluderHeight*kHeightFactor, 0.0f))); 361b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // umbraColor is the interior value, penumbraColor the exterior value. 362b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // umbraAlpha is the factor that is linearly interpolated from outside to inside, and 363b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // then "blurred" by the GrBlurredEdgeFP. It is then multiplied by fAmbientAlpha to get 364b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // the final alpha. 365060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fUmbraColor = SkColorSetARGB(umbraAlpha * 255.9999f, 0, 0, 0); 366060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fPenumbraColor = SkColorSetARGB(0, 0, 0, 0); 367b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 368da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // make sure we're not below the canvas plane 369da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->setZOffset(path.getBounds(), ctm.hasPerspective()); 370da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 371da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->setTransformedHeightFunc(ctm); 372da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 373bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Outer ring: 3*numPts 374bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Middle ring: numPts 375bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions.setReserve(4 * path.countPoints()); 376bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fColors.setReserve(4 * path.countPoints()); 377bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Outer ring: 12*numPts 378bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Middle ring: 0 379bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fIndices.setReserve(12 * path.countPoints()); 380bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 381bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // walk around the path, tessellate and generate outer ring 382bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if original path is transparent, will accumulate sum of points for centroid 383bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPath::Iter iter(path, true); 384bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPoint pts[4]; 385bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPath::Verb verb; 386bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 387bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = SkPoint::Make(0, 0); 388b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth *fColors.push() = fUmbraColor; 389bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fCentroidCount = 0; 390bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 391bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 392bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth switch (verb) { 393bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kLine_Verb: 394a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->INHERITED::handleLine(ctm, &pts[1]); 395bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 396bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kQuad_Verb: 397a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(ctm, pts); 398bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 399bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kCubic_Verb: 400a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleCubic(ctm, pts); 401bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 402bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kConic_Verb: 403a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleConic(ctm, pts, iter.conicWeight()); 404bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 405bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kMove_Verb: 406bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kClose_Verb: 407bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kDone_Verb: 408bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 409bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 410bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 411bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 4120dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon if (!this->indexCount()) { 4130dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon return; 4140dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon } 4150dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 416bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 417da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (compute_normal(fPrevPoint, fFirstPoint, fDirection, &normal)) { 418da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar z = fTransformedHeightFunc(fPrevPoint); 419da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(z); 420da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector scaledNormal(normal); 421da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth scaledNormal *= fRadius; 422da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(scaledNormal, true); 423da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 424da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // set up for final edge 425da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth z = fTransformedHeightFunc(fFirstPoint); 426da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= this->offset(z); 427da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 428da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // make sure we don't end up with a sharp alpha edge along the quad diagonal 429da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] != fColors[fFirstVertex] && 430da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fFirstPoint.distanceToSqd(fPositions[fPrevUmbraIndex]) > kMaxEdgeLenSqr) { 431da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkPoint centerPoint = fPositions[fPrevUmbraIndex] + fFirstPoint; 432da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth centerPoint *= 0.5f; 433da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = centerPoint; 434da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkPMLerp(fColors[fFirstVertex], fColors[fPrevUmbraIndex], 128); 435da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector midNormal = fPrevNormal + normal; 436da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth midNormal *= 0.5f; 437da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = centerPoint + midNormal; 438da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = fPenumbraColor; 439bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 440da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 441da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 442da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 443bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 444da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 445da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 446da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 447da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 448da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPrevUmbraIndex = fPositions.count() - 2; 449da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 450da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 451da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // final edge 452a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fPositions.push() = fFirstPoint + normal; 453bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 454bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 455da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] > fColors[fFirstVertex]) { 456da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 457da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 458da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fFirstVertex; 459bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 460da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 461da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 462da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fFirstVertex; 463da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 464da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 465da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 466da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 467da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 468da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 469da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 470da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fFirstVertex; 471da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 472da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPrevNormal = normal; 473bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 474bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 475bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // finalize centroid 476bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 477bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions[0] *= SkScalarFastInvert(fCentroidCount); 478bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 479bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = 0; 48066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 481bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fFirstVertex; 482bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 483bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 484bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // final fan 485bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fPositions.count() >= 3) { 48666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fFirstVertex; 487a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = fFirstPoint; 488da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(fTransformedHeightFunc(fPrevPoint)); 489e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (this->addArc(fFirstNormal, false)) { 490e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fFirstVertex; 491e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 1; 492e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fFirstVertex + 1; 493e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } else { 494e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth // arc is too small, set the first penumbra point to be the same position 495e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth // as the last one 496e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth fPositions[fFirstVertex + 1] = fPositions[fPositions.count() - 1]; 497e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } 498bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 4990dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon fSucceeded = true; 500bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 501bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 502efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkAmbientShadowTessellator::handleLine(const SkPoint& p) { 503bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fInitPoints.count() < 2) { 504bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fInitPoints.push() = p; 505bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 506bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 507bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 508bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fInitPoints.count() == 2) { 509bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // determine if cw or ccw 510bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector v0 = fInitPoints[1] - fInitPoints[0]; 511bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector v1 = p - fInitPoints[0]; 512bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar perpDot = v0.fX*v1.fY - v0.fY*v1.fX; 513bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (SkScalarNearlyZero(perpDot)) { 514bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // nearly parallel, just treat as straight line and continue 515bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fInitPoints[1] = p; 516bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 517bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 518bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 519bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if perpDot > 0, winding is ccw 520bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fDirection = (perpDot > 0) ? -1 : 1; 521bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 522bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // add first quad 523da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector normal; 524da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!compute_normal(fInitPoints[0], fInitPoints[1], fDirection, &normal)) { 525bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // first two points are incident, make the third point the second and continue 526bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fInitPoints[1] = p; 527bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 528bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 529bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 530a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fFirstPoint = fInitPoints[0]; 531bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fFirstVertex = fPositions.count(); 532da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar z = fTransformedHeightFunc(fFirstPoint); 533da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fFirstNormal = normal; 534da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fFirstNormal *= this->offset(z); 535da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 536bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPrevNormal = fFirstNormal; 537a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = fFirstPoint; 53866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fFirstVertex; 539bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 540da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fFirstPoint; 541da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = this->umbraColor(z); 542da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fFirstPoint + fFirstNormal; 543bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 544bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 545da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPositions[0] += fFirstPoint; 546bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fCentroidCount = 1; 547bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 548da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 549da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // add the first quad 550da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth z = fTransformedHeightFunc(fInitPoints[1]); 551da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(z); 552da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fUmbraColor = this->umbraColor(z); 553da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= fRadius; 554da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addEdge(fInitPoints[1], normal); 555bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 556bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // to ensure we skip this block next time 557bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fInitPoints.push() = p; 558bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 559bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 560bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 561da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (compute_normal(fPositions[fPrevUmbraIndex], p, fDirection, &normal)) { 562da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector scaledNormal = normal; 563da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth scaledNormal *= fRadius; 564da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(scaledNormal, true); 565da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar z = fTransformedHeightFunc(p); 566da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(z); 567da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fUmbraColor = this->umbraColor(z); 568da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= fRadius; 569da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addEdge(p, normal); 570bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 571bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 572bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 573efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { 574da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // make sure we don't end up with a sharp alpha edge along the quad diagonal 575da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] != fUmbraColor && 576da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth nextPoint.distanceToSqd(fPositions[fPrevUmbraIndex]) > kMaxEdgeLenSqr) { 577da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkPoint centerPoint = fPositions[fPrevUmbraIndex] + nextPoint; 578da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth centerPoint *= 0.5f; 579da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = centerPoint; 580da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkPMLerp(fUmbraColor, fColors[fPrevUmbraIndex], 128); 581da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector midNormal = fPrevNormal + nextNormal; 582da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth midNormal *= 0.5f; 583da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = centerPoint + midNormal; 584da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = fPenumbraColor; 585da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 586da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // set triangularization to get best interpolation of color 587da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] > fColors[fPositions.count() - 2]) { 588da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 589da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 590da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 591da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 592da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 593da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 594da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 595da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 596da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 597da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 598da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 599da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 600da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 601da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 602da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 603da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 604da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 605da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPrevUmbraIndex = fPositions.count() - 2; 606da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 607da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 608bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // add next quad 609bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = nextPoint; 610bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fUmbraColor; 611bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = nextPoint + nextNormal; 612bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 613bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 614da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // set triangularization to get best interpolation of color 615da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] > fColors[fPositions.count() - 2]) { 616da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 617da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 618da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 619bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 620da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 621da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 622da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 623da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 624da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 625da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 626da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 627da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 628da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 629da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 630da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 631da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 632bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 633bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if transparent, add point to first one in array and add to center fan 634bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 635bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions[0] += nextPoint; 636bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth ++fCentroidCount; 637bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 638bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = 0; 63966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 640bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 641bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 642bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 64366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fPositions.count() - 2; 644bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPrevNormal = nextNormal; 645a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = nextPoint; 646bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 64791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 64891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth/////////////////////////////////////////////////////////////////////////////////////////////////// 64991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 650aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkSpotShadowTessellator : public SkBaseShadowTessellator { 651958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonpublic: 652a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, 653060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkShadowTessellator::HeightFunc heightFunc, const SkPoint3& lightPos, 654060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkScalar lightRadius, bool transparent); 655958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 656958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonprivate: 657ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon void computeClipAndPathPolygons(const SkPath& path, const SkMatrix& ctm, 658da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth const SkMatrix& shadowTransform); 659ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon void computeClipVectorsAndTestCentroid(); 66066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, SkPoint* clipPoint); 661ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int getClosestUmbraPoint(const SkPoint& point); 662958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 663a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkPoint& p) override; 664ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon void handlePolyPoint(const SkPoint& p); 665958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 666958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon void mapPoints(SkScalar scale, const SkVector& xlate, SkPoint* pts, int count); 667ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon bool addInnerPoint(const SkPoint& pathPoint); 668da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth void addEdge(const SkVector& nextPoint, const SkVector& nextNormal); 669da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 670da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar offset(SkScalar z) { 671da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth float zRatio = SkTPin(z / (fLightZ - z), 0.0f, 0.95f); 672da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return fLightRadius*zRatio; 673da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 674da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 675da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fLightZ; 676da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fLightRadius; 677da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fOffsetAdjust; 678958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 679958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<SkPoint> fClipPolygon; 68066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkTDArray<SkVector> fClipVectors; 681a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fCentroid; 682ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar fArea; 683a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 684ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkTDArray<SkPoint> fPathPolygon; 685ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkTDArray<SkPoint> fUmbraPolygon; 686ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int fCurrClipPoint; 687ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int fCurrUmbraPoint; 68866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool fPrevUmbraOutside; 68966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool fFirstUmbraOutside; 690a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth bool fValidUmbra; 691958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 692aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon typedef SkBaseShadowTessellator INHERITED; 693958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon}; 694958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 695a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van VerthSkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, 696b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkShadowTessellator::HeightFunc heightFunc, 697b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth const SkPoint3& lightPos, SkScalar lightRadius, 698060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth bool transparent) 699da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth : INHERITED(heightFunc, transparent) 700da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fLightZ(lightPos.fZ) 701da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fLightRadius(lightRadius) 702da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fOffsetAdjust(0) 703da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fCurrClipPoint(0) 704da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fPrevUmbraOutside(false) 705da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fFirstUmbraOutside(false) 706da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fValidUmbra(true) { 707da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 708da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // make sure we're not below the canvas plane 709da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (this->setZOffset(path.getBounds(), ctm.hasPerspective())) { 710da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Adjust light height and radius 711da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fLightRadius *= (fLightZ + fZOffset) / fLightZ; 712da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fLightZ += fZOffset; 713da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 714b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 715b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // Set radius and colors 716b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY()); 717da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar occluderHeight = heightFunc(center.fX, center.fY) + fZOffset; 718da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth float zRatio = SkTPin(occluderHeight / (fLightZ - occluderHeight), 0.0f, 0.95f); 719b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkScalar radius = lightRadius * zRatio; 720b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth fRadius = radius; 721060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fUmbraColor = SkColorSetARGB(255, 0, 0, 0); 722060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fPenumbraColor = SkColorSetARGB(0, 0, 0, 0); 723b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 724b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // Compute the scale and translation for the spot shadow. 725da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkMatrix shadowTransform; 726da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!ctm.hasPerspective()) { 727da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar scale = fLightZ / (fLightZ - occluderHeight); 728da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector translate = SkVector::Make(-zRatio * lightPos.fX, -zRatio * lightPos.fY); 729da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth shadowTransform.setScaleTranslate(scale, scale, translate.fX, translate.fY); 730da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 731da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // For perspective, we have a scale, a z-shear, and another projective divide -- 732da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // this varies at each point so we can't use an affine transform. 733da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // We'll just apply this to each generated point in turn. 734da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth shadowTransform.reset(); 735da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Also can't cull the center (for now). 736da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fTransparent = true; 737da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 738da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkMatrix fullTransform = SkMatrix::Concat(shadowTransform, ctm); 739da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 740da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Set up our reverse mapping 741da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->setTransformedHeightFunc(fullTransform); 742b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 743ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // TODO: calculate these reserves better 74466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Penumbra ring: 3*numPts 74566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Umbra ring: numPts 74691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // Inner ring: numPts 74766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPositions.setReserve(5 * path.countPoints()); 74866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fColors.setReserve(5 * path.countPoints()); 74966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Penumbra ring: 12*numPts 75066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Umbra ring: 3*numPts 75166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fIndices.setReserve(15 * path.countPoints()); 752e7c85c45c4c0a97adc6711bb12ecacc36af4ba11Brian Salomon fClipPolygon.setReserve(path.countPoints()); 753ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 754ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // compute rough clip bounds for umbra, plus offset polygon, plus centroid 755da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->computeClipAndPathPolygons(path, ctm, shadowTransform); 756ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fClipPolygon.count() < 3 || fPathPolygon.count() < 3) { 75766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return; 75866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 75966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 760ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // check to see if umbra collapses 761ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar minDistSq = fCentroid.distanceToLineSegmentBetweenSqd(fPathPolygon[0], 762ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon[1]); 763da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkRect bounds; 764da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth bounds.setBounds(&fPathPolygon[0], fPathPolygon.count()); 765ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon for (int i = 1; i < fPathPolygon.count(); ++i) { 766ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int j = i + 1; 767ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (i == fPathPolygon.count() - 1) { 768ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon j = 0; 769ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 770ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint currPoint = fPathPolygon[i]; 771ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint nextPoint = fPathPolygon[j]; 772ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar distSq = fCentroid.distanceToLineSegmentBetweenSqd(currPoint, nextPoint); 773ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (distSq < minDistSq) { 774ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon minDistSq = distSq; 775ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 776ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 777ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr auto kTolerance = 1.0e-2f; 778ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (minDistSq < (radius + kTolerance)*(radius + kTolerance)) { 779ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // if the umbra would collapse, we back off a bit on inner blur and adjust the alpha 780ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar newRadius = SkScalarSqrt(minDistSq) - kTolerance; 781da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fOffsetAdjust = newRadius - radius; 782b6069dfba7b7ab563a3fccb2f38307e47035300cJim Van Verth SkScalar ratio = 128 * (newRadius + radius) / radius; 783ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // they aren't PMColors, but the interpolation algorithm is the same 784ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fUmbraColor = SkPMLerp(fUmbraColor, fPenumbraColor, (unsigned)ratio); 785ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon radius = newRadius; 786ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 787e5f5bf5175e426ebb6aa234f4387831c898f20adJim Van Verth 788ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // compute vectors for clip tests 789ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->computeClipVectorsAndTestCentroid(); 790ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 791ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // generate inner ring 792da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!SkInsetConvexPolygon(&fPathPolygon[0], fPathPolygon.count(), radius, 793da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth &fUmbraPolygon)) { 794ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // this shouldn't happen, but just in case we'll inset using the centroid 795ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fValidUmbra = false; 796ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 797ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 798ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // walk around the path polygon, generate outer ring and connect to inner ring 79966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fTransparent) { 80066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = fCentroid; 80166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 80266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 803ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrUmbraPoint = 0; 804ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon for (int i = 0; i < fPathPolygon.count(); ++i) { 805ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handlePolyPoint(fPathPolygon[i]); 80691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 80791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 8080dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon if (!this->indexCount()) { 8090dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon return; 8100dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon } 8110dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 812ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // finish up the final verts 81391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector normal; 814da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (compute_normal(fPrevPoint, fFirstPoint, fDirection, &normal)) { 815da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= fRadius; 816da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(normal, true); 81791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 81866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add to center fan 81966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fTransparent) { 82066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = 0; 82166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 82266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex; 82366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // or to clip ring 82466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 82566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fFirstUmbraOutside) { 82666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 82766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex; 82866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex + 1; 82966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fPrevUmbraOutside) { 83066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // fill out quad 83166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 83266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex + 1; 83366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 83466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 83566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (fPrevUmbraOutside) { 83666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add tri 83766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 83866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex; 83966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 84066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 84166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 84266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 84391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // add final edge 84491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = fFirstPoint + normal; 84591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 84691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 84766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 84891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 2; 84991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fFirstVertex; 85091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 85191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 2; 85291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 85391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fFirstVertex; 854da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 855da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPrevNormal = normal; 85691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 85791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 85891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // final fan 85991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fPositions.count() >= 3) { 86066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fFirstVertex; 86191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = fFirstPoint; 862e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (this->addArc(fFirstNormal, false)) { 863e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fFirstVertex; 864e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 1; 865e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (fFirstUmbraOutside) { 866e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fFirstVertex + 2; 867e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } else { 868e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fFirstVertex + 1; 869e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } 87066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 871e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth // no arc added, fix up by setting first penumbra point position to last one 872e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (fFirstUmbraOutside) { 873e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth fPositions[fFirstVertex + 2] = fPositions[fPositions.count() - 1]; 874e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } else { 875e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth fPositions[fFirstVertex + 1] = fPositions[fPositions.count() - 1]; 876e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } 87766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 87891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 879da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 880da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (ctm.hasPerspective()) { 881da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth for (int i = 0; i < fPositions.count(); ++i) { 882da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar pathZ = fTransformedHeightFunc(fPositions[i]); 883da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar factor = SkScalarInvert(fLightZ - pathZ); 884da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPositions[i].fX = (fPositions[i].fX*fLightZ - lightPos.fX*pathZ)*factor; 885da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPositions[i].fY = (fPositions[i].fY*fLightZ - lightPos.fY*pathZ)*factor; 886da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 887da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#ifdef DRAW_CENTROID 888da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar pathZ = fTransformedHeightFunc(fCentroid); 889da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar factor = SkScalarInvert(fLightZ - pathZ); 890da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fCentroid.fX = (fCentroid.fX*fLightZ - lightPos.fX*pathZ)*factor; 891da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fCentroid.fY = (fCentroid.fY*fLightZ - lightPos.fY*pathZ)*factor; 892da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#endif 893da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 894da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#ifdef DRAW_CENTROID 895da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(-2, -2); 896da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 897da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(2, -2); 898da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 899da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(-2, 2); 900da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 901da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(2, 2); 902da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 903da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 904da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 4; 905da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 906da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 907da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 908da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 4; 909da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 910da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 911da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#endif 912da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 9130dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon fSucceeded = true; 91491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 91591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 916ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonvoid SkSpotShadowTessellator::computeClipAndPathPolygons(const SkPath& path, const SkMatrix& ctm, 917da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth const SkMatrix& shadowTransform) { 918ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 919ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon.setReserve(path.countPoints()); 920ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 921ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // Walk around the path and compute clip polygon and path polygon. 922ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // Will also accumulate sum of areas for centroid. 923ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // For Bezier curves, we compute additional interior points on curve. 92491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPath::Iter iter(path, true); 92591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint pts[4]; 92691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPath::Verb verb; 92791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 928e7c85c45c4c0a97adc6711bb12ecacc36af4ba11Brian Salomon fClipPolygon.reset(); 929e5f5bf5175e426ebb6aa234f4387831c898f20adJim Van Verth 930ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // init centroid 931ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid = SkPoint::Make(0, 0); 932ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fArea = 0; 933ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 93466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // coefficients to compute cubic Bezier at t = 5/16 935ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kA = 0.32495117187f; 936ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kB = 0.44311523437f; 937ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kC = 0.20141601562f; 938ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kD = 0.03051757812f; 93966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 94066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint curvePoint; 94166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar w; 94291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 94391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth switch (verb) { 94491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kLine_Verb: 945a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(&pts[1], 1); 94691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fClipPolygon.push() = pts[1]; 947ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->INHERITED::handleLine(shadowTransform, &pts[1]); 94891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 94991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kQuad_Verb: 950a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 3); 95166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 1/2 95266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = 0.25f*pts[0].fX + 0.5f*pts[1].fX + 0.25f*pts[2].fX; 95366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = 0.25f*pts[0].fY + 0.5f*pts[1].fY + 0.25f*pts[2].fY; 95466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 95566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[2]; 956ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handleQuad(shadowTransform, pts); 95791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 95891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kConic_Verb: 959a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 3); 96066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon w = iter.conicWeight(); 961a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // point at t = 1/2 96266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = 0.25f*pts[0].fX + w*0.5f*pts[1].fX + 0.25f*pts[2].fX; 96366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = 0.25f*pts[0].fY + w*0.5f*pts[1].fY + 0.25f*pts[2].fY; 96466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint *= SkScalarInvert(0.5f + 0.5f*w); 96566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 96666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[2]; 967ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handleConic(shadowTransform, pts, w); 96891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 96991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kCubic_Verb: 970a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 4); 97166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 5/16 97266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = kA*pts[0].fX + kB*pts[1].fX + kC*pts[2].fX + kD*pts[3].fX; 97366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = kA*pts[0].fY + kB*pts[1].fY + kC*pts[2].fY + kD*pts[3].fY; 97466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 97566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 11/16 97666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = kD*pts[0].fX + kC*pts[1].fX + kB*pts[2].fX + kA*pts[3].fX; 97766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = kD*pts[0].fY + kC*pts[1].fY + kB*pts[2].fY + kA*pts[3].fY; 97866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 97966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[3]; 980ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handleCubic(shadowTransform, pts); 98191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 982ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon case SkPath::kMove_Verb: 98391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kClose_Verb: 984ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon case SkPath::kDone_Verb: 98591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 98691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth default: 98791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkDEBUGFAIL("unknown verb"); 98891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 98991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 99091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 991ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // finish centroid 992ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fPathPolygon.count() > 0) { 993ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint currPoint = fPathPolygon[fPathPolygon.count() - 1]; 994ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint nextPoint = fPathPolygon[0]; 995ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar quadArea = currPoint.cross(nextPoint); 996ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fX += (currPoint.fX + nextPoint.fX) * quadArea; 997ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fY += (currPoint.fY + nextPoint.fY) * quadArea; 998ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fArea += quadArea; 999ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid *= SK_Scalar1 / (3 * fArea); 1000ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1001ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1002ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrClipPoint = fClipPolygon.count() - 1; 100366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon} 100466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1005ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonvoid SkSpotShadowTessellator::computeClipVectorsAndTestCentroid() { 100666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkASSERT(fClipPolygon.count() >= 3); 100766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1008ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // init clip vectors 100966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector v0 = fClipPolygon[1] - fClipPolygon[0]; 101066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipVectors.push() = v0; 101166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 101266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // init centroid check 101366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool hiddenCentroid = true; 1014ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v1 = fCentroid - fClipPolygon[0]; 101566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar initCross = v0.cross(v1); 101666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 101766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon for (int p = 1; p < fClipPolygon.count(); ++p) { 1018ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // add to clip vectors 101966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon v0 = fClipPolygon[(p + 1) % fClipPolygon.count()] - fClipPolygon[p]; 102066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipVectors.push() = v0; 102166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Determine if transformed centroid is inside clipPolygon. 1022ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon v1 = fCentroid - fClipPolygon[p]; 102366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (initCross*v0.cross(v1) <= 0) { 102466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon hiddenCentroid = false; 102566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 102666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 102766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkASSERT(fClipVectors.count() == fClipPolygon.count()); 102866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1029ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fTransparent = fTransparent || !hiddenCentroid; 103066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon} 103166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 103266085ed41779211f9e7e17aa493d4585d73445feBrian Salomonbool SkSpotShadowTessellator::clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, 103366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint* clipPoint) { 103466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector segmentVector = centroid - umbraPoint; 103566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1036ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int startClipPoint = fCurrClipPoint; 103766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon do { 1038ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector dp = umbraPoint - fClipPolygon[fCurrClipPoint]; 1039ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar denom = fClipVectors[fCurrClipPoint].cross(segmentVector); 104066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar t_num = dp.cross(segmentVector); 104166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // if line segments are nearly parallel 104266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (SkScalarNearlyZero(denom)) { 104366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // and collinear 104466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (SkScalarNearlyZero(t_num)) { 104566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return false; 104666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 104766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // otherwise are separate, will try the next poly segment 104866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // else if crossing lies within poly segment 104966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (t_num >= 0 && t_num <= denom) { 1050ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar s_num = dp.cross(fClipVectors[fCurrClipPoint]); 105166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // if umbra point is inside the clip polygon 1052da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (s_num >= 0 && s_num <= denom) { 105366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon segmentVector *= s_num/denom; 105466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *clipPoint = umbraPoint + segmentVector; 105566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return true; 105666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 105766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 1058ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrClipPoint = (fCurrClipPoint + 1) % fClipPolygon.count(); 1059ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } while (fCurrClipPoint != startClipPoint); 106066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 106166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return false; 106291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 106391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1064ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonint SkSpotShadowTessellator::getClosestUmbraPoint(const SkPoint& p) { 1065ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar minDistance = p.distanceToSqd(fUmbraPolygon[fCurrUmbraPoint]); 1066ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int index = fCurrUmbraPoint; 1067ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int dir = 1; 1068ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int next = (index + dir) % fUmbraPolygon.count(); 1069ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1070ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // init travel direction 1071ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar distance = p.distanceToSqd(fUmbraPolygon[next]); 1072ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (distance < minDistance) { 1073ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon index = next; 1074ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon minDistance = distance; 1075ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 1076ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon dir = fUmbraPolygon.count()-1; 1077ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1078ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1079ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // iterate until we find a point that increases the distance 1080ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon next = (index + dir) % fUmbraPolygon.count(); 1081ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon distance = p.distanceToSqd(fUmbraPolygon[next]); 1082ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon while (distance < minDistance) { 1083ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon index = next; 1084ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon minDistance = distance; 1085ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon next = (index + dir) % fUmbraPolygon.count(); 1086ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon distance = p.distanceToSqd(fUmbraPolygon[next]); 1087ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1088ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1089ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrUmbraPoint = index; 1090ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return index; 1091ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1092ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1093efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::mapPoints(SkScalar scale, const SkVector& xlate, 109491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint* pts, int count) { 109591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // TODO: vectorize 109691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth for (int i = 0; i < count; ++i) { 109791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth pts[i] *= scale; 109891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth pts[i] += xlate; 109991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 110091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 110191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1102ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonstatic bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) { 1103ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kClose = (SK_Scalar1 / 16); 1104ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kCloseSqd = kClose*kClose; 1105ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1106ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar distSq = p0.distanceToSqd(p1); 1107ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return distSq < kCloseSqd; 1108ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1109ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1110ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonstatic bool is_collinear(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2) { 1111ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v0 = p1 - p0; 1112ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v1 = p2 - p0; 1113ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return (SkScalarNearlyZero(v0.cross(v1))); 1114ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1115ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1116efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::handleLine(const SkPoint& p) { 1117ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // remove coincident points and add to centroid 1118ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fPathPolygon.count() > 0) { 1119ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon const SkPoint& lastPoint = fPathPolygon[fPathPolygon.count() - 1]; 1120ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (duplicate_pt(p, lastPoint)) { 1121ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return; 1122ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1123ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar quadArea = lastPoint.cross(p); 1124ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fX += (p.fX + lastPoint.fX) * quadArea; 1125ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fY += (p.fY + lastPoint.fY) * quadArea; 1126ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fArea += quadArea; 1127ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1128ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1129ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // try to remove collinear points 1130ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fPathPolygon.count() > 1 && is_collinear(fPathPolygon[fPathPolygon.count()-2], 1131ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon[fPathPolygon.count()-1], 1132ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon p)) { 1133ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon[fPathPolygon.count() - 1] = p; 1134ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 1135ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fPathPolygon.push() = p; 1136ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1137ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1138ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1139ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonvoid SkSpotShadowTessellator::handlePolyPoint(const SkPoint& p) { 114091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fInitPoints.count() < 2) { 114191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fInitPoints.push() = p; 114291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 114391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 114491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 114591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fInitPoints.count() == 2) { 114691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // determine if cw or ccw 114791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector v0 = fInitPoints[1] - fInitPoints[0]; 114891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector v1 = p - fInitPoints[0]; 1149ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar perpDot = v0.cross(v1); 115091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (SkScalarNearlyZero(perpDot)) { 115191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // nearly parallel, just treat as straight line and continue 115291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fInitPoints[1] = p; 115391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 115491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 115591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 115691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // if perpDot > 0, winding is ccw 115791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fDirection = (perpDot > 0) ? -1 : 1; 115891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 115991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // add first quad 1160da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!compute_normal(fInitPoints[0], fInitPoints[1], fDirection, &fFirstNormal)) { 116191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // first two points are incident, make the third point the second and continue 116291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fInitPoints[1] = p; 116391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 116491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 116591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1166da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fFirstNormal *= fRadius; 116791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fFirstPoint = fInitPoints[0]; 116891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fFirstVertex = fPositions.count(); 116991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevNormal = fFirstNormal; 117091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = fFirstPoint; 1171e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth fPrevUmbraIndex = -1; 117266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 117366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon this->addInnerPoint(fFirstPoint); 1174e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth fPrevUmbraIndex = fFirstVertex; 117566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 117666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (!fTransparent) { 117766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint clipPoint; 117866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool isOutside = this->clipUmbraPoint(fPositions[fFirstVertex], fCentroid, &clipPoint); 117966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (isOutside) { 118066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = clipPoint; 118166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 118266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 118366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraOutside = isOutside; 118466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fFirstUmbraOutside = isOutside; 118566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 118691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 118791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint newPoint = fFirstPoint + fFirstNormal; 118891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = newPoint; 118991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 119091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth this->addEdge(fInitPoints[1], fFirstNormal); 119191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 119291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // to ensure we skip this block next time 119391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fInitPoints.push() = p; 119491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 119591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 119691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector normal; 1197da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (compute_normal(fPrevPoint, p, fDirection, &normal)) { 1198da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= fRadius; 1199da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(normal, true); 1200da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addEdge(p, normal); 120191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 120291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 120391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1204ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonbool SkSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint) { 1205ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint umbraPoint; 1206ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (!fValidUmbra) { 1207ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v = fCentroid - pathPoint; 1208ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon v *= 0.95f; 1209ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon umbraPoint = pathPoint + v; 121091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } else { 1211ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon umbraPoint = fUmbraPolygon[this->getClosestUmbraPoint(pathPoint)]; 121291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 121366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 121491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = pathPoint; 1215ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1216ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // merge "close" points 1217e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (fPrevUmbraIndex == -1 || 1218ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon !duplicate_pt(umbraPoint, fPositions[fPrevUmbraIndex])) { 1219ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fPositions.push() = umbraPoint; 1220ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fColors.push() = fUmbraColor; 1221ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1222ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return false; 1223ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 1224ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return true; 1225ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 122691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 122791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1228efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { 122966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add next umbra point 1230ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon bool duplicate = this->addInnerPoint(nextPoint); 1231ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int prevPenumbraIndex = duplicate ? fPositions.count()-1 : fPositions.count()-2; 1232ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int currUmbraIndex = duplicate ? fPrevUmbraIndex : fPositions.count()-1; 123366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1234ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (!duplicate) { 1235ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // add to center fan if transparent or centroid showing 1236ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fTransparent) { 1237ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = 0; 1238ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = fPrevUmbraIndex; 1239ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = currUmbraIndex; 1240ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // otherwise add to clip ring 1241ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 124266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint clipPoint; 1243ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon bool isOutside = this->clipUmbraPoint(fPositions[currUmbraIndex], fCentroid, 1244ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon &clipPoint); 124566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (isOutside) { 124666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = clipPoint; 124766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 124866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 124966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 125066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 125166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex + 1; 125266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fPrevUmbraOutside) { 125366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // fill out quad 125466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 125566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex + 1; 125666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 125766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 125866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (fPrevUmbraOutside) { 125966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add tri 126066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 126166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 126266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 126366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 126466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraOutside = isOutside; 126566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 126666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 126766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 126866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add next penumbra point and quad 126991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint newPoint = nextPoint + nextNormal; 127091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = newPoint; 127191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 127291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1273ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (!duplicate) { 1274ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = fPrevUmbraIndex; 1275ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = prevPenumbraIndex; 1276ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = currUmbraIndex; 1277ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 127891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 127966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = prevPenumbraIndex; 128091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 128166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 128291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 128366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = currUmbraIndex; 128491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevNormal = nextNormal; 128591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 1286958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 1287958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon/////////////////////////////////////////////////////////////////////////////////////////////////// 1288958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 1289aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonsk_sp<SkVertices> SkShadowTessellator::MakeAmbient(const SkPath& path, const SkMatrix& ctm, 1290060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth HeightFunc heightFunc, bool transparent) { 1291060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkAmbientShadowTessellator ambientTess(path, ctm, heightFunc, transparent); 1292aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return ambientTess.releaseVertices(); 1293958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon} 1294958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 1295aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonsk_sp<SkVertices> SkShadowTessellator::MakeSpot(const SkPath& path, const SkMatrix& ctm, 1296060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth HeightFunc heightFunc, const SkPoint3& lightPos, 1297060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkScalar lightRadius, bool transparent) { 1298060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkSpotShadowTessellator spotTess(path, ctm, heightFunc, lightPos, lightRadius, transparent); 1299aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return spotTess.releaseVertices(); 1300958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon} 1301