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