Flutter Engine
The Flutter Engine
SkScan_AntiPath.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2006 The Android Open Source Project
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
9
10#include "include/core/SkRect.h"
14#include "src/core/SkAAClip.h"
15#include "src/core/SkBlitter.h"
17#include "src/core/SkScan.h"
18#include "src/core/SkScanPriv.h"
19
20#include <cstdint>
21
23 // roundOut will pin huge floats to max/min int
24 SkIRect dst = src.roundOut();
25
26 // intersect with a smaller huge rect, so the rect will not be considered empty for being
27 // too large. e.g. { -SK_MaxS32 ... SK_MaxS32 } is considered empty because its width
28 // exceeds signed 32bit.
29 const int32_t limit = SK_MaxS32 >> SK_SUPERSAMPLE_SHIFT;
30 (void)dst.intersect({ -limit, -limit, limit, limit});
31
32 return dst;
33}
34
35static int overflows_short_shift(int value, int shift) {
36 const int s = 16 + shift;
37 return (SkLeftShift(value, s) >> s) - value;
38}
39
40/**
41 Would any of the coordinates of this rectangle not fit in a short,
42 when left-shifted by shift?
43*/
44static int rect_overflows_short_shift(SkIRect rect, int shift) {
45 SkASSERT(!overflows_short_shift(8191, shift));
46 SkASSERT(overflows_short_shift(8192, shift));
49
50 // Since we expect these to succeed, we bit-or together
51 // for a tiny extra bit of speed.
52 return overflows_short_shift(rect.fLeft, shift) |
53 overflows_short_shift(rect.fRight, shift) |
54 overflows_short_shift(rect.fTop, shift) |
55 overflows_short_shift(rect.fBottom, shift);
56}
57
58void SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip,
59 SkBlitter* blitter, bool forceRLE) {
60 if (origClip.isEmpty()) {
61 return;
62 }
63
64 const bool isInverse = path.isInverseFillType();
65 SkIRect ir = safeRoundOut(path.getBounds());
66 if (ir.isEmpty()) {
67 if (isInverse) {
68 blitter->blitRegion(origClip);
69 }
70 return;
71 }
72
73 // If the intersection of the path bounds and the clip bounds
74 // will overflow 32767 when << by SHIFT, we can't supersample,
75 // so draw without antialiasing.
76 SkIRect clippedIR;
77 if (isInverse) {
78 // If the path is an inverse fill, it's going to fill the entire
79 // clip, and we care whether the entire clip exceeds our limits.
80 clippedIR = origClip.getBounds();
81 } else {
82 if (!clippedIR.intersect(ir, origClip.getBounds())) {
83 return;
84 }
85 }
87 SkScan::FillPath(path, origClip, blitter);
88 return;
89 }
90
91 // Our antialiasing can't handle a clip larger than 32767, so we restrict
92 // the clip to that limit here. (the runs[] uses int16_t for its index).
93 //
94 // A more general solution (one that could also eliminate the need to
95 // disable aa based on ir bounds (see overflows_short_shift) would be
96 // to tile the clip/target...
97 SkRegion tmpClipStorage;
98 const SkRegion* clipRgn = &origClip;
99 {
100 static const int32_t kMaxClipCoord = 32767;
101 const SkIRect& bounds = origClip.getBounds();
102 if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) {
103 SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord };
104 tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op);
105 clipRgn = &tmpClipStorage;
106 }
107 }
108 // for here down, use clipRgn, not origClip
109
110 SkScanClipper clipper(blitter, clipRgn, ir);
111
112 if (clipper.getBlitter() == nullptr) { // clipped out
113 if (isInverse) {
114 blitter->blitRegion(*clipRgn);
115 }
116 return;
117 }
118
119 SkASSERT(clipper.getClipRect() == nullptr ||
120 *clipper.getClipRect() == clipRgn->getBounds());
121
122 // now use the (possibly wrapped) blitter
123 blitter = clipper.getBlitter();
124
125 if (isInverse) {
126 sk_blit_above(blitter, ir, *clipRgn);
127 }
128
129 SkScan::AAAFillPath(path, blitter, ir, clipRgn->getBounds(), forceRLE);
130
131 if (isInverse) {
132 sk_blit_below(blitter, ir, *clipRgn);
133 }
134}
135
136///////////////////////////////////////////////////////////////////////////////
137
138void SkScan::FillPath(const SkPath& path, const SkRasterClip& clip, SkBlitter* blitter) {
139 if (clip.isEmpty() || !path.isFinite()) {
140 return;
141 }
142
143 if (clip.isBW()) {
144 FillPath(path, clip.bwRgn(), blitter);
145 } else {
146 SkRegion tmp;
147 SkAAClipBlitter aaBlitter;
148
149 tmp.setRect(clip.getBounds());
150 aaBlitter.init(blitter, &clip.aaRgn());
151 SkScan::FillPath(path, tmp, &aaBlitter);
152 }
153}
154
156 if (clip.isEmpty() || !path.isFinite()) {
157 return;
158 }
159
160 if (clip.isBW()) {
161 AntiFillPath(path, clip.bwRgn(), blitter, false);
162 } else {
163 SkRegion tmp;
164 SkAAClipBlitter aaBlitter;
165
166 tmp.setRect(clip.getBounds());
167 aaBlitter.init(blitter, &clip.aaRgn());
168 AntiFillPath(path, tmp, &aaBlitter, true); // SkAAClipBlitter can blitMask, why forceRLE?
169 }
170}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static constexpr int32_t SkLeftShift(int32_t value, int32_t shift)
Definition: SkMath.h:37
static constexpr int32_t SK_MaxS32
Definition: SkMath.h:21
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
Definition: SkPath.cpp:3892
#define SK_SUPERSAMPLE_SHIFT
Definition: SkScanPriv.h:16
static int rect_overflows_short_shift(SkIRect rect, int shift)
static SkIRect safeRoundOut(const SkRect &src)
static int overflows_short_shift(int value, int shift)
void sk_blit_below(SkBlitter *blitter, const SkIRect &ir, const SkRegion &clip)
void sk_blit_above(SkBlitter *blitter, const SkIRect &ir, const SkRegion &clip)
void init(SkBlitter *blitter, const SkAAClip *aaclip)
Definition: SkAAClip.h:97
void blitRegion(const SkRegion &clip)
Definition: SkBlitter.cpp:310
Definition: SkPath.h:59
bool isEmpty() const
Definition: SkPath.cpp:416
const SkRect & getBounds() const
Definition: SkPath.cpp:430
@ kIntersect_Op
target intersected with operand
Definition: SkRegion.h:368
const SkIRect & getBounds() const
Definition: SkRegion.h:165
bool op(const SkIRect &rect, Op op)
Definition: SkRegion.h:384
bool setRect(const SkIRect &rect)
Definition: SkRegion.cpp:192
bool isEmpty() const
Definition: SkRegion.h:146
static void AntiFillPath(const SkPath &, const SkRasterClip &, SkBlitter *)
static void FillPath(const SkPath &, const SkIRect &, SkBlitter *)
struct MyStruct s
uint8_t value
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
dst
Definition: cp.py:12
Definition: SkRect.h:32
bool intersect(const SkIRect &r)
Definition: SkRect.h:513
bool isEmpty() const
Definition: SkRect.h:202