SkPathMeasure.cpp revision 0910916c0f7b951ee55c4b7c6358295b9bca0565
10910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Copyright (C) 2006-2008 The Android Open Source Project 30910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 50910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * you may not use this file except in compliance with the License. 60910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * You may obtain a copy of the License at 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * See the License for the specific language governing permissions and 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * limitations under the License. 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathMeasure.h" 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGeometry.h" 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPath.h" 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTSearch.h" 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// these must be 0,1,2 since they are in our 2-bit field 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectenum { 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kLine_SegType, 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kCloseLine_SegType, 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kQuad_SegType, 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kCubic_SegType 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxTValue 32767 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkScalar tValue2Scalar(int t) { 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)t <= kMaxTValue); 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FLOAT 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return t * 3.05185e-5f; // t / 32767 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (t + (t >> 14)) << 1; 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::Segment::getScalarT() const { 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return tValue2Scalar(fTValue); 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkPathMeasure::Segment* SkPathMeasure::NextSegment(const Segment* seg) { 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned ptIndex = seg->fPtIndex; 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ++seg; 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (seg->fPtIndex == ptIndex); 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return seg; 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int tspan_big_enough(int tspan) { 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)tspan <= kMaxTValue); 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return tspan >> 10; 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool tangents_too_curvy(const SkVector& tan0, SkVector& tan1) { 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static const SkScalar kFlatEnoughTangentDotProd = SK_Scalar1 * 99 / 100; 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(kFlatEnoughTangentDotProd > 0 && 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kFlatEnoughTangentDotProd < SK_Scalar1); 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPoint::DotProduct(tan0, tan1) < kFlatEnoughTangentDotProd; 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// can't use tangents, since we need [0..1..................2] to be seen 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// as definitely not a line (it is when drawn, but not parametrically) 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// so we compare midpoints 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define CHEAP_DIST_LIMIT (SK_Scalar1/2) // just made this value up 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool quad_too_curvy(const SkPoint pts[3]) { 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // diff = (a/4 + b/2 + c/4) - (a/2 + c/2) 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // diff = -a/4 + b/2 - c/4 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dx = SkScalarHalf(pts[1].fX) - 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarHalf(SkScalarHalf(pts[0].fX + pts[2].fX)); 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dy = SkScalarHalf(pts[1].fY) - 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarHalf(SkScalarHalf(pts[0].fY + pts[2].fY)); 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dist = SkMaxScalar(SkScalarAbs(dx), SkScalarAbs(dy)); 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return dist > CHEAP_DIST_LIMIT; 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool cheap_dist_exceeds_limit(const SkPoint& pt, 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar x, SkScalar y) { 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY)); 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // just made up the 1/2 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return dist > CHEAP_DIST_LIMIT; 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool cubic_too_curvy(const SkPoint pts[4]) { 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return cheap_dist_exceeds_limit(pts[1], 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1/3), 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1/3)) 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project || 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project cheap_dist_exceeds_limit(pts[2], 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1*2/3), 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3)); 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3], 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance, int mint, int maxt, int ptIndex) { 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) { 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[5]; 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int halft = (mint + maxt) >> 1; 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAtHalf(pts, tmp); 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_quad_segs(tmp, distance, mint, halft, ptIndex); 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_quad_segs(&tmp[2], distance, halft, maxt, ptIndex); 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar d = SkPoint::Distance(pts[0], pts[2]); 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(d >= 0); 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!SkScalarNearlyZero(d)) { 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance += d; 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Segment* seg = fSegments.append(); 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fDistance = distance; 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fPtIndex = ptIndex; 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType = kQuad_SegType; 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fTValue = maxt; 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return distance; 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4], 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance, int mint, int maxt, int ptIndex) { 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) { 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[7]; 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int halft = (mint + maxt) >> 1; 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAtHalf(pts, tmp); 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex); 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIndex); 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar d = SkPoint::Distance(pts[0], pts[3]); 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(d >= 0); 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!SkScalarNearlyZero(d)) { 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance += d; 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Segment* seg = fSegments.append(); 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fDistance = distance; 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fPtIndex = ptIndex; 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType = kCubic_SegType; 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fTValue = maxt; 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return distance; 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::buildSegments() { 1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4]; 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int ptIndex = fFirstPtIndex; 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar d, distance = 0; 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool isClosed = fForceClosed; 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool firstMoveTo = ptIndex < 0; 1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Segment* seg; 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegments.reset(); 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (;;) { 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (fIter.next(pts)) { 1660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kMove_Verb: 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!firstMoveTo) { 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project goto DONE; 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex += 1; 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project firstMoveTo = false; 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 1730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kLine_Verb: 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project d = SkPoint::Distance(pts[0], pts[1]); 1760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(d >= 0); 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!SkScalarNearlyZero(d)) { 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance += d; 1790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg = fSegments.append(); 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fDistance = distance; 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fPtIndex = ptIndex; 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType = fIter.isCloseLine() ? 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kCloseLine_SegType : kLine_SegType; 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fTValue = kMaxTValue; 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex += !fIter.isCloseLine(); 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kQuad_Verb: 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_quad_segs(pts, distance, 0, 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxTValue, ptIndex); 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex += 2; 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kCubic_Verb: 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_cubic_segs(pts, distance, 0, 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxTValue, ptIndex); 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex += 3; 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kClose_Verb: 2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project isClosed = true; 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kDone_Verb: 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project goto DONE; 2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectDONE: 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = distance; 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fIsClosed = isClosed; 2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPtIndex = ptIndex + 1; 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = fSegments.begin(); 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* stop = fSegments.end(); 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned ptIndex = 0; 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance = 0; 2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (seg < stop) { 2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fDistance > distance); 2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fPtIndex >= ptIndex); 2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fTValue > 0); 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* s = seg; 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (s < stop - 1 && s[0].fPtIndex == s[1].fPtIndex) { 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(s[0].fType == s[1].fType); 2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(s[0].fTValue < s[1].fTValue); 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project s += 1; 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = seg->fDistance; 2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex = seg->fPtIndex; 2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg += 1; 2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // SkDebugf("\n"); 2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// marked as a friend in SkPath.h 2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkPoint* sk_get_path_points(const SkPath& path, int index) { 2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return &path.fPts[index]; 2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void compute_pos_tan(const SkPath& path, int firstPtIndex, int ptIndex, 2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int segType, SkScalar t, SkPoint* pos, SkVector* tangent) { 2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* pts = sk_get_path_points(path, ptIndex); 2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (segType) { 2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_SegType: 2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCloseLine_SegType: { 2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* endp = (segType == kLine_SegType) ? 2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project &pts[1] : 2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_get_path_points(path, firstPtIndex); 2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pos) { 2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pos->set(SkScalarInterp(pts[0].fX, endp->fX, t), 2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fY, endp->fY, t)); 2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tangent) { 2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tangent->setNormalize(endp->fX - pts[0].fX, endp->fY - pts[0].fY); 2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_SegType: 2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkEvalQuadAt(pts, t, pos, tangent); 2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tangent) { 2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tangent->normalize(); 2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_SegType: 2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkEvalCubicAt(pts, t, pos, tangent, NULL); 2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tangent) { 2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tangent->normalize(); 2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(!"unknown segType"); 2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void seg_to(const SkPath& src, int firstPtIndex, int ptIndex, 2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int segType, SkScalar startT, SkScalar stopT, SkPath* dst) { 2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(startT >= 0 && startT <= SK_Scalar1); 2870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(stopT >= 0 && stopT <= SK_Scalar1); 2880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(startT <= stopT); 2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkScalarNearlyZero(stopT - startT)) { 2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* pts = sk_get_path_points(src, ptIndex); 2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp0[7], tmp1[7]; 2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (segType) { 2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_SegType: 2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCloseLine_SegType: { 3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint* endp = (segType == kLine_SegType) ? 3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project &pts[1] : 3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_get_path_points(src, firstPtIndex); 3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == kMaxTValue) { 3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->lineTo(*endp); 3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->lineTo(SkScalarInterp(pts[0].fX, endp->fX, stopT), 3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fY, endp->fY, stopT)); 3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_SegType: 3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startT == 0) { 3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(pts[1], pts[2]); 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAt(pts, tmp0, stopT); 3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(tmp0[1], tmp0[2]); 3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAt(pts, tmp0, startT); 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(tmp0[3], tmp0[4]); 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAt(&tmp0[2], tmp1, SkScalarDiv(stopT - startT, 3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SK_Scalar1 - startT)); 3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(tmp1[1], tmp1[2]); 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_SegType: 3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startT == 0) { 3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(pts[1], pts[2], pts[3]); 3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAt(pts, tmp0, stopT); 3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]); 3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAt(pts, tmp0, startT); 3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(tmp0[4], tmp0[5], tmp0[6]); 3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAt(&tmp0[3], tmp1, SkScalarDiv(stopT - startT, 3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SK_Scalar1 - startT)); 3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(tmp1[1], tmp1[2], tmp1[3]); 3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(!"unknown segType"); 3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_throw(); 3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////// 3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////// 3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::SkPathMeasure() { 3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPath = NULL; 3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; // signal we need to compute it 3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fForceClosed = false; 3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPtIndex = -1; 3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed) { 3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPath = &path; 3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; // signal we need to compute it 3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fForceClosed = forceClosed; 3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPtIndex = -1; 3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fIter.setPath(path, forceClosed); 3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::~SkPathMeasure() {} 3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Assign a new path, or null to have none. 3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::setPath(const SkPath* path, bool forceClosed) { 3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPath = path; 3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; // signal we need to compute it 3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fForceClosed = forceClosed; 3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPtIndex = -1; 3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (path) { 3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fIter.setPath(*path, forceClosed); 3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegments.reset(); 3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::getLength() { 3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fPath == NULL) { 3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return 0; 3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fLength < 0) { 3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->buildSegments(); 3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fLength >= 0); 3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fLength; 4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkPathMeasure::Segment* SkPathMeasure::distanceToSegment( 4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance, SkScalar* t) { 4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(SkScalar length = ) this->getLength(); 4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(distance >= 0 && distance <= length); 4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = fSegments.begin(); 4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = fSegments.count(); 4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = SkTSearch<SkScalar>(&seg->fDistance, count, distance, 4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sizeof(Segment)); 4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // don't care if we hit an exact match or not, so we xor index if it is negative 4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project index ^= (index >> 31); 4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg = &seg[index]; 4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now interpolate t-values with the prev segment (if possible) 4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar startT = 0, startD = 0; 4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // check if the prev segment is legal, and references the same set of points 4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index > 0) { 4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startD = seg[-1].fDistance; 4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (seg[-1].fPtIndex == seg->fPtIndex) { 4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg[-1].fType == seg->fType); 4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startT = seg[-1].getScalarT(); 4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->getScalarT() > startT); 4280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(distance >= startD); 4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fDistance > startD); 4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *t = startT + SkScalarMulDiv(seg->getScalarT() - startT, 4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance - startD, 4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fDistance - startD); 4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return seg; 4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getPosTan(SkScalar distance, SkPoint* pos, 4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* tangent) { 4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fPath); 4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fPath == NULL) { 4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project EMPTY: 4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar length = this->getLength(); // call this to force computing it 4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = fSegments.count(); 4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (count == 0 || length == 0) { 4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project goto EMPTY; 4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // pin the distance to a legal range 4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (distance < 0) { 4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = 0; 4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else if (distance > length) { 4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = length; 4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar t; 4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = this->distanceToSegment(distance, &t); 4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project compute_pos_tan(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType, 4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project t, pos, tangent); 4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getMatrix(SkScalar distance, SkMatrix* matrix, 4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project MatrixFlags flags) { 4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint position; 4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector tangent; 4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->getPosTan(distance, &position, &tangent)) { 4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (matrix) { 4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (flags & kGetTangent_MatrixFlag) { 4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix->setSinCos(tangent.fY, tangent.fX, 0, 0); 4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix->reset(); 4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (flags & kGetPosition_MatrixFlag) { 4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix->postTranslate(position.fX, position.fY); 4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, 4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool startWithMoveTo) { 4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(dst); 4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar length = this->getLength(); // ensure we have built our segments 4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startD < 0) { 4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startD = 0; 4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopD > length) { 4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stopD = length; 4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startD >= stopD) { 5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint p; 5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar startT, stopT; 5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = this->distanceToSegment(startD, &startT); 5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* stopSeg = this->distanceToSegment(stopD, &stopT); 5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg <= stopSeg); 5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startWithMoveTo) { 5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project compute_pos_tan(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, 5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType, startT, &p, NULL); 5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->moveTo(p); 5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (seg->fPtIndex == stopSeg->fPtIndex) { 5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg_to(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType, 5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startT, stopT, dst); 5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg_to(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType, 5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startT, SK_Scalar1, dst); 5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg = SkPathMeasure::NextSegment(seg); 5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startT = 0; 5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (seg->fPtIndex < stopSeg->fPtIndex); 5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg_to(*fPath, fSegments[0].fPtIndex, seg->fPtIndex, seg->fType, 5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 0, stopT, dst); 5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::isClosed() { 5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (void)this->getLength(); 5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fIsClosed; 5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Move to the next contour in the path. Return true if one exists, or false if 5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project we're done with the path. 5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::nextContour() { 5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; 5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return this->getLength() > 0; 5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 5460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 5490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::dump() { 5510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("pathmeas: length=%g, segs=%d\n", fLength, fSegments.count()); 5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < fSegments.count(); i++) { 5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = &fSegments[i]; 5550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", 5560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), 5570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType); 5580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::UnitTest() { 5620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SUPPORT_UNITTEST 5630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath path; 5640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.moveTo(0, 0); 5660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.lineTo(SK_Scalar1, 0); 5670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.lineTo(SK_Scalar1, SK_Scalar1); 5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.lineTo(0, SK_Scalar1); 5690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPathMeasure meas(path, true); 5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar length = meas.getLength(); 5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(length == SK_Scalar1*4); 5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.reset(); 5750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.moveTo(0, 0); 5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.lineTo(SK_Scalar1*3, SK_Scalar1*4); 5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project meas.setPath(&path, false); 5780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project length = meas.getLength(); 5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(length == SK_Scalar1*5); 5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.reset(); 5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.addCircle(0, 0, SK_Scalar1); 5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project meas.setPath(&path, true); 5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project length = meas.getLength(); 5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("circle arc-length = %g\n", length); 5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < 8; i++) { 5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar d = length * i / 8; 5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint p; 5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector v; 5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project meas.getPosTan(d, &p, &v); 5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("circle arc-length=%g, pos[%g %g] tan[%g %g]\n", 5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project d, p.fX, p.fY, v.fX, v.fY); 5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 599