17839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/* 27839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Copyright 2012 Google Inc. 37839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * 47839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be 57839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * found in the LICENSE file. 67839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */ 77839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkPathOpsLine.h" 87839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 97839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkDLine SkDLine::subDivide(double t1, double t2) const { 107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkDVector delta = tangent(); 117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkDLine dst = {{{ 127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fPts[0].fX - t1 * delta.fX, fPts[0].fY - t1 * delta.fY}, { 137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger fPts[0].fX - t2 * delta.fX, fPts[0].fY - t2 * delta.fY}}}; 147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return dst; 157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// may have this below somewhere else already: 187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// copying here because I thought it was clever 197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Copyright 2001, softSurfer (www.softsurfer.com) 217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// This code may be freely used and modified for any purpose 227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// providing that this copyright notice is included with it. 237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// SoftSurfer makes no warranty for this code, and cannot be held 247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// liable for any real or imagined damage resulting from its use. 257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Users of this code must verify correctness for their application. 267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Assume that a class is already given for the object: 287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Point with coordinates {float x, y;} 297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger//=================================================================== 307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// isLeft(): tests if a point is Left|On|Right of an infinite line. 327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Input: three points P0, P1, and P2 337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// Return: >0 for P2 left of the line through P0 and P1 347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// =0 for P2 on the line 357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// <0 for P2 right of the line 367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// See: the January 2001 Algorithm on Area of Triangles 377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// return (float) ((P1.x - P0.x)*(P2.y - P0.y) - (P2.x - P0.x)*(P1.y - P0.y)); 387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerdouble SkDLine::isLeft(const SkDPoint& pt) const { 397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkDVector p0 = fPts[1] - fPts[0]; 407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkDVector p2 = pt - fPts[0]; 417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return p0.cross(p2); 427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger 4458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek SollenbergerSkDPoint SkDLine::ptAtT(double t) const { 4558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (0 == t) { 4658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return fPts[0]; 4758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 4858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (1 == t) { 4958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return fPts[1]; 5058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger double one_t = 1 - t; 527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger SkDPoint result = { one_t * fPts[0].fX + t * fPts[1].fX, one_t * fPts[0].fY + t * fPts[1].fY }; 537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger return result; 547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger} 5558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdouble SkDLine::exactPoint(const SkDPoint& xy) const { 5758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy == fPts[0]) { // do cheapest test first 5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return 0; 5958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 6058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy == fPts[1]) { 6158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return 1; 6258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 6358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 6458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 6558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 6658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdouble SkDLine::nearPoint(const SkDPoint& xy) const { 6758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!AlmostBetweenUlps(fPts[0].fX, xy.fX, fPts[1].fX) 6858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger || !AlmostBetweenUlps(fPts[0].fY, xy.fY, fPts[1].fY)) { 6958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 7058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 7158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // project a perpendicular ray from the point to the line; find the T on the line 7258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line 7358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay 7458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkDVector ab0 = xy - fPts[0]; 7558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger double numer = len.fX * ab0.fX + ab0.fY * len.fY; 7658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!between(0, numer, denom)) { 7758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 7858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 7958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger double t = numer / denom; 8058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkDPoint realPt = ptAtT(t); 810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against distSq instead ? 8258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // find the ordinal in the original line with the largest unsigned exponent 8358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); 8458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); 8558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger largest = SkTMax(largest, -tiniest); 8658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? 8758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 8858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 8958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger t = SkPinT(t); 9058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(between(0, t, 1)); 9158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return t; 9258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 9358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerbool SkDLine::nearRay(const SkDPoint& xy) const { 950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // project a perpendicular ray from the point to the line; find the T on the line 960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line 970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay 980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDVector ab0 = xy - fPts[0]; 990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double numer = len.fX * ab0.fX + ab0.fY * len.fY; 1000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double t = numer / denom; 1010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDPoint realPt = ptAtT(t); 1020a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against distSq instead ? 1030a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger // find the ordinal in the original line with the largest unsigned exponent 1040a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double tiniest = SkTMin(SkTMin(SkTMin(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); 1050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double largest = SkTMax(SkTMax(SkTMax(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); 1060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger largest = SkTMax(largest, -tiniest); 1070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance? 1080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 1090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger// Returns true if a ray from (0,0) to (x1,y1) is coincident with a ray (0,0) to (x2,y2) 1110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger// OPTIMIZE: a specialty routine could speed this up -- may not be called very often though 1120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergerbool SkDLine::NearRay(double x1, double y1, double x2, double y2) { 1130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double denom1 = x1 * x1 + y1 * y1; 1140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double denom2 = x2 * x2 + y2 * y2; 1150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDLine line = {{{0, 0}, {x1, y1}}}; 1160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDPoint pt = {x2, y2}; 1170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (denom2 > denom1) { 1180a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkTSwap(line[1], pt); 1190a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 1200a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return line.nearRay(pt); 1210a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 1220a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 12358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdouble SkDLine::ExactPointH(const SkDPoint& xy, double left, double right, double y) { 12458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy.fY == y) { 12558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy.fX == left) { 12658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return 0; 12758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 12858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy.fX == right) { 12958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return 1; 13058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 13158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 13258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 13358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 13458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 13558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdouble SkDLine::NearPointH(const SkDPoint& xy, double left, double right, double y) { 1360a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!AlmostBequalUlps(xy.fY, y)) { 13758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 13858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 13958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!AlmostBetweenUlps(left, xy.fX, right)) { 14058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 14158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 14258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger double t = (xy.fX - left) / (right - left); 14358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger t = SkPinT(t); 14458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(between(0, t, 1)); 1450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double realPtX = (1 - t) * left + t * right; 1460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDVector distU = {xy.fY - y, xy.fX - realPtX}; 1470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double distSq = distU.fX * distU.fX + distU.fY * distU.fY; 1480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? 1490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double tiniest = SkTMin(SkTMin(y, left), right); 1500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double largest = SkTMax(SkTMax(y, left), right); 1510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger largest = SkTMax(largest, -tiniest); 1520a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? 1530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return -1; 1540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 15558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return t; 15658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 15758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 15858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdouble SkDLine::ExactPointV(const SkDPoint& xy, double top, double bottom, double x) { 15958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy.fX == x) { 16058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy.fY == top) { 16158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return 0; 16258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 16358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (xy.fY == bottom) { 16458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return 1; 16558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 16658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 16758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 16858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 16958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 17058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenbergerdouble SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double x) { 1710a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!AlmostBequalUlps(xy.fX, x)) { 17258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 17358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 17458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger if (!AlmostBetweenUlps(top, xy.fY, bottom)) { 17558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return -1; 17658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 17758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger double t = (xy.fY - top) / (bottom - top); 17858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger t = SkPinT(t); 17958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger SkASSERT(between(0, t, 1)); 1800a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double realPtY = (1 - t) * top + t * bottom; 1810a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDVector distU = {xy.fX - x, xy.fY - realPtY}; 1820a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double distSq = distU.fX * distU.fX + distU.fY * distU.fY; 1830a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? 1840a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double tiniest = SkTMin(SkTMin(x, top), bottom); 1850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger double largest = SkTMax(SkTMax(x, top), bottom); 1860a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger largest = SkTMax(largest, -tiniest); 1870a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? 1880a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger return -1; 1890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger } 19058190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return t; 19158190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger} 1920a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger 1930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#ifdef SK_DEBUG 1940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenbergervoid SkDLine::dump() { 1950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("{{"); 1960a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fPts[0].dump(); 1970a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf(", "); 1980a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger fPts[1].dump(); 1990a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger SkDebugf("}}\n"); 2000a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger} 2010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#endif 202