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