11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2008 The Android Open Source Project 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStrokerPriv.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGeometry.h" 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPath.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxQuadSubdivide 5 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxCubicSubdivide 4 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool degenerate_vector(const SkVector& v) { 181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return !SkPoint::CanNormalize(v.fX, v.fY); 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool normals_too_curvy(const SkVector& norm0, SkVector& norm1) { 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* root2/2 is a 45-degree angle 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project make this constant bigger for more subdivisions (but not >= 1) 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static const SkScalar kFlatEnoughNormalDotProd = 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SK_ScalarSqrt2/2 + SK_Scalar1/10; 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(kFlatEnoughNormalDotProd > 0 && 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kFlatEnoughNormalDotProd < SK_Scalar1); 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPoint::DotProduct(norm0, norm1) <= kFlatEnoughNormalDotProd; 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool normals_too_pinchy(const SkVector& norm0, SkVector& norm1) { 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static const SkScalar kTooPinchyNormalDotProd = -SK_Scalar1 * 999 / 1000; 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPoint::DotProduct(norm0, norm1) <= kTooPinchyNormalDotProd; 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool set_normal_unitnormal(const SkPoint& before, const SkPoint& after, 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar radius, 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* normal, SkVector* unitNormal) { 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!unitNormal->setNormalize(after.fX - before.fX, after.fY - before.fY)) { 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitNormal->rotateCCW(); 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitNormal->scale(radius, normal); 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool set_normal_unitnormal(const SkVector& vec, 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar radius, 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* normal, SkVector* unitNormal) { 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!unitNormal->setNormalize(vec.fX, vec.fY)) { 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitNormal->rotateCCW(); 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitNormal->scale(radius, normal); 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkPathStroker { 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPathStroker(SkScalar radius, SkScalar miterLimit, SkPaint::Cap cap, 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPaint::Join join); 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void moveTo(const SkPoint&); 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void lineTo(const SkPoint&); 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void quadTo(const SkPoint&, const SkPoint&); 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void cubicTo(const SkPoint&, const SkPoint&, const SkPoint&); 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void close(bool isLine) { this->finishContour(true, isLine); } 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void done(SkPath* dst, bool isLine) { 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->finishContour(false, isLine); 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.addPath(fExtra); 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->swap(fOuter); 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar fRadius; 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar fInvMiterLimit; 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector fFirstNormal, fPrevNormal, fFirstUnitNormal, fPrevUnitNormal; 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint fFirstPt, fPrevPt; // on original path 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint fFirstOuterPt; 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int fSegmentCount; 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool fPrevIsLine; 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkStrokerPriv::CapProc fCapper; 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkStrokerPriv::JoinProc fJoiner; 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath fInner, fOuter; // outer is our working answer, inner is temp 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath fExtra; // added as extra complete contours 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void finishContour(bool close, bool isLine); 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void preJoinTo(const SkPoint&, SkVector* normal, SkVector* unitNormal, 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool isLine); 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void postJoinTo(const SkPoint&, const SkVector& normal, 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkVector& unitNormal); 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void line_to(const SkPoint& currPt, const SkVector& normal); 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void quad_to(const SkPoint pts[3], 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkVector& normalAB, const SkVector& unitNormalAB, 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* normalBC, SkVector* unitNormalBC, 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int subDivide); 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void cubic_to(const SkPoint pts[4], 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkVector& normalAB, const SkVector& unitNormalAB, 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* normalCD, SkVector* unitNormalCD, 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int subDivide); 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::preJoinTo(const SkPoint& currPt, SkVector* normal, 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* unitNormal, bool currIsLine) { 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fSegmentCount >= 0); 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar prevX = fPrevPt.fX; 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar prevY = fPrevPt.fY; 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAssertResult(set_normal_unitnormal(fPrevPt, currPt, fRadius, normal, 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitNormal)); 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fSegmentCount == 0) { 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstNormal = *normal; 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstUnitNormal = *unitNormal; 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstOuterPt.set(prevX + normal->fX, prevY + normal->fY); 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.moveTo(fFirstOuterPt.fX, fFirstOuterPt.fY); 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.moveTo(prevX - normal->fX, prevY - normal->fY); 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { // we have a previous segment 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, *unitNormal, 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fRadius, fInvMiterLimit, fPrevIsLine, currIsLine); 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrevIsLine = currIsLine; 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::postJoinTo(const SkPoint& currPt, const SkVector& normal, 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkVector& unitNormal) { 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrevPt = currPt; 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrevUnitNormal = unitNormal; 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrevNormal = normal; 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegmentCount += 1; 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::finishContour(bool close, bool currIsLine) { 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fSegmentCount > 0) { 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pt; 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (close) { 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fJoiner(&fOuter, &fInner, fPrevUnitNormal, fPrevPt, 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstUnitNormal, fRadius, fInvMiterLimit, 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrevIsLine, currIsLine); 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.close(); 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now add fInner as its own contour 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.getLastPt(&pt); 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.moveTo(pt.fX, pt.fY); 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.reversePathTo(fInner); 1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.close(); 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { // add caps to start and end 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // cap the end 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.getLastPt(&pt); 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCapper(&fOuter, fPrevPt, fPrevNormal, pt, 1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project currIsLine ? &fInner : NULL); 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.reversePathTo(fInner); 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // cap the start 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCapper(&fOuter, fFirstPt, -fFirstNormal, fFirstOuterPt, 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrevIsLine ? &fInner : NULL); 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.close(); 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.reset(); 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegmentCount = -1; 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathStroker::SkPathStroker(SkScalar radius, SkScalar miterLimit, 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPaint::Cap cap, SkPaint::Join join) 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project : fRadius(radius) { 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* This is only used when join is miter_join, but we initialize it here 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project so that it is always defined, to fis valgrind warnings. 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInvMiterLimit = 0; 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (join == SkPaint::kMiter_Join) { 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (miterLimit <= SK_Scalar1) { 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project join = SkPaint::kBevel_Join; 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInvMiterLimit = SkScalarInvert(miterLimit); 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCapper = SkStrokerPriv::CapFactory(cap); 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fJoiner = SkStrokerPriv::JoinFactory(join); 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegmentCount = -1; 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPrevIsLine = false; 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::moveTo(const SkPoint& pt) { 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fSegmentCount > 0) { 2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->finishContour(false, false); 2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegmentCount = 0; 2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPt = fPrevPt = pt; 2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::line_to(const SkPoint& currPt, const SkVector& normal) { 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.lineTo(currPt.fX + normal.fX, currPt.fY + normal.fY); 2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.lineTo(currPt.fX - normal.fX, currPt.fY - normal.fY); 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::lineTo(const SkPoint& currPt) { 2161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (SkPath::IsLineDegenerate(fPrevPt, currPt)) { 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector normal, unitNormal; 2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->preJoinTo(currPt, &normal, &unitNormal, true); 2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->line_to(currPt, normal); 2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->postJoinTo(currPt, normal, unitNormal); 2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::quad_to(const SkPoint pts[3], 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkVector& normalAB, const SkVector& unitNormalAB, 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* normalBC, SkVector* unitNormalBC, 2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int subDivide) { 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!set_normal_unitnormal(pts[1], pts[2], fRadius, 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalBC, unitNormalBC)) { 2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // pts[1] nearly equals pts[2], so just draw a line to pts[2] 2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->line_to(pts[2], normalAB); 2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *normalBC = normalAB; 2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *unitNormalBC = unitNormalAB; 2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (--subDivide >= 0 && normals_too_curvy(unitNormalAB, *unitNormalBC)) { 2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[5]; 2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector norm, unit; 2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAtHalf(pts, tmp); 2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quad_to(&tmp[0], normalAB, unitNormalAB, &norm, &unit, subDivide); 2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quad_to(&tmp[2], norm, unit, normalBC, unitNormalBC, subDivide); 2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector normalB, unitB; 2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAssertResult(set_normal_unitnormal(pts[0], pts[2], fRadius, 2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project &normalB, &unitB)); 2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.quadTo( pts[1].fX + normalB.fX, pts[1].fY + normalB.fY, 2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2].fX + normalBC->fX, pts[2].fY + normalBC->fY); 2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.quadTo( pts[1].fX - normalB.fX, pts[1].fY - normalB.fY, 2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2].fX - normalBC->fX, pts[2].fY - normalBC->fY); 2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::cubic_to(const SkPoint pts[4], 2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkVector& normalAB, const SkVector& unitNormalAB, 2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* normalCD, SkVector* unitNormalCD, 2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int subDivide) { 2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector ab = pts[1] - pts[0]; 2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector cd = pts[3] - pts[2]; 2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector normalBC, unitNormalBC; 2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool degenerateAB = degenerate_vector(ab); 2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool degenerateCD = degenerate_vector(cd); 2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateAB && degenerateCD) { 2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectDRAW_LINE: 2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->line_to(pts[3], normalAB); 2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *normalCD = normalAB; 2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *unitNormalCD = unitNormalAB; 2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateAB) { 2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ab = pts[2] - pts[0]; 2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project degenerateAB = degenerate_vector(ab); 2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateCD) { 2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project cd = pts[3] - pts[1]; 2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project degenerateCD = degenerate_vector(cd); 2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateAB || degenerateCD) { 2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project goto DRAW_LINE; 2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAssertResult(set_normal_unitnormal(cd, fRadius, normalCD, unitNormalCD)); 2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool degenerateBC = !set_normal_unitnormal(pts[1], pts[2], fRadius, 2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project &normalBC, &unitNormalBC); 2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2929f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed if (degenerateBC || normals_too_curvy(unitNormalAB, unitNormalBC) || 2939f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed normals_too_curvy(unitNormalBC, *unitNormalCD)) { 2949f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed // subdivide if we can 2959f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed if (--subDivide < 0) { 2969f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed goto DRAW_LINE; 2979f0b433bdd1680cd1d371c19d7e0ffde8fb2c484Mike Reed } 2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[7]; 2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector norm, unit, dummy, unitDummy; 3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAtHalf(pts, tmp); 3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubic_to(&tmp[0], normalAB, unitNormalAB, &norm, &unit, 3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subDivide); 3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // we use dummys since we already have a valid (and more accurate) 3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // normals for CD 3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubic_to(&tmp[3], norm, unit, &dummy, &unitDummy, subDivide); 3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector normalB, normalC; 3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need normals to inset/outset the off-curve pts B and C 3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (0) { // this is normal to the line between our adjacent pts 3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalB = pts[2] - pts[0]; 3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalB.rotateCCW(); 3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAssertResult(normalB.setLength(fRadius)); 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalC = pts[3] - pts[1]; 3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalC.rotateCCW(); 3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAssertResult(normalC.setLength(fRadius)); 3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { // miter-join 3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector unitBC = pts[2] - pts[1]; 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitBC.normalize(); 3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitBC.rotateCCW(); 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalB = unitNormalAB + unitBC; 3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalC = *unitNormalCD + unitBC; 3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dot = SkPoint::DotProduct(unitNormalAB, unitBC); 3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAssertResult(normalB.setLength(SkScalarDiv(fRadius, 3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarSqrt((SK_Scalar1 + dot)/2)))); 3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dot = SkPoint::DotProduct(*unitNormalCD, unitBC); 3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAssertResult(normalC.setLength(SkScalarDiv(fRadius, 3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarSqrt((SK_Scalar1 + dot)/2)))); 3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.cubicTo( pts[1].fX + normalB.fX, pts[1].fY + normalB.fY, 3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2].fX + normalC.fX, pts[2].fY + normalC.fY, 3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[3].fX + normalCD->fX, pts[3].fY + normalCD->fY); 3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.cubicTo( pts[1].fX - normalB.fX, pts[1].fY - normalB.fY, 3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2].fX - normalC.fX, pts[2].fY - normalC.fY, 3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[3].fX - normalCD->fX, pts[3].fY - normalCD->fY); 3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::quadTo(const SkPoint& pt1, const SkPoint& pt2) { 3471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool degenerateAB = SkPath::IsLineDegenerate(fPrevPt, pt1); 3481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool degenerateBC = SkPath::IsLineDegenerate(pt1, pt2); 3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateAB | degenerateBC) { 3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateAB ^ degenerateBC) { 3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(pt2); 3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector normalAB, unitAB, normalBC, unitBC; 3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->preJoinTo(pt1, &normalAB, &unitAB, false); 3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[3], tmp[5]; 3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[0] = fPrevPt; 3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1] = pt1; 3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2] = pt2; 3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkChopQuadAtMaxCurvature(pts, tmp) == 2) { 3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitBC.setNormalize(pts[2].fX - pts[1].fX, pts[2].fY - pts[1].fY); 3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unitBC.rotateCCW(); 3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (normals_too_pinchy(unitAB, unitBC)) { 3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalBC = unitBC; 3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project normalBC.scale(fRadius); 3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.lineTo(tmp[2].fX + normalAB.fX, tmp[2].fY + normalAB.fY); 3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.lineTo(tmp[2].fX + normalBC.fX, tmp[2].fY + normalBC.fY); 3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fOuter.lineTo(tmp[4].fX + normalBC.fX, tmp[4].fY + normalBC.fY); 3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.lineTo(tmp[2].fX - normalAB.fX, tmp[2].fY - normalAB.fY); 3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.lineTo(tmp[2].fX - normalBC.fX, tmp[2].fY - normalBC.fY); 3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fInner.lineTo(tmp[4].fX - normalBC.fX, tmp[4].fY - normalBC.fY); 3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fExtra.addCircle(tmp[2].fX, tmp[2].fY, fRadius, 3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::kCW_Direction); 3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quad_to(&tmp[0], normalAB, unitAB, &normalBC, &unitBC, 3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxQuadSubdivide); 3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector n = normalBC; 3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector u = unitBC; 3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quad_to(&tmp[2], n, u, &normalBC, &unitBC, 3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxQuadSubdivide); 3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quad_to(pts, normalAB, unitAB, &normalBC, &unitBC, 3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxQuadSubdivide); 3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->postJoinTo(pt2, normalBC, unitBC); 3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathStroker::cubicTo(const SkPoint& pt1, const SkPoint& pt2, 4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint& pt3) { 4031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool degenerateAB = SkPath::IsLineDegenerate(fPrevPt, pt1); 4041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool degenerateBC = SkPath::IsLineDegenerate(pt1, pt2); 4051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool degenerateCD = SkPath::IsLineDegenerate(pt2, pt3); 4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateAB + degenerateBC + degenerateCD >= 2) { 4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(pt3); 4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector normalAB, unitAB, normalCD, unitCD; 4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // find the first tangent (which might be pt1 or pt2 4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* nextPt = &pt1; 4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (degenerateAB) 4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project nextPt = &pt2; 4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->preJoinTo(*nextPt, &normalAB, &unitAB, false); 4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4], tmp[13]; 4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int i, count; 4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector n, u; 4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar tValues[3]; 4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[0] = fPrevPt; 4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1] = pt1; 4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2] = pt2; 4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[3] = pt3; 4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 1 4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project count = SkChopCubicAtMaxCurvature(pts, tmp, tValues); 4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project count = 1; 4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(tmp, pts, 4 * sizeof(SkPoint)); 4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project n = normalAB; 4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project u = unitAB; 4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (i = 0; i < count; i++) { 4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubic_to(&tmp[i * 3], n, u, &normalCD, &unitCD, 4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxCubicSubdivide); 4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (i == count - 1) { 4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project n = normalCD; 4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project u = unitCD; 4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // check for too pinchy 4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (i = 1; i < count; i++) { 4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint p; 4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector v, c; 4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkEvalCubicAt(pts, tValues[i - 1], &p, &v, &c); 4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dot = SkPoint::DotProduct(c, c); 4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project v.scale(SkScalarInvert(dot)); 4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkScalarNearlyZero(v.fX) && SkScalarNearlyZero(v.fY)) { 4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fExtra.addCircle(p.fX, p.fY, fRadius, SkPath::kCW_Direction); 4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->postJoinTo(pt3, normalCD, unitCD); 4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkPaintDefaults.h" 4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkStroke::SkStroke() { 4784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fWidth = SK_Scalar1; 4794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fMiterLimit = SkPaintDefaults_MiterLimit; 4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCap = SkPaint::kDefault_Cap; 4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fJoin = SkPaint::kDefault_Join; 4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fDoFill = false; 4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkStroke::SkStroke(const SkPaint& p) { 4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fWidth = p.getStrokeWidth(); 4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMiterLimit = p.getStrokeMiter(); 4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCap = (uint8_t)p.getStrokeCap(); 4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fJoin = (uint8_t)p.getStrokeJoin(); 4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); 4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkStroke::SkStroke(const SkPaint& p, SkScalar width) { 4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fWidth = width; 4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMiterLimit = p.getStrokeMiter(); 4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCap = (uint8_t)p.getStrokeCap(); 4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fJoin = (uint8_t)p.getStrokeJoin(); 4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fDoFill = SkToU8(p.getStyle() == SkPaint::kStrokeAndFill_Style); 4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkStroke::setWidth(SkScalar width) { 5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(width >= 0); 5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fWidth = width; 5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkStroke::setMiterLimit(SkScalar miterLimit) { 5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(miterLimit >= 0); 5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMiterLimit = miterLimit; 5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkStroke::setCap(SkPaint::Cap cap) { 5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)cap < SkPaint::kCapCount); 5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCap = SkToU8(cap); 5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkStroke::setJoin(SkPaint::Join join) { 5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)join < SkPaint::kJoinCount); 5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fJoin = SkToU8(join); 5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FIXED 5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* return non-zero if the path is too big, and should be shrunk to avoid 5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project overflows during intermediate calculations. Note that we compute the 5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds for this. If we had a custom callback/walker for paths, we could 5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project perhaps go faster by using that, and just perform the abs | in that 5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project routine 5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static int needs_to_shrink(const SkPath& path) { 5310e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed const SkRect& r = path.getBounds(); 5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed mask = SkAbs32(r.fLeft); 5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask |= SkAbs32(r.fTop); 5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask |= SkAbs32(r.fRight); 5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask |= SkAbs32(r.fBottom); 5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // we need the top 3 bits clear (after abs) to avoid overflow 5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return mask >> 29; 5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static void identity_proc(SkPoint pts[], int count) {} 5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static void shift_down_2_proc(SkPoint pts[], int count) { 5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts->fX >>= 2; 5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts->fY >>= 2; 5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts += 1; 5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define APPLY_PROC(proc, pts, count) proc(pts, count) 5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else // float does need any of this 5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project #define APPLY_PROC(proc, pts, count) 5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkStroke::strokePath(const SkPath& src, SkPath* dst) const { 5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&src != NULL && dst != NULL); 5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar radius = SkScalarHalf(fWidth); 5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->reset(); 5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (radius <= 0) { 5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FIXED 5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project void (*proc)(SkPoint pts[], int count) = identity_proc; 5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (needs_to_shrink(src)) { 5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc = shift_down_2_proc; 5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project radius >>= 2; 5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (radius == 0) { 5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPathStroker stroker(radius, fMiterLimit, this->getCap(), 5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getJoin()); 5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Iter iter(src, false); 5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4]; 5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Verb verb, lastSegment = SkPath::kMove_Verb; 5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verb) { 5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kMove_Verb: 5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project APPLY_PROC(proc, &pts[0], 1); 5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stroker.moveTo(pts[0]); 5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kLine_Verb: 5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project APPLY_PROC(proc, &pts[1], 1); 5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stroker.lineTo(pts[1]); 5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project lastSegment = verb; 5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kQuad_Verb: 5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project APPLY_PROC(proc, &pts[1], 2); 5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stroker.quadTo(pts[1], pts[2]); 5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project lastSegment = verb; 5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kCubic_Verb: 5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project APPLY_PROC(proc, &pts[1], 3); 5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stroker.cubicTo(pts[1], pts[2], pts[3]); 6000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project lastSegment = verb; 6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kClose_Verb: 6030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stroker.close(lastSegment == SkPath::kLine_Verb); 6040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 6060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stroker.done(dst, lastSegment == SkPath::kLine_Verb); 6100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FIXED 6120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // undo our previous down_shift 6130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (shift_down_2_proc == proc) { 6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need a real shift methid on path. antialias paths could use this too 6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setScale(SkIntToScalar(4), SkIntToScalar(4)); 6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->transform(matrix); 6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fDoFill) { 6221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (src.cheapIsDirection(SkPath::kCCW_Direction)) { 6231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->reverseAddPath(src); 6241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 6251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->addPath(src); 6261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 62740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 6281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Seems like we can assume that a 2-point src would always result in 6291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // a convex stroke, but testing has proved otherwise. 6301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // TODO: fix the stroker to make this assumption true (without making 6311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // it slower that the work that will be done in computeConvexity()) 6321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if 0 6331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // this test results in a non-convex stroke :( 6341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger static void test(SkCanvas* canvas) { 6351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPoint pts[] = { 146.333328, 192.333328, 300.333344, 293.333344 }; 6361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPaint paint; 6371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger paint.setStrokeWidth(7); 6381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger paint.setStrokeCap(SkPaint::kRound_Cap); 6391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger canvas->drawLine(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, paint); 6401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 6411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif 6421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if 0 6431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (2 == src.countPoints()) { 64440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger dst->setIsConvex(true); 64540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 6461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif 6471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 6481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 6491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // our answer should preserve the inverseness of the src 6501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (src.isInverseFillType()) { 6511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(!dst->isInverseFillType()); 6521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->toggleInverseFillType(); 6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkStroke::strokeLine(const SkPoint& p0, const SkPoint& p1, 6570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath* dst) const { 6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath tmp; 6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.moveTo(p0); 6610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.lineTo(p1); 6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->strokePath(tmp, dst); 6630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 665