SkShadowTessellator.cpp revision aff27a23ad4b38851429066dbfb43cfa7199e37c
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" 1185dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#include "SkPath.h" 12aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon#include "SkVertices.h" 1385dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth 1485dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#if SK_SUPPORT_GPU 1585dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#include "GrPathUtils.h" 1685dc96b8cef031cc38d80f63056581c41c57ff7dJim Van Verth#endif 1758abc9e2c56464336472493745e91133819deb96Jim Van Verth 18958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 19a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth/** 20a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth * Base class 21a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth */ 22aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkBaseShadowTessellator { 23958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonpublic: 24aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkBaseShadowTessellator(SkScalar radius, SkColor umbraColor, SkColor penumbraColor, 25aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon bool transparent); 26aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon virtual ~SkBaseShadowTessellator() {} 270dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 28aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon sk_sp<SkVertices> releaseVertices() { 29aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon if (!fSucceeded) { 30aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return nullptr; 31aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon } 32aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon int vCount = this->vertexCount(); 33aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon int iCount = this->indexCount(); 34aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon // We copy here for two reasons: 1) To tighten up our arrays and 2) to get into memory 35aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon // allocated by new[] rather than malloc. 36aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon // TODO: If we know we're not caching then we should avoid this. 37aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkPoint* positions = new SkPoint[vCount]; 38aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkColor* colors = new SkColor[vCount]; 39aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon uint16_t* indices = new uint16_t[iCount]; 40aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon memcpy(positions, fPositions.begin(), sizeof(SkPoint) * vCount); 41aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon memcpy(colors, fColors.begin(), sizeof(SkColor) * vCount); 42aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon memcpy(indices, fIndices.begin(), sizeof(uint16_t) * iCount); 43aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return SkVertices::MakeIndexed(SkCanvas::kTriangles_VertexMode, 44aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon std::unique_ptr<const SkPoint[]>(positions), 45aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon std::unique_ptr<const SkColor[]>(colors), 46aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon nullptr, 47aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon vCount, 48aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon std::unique_ptr<const uint16_t[]>(indices), 49aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon iCount); 501a8b79a79e8aa6d4723588fd1125cb3b08886af8Brian Salomon } 51958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 52a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthprotected: 53aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon int vertexCount() const { return fPositions.count(); } 54aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon int indexCount() const { return fIndices.count(); } 55aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon 56a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth virtual void handleLine(const SkPoint& p) = 0; 57a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkMatrix& m, SkPoint* p); 58958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 59958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon void handleQuad(const SkPoint pts[3]); 60a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleQuad(const SkMatrix& m, SkPoint pts[3]); 61958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 62a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleCubic(const SkMatrix& m, SkPoint pts[4]); 63958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 64a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleConic(const SkMatrix& m, SkPoint pts[3], SkScalar w); 65958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 66958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon void addArc(const SkVector& nextNormal); 67958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon void finishArcAndAddEdge(const SkVector& nextPoint, const SkVector& nextNormal); 68a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth virtual void addEdge(const SkVector& nextPoint, const SkVector& nextNormal) = 0; 69958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 70a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // first three 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 79958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon int fFirstVertex; 80958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkVector fFirstNormal; 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; 92a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkVector fPrevNormal; 93a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fPrevPoint; 94958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon}; 95958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 96bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verthstatic bool compute_normal(const SkPoint& p0, const SkPoint& p1, SkScalar radius, 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; 102bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (!normal.normalize()) { 103bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return false; 104bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 105bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth normal *= radius*dir; 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) { 112bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth const SkScalar kRecipPixelsPerArcSegment = 0.25f; 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 118bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar steps = r*theta*kRecipPixelsPerArcSegment; 119bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 120bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar dTheta = theta / steps; 121bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *rotSin = SkScalarSinCos(dTheta, rotCos); 122bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *n = SkScalarFloorToInt(steps); 123bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 124bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 125aff27a23ad4b38851429066dbfb43cfa7199e37cBrian SalomonSkBaseShadowTessellator::SkBaseShadowTessellator(SkScalar radius, SkColor umbraColor, 126aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkColor penumbraColor, bool transparent) 127aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon : fFirstVertex(-1) 128aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fSucceeded(false) 129aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fTransparent(transparent) 130aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fUmbraColor(umbraColor) 131aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fPenumbraColor(penumbraColor) 132aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fRadius(radius) 133aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fDirection(1) 134aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon , fPrevUmbraIndex(-1) { 135a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fInitPoints.setReserve(3); 136a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 137a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // child classes will set reserve for positions, colors and indices 138a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 139a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 140a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth// tesselation tolerance values, in device space pixels 141a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kQuadTolerance = 0.2f; 142a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kCubicTolerance = 0.2f; 143a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthstatic const SkScalar kConicTolerance = 0.5f; 144a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 145aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleLine(const SkMatrix& m, SkPoint* p) { 146a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(p, 1); 147a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(*p); 148a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 149a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 150aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleQuad(const SkPoint pts[3]) { 151a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#if SK_SUPPORT_GPU 152a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // TODO: Pull PathUtils out of Ganesh? 153a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int maxCount = GrPathUtils::quadraticPointCount(pts, kQuadTolerance); 154a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setReserve(maxCount); 155a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint* target = fPointBuffer.begin(); 156a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = GrPathUtils::generateQuadraticPoints(pts[0], pts[1], pts[2], 157a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth kQuadTolerance, &target, maxCount); 158a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setCount(count); 159a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; i++) { 160a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(fPointBuffer[i]); 161a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 162a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#else 163a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // for now, just to draw something 164a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[1]); 165a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleLine(pts[2]); 166a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#endif 167a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 168a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 169aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleQuad(const SkMatrix& m, SkPoint pts[3]) { 170a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 3); 171a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(pts); 172a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 173a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 174aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleCubic(const SkMatrix& m, SkPoint pts[4]) { 175a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 4); 176a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#if SK_SUPPORT_GPU 177a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // TODO: Pull PathUtils out of Ganesh? 178a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int maxCount = GrPathUtils::cubicPointCount(pts, kCubicTolerance); 179a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPointBuffer.setReserve(maxCount); 180a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint* target = fPointBuffer.begin(); 181a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = GrPathUtils::generateCubicPoints(pts[0], pts[1], pts[2], pts[3], 182a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth kCubicTolerance, &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 this->handleLine(pts[3]); 192a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth#endif 193a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 194a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 195aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::handleConic(const SkMatrix& m, SkPoint pts[3], SkScalar w) { 196a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth m.mapPoints(pts, 3); 197a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkAutoConicToQuads quadder; 198a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth const SkPoint* quads = quadder.computeQuads(pts, w, kConicTolerance); 199a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint lastPoint = *(quads++); 200a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int count = quadder.countQuads(); 201a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < count; ++i) { 202a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint quadPts[3]; 203a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[0] = lastPoint; 204a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[1] = quads[0]; 205a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quadPts[2] = i == count - 1 ? pts[2] : quads[1]; 206a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(quadPts); 207a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth lastPoint = quadPts[2]; 208a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth quads += 2; 209a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 210a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 211a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 212aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::addArc(const SkVector& nextNormal) { 213a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // fill in fan from previous quad 214a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar rotSin, rotCos; 215a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int numSteps; 216a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth compute_radial_steps(fPrevNormal, nextNormal, fRadius, &rotSin, &rotCos, &numSteps); 217a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkVector prevNormal = fPrevNormal; 218a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth for (int i = 0; i < numSteps; ++i) { 219a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkVector nextNormal; 220a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth nextNormal.fX = prevNormal.fX*rotCos - prevNormal.fY*rotSin; 221a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth nextNormal.fY = prevNormal.fY*rotCos + prevNormal.fX*rotSin; 222a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fPositions.push() = fPrevPoint + nextNormal; 223a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fColors.push() = fPenumbraColor; 224a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPrevUmbraIndex; 225a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPositions.count() - 2; 226a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPositions.count() - 1; 227a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 228a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth prevNormal = nextNormal; 229a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth } 230a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 231a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 232aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonvoid SkBaseShadowTessellator::finishArcAndAddEdge(const SkPoint& nextPoint, 233aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon const SkVector& nextNormal) { 234a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // close out previous arc 235a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fPositions.push() = fPrevPoint + nextNormal; 236a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fColors.push() = fPenumbraColor; 237a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPrevUmbraIndex; 238a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPositions.count() - 2; 239a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fIndices.push() = fPositions.count() - 1; 240a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 241a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->addEdge(nextPoint, nextNormal); 242a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth} 243a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 244a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 245a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth////////////////////////////////////////////////////////////////////////////////////////////////// 246a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 247aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkAmbientShadowTessellator : public SkBaseShadowTessellator { 248a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthpublic: 249a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkAmbientShadowTessellator(const SkPath& path, const SkMatrix& ctm, 250a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar radius, SkColor umbraColor, 251a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkColor penumbraColor, bool transparent); 252a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 253a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthprivate: 254a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkPoint& p) override; 255a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void addEdge(const SkVector& nextPoint, const SkVector& nextNormal) override; 256a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 257a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth int fCentroidCount; 258a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 259aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon typedef SkBaseShadowTessellator INHERITED; 260a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth}; 261a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 262efe3dedbb3493b738abdb56041b093245e4e8711Jim Van VerthSkAmbientShadowTessellator::SkAmbientShadowTessellator(const SkPath& path, 263a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth const SkMatrix& ctm, 264bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar radius, 265efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verth SkColor umbraColor, 266efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verth SkColor penumbraColor, 267bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth bool transparent) 268a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth : INHERITED(radius, umbraColor, penumbraColor, transparent) { 269bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Outer ring: 3*numPts 270bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Middle ring: numPts 271bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions.setReserve(4 * path.countPoints()); 272bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fColors.setReserve(4 * path.countPoints()); 273bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Outer ring: 12*numPts 274bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // Middle ring: 0 275bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fIndices.setReserve(12 * path.countPoints()); 276bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 277bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // walk around the path, tessellate and generate outer ring 278bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if original path is transparent, will accumulate sum of points for centroid 279bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPath::Iter iter(path, true); 280bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPoint pts[4]; 281bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkPath::Verb verb; 282bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 283bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = SkPoint::Make(0, 0); 284bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = umbraColor; 285bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fCentroidCount = 0; 286bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 287bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 288bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth switch (verb) { 289bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kLine_Verb: 290a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->INHERITED::handleLine(ctm, &pts[1]); 291bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 292bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kQuad_Verb: 293a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(ctm, pts); 294bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 295bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kCubic_Verb: 296a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleCubic(ctm, pts); 297bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 298bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kConic_Verb: 299a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleConic(ctm, pts, iter.conicWeight()); 300bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 301bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kMove_Verb: 302bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kClose_Verb: 303bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth case SkPath::kDone_Verb: 304bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth break; 305bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 306bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 307bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 3080dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon if (!this->indexCount()) { 3090dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon return; 3100dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon } 3110dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 312bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 313a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth if (compute_normal(fPrevPoint, fFirstPoint, fRadius, fDirection, 314bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth &normal)) { 315bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth this->addArc(normal); 316bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 317bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // close out previous arc 318a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fPositions.push() = fPrevPoint + normal; 319bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 32066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 321bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 322bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 1; 323bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 324bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // add final edge 325a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth *fPositions.push() = fFirstPoint + normal; 326bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 327bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 32866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 329bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 330bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fFirstVertex; 331bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 332bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 333bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 1; 334bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fFirstVertex; 335bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 336bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 337bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // finalize centroid 338bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 339bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions[0] *= SkScalarFastInvert(fCentroidCount); 340bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 341bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = 0; 34266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 343bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fFirstVertex; 344bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 345bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 346bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // final fan 347bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fPositions.count() >= 3) { 34866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fFirstVertex; 349bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPrevNormal = normal; 350a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = fFirstPoint; 351bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth this->addArc(fFirstNormal); 352bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 353bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fFirstVertex; 354bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 1; 355bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fFirstVertex + 1; 356bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 3570dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon fSucceeded = true; 358bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 359bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 360efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkAmbientShadowTessellator::handleLine(const SkPoint& p) { 361bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fInitPoints.count() < 2) { 362bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fInitPoints.push() = p; 363bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 364bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 365bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 366bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fInitPoints.count() == 2) { 367bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // determine if cw or ccw 368bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector v0 = fInitPoints[1] - fInitPoints[0]; 369bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector v1 = p - fInitPoints[0]; 370bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkScalar perpDot = v0.fX*v1.fY - v0.fY*v1.fX; 371bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (SkScalarNearlyZero(perpDot)) { 372bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // nearly parallel, just treat as straight line and continue 373bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fInitPoints[1] = p; 374bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 375bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 376bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 377bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if perpDot > 0, winding is ccw 378bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fDirection = (perpDot > 0) ? -1 : 1; 379bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 380bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // add first quad 381bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (!compute_normal(fInitPoints[0], fInitPoints[1], fRadius, fDirection, 382bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth &fFirstNormal)) { 383bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // first two points are incident, make the third point the second and continue 384bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fInitPoints[1] = p; 385bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth return; 386bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 387bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 388a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fFirstPoint = fInitPoints[0]; 389bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fFirstVertex = fPositions.count(); 390bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPrevNormal = fFirstNormal; 391a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = fFirstPoint; 39266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fFirstVertex; 393bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 394bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = fInitPoints[0]; 395bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fUmbraColor; 396bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = fInitPoints[0] + fFirstNormal; 397bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 398bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 399bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions[0] += fInitPoints[0]; 400bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fCentroidCount = 1; 401bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 402bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth this->addEdge(fInitPoints[1], fFirstNormal); 403bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 404bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // to ensure we skip this block next time 405bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fInitPoints.push() = p; 406bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 407bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 408bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth SkVector normal; 40966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (compute_normal(fPositions[fPrevUmbraIndex], p, fRadius, fDirection, &normal)) { 410bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth this->addArc(normal); 41191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth this->finishArcAndAddEdge(p, normal); 412bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 413bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 414bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 415efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkAmbientShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { 416bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // add next quad 417bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = nextPoint; 418bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fUmbraColor; 419bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fPositions.push() = nextPoint + nextNormal; 420bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fColors.push() = fPenumbraColor; 421bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 42266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 423bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 3; 424bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 425bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 426bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 3; 427bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 1; 428bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 429bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 430bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth // if transparent, add point to first one in array and add to center fan 431bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth if (fTransparent) { 432bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPositions[0] += nextPoint; 433bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth ++fCentroidCount; 434bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 435bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = 0; 43666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 437bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth *fIndices.push() = fPositions.count() - 2; 438bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth } 439bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth 44066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fPositions.count() - 2; 441bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth fPrevNormal = nextNormal; 442a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth fPrevPoint = nextPoint; 443bce7496d7dd9131cc7121389a55f6d512ee7661eJim Van Verth} 44491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 44591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth/////////////////////////////////////////////////////////////////////////////////////////////////// 44691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 447aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonclass SkSpotShadowTessellator : public SkBaseShadowTessellator { 448958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonpublic: 449a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, 450a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar scale, const SkVector& translate, 451958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkScalar radius, SkColor umbraColor, SkColor penumbraColor, 452958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon bool transparent); 453958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 454958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomonprivate: 455a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void computeClipBounds(const SkPath& path, const SkMatrix& ctm, SkPath* devPath); 45666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon void checkUmbraAndTransformCentroid(SkScalar scale, const SkVector& xlate, 45766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool useDistanceToPoint); 45866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, SkPoint* clipPoint); 459958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 460a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void handleLine(const SkPoint& p) override; 461958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 462958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon void mapPoints(SkScalar scale, const SkVector& xlate, SkPoint* pts, int count); 46366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon void addInnerPoint(const SkPoint& pathPoint); 464a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth void addEdge(const SkVector& nextPoint, const SkVector& nextNormal) override; 465958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 466958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon SkTDArray<SkPoint> fClipPolygon; 46766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkTDArray<SkVector> fClipVectors; 468a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPoint fCentroid; 469a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth 47066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon int fCurrPolyPoint; 47166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool fPrevUmbraOutside; 47266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool fFirstUmbraOutside; 473a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth bool fValidUmbra; 474958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 475aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon typedef SkBaseShadowTessellator INHERITED; 476958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon}; 477958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 478a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van VerthSkSpotShadowTessellator::SkSpotShadowTessellator(const SkPath& path, const SkMatrix& ctm, 47991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkScalar scale, const SkVector& translate, 480a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkScalar radius, SkColor umbraColor, 481a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkColor penumbraColor, bool transparent) 482a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth : INHERITED(radius, umbraColor, penumbraColor, transparent) 4830dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon , fCurrPolyPoint(0) 4840dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon , fPrevUmbraOutside(false) 4850dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon , fFirstUmbraOutside(false) 486a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth , fValidUmbra(true) { 48791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // TODO: calculate these better 48866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Penumbra ring: 3*numPts 48966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Umbra ring: numPts 49091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // Inner ring: numPts 49166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPositions.setReserve(5 * path.countPoints()); 49266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fColors.setReserve(5 * path.countPoints()); 49366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Penumbra ring: 12*numPts 49466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Umbra ring: 3*numPts 49566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fIndices.setReserve(15 * path.countPoints()); 49691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 49791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fClipPolygon.setReserve(path.countPoints()); 49866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // compute rough clip bounds for umbra, plus centroid 499a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPath devPath; 500a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->computeClipBounds(path, ctm, &devPath); 50166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fClipPolygon.count() < 3) { 50266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return; 50366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 5040bd699e497819344083df4715928a54a597cd630Brian Salomon // We are going to apply 'scale' and 'xlate' (in that order) to each computed path point. We 5050bd699e497819344083df4715928a54a597cd630Brian Salomon // want the effect to be to scale the points relative to the path centroid and then translate 5060bd699e497819344083df4715928a54a597cd630Brian Salomon // them by the 'translate' param we were passed. 5070bd699e497819344083df4715928a54a597cd630Brian Salomon SkVector xlate = fCentroid * (1.f - scale) + translate; 50866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 50966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // check to see if we have a valid umbra at all 51066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool usePointCheck = path.isRRect(nullptr) || path.isRect(nullptr) || path.isOval(nullptr); 51166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon this->checkUmbraAndTransformCentroid(scale, translate, usePointCheck); 51291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 51391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // walk around the path, tessellate and generate inner and outer rings 514a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPath::Iter iter(devPath, true); 51591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint pts[4]; 51691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPath::Verb verb; 51766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fTransparent) { 51866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = fCentroid; 51966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 52066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 521a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkMatrix shadowTransform; 522a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth shadowTransform.setScaleTranslate(scale, scale, xlate.fX, xlate.fY); 52391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 52491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth switch (verb) { 52591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kLine_Verb: 526a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->INHERITED::handleLine(shadowTransform, &pts[1]); 52791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 52891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kQuad_Verb: 529a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleQuad(shadowTransform, pts); 53091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 53191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kCubic_Verb: 532a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleCubic(shadowTransform, pts); 53391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 53491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kConic_Verb: 535a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth this->handleConic(shadowTransform, pts, iter.conicWeight()); 53691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 53791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kMove_Verb: 53891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kClose_Verb: 53991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kDone_Verb: 54091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 54191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 54291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 54391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 5440dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon if (!this->indexCount()) { 5450dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon return; 5460dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon } 5470dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon 54891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector normal; 54991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (compute_normal(fPrevPoint, fFirstPoint, fRadius, fDirection, 55091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth &normal)) { 55191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth this->addArc(normal); 55291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 55391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // close out previous arc 55491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = fPrevPoint + normal; 55591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 55666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 55791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 2; 55891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 55991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 56066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add to center fan 56166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fTransparent) { 56266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = 0; 56366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 56466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex; 56566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // or to clip ring 56666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 56766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fFirstUmbraOutside) { 56866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 56966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex; 57066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex + 1; 57166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fPrevUmbraOutside) { 57266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // fill out quad 57366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 57466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex + 1; 57566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 57666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 57766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (fPrevUmbraOutside) { 57866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add tri 57966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 58066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex; 58166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 58266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 58366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 58466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 58591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // add final edge 58691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = fFirstPoint + normal; 58791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 58891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 58966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 59091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 2; 59191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fFirstVertex; 59291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 59391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 2; 59491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 59591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fFirstVertex; 59691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 59791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 59891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // final fan 59991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fPositions.count() >= 3) { 60066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fFirstVertex; 60191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = fFirstPoint; 60291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevNormal = normal; 60391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth this->addArc(fFirstNormal); 60491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 60591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fFirstVertex; 60691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 60766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fFirstUmbraOutside) { 60866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex + 2; 60966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 61066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fFirstVertex + 1; 61166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 61291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 6130dda9cb881900241c1c2193ddf3bede72cda898bBrian Salomon fSucceeded = true; 61491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 61591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 616a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verthvoid SkSpotShadowTessellator::computeClipBounds(const SkPath& path, const SkMatrix& ctm, 617a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkPath* devPath) { 61891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // walk around the path and compute clip polygon 61991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // if original path is transparent, will accumulate sum of points for centroid 62066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // for Bezier curves, we compute additional interior points on curve 62191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPath::Iter iter(path, true); 62291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint pts[4]; 62391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPath::Verb verb; 62491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 62591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fCentroid = SkPoint::Make(0, 0); 62691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth int centroidCount = 0; 62791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fClipPolygon.reset(); 62891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 62966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // coefficients to compute cubic Bezier at t = 5/16 63066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon const SkScalar kA = 0.32495117187f; 63166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon const SkScalar kB = 0.44311523437f; 63266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon const SkScalar kC = 0.20141601562f; 63366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon const SkScalar kD = 0.03051757812f; 63466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 63566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint curvePoint; 63666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar w; 63791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 63891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth switch (verb) { 63991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kMove_Verb: 640a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(&pts[0], 1); 641a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth devPath->moveTo(pts[0]); 64291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 64391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kLine_Verb: 644a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(&pts[1], 1); 645a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth devPath->lineTo(pts[1]); 64691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fCentroid += pts[1]; 64791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth centroidCount++; 64891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fClipPolygon.push() = pts[1]; 64991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 65091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kQuad_Verb: 651a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 3); 652a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth devPath->quadTo(pts[1], pts[2]); 65366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 1/2 65466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = 0.25f*pts[0].fX + 0.5f*pts[1].fX + 0.25f*pts[2].fX; 65566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = 0.25f*pts[0].fY + 0.5f*pts[1].fY + 0.25f*pts[2].fY; 65666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 65766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fCentroid += curvePoint; 65866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[2]; 65991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fCentroid += pts[2]; 66091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth centroidCount += 2; 66191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 66291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kConic_Verb: 663a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 3); 66466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon w = iter.conicWeight(); 665a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth devPath->conicTo(pts[1], pts[2], w); 666a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth // point at t = 1/2 66766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = 0.25f*pts[0].fX + w*0.5f*pts[1].fX + 0.25f*pts[2].fX; 66866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = 0.25f*pts[0].fY + w*0.5f*pts[1].fY + 0.25f*pts[2].fY; 66966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint *= SkScalarInvert(0.5f + 0.5f*w); 67066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 67166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fCentroid += curvePoint; 67266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[2]; 67391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fCentroid += pts[2]; 67491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth centroidCount += 2; 67591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 67691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kCubic_Verb: 677a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth ctm.mapPoints(pts, 4); 678a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth devPath->cubicTo(pts[1], pts[2], pts[3]); 67966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 5/16 68066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = kA*pts[0].fX + kB*pts[1].fX + kC*pts[2].fX + kD*pts[3].fX; 68166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = kA*pts[0].fY + kB*pts[1].fY + kC*pts[2].fY + kD*pts[3].fY; 68266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 68366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fCentroid += curvePoint; 68466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // point at t = 11/16 68566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fX = kD*pts[0].fX + kC*pts[1].fX + kB*pts[2].fX + kA*pts[3].fX; 68666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon curvePoint.fY = kD*pts[0].fY + kC*pts[1].fY + kB*pts[2].fY + kA*pts[3].fY; 68766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = curvePoint; 68866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fCentroid += curvePoint; 68966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipPolygon.push() = pts[3]; 69091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fCentroid += pts[3]; 69191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth centroidCount += 3; 69291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 69391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth case SkPath::kClose_Verb: 694a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth devPath->close(); 69591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth break; 69691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth default: 69791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkDEBUGFAIL("unknown verb"); 69891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 69991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 70091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 70191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fCentroid *= SkScalarInvert(centroidCount); 70266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fCurrPolyPoint = fClipPolygon.count() - 1; 70366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon} 70466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 70566085ed41779211f9e7e17aa493d4585d73445feBrian Salomonvoid SkSpotShadowTessellator::checkUmbraAndTransformCentroid(SkScalar scale, 70666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon const SkVector& xlate, 70766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool useDistanceToPoint) { 70866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkASSERT(fClipPolygon.count() >= 3); 70966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint transformedCentroid = fCentroid; 71066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon transformedCentroid += xlate; 71166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 71266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar localRadius = fRadius / scale; 71366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon localRadius *= localRadius; 71466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 71566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // init umbra check 71666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector w = fCentroid - fClipPolygon[0]; 71766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector v0 = fClipPolygon[1] - fClipPolygon[0]; 71866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipVectors.push() = v0; 71966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool validUmbra; 72066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar minDistance; 72166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // check distance against line segment 72266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (useDistanceToPoint) { 72366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon minDistance = w.lengthSqd(); 72466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 72566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar vSq = v0.dot(v0); 72666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar wDotV = w.dot(v0); 72766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon minDistance = w.dot(w) - wDotV*wDotV/vSq; 72866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 72966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon validUmbra = (minDistance >= localRadius); 73066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 73166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // init centroid check 73266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool hiddenCentroid = true; 73366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector v1 = transformedCentroid - fClipPolygon[0]; 73466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar initCross = v0.cross(v1); 73566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 73666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon for (int p = 1; p < fClipPolygon.count(); ++p) { 73766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Determine whether we have a real umbra by insetting clipPolygon by radius/scale 73866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // and see if it extends past centroid. 73966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // TODO: adjust this later for more accurate umbra calcs 74066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon w = fCentroid - fClipPolygon[p]; 74166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon v0 = fClipPolygon[(p + 1) % fClipPolygon.count()] - fClipPolygon[p]; 74266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fClipVectors.push() = v0; 74366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // check distance against line segment 74466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar distance; 74566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (useDistanceToPoint) { 74666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon distance = w.lengthSqd(); 74766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 74866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar vSq = v0.dot(v0); 74966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar wDotV = w.dot(v0); 75066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon distance = w.dot(w) - wDotV*wDotV/vSq; 75166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 75266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (distance < localRadius) { 75366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon validUmbra = false; 75466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 75566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (distance < minDistance) { 75666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon minDistance = distance; 75766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 75866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // Determine if transformed centroid is inside clipPolygon. 75966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon v1 = transformedCentroid - fClipPolygon[p]; 76066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (initCross*v0.cross(v1) <= 0) { 76166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon hiddenCentroid = false; 76266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 76366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 76466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkASSERT(fClipVectors.count() == fClipPolygon.count()); 76566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 76666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (!validUmbra) { 76766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar ratio = 256 * SkScalarSqrt(minDistance / localRadius); 76866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // they aren't PMColors, but the interpolation algorithm is the same 76966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fUmbraColor = SkPMLerp(fUmbraColor, fPenumbraColor, (unsigned)ratio); 77066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 77166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 77266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fTransparent = fTransparent || !hiddenCentroid || !validUmbra; 77366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fValidUmbra = validUmbra; 77466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fCentroid = transformedCentroid; 77566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon} 77666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 77766085ed41779211f9e7e17aa493d4585d73445feBrian Salomonbool SkSpotShadowTessellator::clipUmbraPoint(const SkPoint& umbraPoint, const SkPoint& centroid, 77866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint* clipPoint) { 77966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector segmentVector = centroid - umbraPoint; 78066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 78166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon int startPolyPoint = fCurrPolyPoint; 78266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon do { 78366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkVector dp = umbraPoint - fClipPolygon[fCurrPolyPoint]; 78466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar denom = fClipVectors[fCurrPolyPoint].cross(segmentVector); 78566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar t_num = dp.cross(segmentVector); 78666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // if line segments are nearly parallel 78766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (SkScalarNearlyZero(denom)) { 78866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // and collinear 78966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (SkScalarNearlyZero(t_num)) { 79066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return false; 79166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 79266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // otherwise are separate, will try the next poly segment 79366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // else if crossing lies within poly segment 79466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (t_num >= 0 && t_num <= denom) { 79566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar s_num = dp.cross(fClipVectors[fCurrPolyPoint]); 79666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // if umbra point is inside the clip polygon 79766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (s_num < 0) { 79866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return false; 79966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 80066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon segmentVector *= s_num/denom; 80166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *clipPoint = umbraPoint + segmentVector; 80266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return true; 80366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 80466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 80566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fCurrPolyPoint = (fCurrPolyPoint + 1) % fClipPolygon.count(); 80666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } while (fCurrPolyPoint != startPolyPoint); 80766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 80866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon return false; 80991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 81091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 811efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::mapPoints(SkScalar scale, const SkVector& xlate, 81291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint* pts, int count) { 81391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // TODO: vectorize 81491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth for (int i = 0; i < count; ++i) { 81591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth pts[i] *= scale; 81691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth pts[i] += xlate; 81791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 81891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 81991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 820efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::handleLine(const SkPoint& p) { 82191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fInitPoints.count() < 2) { 82291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fInitPoints.push() = p; 82391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 82491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 82591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 82691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (fInitPoints.count() == 2) { 82791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // determine if cw or ccw 82891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector v0 = fInitPoints[1] - fInitPoints[0]; 82991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector v1 = p - fInitPoints[0]; 83091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkScalar perpDot = v0.fX*v1.fY - v0.fY*v1.fX; 83191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (SkScalarNearlyZero(perpDot)) { 83291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // nearly parallel, just treat as straight line and continue 83391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fInitPoints[1] = p; 83491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 83591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 83691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 83791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // if perpDot > 0, winding is ccw 83891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fDirection = (perpDot > 0) ? -1 : 1; 83991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 84091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // add first quad 84191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (!compute_normal(fInitPoints[0], fInitPoints[1], fRadius, fDirection, 84291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth &fFirstNormal)) { 84391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // first two points are incident, make the third point the second and continue 84491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fInitPoints[1] = p; 84591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth return; 84691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 84791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 84891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fFirstPoint = fInitPoints[0]; 84991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fFirstVertex = fPositions.count(); 85091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevNormal = fFirstNormal; 85191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = fFirstPoint; 85266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = fFirstVertex; 85366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 85466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon this->addInnerPoint(fFirstPoint); 85566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 85666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (!fTransparent) { 85766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint clipPoint; 85866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool isOutside = this->clipUmbraPoint(fPositions[fFirstVertex], fCentroid, &clipPoint); 85966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (isOutside) { 86066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = clipPoint; 86166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 86266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 86366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraOutside = isOutside; 86466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fFirstUmbraOutside = isOutside; 86566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 86691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 86791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint newPoint = fFirstPoint + fFirstNormal; 86891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = newPoint; 86991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 87091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth this->addEdge(fInitPoints[1], fFirstNormal); 87191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 87291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth // to ensure we skip this block next time 87391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fInitPoints.push() = p; 87491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 87591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 87691af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector normal; 87791af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth if (compute_normal(fPrevPoint, p, fRadius, fDirection, &normal)) { 87891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth this->addArc(normal); 87991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth this->finishArcAndAddEdge(p, normal); 88091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 88191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 88291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 88366085ed41779211f9e7e17aa493d4585d73445feBrian Salomonvoid SkSpotShadowTessellator::addInnerPoint(const SkPoint& pathPoint) { 88491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkVector v = fCentroid - pathPoint; 88591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkScalar distance = v.length(); 88666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkScalar t; 88766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fValidUmbra) { 88866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkASSERT(distance >= fRadius); 88966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon t = fRadius / distance; 89091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } else { 89166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon t = 0.95f; 89291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth } 89366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon v *= t; 89466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint umbraPoint = pathPoint + v; 89566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = umbraPoint; 89666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 89766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 89891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevPoint = pathPoint; 89991af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 90091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 901efe3dedbb3493b738abdb56041b093245e4e8711Jim Van Verthvoid SkSpotShadowTessellator::addEdge(const SkPoint& nextPoint, const SkVector& nextNormal) { 90266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add next umbra point 90366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon this->addInnerPoint(nextPoint); 90466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon int prevPenumbraIndex = fPositions.count() - 2; 90566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon int currUmbraIndex = fPositions.count() - 1; 90666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 90766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add to center fan if transparent or centroid showing 90866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fTransparent) { 90966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = 0; 91066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 91166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 91266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // otherwise add to clip ring 91366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else { 91466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (!fTransparent) { 91566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon SkPoint clipPoint; 91666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon bool isOutside = clipUmbraPoint(fPositions[currUmbraIndex], fCentroid, &clipPoint); 91766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (isOutside) { 91866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fPositions.push() = clipPoint; 91966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fColors.push() = fUmbraColor; 92066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 92166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 92266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 92366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex + 1; 92466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon if (fPrevUmbraOutside) { 92566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // fill out quad 92666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 92766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex + 1; 92866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 92966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 93066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } else if (fPrevUmbraOutside) { 93166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add tri 93266085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 93366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 93466085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex + 1; 93566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 93666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraOutside = isOutside; 93766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 93866085ed41779211f9e7e17aa493d4585d73445feBrian Salomon } 93966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon 94066085ed41779211f9e7e17aa493d4585d73445feBrian Salomon // add next penumbra point and quad 94191af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth SkPoint newPoint = nextPoint + nextNormal; 94291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fPositions.push() = newPoint; 94391af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fColors.push() = fPenumbraColor; 94491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 94566085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = fPrevUmbraIndex; 94666085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = prevPenumbraIndex; 94766085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 94891af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 94966085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = prevPenumbraIndex; 95091af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth *fIndices.push() = fPositions.count() - 1; 95166085ed41779211f9e7e17aa493d4585d73445feBrian Salomon *fIndices.push() = currUmbraIndex; 95291af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth 95366085ed41779211f9e7e17aa493d4585d73445feBrian Salomon fPrevUmbraIndex = currUmbraIndex; 95491af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth fPrevNormal = nextNormal; 95591af72703830f3946c538b47c6c7c96afc0adde2Jim Van Verth} 956958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 957958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon/////////////////////////////////////////////////////////////////////////////////////////////////// 958958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 959aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonsk_sp<SkVertices> SkShadowTessellator::MakeAmbient(const SkPath& path, const SkMatrix& ctm, 960aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkScalar radius, SkColor umbra, SkColor penumbra, 961aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon bool transparent) { 962a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkAmbientShadowTessellator ambientTess(path, ctm, radius, umbra, penumbra, transparent); 963aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return ambientTess.releaseVertices(); 964958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon} 965958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon 966aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomonsk_sp<SkVertices> SkShadowTessellator::MakeSpot(const SkPath& path, const SkMatrix& ctm, 967aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkScalar scale, const SkVector& translate, 968aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkScalar radius, SkColor umbraColor, 969aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon SkColor penumbraColor, bool transparent) { 970a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth SkSpotShadowTessellator spotTess(path, ctm, scale, translate, radius, umbraColor, 971a84898dbb8d8f7cb8c3e9bdfb4c31d85dff1922fJim Van Verth penumbraColor, transparent); 972aff27a23ad4b38851429066dbfb43cfa7199e37cBrian Salomon return spotTess.releaseVertices(); 973958fbc460a1e680c6a9979e140da8bfc00b8831dBrian Salomon} 974