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