| 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 |