1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2008 The Android Open Source Project 4bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 8bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 9685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPathMeasure.h" 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkGeometry.h" 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPath.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTSearch.h" 14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// these must be 0,1,2 since they are in our 2-bit field 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comenum { 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kLine_SegType, 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kQuad_SegType, 19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kCubic_SegType 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 22bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define kMaxTValue 32767 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 24bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline SkScalar tValue2Scalar(int t) { 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)t <= kMaxTValue); 26bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 27bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_SCALAR_IS_FLOAT 28bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return t * 3.05185e-5f; // t / 32767 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#else 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (t + (t >> 14)) << 1; 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 32bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 33bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkScalar SkPathMeasure::Segment::getScalarT() const { 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return tValue2Scalar(fTValue); 36bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 37bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 38bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkPathMeasure::Segment* SkPathMeasure::NextSegment(const Segment* seg) { 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned ptIndex = seg->fPtIndex; 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 41bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com do { 42bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ++seg; 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } while (seg->fPtIndex == ptIndex); 44bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return seg; 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic inline int tspan_big_enough(int tspan) { 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((unsigned)tspan <= kMaxTValue); 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return tspan >> 10; 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// can't use tangents, since we need [0..1..................2] to be seen 55bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// as definitely not a line (it is when drawn, but not parametrically) 56bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com// so we compare midpoints 57bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define CHEAP_DIST_LIMIT (SK_Scalar1/2) // just made this value up 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic bool quad_too_curvy(const SkPoint pts[3]) { 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // diff = (a/4 + b/2 + c/4) - (a/2 + c/2) 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // diff = -a/4 + b/2 - c/4 62bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar dx = SkScalarHalf(pts[1].fX) - 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalarHalf(SkScalarHalf(pts[0].fX + pts[2].fX)); 64bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar dy = SkScalarHalf(pts[1].fY) - 65bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalarHalf(SkScalarHalf(pts[0].fY + pts[2].fY)); 66bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 67bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar dist = SkMaxScalar(SkScalarAbs(dx), SkScalarAbs(dy)); 68bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return dist > CHEAP_DIST_LIMIT; 69bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic bool cheap_dist_exceeds_limit(const SkPoint& pt, 72bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar x, SkScalar y) { 73bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar dist = SkMaxScalar(SkScalarAbs(x - pt.fX), SkScalarAbs(y - pt.fY)); 74bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // just made up the 1/2 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return dist > CHEAP_DIST_LIMIT; 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comstatic bool cubic_too_curvy(const SkPoint pts[4]) { 79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return cheap_dist_exceeds_limit(pts[1], 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1/3), 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1/3)) 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com || 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cheap_dist_exceeds_limit(pts[2], 84bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalarInterp(pts[0].fX, pts[3].fX, SK_Scalar1*2/3), 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalarInterp(pts[0].fY, pts[3].fY, SK_Scalar1*2/3)); 86bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 88bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkScalar SkPathMeasure::compute_quad_segs(const SkPoint pts[3], 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar distance, int mint, int maxt, int ptIndex) { 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (tspan_big_enough(maxt - mint) && quad_too_curvy(pts)) { 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPoint tmp[5]; 92bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int halft = (mint + maxt) >> 1; 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopQuadAtHalf(pts, tmp); 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = this->compute_quad_segs(tmp, distance, mint, halft, ptIndex); 96bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = this->compute_quad_segs(&tmp[2], distance, halft, maxt, ptIndex); 97bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar d = SkPoint::Distance(pts[0], pts[2]); 99839341811ba8026eca7f6e39eeb654eca7971461reed@google.com SkScalar prevD = distance; 100839341811ba8026eca7f6e39eeb654eca7971461reed@google.com distance += d; 101839341811ba8026eca7f6e39eeb654eca7971461reed@google.com if (distance > prevD) { 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Segment* seg = fSegments.append(); 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fDistance = distance; 104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fPtIndex = ptIndex; 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fType = kQuad_SegType; 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fTValue = maxt; 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return distance; 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkScalar SkPathMeasure::compute_cubic_segs(const SkPoint pts[4], 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar distance, int mint, int maxt, int ptIndex) { 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (tspan_big_enough(maxt - mint) && cubic_too_curvy(pts)) { 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPoint tmp[7]; 116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int halft = (mint + maxt) >> 1; 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopCubicAtHalf(pts, tmp); 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = this->compute_cubic_segs(tmp, distance, mint, halft, ptIndex); 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = this->compute_cubic_segs(&tmp[3], distance, halft, maxt, ptIndex); 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar d = SkPoint::Distance(pts[0], pts[3]); 123839341811ba8026eca7f6e39eeb654eca7971461reed@google.com SkScalar prevD = distance; 124839341811ba8026eca7f6e39eeb654eca7971461reed@google.com distance += d; 125839341811ba8026eca7f6e39eeb654eca7971461reed@google.com if (distance > prevD) { 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Segment* seg = fSegments.append(); 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fDistance = distance; 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fPtIndex = ptIndex; 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fType = kCubic_SegType; 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fTValue = maxt; 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return distance; 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPathMeasure::buildSegments() { 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPoint pts[4]; 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int ptIndex = fFirstPtIndex; 13967b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com SkScalar distance = 0; 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool isClosed = fForceClosed; 141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool firstMoveTo = ptIndex < 0; 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Segment* seg; 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 14467b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com /* Note: 14567b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com * as we accumulate distance, we have to check that the result of += 14667b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com * actually made it larger, since a very small delta might be > 0, but 14767b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com * still have no effect on distance (if distance >>> delta). 148839341811ba8026eca7f6e39eeb654eca7971461reed@google.com * 149839341811ba8026eca7f6e39eeb654eca7971461reed@google.com * We do this check below, and in compute_quad_segs and compute_cubic_segs 15067b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com */ 151bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fSegments.reset(); 152ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org bool done = false; 153ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org do { 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (fIter.next(pts)) { 1556cae19e7539368fe697eb353d7e6197f027bc8dareed@google.com case SkPath::kConic_Verb: 1566cae19e7539368fe697eb353d7e6197f027bc8dareed@google.com SkASSERT(0); 1576cae19e7539368fe697eb353d7e6197f027bc8dareed@google.com break; 158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkPath::kMove_Verb: 159ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org ptIndex += 1; 160ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org fPts.append(1, pts); 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (!firstMoveTo) { 162ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org done = true; 163ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org break; 164bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 165ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org firstMoveTo = false; 166ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org break; 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 16867b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com case SkPath::kLine_Verb: { 16967b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com SkScalar d = SkPoint::Distance(pts[0], pts[1]); 170bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(d >= 0); 17167b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com SkScalar prevD = distance; 172ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org distance += d; 17367b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com if (distance > prevD) { 17467b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com seg = fSegments.append(); 17567b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com seg->fDistance = distance; 17667b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com seg->fPtIndex = ptIndex; 17767b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com seg->fType = kLine_SegType; 17867b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com seg->fTValue = kMaxTValue; 17967b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com fPts.append(1, pts + 1); 18067b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com ptIndex++; 18167b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com } 18267b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com } break; 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 18467b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com case SkPath::kQuad_Verb: { 18567b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com SkScalar prevD = distance; 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = this->compute_quad_segs(pts, distance, 0, 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kMaxTValue, ptIndex); 18867b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com if (distance > prevD) { 18967b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com fPts.append(2, pts + 1); 19067b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com ptIndex += 2; 19167b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com } 19267b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com } break; 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 19467b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com case SkPath::kCubic_Verb: { 19567b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com SkScalar prevD = distance; 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = this->compute_cubic_segs(pts, distance, 0, 197bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kMaxTValue, ptIndex); 19867b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com if (distance > prevD) { 19967b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com fPts.append(3, pts + 1); 20067b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com ptIndex += 3; 20167b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com } 20267b63a2f8aa3d3e6053c75e9de7f63887f5d496freed@google.com } break; 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkPath::kClose_Verb: 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com isClosed = true; 206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 207935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case SkPath::kDone_Verb: 209ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org done = true; 210ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org break; 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 212ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org } while (!done); 213ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLength = distance; 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fIsClosed = isClosed; 216ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org fFirstPtIndex = ptIndex; 217bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* seg = fSegments.begin(); 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* stop = fSegments.end(); 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned ptIndex = 0; 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar distance = 0; 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (seg < stop) { 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(seg->fDistance > distance); 227bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(seg->fPtIndex >= ptIndex); 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(seg->fTValue > 0); 229bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 230bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* s = seg; 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (s < stop - 1 && s[0].fPtIndex == s[1].fPtIndex) { 232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(s[0].fType == s[1].fType); 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(s[0].fTValue < s[1].fTValue); 234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com s += 1; 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = seg->fDistance; 238bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ptIndex = seg->fPtIndex; 239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg += 1; 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // SkDebugf("\n"); 242bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 243bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 244bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2466c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.comstatic void compute_pos_tan(const SkPoint pts[], int segType, 2476c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com SkScalar t, SkPoint* pos, SkVector* tangent) { 248bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (segType) { 249bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kLine_SegType: 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (pos) { 251ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org pos->set(SkScalarInterp(pts[0].fX, pts[1].fX, t), 2526c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com SkScalarInterp(pts[0].fY, pts[1].fY, t)); 253bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (tangent) { 255ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org tangent->setNormalize(pts[1].fX - pts[0].fX, pts[1].fY - pts[0].fY); 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kQuad_SegType: 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEvalQuadAt(pts, t, pos, tangent); 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (tangent) { 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tangent->normalize(); 262bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kCubic_SegType: 265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkEvalCubicAt(pts, t, pos, tangent, NULL); 266bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (tangent) { 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com tangent->normalize(); 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 270bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 2712d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unknown segType"); 272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 273bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2756c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.comstatic void seg_to(const SkPoint pts[], int segType, 2766c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com SkScalar startT, SkScalar stopT, SkPath* dst) { 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(startT >= 0 && startT <= SK_Scalar1); 278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(stopT >= 0 && stopT <= SK_Scalar1); 279bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(startT <= stopT); 280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 28182d0b008b242b56745403e86bf33b459745bbb4dreed@google.com if (startT == stopT) { 28282d0b008b242b56745403e86bf33b459745bbb4dreed@google.com return; // should we report this, to undo a moveTo? 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 284bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPoint tmp0[7], tmp1[7]; 286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 287bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com switch (segType) { 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kLine_SegType: 28951651bf077c6f79e0d5a8cdd43468147fe5cd649reed@google.com if (SK_Scalar1 == stopT) { 290ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org dst->lineTo(pts[1]); 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 292ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org dst->lineTo(SkScalarInterp(pts[0].fX, pts[1].fX, stopT), 293ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org SkScalarInterp(pts[0].fY, pts[1].fY, stopT)); 294bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 296bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kQuad_SegType: 29751651bf077c6f79e0d5a8cdd43468147fe5cd649reed@google.com if (0 == startT) { 29851651bf077c6f79e0d5a8cdd43468147fe5cd649reed@google.com if (SK_Scalar1 == stopT) { 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->quadTo(pts[1], pts[2]); 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 301bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopQuadAt(pts, tmp0, stopT); 302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->quadTo(tmp0[1], tmp0[2]); 303bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopQuadAt(pts, tmp0, startT); 30651651bf077c6f79e0d5a8cdd43468147fe5cd649reed@google.com if (SK_Scalar1 == stopT) { 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->quadTo(tmp0[3], tmp0[4]); 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopQuadAt(&tmp0[2], tmp1, SkScalarDiv(stopT - startT, 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SK_Scalar1 - startT)); 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->quadTo(tmp1[1], tmp1[2]); 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 315bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com case kCubic_SegType: 31651651bf077c6f79e0d5a8cdd43468147fe5cd649reed@google.com if (0 == startT) { 31751651bf077c6f79e0d5a8cdd43468147fe5cd649reed@google.com if (SK_Scalar1 == stopT) { 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->cubicTo(pts[1], pts[2], pts[3]); 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopCubicAt(pts, tmp0, stopT); 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->cubicTo(tmp0[1], tmp0[2], tmp0[3]); 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopCubicAt(pts, tmp0, startT); 32551651bf077c6f79e0d5a8cdd43468147fe5cd649reed@google.com if (SK_Scalar1 == stopT) { 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->cubicTo(tmp0[4], tmp0[5], tmp0[6]); 327bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkChopCubicAt(&tmp0[3], tmp1, SkScalarDiv(stopT - startT, 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SK_Scalar1 - startT)); 330bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->cubicTo(tmp1[1], tmp1[2], tmp1[3]); 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 332bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com default: 3352d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unknown segType"); 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_throw(); 337bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 339bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 340bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//////////////////////////////////////////////////////////////////////////////// 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//////////////////////////////////////////////////////////////////////////////// 342bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkPathMeasure::SkPathMeasure() { 344bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPath = NULL; 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLength = -1; // signal we need to compute it 346bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fForceClosed = false; 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fFirstPtIndex = -1; 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 349bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkPathMeasure::SkPathMeasure(const SkPath& path, bool forceClosed) { 351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPath = &path; 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLength = -1; // signal we need to compute it 353bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fForceClosed = forceClosed; 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fFirstPtIndex = -1; 355bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fIter.setPath(path, forceClosed); 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 358bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 359bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkPathMeasure::~SkPathMeasure() {} 360bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 361bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/** Assign a new path, or null to have none. 362bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/ 363bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPathMeasure::setPath(const SkPath* path, bool forceClosed) { 364bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPath = path; 365bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLength = -1; // signal we need to compute it 366bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fForceClosed = forceClosed; 367bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fFirstPtIndex = -1; 368bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 369bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (path) { 370bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fIter.setPath(*path, forceClosed); 371bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fSegments.reset(); 373ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org fPts.reset(); 374bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkScalar SkPathMeasure::getLength() { 377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fPath == NULL) { 378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return 0; 379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (fLength < 0) { 381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->buildSegments(); 382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 383bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fLength >= 0); 384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fLength; 385bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 386bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 387bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst SkPathMeasure::Segment* SkPathMeasure::distanceToSegment( 388bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar distance, SkScalar* t) { 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(SkScalar length = ) this->getLength(); 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(distance >= 0 && distance <= length); 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* seg = fSegments.begin(); 393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int count = fSegments.count(); 394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 395caf8693aa69b3afc94fd73059bc15417255046d0bsalomon@google.com int index = SkTSearch<SkScalar>(&seg->fDistance, count, distance, sizeof(Segment)); 396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // don't care if we hit an exact match or not, so we xor index if it is negative 397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com index ^= (index >> 31); 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg = &seg[index]; 399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now interpolate t-values with the prev segment (if possible) 401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar startT = 0, startD = 0; 402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // check if the prev segment is legal, and references the same set of points 403bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (index > 0) { 404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com startD = seg[-1].fDistance; 405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (seg[-1].fPtIndex == seg->fPtIndex) { 406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(seg[-1].fType == seg->fType); 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com startT = seg[-1].getScalarT(); 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(seg->getScalarT() > startT); 412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(distance >= startD); 413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(seg->fDistance > startD); 414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *t = startT + SkScalarMulDiv(seg->getScalarT() - startT, 416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance - startD, 417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fDistance - startD); 418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return seg; 419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPathMeasure::getPosTan(SkScalar distance, SkPoint* pos, 422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkVector* tangent) { 423cba822f0c18ef67566ce11f5bf1183192c29aa70djsollen@google.com if (NULL == fPath) { 424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar length = this->getLength(); // call this to force computing it 428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int count = fSegments.count(); 429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (count == 0 || length == 0) { 431ef7f0ecebfaa39e8a3b8a3011448e3e35eb71134schenney@chromium.org return false; 432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // pin the distance to a legal range 435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (distance < 0) { 436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = 0; 437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else if (distance > length) { 438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com distance = length; 439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 440935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar t; 442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* seg = this->distanceToSegment(distance, &t); 443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 4446c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com compute_pos_tan(&fPts[seg->fPtIndex], seg->fType, t, pos, tangent); 445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPathMeasure::getMatrix(SkScalar distance, SkMatrix* matrix, 449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com MatrixFlags flags) { 450cba822f0c18ef67566ce11f5bf1183192c29aa70djsollen@google.com if (NULL == fPath) { 451cba822f0c18ef67566ce11f5bf1183192c29aa70djsollen@google.com return false; 452cba822f0c18ef67566ce11f5bf1183192c29aa70djsollen@google.com } 453cba822f0c18ef67566ce11f5bf1183192c29aa70djsollen@google.com 454bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPoint position; 455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkVector tangent; 456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (this->getPosTan(distance, &position, &tangent)) { 458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (matrix) { 459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (flags & kGetTangent_MatrixFlag) { 460bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->setSinCos(tangent.fY, tangent.fX, 0, 0); 461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->reset(); 463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (flags & kGetPosition_MatrixFlag) { 465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com matrix->postTranslate(position.fX, position.fY); 466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 469bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPathMeasure::getSegment(SkScalar startD, SkScalar stopD, SkPath* dst, 474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bool startWithMoveTo) { 475bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(dst); 476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar length = this->getLength(); // ensure we have built our segments 478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (startD < 0) { 480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com startD = 0; 481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (stopD > length) { 483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com stopD = length; 484bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 485bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (startD >= stopD) { 486bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return false; 487bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 488bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 489bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPoint p; 490bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkScalar startT, stopT; 491bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* seg = this->distanceToSegment(startD, &startT); 492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* stopSeg = this->distanceToSegment(stopD, &stopT); 493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(seg <= stopSeg); 494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (startWithMoveTo) { 4966c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com compute_pos_tan(&fPts[seg->fPtIndex], seg->fType, startT, &p, NULL); 497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com dst->moveTo(p); 498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 500bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (seg->fPtIndex == stopSeg->fPtIndex) { 5016c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com seg_to(&fPts[seg->fPtIndex], seg->fType, startT, stopT, dst); 502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } else { 503bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com do { 5046c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com seg_to(&fPts[seg->fPtIndex], seg->fType, startT, SK_Scalar1, dst); 505bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg = SkPathMeasure::NextSegment(seg); 506bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com startT = 0; 507bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } while (seg->fPtIndex < stopSeg->fPtIndex); 5086c9435ca6bbfa1cd040133867767d4bc4cfb1f1breed@google.com seg_to(&fPts[seg->fPtIndex], seg->fType, 0, stopT, dst); 509bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 510bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return true; 511bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 512bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 513bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPathMeasure::isClosed() { 514bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com (void)this->getLength(); 515bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fIsClosed; 516bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 517bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 518bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/** Move to the next contour in the path. Return true if one exists, or false if 519bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com we're done with the path. 520bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com*/ 521bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.combool SkPathMeasure::nextContour() { 522bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLength = -1; 523bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return this->getLength() > 0; 524bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 525bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkPathMeasure::dump() { 532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("pathmeas: length=%g, segs=%d\n", fLength, fSegments.count()); 533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com for (int i = 0; i < fSegments.count(); i++) { 535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const Segment* seg = &fSegments[i]; 536bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDebugf("pathmeas: seg[%d] distance=%g, point=%d, t=%g, type=%d\n", 537bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com i, seg->fDistance, seg->fPtIndex, seg->getScalarT(), 538bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com seg->fType); 539bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 540bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 541bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 542bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 543