Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Macros | Functions | Variables
SkRegionPriv.h File Reference
#include "include/core/SkRegion.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkMath.h"
#include "include/private/base/SkTo.h"
#include <atomic>
#include <functional>

Go to the source code of this file.

Classes

class  SkRegionPriv
 
struct  SkRegion::RunHead
 

Macros

#define assert_sentinel(value, isSentinel)    SkASSERT(SkRegionValueIsSentinel(value) == isSentinel)
 

Functions

bool SkRegionValueIsSentinel (int32_t value)
 

Variables

static constexpr int SkRegion_kRunTypeSentinel = 0x7FFFFFFF
 

Macro Definition Documentation

◆ assert_sentinel

#define assert_sentinel (   value,
  isSentinel 
)     SkASSERT(SkRegionValueIsSentinel(value) == isSentinel)

Definition at line 41 of file SkRegionPriv.h.

47 {
48 const SkRegionPriv::RunType* curr = runs;
49 while (*curr < SkRegion_kRunTypeSentinel) {
50 SkASSERT(curr[0] < curr[1]);
52 curr += 2;
53 }
54 return SkToInt((curr - runs) >> 1);
55}
56#endif
57
58struct SkRegion::RunHead {
59private:
60
61public:
62 std::atomic<int32_t> fRefCnt;
63 int32_t fRunCount;
64
65 /**
66 * Number of spans with different Y values. This does not count the initial
67 * Top value, nor does it count the final Y-Sentinel value. In the logical
68 * case of a rectangle, this would return 1, and an empty region would
69 * return 0.
70 */
71 int getYSpanCount() const {
72 return fYSpanCount;
73 }
74
75 /**
76 * Number of intervals in the entire region. This equals the number of
77 * rects that would be returned by the Iterator. In the logical case of
78 * a rect, this would return 1, and an empty region would return 0.
79 */
80 int getIntervalCount() const {
81 return fIntervalCount;
82 }
83
84 static RunHead* Alloc(int count) {
85 if (count < SkRegion::kRectRegionRuns) {
86 return nullptr;
87 }
88
89 const int64_t size = sk_64_mul(count, sizeof(RunType)) + sizeof(RunHead);
90 if (count < 0 || !SkTFitsIn<int32_t>(size)) { SK_ABORT("Invalid Size"); }
91
92 RunHead* head = (RunHead*)sk_malloc_throw(size);
93 head->fRefCnt = 1;
94 head->fRunCount = count;
95 // these must be filled in later, otherwise we will be invalid
96 head->fYSpanCount = 0;
97 head->fIntervalCount = 0;
98 return head;
99 }
100
101 static RunHead* Alloc(int count, int yspancount, int intervalCount) {
102 if (yspancount <= 0 || intervalCount <= 1) {
103 return nullptr;
104 }
105
106 RunHead* head = Alloc(count);
107 if (!head) {
108 return nullptr;
109 }
110 head->fYSpanCount = yspancount;
111 head->fIntervalCount = intervalCount;
112 return head;
113 }
114
115 SkRegion::RunType* writable_runs() {
116 SkASSERT(fRefCnt == 1);
117 return (SkRegion::RunType*)(this + 1);
118 }
119
120 const SkRegion::RunType* readonly_runs() const {
121 return (const SkRegion::RunType*)(this + 1);
122 }
123
124 RunHead* ensureWritable() {
125 RunHead* writable = this;
126 if (fRefCnt > 1) {
127 // We need to alloc & copy the current region before decrease
128 // the refcount because it could be freed in the meantime.
129 writable = Alloc(fRunCount, fYSpanCount, fIntervalCount);
130 memcpy(writable->writable_runs(), this->readonly_runs(),
131 fRunCount * sizeof(RunType));
132
133 // fRefCount might have changed since we last checked.
134 // If we own the last reference at this point, we need to
135 // free the memory.
136 if (--fRefCnt == 0) {
137 sk_free(this);
138 }
139 }
140 return writable;
141 }
142
143 /**
144 * Given a scanline (including its Bottom value at runs[0]), return the next
145 * scanline. Asserts that there is one (i.e. runs[0] < Sentinel)
146 */
147 static SkRegion::RunType* SkipEntireScanline(const SkRegion::RunType runs[]) {
148 // we are not the Y Sentinel
150
151 const int intervals = runs[1];
152 SkASSERT(runs[2 + intervals * 2] == SkRegion_kRunTypeSentinel);
153#ifdef SK_DEBUG
154 {
155 int n = compute_intervalcount(&runs[2]);
156 SkASSERT(n == intervals);
157 }
158#endif
159
160 // skip the entire line [B N [L R] S]
161 runs += 1 + 1 + intervals * 2 + 1;
162 return const_cast<SkRegion::RunType*>(runs);
163 }
164
165
166 /**
167 * Return the scanline that contains the Y value. This requires that the Y
168 * value is already known to be contained within the bounds of the region,
169 * and so this routine never returns nullptr.
170 *
171 * It returns the beginning of the scanline, starting with its Bottom value.
172 */
173 SkRegion::RunType* findScanline(int y) const {
174 const RunType* runs = this->readonly_runs();
175
176 // if the top-check fails, we didn't do a quick check on the bounds
177 SkASSERT(y >= runs[0]);
178
179 runs += 1; // skip top-Y
180 for (;;) {
181 int bottom = runs[0];
182 // If we hit this, we've walked off the region, and our bounds check
183 // failed.
185 if (y < bottom) {
186 break;
187 }
188 runs = SkipEntireScanline(runs);
189 }
190 return const_cast<SkRegion::RunType*>(runs);
191 }
192
193 // Copy src runs into us, computing interval counts and bounds along the way
194 void computeRunBounds(SkIRect* bounds) {
195 RunType* runs = this->writable_runs();
196 bounds->fTop = *runs++;
197
198 int bot;
199 int ySpanCount = 0;
200 int intervalCount = 0;
201 int left = SK_MaxS32;
202 int rite = SK_MinS32;
203
204 do {
205 bot = *runs++;
207 ySpanCount += 1;
208
209 const int intervals = *runs++;
210 SkASSERT(intervals >= 0);
212
213 if (intervals > 0) {
214#ifdef SK_DEBUG
215 {
216 int n = compute_intervalcount(runs);
217 SkASSERT(n == intervals);
218 }
219#endif
220 RunType L = runs[0];
222 if (left > L) {
223 left = L;
224 }
225
226 runs += intervals * 2;
227 RunType R = runs[-1];
229 if (rite < R) {
230 rite = R;
231 }
232
233 intervalCount += intervals;
234 }
236 runs += 1; // skip x-sentinel
237
238 // test Y-sentinel
239 } while (SkRegion_kRunTypeSentinel > *runs);
240
241#ifdef SK_DEBUG
242 // +1 to skip the last Y-sentinel
243 int runCount = SkToInt(runs - this->writable_runs() + 1);
244 SkASSERT(runCount == fRunCount);
245#endif
246
247 fYSpanCount = ySpanCount;
248 fIntervalCount = intervalCount;
249
250 bounds->fLeft = left;
251 bounds->fRight = rite;
252 bounds->fBottom = bot;
253 }
254
255private:
256 int32_t fYSpanCount;
257 int32_t fIntervalCount;
258};
259
260#endif
int count
#define SK_ABORT(message,...)
Definition SkAssert.h:70
#define SkASSERT(cond)
Definition SkAssert.h:116
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
Definition SkMalloc.h:67
static int64_t sk_64_mul(int64_t a, int64_t b)
Definition SkMath.h:33
static constexpr int32_t SK_MinS32
Definition SkMath.h:22
static constexpr int32_t SK_MaxS32
Definition SkMath.h:21
static bool left(const SkPoint &p0, const SkPoint &p1)
static constexpr int SkRegion_kRunTypeSentinel
constexpr int SkToInt(S x)
Definition SkTo.h:29
SkRegion::RunType RunType
#define R(r)
double y
Optional< SkRect > bounds
Definition SkRecords.h:189
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition switches.h:259
int32_t fTop
smaller y-axis bounds
Definition SkRect.h:34
SkRegion::RunType * writable_runs()
static RunHead * Alloc(int count)
const SkRegion::RunType * readonly_runs() const
void computeRunBounds(SkIRect *bounds)
RunHead * ensureWritable()
int getYSpanCount() const
int getIntervalCount() const
static SkRegion::RunType * SkipEntireScanline(const SkRegion::RunType runs[])
SkRegion::RunType * findScanline(int y) const
std::atomic< int32_t > fRefCnt

Function Documentation

◆ SkRegionValueIsSentinel()

bool SkRegionValueIsSentinel ( int32_t  value)
inline

Definition at line 37 of file SkRegionPriv.h.

37 {
38 return value == (int32_t)SkRegion_kRunTypeSentinel;
39}
uint8_t value

Variable Documentation

◆ SkRegion_kRunTypeSentinel

constexpr int SkRegion_kRunTypeSentinel = 0x7FFFFFFF
staticconstexpr

Definition at line 35 of file SkRegionPriv.h.