11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPath.h" 1135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkReader32.h" 1235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkWriter32.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMath.h" 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////// 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/** 181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Path.bounds is defined to be the bounds of all the control points. 191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * If we called bounds.join(r) we would skip r if r was empty, which breaks 201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * our promise. Hence we have a custom joiner that doesn't look at emptiness 211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void joinNoEmptyChecks(SkRect* dst, const SkRect& src) { 231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->fLeft = SkMinScalar(dst->fLeft, src.fLeft); 241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->fTop = SkMinScalar(dst->fTop, src.fTop); 251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->fRight = SkMaxScalar(dst->fRight, src.fRight); 261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->fBottom = SkMaxScalar(dst->fBottom, src.fBottom); 271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic bool is_degenerate(const SkPath& path) { 304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPath::Iter iter(path, false); 314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkPoint pts[4]; 324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return SkPath::kDone_Verb == iter.next(pts); 334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* This guy's constructor/destructor bracket a path editing operation. It is 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project used when we know the bounds of the amount we are going to add to the path 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (usually a new contour, but not required). 3840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project It captures some state about the path up front (i.e. if it already has a 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project cached bounds), and the if it can, it updates the cache bounds explicitly, 410e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed avoiding the need to revisit all of the points in getBounds(). 4240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger It also notes if the path was originally degenerate, and if so, sets 444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger isConvex to true. Thus it can only be used if the contour being added is 454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger convex. 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkAutoPathBoundsUpdate { 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoPathBoundsUpdate(SkPath* path, const SkRect& r) : fRect(r) { 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->init(path); 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoPathBoundsUpdate(SkPath* path, SkScalar left, SkScalar top, 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar right, SkScalar bottom) { 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fRect.set(left, top, right, bottom); 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->init(path); 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ~SkAutoPathBoundsUpdate() { 604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fPath->setIsConvex(fDegenerate); 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fEmpty) { 620e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fPath->fBounds = fRect; 630e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fPath->fBoundsIsDirty = false; 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else if (!fDirty) { 651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger joinNoEmptyChecks(&fPath->fBounds, fRect); 660e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fPath->fBoundsIsDirty = false; 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 7179377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed SkPath* fPath; 7279377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed SkRect fRect; 7379377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed bool fDirty; 744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger bool fDegenerate; 7579377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed bool fEmpty; 7640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // returns true if we should proceed 7879377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed void init(SkPath* path) { 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPath = path; 802c497e64d20a73267eb92ae88fdc51ba2a356b55Mike Reed fDirty = SkToBool(path->fBoundsIsDirty); 814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fDegenerate = is_degenerate(*path); 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fEmpty = path->isEmpty(); 83aa4832adcc7eba085987357591bcfeb530ba7b0dMike Reed // Cannot use fRect for our bounds unless we know it is sorted 84aa4832adcc7eba085987357591bcfeb530ba7b0dMike Reed fRect.sort(); 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 880e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reedstatic void compute_pt_bounds(SkRect* bounds, const SkTDArray<SkPoint>& pts) { 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts.count() <= 1) { // we ignore just 1 point (moveto) 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds->set(0, 0, 0, 0); 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds->set(pts.begin(), pts.count()); 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// SkDebugf("------- compute bounds %p %d", &pts, pts.count()); 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////// 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Stores the verbs and points as they are given to us, with exceptions: 1011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger - we only record "Close" if it was immediately preceeded by Move | Line | Quad | Cubic 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project - we insert a Move(0,0) if Line | Quad | Cubic is our first command 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project The iterator does more cleanup, especially if forceClose == true 1051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1. If we encounter degenerate segments, remove them 1061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2. if we encounter Close, return a cons'd up Line() first (if the curr-pt != start-pt) 1071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 3. if we encounter Move without a preceeding Close, and forceClose is true, goto #2 1081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 4. if we encounter Line | Quad | Cubic after Close, cons up a Move 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////// 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger// flag to require a moveTo if we begin with something else, like lineTo etc. 1144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define INITIAL_LASTMOVETOINDEX_VALUE ~0 1154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1161cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPath::SkPath() 1171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger : fFillType(kWinding_FillType) 1181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger , fBoundsIsDirty(true) { 11935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fConvexity = kUnknown_Convexity; 1201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask = 0; 1214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; 1221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 123fad89e5c108c0cf674a206cd133da011465ccd09Romain Guy fGenerationID = 0; 1244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fSourcePath = NULL; 12587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif 12679377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed} 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPath::SkPath(const SkPath& src) { 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(src.validate();) 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *this = src; 1311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 13287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger // the assignment operator above increments the ID so correct for that here 1334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fGenerationID = src.fGenerationID; 1344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fSourcePath = NULL; 13587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPath::~SkPath() { 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPath& SkPath::operator=(const SkPath& src) { 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(src.validate();) 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this != &src) { 1460e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fBounds = src.fBounds; 1470e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fPts = src.fPts; 1480e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fVerbs = src.fVerbs; 1490e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fFillType = src.fFillType; 1500e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fBoundsIsDirty = src.fBoundsIsDirty; 15135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fConvexity = src.fConvexity; 1521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask = src.fSegmentMask; 1534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fLastMoveToIndex = src.fLastMoveToIndex; 15487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return *this; 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1603298d565d8a70b84f28b455f6289293883c85494The Android Open Source Projectbool operator==(const SkPath& a, const SkPath& b) { 16179377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed // note: don't need to look at isConvex or bounds, since just comparing the 16279377cbceeea970b663e7934d7cb1f27bb223d98Mike Reed // raw data is sufficient. 1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // We explicitly check fSegmentMask as a quick-reject. We could skip it, 1651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // since it is only a cache of info in the fVerbs, but its a fast way to 1661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // notice a difference 1671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1683298d565d8a70b84f28b455f6289293883c85494The Android Open Source Project return &a == &b || 1691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger (a.fFillType == b.fFillType && a.fSegmentMask == b.fSegmentMask && 1701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger a.fVerbs == b.fVerbs && a.fPts == b.fPts); 1713298d565d8a70b84f28b455f6289293883c85494The Android Open Source Project} 1723298d565d8a70b84f28b455f6289293883c85494The Android Open Source Project 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::swap(SkPath& other) { 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(&other != NULL); 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this != &other) { 1770e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed SkTSwap<SkRect>(fBounds, other.fBounds); 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts.swap(other.fPts); 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs.swap(other.fVerbs); 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTSwap<uint8_t>(fFillType, other.fFillType); 1810e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed SkTSwap<uint8_t>(fBoundsIsDirty, other.fBoundsIsDirty); 18235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkTSwap<uint8_t>(fConvexity, other.fConvexity); 1831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkTSwap<uint8_t>(fSegmentMask, other.fSegmentMask); 1844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkTSwap<int>(fLastMoveToIndex, other.fLastMoveToIndex); 18587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 190fad89e5c108c0cf674a206cd133da011465ccd09Romain Guyuint32_t SkPath::getGenerationID() const { 191fad89e5c108c0cf674a206cd133da011465ccd09Romain Guy return fGenerationID; 192fad89e5c108c0cf674a206cd133da011465ccd09Romain Guy} 1934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerconst SkPath* SkPath::getSourcePath() const { 1954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return fSourcePath; 1964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 1974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 1984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkPath::setSourcePath(const SkPath* path) { 1994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fSourcePath = path; 2004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 20187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif 202fad89e5c108c0cf674a206cd133da011465ccd09Romain Guy 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::reset() { 2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts.reset(); 2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs.reset(); 20887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 2090e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fBoundsIsDirty = true; 21035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fConvexity = kUnknown_Convexity; 2111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask = 0; 2124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::rewind() { 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts.rewind(); 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs.rewind(); 22087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 22135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fConvexity = kUnknown_Convexity; 2221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fBoundsIsDirty = true; 2231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask = 0; 2244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fLastMoveToIndex = INITIAL_LASTMOVETOINDEX_VALUE; 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPath::isEmpty() const { 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 2291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return 0 == fVerbs.count(); 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 2331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger Determines if path is a rect by keeping track of changes in direction 2341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger and looking for a loop either clockwise or counterclockwise. 2351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger The direction is computed such that: 2371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 0: vertical up 2381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 1: horizontal right 2391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2: vertical down 2401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 3: horizontal left 2411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2421cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerA rectangle cycles up/right/down/left or up/left/down/right. 2431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2441cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerThe test fails if: 2451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger The path is closed, and followed by a line. 2461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger A second move creates a new endpoint. 2471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger A diagonal line is parsed. 2481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger There's more than four changes of direction. 2491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger There's a discontinuity on the line (e.g., a move in the middle) 2501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger The line reverses direction. 2511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger The rectangle doesn't complete a cycle. 2521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger The path contains a quadratic or cubic. 2531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger The path contains fewer than four points. 2541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger The final point isn't equal to the first point. 2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2561cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerIt's OK if the path has: 2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger Several colinear line segments composing a rectangle side. 2581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger Single points on the rectangle side. 2591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2601cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerThe direction takes advantage of the corners found since opposite sides 2611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergermust travel in opposite directions. 2621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2631cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerFIXME: Allow colinear quads and cubics to be treated like lines. 2641cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerFIXME: If the API passes fill-only, return true if the filled stroke 2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger is a rectangle, though the caller failed to close the path. 2661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 2671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkPath::isRect(SkRect* rect) const { 2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 26940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int corners = 0; 2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPoint first, last; 2721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger first.set(0, 0); 2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger last.set(0, 0); 2741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int firstDirection = 0; 2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int lastDirection = 0; 2761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int nextDirection = 0; 2771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool closedOrMoved = false; 2781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool autoClose = false; 2791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* verbs = fVerbs.begin(); 2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* verbStop = fVerbs.end(); 2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* pts = fPts.begin(); 2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger while (verbs != verbStop) { 2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger switch (*verbs++) { 2841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kClose_Verb: 2851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts = fPts.begin(); 2861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger autoClose = true; 2871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kLine_Verb: { 2881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScalar left = last.fX; 2891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScalar top = last.fY; 2901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScalar right = pts->fX; 2911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScalar bottom = pts->fY; 2921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ++pts; 2931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (left != right && top != bottom) { 2941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; // diagonal 2951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 2961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (left == right && top == bottom) { 2971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; // single point on side OK 2981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 2991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger nextDirection = (left != right) << 0 | 3001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger (left < right || top < bottom) << 1; 3011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (0 == corners) { 3021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger firstDirection = nextDirection; 3031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger first = last; 3041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger last = pts[-1]; 3051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger corners = 1; 3061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger closedOrMoved = false; 3071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 3081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (closedOrMoved) { 3101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; // closed followed by a line 3111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger closedOrMoved = autoClose; 3131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (lastDirection != nextDirection) { 3141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (++corners > 4) { 3151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; // too many direction changes 3161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger last = pts[-1]; 3191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (lastDirection == nextDirection) { 3201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; // colinear segment 3211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Possible values for corners are 2, 3, and 4. 3231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // When corners == 3, nextDirection opposes firstDirection. 3241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Otherwise, nextDirection at corner 2 opposes corner 4. 3251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int turn = firstDirection ^ (corners - 1); 3261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int directionCycle = 3 == corners ? 0 : nextDirection ^ turn; 3271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if ((directionCycle ^ turn) != nextDirection) { 3281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; // direction didn't follow cycle 3291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 3311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kQuad_Verb: 3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kCubic_Verb: 3341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; // quadratic, cubic not allowed 3351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kMove_Verb: 3361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger last = *pts++; 3371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger closedOrMoved = true; 3381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 3391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger lastDirection = nextDirection; 3411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Success if 4 corners and first point equals last 3431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool result = 4 == corners && first == last; 3441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (result && rect) { 3451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *rect = getBounds(); 3461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return result; 3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectint SkPath::getPoints(SkPoint copy[], int max) const { 3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(max >= 0); 3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = fPts.count(); 3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (copy && max > 0 && count > 0) { 3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(copy, fPts.begin(), sizeof(SkPoint) * SkMin32(max, count)); 3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return count; 3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3611c980e0d7772f05f570ae0227d91635f017c2227Mike ReedSkPoint SkPath::getPoint(int index) const { 3621c980e0d7772f05f570ae0227d91635f017c2227Mike Reed if ((unsigned)index < (unsigned)fPts.count()) { 3631c980e0d7772f05f570ae0227d91635f017c2227Mike Reed return fPts[index]; 3641c980e0d7772f05f570ae0227d91635f017c2227Mike Reed } 3651c980e0d7772f05f570ae0227d91635f017c2227Mike Reed return SkPoint::Make(0, 0); 3661c980e0d7772f05f570ae0227d91635f017c2227Mike Reed} 3671c980e0d7772f05f570ae0227d91635f017c2227Mike Reed 3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkPath::getLastPt(SkPoint* lastPt) const { 3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int count = fPts.count(); 3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (count > 0) { 3731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (lastPt) { 3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *lastPt = fPts[count - 1]; 3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return true; 3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 3781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (lastPt) { 3791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger lastPt->set(0, 0); 3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; 3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::setLastPt(SkScalar x, SkScalar y) { 3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = fPts.count(); 3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (count == 0) { 3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(x, y); 3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts[count - 1].set(x, y); 39287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3960e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reedvoid SkPath::computeBounds() const { 3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 3980e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed SkASSERT(fBoundsIsDirty); 3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4000e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed fBoundsIsDirty = false; 4010e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed compute_pt_bounds(&fBounds, fPts); 4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 40435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkPath::setConvexity(Convexity c) { 40535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (fConvexity != c) { 40635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fConvexity = c; 40735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger GEN_ID_INC; 40835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 40935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger} 41035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project////////////////////////////////////////////////////////////////////////////// 4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// Construction methods 4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#define DIRTY_AFTER_EDIT \ 4151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger do { \ 4161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fBoundsIsDirty = true; \ 4171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fConvexity = kUnknown_Convexity; \ 4180b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger } while (0) 4190b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger 4204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#define DIRTY_AFTER_EDIT_NO_CONVEXITY_CHANGE \ 4214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger do { \ 4224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fBoundsIsDirty = true; \ 4234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } while (0) 4244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::incReserve(U16CPU inc) { 4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs.setReserve(fVerbs.count() + inc); 4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts.setReserve(fPts.count() + inc); 4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::moveTo(SkScalar x, SkScalar y) { 4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int vc = fVerbs.count(); 4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint* pt; 4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // remember our index 4414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fLastMoveToIndex = fPts.count(); 4424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 4431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pt = fPts.append(); 4441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *fVerbs.append() = kMove_Verb; 4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pt->set(x, y); 4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 44787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 4484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger DIRTY_AFTER_EDIT_NO_CONVEXITY_CHANGE; 4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::rMoveTo(SkScalar x, SkScalar y) { 4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pt; 4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getLastPt(&pt); 4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(pt.fX + x, pt.fY + y); 4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergervoid SkPath::injectMoveToIfNeeded() { 4584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (fLastMoveToIndex < 0) { 4594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar x, y; 4604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (fVerbs.count() == 0) { 4614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger x = y = 0; 4624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } else { 4634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkPoint& pt = fPts[~fLastMoveToIndex]; 4644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger x = pt.fX; 4654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger y = pt.fY; 4664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 4674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger this->moveTo(x, y); 4684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 4694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 4704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::lineTo(SkScalar x, SkScalar y) { 4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger this->injectMoveToIfNeeded(); 4754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts.append()->set(x, y); 4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *fVerbs.append() = kLine_Verb; 4781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask |= kLine_SegmentMask; 4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 48087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 4810b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger DIRTY_AFTER_EDIT; 4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::rLineTo(SkScalar x, SkScalar y) { 4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pt; 4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getLastPt(&pt); 4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(pt.fX + x, pt.fY + y); 4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::quadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { 4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger this->injectMoveToIfNeeded(); 4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint* pts = fPts.append(2); 4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[0].set(x1, y1); 4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1].set(x2, y2); 4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *fVerbs.append() = kQuad_Verb; 4991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask |= kQuad_SegmentMask; 5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 50187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 5020b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger DIRTY_AFTER_EDIT; 5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::rQuadTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) { 5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pt; 5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getLastPt(&pt); 5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2); 5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::cubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar x3, SkScalar y3) { 5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger this->injectMoveToIfNeeded(); 5164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint* pts = fPts.append(3); 5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[0].set(x1, y1); 5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1].set(x2, y2); 5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2].set(x3, y3); 5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *fVerbs.append() = kCubic_Verb; 5221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask |= kCubic_SegmentMask; 5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 52487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 5250b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger DIRTY_AFTER_EDIT; 5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::rCubicTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar x3, SkScalar y3) { 5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pt; 5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getLastPt(&pt); 5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(pt.fX + x1, pt.fY + y1, pt.fX + x2, pt.fY + y2, 5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pt.fX + x3, pt.fY + y3); 5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::close() { 5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = fVerbs.count(); 5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (count > 0) { 5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (fVerbs[count - 1]) { 5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_Verb: 5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_Verb: 5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_Verb: 5451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kMove_Verb: 5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *fVerbs.append() = kClose_Verb; 54787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 5501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // don't add a close if it's the first verb or a repeat 5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 5554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // signal that we need a moveTo to follow us (unless we're done) 5564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if 0 5574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (fLastMoveToIndex >= 0) { 5584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fLastMoveToIndex = ~fLastMoveToIndex; 5594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 5604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else 5614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fLastMoveToIndex ^= ~fLastMoveToIndex >> (8 * sizeof(fLastMoveToIndex) - 1); 5624f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 56640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addRect(const SkRect& rect, Direction dir) { 5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->addRect(rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, dir); 5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addRect(SkScalar left, SkScalar top, SkScalar right, 5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar bottom, Direction dir) { 5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoPathBoundsUpdate apbu(this, left, top, right, bottom); 5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(5); 5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(left, top); 5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dir == kCCW_Direction) { 5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(left, bottom); 5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(right, bottom); 5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(right, top); 5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(right, top); 5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(right, bottom); 5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(left, bottom); 5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->close(); 5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define CUBIC_ARC_FACTOR ((SK_ScalarSqrt2 - SK_Scalar1) * 4 / 3) 5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addRoundRect(const SkRect& rect, SkScalar rx, SkScalar ry, 5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Direction dir) { 5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar w = rect.width(); 5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar halfW = SkScalarHalf(w); 5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar h = rect.height(); 5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar halfH = SkScalarHalf(h); 5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (halfW <= 0 || halfH <= 0) { 6000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 60340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool skip_hori = rx >= halfW; 60440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool skip_vert = ry >= halfH; 6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (skip_hori && skip_vert) { 6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->addOval(rect, dir); 6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 61040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 61140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkAutoPathBoundsUpdate apbu(this, rect); 61240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (skip_hori) { 6140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rx = halfW; 6150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else if (skip_vert) { 6160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ry = halfH; 6170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sx = SkScalarMul(rx, CUBIC_ARC_FACTOR); 6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sy = SkScalarMul(ry, CUBIC_ARC_FACTOR); 6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(17); 6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(rect.fRight - rx, rect.fTop); 6240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dir == kCCW_Direction) { 6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_hori) { 6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fLeft + rx, rect.fTop); // top 6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fLeft + rx - sx, rect.fTop, 6290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft, rect.fTop + ry - sy, 6300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft, rect.fTop + ry); // top-left 6310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_vert) { 6320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fLeft, rect.fBottom - ry); // left 6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fLeft, rect.fBottom - ry + sy, 6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft + rx - sx, rect.fBottom, 6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft + rx, rect.fBottom); // bot-left 6370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_hori) { 6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fRight - rx, rect.fBottom); // bottom 6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fRight - rx + sx, rect.fBottom, 6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight, rect.fBottom - ry + sy, 6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight, rect.fBottom - ry); // bot-right 6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_vert) { 6440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fRight, rect.fTop + ry); 6450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fRight, rect.fTop + ry - sy, 6470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight - rx + sx, rect.fTop, 6480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight - rx, rect.fTop); // top-right 6490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 6500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fRight - rx + sx, rect.fTop, 6510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight, rect.fTop + ry - sy, 6520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight, rect.fTop + ry); // top-right 6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_vert) { 6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fRight, rect.fBottom - ry); 6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fRight, rect.fBottom - ry + sy, 6570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight - rx + sx, rect.fBottom, 6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fRight - rx, rect.fBottom); // bot-right 6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_hori) { 6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fLeft + rx, rect.fBottom); // bottom 6610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fLeft + rx - sx, rect.fBottom, 6630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft, rect.fBottom - ry + sy, 6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft, rect.fBottom - ry); // bot-left 6650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_vert) { 6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fLeft, rect.fTop + ry); // left 6670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(rect.fLeft, rect.fTop + ry - sy, 6690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft + rx - sx, rect.fTop, 6700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.fLeft + rx, rect.fTop); // top-left 6710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!skip_hori) { 6720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(rect.fRight - rx, rect.fTop); // top 6730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->close(); 6760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void add_corner_arc(SkPath* path, const SkRect& rect, 6790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar rx, SkScalar ry, int startAngle, 6800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Direction dir, bool forceMoveTo) { 6810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rx = SkMinScalar(SkScalarHalf(rect.width()), rx); 6820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ry = SkMinScalar(SkScalarHalf(rect.height()), ry); 68340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect r; 6850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.set(-rx, -ry, rx, ry); 6860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (startAngle) { 6880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case 0: 6890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.offset(rect.fRight - r.fRight, rect.fBottom - r.fBottom); 6900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 6910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case 90: 6920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.offset(rect.fLeft - r.fLeft, rect.fBottom - r.fBottom); 6930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 6940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case 180: r.offset(rect.fLeft - r.fLeft, rect.fTop - r.fTop); break; 6950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case 270: r.offset(rect.fRight - r.fRight, rect.fTop - r.fTop); break; 6961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger default: SkDEBUGFAIL("unexpected startAngle in add_corner_arc"); 6970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 69840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar start = SkIntToScalar(startAngle); 7000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sweep = SkIntToScalar(90); 7010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkPath::kCCW_Direction == dir) { 7020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project start += sweep; 7030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sweep = -sweep; 7040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 70540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 7060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path->arcTo(r, start, sweep, forceMoveTo); 7070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 7080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addRoundRect(const SkRect& rect, const SkScalar rad[], 7100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Direction dir) { 71140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // abort before we invoke SkAutoPathBoundsUpdate() 71240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (rect.isEmpty()) { 71340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return; 71440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 71540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoPathBoundsUpdate apbu(this, rect); 7170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (kCW_Direction == dir) { 7190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[0], rad[1], 180, dir, true); 7200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[2], rad[3], 270, dir, false); 7210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[4], rad[5], 0, dir, false); 7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[6], rad[7], 90, dir, false); 7230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 7240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[0], rad[1], 180, dir, true); 7250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[6], rad[7], 90, dir, false); 7260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[4], rad[5], 0, dir, false); 7270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project add_corner_arc(this, rect, rad[2], rad[3], 270, dir, false); 7280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->close(); 7300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 7310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addOval(const SkRect& oval, Direction dir) { 7330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoPathBoundsUpdate apbu(this, oval); 7340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar cx = oval.centerX(); 7360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar cy = oval.centerY(); 7370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar rx = SkScalarHalf(oval.width()); 7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar ry = SkScalarHalf(oval.height()); 7390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0 // these seem faster than using quads (1/2 the number of edges) 7400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sx = SkScalarMul(rx, CUBIC_ARC_FACTOR); 7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sy = SkScalarMul(ry, CUBIC_ARC_FACTOR); 7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(13); 7440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(cx + rx, cy); 7450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dir == kCCW_Direction) { 7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx + rx, cy - sy, cx + sx, cy - ry, cx, cy - ry); 7470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx - sx, cy - ry, cx - rx, cy - sy, cx - rx, cy); 7480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx - rx, cy + sy, cx - sx, cy + ry, cx, cy + ry); 7490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx + sx, cy + ry, cx + rx, cy + sy, cx + rx, cy); 7500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx + rx, cy + sy, cx + sx, cy + ry, cx, cy + ry); 7520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx - sx, cy + ry, cx - rx, cy + sy, cx - rx, cy); 7530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx - rx, cy - sy, cx - sx, cy - ry, cx, cy - ry); 7540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(cx + sx, cy - ry, cx + rx, cy - sy, cx + rx, cy); 7550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 7570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sx = SkScalarMul(rx, SK_ScalarTanPIOver8); 7580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sy = SkScalarMul(ry, SK_ScalarTanPIOver8); 7590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar mx = SkScalarMul(rx, SK_ScalarRoot2Over2); 7600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar my = SkScalarMul(ry, SK_ScalarRoot2Over2); 7610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* 7630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project To handle imprecision in computing the center and radii, we revert to 7640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project the provided bounds when we can (i.e. use oval.fLeft instead of cx-rx) 7650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project to ensure that we don't exceed the oval's bounds *ever*, since we want 7660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project to use oval for our fast-bounds, rather than have to recompute it. 7670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 7680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar L = oval.fLeft; // cx - rx 7690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar T = oval.fTop; // cy - ry 7700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar R = oval.fRight; // cx + rx 7710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar B = oval.fBottom; // cy + ry 7720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(17); // 8 quads + close 7740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(R, cy); 7750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dir == kCCW_Direction) { 7760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( R, cy - sy, cx + mx, cy - my); 7770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx + sx, T, cx , T); 7780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx - sx, T, cx - mx, cy - my); 7790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( L, cy - sy, L, cy ); 7800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( L, cy + sy, cx - mx, cy + my); 7810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx - sx, B, cx , B); 7820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx + sx, B, cx + mx, cy + my); 7830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( R, cy + sy, R, cy ); 7840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 7850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( R, cy + sy, cx + mx, cy + my); 7860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx + sx, B, cx , B); 7870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx - sx, B, cx - mx, cy + my); 7880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( L, cy + sy, L, cy ); 7890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( L, cy - sy, cx - mx, cy - my); 7900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx - sx, T, cx , T); 7910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(cx + sx, T, cx + mx, cy - my); 7920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo( R, cy - sy, R, cy ); 7930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 7950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->close(); 7960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 7970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addCircle(SkScalar x, SkScalar y, SkScalar r, Direction dir) { 7990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (r > 0) { 8000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect rect; 8010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.set(x - r, y - r, x + r, y + r); 8020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->addOval(rect, dir); 8030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 8050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGeometry.h" 8070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int build_arc_points(const SkRect& oval, SkScalar startAngle, 8090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sweepAngle, 8100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[kSkBuildQuadArcStorage]) { 8110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector start, stop; 8120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project start.fY = SkScalarSinCos(SkDegreesToRadians(startAngle), &start.fX); 8140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stop.fY = SkScalarSinCos(SkDegreesToRadians(startAngle + sweepAngle), 8150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project &stop.fX); 8161c980e0d7772f05f570ae0227d91635f017c2227Mike Reed 8171c980e0d7772f05f570ae0227d91635f017c2227Mike Reed /* If the sweep angle is nearly (but less than) 360, then due to precision 8181c980e0d7772f05f570ae0227d91635f017c2227Mike Reed loss in radians-conversion and/or sin/cos, we may end up with coincident 8191c980e0d7772f05f570ae0227d91635f017c2227Mike Reed vectors, which will fool SkBuildQuadArc into doing nothing (bad) instead 8201c980e0d7772f05f570ae0227d91635f017c2227Mike Reed of drawing a nearly complete circle (good). 8211c980e0d7772f05f570ae0227d91635f017c2227Mike Reed e.g. canvas.drawArc(0, 359.99, ...) 8221c980e0d7772f05f570ae0227d91635f017c2227Mike Reed -vs- canvas.drawArc(0, 359.9, ...) 8231c980e0d7772f05f570ae0227d91635f017c2227Mike Reed We try to detect this edge case, and tweak the stop vector 8241c980e0d7772f05f570ae0227d91635f017c2227Mike Reed */ 8251c980e0d7772f05f570ae0227d91635f017c2227Mike Reed if (start == stop) { 8261c980e0d7772f05f570ae0227d91635f017c2227Mike Reed SkScalar sw = SkScalarAbs(sweepAngle); 8271c980e0d7772f05f570ae0227d91635f017c2227Mike Reed if (sw < SkIntToScalar(360) && sw > SkIntToScalar(359)) { 8281c980e0d7772f05f570ae0227d91635f017c2227Mike Reed SkScalar stopRad = SkDegreesToRadians(startAngle + sweepAngle); 8291c980e0d7772f05f570ae0227d91635f017c2227Mike Reed // make a guess at a tiny angle (in radians) to tweak by 8301c980e0d7772f05f570ae0227d91635f017c2227Mike Reed SkScalar deltaRad = SkScalarCopySign(SK_Scalar1/512, sweepAngle); 8311c980e0d7772f05f570ae0227d91635f017c2227Mike Reed // not sure how much will be enough, so we use a loop 8321c980e0d7772f05f570ae0227d91635f017c2227Mike Reed do { 8331c980e0d7772f05f570ae0227d91635f017c2227Mike Reed stopRad -= deltaRad; 8341c980e0d7772f05f570ae0227d91635f017c2227Mike Reed stop.fY = SkScalarSinCos(stopRad, &stop.fX); 8351c980e0d7772f05f570ae0227d91635f017c2227Mike Reed } while (start == stop); 8361c980e0d7772f05f570ae0227d91635f017c2227Mike Reed } 8371c980e0d7772f05f570ae0227d91635f017c2227Mike Reed } 8381c980e0d7772f05f570ae0227d91635f017c2227Mike Reed 8390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 84040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 8410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setScale(SkScalarHalf(oval.width()), SkScalarHalf(oval.height())); 8420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.postTranslate(oval.centerX(), oval.centerY()); 84340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 8440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkBuildQuadArc(start, stop, 8450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sweepAngle > 0 ? kCW_SkRotationDirection : kCCW_SkRotationDirection, 8460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project &matrix, pts); 8470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 8480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::arcTo(const SkRect& oval, SkScalar startAngle, SkScalar sweepAngle, 8500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool forceMoveTo) { 8510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (oval.width() < 0 || oval.height() < 0) { 8520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 8530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[kSkBuildQuadArcStorage]; 8560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = build_arc_points(oval, startAngle, sweepAngle, pts); 8570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((count & 1) == 1); 8580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fVerbs.count() == 0) { 8600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project forceMoveTo = true; 8610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(count); 8630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project forceMoveTo ? this->moveTo(pts[0]) : this->lineTo(pts[0]); 8640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 1; i < count; i += 2) { 8650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(pts[i], pts[i+1]); 8660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 8680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addArc(const SkRect& oval, SkScalar startAngle, 8700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sweepAngle) { 8710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (oval.isEmpty() || 0 == sweepAngle) { 8720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 8730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar kFullCircleAngle = SkIntToScalar(360); 8760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (sweepAngle >= kFullCircleAngle || sweepAngle <= -kFullCircleAngle) { 8780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->addOval(oval, sweepAngle > 0 ? kCW_Direction : kCCW_Direction); 8790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 8800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[kSkBuildQuadArcStorage]; 8830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = build_arc_points(oval, startAngle, sweepAngle, pts); 8840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(count); 8860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(pts[0]); 8870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 1; i < count; i += 2) { 8880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(pts[i], pts[i+1]); 8890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 8910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 8930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Need to handle the case when the angle is sharp, and our computed end-points 8940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for the arc go behind pt1 and/or p2... 8950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 8960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2, 8970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar radius) { 8980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector before, after; 89940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need to know our prev pt so we can construct tangent vectors 9010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 9020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint start; 9030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->getLastPt(&start); 90440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // Handle degenerate cases by adding a line to the first point and 90540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // bailing out. 90640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if ((x1 == start.fX && y1 == start.fY) || 90740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger (x1 == x2 && y1 == y2) || 90840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger radius == 0) { 90940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->lineTo(x1, y1); 91040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger return; 91140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 9120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project before.setNormalize(x1 - start.fX, y1 - start.fY); 9130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project after.setNormalize(x2 - x1, y2 - y1); 9140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 91540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar cosh = SkPoint::DotProduct(before, after); 9170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sinh = SkPoint::CrossProduct(before, after); 9180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkScalarNearlyZero(sinh)) { // angle is too tight 92040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->lineTo(x1, y1); 9210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 9220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 92340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dist = SkScalarMulDiv(radius, SK_Scalar1 - cosh, sinh); 9250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dist < 0) { 9260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dist = -dist; 9270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar xx = x1 - SkScalarMul(dist, before.fX); 9300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar yy = y1 - SkScalarMul(dist, before.fY); 9310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRotationDirection arcDir; 9320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now turn before/after into normals 9340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (sinh > 0) { 9350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project before.rotateCCW(); 9360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project after.rotateCCW(); 9370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project arcDir = kCW_SkRotationDirection; 9380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 9390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project before.rotateCW(); 9400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project after.rotateCW(); 9410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project arcDir = kCCW_SkRotationDirection; 9420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 9450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[kSkBuildQuadArcStorage]; 94640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setScale(radius, radius); 9480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.postTranslate(xx - SkScalarMul(radius, before.fX), 9490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project yy - SkScalarMul(radius, before.fY)); 95040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = SkBuildQuadArc(before, after, arcDir, &matrix, pts); 95240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(count); 9540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // [xx,yy] == pts[0] 9550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(xx, yy); 9560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 1; i < count; i += 2) { 9570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(pts[i], pts[i+1]); 9580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 9600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 9620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy) { 9640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 9650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setTranslate(dx, dy); 9670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->addPath(path, matrix); 9680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 9690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::addPath(const SkPath& path, const SkMatrix& matrix) { 9710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(path.fPts.count()); 9720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger RawIter iter(path); 9740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4]; 9750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Verb verb; 9760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix::MapPtsProc proc = matrix.getMapPtsProc(); 9780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while ((verb = iter.next(pts)) != kDone_Verb) { 9800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verb) { 9810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kMove_Verb: 9820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc(matrix, &pts[0], &pts[0], 1); 9830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->moveTo(pts[0]); 9840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 9850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_Verb: 9860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc(matrix, &pts[1], &pts[1], 1); 9870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(pts[1]); 9880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 9890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_Verb: 9900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc(matrix, &pts[1], &pts[1], 2); 9910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(pts[1], pts[2]); 9920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 9930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_Verb: 9940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc(matrix, &pts[1], &pts[1], 3); 9950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(pts[1], pts[2], pts[3]); 9960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 9970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kClose_Verb: 9980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->close(); 9990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 10011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("unknown verb"); 10020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 10050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 10070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic const uint8_t gPtsInVerb[] = { 10090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1, // kMove 10100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1, // kLine 10110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2, // kQuad 10120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3, // kCubic 10130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 0, // kClose 10140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 0 // kDone 10150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 10160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// ignore the initial moveto, and stop when the 1st contour ends 10180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::pathTo(const SkPath& path) { 10190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int i, vcount = path.fVerbs.count(); 10200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (vcount == 0) { 10210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 10220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(vcount); 10250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint8_t* verbs = path.fVerbs.begin(); 10270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* pts = path.fPts.begin() + 1; // 1 for the initial moveTo 10280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(verbs[0] == kMove_Verb); 10300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (i = 1; i < vcount; i++) { 10310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verbs[i]) { 10320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_Verb: 10330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(pts[0].fX, pts[0].fY); 10340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_Verb: 10360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY); 10370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_Verb: 10390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(pts[0].fX, pts[0].fY, pts[1].fX, pts[1].fY, 10400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[2].fX, pts[2].fY); 10410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kClose_Verb: 10430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 10440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts += gPtsInVerb[verbs[i]]; 10460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 10480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// ignore the last point of the 1st contour 10500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::reversePathTo(const SkPath& path) { 10510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int i, vcount = path.fVerbs.count(); 10520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (vcount == 0) { 10530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 10540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->incReserve(vcount); 10570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint8_t* verbs = path.fVerbs.begin(); 10590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* pts = path.fPts.begin(); 10600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(verbs[0] == kMove_Verb); 10620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (i = 1; i < vcount; i++) { 10630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int n = gPtsInVerb[verbs[i]]; 10640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (n == 0) { 10650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts += n; 10680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (--i > 0) { 10710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verbs[i]) { 10720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_Verb: 10730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->lineTo(pts[-1].fX, pts[-1].fY); 10740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_Verb: 10760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->quadTo(pts[-1].fX, pts[-1].fY, pts[-2].fX, pts[-2].fY); 10770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_Verb: 10790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->cubicTo(pts[-1].fX, pts[-1].fY, pts[-2].fX, pts[-2].fY, 10800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[-3].fX, pts[-3].fY); 10810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 10831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("bad verb"); 10840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 10850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts -= gPtsInVerb[verbs[i]]; 10870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 10890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPath::reverseAddPath(const SkPath& src) { 10911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->incReserve(src.fPts.count()); 10921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 10931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* startPts = src.fPts.begin(); 10941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* pts = src.fPts.end(); 10951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* startVerbs = src.fVerbs.begin(); 10961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* verbs = src.fVerbs.end(); 10971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 10981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool needMove = true; 10991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool needClose = false; 11001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger while (verbs > startVerbs) { 11011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger uint8_t v = *--verbs; 11021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int n = gPtsInVerb[v]; 11031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 11041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (needMove) { 11051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger --pts; 11061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->moveTo(pts->fX, pts->fY); 11071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger needMove = false; 11081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 11091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts -= n; 11101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger switch (v) { 11111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kMove_Verb: 11121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (needClose) { 11131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->close(); 11141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger needClose = false; 11151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 11161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger needMove = true; 11171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts += 1; // so we see the point in "if (needMove)" above 11181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 11191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kLine_Verb: 11201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->lineTo(pts[0]); 11211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 11221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kQuad_Verb: 11231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->quadTo(pts[1], pts[0]); 11241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 11251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kCubic_Verb: 11261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->cubicTo(pts[2], pts[1], pts[0]); 11271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 11281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kClose_Verb: 11291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger needClose = true; 11301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 11311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger default: 11321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(!"unexpected verb"); 11331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 11341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 11351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 11361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 11370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 11380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::offset(SkScalar dx, SkScalar dy, SkPath* dst) const { 11400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 11410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setTranslate(dx, dy); 11430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->transform(matrix, dst); 11440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 11450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGeometry.h" 11470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void subdivide_quad_to(SkPath* path, const SkPoint pts[3], 11490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int level = 2) { 11500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (--level >= 0) { 11510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[5]; 11520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAtHalf(pts, tmp); 11540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subdivide_quad_to(path, &tmp[0], level); 11550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subdivide_quad_to(path, &tmp[2], level); 11560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 11570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path->quadTo(pts[1], pts[2]); 11580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 11600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void subdivide_cubic_to(SkPath* path, const SkPoint pts[4], 11620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int level = 2) { 11630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (--level >= 0) { 11640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[7]; 11650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAtHalf(pts, tmp); 11670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subdivide_cubic_to(path, &tmp[0], level); 11680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subdivide_cubic_to(path, &tmp[3], level); 11690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 11700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path->cubicTo(pts[1], pts[2], pts[3]); 11710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 11730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::transform(const SkMatrix& matrix, SkPath* dst) const { 11750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 11760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (dst == NULL) { 11770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst = (SkPath*)this; 11780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11800199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger if (matrix.hasPerspective()) { 11810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath tmp; 11820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.fFillType = fFillType; 11830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Iter iter(*this, false); 11850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4]; 11860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Verb verb; 11870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while ((verb = iter.next(pts)) != kDone_Verb) { 11890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verb) { 11900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kMove_Verb: 11910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.moveTo(pts[0]); 11920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 11930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_Verb: 11940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.lineTo(pts[1]); 11950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 11960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_Verb: 11970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subdivide_quad_to(&tmp, pts); 11980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 11990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_Verb: 12000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project subdivide_cubic_to(&tmp, pts); 12010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 12020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kClose_Verb: 12030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.close(); 12040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 12050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 12061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("unknown verb"); 12070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 12080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1211ebb0af8e21433525397cefdec3a8903e3da966b0Romain Guy // swap() will increment the gen id if needed 12120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->swap(tmp); 12130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.mapPoints(dst->fPts.begin(), dst->fPts.count()); 12140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 12150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // remember that dst might == this, so be sure to check 12160e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed // fBoundsIsDirty before we set it 12170e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed if (!fBoundsIsDirty && matrix.rectStaysRect() && fPts.count() > 1) { 12180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // if we're empty, fastbounds should not be mapped 12190e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed matrix.mapRect(&dst->fBounds, fBounds); 12200e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed dst->fBoundsIsDirty = false; 12210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 12220e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed dst->fBoundsIsDirty = true; 12230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this != dst) { 12260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->fVerbs = fVerbs; 12270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->fPts.setCount(fPts.count()); 12280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->fFillType = fFillType; 12291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->fSegmentMask = fSegmentMask; 12301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dst->fConvexity = fConvexity; 12310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1232ebb0af8e21433525397cefdec3a8903e3da966b0Romain Guy 1233ebb0af8e21433525397cefdec3a8903e3da966b0Romain Guy if (!matrix.isIdentity()) { 1234ebb0af8e21433525397cefdec3a8903e3da966b0Romain Guy GEN_ID_PTR_INC(dst); 1235ebb0af8e21433525397cefdec3a8903e3da966b0Romain Guy } 12360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.mapPoints(dst->fPts.begin(), fPts.begin(), fPts.count()); 1237ebb0af8e21433525397cefdec3a8903e3da966b0Romain Guy 12380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(dst->validate();) 12390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 12410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 12430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 12440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerenum SegmentState { 12464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger kEmptyContour_SegmentState, // The current contour is empty. We may be 12474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // starting processing or we may have just 12484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // closed a contour. 12491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger kAfterMove_SegmentState, // We have seen a move, but nothing else. 12501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger kAfterPrimitive_SegmentState // We have seen a primitive but not yet 12511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // closed the path. Also the initial state. 12520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 12530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPath::Iter::Iter() { 12550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 12560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts = NULL; 12570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMoveTo.fX = fMoveTo.fY = fLastPt.fX = fLastPt.fY = 0; 12581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fForceClose = fCloseLine = false; 12594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fSegmentState = kEmptyContour_SegmentState; 12600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 12610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need to init enough to make next() harmlessly return kDone_Verb 12620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs = NULL; 12630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbStop = NULL; 12640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fNeedClose = false; 12650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 12660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPath::Iter::Iter(const SkPath& path, bool forceClose) { 12680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->setPath(path, forceClose); 12690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 12700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::Iter::setPath(const SkPath& path, bool forceClose) { 12720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts = path.fPts.begin(); 12730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs = path.fVerbs.begin(); 12740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbStop = path.fVerbs.end(); 12751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt.fX = fLastPt.fY = 0; 12761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fMoveTo.fX = fMoveTo.fY = 0; 12770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fForceClose = SkToU8(forceClose); 12780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fNeedClose = false; 12794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fSegmentState = kEmptyContour_SegmentState; 12800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 12810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPath::Iter::isClosedContour() const { 12830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fVerbs == NULL || fVerbs == fVerbStop) { 12840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 12850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fForceClose) { 12870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 12880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint8_t* verbs = fVerbs; 12910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint8_t* stop = fVerbStop; 129240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (kMove_Verb == *verbs) { 12940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project verbs += 1; // skip the initial moveto 12950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (verbs < stop) { 129840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger unsigned v = *verbs++; 12990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (kMove_Verb == v) { 13000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 13010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (kClose_Verb == v) { 13030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 13040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 13070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 13080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPath::Verb SkPath::Iter::autoClose(SkPoint pts[2]) { 13100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fLastPt != fMoveTo) { 13117ecd8eaf1681919d6be87612a374739541b31996Feng Qian // A special case: if both points are NaN, SkPoint::operation== returns 13127ecd8eaf1681919d6be87612a374739541b31996Feng Qian // false, but the iterator expects that they are treated as the same. 13137ecd8eaf1681919d6be87612a374739541b31996Feng Qian // (consider SkPoint is a 2-dimension float point). 1314cac9f6a367de0788a55059ca6b34ed5b3f741390Mike Reed if (SkScalarIsNaN(fLastPt.fX) || SkScalarIsNaN(fLastPt.fY) || 1315cac9f6a367de0788a55059ca6b34ed5b3f741390Mike Reed SkScalarIsNaN(fMoveTo.fX) || SkScalarIsNaN(fMoveTo.fY)) { 13167ecd8eaf1681919d6be87612a374739541b31996Feng Qian return kClose_Verb; 13177ecd8eaf1681919d6be87612a374739541b31996Feng Qian } 1318aa4832adcc7eba085987357591bcfeb530ba7b0dMike Reed 13190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts) { 13200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[0] = fLastPt; 13210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1] = fMoveTo; 13220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLastPt = fMoveTo; 13240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCloseLine = true; 13250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kLine_Verb; 13261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 13271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts[0] = fMoveTo; 13281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return kClose_Verb; 13290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 13310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPath::Iter::cons_moveTo(SkPoint pts[1]) { 13331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fSegmentState == kAfterMove_SegmentState) { 13341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Set the first return pt to the move pt 13350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts) { 13360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *pts = fMoveTo; 13370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentState = kAfterPrimitive_SegmentState; 13390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 13401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(fSegmentState == kAfterPrimitive_SegmentState); 13411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Set the first return pt to the last pt of the previous primitive. 13420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts) { 13430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *pts = fPts[-1]; 13440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 13470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 13480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPath::Iter::consumeDegenerateSegments() { 13501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // We need to step over anything that will not move the current draw point 13511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // forward before the next move is seen 13521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* lastMoveVerb = 0; 13531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* lastMovePt = 0; 13541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPoint lastPt = fLastPt; 13551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger while (fVerbs != fVerbStop) { 13561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger unsigned verb = *fVerbs; 13571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger switch (verb) { 13581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kMove_Verb: 13591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Keep a record of this most recent move 13601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger lastMoveVerb = fVerbs; 13611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger lastMovePt = fPts; 13621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger lastPt = fPts[0]; 13631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs++; 13641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts++; 13651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 13661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 13671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kClose_Verb: 13681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // A close when we are in a segment is always valid 13691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fSegmentState == kAfterPrimitive_SegmentState) { 13701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 13711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 13721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // A close at any other time must be ignored 13731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs++; 13741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 13751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 13761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kLine_Verb: 13771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!IsLineDegenerate(lastPt, fPts[0])) { 13781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (lastMoveVerb) { 13791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs = lastMoveVerb; 13801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts = lastMovePt; 13811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 13821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 13831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 13841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 13851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Ignore this line and continue 13861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs++; 13871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts++; 13881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 13891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 13901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kQuad_Verb: 13911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!IsQuadDegenerate(lastPt, fPts[0], fPts[1])) { 13921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (lastMoveVerb) { 13931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs = lastMoveVerb; 13941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts = lastMovePt; 13951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 13961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 13971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 13981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 13991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Ignore this line and continue 14001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs++; 14011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts += 2; 14021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 14031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kCubic_Verb: 14051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!IsCubicDegenerate(lastPt, fPts[0], fPts[1], fPts[2])) { 14061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (lastMoveVerb) { 14071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs = lastMoveVerb; 14081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts = lastMovePt; 14091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 14101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 14121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Ignore this line and continue 14141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs++; 14151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts += 3; 14161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 14171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger default: 14191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("Should never see kDone_Verb"); 14201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 14231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPath::Verb SkPath::Iter::next(SkPoint pts[4]) { 14251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->consumeDegenerateSegments(); 14261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fVerbs == fVerbStop) { 14281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // Close the curve if requested and if there is some curve to close 14291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fNeedClose && fSegmentState == kAfterPrimitive_SegmentState) { 14300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (kLine_Verb == this->autoClose(pts)) { 14310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kLine_Verb; 14320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fNeedClose = false; 14340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kClose_Verb; 14350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kDone_Verb; 14370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 14390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned verb = *fVerbs++; 14400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* srcPts = fPts; 14410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 14420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verb) { 14430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kMove_Verb: 14440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fNeedClose) { 14450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs -= 1; 14460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project verb = this->autoClose(pts); 14470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (verb == kClose_Verb) { 14480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fNeedClose = false; 14490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (Verb)verb; 14510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fVerbs == fVerbStop) { // might be a trailing moveto 14530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kDone_Verb; 14540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMoveTo = *srcPts; 14560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts) { 14570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[0] = *srcPts; 14580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcPts += 1; 14601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentState = kAfterMove_SegmentState; 14611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt = fMoveTo; 14620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fNeedClose = fForceClose; 14630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 14640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_Verb: 14650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->cons_moveTo(pts)) { 14660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kMove_Verb; 14670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts) { 14690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1] = srcPts[0]; 14700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLastPt = srcPts[0]; 14720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCloseLine = false; 14730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcPts += 1; 14740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 14750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_Verb: 14760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->cons_moveTo(pts)) { 14770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kMove_Verb; 14780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts) { 14800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(&pts[1], srcPts, 2 * sizeof(SkPoint)); 14810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLastPt = srcPts[1]; 14830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcPts += 2; 14840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 14850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_Verb: 14860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->cons_moveTo(pts)) { 14870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return kMove_Verb; 14880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pts) { 14900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(&pts[1], srcPts, 3 * sizeof(SkPoint)); 14910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLastPt = srcPts[2]; 14930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcPts += 3; 14940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 14950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kClose_Verb: 14960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project verb = this->autoClose(pts); 14970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (verb == kLine_Verb) { 14980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs -= 1; 14990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 15000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fNeedClose = false; 15014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fSegmentState = kEmptyContour_SegmentState; 15020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt = fMoveTo; 15040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 15050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts = srcPts; 15070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (Verb)verb; 15080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 15090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 15110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15121cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPath::RawIter::RawIter() { 15131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_DEBUG 15141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts = NULL; 15151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fMoveTo.fX = fMoveTo.fY = fLastPt.fX = fLastPt.fY = 0; 15161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif 15171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // need to init enough to make next() harmlessly return kDone_Verb 15181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs = NULL; 15191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbStop = NULL; 15200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 15210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15221cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPath::RawIter::RawIter(const SkPath& path) { 15231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->setPath(path); 15240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 15250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkPath::RawIter::setPath(const SkPath& path) { 15271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts = path.fPts.begin(); 15281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbs = path.fVerbs.begin(); 15291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fVerbStop = path.fVerbs.end(); 15301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fMoveTo.fX = fMoveTo.fY = 0; 15311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt.fX = fLastPt.fY = 0; 15320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 15330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15341cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerSkPath::Verb SkPath::RawIter::next(SkPoint pts[4]) { 15351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fVerbs == fVerbStop) { 15361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return kDone_Verb; 15370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger unsigned verb = *fVerbs++; 15401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* srcPts = fPts; 15410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger switch (verb) { 15431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kMove_Verb: 15441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (pts) { 15451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts[0] = *srcPts; 15461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 15471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fMoveTo = srcPts[0]; 15481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt = fMoveTo; 15491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger srcPts += 1; 15501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 15511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kLine_Verb: 15521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (pts) { 15531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts[0] = fLastPt; 15541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts[1] = srcPts[0]; 15551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 15561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt = srcPts[0]; 15571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger srcPts += 1; 15581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 15591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kQuad_Verb: 15601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (pts) { 15611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts[0] = fLastPt; 15621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger memcpy(&pts[1], srcPts, 2 * sizeof(SkPoint)); 15631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 15641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt = srcPts[1]; 15651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger srcPts += 2; 15661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 15671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kCubic_Verb: 15681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (pts) { 15691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts[0] = fLastPt; 15701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger memcpy(&pts[1], srcPts, 3 * sizeof(SkPoint)); 15711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 15721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt = srcPts[2]; 15731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger srcPts += 3; 15741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 15751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kClose_Verb: 15761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fLastPt = fMoveTo; 15771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (pts) { 15781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger pts[0] = fMoveTo; 15791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 15801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 15810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fPts = srcPts; 15831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return (Verb)verb; 15840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 15850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 15871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 15880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 15890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Format in flattened buffer: [ptCount, verbCount, pts[], verbs[]] 15900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 15910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 159235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkPath::flatten(SkWriter32& buffer) const { 15930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 15940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write32(fPts.count()); 15960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.write32(fVerbs.count()); 15971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger buffer.write32((fFillType << 8) | fSegmentMask); 15980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.writeMul4(fPts.begin(), sizeof(SkPoint) * fPts.count()); 15990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.writePad(fVerbs.begin(), fVerbs.count()); 16000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 160235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergervoid SkPath::unflatten(SkReader32& buffer) { 16030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPts.setCount(buffer.readS32()); 16040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fVerbs.setCount(buffer.readS32()); 16051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger uint32_t packed = buffer.readS32(); 16061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fFillType = packed >> 8; 16071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fSegmentMask = packed & 0xFF; 16080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.read(fPts.begin(), sizeof(SkPoint) * fPts.count()); 16090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project buffer.read(fVerbs.begin(), fVerbs.count()); 161087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 161187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger GEN_ID_INC; 16120b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger DIRTY_AFTER_EDIT; 16130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 16150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 16180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPath::dump(bool forceClose, const char title[]) const { 16200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Iter iter(*this, forceClose); 16210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4]; 16220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Verb verb; 16230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("path: forceClose=%s %s\n", forceClose ? "true" : "false", 16250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project title ? title : ""); 16260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while ((verb = iter.next(pts)) != kDone_Verb) { 16280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verb) { 16290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kMove_Verb: 16300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT 16310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: moveTo [%g %g]\n", 16320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFloat(pts[0].fX), SkScalarToFloat(pts[0].fY)); 16330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 16340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: moveTo [%x %x]\n", pts[0].fX, pts[0].fY); 16350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 16360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 16370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_Verb: 16380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT 16390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: lineTo [%g %g]\n", 16400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFloat(pts[1].fX), SkScalarToFloat(pts[1].fY)); 16410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 16420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: lineTo [%x %x]\n", pts[1].fX, pts[1].fY); 16430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 16440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 16450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_Verb: 16460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT 16470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: quadTo [%g %g] [%g %g]\n", 16480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFloat(pts[1].fX), SkScalarToFloat(pts[1].fY), 16490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFloat(pts[2].fX), SkScalarToFloat(pts[2].fY)); 16500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 16510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: quadTo [%x %x] [%x %x]\n", 16520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY); 16530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 16540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 16550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_Verb: 16560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CAN_USE_FLOAT 16570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: cubeTo [%g %g] [%g %g] [%g %g]\n", 16580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFloat(pts[1].fX), SkScalarToFloat(pts[1].fY), 16590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFloat(pts[2].fX), SkScalarToFloat(pts[2].fY), 16600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFloat(pts[3].fX), SkScalarToFloat(pts[3].fY)); 16610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 16620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: cubeTo [%x %x] [%x %x] [%x %x]\n", 16630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY, 16640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts[3].fX, pts[3].fY); 16650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 16660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 16670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kClose_Verb: 16680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: close\n"); 16690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 16700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 16710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf(" path: UNKNOWN VERB %d, aborting dump...\n", verb); 16720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project verb = kDone_Verb; // stop the loop 16730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 16740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 16750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 16760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("path: done %s\n", title ? title : ""); 16770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1679a8b45f65acb9d306cb57edd886728933f13d4424Mike Reedvoid SkPath::dump() const { 1680a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed this->dump(false); 1681a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed} 1682a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed 1683a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed#ifdef SK_DEBUG 1684a8b45f65acb9d306cb57edd886728933f13d4424Mike Reedvoid SkPath::validate() const { 1685a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed SkASSERT(this != NULL); 1686a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed SkASSERT((fFillType & ~3) == 0); 1687a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed fPts.validate(); 1688a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed fVerbs.validate(); 168940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1690a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed if (!fBoundsIsDirty) { 1691a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed SkRect bounds; 1692a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed compute_pt_bounds(&bounds, fPts); 1693a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed if (fPts.count() <= 1) { 1694a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed // if we're empty, fBounds may be empty but translated, so we can't 1695a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed // necessarily compare to bounds directly 1696a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed // try path.addOval(2, 2, 2, 2) which is empty, but the bounds will 1697a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed // be [2, 2, 2, 2] 1698a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed SkASSERT(bounds.isEmpty()); 1699a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed SkASSERT(fBounds.isEmpty()); 1700a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed } else { 17011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (bounds.isEmpty()) { 17021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(fBounds.isEmpty()); 17031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 17041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!fBounds.isEmpty()) { 17051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(fBounds.contains(bounds)); 17061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 17071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 17081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 17091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 17101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 17111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger uint32_t mask = 0; 17121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < fVerbs.count(); i++) { 17131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger switch (fVerbs[i]) { 17141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kLine_Verb: 17151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask |= kLine_SegmentMask; 17161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 17171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kQuad_Verb: 17181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask |= kQuad_SegmentMask; 17191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 17201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case kCubic_Verb: 17211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask |= kCubic_SegmentMask; 1722a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed } 1723a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed } 17241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(mask == fSegmentMask); 1725a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed} 17260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 1727a8b45f65acb9d306cb57edd886728933f13d4424Mike Reed 172835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 172935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 173035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic int sign(SkScalar x) { return x < 0; } 173135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#define kValueNeverReturnedBySign 2 173235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 173335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic int CrossProductSign(const SkVector& a, const SkVector& b) { 17341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return SkScalarSignAsInt(SkPoint::CrossProduct(a, b)); 173535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger} 173635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 173735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// only valid for a single contour 173835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstruct Convexicator { 17390b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger Convexicator() : fPtCount(0), fConvexity(SkPath::kConvex_Convexity) { 174035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fSign = 0; 174135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger // warnings 174235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fCurrPt.set(0, 0); 174335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fVec0.set(0, 0); 174435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fVec1.set(0, 0); 174535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fFirstVec.set(0, 0); 174635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 174735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fDx = fDy = 0; 174835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fSx = fSy = kValueNeverReturnedBySign; 174935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 175035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 175135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkPath::Convexity getConvexity() const { return fConvexity; } 175235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 175335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger void addPt(const SkPoint& pt) { 175435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (SkPath::kConcave_Convexity == fConvexity) { 175535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger return; 175635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 175735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 175835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (0 == fPtCount) { 175935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fCurrPt = pt; 176035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger ++fPtCount; 176135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } else { 176235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkVector vec = pt - fCurrPt; 176335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (vec.fX || vec.fY) { 176435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fCurrPt = pt; 176535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (++fPtCount == 2) { 176635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fFirstVec = fVec1 = vec; 176735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } else { 176835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkASSERT(fPtCount > 2); 176935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger this->addVec(vec); 177035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 177135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 177235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int sx = sign(vec.fX); 177335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int sy = sign(vec.fY); 177435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fDx += (sx != fSx); 177535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fDy += (sy != fSy); 177635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fSx = sx; 177735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fSy = sy; 177835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 177935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (fDx > 3 || fDy > 3) { 178035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fConvexity = SkPath::kConcave_Convexity; 178135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 178235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 178335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 178435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 178535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 178635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger void close() { 178735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (fPtCount > 2) { 178835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger this->addVec(fFirstVec); 178935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 179035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 179135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 179235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerprivate: 179335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger void addVec(const SkVector& vec) { 179435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkASSERT(vec.fX || vec.fY); 179535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fVec0 = fVec1; 179635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fVec1 = vec; 179735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int sign = CrossProductSign(fVec0, fVec1); 179835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (0 == fSign) { 179935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fSign = sign; 180035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } else if (sign) { 18010b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger if (fSign != sign) { 180235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger fConvexity = SkPath::kConcave_Convexity; 180335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 180435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 180535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 180635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 180735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkPoint fCurrPt; 180835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkVector fVec0, fVec1, fFirstVec; 180935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int fPtCount; // non-degenerate points 181035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int fSign; 181135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkPath::Convexity fConvexity; 181235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int fDx, fDy, fSx, fSy; 181335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}; 181435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 181535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek SollenbergerSkPath::Convexity SkPath::ComputeConvexity(const SkPath& path) { 181635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkPoint pts[4]; 181735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkPath::Verb verb; 181835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger SkPath::Iter iter(path, true); 181935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 182035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int contourCount = 0; 182135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger int count; 182235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger Convexicator state; 182335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 182435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger while ((verb = iter.next(pts)) != SkPath::kDone_Verb) { 182535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger switch (verb) { 182635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case kMove_Verb: 182735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (++contourCount > 1) { 182835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger return kConcave_Convexity; 182935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 183035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger pts[1] = pts[0]; 183135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger count = 1; 183235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger break; 183335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case kLine_Verb: count = 1; break; 183435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case kQuad_Verb: count = 2; break; 183535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case kCubic_Verb: count = 3; break; 183635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger case kClose_Verb: 183735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger state.close(); 183835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger count = 0; 183935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger break; 184035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger default: 18411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("bad verb"); 184235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger return kConcave_Convexity; 184335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 184435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger 184535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger for (int i = 1; i <= count; i++) { 184635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger state.addPt(pts[i]); 184735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 184835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger // early exit 184935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger if (kConcave_Convexity == state.getConvexity()) { 185035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger return kConcave_Convexity; 185135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 185235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger } 185335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger return state.getConvexity(); 185435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger} 18551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/////////////////////////////////////////////////////////////////////////////// 18571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerclass ContourIter { 18591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerpublic: 18601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ContourIter(const SkTDArray<uint8_t>& verbs, const SkTDArray<SkPoint>& pts); 18611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool done() const { return fDone; } 18631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // if !done() then these may be called 18641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int count() const { return fCurrPtCount; } 18651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* pts() const { return fCurrPt; } 18661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger void next(); 18671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerprivate: 18691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int fCurrPtCount; 18701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* fCurrPt; 18711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* fCurrVerb; 18721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* fStopVerbs; 18731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bool fDone; 18741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGCODE(int fContourCounter;) 18751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}; 18761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18771cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerContourIter::ContourIter(const SkTDArray<uint8_t>& verbs, 18781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkTDArray<SkPoint>& pts) { 18791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fStopVerbs = verbs.begin() + verbs.count(); 18801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fDone = false; 18821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fCurrPt = pts.begin(); 18831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fCurrVerb = verbs.begin(); 18841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fCurrPtCount = 0; 18851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGCODE(fContourCounter = 0;) 18861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->next(); 18871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 18881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid ContourIter::next() { 18901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fCurrVerb >= fStopVerbs) { 18911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fDone = true; 18921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 18931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fDone) { 18941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 18951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 18961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 18971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // skip pts of prev contour 18981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fCurrPt += fCurrPtCount; 18991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 19001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(SkPath::kMove_Verb == fCurrVerb[0]); 19011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int ptCount = 1; // moveTo 19021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* verbs = fCurrVerb; 19031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 19041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (++verbs; verbs < fStopVerbs; ++verbs) { 19051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger switch (*verbs) { 19061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case SkPath::kMove_Verb: 19071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger goto CONTOUR_END; 19081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case SkPath::kLine_Verb: 19091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ptCount += 1; 19101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 19111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case SkPath::kQuad_Verb: 19121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ptCount += 2; 19131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 19141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case SkPath::kCubic_Verb: 19151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ptCount += 3; 19161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 19171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger default: // kClose_Verb, just keep going 19181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 19191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 19201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 19211cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerCONTOUR_END: 19221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fCurrPtCount = ptCount; 19231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fCurrVerb = verbs; 19241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGCODE(++fContourCounter;) 19251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 19261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 19274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger// returns cross product of (p1 - p0) and (p2 - p0) 19281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic SkScalar cross_prod(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2) { 19294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar cross = SkPoint::CrossProduct(p1 - p0, p2 - p0); 19304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // We may get 0 when the above subtracts underflow. We expect this to be 19314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // very rare and lazily promote to double. 19324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (0 == cross) { 19334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger double p0x = SkScalarToDouble(p0.fX); 19344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger double p0y = SkScalarToDouble(p0.fY); 19354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 19364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger double p1x = SkScalarToDouble(p1.fX); 19374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger double p1y = SkScalarToDouble(p1.fY); 19384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 19394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger double p2x = SkScalarToDouble(p2.fX); 19404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger double p2y = SkScalarToDouble(p2.fY); 19414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 19424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger cross = SkDoubleToScalar((p1x - p0x) * (p2y - p0y) - 19434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger (p1y - p0y) * (p2x - p0x)); 19444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 19454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 19464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return cross; 19471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 19481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 19494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger// Returns the first pt with the maximum Y coordinate 19501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic int find_max_y(const SkPoint pts[], int count) { 19511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(count > 0); 19521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScalar max = pts[0].fY; 19534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int firstIndex = 0; 19541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 1; i < count; ++i) { 19554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar y = pts[i].fY; 19564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (y > max) { 19574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger max = y; 19584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger firstIndex = i; 19591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 19601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 19614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return firstIndex; 19621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 19631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 19641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic int find_diff_pt(const SkPoint pts[], int index, int n, int inc) { 19651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int i = index; 19661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (;;) { 19671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger i = (i + inc) % n; 19681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (i == index) { // we wrapped around, so abort 19691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 19701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 19711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (pts[index] != pts[i]) { // found a different point, success! 19721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger break; 19731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 19741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 19751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return i; 19761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 19771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 19784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/** 19794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * Starting at index, and moving forward (incrementing), find the xmin and 19804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * xmax of the contiguous points that have the same Y. 19814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */ 19824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic int find_min_max_x_at_y(const SkPoint pts[], int index, int n, 19834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int* maxIndexPtr) { 19844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkScalar y = pts[index].fY; 19854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar min = pts[index].fX; 19864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar max = min; 19874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int minIndex = index; 19884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maxIndex = index; 19894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger for (int i = index + 1; i < n; ++i) { 19904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (pts[i].fY != y) { 19914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger break; 19924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 19934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar x = pts[i].fX; 19944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (x < min) { 19954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger min = x; 19964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger minIndex = i; 19974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } else if (x > max) { 19984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger max = x; 19994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger maxIndex = i; 20004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 20014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 20024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *maxIndexPtr = maxIndex; 20034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return minIndex; 20044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 20054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 20064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic bool crossToDir(SkScalar cross, SkPath::Direction* dir) { 20074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (dir) { 20084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *dir = cross > 0 ? SkPath::kCW_Direction : SkPath::kCCW_Direction; 20094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 20104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return true; 20114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 20124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 20134f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if 0 20144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkString.h" 20154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "../utils/SkParsePath.h" 20164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void dumpPath(const SkPath& path) { 20174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkString str; 20184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkParsePath::ToSVGString(path, &str); 20194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkDebugf("%s\n", str.c_str()); 20204f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 20214f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 20224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 20234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/* 20244f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * We loop through all contours, and keep the computed cross-product of the 20254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * contour that contained the global y-max. If we just look at the first 20264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * contour, we may find one that is wound the opposite way (correctly) since 20274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * it is the interior of a hole (e.g. 'o'). Thus we must find the contour 20284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * that is outer most (or at least has the global y-max) before we can consider 20294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * its cross product. 20304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */ 20311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkPath::cheapComputeDirection(Direction* dir) const { 20324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger// dumpPath(*this); 20331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // don't want to pay the cost for computing this if it 20341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // is unknown, so we don't call isConvex() 20351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const Convexity conv = this->getConvexityOrUnknown(); 20361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ContourIter iter(fVerbs, fPts); 20381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // initialize with our logical y-min 20404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar ymax = this->getBounds().fTop; 20414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar ymaxCross = 0; 20424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 20431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (; !iter.done(); iter.next()) { 20441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int n = iter.count(); 20451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (n < 3) { 20461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger continue; 20471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 20481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPoint* pts = iter.pts(); 20501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScalar cross = 0; 20511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (kConvex_Convexity == conv) { 20521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // we loop, skipping over degenerate or flat segments that will 20531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // return 0 for the cross-product 20541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger for (int i = 0; i < n - 2; ++i) { 20551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger cross = cross_prod(pts[i], pts[i + 1], pts[i + 2]); 20561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (cross) { 20574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // early-exit, as kConvex is assumed to have only 1 20584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // non-degenerate contour 20594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return crossToDir(cross, dir); 20601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 20611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 20621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 20631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int index = find_max_y(pts, n); 20644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (pts[index].fY < ymax) { 20651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger continue; 20661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 20674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 20684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // If there is more than 1 distinct point at the y-max, we take the 20694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // x-min and x-max of them and just subtract to compute the dir. 20704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (pts[(index + 1) % n].fY == pts[index].fY) { 20714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int maxIndex; 20724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int minIndex = find_min_max_x_at_y(pts, index, n, &maxIndex); 20734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (minIndex == maxIndex) { 20744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger goto TRY_CROSSPROD; 20754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 20764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT(pts[minIndex].fY == pts[index].fY); 20774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT(pts[maxIndex].fY == pts[index].fY); 20784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT(pts[minIndex].fX <= pts[maxIndex].fX); 20794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // we just subtract the indices, and let that auto-convert to 20804f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // SkScalar, since we just want - or + to signal the direction. 20814f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger cross = minIndex - maxIndex; 20824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } else { 20834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger TRY_CROSSPROD: 20844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // Find a next and prev index to use for the cross-product test, 20854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // but we try to find pts that form non-zero vectors from pts[index] 20864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // 20874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // Its possible that we can't find two non-degenerate vectors, so 20884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // we have to guard our search (e.g. all the pts could be in the 20894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // same place). 20904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 20914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // we pass n - 1 instead of -1 so we don't foul up % operator by 20924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // passing it a negative LH argument. 20934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int prev = find_diff_pt(pts, index, n, n - 1); 20944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (prev == index) { 20954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // completely degenerate, skip to next contour 20964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger continue; 20974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 20984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int next = find_diff_pt(pts, index, n, 1); 20994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT(next != index); 21004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger cross = cross_prod(pts[prev], pts[index], pts[next]); 21014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // if we get a zero, but the pts aren't on top of each other, then 21024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // we can just look at the direction 21034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (0 == cross) { 21044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // construct the subtract so we get the correct Direction below 21054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger cross = pts[index].fX - pts[next].fX; 21064f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 21074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 21084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 21094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (cross) { 21104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // record our best guess so far 21114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger ymax = pts[index].fY; 21124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger ymaxCross = cross; 21131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 21141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 21151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 21161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21174f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return ymaxCross ? crossToDir(ymaxCross, dir) : false; 21184f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger} 2119