Flutter Engine
The Flutter Engine
Functions
SkEdgeClipper.cpp File Reference
#include "src/core/SkEdgeClipper.h"
#include "include/core/SkRect.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkMacros.h"
#include "src/core/SkGeometry.h"
#include "src/core/SkLineClipper.h"
#include "src/core/SkPathPriv.h"
#include <algorithm>
#include <cstring>

Go to the source code of this file.

Functions

static bool quick_reject (const SkRect &bounds, const SkRect &clip)
 
static void clamp_le (SkScalar &value, SkScalar max)
 
static void clamp_ge (SkScalar &value, SkScalar min)
 
static bool sort_increasing_Y (SkPoint dst[], const SkPoint src[], int count)
 
static bool chopMonoQuadAt (SkScalar c0, SkScalar c1, SkScalar c2, SkScalar target, SkScalar *t)
 
static bool chopMonoQuadAtY (SkPoint pts[3], SkScalar y, SkScalar *t)
 
static bool chopMonoQuadAtX (SkPoint pts[3], SkScalar x, SkScalar *t)
 
static void chop_quad_in_Y (SkPoint pts[3], const SkRect &clip)
 
static SkScalar mono_cubic_closestT (const SkScalar src[], SkScalar x)
 
static void chop_mono_cubic_at_y (SkPoint src[4], SkScalar y, SkPoint dst[7])
 
static void chop_cubic_in_Y (SkPoint pts[4], const SkRect &clip)
 
static void chop_mono_cubic_at_x (SkPoint src[4], SkScalar x, SkPoint dst[7])
 
static SkRect compute_cubic_bounds (const SkPoint pts[4])
 
static bool too_big_for_reliable_float_math (const SkRect &r)
 

Function Documentation

◆ chop_cubic_in_Y()

static void chop_cubic_in_Y ( SkPoint  pts[4],
const SkRect clip 
)
static

Definition at line 288 of file SkEdgeClipper.cpp.

288 {
289
290 // are we partially above
291 if (pts[0].fY < clip.fTop) {
292 SkPoint tmp[7];
293 chop_mono_cubic_at_y(pts, clip.fTop, tmp);
294
295 /*
296 * For a large range in the points, we can do a poor job of chopping, such that the t
297 * we computed resulted in the lower cubic still being partly above the clip.
298 *
299 * If just the first or first 2 Y values are above the fTop, we can just smash them
300 * down. If the first 3 Ys are above fTop, we can't smash all 3, as that can really
301 * distort the cubic. In this case, we take the first output (tmp[3..6] and treat it as
302 * a guess, and re-chop against fTop. Then we fall through to checking if we need to
303 * smash the first 1 or 2 Y values.
304 */
305 if (tmp[3].fY < clip.fTop && tmp[4].fY < clip.fTop && tmp[5].fY < clip.fTop) {
306 SkPoint tmp2[4];
307 memcpy(tmp2, &tmp[3].fX, 4 * sizeof(SkPoint));
308 chop_mono_cubic_at_y(tmp2, clip.fTop, tmp);
309 }
310
311 // tmp[3, 4].fY should all be to the below clip.fTop.
312 // Since we can't trust the numerics of the chopper, we force those conditions now
313 tmp[3].fY = clip.fTop;
314 clamp_ge(tmp[4].fY, clip.fTop);
315
316 pts[0] = tmp[3];
317 pts[1] = tmp[4];
318 pts[2] = tmp[5];
319 }
320
321 // are we partially below
322 if (pts[3].fY > clip.fBottom) {
323 SkPoint tmp[7];
324 chop_mono_cubic_at_y(pts, clip.fBottom, tmp);
325 tmp[3].fY = clip.fBottom;
326 clamp_le(tmp[2].fY, clip.fBottom);
327
328 pts[1] = tmp[1];
329 pts[2] = tmp[2];
330 pts[3] = tmp[3];
331 }
332}
static void clamp_le(SkScalar &value, SkScalar max)
static void chop_mono_cubic_at_y(SkPoint src[4], SkScalar y, SkPoint dst[7])
static void clamp_ge(SkScalar &value, SkScalar min)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ chop_mono_cubic_at_x()

static void chop_mono_cubic_at_x ( SkPoint  src[4],
SkScalar  x,
SkPoint  dst[7] 
)
static

Definition at line 334 of file SkEdgeClipper.cpp.

334 {
335 if (SkChopMonoCubicAtX(src, x, dst)) {
336 return;
337 }
339}
static SkScalar mono_cubic_closestT(const SkScalar src[], SkScalar x)
void SkChopCubicAt(const SkPoint src[4], SkPoint dst[7], SkScalar t)
Definition: SkGeometry.cpp:473
bool SkChopMonoCubicAtX(const SkPoint src[4], SkScalar x, SkPoint dst[7])
double x
dst
Definition: cp.py:12

◆ chop_mono_cubic_at_y()

static void chop_mono_cubic_at_y ( SkPoint  src[4],
SkScalar  y,
SkPoint  dst[7] 
)
static

Definition at line 280 of file SkEdgeClipper.cpp.

280 {
281 if (SkChopMonoCubicAtY(src, y, dst)) {
282 return;
283 }
285}
bool SkChopMonoCubicAtY(const SkPoint src[4], SkScalar y, SkPoint dst[7])
double y

◆ chop_quad_in_Y()

static void chop_quad_in_Y ( SkPoint  pts[3],
const SkRect clip 
)
static

Definition at line 100 of file SkEdgeClipper.cpp.

100 {
101 SkScalar t;
102 SkPoint tmp[5]; // for SkChopQuadAt
103
104 // are we partially above
105 if (pts[0].fY < clip.fTop) {
106 if (chopMonoQuadAtY(pts, clip.fTop, &t)) {
107 // take the 2nd chopped quad
108 SkChopQuadAt(pts, tmp, t);
109 // clamp to clean up imprecise numerics in the chop
110 tmp[2].fY = clip.fTop;
111 clamp_ge(tmp[3].fY, clip.fTop);
112
113 pts[0] = tmp[2];
114 pts[1] = tmp[3];
115 } else {
116 // if chopMonoQuadAtY failed, then we may have hit inexact numerics
117 // so we just clamp against the top
118 for (int i = 0; i < 3; i++) {
119 if (pts[i].fY < clip.fTop) {
120 pts[i].fY = clip.fTop;
121 }
122 }
123 }
124 }
125
126 // are we partially below
127 if (pts[2].fY > clip.fBottom) {
128 if (chopMonoQuadAtY(pts, clip.fBottom, &t)) {
129 SkChopQuadAt(pts, tmp, t);
130 // clamp to clean up imprecise numerics in the chop
131 clamp_le(tmp[1].fY, clip.fBottom);
132 tmp[2].fY = clip.fBottom;
133
134 pts[1] = tmp[1];
135 pts[2] = tmp[2];
136 } else {
137 // if chopMonoQuadAtY failed, then we may have hit inexact numerics
138 // so we just clamp against the bottom
139 for (int i = 0; i < 3; i++) {
140 if (pts[i].fY > clip.fBottom) {
141 pts[i].fY = clip.fBottom;
142 }
143 }
144 }
145 }
146}
static bool chopMonoQuadAtY(SkPoint pts[3], SkScalar y, SkScalar *t)
void SkChopQuadAt(const SkPoint src[3], SkPoint dst[5], SkScalar t)
Definition: SkGeometry.cpp:175
float SkScalar
Definition: extension.cpp:12

◆ chopMonoQuadAt()

static bool chopMonoQuadAt ( SkScalar  c0,
SkScalar  c1,
SkScalar  c2,
SkScalar  target,
SkScalar t 
)
static

Definition at line 72 of file SkEdgeClipper.cpp.

73 {
74 /* Solve F(t) = y where F(t) := [0](1-t)^2 + 2[1]t(1-t) + [2]t^2
75 * We solve for t, using quadratic equation, hence we have to rearrange
76 * our cooefficents to look like At^2 + Bt + C
77 */
78 SkScalar A = c0 - c1 - c1 + c2;
79 SkScalar B = 2*(c1 - c0);
80 SkScalar C = c0 - target;
81
82 SkScalar roots[2]; // we only expect one, but make room for 2 for safety
84 if (count) {
85 *t = roots[0];
86 return true;
87 }
88 return false;
89}
int count
Definition: FontMgrTest.cpp:50
int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2])
Definition: SkGeometry.cpp:95
uint32_t * target

◆ chopMonoQuadAtX()

static bool chopMonoQuadAtX ( SkPoint  pts[3],
SkScalar  x,
SkScalar t 
)
static

Definition at line 95 of file SkEdgeClipper.cpp.

95 {
96 return chopMonoQuadAt(pts[0].fX, pts[1].fX, pts[2].fX, x, t);
97}
static bool chopMonoQuadAt(SkScalar c0, SkScalar c1, SkScalar c2, SkScalar target, SkScalar *t)

◆ chopMonoQuadAtY()

static bool chopMonoQuadAtY ( SkPoint  pts[3],
SkScalar  y,
SkScalar t 
)
static

Definition at line 91 of file SkEdgeClipper.cpp.

91 {
92 return chopMonoQuadAt(pts[0].fY, pts[1].fY, pts[2].fY, y, t);
93}

◆ clamp_ge()

static void clamp_ge ( SkScalar value,
SkScalar  min 
)
inlinestatic

Definition at line 30 of file SkEdgeClipper.cpp.

30 {
31 if (value < min) {
32 value = min;
33 }
34}
uint8_t value
static float min(float r, float g, float b)
Definition: hsl.cpp:48

◆ clamp_le()

static void clamp_le ( SkScalar value,
SkScalar  max 
)
inlinestatic

Definition at line 24 of file SkEdgeClipper.cpp.

24 {
25 if (value > max) {
26 value = max;
27 }
28}
static float max(float r, float g, float b)
Definition: hsl.cpp:49

◆ compute_cubic_bounds()

static SkRect compute_cubic_bounds ( const SkPoint  pts[4])
static

Definition at line 405 of file SkEdgeClipper.cpp.

405 {
406 SkRect r;
407 r.setBounds(pts, 4);
408 return r;
409}
void setBounds(const SkPoint pts[], int count)
Definition: SkRect.h:881

◆ mono_cubic_closestT()

static SkScalar mono_cubic_closestT ( const SkScalar  src[],
SkScalar  x 
)
static

Definition at line 255 of file SkEdgeClipper.cpp.

255 {
256 SkScalar t = 0.5f;
257 SkScalar lastT;
259 SkScalar step = 0.25f;
260 SkScalar D = src[0];
261 SkScalar A = src[6] + 3*(src[2] - src[4]) - D;
262 SkScalar B = 3*(src[4] - src[2] - src[2] + D);
263 SkScalar C = 3*(src[2] - D);
264 x -= D;
265 SkScalar closest = SK_ScalarMax;
266 do {
267 SkScalar loc = ((A * t + B) * t + C) * t;
268 SkScalar dist = SkScalarAbs(loc - x);
269 if (closest > dist) {
270 closest = dist;
271 bestT = t;
272 }
273 lastT = t;
274 t += loc < x ? step : -step;
275 step *= 0.5f;
276 } while (closest > 0.25f && lastT != t);
277 return bestT;
278}
static int step(int x, SkScalar min, SkScalar max)
Definition: BlurTest.cpp:215
#define SK_INIT_TO_AVOID_WARNING
Definition: SkMacros.h:58
#define SK_ScalarMax
Definition: SkScalar.h:24
#define SkScalarAbs(x)
Definition: SkScalar.h:39
#define B

◆ quick_reject()

static bool quick_reject ( const SkRect bounds,
const SkRect clip 
)
static

Definition at line 20 of file SkEdgeClipper.cpp.

20 {
21 return bounds.fTop >= clip.fBottom || bounds.fBottom <= clip.fTop;
22}
Optional< SkRect > bounds
Definition: SkRecords.h:189

◆ sort_increasing_Y()

static bool sort_increasing_Y ( SkPoint  dst[],
const SkPoint  src[],
int  count 
)
static

Definition at line 40 of file SkEdgeClipper.cpp.

40 {
41 // we need the data to be monotonically increasing in Y
42 if (src[0].fY > src[count - 1].fY) {
43 for (int i = 0; i < count; i++) {
44 dst[i] = src[count - i - 1];
45 }
46 return true;
47 } else {
48 memcpy(dst, src, count * sizeof(SkPoint));
49 return false;
50 }
51}

◆ too_big_for_reliable_float_math()

static bool too_big_for_reliable_float_math ( const SkRect r)
static

Definition at line 411 of file SkEdgeClipper.cpp.

411 {
412 // limit set as the largest float value for which we can still reliably compute things like
413 // - chopping at XY extrema
414 // - chopping at Y or X values for clipping
415 //
416 // Current value chosen just by experiment. Larger (and still succeeds) is always better.
417 //
418 const SkScalar limit = 1 << 22;
419 return r.fLeft < -limit || r.fTop < -limit || r.fRight > limit || r.fBottom > limit;
420}
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15