1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci#include "src/pathops/SkIntersections.h" 8cb93a386Sopenharmony_ci#include "src/pathops/SkPathOpsConic.h" 9cb93a386Sopenharmony_ci#include "src/pathops/SkPathOpsCurve.h" 10cb93a386Sopenharmony_ci#include "src/pathops/SkPathOpsLine.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ciclass LineConicIntersections { 13cb93a386Sopenharmony_cipublic: 14cb93a386Sopenharmony_ci enum PinTPoint { 15cb93a386Sopenharmony_ci kPointUninitialized, 16cb93a386Sopenharmony_ci kPointInitialized 17cb93a386Sopenharmony_ci }; 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci LineConicIntersections(const SkDConic& c, const SkDLine& l, SkIntersections* i) 20cb93a386Sopenharmony_ci : fConic(c) 21cb93a386Sopenharmony_ci , fLine(&l) 22cb93a386Sopenharmony_ci , fIntersections(i) 23cb93a386Sopenharmony_ci , fAllowNear(true) { 24cb93a386Sopenharmony_ci i->setMax(4); // allow short partial coincidence plus discrete intersection 25cb93a386Sopenharmony_ci } 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci LineConicIntersections(const SkDConic& c) 28cb93a386Sopenharmony_ci : fConic(c) 29cb93a386Sopenharmony_ci SkDEBUGPARAMS(fLine(nullptr)) 30cb93a386Sopenharmony_ci SkDEBUGPARAMS(fIntersections(nullptr)) 31cb93a386Sopenharmony_ci SkDEBUGPARAMS(fAllowNear(false)) { 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci void allowNear(bool allow) { 35cb93a386Sopenharmony_ci fAllowNear = allow; 36cb93a386Sopenharmony_ci } 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci void checkCoincident() { 39cb93a386Sopenharmony_ci int last = fIntersections->used() - 1; 40cb93a386Sopenharmony_ci for (int index = 0; index < last; ) { 41cb93a386Sopenharmony_ci double conicMidT = ((*fIntersections)[0][index] + (*fIntersections)[0][index + 1]) / 2; 42cb93a386Sopenharmony_ci SkDPoint conicMidPt = fConic.ptAtT(conicMidT); 43cb93a386Sopenharmony_ci double t = fLine->nearPoint(conicMidPt, nullptr); 44cb93a386Sopenharmony_ci if (t < 0) { 45cb93a386Sopenharmony_ci ++index; 46cb93a386Sopenharmony_ci continue; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci if (fIntersections->isCoincident(index)) { 49cb93a386Sopenharmony_ci fIntersections->removeOne(index); 50cb93a386Sopenharmony_ci --last; 51cb93a386Sopenharmony_ci } else if (fIntersections->isCoincident(index + 1)) { 52cb93a386Sopenharmony_ci fIntersections->removeOne(index + 1); 53cb93a386Sopenharmony_ci --last; 54cb93a386Sopenharmony_ci } else { 55cb93a386Sopenharmony_ci fIntersections->setCoincident(index++); 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci fIntersections->setCoincident(index); 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci#ifdef SK_DEBUG 62cb93a386Sopenharmony_ci static bool close_to(double a, double b, const double c[3]) { 63cb93a386Sopenharmony_ci double max = std::max(-std::min(std::min(c[0], c[1]), c[2]), std::max(std::max(c[0], c[1]), c[2])); 64cb93a386Sopenharmony_ci return approximately_zero_when_compared_to(a - b, max); 65cb93a386Sopenharmony_ci } 66cb93a386Sopenharmony_ci#endif 67cb93a386Sopenharmony_ci int horizontalIntersect(double axisIntercept, double roots[2]) { 68cb93a386Sopenharmony_ci double conicVals[] = { fConic[0].fY, fConic[1].fY, fConic[2].fY }; 69cb93a386Sopenharmony_ci return this->validT(conicVals, axisIntercept, roots); 70cb93a386Sopenharmony_ci } 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_ci int horizontalIntersect(double axisIntercept, double left, double right, bool flipped) { 73cb93a386Sopenharmony_ci this->addExactHorizontalEndPoints(left, right, axisIntercept); 74cb93a386Sopenharmony_ci if (fAllowNear) { 75cb93a386Sopenharmony_ci this->addNearHorizontalEndPoints(left, right, axisIntercept); 76cb93a386Sopenharmony_ci } 77cb93a386Sopenharmony_ci double roots[2]; 78cb93a386Sopenharmony_ci int count = this->horizontalIntersect(axisIntercept, roots); 79cb93a386Sopenharmony_ci for (int index = 0; index < count; ++index) { 80cb93a386Sopenharmony_ci double conicT = roots[index]; 81cb93a386Sopenharmony_ci SkDPoint pt = fConic.ptAtT(conicT); 82cb93a386Sopenharmony_ci SkDEBUGCODE(double conicVals[] = { fConic[0].fY, fConic[1].fY, fConic[2].fY }); 83cb93a386Sopenharmony_ci SkOPOBJASSERT(fIntersections, close_to(pt.fY, axisIntercept, conicVals)); 84cb93a386Sopenharmony_ci double lineT = (pt.fX - left) / (right - left); 85cb93a386Sopenharmony_ci if (this->pinTs(&conicT, &lineT, &pt, kPointInitialized) 86cb93a386Sopenharmony_ci && this->uniqueAnswer(conicT, pt)) { 87cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, pt); 88cb93a386Sopenharmony_ci } 89cb93a386Sopenharmony_ci } 90cb93a386Sopenharmony_ci if (flipped) { 91cb93a386Sopenharmony_ci fIntersections->flip(); 92cb93a386Sopenharmony_ci } 93cb93a386Sopenharmony_ci this->checkCoincident(); 94cb93a386Sopenharmony_ci return fIntersections->used(); 95cb93a386Sopenharmony_ci } 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_ci int intersect() { 98cb93a386Sopenharmony_ci this->addExactEndPoints(); 99cb93a386Sopenharmony_ci if (fAllowNear) { 100cb93a386Sopenharmony_ci this->addNearEndPoints(); 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci double rootVals[2]; 103cb93a386Sopenharmony_ci int roots = this->intersectRay(rootVals); 104cb93a386Sopenharmony_ci for (int index = 0; index < roots; ++index) { 105cb93a386Sopenharmony_ci double conicT = rootVals[index]; 106cb93a386Sopenharmony_ci double lineT = this->findLineT(conicT); 107cb93a386Sopenharmony_ci#ifdef SK_DEBUG 108cb93a386Sopenharmony_ci if (!fIntersections->globalState() 109cb93a386Sopenharmony_ci || !fIntersections->globalState()->debugSkipAssert()) { 110cb93a386Sopenharmony_ci SkDEBUGCODE(SkDPoint conicPt = fConic.ptAtT(conicT)); 111cb93a386Sopenharmony_ci SkDEBUGCODE(SkDPoint linePt = fLine->ptAtT(lineT)); 112cb93a386Sopenharmony_ci SkASSERT(conicPt.approximatelyDEqual(linePt)); 113cb93a386Sopenharmony_ci } 114cb93a386Sopenharmony_ci#endif 115cb93a386Sopenharmony_ci SkDPoint pt; 116cb93a386Sopenharmony_ci if (this->pinTs(&conicT, &lineT, &pt, kPointUninitialized) 117cb93a386Sopenharmony_ci && this->uniqueAnswer(conicT, pt)) { 118cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, pt); 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci } 121cb93a386Sopenharmony_ci this->checkCoincident(); 122cb93a386Sopenharmony_ci return fIntersections->used(); 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci int intersectRay(double roots[2]) { 126cb93a386Sopenharmony_ci double adj = (*fLine)[1].fX - (*fLine)[0].fX; 127cb93a386Sopenharmony_ci double opp = (*fLine)[1].fY - (*fLine)[0].fY; 128cb93a386Sopenharmony_ci double r[3]; 129cb93a386Sopenharmony_ci for (int n = 0; n < 3; ++n) { 130cb93a386Sopenharmony_ci r[n] = (fConic[n].fY - (*fLine)[0].fY) * adj - (fConic[n].fX - (*fLine)[0].fX) * opp; 131cb93a386Sopenharmony_ci } 132cb93a386Sopenharmony_ci return this->validT(r, 0, roots); 133cb93a386Sopenharmony_ci } 134cb93a386Sopenharmony_ci 135cb93a386Sopenharmony_ci int validT(double r[3], double axisIntercept, double roots[2]) { 136cb93a386Sopenharmony_ci double A = r[2]; 137cb93a386Sopenharmony_ci double B = r[1] * fConic.fWeight - axisIntercept * fConic.fWeight + axisIntercept; 138cb93a386Sopenharmony_ci double C = r[0]; 139cb93a386Sopenharmony_ci A += C - 2 * B; // A = a + c - 2*(b*w - xCept*w + xCept) 140cb93a386Sopenharmony_ci B -= C; // B = b*w - w * xCept + xCept - a 141cb93a386Sopenharmony_ci C -= axisIntercept; 142cb93a386Sopenharmony_ci return SkDQuad::RootsValidT(A, 2 * B, C, roots); 143cb93a386Sopenharmony_ci } 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci int verticalIntersect(double axisIntercept, double roots[2]) { 146cb93a386Sopenharmony_ci double conicVals[] = { fConic[0].fX, fConic[1].fX, fConic[2].fX }; 147cb93a386Sopenharmony_ci return this->validT(conicVals, axisIntercept, roots); 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ci int verticalIntersect(double axisIntercept, double top, double bottom, bool flipped) { 151cb93a386Sopenharmony_ci this->addExactVerticalEndPoints(top, bottom, axisIntercept); 152cb93a386Sopenharmony_ci if (fAllowNear) { 153cb93a386Sopenharmony_ci this->addNearVerticalEndPoints(top, bottom, axisIntercept); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci double roots[2]; 156cb93a386Sopenharmony_ci int count = this->verticalIntersect(axisIntercept, roots); 157cb93a386Sopenharmony_ci for (int index = 0; index < count; ++index) { 158cb93a386Sopenharmony_ci double conicT = roots[index]; 159cb93a386Sopenharmony_ci SkDPoint pt = fConic.ptAtT(conicT); 160cb93a386Sopenharmony_ci SkDEBUGCODE(double conicVals[] = { fConic[0].fX, fConic[1].fX, fConic[2].fX }); 161cb93a386Sopenharmony_ci SkOPOBJASSERT(fIntersections, close_to(pt.fX, axisIntercept, conicVals)); 162cb93a386Sopenharmony_ci double lineT = (pt.fY - top) / (bottom - top); 163cb93a386Sopenharmony_ci if (this->pinTs(&conicT, &lineT, &pt, kPointInitialized) 164cb93a386Sopenharmony_ci && this->uniqueAnswer(conicT, pt)) { 165cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, pt); 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci } 168cb93a386Sopenharmony_ci if (flipped) { 169cb93a386Sopenharmony_ci fIntersections->flip(); 170cb93a386Sopenharmony_ci } 171cb93a386Sopenharmony_ci this->checkCoincident(); 172cb93a386Sopenharmony_ci return fIntersections->used(); 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_ciprotected: 176cb93a386Sopenharmony_ci// OPTIMIZE: Functions of the form add .. points are indentical to the conic routines. 177cb93a386Sopenharmony_ci // add endpoints first to get zero and one t values exactly 178cb93a386Sopenharmony_ci void addExactEndPoints() { 179cb93a386Sopenharmony_ci for (int cIndex = 0; cIndex < SkDConic::kPointCount; cIndex += SkDConic::kPointLast) { 180cb93a386Sopenharmony_ci double lineT = fLine->exactPoint(fConic[cIndex]); 181cb93a386Sopenharmony_ci if (lineT < 0) { 182cb93a386Sopenharmony_ci continue; 183cb93a386Sopenharmony_ci } 184cb93a386Sopenharmony_ci double conicT = (double) (cIndex >> 1); 185cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, fConic[cIndex]); 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci } 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_ci void addNearEndPoints() { 190cb93a386Sopenharmony_ci for (int cIndex = 0; cIndex < SkDConic::kPointCount; cIndex += SkDConic::kPointLast) { 191cb93a386Sopenharmony_ci double conicT = (double) (cIndex >> 1); 192cb93a386Sopenharmony_ci if (fIntersections->hasT(conicT)) { 193cb93a386Sopenharmony_ci continue; 194cb93a386Sopenharmony_ci } 195cb93a386Sopenharmony_ci double lineT = fLine->nearPoint(fConic[cIndex], nullptr); 196cb93a386Sopenharmony_ci if (lineT < 0) { 197cb93a386Sopenharmony_ci continue; 198cb93a386Sopenharmony_ci } 199cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, fConic[cIndex]); 200cb93a386Sopenharmony_ci } 201cb93a386Sopenharmony_ci this->addLineNearEndPoints(); 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci 204cb93a386Sopenharmony_ci void addLineNearEndPoints() { 205cb93a386Sopenharmony_ci for (int lIndex = 0; lIndex < 2; ++lIndex) { 206cb93a386Sopenharmony_ci double lineT = (double) lIndex; 207cb93a386Sopenharmony_ci if (fIntersections->hasOppT(lineT)) { 208cb93a386Sopenharmony_ci continue; 209cb93a386Sopenharmony_ci } 210cb93a386Sopenharmony_ci double conicT = ((SkDCurve*) &fConic)->nearPoint(SkPath::kConic_Verb, 211cb93a386Sopenharmony_ci (*fLine)[lIndex], (*fLine)[!lIndex]); 212cb93a386Sopenharmony_ci if (conicT < 0) { 213cb93a386Sopenharmony_ci continue; 214cb93a386Sopenharmony_ci } 215cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, (*fLine)[lIndex]); 216cb93a386Sopenharmony_ci } 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci 219cb93a386Sopenharmony_ci void addExactHorizontalEndPoints(double left, double right, double y) { 220cb93a386Sopenharmony_ci for (int cIndex = 0; cIndex < SkDConic::kPointCount; cIndex += SkDConic::kPointLast) { 221cb93a386Sopenharmony_ci double lineT = SkDLine::ExactPointH(fConic[cIndex], left, right, y); 222cb93a386Sopenharmony_ci if (lineT < 0) { 223cb93a386Sopenharmony_ci continue; 224cb93a386Sopenharmony_ci } 225cb93a386Sopenharmony_ci double conicT = (double) (cIndex >> 1); 226cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, fConic[cIndex]); 227cb93a386Sopenharmony_ci } 228cb93a386Sopenharmony_ci } 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci void addNearHorizontalEndPoints(double left, double right, double y) { 231cb93a386Sopenharmony_ci for (int cIndex = 0; cIndex < SkDConic::kPointCount; cIndex += SkDConic::kPointLast) { 232cb93a386Sopenharmony_ci double conicT = (double) (cIndex >> 1); 233cb93a386Sopenharmony_ci if (fIntersections->hasT(conicT)) { 234cb93a386Sopenharmony_ci continue; 235cb93a386Sopenharmony_ci } 236cb93a386Sopenharmony_ci double lineT = SkDLine::NearPointH(fConic[cIndex], left, right, y); 237cb93a386Sopenharmony_ci if (lineT < 0) { 238cb93a386Sopenharmony_ci continue; 239cb93a386Sopenharmony_ci } 240cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, fConic[cIndex]); 241cb93a386Sopenharmony_ci } 242cb93a386Sopenharmony_ci this->addLineNearEndPoints(); 243cb93a386Sopenharmony_ci } 244cb93a386Sopenharmony_ci 245cb93a386Sopenharmony_ci void addExactVerticalEndPoints(double top, double bottom, double x) { 246cb93a386Sopenharmony_ci for (int cIndex = 0; cIndex < SkDConic::kPointCount; cIndex += SkDConic::kPointLast) { 247cb93a386Sopenharmony_ci double lineT = SkDLine::ExactPointV(fConic[cIndex], top, bottom, x); 248cb93a386Sopenharmony_ci if (lineT < 0) { 249cb93a386Sopenharmony_ci continue; 250cb93a386Sopenharmony_ci } 251cb93a386Sopenharmony_ci double conicT = (double) (cIndex >> 1); 252cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, fConic[cIndex]); 253cb93a386Sopenharmony_ci } 254cb93a386Sopenharmony_ci } 255cb93a386Sopenharmony_ci 256cb93a386Sopenharmony_ci void addNearVerticalEndPoints(double top, double bottom, double x) { 257cb93a386Sopenharmony_ci for (int cIndex = 0; cIndex < SkDConic::kPointCount; cIndex += SkDConic::kPointLast) { 258cb93a386Sopenharmony_ci double conicT = (double) (cIndex >> 1); 259cb93a386Sopenharmony_ci if (fIntersections->hasT(conicT)) { 260cb93a386Sopenharmony_ci continue; 261cb93a386Sopenharmony_ci } 262cb93a386Sopenharmony_ci double lineT = SkDLine::NearPointV(fConic[cIndex], top, bottom, x); 263cb93a386Sopenharmony_ci if (lineT < 0) { 264cb93a386Sopenharmony_ci continue; 265cb93a386Sopenharmony_ci } 266cb93a386Sopenharmony_ci fIntersections->insert(conicT, lineT, fConic[cIndex]); 267cb93a386Sopenharmony_ci } 268cb93a386Sopenharmony_ci this->addLineNearEndPoints(); 269cb93a386Sopenharmony_ci } 270cb93a386Sopenharmony_ci 271cb93a386Sopenharmony_ci double findLineT(double t) { 272cb93a386Sopenharmony_ci SkDPoint xy = fConic.ptAtT(t); 273cb93a386Sopenharmony_ci double dx = (*fLine)[1].fX - (*fLine)[0].fX; 274cb93a386Sopenharmony_ci double dy = (*fLine)[1].fY - (*fLine)[0].fY; 275cb93a386Sopenharmony_ci if (fabs(dx) > fabs(dy)) { 276cb93a386Sopenharmony_ci return (xy.fX - (*fLine)[0].fX) / dx; 277cb93a386Sopenharmony_ci } 278cb93a386Sopenharmony_ci return (xy.fY - (*fLine)[0].fY) / dy; 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci 281cb93a386Sopenharmony_ci bool pinTs(double* conicT, double* lineT, SkDPoint* pt, PinTPoint ptSet) { 282cb93a386Sopenharmony_ci if (!approximately_one_or_less_double(*lineT)) { 283cb93a386Sopenharmony_ci return false; 284cb93a386Sopenharmony_ci } 285cb93a386Sopenharmony_ci if (!approximately_zero_or_more_double(*lineT)) { 286cb93a386Sopenharmony_ci return false; 287cb93a386Sopenharmony_ci } 288cb93a386Sopenharmony_ci double qT = *conicT = SkPinT(*conicT); 289cb93a386Sopenharmony_ci double lT = *lineT = SkPinT(*lineT); 290cb93a386Sopenharmony_ci if (lT == 0 || lT == 1 || (ptSet == kPointUninitialized && qT != 0 && qT != 1)) { 291cb93a386Sopenharmony_ci *pt = (*fLine).ptAtT(lT); 292cb93a386Sopenharmony_ci } else if (ptSet == kPointUninitialized) { 293cb93a386Sopenharmony_ci *pt = fConic.ptAtT(qT); 294cb93a386Sopenharmony_ci } 295cb93a386Sopenharmony_ci SkPoint gridPt = pt->asSkPoint(); 296cb93a386Sopenharmony_ci if (SkDPoint::ApproximatelyEqual(gridPt, (*fLine)[0].asSkPoint())) { 297cb93a386Sopenharmony_ci *pt = (*fLine)[0]; 298cb93a386Sopenharmony_ci *lineT = 0; 299cb93a386Sopenharmony_ci } else if (SkDPoint::ApproximatelyEqual(gridPt, (*fLine)[1].asSkPoint())) { 300cb93a386Sopenharmony_ci *pt = (*fLine)[1]; 301cb93a386Sopenharmony_ci *lineT = 1; 302cb93a386Sopenharmony_ci } 303cb93a386Sopenharmony_ci if (fIntersections->used() > 0 && approximately_equal((*fIntersections)[1][0], *lineT)) { 304cb93a386Sopenharmony_ci return false; 305cb93a386Sopenharmony_ci } 306cb93a386Sopenharmony_ci if (gridPt == fConic[0].asSkPoint()) { 307cb93a386Sopenharmony_ci *pt = fConic[0]; 308cb93a386Sopenharmony_ci *conicT = 0; 309cb93a386Sopenharmony_ci } else if (gridPt == fConic[2].asSkPoint()) { 310cb93a386Sopenharmony_ci *pt = fConic[2]; 311cb93a386Sopenharmony_ci *conicT = 1; 312cb93a386Sopenharmony_ci } 313cb93a386Sopenharmony_ci return true; 314cb93a386Sopenharmony_ci } 315cb93a386Sopenharmony_ci 316cb93a386Sopenharmony_ci bool uniqueAnswer(double conicT, const SkDPoint& pt) { 317cb93a386Sopenharmony_ci for (int inner = 0; inner < fIntersections->used(); ++inner) { 318cb93a386Sopenharmony_ci if (fIntersections->pt(inner) != pt) { 319cb93a386Sopenharmony_ci continue; 320cb93a386Sopenharmony_ci } 321cb93a386Sopenharmony_ci double existingConicT = (*fIntersections)[0][inner]; 322cb93a386Sopenharmony_ci if (conicT == existingConicT) { 323cb93a386Sopenharmony_ci return false; 324cb93a386Sopenharmony_ci } 325cb93a386Sopenharmony_ci // check if midway on conic is also same point. If so, discard this 326cb93a386Sopenharmony_ci double conicMidT = (existingConicT + conicT) / 2; 327cb93a386Sopenharmony_ci SkDPoint conicMidPt = fConic.ptAtT(conicMidT); 328cb93a386Sopenharmony_ci if (conicMidPt.approximatelyEqual(pt)) { 329cb93a386Sopenharmony_ci return false; 330cb93a386Sopenharmony_ci } 331cb93a386Sopenharmony_ci } 332cb93a386Sopenharmony_ci#if ONE_OFF_DEBUG 333cb93a386Sopenharmony_ci SkDPoint qPt = fConic.ptAtT(conicT); 334cb93a386Sopenharmony_ci SkDebugf("%s pt=(%1.9g,%1.9g) cPt=(%1.9g,%1.9g)\n", __FUNCTION__, pt.fX, pt.fY, 335cb93a386Sopenharmony_ci qPt.fX, qPt.fY); 336cb93a386Sopenharmony_ci#endif 337cb93a386Sopenharmony_ci return true; 338cb93a386Sopenharmony_ci } 339cb93a386Sopenharmony_ci 340cb93a386Sopenharmony_ciprivate: 341cb93a386Sopenharmony_ci const SkDConic& fConic; 342cb93a386Sopenharmony_ci const SkDLine* fLine; 343cb93a386Sopenharmony_ci SkIntersections* fIntersections; 344cb93a386Sopenharmony_ci bool fAllowNear; 345cb93a386Sopenharmony_ci}; 346cb93a386Sopenharmony_ci 347cb93a386Sopenharmony_ciint SkIntersections::horizontal(const SkDConic& conic, double left, double right, double y, 348cb93a386Sopenharmony_ci bool flipped) { 349cb93a386Sopenharmony_ci SkDLine line = {{{ left, y }, { right, y }}}; 350cb93a386Sopenharmony_ci LineConicIntersections c(conic, line, this); 351cb93a386Sopenharmony_ci return c.horizontalIntersect(y, left, right, flipped); 352cb93a386Sopenharmony_ci} 353cb93a386Sopenharmony_ci 354cb93a386Sopenharmony_ciint SkIntersections::vertical(const SkDConic& conic, double top, double bottom, double x, 355cb93a386Sopenharmony_ci bool flipped) { 356cb93a386Sopenharmony_ci SkDLine line = {{{ x, top }, { x, bottom }}}; 357cb93a386Sopenharmony_ci LineConicIntersections c(conic, line, this); 358cb93a386Sopenharmony_ci return c.verticalIntersect(x, top, bottom, flipped); 359cb93a386Sopenharmony_ci} 360cb93a386Sopenharmony_ci 361cb93a386Sopenharmony_ciint SkIntersections::intersect(const SkDConic& conic, const SkDLine& line) { 362cb93a386Sopenharmony_ci LineConicIntersections c(conic, line, this); 363cb93a386Sopenharmony_ci c.allowNear(fAllowNear); 364cb93a386Sopenharmony_ci return c.intersect(); 365cb93a386Sopenharmony_ci} 366cb93a386Sopenharmony_ci 367cb93a386Sopenharmony_ciint SkIntersections::intersectRay(const SkDConic& conic, const SkDLine& line) { 368cb93a386Sopenharmony_ci LineConicIntersections c(conic, line, this); 369cb93a386Sopenharmony_ci fUsed = c.intersectRay(fT[0]); 370cb93a386Sopenharmony_ci for (int index = 0; index < fUsed; ++index) { 371cb93a386Sopenharmony_ci fPt[index] = conic.ptAtT(fT[0][index]); 372cb93a386Sopenharmony_ci } 373cb93a386Sopenharmony_ci return fUsed; 374cb93a386Sopenharmony_ci} 375cb93a386Sopenharmony_ci 376cb93a386Sopenharmony_ciint SkIntersections::HorizontalIntercept(const SkDConic& conic, SkScalar y, double* roots) { 377cb93a386Sopenharmony_ci LineConicIntersections c(conic); 378cb93a386Sopenharmony_ci return c.horizontalIntersect(y, roots); 379cb93a386Sopenharmony_ci} 380cb93a386Sopenharmony_ci 381cb93a386Sopenharmony_ciint SkIntersections::VerticalIntercept(const SkDConic& conic, SkScalar x, double* roots) { 382cb93a386Sopenharmony_ci LineConicIntersections c(conic); 383cb93a386Sopenharmony_ci return c.verticalIntersect(x, roots); 384cb93a386Sopenharmony_ci} 385