SkBlitter.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAntiRun.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColor.h"
138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMask.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplatesPriv.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkBlitter::~SkBlitter() {}
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitH(int x, int y, int width) {
278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(!"unimplemented");
288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
3182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                          const int16_t runs[]) {
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(!"unimplemented");
338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
3682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (alpha == 255) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(x, y, 1, height);
3882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    } else {
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int16_t runs[2];
408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[0] = 1;
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[1] = 0;
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        while (--height >= 0) {
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->blitAntiH(x, y++, &alpha, runs);
4582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitRect(int x, int y, int width, int height) {
5082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (--height >= 0) {
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitH(x, y++, width);
5282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline void bits_to_runs(SkBlitter* blitter, int x, int y,
5882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                const uint8_t bits[],
5982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                U8CPU left_mask, int rowBytes,
6082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                U8CPU right_mask) {
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int inFill = 0;
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int pos = 0;
638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (--rowBytes >= 0) {
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned b = *bits++ & left_mask;
6682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (rowBytes == 0) {
678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b &= right_mask;
6882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        for (unsigned test = 0x80; test != 0; test >>= 1) {
7182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (b & test) {
7282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (!inFill) {
738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    pos = x;
748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    inFill = true;
758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
7682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
7782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (inFill) {
788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    blitter->blitH(pos, y, x - pos);
798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    inFill = false;
808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += 1;
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        left_mask = 0xFF;
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // final cleanup
8882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (inFill) {
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        blitter->blitH(pos, y, x - pos);
9082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (mask.fFormat == SkMask::kBW_Format) {
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int cx = clip.fLeft;
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int cy = clip.fTop;
998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int maskLeft = mask.fBounds.fLeft;
1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int mask_rowBytes = mask.fRowBytes;
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = clip.height();
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t* bits = mask.getAddr1(cx, cy);
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
10582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
10682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            while (--height >= 0) {
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bits += mask_rowBytes;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                cy += 1;
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
11182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int left_edge = cx - maskLeft;
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(left_edge >= 0);
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rite_edge = clip.fRight - maskLeft;
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(rite_edge > left_edge);
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int left_mask = 0xFF >> (left_edge & 7);
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rite_mask = 0xFF << (8 - (rite_edge & 7));
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // check for empty right mask, so we don't read off the end (or go slower than we need to)
12282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (rite_mask == 0) {
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(full_runs >= 0);
1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                full_runs -= 1;
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite_mask = 0xFF;
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
12782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (left_mask == 0xFF) {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                full_runs -= 1;
12982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // back up manually so we can keep in sync with our byte-aligned src
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            // have cx reflect our actual starting x-coord
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            cx -= left_edge & 7;
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (full_runs < 0) {
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT((left_mask & rite_mask) != 0);
13782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                while (--height >= 0) {
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    bits += mask_rowBytes;
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    cy += 1;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
14282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
14382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                while (--height >= 0) {
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    bits += mask_rowBytes;
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    cy += 1;
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
15082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    } else {
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int                         width = clip.width();
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int16_t*                    runs = runStorage.get();
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*              aa = mask.getAddr(clip.fLeft, clip.fTop);
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset16((uint16_t*)runs, 1, width);
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[width] = 0;
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = clip.height();
1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int y = clip.fTop;
16182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        while (--height >= 0) {
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->blitAntiH(clip.fLeft, y, aa, runs);
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa += mask.fRowBytes;
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y += 1;
1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////// these guys are not virtual, just a helpers
1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (clip.quickReject(mask.fBounds)) {
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
17582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator clipper(clip, mask.fBounds);
17782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!clipper.done()) {
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitMask(mask, cr);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        clipper.next();
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator clipper(clip, rect);
18782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!clipper.done()) {
1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        clipper.next();
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRegion(const SkRegion& clip) {
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Iterator iter(clip);
19782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!iter.done()) {
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = iter.rect();
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitH(int x, int y, int width) {}
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
21082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                              const int16_t runs[]) {}
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitRect(int x, int y, int width, int height) {}
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic int compute_anti_width(const int16_t runs[]) {
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = 0;
22682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
22782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    for (;;) {
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
22982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
23182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (count == 0) {
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
23382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        width += count;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
23682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(width < 20000);
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return width;
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) {
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) {
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitH(int left, int y, int width) {
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(width > 0);
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!y_in_rect(y, fClipRect)) {
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
25582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int right = left + width;
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (left < fClipRect.fLeft) {
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        left = fClipRect.fLeft;
26182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
26282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (right > fClipRect.fRight) {
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        right = fClipRect.fRight;
26482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    width = right - left;
26782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (width > 0) {
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitH(left, y, width);
26982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
27382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                  const int16_t runs[]) {
27482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
27682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x0 = left;
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x1 = left + compute_anti_width(runs);
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x1 <= fClipRect.fLeft) {
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
28382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1);
28682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x0 < fClipRect.fLeft) {
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int dx = fClipRect.fLeft - x0;
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += dx;
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa += dx;
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x0 = fClipRect.fLeft;
2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
29582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x1 > fClipRect.fRight) {
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x1 = fClipRect.fRight;
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ((int16_t*)runs)[x1 - x0] = 0;
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(compute_anti_width(runs) == x1 - x0);
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlitter->blitAntiH(x0, y, aa, runs);
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(height > 0);
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!x_in_rect(x, fClipRect)) {
3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
31282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int y0 = y;
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int y1 = y + height;
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y0 < fClipRect.fTop) {
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y0 = fClipRect.fTop;
31982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
32082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y1 > fClipRect.fBottom) {
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y1 = fClipRect.fBottom;
32282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y0 < y1) {
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitV(x, y0, y1 - y0, alpha);
32682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    r;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, y, left + width, y + height);
33382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (r.intersect(fClipRect)) {
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
33582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    r = clip;
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (r.intersect(fClipRect)) {
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitMask(mask, r);
34582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fBlitter->justAnOpaqueColor(value);
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitH(int x, int y, int width) {
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int left, right;
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (span.next(&left, &right)) {
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right);
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitH(left, y, right - left);
3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
36482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
36582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                 const int16_t runs[]) {
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = compute_anti_width(runs);
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int left, right;
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
37082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int prevRite = x;
37282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (span.next(&left, &right)) {
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(x <= left);
3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right);
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
37682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // now zero before left
38082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (left > prevRite) {
3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int index = prevRite - x;
3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((uint8_t*)aa)[index] = 0;   // skip runs after right
3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((int16_t*)runs)[index] = SkToS16(left - prevRite);
3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
38582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevRite = right;
3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
38882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
38982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (prevRite > x) {
3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ((int16_t*)runs)[prevRite - x] = 0;
39182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (x < 0) {
3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int skip = runs[0];
3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(skip >= -x);
3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa += skip;
3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += skip;
3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += skip;
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitAntiH(x, y, aa, runs);
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    bounds;
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds.set(x, y, x + 1, y + height);
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& r = iter.rect();
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bounds.contains(r));
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitV(x, r.fTop, r.height(), alpha);
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    bounds;
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds.set(x, y, x + width, y + height);
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& r = iter.rect();
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bounds.contains(r));
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
43382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator iter(*fRgn, clip);
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkIRect&       r = iter.rect();
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBlitter*           blitter = fBlitter;
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
44082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        blitter->blitMask(mask, r);
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
44682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fBlitter->justAnOpaqueColor(value);
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
45382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                   const SkIRect* ir) {
45482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (clip) {
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& clipR = clip->getBounds();
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter = &fNullBlitter;
45982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else if (clip->isRect()) {
46082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (ir == NULL || !clipR.contains(*ir)) {
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRectBlitter.init(blitter, clipR);
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                blitter = &fRectBlitter;
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
46482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRgnBlitter.init(blitter, clip);
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter = &fRgnBlitter;
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorShader.h"
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DShader : public SkShader {
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
47982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    Sk3DShader(SkShader* proxy) : fProxy(proxy) {
48082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeRef(proxy);
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMask = NULL;
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
48382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
48482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual ~Sk3DShader() {
48582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fProxy);
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
48782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void setMask(const SkMask* mask) { fMask = mask; }
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
49182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                            const SkMatrix& matrix) {
49282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (fProxy) {
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return fProxy->setContext(device, paint, matrix);
49482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fPMColor = SkPreMultiplyColor(paint.getColor());
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return this->INHERITED::setContext(device, paint, matrix);
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
49982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
50082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void shadeSpan(int x, int y, SkPMColor span[], int count) {
50182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (fProxy) {
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->shadeSpan(x, y, span, count);
50382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (fMask == NULL) {
50682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (fProxy == NULL) {
5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                sk_memset32(span, fPMColor, count);
50882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            return;
5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fMask->fBounds.contains(x, y));
5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(fMask->fBounds.contains(x + count - 1, y));
5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        size_t          size = fMask->computeImageSize();
5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  alpha = fMask->getAddr(x, y);
5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  mulp = alpha + size;
5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t*  addp = mulp + size;
5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
52082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (fProxy) {
52182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            for (int i = 0; i < count; i++) {
52282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (alpha[i]) {
5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    SkPMColor c = span[i];
52482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                    if (c) {
5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned a = SkGetPackedA32(c);
5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned r = SkGetPackedR32(c);
5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned g = SkGetPackedG32(c);
5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned b = SkGetPackedB32(c);
5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned mul = SkAlpha255To256(mulp[i]);
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned add = addp[i];
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        span[i] = SkPackARGB32(a, r, g, b);
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
53982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                } else {
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    span[i] = 0;
54182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                }
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
54382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {    // color
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned a = SkGetPackedA32(fPMColor);
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned r = SkGetPackedR32(fPMColor);
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned g = SkGetPackedG32(fPMColor);
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            unsigned b = SkGetPackedB32(fPMColor);
54882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            for (int i = 0; i < count; i++) {
54982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (alpha[i]) {
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    unsigned mul = SkAlpha255To256(mulp[i]);
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    unsigned add = addp[i];
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    span[i] = SkPackARGB32( a,
55482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                    SkFastMin32(SkAlphaMul(r, mul) + add, a),
55582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                    SkFastMin32(SkAlphaMul(g, mul) + add, a),
55682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                    SkFastMin32(SkAlphaMul(b, mul) + add, a));
55782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                } else {
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    span[i] = 0;
55982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                }
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
56382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
56482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void beginSession() {
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::beginSession();
56682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (fProxy) {
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->beginSession();
56882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
57082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
57182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void endSession() {
57282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (fProxy) {
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->endSession();
57482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::endSession();
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sk3DShader(SkFlattenableReadBuffer& buffer) :
58082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            INHERITED(buffer) {
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy = static_cast<SkShader*>(buffer.readFlattenable());
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fPMColor = buffer.readU32();
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fMask = NULL;
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
58582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
58682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->INHERITED::flatten(buffer);
5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.writeFlattenable(fProxy);
5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.write32(fPMColor);
5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
59182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
59282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual Factory getFactory() {
5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return CreateProc;
5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
59782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return SkNEW_ARGS(Sk3DShader, (buffer));
5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*       fProxy;
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkPMColor       fPMColor;
6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkMask*   fMask;
6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkShader INHERITED;
6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DBlitter : public SkBlitter {
6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*))
61182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            : fProxy(proxy), f3DShader(shader), fKillProc(killProc) {
6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader->ref();
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
61482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
61582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual ~Sk3DBlitter() {
6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        f3DShader->unref();
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fKillProc(fProxy);
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void blitH(int x, int y, int width) {
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitH(x, y, width);
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
62382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
62482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
62582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                           const int16_t runs[]) {
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitAntiH(x, y, antialias, runs);
6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
62882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
62982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void blitV(int x, int y, int height, SkAlpha alpha) {
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitV(x, y, height, alpha);
6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
63282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
63382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void blitRect(int x, int y, int width, int height) {
6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitRect(x, y, width, height);
6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
63682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
63782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void blitMask(const SkMask& mask, const SkIRect& clip) {
63882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (mask.fFormat == SkMask::k3D_Format) {
6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            f3DShader->setMask(&mask);
6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->blitMask(mask, clip);
6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            f3DShader->setMask(NULL);
64682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->blitMask(mask, clip);
64882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
65082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBlitter*  fProxy;
6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sk3DShader* f3DShader;
6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void        (*fKillProc)(void*);
6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
65782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h"
6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoCallProc {
6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef void (*Proc)(void*);
66482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkAutoCallProc(void* obj, Proc proc)
66682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    : fObj(obj), fProc(proc) {}
66782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
66882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    ~SkAutoCallProc() {
66982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (fObj && fProc) {
6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProc(fObj);
67182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
67382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void* get() const { return fObj; }
67582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
67682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    void* detach() {
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        void* obj = fObj;
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fObj = NULL;
6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return obj;
6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
68182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    void*   fObj;
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Proc    fProc;
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
68782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic void destroy_blitter(void* blitter) {
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    ((SkBlitter*)blitter)->~SkBlitter();
6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
69182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic void delete_blitter(void* blitter) {
6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDELETE((SkBlitter*)blitter);
6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
695d252db03d9650013b545ef9781fe993c07f8f314reed@android.comstatic bool just_solid_color(const SkPaint& paint) {
696d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) {
697d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        SkShader* shader = paint.getShader();
698d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        if (NULL == shader ||
699d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) {
700d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            return true;
701d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        }
702d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
703d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    return false;
704d252db03d9650013b545ef9781fe993c07f8f314reed@android.com}
70582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
706d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/** By analyzing the paint (with an xfermode), we may decide we can take
707d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    special action. This enum lists our possible actions
708d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */
709d252db03d9650013b545ef9781fe993c07f8f314reed@android.comenum XferInterp {
710d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    kNormal_XferInterp,         // no special interpretation, draw normally
711d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    kSrcOver_XferInterp,        // draw as if in srcover mode
712d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    kSkipDrawing_XferInterp     // draw nothing
713d252db03d9650013b545ef9781fe993c07f8f314reed@android.com};
714d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
715d252db03d9650013b545ef9781fe993c07f8f314reed@android.comstatic XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer,
716d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                                     SkBitmap::Config deviceConfig) {
717845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    SkXfermode::Mode  mode;
71882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
719845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com    if (SkXfermode::IsMode(xfer, &mode)) {
720d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        switch (mode) {
721845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            case SkXfermode::kSrc_Mode:
722d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                if (just_solid_color(paint)) {
723d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                    return kSrcOver_XferInterp;
724d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                }
725d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
726845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            case SkXfermode::kDst_Mode:
727d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                return kSkipDrawing_XferInterp;
728845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            case SkXfermode::kSrcOver_Mode:
729d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                return kSrcOver_XferInterp;
730845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            case SkXfermode::kDstOver_Mode:
731d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                if (SkBitmap::kRGB_565_Config == deviceConfig) {
732d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                    return kSkipDrawing_XferInterp;
733d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                }
734d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
735845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            case SkXfermode::kSrcIn_Mode:
736d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                if (SkBitmap::kRGB_565_Config == deviceConfig &&
737d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                    just_solid_color(paint)) {
738d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                    return kSrcOver_XferInterp;
739d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                }
740d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
741845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com            case SkXfermode::kDstIn_Mode:
742d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                if (just_solid_color(paint)) {
743d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                    return kSkipDrawing_XferInterp;
744d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                }
745d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
746d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            default:
747d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
748d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        }
749d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
750d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    return kNormal_XferInterp;
751d252db03d9650013b545ef9781fe993c07f8f314reed@android.com}
752d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlitter* SkBlitter::Choose(const SkBitmap& device,
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkMatrix& matrix,
7556b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com                             const SkPaint& origPaint,
75682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                             void* storage, size_t storageSize) {
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(storageSize == 0 || storage != NULL);
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBlitter*  blitter = NULL;
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // which check, in case we're being called by a client with a dummy device
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // (e.g. they have a bounder that always aborts the draw)
76382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (SkBitmap::kNo_Config == device.getConfig()) {
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return blitter;
7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7686b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    SkPaint paint(origPaint);
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader* shader = paint.getShader();
7706b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    SkColorFilter* cf = paint.getColorFilter();
7716b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    SkXfermode* mode = paint.getXfermode();
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sk3DShader* shader3D = NULL;
77482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (paint.getMaskFilter() != NULL &&
77582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            paint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader3D = SkNEW_ARGS(Sk3DShader, (shader));
7776b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        paint.setShader(shader3D)->unref();
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader = shader3D;
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
781d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    if (NULL != mode) {
782d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        switch (interpret_xfermode(paint, mode, device.config())) {
783d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            case kSrcOver_XferInterp:
784d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                mode = NULL;
7856b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com                paint.setXfermode(NULL);
786d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
787d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            case kSkipDrawing_XferInterp:
788d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
789d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                return blitter;
790d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            default:
791d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
792d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        }
793d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
794d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
7956b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    if (NULL == shader) {
7966b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com#ifdef SK_IGNORE_CF_OPTIMIZATION
7976b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        if (mode || cf) {
7986b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com#else
7996b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        if (mode) {
8006b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com#endif
8016b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // xfermodes (and filters) require shaders for our current blitters
8026b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            shader = SkNEW(SkColorShader);
8036b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            paint.setShader(shader)->unref();
8046b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        } else if (cf) {
8056b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // if no shader && no xfermode, we just apply the colorfilter to
8066b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // our color and move on.
8076b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            paint.setColor(cf->filterColor(paint.getColor()));
8086b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            paint.setColorFilter(NULL);
8096b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            cf = NULL;
8106b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        }
8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
81282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
8136b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    if (cf) {
8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(shader);
8156b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        shader = SkNEW_ARGS(SkFilterShader, (shader, cf));
8166b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        paint.setShader(shader)->unref();
8171fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // blitters should ignore the presence/absence of a filter, since
8181fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // if there is one, the shader will take care of it.
8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
82082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
821cafc9f9e80e30fa75ad8a952e7a290e72f211ce7reed@android.com    if (shader && !shader->setContext(device, paint, matrix)) {
822cafc9f9e80e30fa75ad8a952e7a290e72f211ce7reed@android.com        return SkNEW(SkNullBlitter);
8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    switch (device.getConfig()) {
82682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        case SkBitmap::kA1_Config:
82782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SK_PLACEMENT_NEW_ARGS(blitter, SkA1_Blitter,
82882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                  storage, storageSize, (device, paint));
82982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
83082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
83182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        case SkBitmap::kA8_Config:
83282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (shader) {
83382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter,
83482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                      storage, storageSize, (device, paint));
83582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
83682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter,
83782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                      storage, storageSize, (device, paint));
83882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
83982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
84082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
84182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        case SkBitmap::kARGB_4444_Config:
84282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            blitter = SkBlitter_ChooseD4444(device, paint, storage, storageSize);
84382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
84482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
84582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        case SkBitmap::kRGB_565_Config:
84682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            blitter = SkBlitter_ChooseD565(device, paint, storage, storageSize);
84782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
84882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
84982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        case SkBitmap::kARGB_8888_Config:
85082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (shader) {
85182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter,
85282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                      storage, storageSize, (device, paint));
85382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else if (paint.getColor() == SK_ColorBLACK) {
85482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter,
85582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                      storage, storageSize, (device, paint));
85682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else if (paint.getAlpha() == 0xFF) {
85782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter,
85882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                      storage, storageSize, (device, paint));
85982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
86082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter,
86182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                      storage, storageSize, (device, paint));
86282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
86382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
86482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
86582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        default:
86682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SkASSERT(!"unsupported device config");
86782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize);
86882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
87182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (shader3D) {
8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter;
8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoCallProc  tmp(blitter, proc);
8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc));
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        (void)tmp.detach();
8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst uint16_t gMask_0F0F = 0xF0F;
8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst uint32_t gMask_00FF00FF = 0xFF00FF;
8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint)
8895119bdb952025a30f115b9c6a187173956e55097reed@android.com        : INHERITED(device) {
8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader = paint.getShader();
8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fShader);
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->ref();
8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->beginSession();
8955119bdb952025a30f115b9c6a187173956e55097reed@android.com    fShaderFlags = fShader->getFlags();
8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8985119bdb952025a30f115b9c6a187173956e55097reed@android.comSkShaderBlitter::~SkShaderBlitter() {
8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->endSession();
9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->unref();
9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
903