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#include "SkPathOpsCubic.h"
12#include "SkPathOpsLine.h"
13#include "SkPathOpsQuad.h"
14
15static SkDPoint dline_xy_at_t(const SkPoint a[2], double t) {
16    SkDLine line;
17    line.set(a);
18    return line.ptAtT(t);
19}
20
21static SkDPoint dquad_xy_at_t(const SkPoint a[3], double t) {
22    SkDQuad quad;
23    quad.set(a);
24    return quad.ptAtT(t);
25}
26
27static SkDPoint dcubic_xy_at_t(const SkPoint a[4], double t) {
28    SkDCubic cubic;
29    cubic.set(a);
30    return cubic.ptAtT(t);
31}
32
33static SkDPoint (* const CurveDPointAtT[])(const SkPoint[], double ) = {
34    NULL,
35    dline_xy_at_t,
36    dquad_xy_at_t,
37    dcubic_xy_at_t
38};
39
40static SkPoint fline_xy_at_t(const SkPoint a[2], double t) {
41    return dline_xy_at_t(a, t).asSkPoint();
42}
43
44static SkPoint fquad_xy_at_t(const SkPoint a[3], double t) {
45    return dquad_xy_at_t(a, t).asSkPoint();
46}
47
48static SkPoint fcubic_xy_at_t(const SkPoint a[4], double t) {
49    return dcubic_xy_at_t(a, t).asSkPoint();
50}
51
52static SkPoint (* const CurvePointAtT[])(const SkPoint[], double ) = {
53    NULL,
54    fline_xy_at_t,
55    fquad_xy_at_t,
56    fcubic_xy_at_t
57};
58
59static SkDVector dline_dxdy_at_t(const SkPoint a[2], double ) {
60    SkDLine line;
61    line.set(a);
62    return line[1] - line[0];
63}
64
65static SkDVector dquad_dxdy_at_t(const SkPoint a[3], double t) {
66    SkDQuad quad;
67    quad.set(a);
68    return quad.dxdyAtT(t);
69}
70
71static SkDVector dcubic_dxdy_at_t(const SkPoint a[4], double t) {
72    SkDCubic cubic;
73    cubic.set(a);
74    return cubic.dxdyAtT(t);
75}
76
77static SkDVector (* const CurveDSlopeAtT[])(const SkPoint[], double ) = {
78    NULL,
79    dline_dxdy_at_t,
80    dquad_dxdy_at_t,
81    dcubic_dxdy_at_t
82};
83
84static SkVector fline_dxdy_at_t(const SkPoint a[2], double ) {
85    return a[1] - a[0];
86}
87
88static SkVector fquad_dxdy_at_t(const SkPoint a[3], double t) {
89    return dquad_dxdy_at_t(a, t).asSkVector();
90}
91
92static SkVector fcubic_dxdy_at_t(const SkPoint a[4], double t) {
93    return dcubic_dxdy_at_t(a, t).asSkVector();
94}
95
96static SkVector (* const CurveSlopeAtT[])(const SkPoint[], double ) = {
97    NULL,
98    fline_dxdy_at_t,
99    fquad_dxdy_at_t,
100    fcubic_dxdy_at_t
101};
102
103static SkPoint quad_top(const SkPoint a[3], double startT, double endT) {
104    SkDQuad quad;
105    quad.set(a);
106    SkDPoint topPt = quad.top(startT, endT);
107    return topPt.asSkPoint();
108}
109
110static SkPoint cubic_top(const SkPoint a[4], double startT, double endT) {
111    SkDCubic cubic;
112    cubic.set(a);
113    SkDPoint topPt = cubic.top(startT, endT);
114    return topPt.asSkPoint();
115}
116
117static SkPoint (* const CurveTop[])(const SkPoint[], double , double ) = {
118    NULL,
119    NULL,
120    quad_top,
121    cubic_top
122};
123
124static bool line_is_vertical(const SkPoint a[2], double startT, double endT) {
125    SkDLine line;
126    line.set(a);
127    SkDPoint dst[2] = { line.ptAtT(startT), line.ptAtT(endT) };
128    return AlmostEqualUlps(dst[0].fX, dst[1].fX);
129}
130
131static bool quad_is_vertical(const SkPoint a[3], double startT, double endT) {
132    SkDQuad quad;
133    quad.set(a);
134    SkDQuad dst = quad.subDivide(startT, endT);
135    return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX);
136}
137
138static bool cubic_is_vertical(const SkPoint a[4], double startT, double endT) {
139    SkDCubic cubic;
140    cubic.set(a);
141    SkDCubic dst = cubic.subDivide(startT, endT);
142    return AlmostEqualUlps(dst[0].fX, dst[1].fX) && AlmostEqualUlps(dst[1].fX, dst[2].fX)
143            && AlmostEqualUlps(dst[2].fX, dst[3].fX);
144}
145
146static bool (* const CurveIsVertical[])(const SkPoint[], double , double) = {
147    NULL,
148    line_is_vertical,
149    quad_is_vertical,
150    cubic_is_vertical
151};
152
153static void line_intersect_ray(const SkPoint a[2], const SkDLine& ray, SkIntersections* i) {
154    SkDLine line;
155    line.set(a);
156    i->intersectRay(line, ray);
157}
158
159static void quad_intersect_ray(const SkPoint a[3], const SkDLine& ray, SkIntersections* i) {
160    SkDQuad quad;
161    quad.set(a);
162    i->intersectRay(quad, ray);
163}
164
165static void cubic_intersect_ray(const SkPoint a[4], const SkDLine& ray, SkIntersections* i) {
166    SkDCubic cubic;
167    cubic.set(a);
168    i->intersectRay(cubic, ray);
169}
170
171static void (* const CurveIntersectRay[])(const SkPoint[] , const SkDLine& , SkIntersections* ) = {
172    NULL,
173    line_intersect_ray,
174    quad_intersect_ray,
175    cubic_intersect_ray
176};
177
178#endif
179