Home | History | Annotate | Download | only in pathops
      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