• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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