SkShadowTessellator.cpp revision 7638785bea9fa6ce3505c3393ad3d3aff9af2d0d
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: 25e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkBaseShadowTessellator(const SkPoint3& zPlaneParams, 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 59e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkScalar heightFunc(SkScalar x, SkScalar y) { 60e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth return fZPlaneParams.fX*x + fZPlaneParams.fY*y + fZPlaneParams.fZ; 61e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth } 62e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth 63e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkPoint3 fZPlaneParams; 64da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth std::function<SkScalar(const SkPoint&)> fTransformedHeightFunc; 65da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fZOffset; 66da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // members for perspective height function 674c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth SkPoint3 fTransformedZParams; 68da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fPartialDeterminants[3]; 69b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 70da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // first two points 71a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkTDArray<SkPoint> fInitPoints; 72a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // temporary buffer 73a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkTDArray<SkPoint> fPointBuffer; 74958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 75958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<SkPoint> fPositions; 76958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<SkColor> fColors; 77958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<uint16_t> fIndices; 78958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 797638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth int fFirstVertexIndex; 807638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkVector fFirstOutset; 81a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fFirstPoint; 820dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 830dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon bool fSucceeded; 84a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth bool fTransparent; 85a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 86a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkColor fUmbraColor; 87a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkColor fPenumbraColor; 88a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 89a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar fRadius; 90a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar fDirection; 91a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int fPrevUmbraIndex; 927638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkVector fPrevOutset; 93a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fPrevPoint; 94958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon}; 95958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 96da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verthstatic bool compute_normal(const SkPoint& p0, const SkPoint& p1, SkScalar dir, 97bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector* newNormal) { 98bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 99bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // compute perpendicular 100bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth normal.fX = p0.fY - p1.fY; 101bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth normal.fY = p1.fX - p0.fX; 102da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= dir; 103bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (!normal.normalize()) { 104bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return false; 105bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 106bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *newNormal = normal; 107bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return true; 108bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 109bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 110bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verthstatic void compute_radial_steps(const SkVector& v1, const SkVector& v2, SkScalar r, 111bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar* rotSin, SkScalar* rotCos, int* n) { 112e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth const SkScalar kRecipPixelsPerArcSegment = 0.125f; 113bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 114bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar rCos = v1.dot(v2); 115bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar rSin = v1.cross(v2); 116bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar theta = SkScalarATan2(rSin, rCos); 117bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 118e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth int steps = SkScalarFloorToInt(r*theta*kRecipPixelsPerArcSegment); 119bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 120bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar dTheta = theta / steps; 121bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *rotSin = SkScalarSinCos(dTheta, rotCos); 122e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *n = steps; 123bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 124bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 125e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van VerthSkBaseShadowTessellator::SkBaseShadowTessellator(const SkPoint3& zPlaneParams, bool transparent) 126e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth : fZPlaneParams(zPlaneParams) 127da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fZOffset(0) 1287638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth , fFirstVertexIndex(-1) 129aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fSucceeded(false) 130aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fTransparent(transparent) 131aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fDirection(1) 132aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fPrevUmbraIndex(-1) { 133a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fInitPoints.setReserve(3); 134a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 135a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // child classes will set reserve for positions, colors and indices 136a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 137a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 138da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verthbool SkBaseShadowTessellator::setZOffset(const SkRect& bounds, bool perspective) { 139e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkScalar minZ = this->heightFunc(bounds.fLeft, bounds.fTop); 140da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (perspective) { 141e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkScalar z = this->heightFunc(bounds.fLeft, bounds.fBottom); 142da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (z < minZ) { 143da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth minZ = z; 144da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 145e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth z = this->heightFunc(bounds.fRight, bounds.fTop); 146da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (z < minZ) { 147da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth minZ = z; 148da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 149e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth z = this->heightFunc(bounds.fRight, bounds.fBottom); 150da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (z < minZ) { 151da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth minZ = z; 152da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 153da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 154da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 155da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (minZ < kMinHeight) { 156da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fZOffset = -minZ + kMinHeight; 157da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return true; 158da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 159da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 160da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return false; 161da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth} 162da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 163a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth// tesselation tolerance values, in device space pixels 164b8b51e6b2f431c89907139bec52ed64b7ed303edMike Klein#if SK_SUPPORT_GPU 165a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kQuadTolerance = 0.2f; 166a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kCubicTolerance = 0.2f; 167b8b51e6b2f431c89907139bec52ed64b7ed303edMike Klein#endif 168a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kConicTolerance = 0.5f; 169a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 170aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleLine(const SkMatrix& m, SkPoint* p) { 171a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(p, 1); 172a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(*p); 173a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 174a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 175aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleQuad(const SkPoint pts[3]) { 176a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#if SK_SUPPORT_GPU 177a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // TODO: Pull PathUtils out of Ganesh? 178a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); 179a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setReserve(maxCount); 180a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint* target = fPointBuffer.begin(); 181a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], 182a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth kQuadTolerance, &target, maxCount); 183a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setCount(count); 184a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; i++) { 185a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(fPointBuffer[i]); 186a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 187a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#else 188a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // for now, just to draw something 189a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[1]); 190a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[2]); 191a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#endif 192a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 193a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 194aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleQuad(const SkMatrix& m, SkPoint pts[3]) { 195a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 3); 196a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(pts); 197a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 198a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 199aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleCubic(const SkMatrix& m, SkPoint pts[4]) { 200a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 4); 201a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#if SK_SUPPORT_GPU 202a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // TODO: Pull PathUtils out of Ganesh? 203a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance); 204a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setReserve(maxCount); 205a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint* target = fPointBuffer.begin(); 206a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], 207a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth kCubicTolerance, &target, maxCount); 208a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setCount(count); 209a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; i++) { 210a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(fPointBuffer[i]); 211a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 212a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#else 213a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // for now, just to draw something 214a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[1]); 215a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[2]); 216a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[3]); 217a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#endif 218a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 219a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 220aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleConic(const SkMatrix& m, SkPoint pts[3], SkScalar w) { 221da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (m.hasPerspective()) { 222da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth w = SkConic::TransformW(pts, w, m); 223da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 224a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 3); 225a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkAutoConicToQuads quadder; 226a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance); 227a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint lastPoint = *(quads++); 228a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = quadder.countQuads(); 229a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; ++i) { 230a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint quadPts[3]; 231a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[0] = lastPoint; 232a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[1] = quads[0]; 233a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[2] = i == count - 1 ? pts[2] : quads[1]; 234a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(quadPts); 235a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth lastPoint = quadPts[2]; 236a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quads += 2; 237a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 238a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 239a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 240e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verthbool SkBaseShadowTessellator::addArc(const SkVector& nextNormal, bool finishArc) { 241a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // fill in fan from previous quad 242a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar rotSin, rotCos; 243a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int numSteps; 2447638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth compute_radial_steps(fPrevOutset, nextNormal, fRadius, &rotSin, &rotCos, &numSteps); 2457638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkVector prevNormal = fPrevOutset; 246e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth for (int i = 0; i < numSteps-1; ++i) { 247da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector currNormal; 248da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth currNormal.fX = prevNormal.fX*rotCos - prevNormal.fY*rotSin; 249da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth currNormal.fY = prevNormal.fY*rotCos + prevNormal.fX*rotSin; 250da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fPrevPoint + currNormal; 251a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fColors.push() = fPenumbraColor; 252a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPrevUmbraIndex; 253a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPositions.count() - 1; 254e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 2; 255a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 256da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth prevNormal = currNormal; 257a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 258e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (finishArc && numSteps) { 259da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fPrevPoint + nextNormal; 260da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = fPenumbraColor; 261da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 262da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 263e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 2; 264da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 2657638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevOutset = nextNormal; 266e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth 267e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth return (numSteps > 0); 268a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 269a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 270da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verthbool SkBaseShadowTessellator::setTransformedHeightFunc(const SkMatrix& ctm) { 2714c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth if (SkScalarNearlyZero(fZPlaneParams.fX) && SkScalarNearlyZero(fZPlaneParams.fY)) { 272da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fTransformedHeightFunc = [this](const SkPoint& p) { 273e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth return fZPlaneParams.fZ; 274da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth }; 275da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 276da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkMatrix ctmInverse; 277da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!ctm.invert(&ctmInverse)) { 278da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return false; 279da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 280da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // multiply by transpose 2814c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedZParams = SkPoint3::Make( 282e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMScaleX] * fZPlaneParams.fX + 283e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMSkewY] * fZPlaneParams.fY + 284e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMPersp0] * fZPlaneParams.fZ, 285e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth 286e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMSkewX] * fZPlaneParams.fX + 287e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMScaleY] * fZPlaneParams.fY + 288e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMPersp1] * fZPlaneParams.fZ, 289e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth 290e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMTransX] * fZPlaneParams.fX + 291e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMTransY] * fZPlaneParams.fY + 292e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ctmInverse[SkMatrix::kMPersp2] * fZPlaneParams.fZ 293e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth ); 294da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 2954c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth if (ctm.hasPerspective()) { 2964c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth // We use Cramer's rule to solve for the W value for a given post-divide X and Y, 2974c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth // so pre-compute those values that are independent of X and Y. 2984c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth // W is det(ctmInverse)/(PD[0]*X + PD[1]*Y + PD[2]) 2994c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fPartialDeterminants[0] = ctm[SkMatrix::kMSkewY] * ctm[SkMatrix::kMPersp1] - 3004c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth ctm[SkMatrix::kMScaleY] * ctm[SkMatrix::kMPersp0]; 3014c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fPartialDeterminants[1] = ctm[SkMatrix::kMPersp0] * ctm[SkMatrix::kMSkewX] - 3024c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth ctm[SkMatrix::kMPersp1] * ctm[SkMatrix::kMScaleX]; 3034c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fPartialDeterminants[2] = ctm[SkMatrix::kMScaleX] * ctm[SkMatrix::kMScaleY] - 3044c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth ctm[SkMatrix::kMSkewX] * ctm[SkMatrix::kMSkewY]; 3054c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth SkScalar ctmDeterminant = ctm[SkMatrix::kMTransX] * fPartialDeterminants[0] + 3064c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth ctm[SkMatrix::kMTransY] * fPartialDeterminants[1] + 3074c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth ctm[SkMatrix::kMPersp2] * fPartialDeterminants[2]; 3084c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth 3094c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth // Pre-bake the numerator of Cramer's rule into the zParams to avoid another multiply. 3104c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth // TODO: this may introduce numerical instability, but I haven't seen any issues yet. 3114c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedZParams.fX *= ctmDeterminant; 3124c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedZParams.fY *= ctmDeterminant; 3134c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedZParams.fZ *= ctmDeterminant; 3144c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth 3154c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedHeightFunc = [this](const SkPoint& p) { 3164c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth SkScalar denom = p.fX * fPartialDeterminants[0] + 3174c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth p.fY * fPartialDeterminants[1] + 3184c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fPartialDeterminants[2]; 3194c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth SkScalar w = SkScalarFastInvert(denom); 3204c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth return fZOffset + w*(fTransformedZParams.fX * p.fX + 3214c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedZParams.fY * p.fY + 3224c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedZParams.fZ); 3234c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth }; 3244c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth } else { 3254c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedHeightFunc = [this](const SkPoint& p) { 3264c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth return fZOffset + fTransformedZParams.fX * p.fX + 3274c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth fTransformedZParams.fY * p.fY + fTransformedZParams.fZ; 3284c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth }; 3294c9b893953a4dddc20edafd7583523c94c01c889Jim Van Verth } 330da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 331a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 332da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return true; 333a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 334a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 335a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 336a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth////////////////////////////////////////////////////////////////////////////////////////////////// 337a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 338aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkAmbientShadowTessellator : public SkBaseShadowTessellator { 339a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthpublic: 340a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm, 341e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth const SkPoint3& zPlaneParams, bool transparent); 342a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 343a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthprivate: 344a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkPoint& p) override; 345da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth void addEdge(const SkVector& nextPoint, const SkVector& nextNormal); 346da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 347da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth static constexpr auto kHeightFactor = 1.0f / 128.0f; 348da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth static constexpr auto kGeomFactor = 64.0f; 349da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth static constexpr auto kMaxEdgeLenSqr = 20 * 20; 3507638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth static constexpr auto kInsetFactor = -0.5f; 351a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 352da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar offset(SkScalar z) { 353da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return z * kHeightFactor * kGeomFactor; 354da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 355da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkColor umbraColor(SkScalar z) { 356da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(z*kHeightFactor, 0.0f))); 357060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth return SkColorSetARGB(umbraAlpha * 255.9999f, 0, 0, 0); 358da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 359da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 360a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int fCentroidCount; 3617638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth bool fSplitFirstEdge; 3627638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth bool fSplitPreviousEdge; 363a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 364aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon typedef SkBaseShadowTessellator INHERITED; 365a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth}; 366a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 367efe3dedbb3493b738abdb56041b093245e4e8711Jim Van VerthSkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, 368a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth const SkMatrix& ctm, 369e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth const SkPoint3& zPlaneParams, 370bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth bool transparent) 3717638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth : INHERITED(zPlaneParams, transparent) 3727638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth , fSplitFirstEdge(false) 3737638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth , fSplitPreviousEdge(false) { 374da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Set base colors 375b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkScalar occluderHeight = heightFunc(0, 0); 376b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkScalar umbraAlpha = SkScalarInvert((1.0f + SkTMax(occluderHeight*kHeightFactor, 0.0f))); 377b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // umbraColor is the interior value, penumbraColor the exterior value. 378b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // umbraAlpha is the factor that is linearly interpolated from outside to inside, and 379b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // then "blurred" by the GrBlurredEdgeFP. It is then multiplied by fAmbientAlpha to get 380b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // the final alpha. 381060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fUmbraColor = SkColorSetARGB(umbraAlpha * 255.9999f, 0, 0, 0); 382060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fPenumbraColor = SkColorSetARGB(0, 0, 0, 0); 383b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 384da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // make sure we're not below the canvas plane 385da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->setZOffset(path.getBounds(), ctm.hasPerspective()); 386da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 387da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->setTransformedHeightFunc(ctm); 388da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 389bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Outer ring: 3*numPts 390bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Middle ring: numPts 391bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions.setReserve(4 * path.countPoints()); 392bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fColors.setReserve(4 * path.countPoints()); 393bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Outer ring: 12*numPts 394bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Middle ring: 0 395bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fIndices.setReserve(12 * path.countPoints()); 396bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 397bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // walk around the path, tessellate and generate outer ring 398bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if original path is transparent, will accumulate sum of points for centroid 399bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPath::Iter iter(path, true); 400bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPoint pts[4]; 401bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPath::Verb verb; 402bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 403bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = SkPoint::Make(0, 0); 404b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth *fColors.push() = fUmbraColor; 405bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fCentroidCount = 0; 406bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 407bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 408bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth switch (verb) { 409bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kLine_Verb: 410a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->INHERITED::handleLine(ctm, &pts[1]); 411bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 412bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kQuad_Verb: 413a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(ctm, pts); 414bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 415bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kCubic_Verb: 416a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleCubic(ctm, pts); 417bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 418bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kConic_Verb: 419a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleConic(ctm, pts, iter.conicWeight()); 420bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 421bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kMove_Verb: 422bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kClose_Verb: 423bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kDone_Verb: 424bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 425bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 426bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 427bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 4280dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon if (!this->indexCount()) { 4290dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon return; 4300dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon } 4310dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 4327638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // Finish up 433bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 434da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (compute_normal(fPrevPoint, fFirstPoint, fDirection, &normal)) { 435da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar z = fTransformedHeightFunc(fPrevPoint); 436da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(z); 437da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector scaledNormal(normal); 438da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth scaledNormal *= fRadius; 439da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(scaledNormal, true); 440da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 4417638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // fix-up the last and first umbra points 4427638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkVector inset = normal; 4437638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // adding to an average, so multiply by an additional half 4447638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth inset *= 0.5f*kInsetFactor; 4457638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fPrevUmbraIndex] += inset; 4467638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fFirstVertexIndex] += inset; 4477638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // we multiply by another half because now we're adding to an average of an average 4487638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth inset *= 0.5f; 4497638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (fSplitPreviousEdge) { 4507638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fPrevUmbraIndex - 2] += inset; 4517638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth } 4527638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (fSplitFirstEdge) { 4537638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fFirstVertexIndex + 2] += inset; 4547638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth } 4557638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth 456da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // set up for final edge 457da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth z = fTransformedHeightFunc(fFirstPoint); 458da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= this->offset(z); 459da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 460da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // make sure we don't end up with a sharp alpha edge along the quad diagonal 4617638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (fColors[fPrevUmbraIndex] != fColors[fFirstVertexIndex] && 462da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fFirstPoint.distanceToSqd(fPositions[fPrevUmbraIndex]) > kMaxEdgeLenSqr) { 4637638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkPoint centerPoint = fPositions[fPrevUmbraIndex] + fPositions[fFirstVertexIndex]; 4647638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth centerPoint *= 0.5f; 4657638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fPositions.push() = centerPoint; 4667638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fColors.push() = SkPMLerp(fColors[fFirstVertexIndex], fColors[fPrevUmbraIndex], 128); 4677638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth centerPoint = fPositions[fPositions.count()-2] + fPositions[fFirstVertexIndex+1]; 468da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth centerPoint *= 0.5f; 469da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = centerPoint; 470da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = fPenumbraColor; 471bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 4727638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (fColors[fPrevUmbraIndex] > fColors[fPositions.count() - 2]) { 4737638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPrevUmbraIndex; 4747638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 3; 4757638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 2; 476bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 4777638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 3; 4787638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 1; 4797638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 2; 4807638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth } else { 4817638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPrevUmbraIndex; 4827638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 2; 4837638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 1; 4847638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth 4857638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPrevUmbraIndex; 4867638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 1; 4877638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fPositions.count() - 3; 4887638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth } 489da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 4901c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth // if transparent, add point to first one in array and add to center fan 4911c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth if (fTransparent) { 4921c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth fPositions[0] += centerPoint; 4931c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth ++fCentroidCount; 4941c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth 4951c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth *fIndices.push() = 0; 4961c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 4971c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth *fIndices.push() = fPositions.count() - 2; 4981c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth } 4991c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth 500da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPrevUmbraIndex = fPositions.count() - 2; 501da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 502da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 503da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // final edge 504a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fPositions.push() = fFirstPoint + normal; 505bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 506bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 5077638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (fColors[fPrevUmbraIndex] > fColors[fFirstVertexIndex]) { 508da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 509da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 5107638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 511bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 512da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 513da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 5147638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 515da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 516da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 517da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 518da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 519da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 520da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 521da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 5227638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 523da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 5247638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevOutset = normal; 525bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 526bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 527bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // finalize centroid 528bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 529bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions[0] *= SkScalarFastInvert(fCentroidCount); 5301c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth fColors[0] = this->umbraColor(fTransformedHeightFunc(fPositions[0])); 531bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 532bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = 0; 53366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 5347638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 535bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 536bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 537bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // final fan 538bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fPositions.count() >= 3) { 5397638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevUmbraIndex = fFirstVertexIndex; 540a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = fFirstPoint; 541da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(fTransformedHeightFunc(fPrevPoint)); 5427638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (this->addArc(fFirstOutset, false)) { 5437638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 544e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 1; 5457638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex + 1; 546e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } else { 547e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth // arc is too small, set the first penumbra point to be the same position 548e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth // as the last one 5497638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fFirstVertexIndex + 1] = fPositions[fPositions.count() - 1]; 550e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } 551bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 5520dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon fSucceeded = true; 553bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 554bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 555efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkAmbientShadowTessellator::handleLine(const SkPoint& p) { 556bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fInitPoints.count() < 2) { 557bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fInitPoints.push() = p; 558bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 559bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 560bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 561bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fInitPoints.count() == 2) { 562bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // determine if cw or ccw 563bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector v0 = fInitPoints[1] - fInitPoints[0]; 564bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector v1 = p - fInitPoints[0]; 565bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar perpDot = v0.fX*v1.fY - v0.fY*v1.fX; 566bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (SkScalarNearlyZero(perpDot)) { 567bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // nearly parallel, just treat as straight line and continue 568bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fInitPoints[1] = p; 569bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 570bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 571bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 572bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if perpDot > 0, winding is ccw 573bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fDirection = (perpDot > 0) ? -1 : 1; 574bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 575bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // add first quad 576da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector normal; 577da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!compute_normal(fInitPoints[0], fInitPoints[1], fDirection, &normal)) { 578bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // first two points are incident, make the third point the second and continue 579bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fInitPoints[1] = p; 580bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 581bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 582bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 583a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fFirstPoint = fInitPoints[0]; 5847638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fFirstVertexIndex = fPositions.count(); 585da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar z = fTransformedHeightFunc(fFirstPoint); 5867638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fFirstOutset = normal; 5877638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fFirstOutset *= this->offset(z); 588da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 5897638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevOutset = fFirstOutset; 590a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = fFirstPoint; 5917638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevUmbraIndex = fFirstVertexIndex; 592bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 593da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fFirstPoint; 594da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = this->umbraColor(z); 5957638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fPositions.push() = fFirstPoint + fFirstOutset; 596bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 597bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 598da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPositions[0] += fFirstPoint; 599bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fCentroidCount = 1; 600bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 601da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 602da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // add the first quad 603da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth z = fTransformedHeightFunc(fInitPoints[1]); 604da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(z); 605da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fUmbraColor = this->umbraColor(z); 606da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addEdge(fInitPoints[1], normal); 607bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 608bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // to ensure we skip this block next time 609bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fInitPoints.push() = p; 610bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 611bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 612bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 6137638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (compute_normal(fPrevPoint, p, fDirection, &normal)) { 614da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector scaledNormal = normal; 615da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth scaledNormal *= fRadius; 616da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(scaledNormal, true); 617da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar z = fTransformedHeightFunc(p); 618da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fRadius = this->offset(z); 619da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fUmbraColor = this->umbraColor(z); 620da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addEdge(p, normal); 621bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 622bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 623bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 624efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { 6257638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // We compute the inset in two stages: first we inset by half the current normal, 6267638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // then on the next addEdge() we add half of the next normal to get an average of the two 6277638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkVector insetNormal = nextNormal; 6287638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth insetNormal *= 0.5f*kInsetFactor; 6297638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth 6307638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // Adding the other half of the average for the previous edge 6317638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fPrevUmbraIndex] += insetNormal; 6327638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth 6337638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkPoint umbraPoint = nextPoint + insetNormal; 6347638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkVector outsetNormal = nextNormal; 6357638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth outsetNormal *= fRadius; 6367638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkPoint penumbraPoint = nextPoint + outsetNormal; 6377638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth 6387638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // For split edges, we're adding an average of two averages, so we multiply by another half 6397638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (fSplitPreviousEdge) { 6407638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth insetNormal *= 0.5f; 6417638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fPrevUmbraIndex - 2] += insetNormal; 6427638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth } 6437638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth 6447638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // Split the edge to make sure we don't end up with a sharp alpha edge along the quad diagonal 645da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] != fUmbraColor && 646da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth nextPoint.distanceToSqd(fPositions[fPrevUmbraIndex]) > kMaxEdgeLenSqr) { 6477638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth 6487638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth // This is lacking 1/4 of the next inset -- we'll add it the next time we call addEdge() 6497638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkPoint centerPoint = fPositions[fPrevUmbraIndex] + umbraPoint; 650da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth centerPoint *= 0.5f; 651da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = centerPoint; 652da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkPMLerp(fUmbraColor, fColors[fPrevUmbraIndex], 128); 6537638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth centerPoint = fPositions[fPositions.count()-2] + penumbraPoint; 6547638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth centerPoint *= 0.5f; 6557638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fPositions.push() = centerPoint; 656da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = fPenumbraColor; 657da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 658da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // set triangularization to get best interpolation of color 659da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] > fColors[fPositions.count() - 2]) { 660da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 661da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 662da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 663da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 664da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 665da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 666da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 667da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 668da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 669da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 670da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 671da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 672da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 673da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 674da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 675da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 676da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 6771c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth // if transparent, add point to first one in array and add to center fan 6781c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth if (fTransparent) { 6791c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth fPositions[0] += centerPoint; 6801c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth ++fCentroidCount; 6811c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth 6821c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth *fIndices.push() = 0; 6831c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 6841c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth *fIndices.push() = fPositions.count() - 2; 6851c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth } 6861c4c1144c980e672b6744adb3f30e11cb2d54750Jim Van Verth 6877638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fSplitPreviousEdge = true; 6887638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (fPrevUmbraIndex == fFirstVertexIndex) { 6897638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fSplitFirstEdge = true; 6907638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth } 691da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPrevUmbraIndex = fPositions.count() - 2; 6927638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth } else { 6937638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fSplitPreviousEdge = false; 694da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 695da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 696bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // add next quad 6977638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fPositions.push() = umbraPoint; 698bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fUmbraColor; 6997638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fPositions.push() = penumbraPoint; 700bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 701bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 702da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // set triangularization to get best interpolation of color 703da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (fColors[fPrevUmbraIndex] > fColors[fPositions.count() - 2]) { 704da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 705da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 706da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 707bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 708da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 709da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 710da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 711da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 712da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 713da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 714da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 715da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 716da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPrevUmbraIndex; 717da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 718da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 719da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 720bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 721bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if transparent, add point to first one in array and add to center fan 722bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 723bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions[0] += nextPoint; 724bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth ++fCentroidCount; 725bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 726bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = 0; 72766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 728bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 729bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 730bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 73166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fPositions.count() - 2; 732a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = nextPoint; 7337638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevOutset = outsetNormal; 734bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 73591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 73691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth/////////////////////////////////////////////////////////////////////////////////////////////////// 73791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 738aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkSpotShadowTessellator : public SkBaseShadowTessellator { 739958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonpublic: 740a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, 741e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth const SkPoint3& zPlaneParams, const SkPoint3& lightPos, 742060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkScalar lightRadius, bool transparent); 743958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 744958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonprivate: 745ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon void computeClipAndPathPolygons(const SkPath& path, const SkMatrix& ctm, 746da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth const SkMatrix& shadowTransform); 747ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon void computeClipVectorsAndTestCentroid(); 74866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, SkPoint* clipPoint); 749ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int getClosestUmbraPoint(const SkPoint& point); 750958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 751a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkPoint& p) override; 752ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon void handlePolyPoint(const SkPoint& p); 753958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 754958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon void mapPoints(SkScalar scale, const SkVector& xlate, SkPoint* pts, int count); 755ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon bool addInnerPoint(const SkPoint& pathPoint); 756da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth void addEdge(const SkVector& nextPoint, const SkVector& nextNormal); 757da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 758da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar offset(SkScalar z) { 759da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth float zRatio = SkTPin(z / (fLightZ - z), 0.0f, 0.95f); 760da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth return fLightRadius*zRatio; 761da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 762da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 763da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fLightZ; 764da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fLightRadius; 765da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar fOffsetAdjust; 766958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 767958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<SkPoint> fClipPolygon; 76866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkTDArray<SkVector> fClipVectors; 769a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fCentroid; 770ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar fArea; 771a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 772ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkTDArray<SkPoint> fPathPolygon; 773ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkTDArray<SkPoint> fUmbraPolygon; 774ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int fCurrClipPoint; 775ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int fCurrUmbraPoint; 77666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool fPrevUmbraOutside; 77766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool fFirstUmbraOutside; 778a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth bool fValidUmbra; 779958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 780aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon typedef SkBaseShadowTessellator INHERITED; 781958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon}; 782958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 783a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van VerthSkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, 784e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth const SkPoint3& zPlaneParams, 785b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth const SkPoint3& lightPos, SkScalar lightRadius, 786060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth bool transparent) 787e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth : INHERITED(zPlaneParams, transparent) 788da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fLightZ(lightPos.fZ) 789da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fLightRadius(lightRadius) 790da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fOffsetAdjust(0) 791da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fCurrClipPoint(0) 792da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fPrevUmbraOutside(false) 793da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fFirstUmbraOutside(false) 794da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth , fValidUmbra(true) { 795da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 796da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // make sure we're not below the canvas plane 797da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (this->setZOffset(path.getBounds(), ctm.hasPerspective())) { 798da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Adjust light height and radius 799da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fLightRadius *= (fLightZ + fZOffset) / fLightZ; 800da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fLightZ += fZOffset; 801da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 802b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 803b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // Set radius and colors 804b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkPoint center = SkPoint::Make(path.getBounds().centerX(), path.getBounds().centerY()); 805e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkScalar occluderHeight = this->heightFunc(center.fX, center.fY) + fZOffset; 806da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth float zRatio = SkTPin(occluderHeight / (fLightZ - occluderHeight), 0.0f, 0.95f); 807b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth SkScalar radius = lightRadius * zRatio; 808b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth fRadius = radius; 809060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fUmbraColor = SkColorSetARGB(255, 0, 0, 0); 810060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth fPenumbraColor = SkColorSetARGB(0, 0, 0, 0); 811b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 812b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth // Compute the scale and translation for the spot shadow. 813da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkMatrix shadowTransform; 814da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!ctm.hasPerspective()) { 815da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar scale = fLightZ / (fLightZ - occluderHeight); 816da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkVector translate = SkVector::Make(-zRatio * lightPos.fX, -zRatio * lightPos.fY); 817da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth shadowTransform.setScaleTranslate(scale, scale, translate.fX, translate.fY); 818da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } else { 819da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // For perspective, we have a scale, a z-shear, and another projective divide -- 820da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // this varies at each point so we can't use an affine transform. 821da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // We'll just apply this to each generated point in turn. 822da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth shadowTransform.reset(); 823da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Also can't cull the center (for now). 824da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fTransparent = true; 825da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 826da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkMatrix fullTransform = SkMatrix::Concat(shadowTransform, ctm); 827da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 828da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth // Set up our reverse mapping 829da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->setTransformedHeightFunc(fullTransform); 830b436655ad5c40a04b65c1642d0a0e781ce296c96Jim Van Verth 831ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // TODO: calculate these reserves better 83266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Penumbra ring: 3*numPts 83366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Umbra ring: numPts 83491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // Inner ring: numPts 83566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPositions.setReserve(5 * path.countPoints()); 83666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fColors.setReserve(5 * path.countPoints()); 83766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Penumbra ring: 12*numPts 83866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Umbra ring: 3*numPts 83966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fIndices.setReserve(15 * path.countPoints()); 840e7c85c45c4c0a97adc6711bb12ecacc36af4ba11Brian Salomon fClipPolygon.setReserve(path.countPoints()); 841ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 842ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // compute rough clip bounds for umbra, plus offset polygon, plus centroid 843da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->computeClipAndPathPolygons(path, ctm, shadowTransform); 844ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fClipPolygon.count() < 3 || fPathPolygon.count() < 3) { 84566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return; 84666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 84766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 848ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // check to see if umbra collapses 849ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar minDistSq = fCentroid.distanceToLineSegmentBetweenSqd(fPathPolygon[0], 850ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon[1]); 851da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkRect bounds; 852da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth bounds.setBounds(&fPathPolygon[0], fPathPolygon.count()); 853ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon for (int i = 1; i < fPathPolygon.count(); ++i) { 854ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int j = i + 1; 855ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (i == fPathPolygon.count() - 1) { 856ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon j = 0; 857ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 858ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint currPoint = fPathPolygon[i]; 859ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint nextPoint = fPathPolygon[j]; 860ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar distSq = fCentroid.distanceToLineSegmentBetweenSqd(currPoint, nextPoint); 861ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (distSq < minDistSq) { 862ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon minDistSq = distSq; 863ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 864ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 865ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr auto kTolerance = 1.0e-2f; 866ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (minDistSq < (radius + kTolerance)*(radius + kTolerance)) { 867ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // if the umbra would collapse, we back off a bit on inner blur and adjust the alpha 868ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar newRadius = SkScalarSqrt(minDistSq) - kTolerance; 869da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fOffsetAdjust = newRadius - radius; 870b6069dfba7b7ab563a3fccb2f38307e47035300cJim Van Verth SkScalar ratio = 128 * (newRadius + radius) / radius; 871ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // they aren't PMColors, but the interpolation algorithm is the same 872ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fUmbraColor = SkPMLerp(fUmbraColor, fPenumbraColor, (unsigned)ratio); 873ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon radius = newRadius; 874ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 875e5f5bf5175e426ebb6aa234f4387831c898f20adJim Van Verth 876ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // compute vectors for clip tests 877ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->computeClipVectorsAndTestCentroid(); 878ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 879ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // generate inner ring 880da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (!SkInsetConvexPolygon(&fPathPolygon[0], fPathPolygon.count(), radius, 881da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth &fUmbraPolygon)) { 882ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // this shouldn't happen, but just in case we'll inset using the centroid 883ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fValidUmbra = false; 884ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 885ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 886ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // walk around the path polygon, generate outer ring and connect to inner ring 88766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fTransparent) { 88866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = fCentroid; 88966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 89066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 891ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrUmbraPoint = 0; 892ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon for (int i = 0; i < fPathPolygon.count(); ++i) { 893ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handlePolyPoint(fPathPolygon[i]); 89491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 89591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 8960dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon if (!this->indexCount()) { 8970dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon return; 8980dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon } 8990dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 900ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // finish up the final verts 90191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector normal; 902da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (compute_normal(fPrevPoint, fFirstPoint, fDirection, &normal)) { 903da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= fRadius; 904da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(normal, true); 90591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 90666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add to center fan 90766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fTransparent) { 90866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = 0; 90966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 9107638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 91166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // or to clip ring 91266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 91366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fFirstUmbraOutside) { 91466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 9157638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 9167638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex + 1; 91766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fPrevUmbraOutside) { 91866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // fill out quad 91966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 9207638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex + 1; 92166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 92266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 92366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (fPrevUmbraOutside) { 92466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add tri 92566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 9267638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 92766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 92866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 92966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 93066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 93191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // add final edge 93291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = fFirstPoint + normal; 93391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 93491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 93566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 93691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 2; 9377638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 93891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 93991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 2; 94091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 9417638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 942da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 9437638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevOutset = normal; 94491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 94591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 94691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // final fan 94791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fPositions.count() >= 3) { 9487638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevUmbraIndex = fFirstVertexIndex; 94991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = fFirstPoint; 9507638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (this->addArc(fFirstOutset, false)) { 9517638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex; 952e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth *fIndices.push() = fPositions.count() - 1; 953e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (fFirstUmbraOutside) { 9547638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex + 2; 955e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } else { 9567638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth *fIndices.push() = fFirstVertexIndex + 1; 957e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } 95866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 959e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth // no arc added, fix up by setting first penumbra point position to last one 960e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (fFirstUmbraOutside) { 9617638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fFirstVertexIndex + 2] = fPositions[fPositions.count() - 1]; 962e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } else { 9637638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPositions[fFirstVertexIndex + 1] = fPositions[fPositions.count() - 1]; 964e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth } 96566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 96691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 967da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 968da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (ctm.hasPerspective()) { 969da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth for (int i = 0; i < fPositions.count(); ++i) { 970da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar pathZ = fTransformedHeightFunc(fPositions[i]); 971da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar factor = SkScalarInvert(fLightZ - pathZ); 972da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPositions[i].fX = (fPositions[i].fX*fLightZ - lightPos.fX*pathZ)*factor; 973da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fPositions[i].fY = (fPositions[i].fY*fLightZ - lightPos.fY*pathZ)*factor; 974da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 975da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#ifdef DRAW_CENTROID 976da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar pathZ = fTransformedHeightFunc(fCentroid); 977da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth SkScalar factor = SkScalarInvert(fLightZ - pathZ); 978da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fCentroid.fX = (fCentroid.fX*fLightZ - lightPos.fX*pathZ)*factor; 979da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth fCentroid.fY = (fCentroid.fY*fLightZ - lightPos.fY*pathZ)*factor; 980da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#endif 981da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth } 982da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#ifdef DRAW_CENTROID 983da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(-2, -2); 984da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 985da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(2, -2); 986da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 987da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(-2, 2); 988da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 989da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fPositions.push() = fCentroid + SkVector::Make(2, 2); 990da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fColors.push() = SkColorSetARGB(255, 0, 255, 255); 991da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 992da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 4; 993da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 2; 994da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 995da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 996da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 4; 997da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 1; 998da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth *fIndices.push() = fPositions.count() - 3; 999da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth#endif 1000da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth 10010dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon fSucceeded = true; 100291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 100391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1004ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonvoid SkSpotShadowTessellator::computeClipAndPathPolygons(const SkPath& path, const SkMatrix& ctm, 1005da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth const SkMatrix& shadowTransform) { 1006ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1007ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon.setReserve(path.countPoints()); 1008ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1009ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // Walk around the path and compute clip polygon and path polygon. 1010ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // Will also accumulate sum of areas for centroid. 1011ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // For Bezier curves, we compute additional interior points on curve. 101291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPath::Iter iter(path, true); 101391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint pts[4]; 101491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPath::Verb verb; 101591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1016e7c85c45c4c0a97adc6711bb12ecacc36af4ba11Brian Salomon fClipPolygon.reset(); 1017e5f5bf5175e426ebb6aa234f4387831c898f20adJim Van Verth 1018ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // init centroid 1019ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid = SkPoint::Make(0, 0); 1020ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fArea = 0; 1021ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 102266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // coefficients to compute cubic Bezier at t = 5/16 1023ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kA = 0.32495117187f; 1024ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kB = 0.44311523437f; 1025ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kC = 0.20141601562f; 1026ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kD = 0.03051757812f; 102766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 102866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint curvePoint; 102966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar w; 103091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 103191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth switch (verb) { 103291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kLine_Verb: 1033a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(&pts[1], 1); 103491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fClipPolygon.push() = pts[1]; 1035ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->INHERITED::handleLine(shadowTransform, &pts[1]); 103691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 103791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kQuad_Verb: 1038a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 3); 103966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 1/2 104066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = 0.25f*pts[0].fX + 0.5f*pts[1].fX + 0.25f*pts[2].fX; 104166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = 0.25f*pts[0].fY + 0.5f*pts[1].fY + 0.25f*pts[2].fY; 104266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 104366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[2]; 1044ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handleQuad(shadowTransform, pts); 104591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 104691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kConic_Verb: 1047a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 3); 104866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon w = iter.conicWeight(); 1049a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // point at t = 1/2 105066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = 0.25f*pts[0].fX + w*0.5f*pts[1].fX + 0.25f*pts[2].fX; 105166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = 0.25f*pts[0].fY + w*0.5f*pts[1].fY + 0.25f*pts[2].fY; 105266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint *= SkScalarInvert(0.5f + 0.5f*w); 105366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 105466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[2]; 1055ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handleConic(shadowTransform, pts, w); 105691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 105791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kCubic_Verb: 1058a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 4); 105966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 5/16 106066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = kA*pts[0].fX + kB*pts[1].fX + kC*pts[2].fX + kD*pts[3].fX; 106166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = kA*pts[0].fY + kB*pts[1].fY + kC*pts[2].fY + kD*pts[3].fY; 106266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 106366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 11/16 106466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = kD*pts[0].fX + kC*pts[1].fX + kB*pts[2].fX + kA*pts[3].fX; 106566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = kD*pts[0].fY + kC*pts[1].fY + kB*pts[2].fY + kA*pts[3].fY; 106666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 106766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[3]; 1068ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon this->handleCubic(shadowTransform, pts); 106991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 1070ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon case SkPath::kMove_Verb: 107191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kClose_Verb: 1072ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon case SkPath::kDone_Verb: 107391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 107491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth default: 107591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkDEBUGFAIL("unknown verb"); 107691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 107791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 107891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1079ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // finish centroid 1080ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fPathPolygon.count() > 0) { 1081ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint currPoint = fPathPolygon[fPathPolygon.count() - 1]; 1082ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint nextPoint = fPathPolygon[0]; 1083ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar quadArea = currPoint.cross(nextPoint); 1084ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fX += (currPoint.fX + nextPoint.fX) * quadArea; 1085ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fY += (currPoint.fY + nextPoint.fY) * quadArea; 1086ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fArea += quadArea; 1087ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid *= SK_Scalar1 / (3 * fArea); 1088ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1089ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1090ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrClipPoint = fClipPolygon.count() - 1; 109166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon} 109266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1093ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonvoid SkSpotShadowTessellator::computeClipVectorsAndTestCentroid() { 109466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkASSERT(fClipPolygon.count() >= 3); 109566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1096ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // init clip vectors 109766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector v0 = fClipPolygon[1] - fClipPolygon[0]; 109866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipVectors.push() = v0; 109966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 110066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // init centroid check 110166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool hiddenCentroid = true; 1102ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v1 = fCentroid - fClipPolygon[0]; 110366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar initCross = v0.cross(v1); 110466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 110566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon for (int p = 1; p < fClipPolygon.count(); ++p) { 1106ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // add to clip vectors 110766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon v0 = fClipPolygon[(p + 1) % fClipPolygon.count()] - fClipPolygon[p]; 110866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipVectors.push() = v0; 110966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Determine if transformed centroid is inside clipPolygon. 1110ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon v1 = fCentroid - fClipPolygon[p]; 111166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (initCross*v0.cross(v1) <= 0) { 111266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon hiddenCentroid = false; 111366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 111466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 111566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkASSERT(fClipVectors.count() == fClipPolygon.count()); 111666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1117ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fTransparent = fTransparent || !hiddenCentroid; 111866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon} 111966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 112066085ed41779211f9e7e17aa493d4585d73445feBrian Salomonbool SkSpotShadowTessellator::clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, 112166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint* clipPoint) { 112266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector segmentVector = centroid - umbraPoint; 112366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1124ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int startClipPoint = fCurrClipPoint; 112566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon do { 1126ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector dp = umbraPoint - fClipPolygon[fCurrClipPoint]; 1127ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar denom = fClipVectors[fCurrClipPoint].cross(segmentVector); 112866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar t_num = dp.cross(segmentVector); 112966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // if line segments are nearly parallel 113066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (SkScalarNearlyZero(denom)) { 113166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // and collinear 113266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (SkScalarNearlyZero(t_num)) { 113366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return false; 113466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 113566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // otherwise are separate, will try the next poly segment 113666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // else if crossing lies within poly segment 113766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (t_num >= 0 && t_num <= denom) { 1138ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar s_num = dp.cross(fClipVectors[fCurrClipPoint]); 113966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // if umbra point is inside the clip polygon 1140da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (s_num >= 0 && s_num <= denom) { 114166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon segmentVector *= s_num/denom; 114266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *clipPoint = umbraPoint + segmentVector; 114366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return true; 114466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 114566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 1146ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrClipPoint = (fCurrClipPoint + 1) % fClipPolygon.count(); 1147ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } while (fCurrClipPoint != startClipPoint); 114866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 114966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return false; 115091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 115191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1152ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonint SkSpotShadowTessellator::getClosestUmbraPoint(const SkPoint& p) { 1153ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar minDistance = p.distanceToSqd(fUmbraPolygon[fCurrUmbraPoint]); 1154ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int index = fCurrUmbraPoint; 1155ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int dir = 1; 1156ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int next = (index + dir) % fUmbraPolygon.count(); 1157ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1158ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // init travel direction 1159ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar distance = p.distanceToSqd(fUmbraPolygon[next]); 1160ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (distance < minDistance) { 1161ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon index = next; 1162ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon minDistance = distance; 1163ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 1164ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon dir = fUmbraPolygon.count()-1; 1165ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1166ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1167ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // iterate until we find a point that increases the distance 1168ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon next = (index + dir) % fUmbraPolygon.count(); 1169ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon distance = p.distanceToSqd(fUmbraPolygon[next]); 1170ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon while (distance < minDistance) { 1171ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon index = next; 1172ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon minDistance = distance; 1173ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon next = (index + dir) % fUmbraPolygon.count(); 1174ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon distance = p.distanceToSqd(fUmbraPolygon[next]); 1175ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1176ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1177ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCurrUmbraPoint = index; 1178ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return index; 1179ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1180ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1181efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::mapPoints(SkScalar scale, const SkVector& xlate, 118291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint* pts, int count) { 118391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // TODO: vectorize 118491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth for (int i = 0; i < count; ++i) { 118591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth pts[i] *= scale; 118691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth pts[i] += xlate; 118791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 118891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 118991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1190ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonstatic bool duplicate_pt(const SkPoint& p0, const SkPoint& p1) { 1191ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kClose = (SK_Scalar1 / 16); 1192ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon static constexpr SkScalar kCloseSqd = kClose*kClose; 1193ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1194ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar distSq = p0.distanceToSqd(p1); 1195ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return distSq < kCloseSqd; 1196ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1197ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1198ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonstatic bool is_collinear(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2) { 1199ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v0 = p1 - p0; 1200ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v1 = p2 - p0; 1201ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return (SkScalarNearlyZero(v0.cross(v1))); 1202ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1203ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1204efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::handleLine(const SkPoint& p) { 1205ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // remove coincident points and add to centroid 1206ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fPathPolygon.count() > 0) { 1207ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon const SkPoint& lastPoint = fPathPolygon[fPathPolygon.count() - 1]; 1208ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (duplicate_pt(p, lastPoint)) { 1209ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return; 1210ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1211ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar quadArea = lastPoint.cross(p); 1212ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fX += (p.fX + lastPoint.fX) * quadArea; 1213ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fCentroid.fY += (p.fY + lastPoint.fY) * quadArea; 1214ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fArea += quadArea; 1215ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1216ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1217ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // try to remove collinear points 1218ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fPathPolygon.count() > 1 && is_collinear(fPathPolygon[fPathPolygon.count()-2], 1219ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon[fPathPolygon.count()-1], 1220ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon p)) { 1221ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon fPathPolygon[fPathPolygon.count() - 1] = p; 1222ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 1223ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fPathPolygon.push() = p; 1224ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 1225ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon} 1226ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1227ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonvoid SkSpotShadowTessellator::handlePolyPoint(const SkPoint& p) { 122891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fInitPoints.count() < 2) { 122991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fInitPoints.push() = p; 123091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 123191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 123291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 123391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fInitPoints.count() == 2) { 123491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // determine if cw or ccw 123591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector v0 = fInitPoints[1] - fInitPoints[0]; 123691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector v1 = p - fInitPoints[0]; 1237ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkScalar perpDot = v0.cross(v1); 123891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (SkScalarNearlyZero(perpDot)) { 123991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // nearly parallel, just treat as straight line and continue 124091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fInitPoints[1] = p; 124191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 124291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 124391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 124491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // if perpDot > 0, winding is ccw 124591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fDirection = (perpDot > 0) ? -1 : 1; 124691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 124791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // add first quad 12487638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth if (!compute_normal(fInitPoints[0], fInitPoints[1], fDirection, &fFirstOutset)) { 124991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // first two points are incident, make the third point the second and continue 125091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fInitPoints[1] = p; 125191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 125291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 125391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 12547638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fFirstOutset *= fRadius; 125591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fFirstPoint = fInitPoints[0]; 12567638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fFirstVertexIndex = fPositions.count(); 12577638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevOutset = fFirstOutset; 125891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = fFirstPoint; 1259e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth fPrevUmbraIndex = -1; 126066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 126166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon this->addInnerPoint(fFirstPoint); 12627638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevUmbraIndex = fFirstVertexIndex; 126366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 126466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (!fTransparent) { 126566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint clipPoint; 12667638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth bool isOutside = this->clipUmbraPoint(fPositions[fFirstVertexIndex], fCentroid, &clipPoint); 126766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (isOutside) { 126866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = clipPoint; 126966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 127066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 127166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraOutside = isOutside; 127266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fFirstUmbraOutside = isOutside; 127366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 127491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 12757638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth SkPoint newPoint = fFirstPoint + fFirstOutset; 127691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = newPoint; 127791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 12787638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth this->addEdge(fInitPoints[1], fFirstOutset); 127991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 128091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // to ensure we skip this block next time 128191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fInitPoints.push() = p; 128291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 128391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 128491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector normal; 1285da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth if (compute_normal(fPrevPoint, p, fDirection, &normal)) { 1286da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth normal *= fRadius; 1287da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addArc(normal, true); 1288da96550d3941cb794a799c73506a1c5b695c70a1Jim Van Verth this->addEdge(p, normal); 128991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 129091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 129191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1292ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomonbool SkSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint) { 1293ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkPoint umbraPoint; 1294ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (!fValidUmbra) { 1295ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon SkVector v = fCentroid - pathPoint; 1296ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon v *= 0.95f; 1297ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon umbraPoint = pathPoint + v; 129891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } else { 1299ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon umbraPoint = fUmbraPolygon[this->getClosestUmbraPoint(pathPoint)]; 130091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 130166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 130291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = pathPoint; 1303ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1304ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // merge "close" points 1305e7e1d9d039b12a86b9a595871a2bd13fe1c28f72Jim Van Verth if (fPrevUmbraIndex == -1 || 1306ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon !duplicate_pt(umbraPoint, fPositions[fPrevUmbraIndex])) { 1307ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fPositions.push() = umbraPoint; 1308ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fColors.push() = fUmbraColor; 1309ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon 1310ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return false; 1311ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 1312ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon return true; 1313ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 131491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 131591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1316efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { 131766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add next umbra point 1318ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon bool duplicate = this->addInnerPoint(nextPoint); 1319ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int prevPenumbraIndex = duplicate ? fPositions.count()-1 : fPositions.count()-2; 1320ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon int currUmbraIndex = duplicate ? fPrevUmbraIndex : fPositions.count()-1; 132166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 1322ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (!duplicate) { 1323ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // add to center fan if transparent or centroid showing 1324ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (fTransparent) { 1325ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = 0; 1326ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = fPrevUmbraIndex; 1327ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = currUmbraIndex; 1328ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon // otherwise add to clip ring 1329ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } else { 133066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint clipPoint; 1331ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon bool isOutside = this->clipUmbraPoint(fPositions[currUmbraIndex], fCentroid, 1332ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon &clipPoint); 133366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (isOutside) { 133466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = clipPoint; 133566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 133666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 133766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 133866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 133966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex + 1; 134066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fPrevUmbraOutside) { 134166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // fill out quad 134266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 134366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex + 1; 134466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 134566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 134666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (fPrevUmbraOutside) { 134766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add tri 134866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 134966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 135066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 135166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 135266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraOutside = isOutside; 135366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 135466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 135566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 135666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add next penumbra point and quad 135791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint newPoint = nextPoint + nextNormal; 135891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = newPoint; 135991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 136091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 1361ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon if (!duplicate) { 1362ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = fPrevUmbraIndex; 1363ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = prevPenumbraIndex; 1364ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon *fIndices.push() = currUmbraIndex; 1365ab664fa5b5fb96dd1079c090534330ca7e8a10efBrian Salomon } 136691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 136766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = prevPenumbraIndex; 136891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 136966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 137091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 137166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = currUmbraIndex; 13727638785bea9fa6ce3505c3393ad3d3aff9af2d0dJim Van Verth fPrevOutset = nextNormal; 137391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 1374958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 1375958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon/////////////////////////////////////////////////////////////////////////////////////////////////// 1376958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 1377aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonsk_sp<SkVertices> SkShadowTessellator::MakeAmbient(const SkPath& path, const SkMatrix& ctm, 1378e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth const SkPoint3& zPlane, bool transparent) { 1379e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkAmbientShadowTessellator ambientTess(path, ctm, zPlane, transparent); 1380aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return ambientTess.releaseVertices(); 1381958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon} 1382958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 1383aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonsk_sp<SkVertices> SkShadowTessellator::MakeSpot(const SkPath& path, const SkMatrix& ctm, 1384e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth const SkPoint3& zPlane, const SkPoint3& lightPos, 1385060d9820364b0cf09c7eb3bda449f24c3dcba2e2Jim Van Verth SkScalar lightRadius, bool transparent) { 1386e308a122ef996a64a21a6339e3b50b9edfdf654fJim Van Verth SkSpotShadowTessellator spotTess(path, ctm, zPlane, lightPos, lightRadius, transparent); 1387aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return spotTess.releaseVertices(); 1388958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon} 1389