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