1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/*
3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project
4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com *
5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file.
7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */
8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com
9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlitter.h"
11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkAntiRun.h"
12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColor.h"
13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorFilter.h"
14e54ef29a2cc707807a3b5581fc01f49f75a3bf86reed@google.com#include "SkFilterShader.h"
159ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkFlattenableBuffers.h"
16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMask.h"
17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMaskFilter.h"
18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTemplatesPriv.h"
19c29484063de303a04774d87c060434c8b496f7b0reed@google.com#include "SkTLazy.h"
20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkUtils.h"
21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkXfermode.h"
22bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#include "SkString.h"
23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
244130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.comSkBlitter::~SkBlitter() {}
25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
269c5343d6390ef1f4d6daee484524d7d616167f20reed@google.combool SkBlitter::isNullBlitter() const { return false; }
279c5343d6390ef1f4d6daee484524d7d616167f20reed@google.com
28919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return NULL;
30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
32919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitH(int x, int y, int width) {
332d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com    SkDEBUGFAIL("unimplemented");
34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
36919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
37919114813d58933c9d9433b141e0222c34b700b1reed@google.com                          const int16_t runs[]) {
382d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com    SkDEBUGFAIL("unimplemented");
39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
41919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
42919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (alpha == 255) {
43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->blitRect(x, y, 1, height);
44919114813d58933c9d9433b141e0222c34b700b1reed@google.com    } else {
45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int16_t runs[2];
46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        runs[0] = 1;
47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        runs[1] = 0;
48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
49919114813d58933c9d9433b141e0222c34b700b1reed@google.com        while (--height >= 0) {
50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            this->blitAntiH(x, y++, &alpha, runs);
51919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
55919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitRect(int x, int y, int width, int height) {
560182ae97e654d95b82ce36e34c7049e949427298tomhudson@google.com    SkASSERT(width > 0);
57919114813d58933c9d9433b141e0222c34b700b1reed@google.com    while (--height >= 0) {
58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->blitH(x, y++, width);
59919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
626130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com/// Default implementation doesn't check for any easy optimizations
636130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com/// such as alpha == 0 or 255; also uses blitV(), which some subclasses
646130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com/// may not support.
656130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.comvoid SkBlitter::blitAntiRect(int x, int y, int width, int height,
666130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                             SkAlpha leftAlpha, SkAlpha rightAlpha) {
6767b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com    this->blitV(x++, y, height, leftAlpha);
680182ae97e654d95b82ce36e34c7049e949427298tomhudson@google.com    if (width > 0) {
6967b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com        this->blitRect(x, y, width, height);
7067b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com        x += width;
7167b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com    }
7267b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com    this->blitV(x, y, height, rightAlpha);
736130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com}
746130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com//////////////////////////////////////////////////////////////////////////////
76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
77919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic inline void bits_to_runs(SkBlitter* blitter, int x, int y,
78919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                const uint8_t bits[],
79919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                U8CPU left_mask, int rowBytes,
80919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                U8CPU right_mask) {
81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int inFill = 0;
82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int pos = 0;
83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
84919114813d58933c9d9433b141e0222c34b700b1reed@google.com    while (--rowBytes >= 0) {
85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        unsigned b = *bits++ & left_mask;
86919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (rowBytes == 0) {
87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            b &= right_mask;
88919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
90919114813d58933c9d9433b141e0222c34b700b1reed@google.com        for (unsigned test = 0x80; test != 0; test >>= 1) {
91919114813d58933c9d9433b141e0222c34b700b1reed@google.com            if (b & test) {
92919114813d58933c9d9433b141e0222c34b700b1reed@google.com                if (!inFill) {
93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    pos = x;
94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    inFill = true;
95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
96919114813d58933c9d9433b141e0222c34b700b1reed@google.com            } else {
97919114813d58933c9d9433b141e0222c34b700b1reed@google.com                if (inFill) {
98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    blitter->blitH(pos, y, x - pos);
99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    inFill = false;
100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            x += 1;
103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        left_mask = 0xFF;
105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // final cleanup
108919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (inFill) {
109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        blitter->blitH(pos, y, x - pos);
110919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
113919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(mask.fBounds.contains(clip));
115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
116919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (mask.fFormat == SkMask::kBW_Format) {
117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int cx = clip.fLeft;
118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int cy = clip.fTop;
119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int maskLeft = mask.fBounds.fLeft;
120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int mask_rowBytes = mask.fRowBytes;
121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int height = clip.height();
122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const uint8_t* bits = mask.getAddr1(cx, cy);
124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
125919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
126919114813d58933c9d9433b141e0222c34b700b1reed@google.com            while (--height >= 0) {
127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                bits += mask_rowBytes;
129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                cy += 1;
130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
131919114813d58933c9d9433b141e0222c34b700b1reed@google.com        } else {
132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int left_edge = cx - maskLeft;
133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(left_edge >= 0);
134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int rite_edge = clip.fRight - maskLeft;
135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(rite_edge > left_edge);
136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int left_mask = 0xFF >> (left_edge & 7);
138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int rite_mask = 0xFF << (8 - (rite_edge & 7));
139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
141b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com            // check for empty right mask, so we don't read off the end (or go slower than we need to)
142919114813d58933c9d9433b141e0222c34b700b1reed@google.com            if (rite_mask == 0) {
143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                SkASSERT(full_runs >= 0);
144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                full_runs -= 1;
145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                rite_mask = 0xFF;
146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
147919114813d58933c9d9433b141e0222c34b700b1reed@google.com            if (left_mask == 0xFF) {
148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                full_runs -= 1;
149919114813d58933c9d9433b141e0222c34b700b1reed@google.com            }
150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
151b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com            // back up manually so we can keep in sync with our byte-aligned src
152b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com            // have cx reflect our actual starting x-coord
153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            cx -= left_edge & 7;
154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
155919114813d58933c9d9433b141e0222c34b700b1reed@google.com            if (full_runs < 0) {
156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                SkASSERT((left_mask & rite_mask) != 0);
157919114813d58933c9d9433b141e0222c34b700b1reed@google.com                while (--height >= 0) {
158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    bits += mask_rowBytes;
160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    cy += 1;
161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
162919114813d58933c9d9433b141e0222c34b700b1reed@google.com            } else {
163919114813d58933c9d9433b141e0222c34b700b1reed@google.com                while (--height >= 0) {
164b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com                    bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    bits += mask_rowBytes;
166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    cy += 1;
167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                }
168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
170919114813d58933c9d9433b141e0222c34b700b1reed@google.com    } else {
171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int                         width = clip.width();
172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int16_t*                    runs = runStorage.get();
174e2961f787751b880e535e893ca068af71218ba32reed@google.com        const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        sk_memset16((uint16_t*)runs, 1, width);
177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        runs[width] = 0;
178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int height = clip.height();
180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int y = clip.fTop;
181919114813d58933c9d9433b141e0222c34b700b1reed@google.com        while (--height >= 0) {
182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            this->blitAntiH(clip.fLeft, y, aa, runs);
183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            aa += mask.fRowBytes;
184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            y += 1;
185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////// these guys are not virtual, just a helpers
190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    if (clip.quickReject(mask.fBounds)) {
193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
195919114813d58933c9d9433b141e0222c34b700b1reed@google.com
196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Cliperator clipper(clip, mask.fBounds);
197919114813d58933c9d9433b141e0222c34b700b1reed@google.com
198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    while (!clipper.done()) {
199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const SkIRect& cr = clipper.rect();
200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->blitMask(mask, cr);
201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        clipper.next();
202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Cliperator clipper(clip, rect);
207919114813d58933c9d9433b141e0222c34b700b1reed@google.com
208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    while (!clipper.done()) {
209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const SkIRect& cr = clipper.rect();
210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        clipper.next();
212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBlitter::blitRegion(const SkRegion& clip) {
216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Iterator iter(clip);
217919114813d58933c9d9433b141e0222c34b700b1reed@google.com
218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    while (!iter.done()) {
219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const SkIRect& cr = iter.rect();
220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        iter.next();
222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
225919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
227919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitH(int x, int y, int width) {}
228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
229919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
230919114813d58933c9d9433b141e0222c34b700b1reed@google.com                              const int16_t runs[]) {}
231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
232919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
234919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitRect(int x, int y, int width, int height) {}
235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
236919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
238919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return NULL;
240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
2429c5343d6390ef1f4d6daee484524d7d616167f20reed@google.combool SkNullBlitter::isNullBlitter() const { return true; }
2439c5343d6390ef1f4d6daee484524d7d616167f20reed@google.com
244919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
246919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic int compute_anti_width(const int16_t runs[]) {
247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int width = 0;
248919114813d58933c9d9433b141e0222c34b700b1reed@google.com
249919114813d58933c9d9433b141e0222c34b700b1reed@google.com    for (;;) {
250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int count = runs[0];
251919114813d58933c9d9433b141e0222c34b700b1reed@google.com
252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(count >= 0);
253919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (count == 0) {
254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            break;
255919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        width += count;
257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        runs += count;
258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return width;
260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
262919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) {
263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
266919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) {
267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
270919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitH(int left, int y, int width) {
271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(width > 0);
272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
273919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (!y_in_rect(y, fClipRect)) {
274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
275919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int right = left + width;
278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
279919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (left < fClipRect.fLeft) {
280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        left = fClipRect.fLeft;
281919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
282919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (right > fClipRect.fRight) {
283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        right = fClipRect.fRight;
284919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    width = right - left;
287919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (width > 0) {
288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitH(left, y, width);
289919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
292919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
293919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                  const int16_t runs[]) {
294919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
296919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int x0 = left;
299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int x1 = left + compute_anti_width(runs);
300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
301919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (x1 <= fClipRect.fLeft) {
302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
303919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(x0 < x1);
306919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (x0 < fClipRect.fLeft) {
307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        int dx = fClipRect.fLeft - x0;
308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        runs += dx;
310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        aa += dx;
311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x0 = fClipRect.fLeft;
312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
315919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (x1 > fClipRect.fRight) {
316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        x1 = fClipRect.fRight;
317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        ((int16_t*)runs)[x1 - x0] = 0;
319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(compute_anti_width(runs) == x1 - x0);
323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fBlitter->blitAntiH(x0, y, aa, runs);
325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
327919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(height > 0);
329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
330919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (!x_in_rect(x, fClipRect)) {
331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return;
332919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int y0 = y;
335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int y1 = y + height;
336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
337919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (y0 < fClipRect.fTop) {
338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        y0 = fClipRect.fTop;
339919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
340919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (y1 > fClipRect.fBottom) {
341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        y1 = fClipRect.fBottom;
342919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
344919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (y0 < y1) {
345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitV(x, y0, y1 - y0, alpha);
346919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
349919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect    r;
351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    r.set(left, y, left + width, y + height);
353919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (r.intersect(fClipRect)) {
354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
355919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
3586130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.comvoid SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
3596130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
3606130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    SkIRect    r;
3616130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
3626130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    // The *true* width of the rectangle blitted is width+2:
3636130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    r.set(left, y, left + width + 2, y + height);
3646130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    if (r.intersect(fClipRect)) {
3656130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        if (r.fLeft != left) {
3666130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            SkASSERT(r.fLeft > left);
3676130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            leftAlpha = 255;
3686130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        }
3696130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        if (r.fRight != left + width + 2) {
3706130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            SkASSERT(r.fRight < left + width + 2);
3716130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            rightAlpha = 255;
3726130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        }
3736130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        if (255 == leftAlpha && 255 == rightAlpha) {
3746130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
3756130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        } else if (1 == r.width()) {
3766130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            if (r.fLeft == left) {
3776130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
3786130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            } else {
3796130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                SkASSERT(r.fLeft == left + width + 1);
3806130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
3816130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            }
3826130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        } else {
3836130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
3846130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                                   leftAlpha, rightAlpha);
3856130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        }
3866130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    }
3876130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com}
3886130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
389919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(mask.fBounds.contains(clip));
391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect    r = clip;
393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
394919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (r.intersect(fClipRect)) {
395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitMask(mask, r);
396919114813d58933c9d9433b141e0222c34b700b1reed@google.com    }
397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
399919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return fBlitter->justAnOpaqueColor(value);
401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
403919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
405919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitH(int x, int y, int width) {
406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int left, right;
408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
409919114813d58933c9d9433b141e0222c34b700b1reed@google.com    while (span.next(&left, &right)) {
410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(left < right);
411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitH(left, y, right - left);
412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
415919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
416919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                 const int16_t runs[]) {
417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int width = compute_anti_width(runs);
418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int left, right;
420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
421919114813d58933c9d9433b141e0222c34b700b1reed@google.com
422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    int prevRite = x;
423919114813d58933c9d9433b141e0222c34b700b1reed@google.com    while (span.next(&left, &right)) {
424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(x <= left);
425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(left < right);
426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
427919114813d58933c9d9433b141e0222c34b700b1reed@google.com
428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        // now zero before left
431919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (left > prevRite) {
432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int index = prevRite - x;
433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            ((uint8_t*)aa)[index] = 0;   // skip runs after right
434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            ((int16_t*)runs)[index] = SkToS16(left - prevRite);
435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
436919114813d58933c9d9433b141e0222c34b700b1reed@google.com
437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        prevRite = right;
438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
439919114813d58933c9d9433b141e0222c34b700b1reed@google.com
440919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (prevRite > x) {
441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        ((int16_t*)runs)[prevRite - x] = 0;
442919114813d58933c9d9433b141e0222c34b700b1reed@google.com
443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        if (x < 0) {
444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            int skip = runs[0];
445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            SkASSERT(skip >= -x);
446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            aa += skip;
447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            runs += skip;
448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            x += skip;
449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitAntiH(x, y, aa, runs);
451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
454919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect    bounds;
456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bounds.set(x, y, x + 1, y + height);
457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
460919114813d58933c9d9433b141e0222c34b700b1reed@google.com    while (!iter.done()) {
461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const SkIRect& r = iter.rect();
462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(bounds.contains(r));
463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitV(x, r.fTop, r.height(), alpha);
465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        iter.next();
466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
469919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkIRect    bounds;
471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    bounds.set(x, y, x + width, y + height);
472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
475919114813d58933c9d9433b141e0222c34b700b1reed@google.com    while (!iter.done()) {
476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const SkIRect& r = iter.rect();
477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(bounds.contains(r));
478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        iter.next();
481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
4846130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.comvoid SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
4856130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                                    SkAlpha leftAlpha, SkAlpha rightAlpha) {
4866130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    // The *true* width of the rectangle to blit is width + 2
4876130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    SkIRect    bounds;
4886130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    bounds.set(x, y, x + width + 2, y + height);
4896130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
4906130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    SkRegion::Cliperator    iter(*fRgn, bounds);
4916130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
4926130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    while (!iter.done()) {
4936130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        const SkIRect& r = iter.rect();
4946130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        SkASSERT(bounds.contains(r));
4956130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        SkASSERT(r.fLeft >= x);
496d5a4a434a91cf65e53807785ac6a3d3747726fcetomhudson@google.com        SkASSERT(r.fRight <= x + width + 2);
4976130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
4986130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
4996130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
5006130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                                      rightAlpha : 255;
5016130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
5026130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
5036130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
5046130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        } else if (1 == r.width()) {
5056130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            if (r.fLeft == x) {
506935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
5076130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                                effectiveLeftAlpha);
5086130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            } else {
5096130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                SkASSERT(r.fLeft == x + width + 1);
5106130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
5116130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                                effectiveRightAlpha);
5126130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            }
5136130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        } else {
5146130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
5156130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com                                   effectiveLeftAlpha, effectiveRightAlpha);
5166130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        }
5176130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com        iter.next();
5186130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com    }
5196130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com}
5206130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
5216130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com
522919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
523bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(mask.fBounds.contains(clip));
524bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
525bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkRegion::Cliperator iter(*fRgn, clip);
526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    const SkIRect&       r = iter.rect();
527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkBlitter*           blitter = fBlitter;
528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
529919114813d58933c9d9433b141e0222c34b700b1reed@google.com    while (!iter.done()) {
530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        blitter->blitMask(mask, r);
531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        iter.next();
532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
535919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
536bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return fBlitter->justAnOpaqueColor(value);
537bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
538bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
539919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
540bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
541919114813d58933c9d9433b141e0222c34b700b1reed@google.comSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
542919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                   const SkIRect* ir) {
543919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (clip) {
544bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const SkIRect& clipR = clip->getBounds();
545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
546919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
547bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            blitter = &fNullBlitter;
548919114813d58933c9d9433b141e0222c34b700b1reed@google.com        } else if (clip->isRect()) {
549919114813d58933c9d9433b141e0222c34b700b1reed@google.com            if (ir == NULL || !clipR.contains(*ir)) {
550bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                fRectBlitter.init(blitter, clipR);
551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                blitter = &fRectBlitter;
552bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
553919114813d58933c9d9433b141e0222c34b700b1reed@google.com        } else {
554bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fRgnBlitter.init(blitter, clip);
555bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            blitter = &fRgnBlitter;
556bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
557bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
558bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return blitter;
559bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
560bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
561919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
562bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
563bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorShader.h"
564bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorPriv.h"
565bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
566bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass Sk3DShader : public SkShader {
567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic:
568919114813d58933c9d9433b141e0222c34b700b1reed@google.com    Sk3DShader(SkShader* proxy) : fProxy(proxy) {
569919114813d58933c9d9433b141e0222c34b700b1reed@google.com        SkSafeRef(proxy);
570bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fMask = NULL;
571bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
572919114813d58933c9d9433b141e0222c34b700b1reed@google.com
573919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual ~Sk3DShader() {
574919114813d58933c9d9433b141e0222c34b700b1reed@google.com        SkSafeUnref(fProxy);
575bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
576919114813d58933c9d9433b141e0222c34b700b1reed@google.com
577bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void setMask(const SkMask* mask) { fMask = mask; }
578bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
579919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
580bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com                            const SkMatrix& matrix) SK_OVERRIDE {
581bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        if (!this->INHERITED::setContext(device, paint, matrix)) {
582bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com            return false;
583bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        }
584919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (fProxy) {
585bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com            if (!fProxy->setContext(device, paint, matrix)) {
586bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com                // must keep our set/end context calls balanced
587bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com                this->INHERITED::endContext();
588bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com                return false;
589bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com            }
590919114813d58933c9d9433b141e0222c34b700b1reed@google.com        } else {
591bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fPMColor = SkPreMultiplyColor(paint.getColor());
592bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
593bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        return true;
594bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com    }
5951fa5c44bd02b1cb42ad2fcc20ab1bb06d9ca7fbbskia.committer@gmail.com
596bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com    virtual void endContext() SK_OVERRIDE {
597bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        if (fProxy) {
598bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com            fProxy->endContext();
599bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        }
600bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        this->INHERITED::endContext();
601bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
602919114813d58933c9d9433b141e0222c34b700b1reed@google.com
603bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com    virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE {
604919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (fProxy) {
605bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fProxy->shadeSpan(x, y, span, count);
606919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
608919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (fMask == NULL) {
609919114813d58933c9d9433b141e0222c34b700b1reed@google.com            if (fProxy == NULL) {
610bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                sk_memset32(span, fPMColor, count);
611919114813d58933c9d9433b141e0222c34b700b1reed@google.com            }
612bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            return;
613bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
614bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
615bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(fMask->fBounds.contains(x, y));
616bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(fMask->fBounds.contains(x + count - 1, y));
617bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
618bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        size_t          size = fMask->computeImageSize();
619e2961f787751b880e535e893ca068af71218ba32reed@google.com        const uint8_t*  alpha = fMask->getAddr8(x, y);
620bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const uint8_t*  mulp = alpha + size;
621bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        const uint8_t*  addp = mulp + size;
622bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
623919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (fProxy) {
624919114813d58933c9d9433b141e0222c34b700b1reed@google.com            for (int i = 0; i < count; i++) {
625919114813d58933c9d9433b141e0222c34b700b1reed@google.com                if (alpha[i]) {
626bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    SkPMColor c = span[i];
627919114813d58933c9d9433b141e0222c34b700b1reed@google.com                    if (c) {
628bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        unsigned a = SkGetPackedA32(c);
629bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        unsigned r = SkGetPackedR32(c);
630bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        unsigned g = SkGetPackedG32(c);
631bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        unsigned b = SkGetPackedB32(c);
632bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
633bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        unsigned mul = SkAlpha255To256(mulp[i]);
634bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        unsigned add = addp[i];
635bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
636bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
637bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
638bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
639bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
640bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                        span[i] = SkPackARGB32(a, r, g, b);
641bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    }
642919114813d58933c9d9433b141e0222c34b700b1reed@google.com                } else {
643bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    span[i] = 0;
644919114813d58933c9d9433b141e0222c34b700b1reed@google.com                }
645bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
646919114813d58933c9d9433b141e0222c34b700b1reed@google.com        } else {    // color
647bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            unsigned a = SkGetPackedA32(fPMColor);
648bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            unsigned r = SkGetPackedR32(fPMColor);
649bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            unsigned g = SkGetPackedG32(fPMColor);
650bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            unsigned b = SkGetPackedB32(fPMColor);
651919114813d58933c9d9433b141e0222c34b700b1reed@google.com            for (int i = 0; i < count; i++) {
652919114813d58933c9d9433b141e0222c34b700b1reed@google.com                if (alpha[i]) {
653bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    unsigned mul = SkAlpha255To256(mulp[i]);
654bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    unsigned add = addp[i];
655bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
656bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    span[i] = SkPackARGB32( a,
657919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                    SkFastMin32(SkAlphaMul(r, mul) + add, a),
658919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                    SkFastMin32(SkAlphaMul(g, mul) + add, a),
659919114813d58933c9d9433b141e0222c34b700b1reed@google.com                                    SkFastMin32(SkAlphaMul(b, mul) + add, a));
660919114813d58933c9d9433b141e0222c34b700b1reed@google.com                } else {
661bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                    span[i] = 0;
662919114813d58933c9d9433b141e0222c34b700b1reed@google.com                }
663bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            }
664bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        }
665bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
666919114813d58933c9d9433b141e0222c34b700b1reed@google.com
667bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#ifdef SK_DEVELOPER
668bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com    virtual void toString(SkString* str) const SK_OVERRIDE {
669bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com        str->append("Sk3DShader: (");
670bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com
671bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com        if (NULL != fProxy) {
672bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com            str->append("Proxy: ");
673bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com            fProxy->toString(str);
674bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com        }
675bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com
676bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com        this->INHERITED::toString(str);
677bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com
678bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com        str->append(")");
679bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com    }
680bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#endif
681bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com
6824d1d95c61576960796347e1dd5006d878e9d2dc0djsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
6834d1d95c61576960796347e1dd5006d878e9d2dc0djsollen@google.com
684bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprotected:
685cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.com    Sk3DShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
6865e901c8c1bea70be7fc2c39112746891e38f72c9reed@google.com        fProxy = buffer.readShader();
6879ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com        fPMColor = buffer.readColor();
688bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fMask = NULL;
689bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
690919114813d58933c9d9433b141e0222c34b700b1reed@google.com
691cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
692bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        this->INHERITED::flatten(buffer);
693bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        buffer.writeFlattenable(fProxy);
6949ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com        buffer.writeColor(fPMColor);
695bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
696919114813d58933c9d9433b141e0222c34b700b1reed@google.com
697bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate:
698bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkShader*       fProxy;
699bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkPMColor       fPMColor;
700bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    const SkMask*   fMask;
701bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
702bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    typedef SkShader INHERITED;
703bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com};
704bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
705bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass Sk3DBlitter : public SkBlitter {
706bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic:
707bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
708919114813d58933c9d9433b141e0222c34b700b1reed@google.com            : fProxy(proxy), f3DShader(shader), fKillProc(killProc) {
709bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        shader->ref();
710bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
711919114813d58933c9d9433b141e0222c34b700b1reed@google.com
712919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual ~Sk3DBlitter() {
713bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        f3DShader->unref();
714bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fKillProc(fProxy);
715bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
716bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
717919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual void blitH(int x, int y, int width) {
718bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fProxy->blitH(x, y, width);
719bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
720919114813d58933c9d9433b141e0222c34b700b1reed@google.com
721919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
722919114813d58933c9d9433b141e0222c34b700b1reed@google.com                           const int16_t runs[]) {
723bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fProxy->blitAntiH(x, y, antialias, runs);
724bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
725919114813d58933c9d9433b141e0222c34b700b1reed@google.com
726919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual void blitV(int x, int y, int height, SkAlpha alpha) {
727bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fProxy->blitV(x, y, height, alpha);
728bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
729919114813d58933c9d9433b141e0222c34b700b1reed@google.com
730919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual void blitRect(int x, int y, int width, int height) {
731bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fProxy->blitRect(x, y, width, height);
732bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
733919114813d58933c9d9433b141e0222c34b700b1reed@google.com
734919114813d58933c9d9433b141e0222c34b700b1reed@google.com    virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
735919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (mask.fFormat == SkMask::k3D_Format) {
736bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            f3DShader->setMask(&mask);
737bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
738bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
739bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fProxy->blitMask(mask, clip);
740bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
741bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
742bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            f3DShader->setMask(NULL);
743919114813d58933c9d9433b141e0222c34b700b1reed@google.com        } else {
744bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fProxy->blitMask(mask, clip);
745919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
746bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
747919114813d58933c9d9433b141e0222c34b700b1reed@google.com
748bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate:
749bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkBlitter*  fProxy;
750bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Sk3DShader* f3DShader;
751bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void        (*fKillProc)(void*);
752bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com};
753bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
754919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
755bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
756bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkCoreBlitters.h"
757bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
758bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkAutoCallProc {
759bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic:
760bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    typedef void (*Proc)(void*);
761919114813d58933c9d9433b141e0222c34b700b1reed@google.com
762bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkAutoCallProc(void* obj, Proc proc)
763919114813d58933c9d9433b141e0222c34b700b1reed@google.com    : fObj(obj), fProc(proc) {}
764919114813d58933c9d9433b141e0222c34b700b1reed@google.com
765919114813d58933c9d9433b141e0222c34b700b1reed@google.com    ~SkAutoCallProc() {
766919114813d58933c9d9433b141e0222c34b700b1reed@google.com        if (fObj && fProc) {
767bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com            fProc(fObj);
768919114813d58933c9d9433b141e0222c34b700b1reed@google.com        }
769bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
770919114813d58933c9d9433b141e0222c34b700b1reed@google.com
771bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void* get() const { return fObj; }
772919114813d58933c9d9433b141e0222c34b700b1reed@google.com
773919114813d58933c9d9433b141e0222c34b700b1reed@google.com    void* detach() {
774bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        void* obj = fObj;
775bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        fObj = NULL;
776bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return obj;
777bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
778919114813d58933c9d9433b141e0222c34b700b1reed@google.com
779bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate:
780bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    void*   fObj;
781bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Proc    fProc;
782bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com};
7837345112995b14b457ec7d67e3d1211dd7a7597b0commit-bot@chromium.org#define SkAutoCallProc(...) SK_REQUIRE_LOCAL_VAR(SkAutoCallProc)
784bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
785919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic void destroy_blitter(void* blitter) {
786bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    ((SkBlitter*)blitter)->~SkBlitter();
787bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
788bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
789919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic void delete_blitter(void* blitter) {
790bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkDELETE((SkBlitter*)blitter);
791bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
792bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
793155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.comstatic bool just_solid_color(const SkPaint& paint) {
794155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
795155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com        SkShader* shader = paint.getShader();
796155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com        if (NULL == shader ||
797155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
798155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com            return true;
799155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com        }
800155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    }
801155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    return false;
802155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com}
803919114813d58933c9d9433b141e0222c34b700b1reed@google.com
804155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com/** By analyzing the paint (with an xfermode), we may decide we can take
805155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    special action. This enum lists our possible actions
806155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com */
807155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.comenum XferInterp {
808155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    kNormal_XferInterp,         // no special interpretation, draw normally
809155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    kSrcOver_XferInterp,        // draw as if in srcover mode
810155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    kSkipDrawing_XferInterp     // draw nothing
811155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com};
812155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com
813155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.comstatic XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
814155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                                     SkBitmap::Config deviceConfig) {
8154130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com    SkXfermode::Mode  mode;
816919114813d58933c9d9433b141e0222c34b700b1reed@google.com
8177152b7b11a143fdfb7eb8d185df0ce124d853011mike@reedtribe.org    if (SkXfermode::AsMode(xfer, &mode)) {
818155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com        switch (mode) {
8194130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com            case SkXfermode::kSrc_Mode:
820155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                if (just_solid_color(paint)) {
821155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                    return kSrcOver_XferInterp;
822155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                }
823155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                break;
8244130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com            case SkXfermode::kDst_Mode:
825155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                return kSkipDrawing_XferInterp;
8264130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com            case SkXfermode::kSrcOver_Mode:
827155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                return kSrcOver_XferInterp;
8284130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com            case SkXfermode::kDstOver_Mode:
829155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                if (SkBitmap::kRGB_565_Config == deviceConfig) {
830155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                    return kSkipDrawing_XferInterp;
831155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                }
832155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                break;
8334130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com            case SkXfermode::kSrcIn_Mode:
834155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                if (SkBitmap::kRGB_565_Config == deviceConfig &&
835155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                    just_solid_color(paint)) {
836155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                    return kSrcOver_XferInterp;
837155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                }
838155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                break;
8394130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com            case SkXfermode::kDstIn_Mode:
840155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                if (just_solid_color(paint)) {
841155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                    return kSkipDrawing_XferInterp;
842155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                }
843155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                break;
844155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com            default:
845155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                break;
846155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com        }
847155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    }
848155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    return kNormal_XferInterp;
849155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com}
850155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com
851bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBlitter* SkBlitter::Choose(const SkBitmap& device,
852bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com                             const SkMatrix& matrix,
85315477316c7e77f3adf05b922dfc144237bde141dreed@google.com                             const SkPaint& origPaint,
8540ae872fff20fdac8efed4cac5894a392360bd919reed@google.com                             void* storage, size_t storageSize,
8550ae872fff20fdac8efed4cac5894a392360bd919reed@google.com                             bool drawCoverage) {
856bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(storageSize == 0 || storage != NULL);
857bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
858bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkBlitter*  blitter = NULL;
859bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
860bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // which check, in case we're being called by a client with a dummy device
861bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    // (e.g. they have a bounder that always aborts the draw)
8620ae872fff20fdac8efed4cac5894a392360bd919reed@google.com    if (SkBitmap::kNo_Config == device.config() ||
8630ae872fff20fdac8efed4cac5894a392360bd919reed@google.com            (drawCoverage && (SkBitmap::kA8_Config != device.config()))) {
864bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
865bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        return blitter;
866bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
867bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
868c29484063de303a04774d87c060434c8b496f7b0reed@google.com    SkShader* shader = origPaint.getShader();
869c29484063de303a04774d87c060434c8b496f7b0reed@google.com    SkColorFilter* cf = origPaint.getColorFilter();
870c29484063de303a04774d87c060434c8b496f7b0reed@google.com    SkXfermode* mode = origPaint.getXfermode();
871bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    Sk3DShader* shader3D = NULL;
872c29484063de303a04774d87c060434c8b496f7b0reed@google.com
873d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
874935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
875c29484063de303a04774d87c060434c8b496f7b0reed@google.com    if (origPaint.getMaskFilter() != NULL &&
876c29484063de303a04774d87c060434c8b496f7b0reed@google.com            origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
877bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        shader3D = SkNEW_ARGS(Sk3DShader, (shader));
878c29484063de303a04774d87c060434c8b496f7b0reed@google.com        // we know we haven't initialized lazyPaint yet, so just do it
879d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com        paint.writable()->setShader(shader3D)->unref();
880bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        shader = shader3D;
881bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
882bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
883155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    if (NULL != mode) {
884c29484063de303a04774d87c060434c8b496f7b0reed@google.com        switch (interpret_xfermode(*paint, mode, device.config())) {
885155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com            case kSrcOver_XferInterp:
886155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                mode = NULL;
887d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com                paint.writable()->setXfermode(NULL);
888155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                break;
889155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com            case kSkipDrawing_XferInterp:
890155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
891155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                return blitter;
892155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com            default:
893155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com                break;
894155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com        }
895155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com    }
896155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com
897e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    /*
898e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com     *  If the xfermode is CLEAR, then we can completely ignore the installed
899e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com     *  color/shader/colorfilter, and just pretend we're SRC + color==0. This
900e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com     *  will fall into our optimizations for SRC mode.
901e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com     */
902e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) {
903e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        SkPaint* p = paint.writable();
904e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        shader = p->setShader(NULL);
905e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        cf = p->setColorFilter(NULL);
906e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        mode = p->setXfermodeMode(SkXfermode::kSrc_Mode);
907e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com        p->setColor(0);
908e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com    }
909e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com
91015477316c7e77f3adf05b922dfc144237bde141dreed@google.com    if (NULL == shader) {
91115477316c7e77f3adf05b922dfc144237bde141dreed@google.com        if (mode) {
91215477316c7e77f3adf05b922dfc144237bde141dreed@google.com            // xfermodes (and filters) require shaders for our current blitters
91315477316c7e77f3adf05b922dfc144237bde141dreed@google.com            shader = SkNEW(SkColorShader);
914d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com            paint.writable()->setShader(shader)->unref();
91515477316c7e77f3adf05b922dfc144237bde141dreed@google.com        } else if (cf) {
91615477316c7e77f3adf05b922dfc144237bde141dreed@google.com            // if no shader && no xfermode, we just apply the colorfilter to
91715477316c7e77f3adf05b922dfc144237bde141dreed@google.com            // our color and move on.
918d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com            SkPaint* writablePaint = paint.writable();
919d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com            writablePaint->setColor(cf->filterColor(paint->getColor()));
920d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com            writablePaint->setColorFilter(NULL);
92115477316c7e77f3adf05b922dfc144237bde141dreed@google.com            cf = NULL;
92215477316c7e77f3adf05b922dfc144237bde141dreed@google.com        }
923bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
924919114813d58933c9d9433b141e0222c34b700b1reed@google.com
92515477316c7e77f3adf05b922dfc144237bde141dreed@google.com    if (cf) {
926bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkASSERT(shader);
92715477316c7e77f3adf05b922dfc144237bde141dreed@google.com        shader = SkNEW_ARGS(SkFilterShader, (shader, cf));
928d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com        paint.writable()->setShader(shader)->unref();
929ad6f8bba9429d18d5974f0716dc2113b8fb73001reed@android.com        // blitters should ignore the presence/absence of a filter, since
930ad6f8bba9429d18d5974f0716dc2113b8fb73001reed@android.com        // if there is one, the shader will take care of it.
931bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
932919114813d58933c9d9433b141e0222c34b700b1reed@google.com
933bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com    /*
934bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com     *  We need to have balanced calls to the shader:
935bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com     *      setContext
936bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com     *      endContext
937bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com     *  We make the first call here, in case it fails we can abort the draw.
938bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com     *  The endContext() call is made by the blitter (assuming setContext did
939bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com     *  not fail) in its destructor.
940bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com     */
941c29484063de303a04774d87c060434c8b496f7b0reed@google.com    if (shader && !shader->setContext(device, *paint, matrix)) {
942bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
943bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com        return blitter;
944bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
945bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
9467a59bd231c10eb208b4a4a1633dd301f516bf1bbskia.committer@gmail.com
947bb6a0d330cd7dae11f94aff99c001d4d1eca0716reed@google.com    switch (device.config()) {
948919114813d58933c9d9433b141e0222c34b700b1reed@google.com        case SkBitmap::kA8_Config:
9490ae872fff20fdac8efed4cac5894a392360bd919reed@google.com            if (drawCoverage) {
9500ae872fff20fdac8efed4cac5894a392360bd919reed@google.com                SkASSERT(NULL == shader);
9510ae872fff20fdac8efed4cac5894a392360bd919reed@google.com                SkASSERT(NULL == paint->getXfermode());
9520ae872fff20fdac8efed4cac5894a392360bd919reed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Coverage_Blitter,
9530ae872fff20fdac8efed4cac5894a392360bd919reed@google.com                                      storage, storageSize, (device, *paint));
9540ae872fff20fdac8efed4cac5894a392360bd919reed@google.com            } else if (shader) {
955919114813d58933c9d9433b141e0222c34b700b1reed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter,
956c29484063de303a04774d87c060434c8b496f7b0reed@google.com                                      storage, storageSize, (device, *paint));
957919114813d58933c9d9433b141e0222c34b700b1reed@google.com            } else {
958919114813d58933c9d9433b141e0222c34b700b1reed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter,
959c29484063de303a04774d87c060434c8b496f7b0reed@google.com                                      storage, storageSize, (device, *paint));
960919114813d58933c9d9433b141e0222c34b700b1reed@google.com            }
961919114813d58933c9d9433b141e0222c34b700b1reed@google.com            break;
962919114813d58933c9d9433b141e0222c34b700b1reed@google.com
963919114813d58933c9d9433b141e0222c34b700b1reed@google.com        case SkBitmap::kRGB_565_Config:
964c29484063de303a04774d87c060434c8b496f7b0reed@google.com            blitter = SkBlitter_ChooseD565(device, *paint, storage, storageSize);
965919114813d58933c9d9433b141e0222c34b700b1reed@google.com            break;
966919114813d58933c9d9433b141e0222c34b700b1reed@google.com
967919114813d58933c9d9433b141e0222c34b700b1reed@google.com        case SkBitmap::kARGB_8888_Config:
968919114813d58933c9d9433b141e0222c34b700b1reed@google.com            if (shader) {
969919114813d58933c9d9433b141e0222c34b700b1reed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter,
970c29484063de303a04774d87c060434c8b496f7b0reed@google.com                                      storage, storageSize, (device, *paint));
971c29484063de303a04774d87c060434c8b496f7b0reed@google.com            } else if (paint->getColor() == SK_ColorBLACK) {
972919114813d58933c9d9433b141e0222c34b700b1reed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter,
973c29484063de303a04774d87c060434c8b496f7b0reed@google.com                                      storage, storageSize, (device, *paint));
974c29484063de303a04774d87c060434c8b496f7b0reed@google.com            } else if (paint->getAlpha() == 0xFF) {
975919114813d58933c9d9433b141e0222c34b700b1reed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter,
976c29484063de303a04774d87c060434c8b496f7b0reed@google.com                                      storage, storageSize, (device, *paint));
977919114813d58933c9d9433b141e0222c34b700b1reed@google.com            } else {
978919114813d58933c9d9433b141e0222c34b700b1reed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter,
979c29484063de303a04774d87c060434c8b496f7b0reed@google.com                                      storage, storageSize, (device, *paint));
980919114813d58933c9d9433b141e0222c34b700b1reed@google.com            }
981919114813d58933c9d9433b141e0222c34b700b1reed@google.com            break;
982919114813d58933c9d9433b141e0222c34b700b1reed@google.com
983919114813d58933c9d9433b141e0222c34b700b1reed@google.com        default:
9842d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com            SkDEBUGFAIL("unsupported device config");
985919114813d58933c9d9433b141e0222c34b700b1reed@google.com            SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
986919114813d58933c9d9433b141e0222c34b700b1reed@google.com            break;
987bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
988bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
989919114813d58933c9d9433b141e0222c34b700b1reed@google.com    if (shader3D) {
990bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
991bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        SkAutoCallProc  tmp(blitter, proc);
992bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
993bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
994bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com        (void)tmp.detach();
995bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    }
996bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    return blitter;
997bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
998bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
999919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
1000bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1001bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst uint16_t gMask_0F0F = 0xF0F;
1002bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst uint32_t gMask_00FF00FF = 0xFF00FF;
1003bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1004919114813d58933c9d9433b141e0222c34b700b1reed@google.com///////////////////////////////////////////////////////////////////////////////
1005bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1006bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
10079ed8f76ef95fdda704a60a0e787395612bc70443reed@android.com        : INHERITED(device) {
1008bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fShader = paint.getShader();
1009bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    SkASSERT(fShader);
1010bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com    SkASSERT(fShader->setContextHasBeenCalled());
1011bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
1012bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fShader->ref();
10139ed8f76ef95fdda704a60a0e787395612bc70443reed@android.com    fShaderFlags = fShader->getFlags();
1014bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1015bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com
10169ed8f76ef95fdda704a60a0e787395612bc70443reed@android.comSkShaderBlitter::~SkShaderBlitter() {
1017bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com    SkASSERT(fShader->setContextHasBeenCalled());
1018bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com    fShader->endContext();
1019bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com    fShader->unref();
1020bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}
1021