OLD | NEW |
| (Empty) |
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 | |
36 virtual void blitAntiH(int x, int y, const SkAlpha antialias[], | |
37 const int16_t runs[]) { | |
38 SkASSERT(!"How did I get here?"); | |
39 } | |
40 virtual void blitV(int x, int y, int height, SkAlpha alpha) { | |
41 SkASSERT(!"How did I get here?"); | |
42 } | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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.getS
topAlpha(), 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); | |
198 virtual ~MaskSuperBlitter() { | |
199 fRealBlitter->blitMask(fMask, fClipRect); | |
200 } | |
201 | |
202 virtual void blitH(int x, int y, int width); | |
203 | |
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 en
d, rather than | |
222 // perform a test to see if stopAlpha != 0 | |
223 uint32_t fStorage[(kMAX_STORAGE >> 2) + 1]; | |
224 }; | |
225 | |
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 | |
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 | |
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 s
pace | |
278 // (see the + 1 comment in fStorage[] | |
279 *alpha = SkToU8(*alpha + stopAlpha); | |
280 } | |
281 | |
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 #ifdef SK_DEBUG | |
290 { | |
291 int ix = x >> SHIFT; | |
292 SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight); | |
293 } | |
294 #endif | |
295 | |
296 x -= (fMask.fBounds.fLeft << SHIFT); | |
297 | |
298 // hack, until I figure out why my cubics (I think) go beyond the bounds | |
299 if (x < 0) | |
300 { | |
301 width += x; | |
302 x = 0; | |
303 } | |
304 | |
305 // we sub 1 from maxValue 1 time for each block, so that we don't | |
306 // hit 256 as a summed max, but 255. | |
307 // int maxValue = (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT); | |
308 | |
309 uint8_t* row = fMask.fImage + iy * fMask.fRowBytes + (x >> SHIFT); | |
310 | |
311 int start = x; | |
312 int stop = x + width; | |
313 | |
314 SkASSERT(start >= 0 && stop > start); | |
315 int fb = start & SUPER_Mask; | |
316 int fe = stop & SUPER_Mask; | |
317 int n = (stop >> SHIFT) - (start >> SHIFT) - 1; | |
318 | |
319 | |
320 if (n < 0) | |
321 { | |
322 add_aa_span(row, coverage_to_alpha(fe - fb)); | |
323 } | |
324 else | |
325 { | |
326 fb = (1 << SHIFT) - fb; | |
327 add_aa_span(row, coverage_to_alpha(fb), n, coverage_to_alpha(fe), | |
328 (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); | |
329 } | |
330 | |
331 #ifdef SK_DEBUG | |
332 fCurrX = x + width; | |
333 #endif | |
334 } | |
335 | |
336 /////////////////////////////////////////////////////////////////////////////// | |
337 | |
338 static int overflows_short(int value) { | |
339 return value - (short)value; | |
340 } | |
341 | |
342 void SkScan::AntiFillPath(const SkPath& path, const SkRegion& clip, | |
343 SkBlitter* blitter) { | |
344 if (clip.isEmpty()) { | |
345 return; | |
346 } | |
347 | |
348 SkRect r; | |
349 SkIRect ir; | |
350 | |
351 path.computeBounds(&r, SkPath::kFast_BoundsType); | |
352 r.roundOut(&ir); | |
353 if (ir.isEmpty()) { | |
354 return; | |
355 } | |
356 | |
357 if (overflows_short(ir.fLeft << SHIFT) || | |
358 overflows_short(ir.fRight << SHIFT) || | |
359 overflows_short(ir.width() << SHIFT) || | |
360 overflows_short(ir.fTop << SHIFT) || | |
361 overflows_short(ir.fBottom << SHIFT) || | |
362 overflows_short(ir.height() << SHIFT)) { | |
363 // can't supersample, try drawing w/o antialiasing | |
364 SkScan::FillPath(path, clip, blitter); | |
365 return; | |
366 } | |
367 | |
368 SkScanClipper clipper(blitter, &clip, ir); | |
369 const SkIRect* clipRect = clipper.getClipRect(); | |
370 | |
371 if (clipper.getBlitter() == NULL) { // clipped out | |
372 if (path.isInverseFillType()) { | |
373 blitter->blitRegion(clip); | |
374 } | |
375 return; | |
376 } | |
377 | |
378 // now use the (possibly wrapped) blitter | |
379 blitter = clipper.getBlitter(); | |
380 | |
381 if (path.isInverseFillType()) { | |
382 sk_blit_above_and_below(blitter, ir, clip); | |
383 } | |
384 | |
385 SkIRect superRect, *superClipRect = NULL; | |
386 | |
387 if (clipRect) | |
388 { | |
389 superRect.set( clipRect->fLeft << SHIFT, clipRect->fTop << SHIFT, | |
390 clipRect->fRight << SHIFT, clipRect->fBottom << SHIFT); | |
391 superClipRect = &superRect; | |
392 } | |
393 | |
394 // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it | |
395 // if we're an inverse filltype | |
396 if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir)) | |
397 { | |
398 MaskSuperBlitter superBlit(blitter, ir, clip); | |
399 sk_fill_path(path, superClipRect, &superBlit, ir.fBottom, SHIFT, clip); | |
400 } | |
401 else | |
402 { | |
403 SuperBlitter superBlit(blitter, ir, clip); | |
404 sk_fill_path(path, superClipRect, &superBlit, ir.fBottom, SHIFT, clip); | |
405 } | |
406 } | |
OLD | NEW |