1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAntiRun.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColor.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
12a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkCoreBlitters.h"
1302f65f2d9168f2304a09d784dbcfeefb7669c8b4reed@google.com#include "SkFilterShader.h"
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
158b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMask.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
18a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkString.h"
19458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com#include "SkTLazy.h"
208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h"
22c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco#include "SkXfermodeInterpretation.h"
238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkBlitter::~SkBlitter() {}
258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26ea033606a06d05d2d42aa7118409fee798e53167reed@google.combool SkBlitter::isNullBlitter() const { return false; }
27ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
2880116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.orgbool SkBlitter::resetShaderContext(const SkShader::ContextRec&) {
2987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    return true;
3087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
3187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
3287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkShader::Context* SkBlitter::getShaderContext() const {
3387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    return NULL;
3487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
3587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
3682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitH(int x, int y, int width) {
410c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com    SkDEBUGFAIL("unimplemented");
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
4582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                          const int16_t runs[]) {
460c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com    SkDEBUGFAIL("unimplemented");
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
5082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (alpha == 255) {
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(x, y, 1, height);
5282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    } else {
538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int16_t runs[2];
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[0] = 1;
558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[1] = 0;
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        while (--height >= 0) {
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->blitAntiH(x, y++, &alpha, runs);
5982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitRect(int x, int y, int width, int height) {
64a31ac73b8e261f02c4bd6ae1d622c4bd00226b80tomhudson@google.com    SkASSERT(width > 0);
6582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (--height >= 0) {
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitH(x, y++, width);
6782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7049eac192faa35159752525b23345563252721c64tomhudson@google.com/// Default implementation doesn't check for any easy optimizations
7149eac192faa35159752525b23345563252721c64tomhudson@google.com/// such as alpha == 0 or 255; also uses blitV(), which some subclasses
7249eac192faa35159752525b23345563252721c64tomhudson@google.com/// may not support.
7349eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkBlitter::blitAntiRect(int x, int y, int width, int height,
7449eac192faa35159752525b23345563252721c64tomhudson@google.com                             SkAlpha leftAlpha, SkAlpha rightAlpha) {
754714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com    this->blitV(x++, y, height, leftAlpha);
76a31ac73b8e261f02c4bd6ae1d622c4bd00226b80tomhudson@google.com    if (width > 0) {
774714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com        this->blitRect(x, y, width, height);
784714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com        x += width;
794714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com    }
804714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com    this->blitV(x, y, height, rightAlpha);
8149eac192faa35159752525b23345563252721c64tomhudson@google.com}
8249eac192faa35159752525b23345563252721c64tomhudson@google.com
838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline void bits_to_runs(SkBlitter* blitter, int x, int y,
8682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                const uint8_t bits[],
8782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                U8CPU left_mask, int rowBytes,
8882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                U8CPU right_mask) {
898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int inFill = 0;
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int pos = 0;
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (--rowBytes >= 0) {
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        unsigned b = *bits++ & left_mask;
9482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (rowBytes == 0) {
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b &= right_mask;
9682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        for (unsigned test = 0x80; test != 0; test >>= 1) {
9982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (b & test) {
10082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (!inFill) {
1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    pos = x;
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    inFill = true;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
10482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
10582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (inFill) {
1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    blitter->blitH(pos, y, x - pos);
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    inFill = false;
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += 1;
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        left_mask = 0xFF;
1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // final cleanup
11682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (inFill) {
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        blitter->blitH(pos, y, x - pos);
11882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
12482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (mask.fFormat == SkMask::kBW_Format) {
1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int cx = clip.fLeft;
1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int cy = clip.fTop;
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int maskLeft = mask.fBounds.fLeft;
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int mask_rowBytes = mask.fRowBytes;
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = clip.height();
1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t* bits = mask.getAddr1(cx, cy);
1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
13382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
13482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            while (--height >= 0) {
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF);
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                bits += mask_rowBytes;
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                cy += 1;
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
13982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int left_edge = cx - maskLeft;
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(left_edge >= 0);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rite_edge = clip.fRight - maskLeft;
1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(rite_edge > left_edge);
1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int left_mask = 0xFF >> (left_edge & 7);
1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int rite_mask = 0xFF << (8 - (rite_edge & 7));
1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
149a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com            // check for empty right mask, so we don't read off the end (or go slower than we need to)
15082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (rite_mask == 0) {
1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT(full_runs >= 0);
1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                full_runs -= 1;
1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                rite_mask = 0xFF;
1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
15582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (left_mask == 0xFF) {
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                full_runs -= 1;
15782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
159a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com            // back up manually so we can keep in sync with our byte-aligned src
160a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com            // have cx reflect our actual starting x-coord
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            cx -= left_edge & 7;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
16382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (full_runs < 0) {
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                SkASSERT((left_mask & rite_mask) != 0);
16582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                while (--height >= 0) {
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask);
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    bits += mask_rowBytes;
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    cy += 1;
1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
17082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
17182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                while (--height >= 0) {
172a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com                    bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask);
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    bits += mask_rowBytes;
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    cy += 1;
1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
17882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    } else {
1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int                         width = clip.width();
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int16_t*                    runs = runStorage.get();
1827989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com        const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset16((uint16_t*)runs, 1, width);
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[width] = 0;
1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = clip.height();
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int y = clip.fTop;
18982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        while (--height >= 0) {
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->blitAntiH(clip.fLeft, y, aa, runs);
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa += mask.fRowBytes;
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y += 1;
1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////// these guys are not virtual, just a helpers
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (clip.quickReject(mask.fBounds)) {
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator clipper(clip, mask.fBounds);
20582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!clipper.done()) {
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitMask(mask, cr);
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        clipper.next();
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator clipper(clip, rect);
21582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!clipper.done()) {
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        clipper.next();
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRegion(const SkRegion& clip) {
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Iterator iter(clip);
22582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!iter.done()) {
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = iter.rect();
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitH(int x, int y, int width) {}
2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
23782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
23882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                              const int16_t runs[]) {}
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitRect(int x, int y, int width, int height) {}
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return NULL;
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
250ea033606a06d05d2d42aa7118409fee798e53167reed@google.combool SkNullBlitter::isNullBlitter() const { return true; }
251ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
25282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic int compute_anti_width(const int16_t runs[]) {
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = 0;
25682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
25782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    for (;;) {
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
25982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
26182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (count == 0) {
2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
26382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        width += count;
2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return width;
2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) {
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) {
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitH(int left, int y, int width) {
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(width > 0);
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!y_in_rect(y, fClipRect)) {
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
28382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int right = left + width;
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (left < fClipRect.fLeft) {
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        left = fClipRect.fLeft;
28982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
29082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (right > fClipRect.fRight) {
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        right = fClipRect.fRight;
29282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    width = right - left;
29582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (width > 0) {
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitH(left, y, width);
29782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
30182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                  const int16_t runs[]) {
30282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
30482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x0 = left;
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x1 = left + compute_anti_width(runs);
3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x1 <= fClipRect.fLeft) {
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
31182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1);
31482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x0 < fClipRect.fLeft) {
3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int dx = fClipRect.fLeft - x0;
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += dx;
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa += dx;
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x0 = fClipRect.fLeft;
3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
32382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x1 > fClipRect.fRight) {
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x1 = fClipRect.fRight;
3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ((int16_t*)runs)[x1 - x0] = 0;
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(compute_anti_width(runs) == x1 - x0);
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlitter->blitAntiH(x0, y, aa, runs);
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(height > 0);
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
33882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!x_in_rect(x, fClipRect)) {
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
34082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int y0 = y;
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int y1 = y + height;
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y0 < fClipRect.fTop) {
3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y0 = fClipRect.fTop;
34782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
34882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y1 > fClipRect.fBottom) {
3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y1 = fClipRect.fBottom;
35082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y0 < y1) {
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitV(x, y0, y1 - y0, alpha);
35482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    r;
3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, y, left + width, y + height);
36182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (r.intersect(fClipRect)) {
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
36382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
36649eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
36749eac192faa35159752525b23345563252721c64tomhudson@google.com                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
36849eac192faa35159752525b23345563252721c64tomhudson@google.com    SkIRect    r;
36949eac192faa35159752525b23345563252721c64tomhudson@google.com
37049eac192faa35159752525b23345563252721c64tomhudson@google.com    // The *true* width of the rectangle blitted is width+2:
37149eac192faa35159752525b23345563252721c64tomhudson@google.com    r.set(left, y, left + width + 2, y + height);
37249eac192faa35159752525b23345563252721c64tomhudson@google.com    if (r.intersect(fClipRect)) {
37349eac192faa35159752525b23345563252721c64tomhudson@google.com        if (r.fLeft != left) {
37449eac192faa35159752525b23345563252721c64tomhudson@google.com            SkASSERT(r.fLeft > left);
37549eac192faa35159752525b23345563252721c64tomhudson@google.com            leftAlpha = 255;
37649eac192faa35159752525b23345563252721c64tomhudson@google.com        }
37749eac192faa35159752525b23345563252721c64tomhudson@google.com        if (r.fRight != left + width + 2) {
37849eac192faa35159752525b23345563252721c64tomhudson@google.com            SkASSERT(r.fRight < left + width + 2);
37949eac192faa35159752525b23345563252721c64tomhudson@google.com            rightAlpha = 255;
38049eac192faa35159752525b23345563252721c64tomhudson@google.com        }
38149eac192faa35159752525b23345563252721c64tomhudson@google.com        if (255 == leftAlpha && 255 == rightAlpha) {
38249eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
38349eac192faa35159752525b23345563252721c64tomhudson@google.com        } else if (1 == r.width()) {
38449eac192faa35159752525b23345563252721c64tomhudson@google.com            if (r.fLeft == left) {
38549eac192faa35159752525b23345563252721c64tomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
38649eac192faa35159752525b23345563252721c64tomhudson@google.com            } else {
38749eac192faa35159752525b23345563252721c64tomhudson@google.com                SkASSERT(r.fLeft == left + width + 1);
38849eac192faa35159752525b23345563252721c64tomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
38949eac192faa35159752525b23345563252721c64tomhudson@google.com            }
39049eac192faa35159752525b23345563252721c64tomhudson@google.com        } else {
39149eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
39249eac192faa35159752525b23345563252721c64tomhudson@google.com                                   leftAlpha, rightAlpha);
39349eac192faa35159752525b23345563252721c64tomhudson@google.com        }
39449eac192faa35159752525b23345563252721c64tomhudson@google.com    }
39549eac192faa35159752525b23345563252721c64tomhudson@google.com}
39649eac192faa35159752525b23345563252721c64tomhudson@google.com
39782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    r = clip;
4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (r.intersect(fClipRect)) {
4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitMask(mask, r);
40482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
40782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fBlitter->justAnOpaqueColor(value);
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitH(int x, int y, int width) {
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int left, right;
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (span.next(&left, &right)) {
4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right);
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitH(left, y, right - left);
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
42482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                 const int16_t runs[]) {
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = compute_anti_width(runs);
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int left, right;
4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
42982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int prevRite = x;
43182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (span.next(&left, &right)) {
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(x <= left);
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right);
4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
43582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // now zero before left
43982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (left > prevRite) {
4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int index = prevRite - x;
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((uint8_t*)aa)[index] = 0;   // skip runs after right
4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((int16_t*)runs)[index] = SkToS16(left - prevRite);
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
44482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevRite = right;
4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
44782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
44882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (prevRite > x) {
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ((int16_t*)runs)[prevRite - x] = 0;
45082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (x < 0) {
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int skip = runs[0];
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(skip >= -x);
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa += skip;
4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += skip;
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += skip;
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitAntiH(x, y, aa, runs);
4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
46282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    bounds;
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds.set(x, y, x + 1, y + height);
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
46882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& r = iter.rect();
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bounds.contains(r));
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitV(x, r.fTop, r.height(), alpha);
4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    bounds;
4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds.set(x, y, x + width, y + height);
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
48382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& r = iter.rect();
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bounds.contains(r));
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49249eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
49349eac192faa35159752525b23345563252721c64tomhudson@google.com                                    SkAlpha leftAlpha, SkAlpha rightAlpha) {
49449eac192faa35159752525b23345563252721c64tomhudson@google.com    // The *true* width of the rectangle to blit is width + 2
49549eac192faa35159752525b23345563252721c64tomhudson@google.com    SkIRect    bounds;
49649eac192faa35159752525b23345563252721c64tomhudson@google.com    bounds.set(x, y, x + width + 2, y + height);
49749eac192faa35159752525b23345563252721c64tomhudson@google.com
49849eac192faa35159752525b23345563252721c64tomhudson@google.com    SkRegion::Cliperator    iter(*fRgn, bounds);
49949eac192faa35159752525b23345563252721c64tomhudson@google.com
50049eac192faa35159752525b23345563252721c64tomhudson@google.com    while (!iter.done()) {
50149eac192faa35159752525b23345563252721c64tomhudson@google.com        const SkIRect& r = iter.rect();
50249eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(bounds.contains(r));
50349eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(r.fLeft >= x);
50431bab3934c773c2bd4c1e5e9ba8eb87c1c623b09tomhudson@google.com        SkASSERT(r.fRight <= x + width + 2);
50549eac192faa35159752525b23345563252721c64tomhudson@google.com
50649eac192faa35159752525b23345563252721c64tomhudson@google.com        SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
50749eac192faa35159752525b23345563252721c64tomhudson@google.com        SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
50849eac192faa35159752525b23345563252721c64tomhudson@google.com                                      rightAlpha : 255;
50949eac192faa35159752525b23345563252721c64tomhudson@google.com
51049eac192faa35159752525b23345563252721c64tomhudson@google.com        if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
51149eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
51249eac192faa35159752525b23345563252721c64tomhudson@google.com        } else if (1 == r.width()) {
51349eac192faa35159752525b23345563252721c64tomhudson@google.com            if (r.fLeft == x) {
514fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
51549eac192faa35159752525b23345563252721c64tomhudson@google.com                                effectiveLeftAlpha);
51649eac192faa35159752525b23345563252721c64tomhudson@google.com            } else {
51749eac192faa35159752525b23345563252721c64tomhudson@google.com                SkASSERT(r.fLeft == x + width + 1);
51849eac192faa35159752525b23345563252721c64tomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
51949eac192faa35159752525b23345563252721c64tomhudson@google.com                                effectiveRightAlpha);
52049eac192faa35159752525b23345563252721c64tomhudson@google.com            }
52149eac192faa35159752525b23345563252721c64tomhudson@google.com        } else {
52249eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
52349eac192faa35159752525b23345563252721c64tomhudson@google.com                                   effectiveLeftAlpha, effectiveRightAlpha);
52449eac192faa35159752525b23345563252721c64tomhudson@google.com        }
52549eac192faa35159752525b23345563252721c64tomhudson@google.com        iter.next();
52649eac192faa35159752525b23345563252721c64tomhudson@google.com    }
52749eac192faa35159752525b23345563252721c64tomhudson@google.com}
52849eac192faa35159752525b23345563252721c64tomhudson@google.com
52949eac192faa35159752525b23345563252721c64tomhudson@google.com
53082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator iter(*fRgn, clip);
5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkIRect&       r = iter.rect();
5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBlitter*           blitter = fBlitter;
5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
53782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        blitter->blitMask(mask, r);
5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fBlitter->justAnOpaqueColor(value);
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
55082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                   const SkIRect* ir) {
55182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (clip) {
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& clipR = clip->getBounds();
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter = &fNullBlitter;
55682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else if (clip->isRect()) {
55782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (ir == NULL || !clipR.contains(*ir)) {
5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRectBlitter.init(blitter, clipR);
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                blitter = &fRectBlitter;
5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
56182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRgnBlitter.init(blitter, clip);
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter = &fRgnBlitter;
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorShader.h"
5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DShader : public SkShader {
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
57682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    Sk3DShader(SkShader* proxy) : fProxy(proxy) {
57782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeRef(proxy);
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
57982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
58082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual ~Sk3DShader() {
58182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        SkSafeUnref(fProxy);
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
58382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
58436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    size_t contextSize() const override {
58587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        size_t size = sizeof(Sk3DShaderContext);
58687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        if (fProxy) {
58787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            size += fProxy->contextSize();
58887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        }
58987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        return size;
59087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    }
5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
59236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    Context* onCreateContext(const ContextRec& rec, void* storage) const override {
593ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        SkShader::Context* proxyContext = NULL;
594a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com        if (fProxy) {
59587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext);
596e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org            proxyContext = fProxy->createContext(rec, proxyContextStorage);
597ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org            if (!proxyContext) {
598ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org                return NULL;
599ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org            }
600a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com        }
601e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, rec, proxyContext));
6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
60382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
60487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    class Sk3DShaderContext : public SkShader::Context {
60587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    public:
60687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        // Calls proxyContext's destructor but will NOT free its memory.
607e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec,
608e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org                          SkShader::Context* proxyContext)
609e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org            : INHERITED(shader, rec)
61087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            , fMask(NULL)
61187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            , fProxyContext(proxyContext)
61287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        {
61387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (!fProxyContext) {
614e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org                fPMColor = SkPreMultiplyColor(rec.fPaint->getColor());
61587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            }
61682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
61887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        virtual ~Sk3DShaderContext() {
61987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (fProxyContext) {
62087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                fProxyContext->~Context();
62182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        void set3DMask(const SkMask* mask) override { fMask = mask; }
6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        void shadeSpan(int x, int y, SkPMColor span[], int count) override {
62787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (fProxyContext) {
62887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                fProxyContext->shadeSpan(x, y, span, count);
62987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            }
6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
63187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (fMask == NULL) {
63287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                if (fProxyContext == NULL) {
63387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    sk_memset32(span, fPMColor, count);
63487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                }
63587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                return;
63687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            }
6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
63887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            SkASSERT(fMask->fBounds.contains(x, y));
63987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            SkASSERT(fMask->fBounds.contains(x + count - 1, y));
64087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
64187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            size_t          size = fMask->computeImageSize();
64287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            const uint8_t*  alpha = fMask->getAddr8(x, y);
64387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            const uint8_t*  mulp = alpha + size;
64487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            const uint8_t*  addp = mulp + size;
64587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
64687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (fProxyContext) {
64787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                for (int i = 0; i < count; i++) {
64887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    if (alpha[i]) {
64987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        SkPMColor c = span[i];
65087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        if (c) {
65187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned a = SkGetPackedA32(c);
65287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned r = SkGetPackedR32(c);
65387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned g = SkGetPackedG32(c);
65487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned b = SkGetPackedB32(c);
65587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
65687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned mul = SkAlpha255To256(mulp[i]);
65787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned add = addp[i];
65887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
65987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
66087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
66187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
66287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
66387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            span[i] = SkPackARGB32(a, r, g, b);
66487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        }
66587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    } else {
66687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        span[i] = 0;
66787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    }
66887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                }
66987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            } else {    // color
67087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned a = SkGetPackedA32(fPMColor);
67187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned r = SkGetPackedR32(fPMColor);
67287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned g = SkGetPackedG32(fPMColor);
67387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned b = SkGetPackedB32(fPMColor);
67487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                for (int i = 0; i < count; i++) {
67587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    if (alpha[i]) {
6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned mul = SkAlpha255To256(mulp[i]);
6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned add = addp[i];
6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        span[i] = SkPackARGB32( a,
68087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                        SkFastMin32(SkAlphaMul(r, mul) + add, a),
68187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                        SkFastMin32(SkAlphaMul(g, mul) + add, a),
68287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                        SkFastMin32(SkAlphaMul(b, mul) + add, a));
68387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    } else {
68487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        span[i] = 0;
6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
68682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                }
6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
68987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
69087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    private:
69187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        // Unowned.
69287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        const SkMask*       fMask;
69387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        // Memory is unowned, but we need to call the destructor.
69487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkShader::Context*  fProxyContext;
69587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkPMColor           fPMColor;
69687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
69787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        typedef SkShader::Context INHERITED;
69887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    };
69982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
7000f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
70136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void toString(SkString* str) const override {
70276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append("Sk3DShader: (");
70376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
70449f085dddff10473b6ebf832a974288300224e60bsalomon        if (fProxy) {
70576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            str->append("Proxy: ");
70676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            fProxy->toString(str);
70776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        }
70876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
70976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        this->INHERITED::toString(str);
71076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
71176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append(")");
71276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
71376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif
71476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
715ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
716ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com
7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
71836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buffer) const override {
7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        buffer.writeFlattenable(fProxy);
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
72182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkShader*       fProxy;
7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkShader INHERITED;
7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* Sk3DShader::CreateProc(SkReadBuffer& buffer) {
7299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkAutoTUnref<SkShader> shader(buffer.readShader());
7309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    return SkNEW_ARGS(Sk3DShader, (shader));
7319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
7329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DBlitter : public SkBlitter {
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
735cc0e3110bde60201882a2c512a5cdd73c838f351reed    Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext)
736a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        : fProxy(proxy)
737cc0e3110bde60201882a2c512a5cdd73c838f351reed        , fShaderContext(shaderContext)
738a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org    {}
7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
74036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override {
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitH(x, y, width);
7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
74382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
74482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    virtual void blitAntiH(int x, int y, const SkAlpha antialias[],
74536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein                           const int16_t runs[]) override {
7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitAntiH(x, y, antialias, runs);
7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
74882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
74936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitV(int x, int y, int height, SkAlpha alpha) override {
7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitV(x, y, height, alpha);
7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
75282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
75336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override {
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitRect(x, y, width, height);
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
75682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
75736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitMask(const SkMask& mask, const SkIRect& clip) override {
75882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (mask.fFormat == SkMask::k3D_Format) {
759cc0e3110bde60201882a2c512a5cdd73c838f351reed            fShaderContext->set3DMask(&mask);
7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->blitMask(mask, clip);
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
765cc0e3110bde60201882a2c512a5cdd73c838f351reed            fShaderContext->set3DMask(NULL);
76682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->blitMask(mask, clip);
76882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
77082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
77287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // Both pointers are unowned. They will be deleted by SkSmallAllocator.
773cc0e3110bde60201882a2c512a5cdd73c838f351reed    SkBlitter*          fProxy;
774cc0e3110bde60201882a2c512a5cdd73c838f351reed    SkShader::Context*  fShaderContext;
7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
77782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h"
7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlitter* SkBlitter::Choose(const SkBitmap& device,
7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkMatrix& matrix,
7836b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com                             const SkPaint& origPaint,
784a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                             SkTBlitterAllocator* allocator,
785126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com                             bool drawCoverage) {
786a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org    SkASSERT(allocator != NULL);
7878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // which check, in case we're being called by a client with a dummy device
7898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // (e.g. they have a bounder that always aborts the draw)
790900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    if (kUnknown_SkColorType == device.colorType() ||
791900ecf2f1579d42c9d2959831787af0346320f86reed@google.com            (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
792b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        return allocator->createT<SkNullBlitter>();
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
795458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com    SkShader* shader = origPaint.getShader();
796458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com    SkColorFilter* cf = origPaint.getColorFilter();
797458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com    SkXfermode* mode = origPaint.getXfermode();
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    Sk3DShader* shader3D = NULL;
799458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com
8005dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
801fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
802458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com    if (origPaint.getMaskFilter() != NULL &&
803458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com            origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader3D = SkNEW_ARGS(Sk3DShader, (shader));
805458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com        // we know we haven't initialized lazyPaint yet, so just do it
8065dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com        paint.writable()->setShader(shader3D)->unref();
8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        shader = shader3D;
8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
81049f085dddff10473b6ebf832a974288300224e60bsalomon    if (mode) {
811c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco        bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType();
812c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco        switch (SkInterpretXfermode(*paint, deviceIsOpaque)) {
813c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco            case kSrcOver_SkXfermodeInterpretation:
814d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                mode = NULL;
8155dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com                paint.writable()->setXfermode(NULL);
816d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
817c375b0b5c5c03d381111bf7bff12507d5ed24769senorblanco            case kSkipDrawing_SkXfermodeInterpretation:{
818b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return allocator->createT<SkNullBlitter>();
819a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            }
820d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            default:
821d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
822d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        }
823d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
824d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
82513201e74f43b9c5fa173339eb36de515370e6973reed@google.com    /*
82613201e74f43b9c5fa173339eb36de515370e6973reed@google.com     *  If the xfermode is CLEAR, then we can completely ignore the installed
82713201e74f43b9c5fa173339eb36de515370e6973reed@google.com     *  color/shader/colorfilter, and just pretend we're SRC + color==0. This
82813201e74f43b9c5fa173339eb36de515370e6973reed@google.com     *  will fall into our optimizations for SRC mode.
82913201e74f43b9c5fa173339eb36de515370e6973reed@google.com     */
83013201e74f43b9c5fa173339eb36de515370e6973reed@google.com    if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) {
83113201e74f43b9c5fa173339eb36de515370e6973reed@google.com        SkPaint* p = paint.writable();
83213201e74f43b9c5fa173339eb36de515370e6973reed@google.com        shader = p->setShader(NULL);
83313201e74f43b9c5fa173339eb36de515370e6973reed@google.com        cf = p->setColorFilter(NULL);
83413201e74f43b9c5fa173339eb36de515370e6973reed@google.com        mode = p->setXfermodeMode(SkXfermode::kSrc_Mode);
83513201e74f43b9c5fa173339eb36de515370e6973reed@google.com        p->setColor(0);
83613201e74f43b9c5fa173339eb36de515370e6973reed@google.com    }
83713201e74f43b9c5fa173339eb36de515370e6973reed@google.com
8386b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    if (NULL == shader) {
8396b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        if (mode) {
8406b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // xfermodes (and filters) require shaders for our current blitters
84176a3b2abd02841c4ae786ac4cf59c3a51c545f73commit-bot@chromium.org            shader = SkNEW_ARGS(SkColorShader, (paint->getColor()));
8425dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com            paint.writable()->setShader(shader)->unref();
84376a3b2abd02841c4ae786ac4cf59c3a51c545f73commit-bot@chromium.org            paint.writable()->setAlpha(0xFF);
8446b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        } else if (cf) {
8456b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // if no shader && no xfermode, we just apply the colorfilter to
8466b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // our color and move on.
8475dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com            SkPaint* writablePaint = paint.writable();
8485dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com            writablePaint->setColor(cf->filterColor(paint->getColor()));
8495dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com            writablePaint->setColorFilter(NULL);
8506b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            cf = NULL;
8516b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        }
8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
85382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
8546b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    if (cf) {
8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(shader);
8566b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        shader = SkNEW_ARGS(SkFilterShader, (shader, cf));
8575dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com        paint.writable()->setShader(shader)->unref();
8581fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // blitters should ignore the presence/absence of a filter, since
8591fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // if there is one, the shader will take care of it.
8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
86182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
862a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com    /*
86387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org     *  We create a SkShader::Context object, and store it on the blitter.
864a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com     */
865b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    SkShader::Context* shaderContext = NULL;
86687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    if (shader) {
867e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        SkShader::ContextRec rec(device, *paint, matrix);
868b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        size_t contextSize = shader->contextSize();
869b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        if (contextSize) {
870b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            // Try to create the ShaderContext
871b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            void* storage = allocator->reserveT<SkShader::Context>(contextSize);
872b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            shaderContext = shader->createContext(rec, storage);
873b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            if (!shaderContext) {
874b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                allocator->freeLast();
875b0ae649b7ebda86ef53bf913798b809d500973edbsalomon                return allocator->createT<SkNullBlitter>();
876b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            }
877b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            SkASSERT(shaderContext);
878b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            SkASSERT((void*) shaderContext == storage);
879b0ae649b7ebda86ef53bf913798b809d500973edbsalomon        } else {
880b0ae649b7ebda86ef53bf913798b809d500973edbsalomon            return allocator->createT<SkNullBlitter>();
88187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        }
8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
884b0ae649b7ebda86ef53bf913798b809d500973edbsalomon    SkBlitter*  blitter = NULL;
885900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    switch (device.colorType()) {
886900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        case kAlpha_8_SkColorType:
887126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com            if (drawCoverage) {
888126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com                SkASSERT(NULL == shader);
889126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com                SkASSERT(NULL == paint->getXfermode());
890a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint);
891126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com            } else if (shader) {
89287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext);
89382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
894a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<SkA8_Blitter>(device, *paint);
89582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
89682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
89782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
898900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        case kRGB_565_SkColorType:
89987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator);
90082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
90182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
90228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
90382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (shader) {
90487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                blitter = allocator->createT<SkARGB32_Shader_Blitter>(
90587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        device, *paint, shaderContext);
906458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com            } else if (paint->getColor() == SK_ColorBLACK) {
907a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
908458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com            } else if (paint->getAlpha() == 0xFF) {
909a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint);
91082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
911a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org                blitter = allocator->createT<SkARGB32_Blitter>(device, *paint);
91282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
91382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
91482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
91582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        default:
9160c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com            SkDEBUGFAIL("unsupported device config");
917a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            blitter = allocator->createT<SkNullBlitter>();
91882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
92182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (shader3D) {
922a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        SkBlitter* innerBlitter = blitter;
923a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        // innerBlitter was allocated by allocator, which will delete it.
924cc0e3110bde60201882a2c512a5cdd73c838f351reed        // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to
925cc0e3110bde60201882a2c512a5cdd73c838f351reed        // wrapper the blitter to notify it when we see an emboss mask.
926cc0e3110bde60201882a2c512a5cdd73c838f351reed        blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext);
9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
93182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
933ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgclass SkTransparentShaderContext : public SkShader::Context {
934ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgpublic:
935ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    SkTransparentShaderContext(const SkShader& shader, const SkShader::ContextRec& rec)
936ca76c55d60dfe041e30e210d41fa0feb7fb54a1fscroggo        // Override rec with the identity matrix, so it is guaranteed to be invertible.
937ca76c55d60dfe041e30e210d41fa0feb7fb54a1fscroggo        : INHERITED(shader, SkShader::ContextRec(*rec.fDevice, *rec.fPaint, SkMatrix::I())) {}
938ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org
93936352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void shadeSpan(int x, int y, SkPMColor colors[], int count) override {
940ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        sk_bzero(colors, count * sizeof(SkPMColor));
941ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    }
942ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org
943ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgprivate:
944ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    typedef SkShader::Context INHERITED;
945ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org};
946ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org
94787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint,
94887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                 SkShader::Context* shaderContext)
94987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        : INHERITED(device)
95087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        , fShader(paint.getShader())
95187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        , fShaderContext(shaderContext) {
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fShader);
95387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkASSERT(fShaderContext);
9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->ref();
95687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderFlags = fShaderContext->getFlags();
9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9595119bdb952025a30f115b9c6a187173956e55097reed@android.comSkShaderBlitter::~SkShaderBlitter() {
9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->unref();
9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
96287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
96380116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.orgbool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) {
96487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // Only destroy the old context if we have a new one. We need to ensure to have a
96587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // live context in fShaderContext because the storage is owned by an SkSmallAllocator
96687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // outside of this class.
96787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // The new context will be of the same size as the old one because we use the same
96887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // shader to create it. It is therefore safe to re-use the storage.
96987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderContext->~Context();
970ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext);
971ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    if (NULL == ctx) {
972ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        // Need a valid context in fShaderContext's storage, so we can later (or our caller) call
973ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        // the in-place destructor.
974ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec));
97580116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org        return false;
976ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    }
97780116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org    return true;
97887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org}
979