1 /* 2 * Copyright 2012 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #ifndef SkPathOpsCurve_DEFINE 8 #define SkPathOpsCurve_DEFINE 9 10 #include "SkIntersections.h" 11 12 #ifndef SK_RELEASE 13 #include "SkPath.h" 14 #endif 15 16 struct SkPathOpsBounds; 17 18 struct SkOpCurve { 19 SkPoint fPts[4]; 20 SkScalar fWeight; 21 SkDEBUGCODE(SkPath::Verb fVerb); 22 23 const SkPoint& operator[](int n) const { 24 SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb)); 25 return fPts[n]; 26 } 27 28 void dump() const; 29 30 void set(const SkDQuad& quad) { 31 for (int index = 0; index < SkDQuad::kPointCount; ++index) { 32 fPts[index] = quad[index].asSkPoint(); 33 } 34 SkDEBUGCODE(fWeight = 1); 35 SkDEBUGCODE(fVerb = SkPath::kQuad_Verb); 36 } 37 38 void set(const SkDCubic& cubic) { 39 for (int index = 0; index < SkDCubic::kPointCount; ++index) { 40 fPts[index] = cubic[index].asSkPoint(); 41 } 42 SkDEBUGCODE(fWeight = 1); 43 SkDEBUGCODE(fVerb = SkPath::kCubic_Verb); 44 } 45 46 }; 47 48 struct SkDCurve { 49 union { 50 SkDLine fLine; 51 SkDQuad fQuad; 52 SkDConic fConic; 53 SkDCubic fCubic; 54 }; 55 SkDEBUGCODE(SkPath::Verb fVerb); 56 57 const SkDPoint& operator[](int n) const { 58 SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb)); 59 return fCubic[n]; 60 } 61 62 SkDPoint& operator[](int n) { 63 SkASSERT(n >= 0 && n <= SkPathOpsVerbToPoints(fVerb)); 64 return fCubic[n]; 65 } 66 67 SkDPoint conicTop(const SkPoint curve[3], SkScalar curveWeight, 68 double s, double e, double* topT); 69 SkDPoint cubicTop(const SkPoint curve[4], SkScalar , double s, double e, double* topT); 70 void dumpID(int ) const; 71 SkDPoint lineTop(const SkPoint[2], SkScalar , double , double , double* topT); 72 SkDPoint quadTop(const SkPoint curve[3], SkScalar , double s, double e, double* topT); 73 74 void setConicBounds(const SkPoint curve[3], SkScalar curveWeight, 75 double s, double e, SkPathOpsBounds* ); 76 void setCubicBounds(const SkPoint curve[4], SkScalar , 77 double s, double e, SkPathOpsBounds* ); 78 void setQuadBounds(const SkPoint curve[3], SkScalar , 79 double s, double e, SkPathOpsBounds*); 80 }; 81 82 83 extern SkDPoint (SkDCurve::* const Top[])(const SkPoint curve[], SkScalar cWeight, 84 double tStart, double tEnd, double* topT); 85 86 static SkDPoint dline_xy_at_t(const SkPoint a[2], SkScalar , double t) { 87 SkDLine line; 88 line.set(a); 89 return line.ptAtT(t); 90 } 91 92 static SkDPoint dquad_xy_at_t(const SkPoint a[3], SkScalar , double t) { 93 SkDQuad quad; 94 quad.set(a); 95 return quad.ptAtT(t); 96 } 97 98 static SkDPoint dconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) { 99 SkDConic conic; 100 conic.set(a, weight); 101 return conic.ptAtT(t); 102 } 103 104 static SkDPoint dcubic_xy_at_t(const SkPoint a[4], SkScalar , double t) { 105 SkDCubic cubic; 106 cubic.set(a); 107 return cubic.ptAtT(t); 108 } 109 110 static SkDPoint (* const CurveDPointAtT[])(const SkPoint[], SkScalar , double ) = { 111 nullptr, 112 dline_xy_at_t, 113 dquad_xy_at_t, 114 dconic_xy_at_t, 115 dcubic_xy_at_t 116 }; 117 118 static SkPoint fline_xy_at_t(const SkPoint a[2], SkScalar weight, double t) { 119 return dline_xy_at_t(a, weight, t).asSkPoint(); 120 } 121 122 static SkPoint fquad_xy_at_t(const SkPoint a[3], SkScalar weight, double t) { 123 return dquad_xy_at_t(a, weight, t).asSkPoint(); 124 } 125 126 static SkPoint fconic_xy_at_t(const SkPoint a[3], SkScalar weight, double t) { 127 return dconic_xy_at_t(a, weight, t).asSkPoint(); 128 } 129 130 static SkPoint fcubic_xy_at_t(const SkPoint a[4], SkScalar weight, double t) { 131 return dcubic_xy_at_t(a, weight, t).asSkPoint(); 132 } 133 134 static SkPoint (* const CurvePointAtT[])(const SkPoint[], SkScalar , double ) = { 135 nullptr, 136 fline_xy_at_t, 137 fquad_xy_at_t, 138 fconic_xy_at_t, 139 fcubic_xy_at_t 140 }; 141 142 static SkDVector dline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) { 143 SkDLine line; 144 line.set(a); 145 return line[1] - line[0]; 146 } 147 148 static SkDVector dquad_dxdy_at_t(const SkPoint a[3], SkScalar , double t) { 149 SkDQuad quad; 150 quad.set(a); 151 return quad.dxdyAtT(t); 152 } 153 154 static SkDVector dconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) { 155 SkDConic conic; 156 conic.set(a, weight); 157 return conic.dxdyAtT(t); 158 } 159 160 static SkDVector dcubic_dxdy_at_t(const SkPoint a[4], SkScalar , double t) { 161 SkDCubic cubic; 162 cubic.set(a); 163 return cubic.dxdyAtT(t); 164 } 165 166 static SkDVector (* const CurveDSlopeAtT[])(const SkPoint[], SkScalar , double ) = { 167 nullptr, 168 dline_dxdy_at_t, 169 dquad_dxdy_at_t, 170 dconic_dxdy_at_t, 171 dcubic_dxdy_at_t 172 }; 173 174 static SkVector fline_dxdy_at_t(const SkPoint a[2], SkScalar , double ) { 175 return a[1] - a[0]; 176 } 177 178 static SkVector fquad_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) { 179 return dquad_dxdy_at_t(a, weight, t).asSkVector(); 180 } 181 182 static SkVector fconic_dxdy_at_t(const SkPoint a[3], SkScalar weight, double t) { 183 return dconic_dxdy_at_t(a, weight, t).asSkVector(); 184 } 185 186 static SkVector fcubic_dxdy_at_t(const SkPoint a[4], SkScalar weight, double t) { 187 return dcubic_dxdy_at_t(a, weight, t).asSkVector(); 188 } 189 190 static SkVector (* const CurveSlopeAtT[])(const SkPoint[], SkScalar , double ) = { 191 nullptr, 192 fline_dxdy_at_t, 193 fquad_dxdy_at_t, 194 fconic_dxdy_at_t, 195 fcubic_dxdy_at_t 196 }; 197 198 static bool line_is_vertical(const SkPoint a[2], SkScalar , double startT, double endT) { 199 SkDLine line; 200 line.set(a); 201 SkDPoint dst[2] = { line.ptAtT(startT), line.ptAtT(endT) }; 202 return AlmostEqualUlps(dst[0].fX, dst[1].fX); 203 } 204 205 static bool quad_is_vertical(const SkPoint a[3], SkScalar , double startT, double endT) { 206 SkDQuad quad; 207 quad.set(a); 208 SkDQuad dst = quad.subDivide(startT, endT); 209 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX); 210 } 211 212 static bool conic_is_vertical(const SkPoint a[3], SkScalar weight, double startT, double endT) { 213 SkDConic conic; 214 conic.set(a, weight); 215 SkDConic dst = conic.subDivide(startT, endT); 216 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX); 217 } 218 219 static bool cubic_is_vertical(const SkPoint a[4], SkScalar , double startT, double endT) { 220 SkDCubic cubic; 221 cubic.set(a); 222 SkDCubic dst = cubic.subDivide(startT, endT); 223 return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX) 224 && AlmostEqualUlps(dst[2].fX, dst[3].fX); 225 } 226 227 static bool (* const CurveIsVertical[])(const SkPoint[], SkScalar , double , double) = { 228 nullptr, 229 line_is_vertical, 230 quad_is_vertical, 231 conic_is_vertical, 232 cubic_is_vertical 233 }; 234 235 static void line_intersect_ray(const SkPoint a[2], SkScalar , const SkDLine& ray, 236 SkIntersections* i) { 237 SkDLine line; 238 line.set(a); 239 i->intersectRay(line, ray); 240 } 241 242 static void quad_intersect_ray(const SkPoint a[3], SkScalar , const SkDLine& ray, 243 SkIntersections* i) { 244 SkDQuad quad; 245 quad.set(a); 246 i->intersectRay(quad, ray); 247 } 248 249 static void conic_intersect_ray(const SkPoint a[3], SkScalar weight, const SkDLine& ray, 250 SkIntersections* i) { 251 SkDConic conic; 252 conic.set(a, weight); 253 i->intersectRay(conic, ray); 254 } 255 256 static void cubic_intersect_ray(const SkPoint a[4], SkScalar , const SkDLine& ray, 257 SkIntersections* i) { 258 SkDCubic cubic; 259 cubic.set(a); 260 i->intersectRay(cubic, ray); 261 } 262 263 static void (* const CurveIntersectRay[])(const SkPoint[] , SkScalar , const SkDLine& , 264 SkIntersections* ) = { 265 nullptr, 266 line_intersect_ray, 267 quad_intersect_ray, 268 conic_intersect_ray, 269 cubic_intersect_ray 270 }; 271 272 static int line_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) { 273 SkDLine line; 274 roots[0] = SkIntersections::HorizontalIntercept(line.set(a), y); 275 return between(0, roots[0], 1); 276 } 277 278 static int line_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) { 279 SkDLine line; 280 roots[0] = SkIntersections::VerticalIntercept(line.set(a), x); 281 return between(0, roots[0], 1); 282 } 283 284 static int quad_intercept_h(const SkPoint a[2], SkScalar , SkScalar y, double* roots) { 285 SkDQuad quad; 286 return SkIntersections::HorizontalIntercept(quad.set(a), y, roots); 287 } 288 289 static int quad_intercept_v(const SkPoint a[2], SkScalar , SkScalar x, double* roots) { 290 SkDQuad quad; 291 return SkIntersections::VerticalIntercept(quad.set(a), x, roots); 292 } 293 294 static int conic_intercept_h(const SkPoint a[2], SkScalar w, SkScalar y, double* roots) { 295 SkDConic conic; 296 return SkIntersections::HorizontalIntercept(conic.set(a, w), y, roots); 297 } 298 299 static int conic_intercept_v(const SkPoint a[2], SkScalar w, SkScalar x, double* roots) { 300 SkDConic conic; 301 return SkIntersections::VerticalIntercept(conic.set(a, w), x, roots); 302 } 303 304 static int cubic_intercept_h(const SkPoint a[3], SkScalar , SkScalar y, double* roots) { 305 SkDCubic cubic; 306 return cubic.set(a).horizontalIntersect(y, roots); 307 } 308 309 static int cubic_intercept_v(const SkPoint a[3], SkScalar , SkScalar x, double* roots) { 310 SkDCubic cubic; 311 return cubic.set(a).verticalIntersect(x, roots); 312 } 313 314 static int (* const CurveIntercept[])(const SkPoint[] , SkScalar , SkScalar , double* ) = { 315 nullptr, 316 nullptr, 317 line_intercept_h, 318 line_intercept_v, 319 quad_intercept_h, 320 quad_intercept_v, 321 conic_intercept_h, 322 conic_intercept_v, 323 cubic_intercept_h, 324 cubic_intercept_v, 325 }; 326 327 #endif 328