1 /* libs/graphics/sgl/SkScan_AntiPath.cpp
2 **
3 ** Copyright 2006, The Android Open Source Project
4 **
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
8 **
9 ** http://www.apache.org/licenses/LICENSE-2.0
10 **
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
16 */
17
18 #include "SkScanPriv.h"
19 #include "SkPath.h"
20 #include "SkMatrix.h"
21 #include "SkBlitter.h"
22 #include "SkRegion.h"
23 #include "SkAntiRun.h"
24
25 #define SHIFT 2
26 #define SCALE (1 << SHIFT)
27 #define MASK (SCALE - 1)
28
29 ///////////////////////////////////////////////////////////////////////////////////////////
30
31 class BaseSuperBlitter : public SkBlitter {
32 public:
33 BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
34 const SkRegion& clip);
35
blitAntiH(int x,int y,const SkAlpha antialias[],const int16_t runs[])36 virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
37 const int16_t runs[]) {
38 SkASSERT(!"How did I get here?");
39 }
blitV(int x,int y,int height,SkAlpha alpha)40 virtual void blitV(int x, int y, int height, SkAlpha alpha) {
41 SkASSERT(!"How did I get here?");
42 }
blitRect(int x,int y,int width,int height)43 virtual void blitRect(int x, int y, int width, int height) {
44 SkASSERT(!"How did I get here?");
45 }
46
47 protected:
48 SkBlitter* fRealBlitter;
49 int fCurrIY;
50 int fWidth, fLeft, fSuperLeft;
51
52 SkDEBUGCODE(int fCurrX;)
53 SkDEBUGCODE(int fCurrY;)
54 };
55
BaseSuperBlitter(SkBlitter * realBlitter,const SkIRect & ir,const SkRegion & clip)56 BaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
57 const SkRegion& clip) {
58 fRealBlitter = realBlitter;
59
60 // take the union of the ir bounds and clip, since we may be called with an
61 // inverse filltype
62 const int left = SkMin32(ir.fLeft, clip.getBounds().fLeft);
63 const int right = SkMax32(ir.fRight, clip.getBounds().fRight);
64
65 fLeft = left;
66 fSuperLeft = left << SHIFT;
67 fWidth = right - left;
68 fCurrIY = -1;
69 SkDEBUGCODE(fCurrX = -1; fCurrY = -1;)
70 }
71
72 class SuperBlitter : public BaseSuperBlitter {
73 public:
74 SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
75 const SkRegion& clip);
76
~SuperBlitter()77 virtual ~SuperBlitter() {
78 this->flush();
79 sk_free(fRuns.fRuns);
80 }
81
82 void flush();
83
84 virtual void blitH(int x, int y, int width);
85
86 private:
87 SkAlphaRuns fRuns;
88 };
89
SuperBlitter(SkBlitter * realBlitter,const SkIRect & ir,const SkRegion & clip)90 SuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
91 const SkRegion& clip)
92 : BaseSuperBlitter(realBlitter, ir, clip) {
93 const int width = fWidth;
94
95 // extra one to store the zero at the end
96 fRuns.fRuns = (int16_t*)sk_malloc_throw((width + 1 + (width + 2)/2) * sizeof(int16_t));
97 fRuns.fAlpha = (uint8_t*)(fRuns.fRuns + width + 1);
98 fRuns.reset(width);
99 }
100
flush()101 void SuperBlitter::flush()
102 {
103 if (fCurrIY >= 0)
104 {
105 if (!fRuns.empty())
106 {
107 // SkDEBUGCODE(fRuns.dump();)
108 fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns);
109 fRuns.reset(fWidth);
110 }
111 fCurrIY = -1;
112 SkDEBUGCODE(fCurrX = -1;)
113 }
114 }
115
coverage_to_alpha(int aa)116 static inline int coverage_to_alpha(int aa)
117 {
118 aa <<= 8 - 2*SHIFT;
119 aa -= aa >> (8 - SHIFT - 1);
120 return aa;
121 }
122
123 #define SUPER_Mask ((1 << SHIFT) - 1)
124
blitH(int x,int y,int width)125 void SuperBlitter::blitH(int x, int y, int width)
126 {
127 int iy = y >> SHIFT;
128 SkASSERT(iy >= fCurrIY);
129
130 x -= fSuperLeft;
131 // hack, until I figure out why my cubics (I think) go beyond the bounds
132 if (x < 0)
133 {
134 width += x;
135 x = 0;
136 }
137
138 #ifdef SK_DEBUG
139 SkASSERT(y >= fCurrY);
140 SkASSERT(y != fCurrY || x >= fCurrX);
141 fCurrY = y;
142 #endif
143
144 if (iy != fCurrIY) // new scanline
145 {
146 this->flush();
147 fCurrIY = iy;
148 }
149
150 // we sub 1 from maxValue 1 time for each block, so that we don't
151 // hit 256 as a summed max, but 255.
152 // int maxValue = (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT);
153
154 #if 0
155 SkAntiRun<SHIFT> arun;
156 arun.set(x, x + width);
157 fRuns.add(x >> SHIFT, arun.getStartAlpha(), arun.getMiddleCount(), arun.getStopAlpha(), maxValue);
158 #else
159 {
160 int start = x;
161 int stop = x + width;
162
163 SkASSERT(start >= 0 && stop > start);
164 int fb = start & SUPER_Mask;
165 int fe = stop & SUPER_Mask;
166 int n = (stop >> SHIFT) - (start >> SHIFT) - 1;
167
168 if (n < 0)
169 {
170 fb = fe - fb;
171 n = 0;
172 fe = 0;
173 }
174 else
175 {
176 if (fb == 0)
177 n += 1;
178 else
179 fb = (1 << SHIFT) - fb;
180 }
181 fRuns.add(x >> SHIFT, coverage_to_alpha(fb), n, coverage_to_alpha(fe),
182 (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT));
183 }
184 #endif
185
186 #ifdef SK_DEBUG
187 fRuns.assertValid(y & MASK, (1 << (8 - SHIFT)));
188 fCurrX = x + width;
189 #endif
190 }
191
192 ///////////////////////////////////////////////////////////////////////////////
193
194 class MaskSuperBlitter : public BaseSuperBlitter {
195 public:
196 MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
197 const SkRegion& clip);
~MaskSuperBlitter()198 virtual ~MaskSuperBlitter() {
199 fRealBlitter->blitMask(fMask, fClipRect);
200 }
201
202 virtual void blitH(int x, int y, int width);
203
CanHandleRect(const SkIRect & bounds)204 static bool CanHandleRect(const SkIRect& bounds)
205 {
206 int width = bounds.width();
207 int rb = SkAlign4(width);
208
209 return (width <= MaskSuperBlitter::kMAX_WIDTH) &&
210 (rb * bounds.height() <= MaskSuperBlitter::kMAX_STORAGE);
211 }
212
213 private:
214 enum {
215 kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster
216 kMAX_STORAGE = 1024
217 };
218
219 SkMask fMask;
220 SkIRect fClipRect;
221 // we add 1 because add_aa_span can write (unchanged) 1 extra byte at the end, rather than
222 // perform a test to see if stopAlpha != 0
223 uint32_t fStorage[(kMAX_STORAGE >> 2) + 1];
224 };
225
MaskSuperBlitter(SkBlitter * realBlitter,const SkIRect & ir,const SkRegion & clip)226 MaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir,
227 const SkRegion& clip)
228 : BaseSuperBlitter(realBlitter, ir, clip) {
229 SkASSERT(CanHandleRect(ir));
230
231 fMask.fImage = (uint8_t*)fStorage;
232 fMask.fBounds = ir;
233 fMask.fRowBytes = ir.width();
234 fMask.fFormat = SkMask::kA8_Format;
235
236 fClipRect = ir;
237 fClipRect.intersect(clip.getBounds());
238
239 // For valgrind, write 1 extra byte at the end so we don't read
240 // uninitialized memory. See comment in add_aa_span and fStorage[].
241 memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1);
242 }
243
add_aa_span(uint8_t * alpha,U8CPU startAlpha)244 static void add_aa_span(uint8_t* alpha, U8CPU startAlpha)
245 {
246 /* I should be able to just add alpha[x] + startAlpha.
247 However, if the trailing edge of the previous span and the leading
248 edge of the current span round to the same super-sampled x value,
249 I might overflow to 256 with this add, hence the funny subtract.
250 */
251 unsigned tmp = *alpha + startAlpha;
252 SkASSERT(tmp <= 256);
253 *alpha = SkToU8(tmp - (tmp >> 8));
254 }
255
add_aa_span(uint8_t * alpha,U8CPU startAlpha,int middleCount,U8CPU stopAlpha,U8CPU maxValue)256 static void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, U8CPU stopAlpha, U8CPU maxValue)
257 {
258 SkASSERT(middleCount >= 0);
259
260 /* I should be able to just add alpha[x] + startAlpha.
261 However, if the trailing edge of the previous span and the leading
262 edge of the current span round to the same super-sampled x value,
263 I might overflow to 256 with this add, hence the funny subtract.
264 */
265 unsigned tmp = *alpha + startAlpha;
266 SkASSERT(tmp <= 256);
267 *alpha++ = SkToU8(tmp - (tmp >> 8));
268
269 while (--middleCount >= 0)
270 {
271 alpha[0] = SkToU8(alpha[0] + maxValue);
272 alpha += 1;
273 }
274
275 // potentially this can be off the end of our "legal" alpha values, but that
276 // only happens if stopAlpha is also 0. Rather than test for stopAlpha != 0
277 // every time (slow), we just do it, and ensure that we've allocated extra space
278 // (see the + 1 comment in fStorage[]
279 *alpha = SkToU8(*alpha + stopAlpha);
280 }
281
blitH(int x,int y,int width)282 void MaskSuperBlitter::blitH(int x, int y, int width)
283 {
284 int iy = (y >> SHIFT);
285
286 SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom);
287 iy -= fMask.fBounds.fTop; // make it relative to 0
288
289 // This should never happen, but it does. Until the true cause is
290 // discovered, let's skip this span instead of crashing.
291 // See http://crbug.com/17569.
292 if (iy < 0) {
293 return;
294 }
295
296 #ifdef SK_DEBUG
297 {
298 int ix = x >> SHIFT;
299 SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight);
300 }
301 #endif
302
303 x -= (fMask.fBounds.fLeft << SHIFT);
304
305 // hack, until I figure out why my cubics (I think) go beyond the bounds
306 if (x < 0)
307 {
308 width += x;
309 x = 0;
310 }
311
312 // we sub 1 from maxValue 1 time for each block, so that we don't
313 // hit 256 as a summed max, but 255.
314 // int maxValue = (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT);
315
316 uint8_t* row = fMask.fImage + iy * fMask.fRowBytes + (x >> SHIFT);
317
318 int start = x;
319 int stop = x + width;
320
321 SkASSERT(start >= 0 && stop > start);
322 int fb = start & SUPER_Mask;
323 int fe = stop & SUPER_Mask;
324 int n = (stop >> SHIFT) - (start >> SHIFT) - 1;
325
326
327 if (n < 0)
328 {
329 SkASSERT(row >= fMask.fImage);
330 SkASSERT(row < fMask.fImage + kMAX_STORAGE + 1);
331 add_aa_span(row, coverage_to_alpha(fe - fb));
332 }
333 else
334 {
335 fb = (1 << SHIFT) - fb;
336 SkASSERT(row >= fMask.fImage);
337 SkASSERT(row + n + 1 < fMask.fImage + kMAX_STORAGE + 1);
338 add_aa_span(row, coverage_to_alpha(fb), n, coverage_to_alpha(fe),
339 (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT));
340 }
341
342 #ifdef SK_DEBUG
343 fCurrX = x + width;
344 #endif
345 }
346
347 ///////////////////////////////////////////////////////////////////////////////
348
349 /* Returns non-zero if (value << shift) overflows a short, which would mean
350 we could not shift it up and then convert to SkFixed.
351 i.e. is x expressible as signed (16-shift) bits?
352 */
overflows_short_shift(int value,int shift)353 static int overflows_short_shift(int value, int shift) {
354 const int s = 16 + shift;
355 return (value << s >> s) - value;
356 }
357
AntiFillPath(const SkPath & path,const SkRegion & clip,SkBlitter * blitter)358 void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip,
359 SkBlitter* blitter) {
360 if (clip.isEmpty()) {
361 return;
362 }
363
364 SkIRect ir;
365 path.getBounds().roundOut(&ir);
366 if (ir.isEmpty()) {
367 return;
368 }
369 SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
370
371 // use bit-or since we expect all to pass, so no need to go slower with
372 // a short-circuiting logical-or
373 if (overflows_short_shift(ir.fLeft, SHIFT) |
374 overflows_short_shift(ir.fRight, SHIFT) |
375 overflows_short_shift(ir.fTop, SHIFT) |
376 overflows_short_shift(ir.fBottom, SHIFT)) {
377 // can't supersample, so draw w/o antialiasing
378 SkScan::FillPath(path, clip, blitter);
379 return;
380 }
381
382 SkScanClipper clipper(blitter, &clip, ir);
383 const SkIRect* clipRect = clipper.getClipRect();
384
385 if (clipper.getBlitter() == NULL) { // clipped out
386 if (path.isInverseFillType()) {
387 blitter->blitRegion(clip);
388 }
389 return;
390 }
391
392 // now use the (possibly wrapped) blitter
393 blitter = clipper.getBlitter();
394
395 if (path.isInverseFillType()) {
396 sk_blit_above_and_below(blitter, ir, clip);
397 }
398
399 SkIRect superRect, *superClipRect = NULL;
400
401 if (clipRect)
402 {
403 superRect.set( clipRect->fLeft << SHIFT, clipRect->fTop << SHIFT,
404 clipRect->fRight << SHIFT, clipRect->fBottom << SHIFT);
405 superClipRect = &superRect;
406 }
407
408 SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
409
410 // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it
411 // if we're an inverse filltype
412 if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir))
413 {
414 MaskSuperBlitter superBlit(blitter, ir, clip);
415 SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop);
416 sk_fill_path(path, superClipRect, &superBlit, ir.fBottom, SHIFT, clip);
417 }
418 else
419 {
420 SuperBlitter superBlit(blitter, ir, clip);
421 sk_fill_path(path, superClipRect, &superBlit, ir.fBottom, SHIFT, clip);
422 }
423 }
424