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 (NULL != 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     Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) {
    718         fProxy = buffer.readShader();
    719         // Leaving this here until we bump the picture version, though this
    720         // shader should never be recorded.
    721         buffer.readColor();
    722     }
    723 
    724     virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
    725         this->INHERITED::flatten(buffer);
    726         buffer.writeFlattenable(fProxy);
    727         // Leaving this here until we bump the picture version, though this
    728         // shader should never be recorded.
    729         buffer.writeColor(SkColor());
    730     }
    731 
    732 private:
    733     SkShader*       fProxy;
    734 
    735     typedef SkShader INHERITED;
    736 };
    737 
    738 class Sk3DBlitter : public SkBlitter {
    739 public:
    740     Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext)
    741         : fProxy(proxy)
    742         , fShaderContext(shaderContext)
    743     {}
    744 
    745     virtual void blitH(int x, int y, int width) {
    746         fProxy->blitH(x, y, width);
    747     }
    748 
    749     virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
    750                            const int16_t runs[]) {
    751         fProxy->blitAntiH(x, y, antialias, runs);
    752     }
    753 
    754     virtual void blitV(int x, int y, int height, SkAlpha alpha) {
    755         fProxy->blitV(x, y, height, alpha);
    756     }
    757 
    758     virtual void blitRect(int x, int y, int width, int height) {
    759         fProxy->blitRect(x, y, width, height);
    760     }
    761 
    762     virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
    763         if (mask.fFormat == SkMask::k3D_Format) {
    764             fShaderContext->set3DMask(&mask);
    765 
    766             ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
    767             fProxy->blitMask(mask, clip);
    768             ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
    769 
    770             fShaderContext->set3DMask(NULL);
    771         } else {
    772             fProxy->blitMask(mask, clip);
    773         }
    774     }
    775 
    776 private:
    777     // Both pointers are unowned. They will be deleted by SkSmallAllocator.
    778     SkBlitter*          fProxy;
    779     SkShader::Context*  fShaderContext;
    780 };
    781 
    782 ///////////////////////////////////////////////////////////////////////////////
    783 
    784 #include "SkCoreBlitters.h"
    785 
    786 static bool just_solid_color(const SkPaint& paint) {
    787     if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
    788         SkShader* shader = paint.getShader();
    789         if (NULL == shader) {
    790             return true;
    791         }
    792     }
    793     return false;
    794 }
    795 
    796 /** By analyzing the paint (with an xfermode), we may decide we can take
    797     special action. This enum lists our possible actions
    798  */
    799 enum XferInterp {
    800     kNormal_XferInterp,         // no special interpretation, draw normally
    801     kSrcOver_XferInterp,        // draw as if in srcover mode
    802     kSkipDrawing_XferInterp     // draw nothing
    803 };
    804 
    805 static XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
    806                                      SkColorType deviceCT) {
    807     SkXfermode::Mode  mode;
    808 
    809     if (SkXfermode::AsMode(xfer, &mode)) {
    810         switch (mode) {
    811             case SkXfermode::kSrc_Mode:
    812                 if (just_solid_color(paint)) {
    813                     return kSrcOver_XferInterp;
    814                 }
    815                 break;
    816             case SkXfermode::kDst_Mode:
    817                 return kSkipDrawing_XferInterp;
    818             case SkXfermode::kSrcOver_Mode:
    819                 return kSrcOver_XferInterp;
    820             case SkXfermode::kDstOver_Mode:
    821                 if (kRGB_565_SkColorType == deviceCT) {
    822                     return kSkipDrawing_XferInterp;
    823                 }
    824                 break;
    825             case SkXfermode::kSrcIn_Mode:
    826                 if (kRGB_565_SkColorType == deviceCT &&
    827                     just_solid_color(paint)) {
    828                     return kSrcOver_XferInterp;
    829                 }
    830                 break;
    831             case SkXfermode::kDstIn_Mode:
    832                 if (just_solid_color(paint)) {
    833                     return kSkipDrawing_XferInterp;
    834                 }
    835                 break;
    836             default:
    837                 break;
    838         }
    839     }
    840     return kNormal_XferInterp;
    841 }
    842 
    843 SkBlitter* SkBlitter::Choose(const SkBitmap& device,
    844                              const SkMatrix& matrix,
    845                              const SkPaint& origPaint,
    846                              SkTBlitterAllocator* allocator,
    847                              bool drawCoverage) {
    848     SkASSERT(allocator != NULL);
    849 
    850     SkBlitter*  blitter = NULL;
    851 
    852     // which check, in case we're being called by a client with a dummy device
    853     // (e.g. they have a bounder that always aborts the draw)
    854     if (kUnknown_SkColorType == device.colorType() ||
    855             (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
    856         blitter = allocator->createT<SkNullBlitter>();
    857         return blitter;
    858     }
    859 
    860     SkShader* shader = origPaint.getShader();
    861     SkColorFilter* cf = origPaint.getColorFilter();
    862     SkXfermode* mode = origPaint.getXfermode();
    863     Sk3DShader* shader3D = NULL;
    864 
    865     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
    866 
    867     if (origPaint.getMaskFilter() != NULL &&
    868             origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
    869         shader3D = SkNEW_ARGS(Sk3DShader, (shader));
    870         // we know we haven't initialized lazyPaint yet, so just do it
    871         paint.writable()->setShader(shader3D)->unref();
    872         shader = shader3D;
    873     }
    874 
    875     if (NULL != mode) {
    876         switch (interpret_xfermode(*paint, mode, device.colorType())) {
    877             case kSrcOver_XferInterp:
    878                 mode = NULL;
    879                 paint.writable()->setXfermode(NULL);
    880                 break;
    881             case kSkipDrawing_XferInterp:{
    882                 blitter = allocator->createT<SkNullBlitter>();
    883                 return blitter;
    884             }
    885             default:
    886                 break;
    887         }
    888     }
    889 
    890     /*
    891      *  If the xfermode is CLEAR, then we can completely ignore the installed
    892      *  color/shader/colorfilter, and just pretend we're SRC + color==0. This
    893      *  will fall into our optimizations for SRC mode.
    894      */
    895     if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) {
    896         SkPaint* p = paint.writable();
    897         shader = p->setShader(NULL);
    898         cf = p->setColorFilter(NULL);
    899         mode = p->setXfermodeMode(SkXfermode::kSrc_Mode);
    900         p->setColor(0);
    901     }
    902 
    903     if (NULL == shader) {
    904         if (mode) {
    905             // xfermodes (and filters) require shaders for our current blitters
    906             shader = SkNEW_ARGS(SkColorShader, (paint->getColor()));
    907             paint.writable()->setShader(shader)->unref();
    908             paint.writable()->setAlpha(0xFF);
    909         } else if (cf) {
    910             // if no shader && no xfermode, we just apply the colorfilter to
    911             // our color and move on.
    912             SkPaint* writablePaint = paint.writable();
    913             writablePaint->setColor(cf->filterColor(paint->getColor()));
    914             writablePaint->setColorFilter(NULL);
    915             cf = NULL;
    916         }
    917     }
    918 
    919     if (cf) {
    920         SkASSERT(shader);
    921         shader = SkNEW_ARGS(SkFilterShader, (shader, cf));
    922         paint.writable()->setShader(shader)->unref();
    923         // blitters should ignore the presence/absence of a filter, since
    924         // if there is one, the shader will take care of it.
    925     }
    926 
    927     /*
    928      *  We create a SkShader::Context object, and store it on the blitter.
    929      */
    930     SkShader::Context* shaderContext;
    931     if (shader) {
    932         SkShader::ContextRec rec(device, *paint, matrix);
    933         // Try to create the ShaderContext
    934         void* storage = allocator->reserveT<SkShader::Context>(shader->contextSize());
    935         shaderContext = shader->createContext(rec, storage);
    936         if (!shaderContext) {
    937             allocator->freeLast();
    938             blitter = allocator->createT<SkNullBlitter>();
    939             return blitter;
    940         }
    941         SkASSERT(shaderContext);
    942         SkASSERT((void*) shaderContext == storage);
    943     } else {
    944         shaderContext = NULL;
    945     }
    946 
    947 
    948     switch (device.colorType()) {
    949         case kAlpha_8_SkColorType:
    950             if (drawCoverage) {
    951                 SkASSERT(NULL == shader);
    952                 SkASSERT(NULL == paint->getXfermode());
    953                 blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint);
    954             } else if (shader) {
    955                 blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext);
    956             } else {
    957                 blitter = allocator->createT<SkA8_Blitter>(device, *paint);
    958             }
    959             break;
    960 
    961         case kRGB_565_SkColorType:
    962             blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator);
    963             break;
    964 
    965         case kN32_SkColorType:
    966             if (shader) {
    967                 blitter = allocator->createT<SkARGB32_Shader_Blitter>(
    968                         device, *paint, shaderContext);
    969             } else if (paint->getColor() == SK_ColorBLACK) {
    970                 blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
    971             } else if (paint->getAlpha() == 0xFF) {
    972                 blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint);
    973             } else {
    974                 blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
    975             }
    976             break;
    977 
    978         default:
    979             SkDEBUGFAIL("unsupported device config");
    980             blitter = allocator->createT<SkNullBlitter>();
    981             break;
    982     }
    983 
    984     if (shader3D) {
    985         SkBlitter* innerBlitter = blitter;
    986         // innerBlitter was allocated by allocator, which will delete it.
    987         // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to
    988         // wrapper the blitter to notify it when we see an emboss mask.
    989         blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext);
    990     }
    991     return blitter;
    992 }
    993 
    994 ///////////////////////////////////////////////////////////////////////////////
    995 
    996 class SkTransparentShaderContext : public SkShader::Context {
    997 public:
    998     SkTransparentShaderContext(const SkShader& shader, const SkShader::ContextRec& rec)
    999         // Override rec with the identity matrix, so it is guaranteed to be invertible.
   1000         : INHERITED(shader, SkShader::ContextRec(*rec.fDevice, *rec.fPaint, SkMatrix::I())) {}
   1001 
   1002     virtual void shadeSpan(int x, int y, SkPMColor colors[], int count) SK_OVERRIDE {
   1003         sk_bzero(colors, count * sizeof(SkPMColor));
   1004     }
   1005 
   1006 private:
   1007     typedef SkShader::Context INHERITED;
   1008 };
   1009 
   1010 SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint,
   1011                                  SkShader::Context* shaderContext)
   1012         : INHERITED(device)
   1013         , fShader(paint.getShader())
   1014         , fShaderContext(shaderContext) {
   1015     SkASSERT(fShader);
   1016     SkASSERT(fShaderContext);
   1017 
   1018     fShader->ref();
   1019     fShaderFlags = fShaderContext->getFlags();
   1020 }
   1021 
   1022 SkShaderBlitter::~SkShaderBlitter() {
   1023     fShader->unref();
   1024 }
   1025 
   1026 bool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) {
   1027     // Only destroy the old context if we have a new one. We need to ensure to have a
   1028     // live context in fShaderContext because the storage is owned by an SkSmallAllocator
   1029     // outside of this class.
   1030     // The new context will be of the same size as the old one because we use the same
   1031     // shader to create it. It is therefore safe to re-use the storage.
   1032     fShaderContext->~Context();
   1033     SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext);
   1034     if (NULL == ctx) {
   1035         // Need a valid context in fShaderContext's storage, so we can later (or our caller) call
   1036         // the in-place destructor.
   1037         SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec));
   1038         return false;
   1039     }
   1040     return true;
   1041 }
   1042