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