|  | /* | 
|  | * Copyright 2012 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  | #ifndef SkIntersections_DEFINE | 
|  | #define SkIntersections_DEFINE | 
|  |  | 
|  | #include "SkPathOpsCubic.h" | 
|  | #include "SkPathOpsLine.h" | 
|  | #include "SkPathOpsPoint.h" | 
|  | #include "SkPathOpsQuad.h" | 
|  |  | 
|  | class SkIntersections { | 
|  | public: | 
|  | SkIntersections() | 
|  | : fSwap(0) | 
|  | #ifdef SK_DEBUG | 
|  | , fDepth(0) | 
|  | #endif | 
|  | { | 
|  | sk_bzero(fPt, sizeof(fPt)); | 
|  | sk_bzero(fPt2, sizeof(fPt2)); | 
|  | sk_bzero(fT, sizeof(fT)); | 
|  | sk_bzero(fIsCoincident, sizeof(fIsCoincident)); | 
|  | sk_bzero(fNearlySame, sizeof(fNearlySame)); | 
|  | reset(); | 
|  | fMax = 0;  // require that the caller set the max | 
|  | } | 
|  |  | 
|  | class TArray { | 
|  | public: | 
|  | explicit TArray(const double ts[9]) : fTArray(ts) {} | 
|  | double operator[](int n) const { | 
|  | return fTArray[n]; | 
|  | } | 
|  | const double* fTArray; | 
|  | }; | 
|  | TArray operator[](int n) const { return TArray(fT[n]); } | 
|  |  | 
|  | void allowNear(bool nearAllowed) { | 
|  | fAllowNear = nearAllowed; | 
|  | } | 
|  |  | 
|  | int cubic(const SkPoint a[4]) { | 
|  | SkDCubic cubic; | 
|  | cubic.set(a); | 
|  | fMax = 1;  // self intersect | 
|  | return intersect(cubic); | 
|  | } | 
|  |  | 
|  | int cubicCubic(const SkPoint a[4], const SkPoint b[4]) { | 
|  | SkDCubic aCubic; | 
|  | aCubic.set(a); | 
|  | SkDCubic bCubic; | 
|  | bCubic.set(b); | 
|  | fMax = 9; | 
|  | return intersect(aCubic, bCubic); | 
|  | } | 
|  |  | 
|  | int cubicHorizontal(const SkPoint a[4], SkScalar left, SkScalar right, SkScalar y, | 
|  | bool flipped) { | 
|  | SkDCubic cubic; | 
|  | cubic.set(a); | 
|  | fMax = 3; | 
|  | return horizontal(cubic, left, right, y, flipped); | 
|  | } | 
|  |  | 
|  | int cubicVertical(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) { | 
|  | SkDCubic cubic; | 
|  | cubic.set(a); | 
|  | fMax = 3; | 
|  | return vertical(cubic, top, bottom, x, flipped); | 
|  | } | 
|  |  | 
|  | int cubicLine(const SkPoint a[4], const SkPoint b[2]) { | 
|  | SkDCubic cubic; | 
|  | cubic.set(a); | 
|  | SkDLine line; | 
|  | line.set(b); | 
|  | fMax = 3; | 
|  | return intersect(cubic, line); | 
|  | } | 
|  |  | 
|  | int cubicQuad(const SkPoint a[4], const SkPoint b[3]) { | 
|  | SkDCubic cubic; | 
|  | cubic.set(a); | 
|  | SkDQuad quad; | 
|  | quad.set(b); | 
|  | fMax = 6; | 
|  | return intersect(cubic, quad); | 
|  | } | 
|  |  | 
|  | bool hasT(double t) const { | 
|  | SkASSERT(t == 0 || t == 1); | 
|  | return fUsed > 0 && (t == 0 ? fT[0][0] == 0 : fT[0][fUsed - 1] == 1); | 
|  | } | 
|  |  | 
|  | int insertSwap(double one, double two, const SkDPoint& pt) { | 
|  | if (fSwap) { | 
|  | return insert(two, one, pt); | 
|  | } else { | 
|  | return insert(one, two, pt); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool isCoincident(int index) { | 
|  | return (fIsCoincident[0] & 1 << index) != 0; | 
|  | } | 
|  |  | 
|  | int lineHorizontal(const SkPoint a[2], SkScalar left, SkScalar right, SkScalar y, | 
|  | bool flipped) { | 
|  | SkDLine line; | 
|  | line.set(a); | 
|  | fMax = 2; | 
|  | return horizontal(line, left, right, y, flipped); | 
|  | } | 
|  |  | 
|  | int lineVertical(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) { | 
|  | SkDLine line; | 
|  | line.set(a); | 
|  | fMax = 2; | 
|  | return vertical(line, top, bottom, x, flipped); | 
|  | } | 
|  |  | 
|  | int lineLine(const SkPoint a[2], const SkPoint b[2]) { | 
|  | SkDLine aLine, bLine; | 
|  | aLine.set(a); | 
|  | bLine.set(b); | 
|  | fMax = 2; | 
|  | return intersect(aLine, bLine); | 
|  | } | 
|  |  | 
|  | bool nearlySame(int index) const { | 
|  | SkASSERT(index == 0 || index == 1); | 
|  | return fNearlySame[index]; | 
|  | } | 
|  |  | 
|  | const SkDPoint& pt(int index) const { | 
|  | return fPt[index]; | 
|  | } | 
|  |  | 
|  | const SkDPoint& pt2(int index) const { | 
|  | return fPt2[index]; | 
|  | } | 
|  |  | 
|  | int quadHorizontal(const SkPoint a[3], SkScalar left, SkScalar right, SkScalar y, | 
|  | bool flipped) { | 
|  | SkDQuad quad; | 
|  | quad.set(a); | 
|  | fMax = 2; | 
|  | return horizontal(quad, left, right, y, flipped); | 
|  | } | 
|  |  | 
|  | int quadVertical(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped) { | 
|  | SkDQuad quad; | 
|  | quad.set(a); | 
|  | fMax = 2; | 
|  | return vertical(quad, top, bottom, x, flipped); | 
|  | } | 
|  |  | 
|  | int quadLine(const SkPoint a[3], const SkPoint b[2]) { | 
|  | SkDQuad quad; | 
|  | quad.set(a); | 
|  | SkDLine line; | 
|  | line.set(b); | 
|  | fMax = 3; // 2;  permit small coincident segment + non-coincident intersection | 
|  | return intersect(quad, line); | 
|  | } | 
|  |  | 
|  | int quadQuad(const SkPoint a[3], const SkPoint b[3]) { | 
|  | SkDQuad aQuad; | 
|  | aQuad.set(a); | 
|  | SkDQuad bQuad; | 
|  | bQuad.set(b); | 
|  | fMax = 4; | 
|  | return intersect(aQuad, bQuad); | 
|  | } | 
|  |  | 
|  | // leaves swap, max alone | 
|  | void reset() { | 
|  | fAllowNear = true; | 
|  | fUsed = 0; | 
|  | } | 
|  |  | 
|  | void set(bool swap, int tIndex, double t) { | 
|  | fT[(int) swap][tIndex] = t; | 
|  | } | 
|  |  | 
|  | void setMax(int max) { | 
|  | fMax = max; | 
|  | } | 
|  |  | 
|  | void swap() { | 
|  | fSwap ^= true; | 
|  | } | 
|  |  | 
|  | void swapPts(); | 
|  |  | 
|  | bool swapped() const { | 
|  | return fSwap; | 
|  | } | 
|  |  | 
|  | int used() const { | 
|  | return fUsed; | 
|  | } | 
|  |  | 
|  | void downDepth() { | 
|  | SkASSERT(--fDepth >= 0); | 
|  | } | 
|  |  | 
|  | void upDepth() { | 
|  | SkASSERT(++fDepth < 16); | 
|  | } | 
|  |  | 
|  | void append(const SkIntersections& ); | 
|  | void cleanUpCoincidence(); | 
|  | int coincidentUsed() const; | 
|  | void cubicInsert(double one, double two, const SkDPoint& pt, const SkDCubic& c1, | 
|  | const SkDCubic& c2); | 
|  | int cubicRay(const SkPoint pts[4], const SkDLine& line); | 
|  | void flip(); | 
|  | int horizontal(const SkDLine&, double y); | 
|  | int horizontal(const SkDLine&, double left, double right, double y, bool flipped); | 
|  | int horizontal(const SkDQuad&, double left, double right, double y, bool flipped); | 
|  | int horizontal(const SkDQuad&, double left, double right, double y, double tRange[2]); | 
|  | int horizontal(const SkDCubic&, double y, double tRange[3]); | 
|  | int horizontal(const SkDCubic&, double left, double right, double y, bool flipped); | 
|  | int horizontal(const SkDCubic&, double left, double right, double y, double tRange[3]); | 
|  | // FIXME : does not respect swap | 
|  | int insert(double one, double two, const SkDPoint& pt); | 
|  | void insertNear(double one, double two, const SkDPoint& pt1, const SkDPoint& pt2); | 
|  | // start if index == 0 : end if index == 1 | 
|  | void insertCoincident(double one, double two, const SkDPoint& pt); | 
|  | int intersect(const SkDLine&, const SkDLine&); | 
|  | int intersect(const SkDQuad&, const SkDLine&); | 
|  | int intersect(const SkDQuad&, const SkDQuad&); | 
|  | int intersect(const SkDCubic&);  // return true if cubic self-intersects | 
|  | int intersect(const SkDCubic&, const SkDLine&); | 
|  | int intersect(const SkDCubic&, const SkDQuad&); | 
|  | int intersect(const SkDCubic&, const SkDCubic&); | 
|  | int intersectRay(const SkDLine&, const SkDLine&); | 
|  | int intersectRay(const SkDQuad&, const SkDLine&); | 
|  | int intersectRay(const SkDCubic&, const SkDLine&); | 
|  | static SkDPoint Line(const SkDLine&, const SkDLine&); | 
|  | int lineRay(const SkPoint pts[2], const SkDLine& line); | 
|  | void offset(int base, double start, double end); | 
|  | void quickRemoveOne(int index, int replace); | 
|  | int quadRay(const SkPoint pts[3], const SkDLine& line); | 
|  | void removeOne(int index); | 
|  | static bool Test(const SkDLine& , const SkDLine&); | 
|  | int vertical(const SkDLine&, double x); | 
|  | int vertical(const SkDLine&, double top, double bottom, double x, bool flipped); | 
|  | int vertical(const SkDQuad&, double top, double bottom, double x, bool flipped); | 
|  | int vertical(const SkDCubic&, double top, double bottom, double x, bool flipped); | 
|  | int verticalCubic(const SkPoint a[4], SkScalar top, SkScalar bottom, SkScalar x, bool flipped); | 
|  | int verticalLine(const SkPoint a[2], SkScalar top, SkScalar bottom, SkScalar x, bool flipped); | 
|  | int verticalQuad(const SkPoint a[3], SkScalar top, SkScalar bottom, SkScalar x, bool flipped); | 
|  |  | 
|  | int depth() const { | 
|  | #ifdef SK_DEBUG | 
|  | return fDepth; | 
|  | #else | 
|  | return 0; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | private: | 
|  | bool cubicCheckCoincidence(const SkDCubic& c1, const SkDCubic& c2); | 
|  | bool cubicExactEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2); | 
|  | void cubicNearEnd(const SkDCubic& cubic1, bool start, const SkDCubic& cubic2, const SkDRect& ); | 
|  | void cleanUpParallelLines(bool parallel); | 
|  | void computePoints(const SkDLine& line, int used); | 
|  |  | 
|  | SkDPoint fPt[9];  // FIXME: since scans store points as SkPoint, this should also | 
|  | SkDPoint fPt2[9];  // used by nearly same to store alternate intersection point | 
|  | double fT[2][9]; | 
|  | uint16_t fIsCoincident[2];  // bit set for each curve's coincident T | 
|  | bool fNearlySame[2];  // true if end points nearly match | 
|  | unsigned char fUsed; | 
|  | unsigned char fMax; | 
|  | bool fAllowNear; | 
|  | bool fSwap; | 
|  | #ifdef SK_DEBUG | 
|  | int fDepth; | 
|  | #endif | 
|  | }; | 
|  |  | 
|  | extern int (SkIntersections::*CurveRay[])(const SkPoint[], const SkDLine& ); | 
|  | extern int (SkIntersections::*CurveVertical[])(const SkPoint[], SkScalar top, SkScalar bottom, | 
|  | SkScalar x, bool flipped); | 
|  |  | 
|  | #endif |