/src/skia/src/pathops/SkPathOpsLine.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | #include "src/pathops/SkPathOpsLine.h" |
8 | | |
9 | 153M | SkDPoint SkDLine::ptAtT(double t) const { |
10 | 153M | if (0 == t) { |
11 | 37.4M | return fPts[0]; |
12 | 37.4M | } |
13 | 116M | if (1 == t) { |
14 | 36.0M | return fPts[1]; |
15 | 36.0M | } |
16 | 80.1M | double one_t = 1 - t; |
17 | 80.1M | SkDPoint result = { one_t * fPts[0].fX + t * fPts[1].fX, one_t * fPts[0].fY + t * fPts[1].fY }; |
18 | 80.1M | return result; |
19 | 80.1M | } |
20 | | |
21 | 137M | double SkDLine::exactPoint(const SkDPoint& xy) const { |
22 | 137M | if (xy == fPts[0]) { // do cheapest test first |
23 | 15.4M | return 0; |
24 | 15.4M | } |
25 | 121M | if (xy == fPts[1]) { |
26 | 15.2M | return 1; |
27 | 15.2M | } |
28 | 106M | return -1; |
29 | 106M | } |
30 | | |
31 | 132M | double SkDLine::nearPoint(const SkDPoint& xy, bool* unequal) const { |
32 | 132M | if (!AlmostBetweenUlps(fPts[0].fX, xy.fX, fPts[1].fX) |
33 | 79.2M | || !AlmostBetweenUlps(fPts[0].fY, xy.fY, fPts[1].fY)) { |
34 | 79.2M | return -1; |
35 | 79.2M | } |
36 | | // project a perpendicular ray from the point to the line; find the T on the line |
37 | 53.3M | SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line |
38 | 53.3M | double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay |
39 | 53.3M | SkDVector ab0 = xy - fPts[0]; |
40 | 53.3M | double numer = len.fX * ab0.fX + ab0.fY * len.fY; |
41 | 53.3M | if (!between(0, numer, denom)) { |
42 | 209k | return -1; |
43 | 209k | } |
44 | 53.1M | if (!denom) { |
45 | 0 | return 0; |
46 | 0 | } |
47 | 53.1M | double t = numer / denom; |
48 | 53.1M | SkDPoint realPt = ptAtT(t); |
49 | 53.1M | double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against distSq instead ? |
50 | | // find the ordinal in the original line with the largest unsigned exponent |
51 | 53.1M | double tiniest = std::min(std::min(std::min(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
52 | 53.1M | double largest = std::max(std::max(std::max(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
53 | 53.1M | largest = std::max(largest, -tiniest); |
54 | 53.1M | if (!AlmostEqualUlps_Pin(largest, largest + dist)) { // is the dist within ULPS tolerance? |
55 | 22.1M | return -1; |
56 | 22.1M | } |
57 | 31.0M | if (unequal) { |
58 | 24.4M | *unequal = (float) largest != (float) (largest + dist); |
59 | 24.4M | } |
60 | 31.0M | t = SkPinT(t); // a looser pin breaks skpwww_lptemp_com_3 |
61 | 31.0M | SkASSERT(between(0, t, 1)); |
62 | 31.0M | return t; |
63 | 31.0M | } |
64 | | |
65 | 4.76M | bool SkDLine::nearRay(const SkDPoint& xy) const { |
66 | | // project a perpendicular ray from the point to the line; find the T on the line |
67 | 4.76M | SkDVector len = fPts[1] - fPts[0]; // the x/y magnitudes of the line |
68 | 4.76M | double denom = len.fX * len.fX + len.fY * len.fY; // see DLine intersectRay |
69 | 4.76M | SkDVector ab0 = xy - fPts[0]; |
70 | 4.76M | double numer = len.fX * ab0.fX + ab0.fY * len.fY; |
71 | 4.76M | double t = numer / denom; |
72 | 4.76M | SkDPoint realPt = ptAtT(t); |
73 | 4.76M | double dist = realPt.distance(xy); // OPTIMIZATION: can we compare against distSq instead ? |
74 | | // find the ordinal in the original line with the largest unsigned exponent |
75 | 4.76M | double tiniest = std::min(std::min(std::min(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
76 | 4.76M | double largest = std::max(std::max(std::max(fPts[0].fX, fPts[0].fY), fPts[1].fX), fPts[1].fY); |
77 | 4.76M | largest = std::max(largest, -tiniest); |
78 | 4.76M | return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance? |
79 | 4.76M | } |
80 | | |
81 | 6.09M | double SkDLine::ExactPointH(const SkDPoint& xy, double left, double right, double y) { |
82 | 6.09M | if (xy.fY == y) { |
83 | 2.59M | if (xy.fX == left) { |
84 | 921k | return 0; |
85 | 921k | } |
86 | 1.66M | if (xy.fX == right) { |
87 | 837k | return 1; |
88 | 837k | } |
89 | 4.33M | } |
90 | 4.33M | return -1; |
91 | 4.33M | } |
92 | | |
93 | 5.65M | double SkDLine::NearPointH(const SkDPoint& xy, double left, double right, double y) { |
94 | 5.65M | if (!AlmostBequalUlps(xy.fY, y)) { |
95 | 3.41M | return -1; |
96 | 3.41M | } |
97 | 2.23M | if (!AlmostBetweenUlps(left, xy.fX, right)) { |
98 | 622k | return -1; |
99 | 622k | } |
100 | 1.61M | double t = (xy.fX - left) / (right - left); |
101 | 1.61M | t = SkPinT(t); |
102 | 1.61M | SkASSERT(between(0, t, 1)); |
103 | 1.61M | double realPtX = (1 - t) * left + t * right; |
104 | 1.61M | SkDVector distU = {xy.fY - y, xy.fX - realPtX}; |
105 | 1.61M | double distSq = distU.fX * distU.fX + distU.fY * distU.fY; |
106 | 1.61M | double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? |
107 | 1.61M | double tiniest = std::min(std::min(y, left), right); |
108 | 1.61M | double largest = std::max(std::max(y, left), right); |
109 | 1.61M | largest = std::max(largest, -tiniest); |
110 | 1.61M | if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? |
111 | 0 | return -1; |
112 | 0 | } |
113 | 1.61M | return t; |
114 | 1.61M | } |
115 | | |
116 | 7.70M | double SkDLine::ExactPointV(const SkDPoint& xy, double top, double bottom, double x) { |
117 | 7.70M | if (xy.fX == x) { |
118 | 3.71M | if (xy.fY == top) { |
119 | 1.22M | return 0; |
120 | 1.22M | } |
121 | 2.48M | if (xy.fY == bottom) { |
122 | 1.05M | return 1; |
123 | 1.05M | } |
124 | 5.42M | } |
125 | 5.42M | return -1; |
126 | 5.42M | } |
127 | | |
128 | 7.15M | double SkDLine::NearPointV(const SkDPoint& xy, double top, double bottom, double x) { |
129 | 7.15M | if (!AlmostBequalUlps(xy.fX, x)) { |
130 | 3.95M | return -1; |
131 | 3.95M | } |
132 | 3.19M | if (!AlmostBetweenUlps(top, xy.fY, bottom)) { |
133 | 790k | return -1; |
134 | 790k | } |
135 | 2.40M | double t = (xy.fY - top) / (bottom - top); |
136 | 2.40M | t = SkPinT(t); |
137 | 2.40M | SkASSERT(between(0, t, 1)); |
138 | 2.40M | double realPtY = (1 - t) * top + t * bottom; |
139 | 2.40M | SkDVector distU = {xy.fX - x, xy.fY - realPtY}; |
140 | 2.40M | double distSq = distU.fX * distU.fX + distU.fY * distU.fY; |
141 | 2.40M | double dist = sqrt(distSq); // OPTIMIZATION: can we compare against distSq instead ? |
142 | 2.40M | double tiniest = std::min(std::min(x, top), bottom); |
143 | 2.40M | double largest = std::max(std::max(x, top), bottom); |
144 | 2.40M | largest = std::max(largest, -tiniest); |
145 | 2.40M | if (!AlmostEqualUlps(largest, largest + dist)) { // is the dist within ULPS tolerance? |
146 | 0 | return -1; |
147 | 0 | } |
148 | 2.40M | return t; |
149 | 2.40M | } |