11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 20910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2008 The Android Open Source Project 40910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 91cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathMeasure.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGeometry.h" 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPath.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTSearch.h" 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// these must be 0,1,2 since they are in our 2-bit field 160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectenum { 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kLine_SegType, 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kQuad_SegType, 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kCubic_SegType 200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kMaxTValue 32767 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkScalar tValue2Scalar(int t) { 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)t <= kMaxTValue); 260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_SCALAR_IS_FLOAT 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return t * 3.05185e-5f; // t / 32767 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (t + (t >> 14)) << 1; 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::Segment::getScalarT() const { 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return tValue2Scalar(fTValue); 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkPathMeasure::Segment* SkPathMeasure::NextSegment(const Segment* seg) { 390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned ptIndex = seg->fPtIndex; 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ++seg; 430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (seg->fPtIndex == ptIndex); 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return seg; 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int tspan_big_enough(int tspan) { 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)tspan <= kMaxTValue); 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return tspan >> 10; 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if 0 550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool tangents_too_curvy(const SkVector& tan0, SkVector& tan1) { 560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static const SkScalar kFlatEnoughTangentDotProd = SK_Scalar1 * 99 / 100; 570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(kFlatEnoughTangentDotProd > 0 && 590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kFlatEnoughTangentDotProd < SK_Scalar1); 600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkPoint::DotProduct(tan0, tan1) < kFlatEnoughTangentDotProd; 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// can't use tangents, since we need [0..1..................2] to be seen 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// as definitely not a line (it is when drawn, but not parametrically) 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// so we compare midpoints 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define CHEAP_DIST_LIMIT (SK_Scalar1/2) // just made this value up 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool quad_too_curvy(const SkPoint pts[3]) { 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // diff = (a/4 + b/2 + c/4) - (a/2 + c/2) 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // diff = -a/4 + b/2 - c/4 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dx = SkScalarHalf(pts[1].fX) - 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarHalf(SkScalarHalf(pts[0].fX + pts[2].fX)); 750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dy = SkScalarHalf(pts[1].fY) - 760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarHalf(SkScalarHalf(pts[0].fY + pts[2].fY)); 770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dist = SkMaxScalar(SkScalarAbs(dx), SkScalarAbs(dy)); 790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return dist > CHEAP_DIST_LIMIT; 800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool cheap_dist_exceeds_limit(const SkPoint& pt, 830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar x, SkScalar y) { 840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY)); 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // just made up the 1/2 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return dist > CHEAP_DIST_LIMIT; 870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool cubic_too_curvy(const SkPoint pts[4]) { 900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return cheap_dist_exceeds_limit(pts[1], 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1/3), 920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1/3)) 930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project || 940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project cheap_dist_exceeds_limit(pts[2], 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1*2/3), 960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3)); 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3], 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance, int mint, int maxt, int ptIndex) { 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) { 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[5]; 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int halft = (mint + maxt) >> 1; 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAtHalf(pts, tmp); 1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_quad_segs(tmp, distance, mint, halft, ptIndex); 1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_quad_segs(&tmp[2], distance, halft, maxt, ptIndex); 1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar d = SkPoint::Distance(pts[0], pts[2]); 1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(d >= 0); 1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!SkScalarNearlyZero(d)) { 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance += d; 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Segment* seg = fSegments.append(); 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fDistance = distance; 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fPtIndex = ptIndex; 1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType = kQuad_SegType; 1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fTValue = maxt; 1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return distance; 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4], 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance, int mint, int maxt, int ptIndex) { 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) { 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp[7]; 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int halft = (mint + maxt) >> 1; 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAtHalf(pts, tmp); 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex); 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIndex); 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar d = SkPoint::Distance(pts[0], pts[3]); 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(d >= 0); 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!SkScalarNearlyZero(d)) { 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance += d; 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Segment* seg = fSegments.append(); 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fDistance = distance; 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fPtIndex = ptIndex; 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType = kCubic_SegType; 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fTValue = maxt; 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return distance; 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::buildSegments() { 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pts[4]; 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int ptIndex = fFirstPtIndex; 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar d, distance = 0; 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool isClosed = fForceClosed; 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool firstMoveTo = ptIndex < 0; 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Segment* seg; 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegments.reset(); 1564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger bool done = false; 1574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger do { 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (fIter.next(pts)) { 1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kMove_Verb: 1604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger ptIndex += 1; 1614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fPts.append(1, pts); 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!firstMoveTo) { 1634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger done = true; 1644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger break; 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1664f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger firstMoveTo = false; 1674f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger break; 1680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kLine_Verb: 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project d = SkPoint::Distance(pts[0], pts[1]); 1710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(d >= 0); 1724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger distance += d; 1734f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg = fSegments.append(); 1744f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg->fDistance = distance; 1754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg->fPtIndex = ptIndex; 1764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg->fType = kLine_SegType; 1774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg->fTValue = kMaxTValue; 1784f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fPts.append(1, pts + 1); 1794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger ptIndex++; 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 1810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kQuad_Verb: 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_quad_segs(pts, distance, 0, 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxTValue, ptIndex); 1854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fPts.append(2, pts + 1); 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex += 2; 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kCubic_Verb: 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = this->compute_cubic_segs(pts, distance, 0, 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project kMaxTValue, ptIndex); 1924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fPts.append(3, pts + 1); 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex += 3; 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kClose_Verb: 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project isClosed = true; 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kDone_Verb: 2014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger done = true; 2024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger break; 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } while (!done); 2054f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = distance; 2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fIsClosed = isClosed; 2084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fFirstPtIndex = ptIndex; 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = fSegments.begin(); 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* stop = fSegments.end(); 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned ptIndex = 0; 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance = 0; 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (seg < stop) { 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fDistance > distance); 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fPtIndex >= ptIndex); 2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fTValue > 0); 2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* s = seg; 2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (s < stop - 1 && s[0].fPtIndex == s[1].fPtIndex) { 2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(s[0].fType == s[1].fType); 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(s[0].fTValue < s[1].fTValue); 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project s += 1; 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = seg->fDistance; 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ptIndex = seg->fPtIndex; 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg += 1; 2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // SkDebugf("\n"); 2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void compute_pos_tan(const SkTDArray<SkPoint>& segmentPts, int ptIndex, 2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int segType, SkScalar t, SkPoint* pos, SkVector* tangent) { 2404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkPoint* pts = &segmentPts[ptIndex]; 2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (segType) { 2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_SegType: 2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (pos) { 2454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger pos->set(SkScalarInterp(pts[0].fX, pts[1].fX, t), 2464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalarInterp(pts[0].fY, pts[1].fY, t)); 2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tangent) { 2494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger tangent->setNormalize(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY); 2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_SegType: 2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkEvalQuadAt(pts, t, pos, tangent); 2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tangent) { 2550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tangent->normalize(); 2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_SegType: 2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkEvalCubicAt(pts, t, pos, tangent, NULL); 2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (tangent) { 2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tangent->normalize(); 2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("unknown segType"); 2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic void seg_to(const SkTDArray<SkPoint>& segmentPts, int ptIndex, 2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int segType, SkScalar startT, SkScalar stopT, SkPath* dst) { 2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(startT >= 0 && startT <= SK_Scalar1); 2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(stopT >= 0 && stopT <= SK_Scalar1); 2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(startT <= stopT); 2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkScalarNearlyZero(stopT - startT)) { 2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2794f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkPoint* pts = &segmentPts[ptIndex]; 2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint tmp0[7], tmp1[7]; 2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (segType) { 2830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kLine_SegType: 2840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == kMaxTValue) { 2854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger dst->lineTo(pts[1]); 2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 2874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger dst->lineTo(SkScalarInterp(pts[0].fX, pts[1].fX, stopT), 2884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalarInterp(pts[0].fY, pts[1].fY, stopT)); 2890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kQuad_SegType: 2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startT == 0) { 2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(pts[1], pts[2]); 2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAt(pts, tmp0, stopT); 2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(tmp0[1], tmp0[2]); 2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAt(pts, tmp0, startT); 3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(tmp0[3], tmp0[4]); 3030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopQuadAt(&tmp0[2], tmp1, SkScalarDiv(stopT - startT, 3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SK_Scalar1 - startT)); 3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(tmp1[1], tmp1[2]); 3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 3100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case kCubic_SegType: 3110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startT == 0) { 3120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(pts[1], pts[2], pts[3]); 3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAt(pts, tmp0, stopT); 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]); 3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAt(pts, tmp0, startT); 3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopT == SK_Scalar1) { 3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(tmp0[4], tmp0[5], tmp0[6]); 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkChopCubicAt(&tmp0[3], tmp1, SkScalarDiv(stopT - startT, 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SK_Scalar1 - startT)); 3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(tmp1[1], tmp1[2], tmp1[3]); 3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 3301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("unknown segType"); 3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_throw(); 3320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////// 3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////// 3370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::SkPathMeasure() { 3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPath = NULL; 3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; // signal we need to compute it 3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fForceClosed = false; 3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPtIndex = -1; 3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed) { 3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPath = &path; 3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; // signal we need to compute it 3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fForceClosed = forceClosed; 3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPtIndex = -1; 3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fIter.setPath(path, forceClosed); 3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkPathMeasure::~SkPathMeasure() {} 3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Assign a new path, or null to have none. 3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::setPath(const SkPath* path, bool forceClosed) { 3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPath = path; 3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; // signal we need to compute it 3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fForceClosed = forceClosed; 3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fFirstPtIndex = -1; 3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (path) { 3650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fIter.setPath(*path, forceClosed); 3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fSegments.reset(); 3684f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fPts.reset(); 3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkScalar SkPathMeasure::getLength() { 3720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fPath == NULL) { 3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return 0; 3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fLength < 0) { 3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->buildSegments(); 3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fLength >= 0); 3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fLength; 3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectconst SkPathMeasure::Segment* SkPathMeasure::distanceToSegment( 3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar distance, SkScalar* t) { 3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(SkScalar length = ) this->getLength(); 3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(distance >= 0 && distance <= length); 3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = fSegments.begin(); 3880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = fSegments.count(); 3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = SkTSearch<SkScalar>(&seg->fDistance, count, distance, 3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sizeof(Segment)); 3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // don't care if we hit an exact match or not, so we xor index if it is negative 3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project index ^= (index >> 31); 3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg = &seg[index]; 3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now interpolate t-values with the prev segment (if possible) 3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar startT = 0, startD = 0; 3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // check if the prev segment is legal, and references the same set of points 3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index > 0) { 4000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startD = seg[-1].fDistance; 4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (seg[-1].fPtIndex == seg->fPtIndex) { 4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg[-1].fType == seg->fType); 4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startT = seg[-1].getScalarT(); 4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->getScalarT() > startT); 4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(distance >= startD); 4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg->fDistance > startD); 4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *t = startT + SkScalarMulDiv(seg->getScalarT() - startT, 4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance - startD, 4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fDistance - startD); 4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return seg; 4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getPosTan(SkScalar distance, SkPoint* pos, 4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector* tangent) { 4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fPath); 4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fPath == NULL) { 4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar length = this->getLength(); // call this to force computing it 4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count = fSegments.count(); 4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (count == 0 || length == 0) { 4284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger return false; 4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // pin the distance to a legal range 4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (distance < 0) { 4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = 0; 4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else if (distance > length) { 4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project distance = length; 4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar t; 4390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = this->distanceToSegment(distance, &t); 4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger compute_pos_tan(fPts, seg->fPtIndex, seg->fType, t, pos, tangent); 4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 4430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getMatrix(SkScalar distance, SkMatrix* matrix, 4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project MatrixFlags flags) { 4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint position; 4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector tangent; 4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (this->getPosTan(distance, &position, &tangent)) { 4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (matrix) { 4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (flags & kGetTangent_MatrixFlag) { 4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix->setSinCos(tangent.fY, tangent.fX, 0, 0); 4540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 4550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix->reset(); 4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (flags & kGetPosition_MatrixFlag) { 4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix->postTranslate(position.fX, position.fY); 4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 4640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, 4670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool startWithMoveTo) { 4680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(dst); 4690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar length = this->getLength(); // ensure we have built our segments 4710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startD < 0) { 4730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startD = 0; 4740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (stopD > length) { 4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stopD = length; 4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startD >= stopD) { 4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint p; 4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar startT, stopT; 4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = this->distanceToSegment(startD, &startT); 4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* stopSeg = this->distanceToSegment(stopD, &stopT); 4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(seg <= stopSeg); 4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (startWithMoveTo) { 4894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger compute_pos_tan(fPts, seg->fPtIndex, seg->fType, startT, &p, NULL); 4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->moveTo(p); 4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (seg->fPtIndex == stopSeg->fPtIndex) { 4944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg_to(fPts, seg->fPtIndex, seg->fType, startT, stopT, dst); 4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 4974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg_to(fPts, seg->fPtIndex, seg->fType, startT, SK_Scalar1, dst); 4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg = SkPathMeasure::NextSegment(seg); 4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project startT = 0; 5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (seg->fPtIndex < stopSeg->fPtIndex); 5014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger seg_to(fPts, seg->fPtIndex, seg->fType, 0, stopT, dst); 5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::isClosed() { 5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (void)this->getLength(); 5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fIsClosed; 5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/** Move to the next contour in the path. Return true if one exists, or false if 5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project we're done with the path. 5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkPathMeasure::nextContour() { 5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fLength = -1; 5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return this->getLength() > 0; 5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkPathMeasure::dump() { 5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("pathmeas: length=%g, segs=%d\n", fLength, fSegments.count()); 5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < fSegments.count(); i++) { 5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const Segment* seg = &fSegments[i]; 5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", 5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), 5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project seg->fType); 5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 536