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