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