Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "SkBlitter.h"
     11 #include "SkAntiRun.h"
     12 #include "SkColor.h"
     13 #include "SkColorFilter.h"
     14 #include "SkMask.h"
     15 #include "SkMaskFilter.h"
     16 #include "SkTemplatesPriv.h"
     17 #include "SkUtils.h"
     18 #include "SkXfermode.h"
     19 
     20 SkBlitter::~SkBlitter() {}
     21 
     22 const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
     23     return NULL;
     24 }
     25 
     26 void SkBlitter::blitH(int x, int y, int width) {
     27     SkDEBUGFAIL("unimplemented");
     28 }
     29 
     30 void SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
     31                           const int16_t runs[]) {
     32     SkDEBUGFAIL("unimplemented");
     33 }
     34 
     35 void SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
     36     if (alpha == 255) {
     37         this->blitRect(x, y, 1, height);
     38     } else {
     39         int16_t runs[2];
     40         runs[0] = 1;
     41         runs[1] = 0;
     42 
     43         while (--height >= 0) {
     44             this->blitAntiH(x, y++, &alpha, runs);
     45         }
     46     }
     47 }
     48 
     49 void SkBlitter::blitRect(int x, int y, int width, int height) {
     50     SkASSERT(width > 0);
     51     while (--height >= 0) {
     52         this->blitH(x, y++, width);
     53     }
     54 }
     55 
     56 /// Default implementation doesn't check for any easy optimizations
     57 /// such as alpha == 0 or 255; also uses blitV(), which some subclasses
     58 /// may not support.
     59 void SkBlitter::blitAntiRect(int x, int y, int width, int height,
     60                              SkAlpha leftAlpha, SkAlpha rightAlpha) {
     61     this->blitV(x++, y, height, leftAlpha);
     62     if (width > 0) {
     63         this->blitRect(x, y, width, height);
     64         x += width;
     65     }
     66     this->blitV(x, y, height, rightAlpha);
     67 }
     68 
     69 //////////////////////////////////////////////////////////////////////////////
     70 
     71 static inline void bits_to_runs(SkBlitter* blitter, int x, int y,
     72                                 const uint8_t bits[],
     73                                 U8CPU left_mask, int rowBytes,
     74                                 U8CPU right_mask) {
     75     int inFill = 0;
     76     int pos = 0;
     77 
     78     while (--rowBytes >= 0) {
     79         unsigned b = *bits++ & left_mask;
     80         if (rowBytes == 0) {
     81             b &= right_mask;
     82         }
     83 
     84         for (unsigned test = 0x80; test != 0; test >>= 1) {
     85             if (b & test) {
     86                 if (!inFill) {
     87                     pos = x;
     88                     inFill = true;
     89                 }
     90             } else {
     91                 if (inFill) {
     92                     blitter->blitH(pos, y, x - pos);
     93                     inFill = false;
     94                 }
     95             }
     96             x += 1;
     97         }
     98         left_mask = 0xFF;
     99     }
    100 
    101     // final cleanup
    102     if (inFill) {
    103         blitter->blitH(pos, y, x - pos);
    104     }
    105 }
    106 
    107 void SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    108     SkASSERT(mask.fBounds.contains(clip));
    109 
    110     if (mask.fFormat == SkMask::kBW_Format) {
    111         int cx = clip.fLeft;
    112         int cy = clip.fTop;
    113         int maskLeft = mask.fBounds.fLeft;
    114         int mask_rowBytes = mask.fRowBytes;
    115         int height = clip.height();
    116 
    117         const uint8_t* bits = mask.getAddr1(cx, cy);
    118 
    119         if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
    120             while (--height >= 0) {
    121                 bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
    122                 bits += mask_rowBytes;
    123                 cy += 1;
    124             }
    125         } else {
    126             int left_edge = cx - maskLeft;
    127             SkASSERT(left_edge >= 0);
    128             int rite_edge = clip.fRight - maskLeft;
    129             SkASSERT(rite_edge > left_edge);
    130 
    131             int left_mask = 0xFF >> (left_edge & 7);
    132             int rite_mask = 0xFF << (8 - (rite_edge & 7));
    133             int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
    134 
    135             // check for empty right mask, so we don't read off the end (or go slower than we need to)
    136             if (rite_mask == 0) {
    137                 SkASSERT(full_runs >= 0);
    138                 full_runs -= 1;
    139                 rite_mask = 0xFF;
    140             }
    141             if (left_mask == 0xFF) {
    142                 full_runs -= 1;
    143             }
    144 
    145             // back up manually so we can keep in sync with our byte-aligned src
    146             // have cx reflect our actual starting x-coord
    147             cx -= left_edge & 7;
    148 
    149             if (full_runs < 0) {
    150                 SkASSERT((left_mask & rite_mask) != 0);
    151                 while (--height >= 0) {
    152                     bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
    153                     bits += mask_rowBytes;
    154                     cy += 1;
    155                 }
    156             } else {
    157                 while (--height >= 0) {
    158                     bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
    159                     bits += mask_rowBytes;
    160                     cy += 1;
    161                 }
    162             }
    163         }
    164     } else {
    165         int                         width = clip.width();
    166         SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
    167         int16_t*                    runs = runStorage.get();
    168         const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
    169 
    170         sk_memset16((uint16_t*)runs, 1, width);
    171         runs[width] = 0;
    172 
    173         int height = clip.height();
    174         int y = clip.fTop;
    175         while (--height >= 0) {
    176             this->blitAntiH(clip.fLeft, y, aa, runs);
    177             aa += mask.fRowBytes;
    178             y += 1;
    179         }
    180     }
    181 }
    182 
    183 /////////////////////// these guys are not virtual, just a helpers
    184 
    185 void SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
    186     if (clip.quickReject(mask.fBounds)) {
    187         return;
    188     }
    189 
    190     SkRegion::Cliperator clipper(clip, mask.fBounds);
    191 
    192     while (!clipper.done()) {
    193         const SkIRect& cr = clipper.rect();
    194         this->blitMask(mask, cr);
    195         clipper.next();
    196     }
    197 }
    198 
    199 void SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
    200     SkRegion::Cliperator clipper(clip, rect);
    201 
    202     while (!clipper.done()) {
    203         const SkIRect& cr = clipper.rect();
    204         this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
    205         clipper.next();
    206     }
    207 }
    208 
    209 void SkBlitter::blitRegion(const SkRegion& clip) {
    210     SkRegion::Iterator iter(clip);
    211 
    212     while (!iter.done()) {
    213         const SkIRect& cr = iter.rect();
    214         this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
    215         iter.next();
    216     }
    217 }
    218 
    219 ///////////////////////////////////////////////////////////////////////////////
    220 
    221 void SkNullBlitter::blitH(int x, int y, int width) {}
    222 
    223 void SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
    224                               const int16_t runs[]) {}
    225 
    226 void SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
    227 
    228 void SkNullBlitter::blitRect(int x, int y, int width, int height) {}
    229 
    230 void SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
    231 
    232 const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
    233     return NULL;
    234 }
    235 
    236 ///////////////////////////////////////////////////////////////////////////////
    237 
    238 static int compute_anti_width(const int16_t runs[]) {
    239     int width = 0;
    240 
    241     for (;;) {
    242         int count = runs[0];
    243 
    244         SkASSERT(count >= 0);
    245         if (count == 0) {
    246             break;
    247         }
    248         width += count;
    249         runs += count;
    250     }
    251     return width;
    252 }
    253 
    254 static inline bool y_in_rect(int y, const SkIRect& rect) {
    255     return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
    256 }
    257 
    258 static inline bool x_in_rect(int x, const SkIRect& rect) {
    259     return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
    260 }
    261 
    262 void SkRectClipBlitter::blitH(int left, int y, int width) {
    263     SkASSERT(width > 0);
    264 
    265     if (!y_in_rect(y, fClipRect)) {
    266         return;
    267     }
    268 
    269     int right = left + width;
    270 
    271     if (left < fClipRect.fLeft) {
    272         left = fClipRect.fLeft;
    273     }
    274     if (right > fClipRect.fRight) {
    275         right = fClipRect.fRight;
    276     }
    277 
    278     width = right - left;
    279     if (width > 0) {
    280         fBlitter->blitH(left, y, width);
    281     }
    282 }
    283 
    284 void SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
    285                                   const int16_t runs[]) {
    286     if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
    287         return;
    288     }
    289 
    290     int x0 = left;
    291     int x1 = left + compute_anti_width(runs);
    292 
    293     if (x1 <= fClipRect.fLeft) {
    294         return;
    295     }
    296 
    297     SkASSERT(x0 < x1);
    298     if (x0 < fClipRect.fLeft) {
    299         int dx = fClipRect.fLeft - x0;
    300         SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
    301         runs += dx;
    302         aa += dx;
    303         x0 = fClipRect.fLeft;
    304     }
    305 
    306     SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
    307     if (x1 > fClipRect.fRight) {
    308         x1 = fClipRect.fRight;
    309         SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
    310         ((int16_t*)runs)[x1 - x0] = 0;
    311     }
    312 
    313     SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
    314     SkASSERT(compute_anti_width(runs) == x1 - x0);
    315 
    316     fBlitter->blitAntiH(x0, y, aa, runs);
    317 }
    318 
    319 void SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
    320     SkASSERT(height > 0);
    321 
    322     if (!x_in_rect(x, fClipRect)) {
    323         return;
    324     }
    325 
    326     int y0 = y;
    327     int y1 = y + height;
    328 
    329     if (y0 < fClipRect.fTop) {
    330         y0 = fClipRect.fTop;
    331     }
    332     if (y1 > fClipRect.fBottom) {
    333         y1 = fClipRect.fBottom;
    334     }
    335 
    336     if (y0 < y1) {
    337         fBlitter->blitV(x, y0, y1 - y0, alpha);
    338     }
    339 }
    340 
    341 void SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
    342     SkIRect    r;
    343 
    344     r.set(left, y, left + width, y + height);
    345     if (r.intersect(fClipRect)) {
    346         fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
    347     }
    348 }
    349 
    350 void SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
    351                                      SkAlpha leftAlpha, SkAlpha rightAlpha) {
    352     SkIRect    r;
    353 
    354     // The *true* width of the rectangle blitted is width+2:
    355     r.set(left, y, left + width + 2, y + height);
    356     if (r.intersect(fClipRect)) {
    357         if (r.fLeft != left) {
    358             SkASSERT(r.fLeft > left);
    359             leftAlpha = 255;
    360         }
    361         if (r.fRight != left + width + 2) {
    362             SkASSERT(r.fRight < left + width + 2);
    363             rightAlpha = 255;
    364         }
    365         if (255 == leftAlpha && 255 == rightAlpha) {
    366             fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
    367         } else if (1 == r.width()) {
    368             if (r.fLeft == left) {
    369                 fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
    370             } else {
    371                 SkASSERT(r.fLeft == left + width + 1);
    372                 fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
    373             }
    374         } else {
    375             fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
    376                                    leftAlpha, rightAlpha);
    377         }
    378     }
    379 }
    380 
    381 void SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    382     SkASSERT(mask.fBounds.contains(clip));
    383 
    384     SkIRect    r = clip;
    385 
    386     if (r.intersect(fClipRect)) {
    387         fBlitter->blitMask(mask, r);
    388     }
    389 }
    390 
    391 const SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
    392     return fBlitter->justAnOpaqueColor(value);
    393 }
    394 
    395 ///////////////////////////////////////////////////////////////////////////////
    396 
    397 void SkRgnClipBlitter::blitH(int x, int y, int width) {
    398     SkRegion::Spanerator span(*fRgn, y, x, x + width);
    399     int left, right;
    400 
    401     while (span.next(&left, &right)) {
    402         SkASSERT(left < right);
    403         fBlitter->blitH(left, y, right - left);
    404     }
    405 }
    406 
    407 void SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
    408                                  const int16_t runs[]) {
    409     int width = compute_anti_width(runs);
    410     SkRegion::Spanerator span(*fRgn, y, x, x + width);
    411     int left, right;
    412     SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
    413 
    414     int prevRite = x;
    415     while (span.next(&left, &right)) {
    416         SkASSERT(x <= left);
    417         SkASSERT(left < right);
    418         SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
    419 
    420         SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
    421 
    422         // now zero before left
    423         if (left > prevRite) {
    424             int index = prevRite - x;
    425             ((uint8_t*)aa)[index] = 0;   // skip runs after right
    426             ((int16_t*)runs)[index] = SkToS16(left - prevRite);
    427         }
    428 
    429         prevRite = right;
    430     }
    431 
    432     if (prevRite > x) {
    433         ((int16_t*)runs)[prevRite - x] = 0;
    434 
    435         if (x < 0) {
    436             int skip = runs[0];
    437             SkASSERT(skip >= -x);
    438             aa += skip;
    439             runs += skip;
    440             x += skip;
    441         }
    442         fBlitter->blitAntiH(x, y, aa, runs);
    443     }
    444 }
    445 
    446 void SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
    447     SkIRect    bounds;
    448     bounds.set(x, y, x + 1, y + height);
    449 
    450     SkRegion::Cliperator    iter(*fRgn, bounds);
    451 
    452     while (!iter.done()) {
    453         const SkIRect& r = iter.rect();
    454         SkASSERT(bounds.contains(r));
    455 
    456         fBlitter->blitV(x, r.fTop, r.height(), alpha);
    457         iter.next();
    458     }
    459 }
    460 
    461 void SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
    462     SkIRect    bounds;
    463     bounds.set(x, y, x + width, y + height);
    464 
    465     SkRegion::Cliperator    iter(*fRgn, bounds);
    466 
    467     while (!iter.done()) {
    468         const SkIRect& r = iter.rect();
    469         SkASSERT(bounds.contains(r));
    470 
    471         fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
    472         iter.next();
    473     }
    474 }
    475 
    476 void SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
    477                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
    478     // The *true* width of the rectangle to blit is width + 2
    479     SkIRect    bounds;
    480     bounds.set(x, y, x + width + 2, y + height);
    481 
    482     SkRegion::Cliperator    iter(*fRgn, bounds);
    483 
    484     while (!iter.done()) {
    485         const SkIRect& r = iter.rect();
    486         SkASSERT(bounds.contains(r));
    487         SkASSERT(r.fLeft >= x);
    488         SkASSERT(r.fRight <= x + width + 2);
    489 
    490         SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
    491         SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
    492                                       rightAlpha : 255;
    493 
    494         if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
    495             fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
    496         } else if (1 == r.width()) {
    497             if (r.fLeft == x) {
    498                 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
    499                                 effectiveLeftAlpha);
    500             } else {
    501                 SkASSERT(r.fLeft == x + width + 1);
    502                 fBlitter->blitV(r.fLeft, r.fTop, r.height(),
    503                                 effectiveRightAlpha);
    504             }
    505         } else {
    506             fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
    507                                    effectiveLeftAlpha, effectiveRightAlpha);
    508         }
    509         iter.next();
    510     }
    511 }
    512 
    513 
    514 void SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
    515     SkASSERT(mask.fBounds.contains(clip));
    516 
    517     SkRegion::Cliperator iter(*fRgn, clip);
    518     const SkIRect&       r = iter.rect();
    519     SkBlitter*           blitter = fBlitter;
    520 
    521     while (!iter.done()) {
    522         blitter->blitMask(mask, r);
    523         iter.next();
    524     }
    525 }
    526 
    527 const SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
    528     return fBlitter->justAnOpaqueColor(value);
    529 }
    530 
    531 ///////////////////////////////////////////////////////////////////////////////
    532 
    533 SkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
    534                                    const SkIRect* ir) {
    535     if (clip) {
    536         const SkIRect& clipR = clip->getBounds();
    537 
    538         if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
    539             blitter = &fNullBlitter;
    540         } else if (clip->isRect()) {
    541             if (ir == NULL || !clipR.contains(*ir)) {
    542                 fRectBlitter.init(blitter, clipR);
    543                 blitter = &fRectBlitter;
    544             }
    545         } else {
    546             fRgnBlitter.init(blitter, clip);
    547             blitter = &fRgnBlitter;
    548         }
    549     }
    550     return blitter;
    551 }
    552 
    553 ///////////////////////////////////////////////////////////////////////////////
    554 
    555 #include "SkColorShader.h"
    556 #include "SkColorPriv.h"
    557 
    558 class Sk3DShader : public SkShader {
    559 public:
    560     Sk3DShader(SkShader* proxy) : fProxy(proxy) {
    561         SkSafeRef(proxy);
    562         fMask = NULL;
    563     }
    564 
    565     virtual ~Sk3DShader() {
    566         SkSafeUnref(fProxy);
    567     }
    568 
    569     void setMask(const SkMask* mask) { fMask = mask; }
    570 
    571     virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
    572                             const SkMatrix& matrix) {
    573         if (fProxy) {
    574             return fProxy->setContext(device, paint, matrix);
    575         } else {
    576             fPMColor = SkPreMultiplyColor(paint.getColor());
    577             return this->INHERITED::setContext(device, paint, matrix);
    578         }
    579     }
    580 
    581     virtual void shadeSpan(int x, int y, SkPMColor span[], int count) {
    582         if (fProxy) {
    583             fProxy->shadeSpan(x, y, span, count);
    584         }
    585 
    586         if (fMask == NULL) {
    587             if (fProxy == NULL) {
    588                 sk_memset32(span, fPMColor, count);
    589             }
    590             return;
    591         }
    592 
    593         SkASSERT(fMask->fBounds.contains(x, y));
    594         SkASSERT(fMask->fBounds.contains(x + count - 1, y));
    595 
    596         size_t          size = fMask->computeImageSize();
    597         const uint8_t*  alpha = fMask->getAddr8(x, y);
    598         const uint8_t*  mulp = alpha + size;
    599         const uint8_t*  addp = mulp + size;
    600 
    601         if (fProxy) {
    602             for (int i = 0; i < count; i++) {
    603                 if (alpha[i]) {
    604                     SkPMColor c = span[i];
    605                     if (c) {
    606                         unsigned a = SkGetPackedA32(c);
    607                         unsigned r = SkGetPackedR32(c);
    608                         unsigned g = SkGetPackedG32(c);
    609                         unsigned b = SkGetPackedB32(c);
    610 
    611                         unsigned mul = SkAlpha255To256(mulp[i]);
    612                         unsigned add = addp[i];
    613 
    614                         r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
    615                         g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
    616                         b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
    617 
    618                         span[i] = SkPackARGB32(a, r, g, b);
    619                     }
    620                 } else {
    621                     span[i] = 0;
    622                 }
    623             }
    624         } else {    // color
    625             unsigned a = SkGetPackedA32(fPMColor);
    626             unsigned r = SkGetPackedR32(fPMColor);
    627             unsigned g = SkGetPackedG32(fPMColor);
    628             unsigned b = SkGetPackedB32(fPMColor);
    629             for (int i = 0; i < count; i++) {
    630                 if (alpha[i]) {
    631                     unsigned mul = SkAlpha255To256(mulp[i]);
    632                     unsigned add = addp[i];
    633 
    634                     span[i] = SkPackARGB32( a,
    635                                     SkFastMin32(SkAlphaMul(r, mul) + add, a),
    636                                     SkFastMin32(SkAlphaMul(g, mul) + add, a),
    637                                     SkFastMin32(SkAlphaMul(b, mul) + add, a));
    638                 } else {
    639                     span[i] = 0;
    640                 }
    641             }
    642         }
    643     }
    644 
    645     virtual void beginSession() {
    646         this->INHERITED::beginSession();
    647         if (fProxy) {
    648             fProxy->beginSession();
    649         }
    650     }
    651 
    652     virtual void endSession() {
    653         if (fProxy) {
    654             fProxy->endSession();
    655         }
    656         this->INHERITED::endSession();
    657     }
    658 
    659 protected:
    660     Sk3DShader(SkFlattenableReadBuffer& buffer) :
    661             INHERITED(buffer) {
    662         fProxy = static_cast<SkShader*>(buffer.readFlattenable());
    663         fPMColor = buffer.readU32();
    664         fMask = NULL;
    665     }
    666 
    667     virtual void flatten(SkFlattenableWriteBuffer& buffer) {
    668         this->INHERITED::flatten(buffer);
    669         buffer.writeFlattenable(fProxy);
    670         buffer.write32(fPMColor);
    671     }
    672 
    673     virtual Factory getFactory() {
    674         return CreateProc;
    675     }
    676 
    677 private:
    678     static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
    679         return SkNEW_ARGS(Sk3DShader, (buffer));
    680     }
    681 
    682     SkShader*       fProxy;
    683     SkPMColor       fPMColor;
    684     const SkMask*   fMask;
    685 
    686     typedef SkShader INHERITED;
    687 };
    688 
    689 class Sk3DBlitter : public SkBlitter {
    690 public:
    691     Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
    692             : fProxy(proxy), f3DShader(shader), fKillProc(killProc) {
    693         shader->ref();
    694     }
    695 
    696     virtual ~Sk3DBlitter() {
    697         f3DShader->unref();
    698         fKillProc(fProxy);
    699     }
    700 
    701     virtual void blitH(int x, int y, int width) {
    702         fProxy->blitH(x, y, width);
    703     }
    704 
    705     virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
    706                            const int16_t runs[]) {
    707         fProxy->blitAntiH(x, y, antialias, runs);
    708     }
    709 
    710     virtual void blitV(int x, int y, int height, SkAlpha alpha) {
    711         fProxy->blitV(x, y, height, alpha);
    712     }
    713 
    714     virtual void blitRect(int x, int y, int width, int height) {
    715         fProxy->blitRect(x, y, width, height);
    716     }
    717 
    718     virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
    719         if (mask.fFormat == SkMask::k3D_Format) {
    720             f3DShader->setMask(&mask);
    721 
    722             ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
    723             fProxy->blitMask(mask, clip);
    724             ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
    725 
    726             f3DShader->setMask(NULL);
    727         } else {
    728             fProxy->blitMask(mask, clip);
    729         }
    730     }
    731 
    732 private:
    733     SkBlitter*  fProxy;
    734     Sk3DShader* f3DShader;
    735     void        (*fKillProc)(void*);
    736 };
    737 
    738 ///////////////////////////////////////////////////////////////////////////////
    739 
    740 #include "SkCoreBlitters.h"
    741 
    742 class SkAutoCallProc {
    743 public:
    744     typedef void (*Proc)(void*);
    745 
    746     SkAutoCallProc(void* obj, Proc proc)
    747     : fObj(obj), fProc(proc) {}
    748 
    749     ~SkAutoCallProc() {
    750         if (fObj && fProc) {
    751             fProc(fObj);
    752         }
    753     }
    754 
    755     void* get() const { return fObj; }
    756 
    757     void* detach() {
    758         void* obj = fObj;
    759         fObj = NULL;
    760         return obj;
    761     }
    762 
    763 private:
    764     void*   fObj;
    765     Proc    fProc;
    766 };
    767 
    768 static void destroy_blitter(void* blitter) {
    769     ((SkBlitter*)blitter)->~SkBlitter();
    770 }
    771 
    772 static void delete_blitter(void* blitter) {
    773     SkDELETE((SkBlitter*)blitter);
    774 }
    775 
    776 static bool just_solid_color(const SkPaint& paint) {
    777     if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
    778         SkShader* shader = paint.getShader();
    779         if (NULL == shader ||
    780             (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
    781             return true;
    782         }
    783     }
    784     return false;
    785 }
    786 
    787 /** By analyzing the paint (with an xfermode), we may decide we can take
    788     special action. This enum lists our possible actions
    789  */
    790 enum XferInterp {
    791     kNormal_XferInterp,         // no special interpretation, draw normally
    792     kSrcOver_XferInterp,        // draw as if in srcover mode
    793     kSkipDrawing_XferInterp     // draw nothing
    794 };
    795 
    796 static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
    797                                      SkBitmap::Config deviceConfig) {
    798     SkXfermode::Mode  mode;
    799 
    800     if (SkXfermode::AsMode(xfer, &mode)) {
    801         switch (mode) {
    802             case SkXfermode::kSrc_Mode:
    803                 if (just_solid_color(paint)) {
    804                     return kSrcOver_XferInterp;
    805                 }
    806                 break;
    807             case SkXfermode::kDst_Mode:
    808                 return kSkipDrawing_XferInterp;
    809             case SkXfermode::kSrcOver_Mode:
    810                 return kSrcOver_XferInterp;
    811             case SkXfermode::kDstOver_Mode:
    812                 if (SkBitmap::kRGB_565_Config == deviceConfig) {
    813                     return kSkipDrawing_XferInterp;
    814                 }
    815                 break;
    816             case SkXfermode::kSrcIn_Mode:
    817                 if (SkBitmap::kRGB_565_Config == deviceConfig &&
    818                     just_solid_color(paint)) {
    819                     return kSrcOver_XferInterp;
    820                 }
    821                 break;
    822             case SkXfermode::kDstIn_Mode:
    823                 if (just_solid_color(paint)) {
    824                     return kSkipDrawing_XferInterp;
    825                 }
    826                 break;
    827             default:
    828                 break;
    829         }
    830     }
    831     return kNormal_XferInterp;
    832 }
    833 
    834 SkBlitter* SkBlitter::Choose(const SkBitmap& device,
    835                              const SkMatrix& matrix,
    836                              const SkPaint& origPaint,
    837                              void* storage, size_t storageSize) {
    838     SkASSERT(storageSize == 0 || storage != NULL);
    839 
    840     SkBlitter*  blitter = NULL;
    841 
    842     // which check, in case we're being called by a client with a dummy device
    843     // (e.g. they have a bounder that always aborts the draw)
    844     if (SkBitmap::kNo_Config == device.getConfig()) {
    845         SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
    846         return blitter;
    847     }
    848 
    849     SkPaint paint(origPaint);
    850     SkShader* shader = paint.getShader();
    851     SkColorFilter* cf = paint.getColorFilter();
    852     SkXfermode* mode = paint.getXfermode();
    853 
    854     Sk3DShader* shader3D = NULL;
    855     if (paint.getMaskFilter() != NULL &&
    856             paint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
    857         shader3D = SkNEW_ARGS(Sk3DShader, (shader));
    858         paint.setShader(shader3D)->unref();
    859         shader = shader3D;
    860     }
    861 
    862     if (NULL != mode) {
    863         switch (interpret_xfermode(paint, mode, device.config())) {
    864             case kSrcOver_XferInterp:
    865                 mode = NULL;
    866                 paint.setXfermode(NULL);
    867                 break;
    868             case kSkipDrawing_XferInterp:
    869                 SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
    870                 return blitter;
    871             default:
    872                 break;
    873         }
    874     }
    875 
    876     if (NULL == shader) {
    877 #ifdef SK_IGNORE_CF_OPTIMIZATION
    878         if (mode || cf) {
    879 #else
    880         if (mode) {
    881 #endif
    882             // xfermodes (and filters) require shaders for our current blitters
    883             shader = SkNEW(SkColorShader);
    884             paint.setShader(shader)->unref();
    885         } else if (cf) {
    886             // if no shader && no xfermode, we just apply the colorfilter to
    887             // our color and move on.
    888             paint.setColor(cf->filterColor(paint.getColor()));
    889             paint.setColorFilter(NULL);
    890             cf = NULL;
    891         }
    892     }
    893 
    894     if (cf) {
    895         SkASSERT(shader);
    896         shader = SkNEW_ARGS(SkFilterShader, (shader, cf));
    897         paint.setShader(shader)->unref();
    898         // blitters should ignore the presence/absence of a filter, since
    899         // if there is one, the shader will take care of it.
    900     }
    901 
    902     if (shader && !shader->setContext(device, paint, matrix)) {
    903         return SkNEW(SkNullBlitter);
    904     }
    905 
    906     switch (device.getConfig()) {
    907         case SkBitmap::kA1_Config:
    908             SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter,
    909                                   storage, storageSize, (device, paint));
    910             break;
    911 
    912         case SkBitmap::kA8_Config:
    913             if (shader) {
    914                 SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter,
    915                                       storage, storageSize, (device, paint));
    916             } else {
    917                 SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter,
    918                                       storage, storageSize, (device, paint));
    919             }
    920             break;
    921 
    922         case SkBitmap::kARGB_4444_Config:
    923             blitter = SkBlitter_ChooseD4444(device, paint, storage, storageSize);
    924             break;
    925 
    926         case SkBitmap::kRGB_565_Config:
    927             blitter = SkBlitter_ChooseD565(device, paint, storage, storageSize);
    928             break;
    929 
    930         case SkBitmap::kARGB_8888_Config:
    931             if (shader) {
    932                 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter,
    933                                       storage, storageSize, (device, paint));
    934             } else if (paint.getColor() == SK_ColorBLACK) {
    935                 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter,
    936                                       storage, storageSize, (device, paint));
    937             } else if (paint.getAlpha() == 0xFF) {
    938                 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter,
    939                                       storage, storageSize, (device, paint));
    940             } else {
    941                 SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter,
    942                                       storage, storageSize, (device, paint));
    943             }
    944             break;
    945 
    946         default:
    947             SkDEBUGFAIL("unsupported device config");
    948             SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
    949             break;
    950     }
    951 
    952     if (shader3D) {
    953         void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
    954         SkAutoCallProc  tmp(blitter, proc);
    955 
    956         blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
    957         (void)tmp.detach();
    958     }
    959     return blitter;
    960 }
    961 
    962 ///////////////////////////////////////////////////////////////////////////////
    963 
    964 const uint16_t gMask_0F0F = 0xF0F;
    965 const uint32_t gMask_00FF00FF = 0xFF00FF;
    966 
    967 ///////////////////////////////////////////////////////////////////////////////
    968 
    969 SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
    970         : INHERITED(device) {
    971     fShader = paint.getShader();
    972     SkASSERT(fShader);
    973 
    974     fShader->ref();
    975     fShader->beginSession();
    976     fShaderFlags = fShader->getFlags();
    977 }
    978 
    979 SkShaderBlitter::~SkShaderBlitter() {
    980     fShader->endSession();
    981     fShader->unref();
    982 }
    983 
    984