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
883e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby#include "SkArenaAlloc.h"
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h"
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAntiRun.h"
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColor.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h"
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMask.h"
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h"
17a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkString.h"
18458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com#include "SkTLazy.h"
198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h"
20a681433d42323d6d48e1aa3cb2ef97fb9d958d93halcanary#include "SkXfermodeInterpretation.h"
218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
22395eabeb0e72334c45324874c6e009b54634df21reed// define this for testing srgb blits
23a34be68a7eff0ae475b194f8a29975460cf3e456reed//#define SK_FORCE_PM4f_FOR_L32_BLITS
24395eabeb0e72334c45324874c6e009b54634df21reed
25845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkBlitter::~SkBlitter() {}
268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
27ea033606a06d05d2d42aa7118409fee798e53167reed@google.combool SkBlitter::isNullBlitter() const { return false; }
28ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
2941e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
3096fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
337df9e4a87d84415391c167ea54cd389d4b423c2dherb/*
3482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitH(int x, int y, int width) {
350c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com    SkDEBUGFAIL("unimplemented");
368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
387df9e4a87d84415391c167ea54cd389d4b423c2dherb
3982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
4082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                          const int16_t runs[]) {
410c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com    SkDEBUGFAIL("unimplemented");
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
437df9e4a87d84415391c167ea54cd389d4b423c2dherb */
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
4682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (alpha == 255) {
478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(x, y, 1, height);
4882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    } else {
498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int16_t runs[2];
508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[0] = 1;
518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[1] = 0;
528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        while (--height >= 0) {
548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->blitAntiH(x, y++, &alpha, runs);
5582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitRect(int x, int y, int width, int height) {
60a31ac73b8e261f02c4bd6ae1d622c4bd00226b80tomhudson@google.com    SkASSERT(width > 0);
6182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (--height >= 0) {
628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitH(x, y++, width);
6382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
6638911a7cb53474575e1cd1cb545902b50ee00889liyuqian/// Default implementation doesn't check for easy optimizations
6738911a7cb53474575e1cd1cb545902b50ee00889liyuqian/// such as alpha == 255; also uses blitV(), which some subclasses
6849eac192faa35159752525b23345563252721c64tomhudson@google.com/// may not support.
6949eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkBlitter::blitAntiRect(int x, int y, int width, int height,
7049eac192faa35159752525b23345563252721c64tomhudson@google.com                             SkAlpha leftAlpha, SkAlpha rightAlpha) {
7138911a7cb53474575e1cd1cb545902b50ee00889liyuqian    if (leftAlpha > 0) { // we may send in x = -1 with leftAlpha = 0
7238911a7cb53474575e1cd1cb545902b50ee00889liyuqian        this->blitV(x, y, height, leftAlpha);
7338911a7cb53474575e1cd1cb545902b50ee00889liyuqian    }
7438911a7cb53474575e1cd1cb545902b50ee00889liyuqian    x++;
75a31ac73b8e261f02c4bd6ae1d622c4bd00226b80tomhudson@google.com    if (width > 0) {
764714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com        this->blitRect(x, y, width, height);
774714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com        x += width;
784714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com    }
7938911a7cb53474575e1cd1cb545902b50ee00889liyuqian    if (rightAlpha > 0) {
8038911a7cb53474575e1cd1cb545902b50ee00889liyuqian        this->blitV(x, y, height, rightAlpha);
8138911a7cb53474575e1cd1cb545902b50ee00889liyuqian    }
8249eac192faa35159752525b23345563252721c64tomhudson@google.com}
8349eac192faa35159752525b23345563252721c64tomhudson@google.com
848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
8682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline void bits_to_runs(SkBlitter* blitter, int x, int y,
8782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                const uint8_t bits[],
885520dede2968372e79c572e37b7f325524ee0739herb                                uint8_t left_mask, ptrdiff_t rowBytes,
895520dede2968372e79c572e37b7f325524ee0739herb                                uint8_t right_mask) {
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int inFill = 0;
918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int pos = 0;
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (--rowBytes >= 0) {
945520dede2968372e79c572e37b7f325524ee0739herb        uint8_t b = *bits++ & left_mask;
9582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (rowBytes == 0) {
968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            b &= right_mask;
9782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
995520dede2968372e79c572e37b7f325524ee0739herb        for (uint8_t test = 0x80U; test != 0; test >>= 1) {
10082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            if (b & test) {
10182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (!inFill) {
1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    pos = x;
1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    inFill = true;
1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
10582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
10682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                if (inFill) {
1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    blitter->blitH(pos, y, x - pos);
1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    inFill = false;
1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                }
1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += 1;
1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1135520dede2968372e79c572e37b7f325524ee0739herb        left_mask = 0xFFU;
1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // final cleanup
11782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (inFill) {
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        blitter->blitH(pos, y, x - pos);
11982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1225520dede2968372e79c572e37b7f325524ee0739herb// maskBitCount is the number of 1's to place in the mask. It must be in the range between 1 and 8.
1235520dede2968372e79c572e37b7f325524ee0739herbstatic uint8_t generate_right_mask(int maskBitCount) {
1245520dede2968372e79c572e37b7f325524ee0739herb    return static_cast<uint8_t>(0xFF00U >> maskBitCount);
1255520dede2968372e79c572e37b7f325524ee0739herb}
1265520dede2968372e79c572e37b7f325524ee0739herb
12782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
130d96e7e503fd24825a6717d58e90a97f95e8ebbc6reed    if (mask.fFormat == SkMask::kLCD16_Format) {
131d96e7e503fd24825a6717d58e90a97f95e8ebbc6reed        return; // needs to be handled by subclass
132d96e7e503fd24825a6717d58e90a97f95e8ebbc6reed    }
133d96e7e503fd24825a6717d58e90a97f95e8ebbc6reed
13482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (mask.fFormat == SkMask::kBW_Format) {
1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int cx = clip.fLeft;
1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int cy = clip.fTop;
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int maskLeft = mask.fBounds.fLeft;
1385520dede2968372e79c572e37b7f325524ee0739herb        int maskRowBytes = mask.fRowBytes;
1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = clip.height();
1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const uint8_t* bits = mask.getAddr1(cx, cy);
1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1435520dede2968372e79c572e37b7f325524ee0739herb        SkDEBUGCODE(const uint8_t* endOfImage =
1445520dede2968372e79c572e37b7f325524ee0739herb            mask.fImage + (mask.fBounds.height() - 1) * maskRowBytes
1455520dede2968372e79c572e37b7f325524ee0739herb            + ((mask.fBounds.width() + 7) >> 3));
1465520dede2968372e79c572e37b7f325524ee0739herb
14782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) {
14882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            while (--height >= 0) {
1495520dede2968372e79c572e37b7f325524ee0739herb                int affectedRightBit = mask.fBounds.width() - 1;
1505520dede2968372e79c572e37b7f325524ee0739herb                ptrdiff_t rowBytes = (affectedRightBit >> 3) + 1;
1515520dede2968372e79c572e37b7f325524ee0739herb                SkASSERT(bits + rowBytes <= endOfImage);
1525520dede2968372e79c572e37b7f325524ee0739herb                U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
1535520dede2968372e79c572e37b7f325524ee0739herb                bits_to_runs(this, cx, cy, bits, 0xFF, rowBytes, rightMask);
1545520dede2968372e79c572e37b7f325524ee0739herb                bits += maskRowBytes;
1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                cy += 1;
1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
15782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
1583be72b0413ebc7cb1133e704169e3d543830d8e7herb            // Bits is calculated as the offset into the mask at the point {cx, cy} therefore, all
1595520dede2968372e79c572e37b7f325524ee0739herb            // addressing into the bit mask is relative to that point. Since this is an address
1605520dede2968372e79c572e37b7f325524ee0739herb            // calculated from a arbitrary bit in that byte, calculate the left most bit.
1615520dede2968372e79c572e37b7f325524ee0739herb            int bitsLeft = cx - ((cx - maskLeft) & 7);
1625520dede2968372e79c572e37b7f325524ee0739herb
1635520dede2968372e79c572e37b7f325524ee0739herb            // Everything is relative to the bitsLeft.
1645520dede2968372e79c572e37b7f325524ee0739herb            int leftEdge = cx - bitsLeft;
1655520dede2968372e79c572e37b7f325524ee0739herb            SkASSERT(leftEdge >= 0);
1665520dede2968372e79c572e37b7f325524ee0739herb            int rightEdge = clip.fRight - bitsLeft;
1675520dede2968372e79c572e37b7f325524ee0739herb            SkASSERT(rightEdge > leftEdge);
1685520dede2968372e79c572e37b7f325524ee0739herb
1695520dede2968372e79c572e37b7f325524ee0739herb            // Calculate left byte and mask
1705520dede2968372e79c572e37b7f325524ee0739herb            const uint8_t* leftByte = bits;
1715520dede2968372e79c572e37b7f325524ee0739herb            U8CPU leftMask = 0xFFU >> (leftEdge & 7);
1725520dede2968372e79c572e37b7f325524ee0739herb
1735520dede2968372e79c572e37b7f325524ee0739herb            // Calculate right byte and mask
1745520dede2968372e79c572e37b7f325524ee0739herb            int affectedRightBit = rightEdge - 1;
1755520dede2968372e79c572e37b7f325524ee0739herb            const uint8_t* rightByte = bits + (affectedRightBit >> 3);
1765520dede2968372e79c572e37b7f325524ee0739herb            U8CPU rightMask = generate_right_mask((affectedRightBit & 7) + 1);
1775520dede2968372e79c572e37b7f325524ee0739herb
1785520dede2968372e79c572e37b7f325524ee0739herb            // leftByte and rightByte are byte locations therefore, to get a count of bytes the
1795520dede2968372e79c572e37b7f325524ee0739herb            // code must add one.
1805520dede2968372e79c572e37b7f325524ee0739herb            ptrdiff_t rowBytes = rightByte - leftByte + 1;
1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1825520dede2968372e79c572e37b7f325524ee0739herb            while (--height >= 0) {
1835520dede2968372e79c572e37b7f325524ee0739herb                SkASSERT(bits + rowBytes <= endOfImage);
1845520dede2968372e79c572e37b7f325524ee0739herb                bits_to_runs(this, bitsLeft, cy, bits, leftMask, rowBytes, rightMask);
1855520dede2968372e79c572e37b7f325524ee0739herb                bits += maskRowBytes;
1865520dede2968372e79c572e37b7f325524ee0739herb                cy += 1;
1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
18982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    } else {
1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int                         width = clip.width();
1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAutoSTMalloc<64, int16_t> runStorage(width + 1);
1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int16_t*                    runs = runStorage.get();
1937989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com        const uint8_t*              aa = mask.getAddr8(clip.fLeft, clip.fTop);
1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        sk_memset16((uint16_t*)runs, 1, width);
1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs[width] = 0;
1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int height = clip.height();
1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int y = clip.fTop;
20082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        while (--height >= 0) {
2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            this->blitAntiH(clip.fLeft, y, aa, runs);
2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa += mask.fRowBytes;
2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            y += 1;
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////// these guys are not virtual, just a helpers
2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) {
2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    if (clip.quickReject(mask.fBounds)) {
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator clipper(clip, mask.fBounds);
21682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!clipper.done()) {
2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitMask(mask, cr);
2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        clipper.next();
2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) {
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator clipper(clip, rect);
22682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!clipper.done()) {
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = clipper.rect();
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        clipper.next();
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRegion(const SkRegion& clip) {
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Iterator iter(clip);
23682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    while (!iter.done()) {
2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& cr = iter.rect();
2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitH(int x, int y, int width) {}
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
24882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[],
24982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                              const int16_t runs[]) {}
2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {}
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitRect(int x, int y, int width, int height) {}
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {}
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
25741e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
25896fcdcc219d2a0d3579719b84b28bede76efba64halcanary    return nullptr;
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
261ea033606a06d05d2d42aa7118409fee798e53167reed@google.combool SkNullBlitter::isNullBlitter() const { return true; }
262ea033606a06d05d2d42aa7118409fee798e53167reed@google.com
26382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic int compute_anti_width(const int16_t runs[]) {
2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = 0;
26782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
26882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    for (;;) {
2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int count = runs[0];
27082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(count >= 0);
27282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (count == 0) {
2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            break;
27482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        width += count;
2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += count;
2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return width;
2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) {
2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (unsigned)(y - rect.fTop) < (unsigned)rect.height();
2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) {
2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (unsigned)(x - rect.fLeft) < (unsigned)rect.width();
2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
28982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitH(int left, int y, int width) {
2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(width > 0);
2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!y_in_rect(y, fClipRect)) {
2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
29482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int right = left + width;
2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (left < fClipRect.fLeft) {
2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        left = fClipRect.fLeft;
30082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
30182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (right > fClipRect.fRight) {
3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        right = fClipRect.fRight;
30382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    width = right - left;
30682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (width > 0) {
3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitH(left, y, width);
30882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
31182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[],
31282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                  const int16_t runs[]) {
31382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) {
3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
31582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x0 = left;
3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int x1 = left + compute_anti_width(runs);
3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
32082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x1 <= fClipRect.fLeft) {
3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
32282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1);
32582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x0 < fClipRect.fLeft) {
3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        int dx = fClipRect.fLeft - x0;
3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx);
3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        runs += dx;
3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        aa += dx;
3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x0 = fClipRect.fLeft;
3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
33482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (x1 > fClipRect.fRight) {
3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x1 = fClipRect.fRight;
3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0);
3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ((int16_t*)runs)[x1 - x0] = 0;
3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(x0 < x1 && runs[x1 - x0] == 0);
3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(compute_anti_width(runs) == x1 - x0);
3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fBlitter->blitAntiH(x0, y, aa, runs);
3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(height > 0);
3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
34982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (!x_in_rect(x, fClipRect)) {
3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return;
35182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int y0 = y;
3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int y1 = y + height;
3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
35682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y0 < fClipRect.fTop) {
3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y0 = fClipRect.fTop;
35882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
35982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y1 > fClipRect.fBottom) {
3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        y1 = fClipRect.fBottom;
36182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
36382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (y0 < y1) {
3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitV(x, y0, y1 - y0, alpha);
36582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
36882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) {
3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    r;
3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    r.set(left, y, left + width, y + height);
37282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (r.intersect(fClipRect)) {
3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
37482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
37749eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height,
37849eac192faa35159752525b23345563252721c64tomhudson@google.com                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
37949eac192faa35159752525b23345563252721c64tomhudson@google.com    SkIRect    r;
38049eac192faa35159752525b23345563252721c64tomhudson@google.com
38149eac192faa35159752525b23345563252721c64tomhudson@google.com    // The *true* width of the rectangle blitted is width+2:
38249eac192faa35159752525b23345563252721c64tomhudson@google.com    r.set(left, y, left + width + 2, y + height);
38349eac192faa35159752525b23345563252721c64tomhudson@google.com    if (r.intersect(fClipRect)) {
38449eac192faa35159752525b23345563252721c64tomhudson@google.com        if (r.fLeft != left) {
38549eac192faa35159752525b23345563252721c64tomhudson@google.com            SkASSERT(r.fLeft > left);
38649eac192faa35159752525b23345563252721c64tomhudson@google.com            leftAlpha = 255;
38749eac192faa35159752525b23345563252721c64tomhudson@google.com        }
38849eac192faa35159752525b23345563252721c64tomhudson@google.com        if (r.fRight != left + width + 2) {
38949eac192faa35159752525b23345563252721c64tomhudson@google.com            SkASSERT(r.fRight < left + width + 2);
39049eac192faa35159752525b23345563252721c64tomhudson@google.com            rightAlpha = 255;
39149eac192faa35159752525b23345563252721c64tomhudson@google.com        }
39249eac192faa35159752525b23345563252721c64tomhudson@google.com        if (255 == leftAlpha && 255 == rightAlpha) {
39349eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
39449eac192faa35159752525b23345563252721c64tomhudson@google.com        } else if (1 == r.width()) {
39549eac192faa35159752525b23345563252721c64tomhudson@google.com            if (r.fLeft == left) {
39649eac192faa35159752525b23345563252721c64tomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha);
39749eac192faa35159752525b23345563252721c64tomhudson@google.com            } else {
39849eac192faa35159752525b23345563252721c64tomhudson@google.com                SkASSERT(r.fLeft == left + width + 1);
39949eac192faa35159752525b23345563252721c64tomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha);
40049eac192faa35159752525b23345563252721c64tomhudson@google.com            }
40149eac192faa35159752525b23345563252721c64tomhudson@google.com        } else {
40249eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
40349eac192faa35159752525b23345563252721c64tomhudson@google.com                                   leftAlpha, rightAlpha);
40449eac192faa35159752525b23345563252721c64tomhudson@google.com        }
40549eac192faa35159752525b23345563252721c64tomhudson@google.com    }
40649eac192faa35159752525b23345563252721c64tomhudson@google.com}
40749eac192faa35159752525b23345563252721c64tomhudson@google.com
40882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    r = clip;
4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (r.intersect(fClipRect)) {
4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitMask(mask, r);
41582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    }
4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
41841e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) {
4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fBlitter->justAnOpaqueColor(value);
4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitH(int x, int y, int width) {
4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int left, right;
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
42882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (span.next(&left, &right)) {
4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right);
4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitH(left, y, right - left);
4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
43482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[],
43582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                 const int16_t runs[]) {
4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int width = compute_anti_width(runs);
4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Spanerator span(*fRgn, y, x, x + width);
4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int left, right;
4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();)
44082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int prevRite = x;
44282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (span.next(&left, &right)) {
4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(x <= left);
4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left < right);
4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(left >= bounds.fLeft && right <= bounds.fRight);
44682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left);
4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        // now zero before left
45082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (left > prevRite) {
4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int index = prevRite - x;
4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((uint8_t*)aa)[index] = 0;   // skip runs after right
4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((int16_t*)runs)[index] = SkToS16(left - prevRite);
4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
45582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        prevRite = right;
4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
45882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
45982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (prevRite > x) {
4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        ((int16_t*)runs)[prevRite - x] = 0;
46182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        if (x < 0) {
4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            int skip = runs[0];
4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            SkASSERT(skip >= -x);
4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            aa += skip;
4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            runs += skip;
4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            x += skip;
4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitAntiH(x, y, aa, runs);
4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    bounds;
4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds.set(x, y, x + 1, y + height);
4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
47982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& r = iter.rect();
4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bounds.contains(r));
4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitV(x, r.fTop, r.height(), alpha);
4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
48882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) {
4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkIRect    bounds;
4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    bounds.set(x, y, x + width, y + height);
4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator    iter(*fRgn, bounds);
4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
49482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& r = iter.rect();
4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(bounds.contains(r));
4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
50349eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height,
50449eac192faa35159752525b23345563252721c64tomhudson@google.com                                    SkAlpha leftAlpha, SkAlpha rightAlpha) {
50549eac192faa35159752525b23345563252721c64tomhudson@google.com    // The *true* width of the rectangle to blit is width + 2
50649eac192faa35159752525b23345563252721c64tomhudson@google.com    SkIRect    bounds;
50749eac192faa35159752525b23345563252721c64tomhudson@google.com    bounds.set(x, y, x + width + 2, y + height);
50849eac192faa35159752525b23345563252721c64tomhudson@google.com
50949eac192faa35159752525b23345563252721c64tomhudson@google.com    SkRegion::Cliperator    iter(*fRgn, bounds);
51049eac192faa35159752525b23345563252721c64tomhudson@google.com
51149eac192faa35159752525b23345563252721c64tomhudson@google.com    while (!iter.done()) {
51249eac192faa35159752525b23345563252721c64tomhudson@google.com        const SkIRect& r = iter.rect();
51349eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(bounds.contains(r));
51449eac192faa35159752525b23345563252721c64tomhudson@google.com        SkASSERT(r.fLeft >= x);
51531bab3934c773c2bd4c1e5e9ba8eb87c1c623b09tomhudson@google.com        SkASSERT(r.fRight <= x + width + 2);
51649eac192faa35159752525b23345563252721c64tomhudson@google.com
51749eac192faa35159752525b23345563252721c64tomhudson@google.com        SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255;
51849eac192faa35159752525b23345563252721c64tomhudson@google.com        SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ?
51949eac192faa35159752525b23345563252721c64tomhudson@google.com                                      rightAlpha : 255;
52049eac192faa35159752525b23345563252721c64tomhudson@google.com
52149eac192faa35159752525b23345563252721c64tomhudson@google.com        if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) {
52249eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height());
52349eac192faa35159752525b23345563252721c64tomhudson@google.com        } else if (1 == r.width()) {
52449eac192faa35159752525b23345563252721c64tomhudson@google.com            if (r.fLeft == x) {
525fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
52649eac192faa35159752525b23345563252721c64tomhudson@google.com                                effectiveLeftAlpha);
52749eac192faa35159752525b23345563252721c64tomhudson@google.com            } else {
52849eac192faa35159752525b23345563252721c64tomhudson@google.com                SkASSERT(r.fLeft == x + width + 1);
52949eac192faa35159752525b23345563252721c64tomhudson@google.com                fBlitter->blitV(r.fLeft, r.fTop, r.height(),
53049eac192faa35159752525b23345563252721c64tomhudson@google.com                                effectiveRightAlpha);
53149eac192faa35159752525b23345563252721c64tomhudson@google.com            }
53249eac192faa35159752525b23345563252721c64tomhudson@google.com        } else {
53349eac192faa35159752525b23345563252721c64tomhudson@google.com            fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(),
53449eac192faa35159752525b23345563252721c64tomhudson@google.com                                   effectiveLeftAlpha, effectiveRightAlpha);
53549eac192faa35159752525b23345563252721c64tomhudson@google.com        }
53649eac192faa35159752525b23345563252721c64tomhudson@google.com        iter.next();
53749eac192faa35159752525b23345563252721c64tomhudson@google.com    }
53849eac192faa35159752525b23345563252721c64tomhudson@google.com}
53949eac192faa35159752525b23345563252721c64tomhudson@google.com
54049eac192faa35159752525b23345563252721c64tomhudson@google.com
54182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(mask.fBounds.contains(clip));
5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkRegion::Cliperator iter(*fRgn, clip);
5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    const SkIRect&       r = iter.rect();
5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkBlitter*           blitter = fBlitter;
5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
54882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    while (!iter.done()) {
5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        blitter->blitMask(mask, r);
5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        iter.next();
5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55441e010cb901c0da9066c4df562030808c9ccd7f8reedconst SkPixmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) {
5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fBlitter->justAnOpaqueColor(value);
5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
55882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip,
56182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                                   const SkIRect* ir) {
56282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (clip) {
5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        const SkIRect& clipR = clip->getBounds();
5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
56582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) {
5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter = &fNullBlitter;
56782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else if (clip->isRect()) {
56896fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (ir == nullptr || !clipR.contains(*ir)) {
5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                fRectBlitter.init(blitter, clipR);
5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                blitter = &fRectBlitter;
5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
57282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fRgnBlitter.init(blitter, clip);
5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            blitter = &fRgnBlitter;
5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
58082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorShader.h"
5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h"
5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DShader : public SkShader {
5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
5878a21c9fe7f5fef9e87115defef27bd7218419f28reed    Sk3DShader(sk_sp<SkShader> proxy) : fProxy(std::move(proxy)) {}
58882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
58983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby    Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override {
59096fcdcc219d2a0d3579719b84b28bede76efba64halcanary        SkShader::Context* proxyContext = nullptr;
591a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com        if (fProxy) {
59283e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby            proxyContext = fProxy->makeContext(rec, alloc);
593ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org            if (!proxyContext) {
59496fcdcc219d2a0d3579719b84b28bede76efba64halcanary                return nullptr;
595ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org            }
596a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com        }
59783e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        return alloc->make<Sk3DShaderContext>(*this, rec, proxyContext);
5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
59982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
60087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    class Sk3DShaderContext : public SkShader::Context {
60187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    public:
60287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        // Calls proxyContext's destructor but will NOT free its memory.
603e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org        Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec,
604e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org                          SkShader::Context* proxyContext)
605e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org            : INHERITED(shader, rec)
60696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            , fMask(nullptr)
60787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            , fProxyContext(proxyContext)
60887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        {
60987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (!fProxyContext) {
610e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org                fPMColor = SkPreMultiplyColor(rec.fPaint->getColor());
61187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            }
61282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
614d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon        ~Sk3DShaderContext() override {
61587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (fProxyContext) {
61687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                fProxyContext->~Context();
61782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        void set3DMask(const SkMask* mask) override { fMask = mask; }
6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        void shadeSpan(int x, int y, SkPMColor span[], int count) override {
62387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (fProxyContext) {
62487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                fProxyContext->shadeSpan(x, y, span, count);
62587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            }
6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
62796fcdcc219d2a0d3579719b84b28bede76efba64halcanary            if (fMask == nullptr) {
62896fcdcc219d2a0d3579719b84b28bede76efba64halcanary                if (fProxyContext == nullptr) {
62987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    sk_memset32(span, fPMColor, count);
63087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                }
63187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                return;
63287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            }
6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
63487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            SkASSERT(fMask->fBounds.contains(x, y));
63587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            SkASSERT(fMask->fBounds.contains(x + count - 1, y));
63687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
63787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            size_t          size = fMask->computeImageSize();
63887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            const uint8_t*  alpha = fMask->getAddr8(x, y);
63987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            const uint8_t*  mulp = alpha + size;
64087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            const uint8_t*  addp = mulp + size;
64187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
64287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            if (fProxyContext) {
64387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                for (int i = 0; i < count; i++) {
64487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    if (alpha[i]) {
64587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        SkPMColor c = span[i];
64687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        if (c) {
64787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned a = SkGetPackedA32(c);
64887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned r = SkGetPackedR32(c);
64987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned g = SkGetPackedG32(c);
65087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned b = SkGetPackedB32(c);
65187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
65287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned mul = SkAlpha255To256(mulp[i]);
65387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            unsigned add = addp[i];
65487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
65587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            r = SkFastMin32(SkAlphaMul(r, mul) + add, a);
65687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            g = SkFastMin32(SkAlphaMul(g, mul) + add, a);
65787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            b = SkFastMin32(SkAlphaMul(b, mul) + add, a);
65887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
65987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                            span[i] = SkPackARGB32(a, r, g, b);
66087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        }
66187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    } else {
66287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        span[i] = 0;
66387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    }
66487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                }
66587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org            } else {    // color
66687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned a = SkGetPackedA32(fPMColor);
66787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned r = SkGetPackedR32(fPMColor);
66887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned g = SkGetPackedG32(fPMColor);
66987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                unsigned b = SkGetPackedB32(fPMColor);
67087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                for (int i = 0; i < count; i++) {
67187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    if (alpha[i]) {
6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned mul = SkAlpha255To256(mulp[i]);
6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                        unsigned add = addp[i];
6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        span[i] = SkPackARGB32( a,
67687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                        SkFastMin32(SkAlphaMul(r, mul) + add, a),
67787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                        SkFastMin32(SkAlphaMul(g, mul) + add, a),
67887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                        SkFastMin32(SkAlphaMul(b, mul) + add, a));
67987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                    } else {
68087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                        span[i] = 0;
6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                    }
68282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com                }
6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            }
6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
68587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
68687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    private:
68787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        // Unowned.
68887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        const SkMask*       fMask;
68987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        // Memory is unowned, but we need to call the destructor.
69087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkShader::Context*  fProxyContext;
69187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        SkPMColor           fPMColor;
69287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
69387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        typedef SkShader::Context INHERITED;
69487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    };
69582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
6960f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING
69736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void toString(SkString* str) const override {
69876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append("Sk3DShader: (");
69976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
70049f085dddff10473b6ebf832a974288300224e60bsalomon        if (fProxy) {
70176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            str->append("Proxy: ");
70276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com            fProxy->toString(str);
70376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        }
70476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
70576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        this->INHERITED::toString(str);
70676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
70776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com        str->append(")");
70876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com    }
70976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif
71076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com
711ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader)
712ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com
7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected:
71436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void flatten(SkWriteBuffer& buffer) const override {
7158a21c9fe7f5fef9e87115defef27bd7218419f28reed        buffer.writeFlattenable(fProxy.get());
7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
71782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
7198a21c9fe7f5fef9e87115defef27bd7218419f28reed    sk_sp<SkShader> fProxy;
7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    typedef SkShader INHERITED;
7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
72460c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> Sk3DShader::CreateProc(SkReadBuffer& buffer) {
72560c9b58b3214b0154c931656e91e39b230e987d8reed    return sk_make_sp<Sk3DShader>(buffer.readShader());
7269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed}
7279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DBlitter : public SkBlitter {
7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
730cc0e3110bde60201882a2c512a5cdd73c838f351reed    Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext)
731a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        : fProxy(proxy)
732cc0e3110bde60201882a2c512a5cdd73c838f351reed        , fShaderContext(shaderContext)
733a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org    {}
7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
73536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitH(int x, int y, int width) override {
7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitH(x, y, width);
7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
73882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
73960c9b58b3214b0154c931656e91e39b230e987d8reed    void blitAntiH(int x, int y, const SkAlpha antialias[], const int16_t runs[]) override {
7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitAntiH(x, y, antialias, runs);
7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
74282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
74336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitV(int x, int y, int height, SkAlpha alpha) override {
7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitV(x, y, height, alpha);
7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
74682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
74736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitRect(int x, int y, int width, int height) override {
7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fProxy->blitRect(x, y, width, height);
7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
75082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
75136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void blitMask(const SkMask& mask, const SkIRect& clip) override {
75282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        if (mask.fFormat == SkMask::k3D_Format) {
753cc0e3110bde60201882a2c512a5cdd73c838f351reed            fShaderContext->set3DMask(&mask);
7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((SkMask*)&mask)->fFormat = SkMask::kA8_Format;
7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->blitMask(mask, clip);
7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            ((SkMask*)&mask)->fFormat = SkMask::k3D_Format;
7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
75996fcdcc219d2a0d3579719b84b28bede76efba64halcanary            fShaderContext->set3DMask(nullptr);
76082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        } else {
7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com            fProxy->blitMask(mask, clip);
76282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        }
7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
76482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate:
76687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    // Both pointers are unowned. They will be deleted by SkSmallAllocator.
767cc0e3110bde60201882a2c512a5cdd73c838f351reed    SkBlitter*          fProxy;
768cc0e3110bde60201882a2c512a5cdd73c838f351reed    SkShader::Context*  fShaderContext;
7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
77182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h"
7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
775d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalitaSkShader::ContextRec::DstType SkBlitter::PreferredShaderDest(const SkImageInfo& dstInfo) {
776d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita#ifdef SK_FORCE_PM4f_FOR_L32_BLITS
777d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita    return SkShader::ContextRec::kPM4f_DstType;
778d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita#else
779960b2d69bbae19dc814f06d841b94ef71e291b48reed    return (dstInfo.gammaCloseToSRGB() || dstInfo.colorType() == kRGBA_F16_SkColorType)
780d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita            ? SkShader::ContextRec::kPM4f_DstType
781d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita            : SkShader::ContextRec::kPMColor_DstType;
782d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita#endif
783d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita}
784d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita
78541e010cb901c0da9066c4df562030808c9ccd7f8reedSkBlitter* SkBlitter::Choose(const SkPixmap& device,
7868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com                             const SkMatrix& matrix,
7876b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com                             const SkPaint& origPaint,
78883e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                             SkArenaAlloc* alloc,
789126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com                             bool drawCoverage) {
79083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby    SkASSERT(alloc != nullptr);
7918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
7928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // which check, in case we're being called by a client with a dummy device
7938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // (e.g. they have a bounder that always aborts the draw)
794900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    if (kUnknown_SkColorType == device.colorType() ||
795900ecf2f1579d42c9d2959831787af0346320f86reed@google.com            (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) {
79683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        return alloc->make<SkNullBlitter>();
7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
799458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com    SkShader* shader = origPaint.getShader();
800458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com    SkColorFilter* cf = origPaint.getColorFilter();
801374772bd61951f01bf84fe17bf53d8867681c9aereed    SkBlendMode mode = origPaint.getBlendMode();
802fe63045f075165b1be5d3e7fc5c710021d85f53breed    sk_sp<Sk3DShader> shader3D;
803458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com
8045dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
805fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
80696fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (origPaint.getMaskFilter() != nullptr &&
807458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com            origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) {
808fe63045f075165b1be5d3e7fc5c710021d85f53breed        shader3D = sk_make_sp<Sk3DShader>(sk_ref_sp(shader));
809458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com        // we know we haven't initialized lazyPaint yet, so just do it
810fe63045f075165b1be5d3e7fc5c710021d85f53breed        paint.writable()->setShader(shader3D);
811fe63045f075165b1be5d3e7fc5c710021d85f53breed        shader = shader3D.get();
8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
814374772bd61951f01bf84fe17bf53d8867681c9aereed    if (mode != SkBlendMode::kSrcOver) {
815a681433d42323d6d48e1aa3cb2ef97fb9d958d93halcanary        bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType();
816a681433d42323d6d48e1aa3cb2ef97fb9d958d93halcanary        switch (SkInterpretXfermode(*paint, deviceIsOpaque)) {
817a681433d42323d6d48e1aa3cb2ef97fb9d958d93halcanary            case kSrcOver_SkXfermodeInterpretation:
818374772bd61951f01bf84fe17bf53d8867681c9aereed                mode = SkBlendMode::kSrcOver;
819374772bd61951f01bf84fe17bf53d8867681c9aereed                paint.writable()->setBlendMode(mode);
820d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
821a681433d42323d6d48e1aa3cb2ef97fb9d958d93halcanary            case kSkipDrawing_SkXfermodeInterpretation:{
82283e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                return alloc->make<SkNullBlitter>();
823a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org            }
824d252db03d9650013b545ef9781fe993c07f8f314reed@android.com            default:
825d252db03d9650013b545ef9781fe993c07f8f314reed@android.com                break;
826d252db03d9650013b545ef9781fe993c07f8f314reed@android.com        }
827d252db03d9650013b545ef9781fe993c07f8f314reed@android.com    }
828d252db03d9650013b545ef9781fe993c07f8f314reed@android.com
82913201e74f43b9c5fa173339eb36de515370e6973reed@google.com    /*
83013201e74f43b9c5fa173339eb36de515370e6973reed@google.com     *  If the xfermode is CLEAR, then we can completely ignore the installed
83113201e74f43b9c5fa173339eb36de515370e6973reed@google.com     *  color/shader/colorfilter, and just pretend we're SRC + color==0. This
83213201e74f43b9c5fa173339eb36de515370e6973reed@google.com     *  will fall into our optimizations for SRC mode.
83313201e74f43b9c5fa173339eb36de515370e6973reed@google.com     */
834374772bd61951f01bf84fe17bf53d8867681c9aereed    if (mode == SkBlendMode::kClear) {
83513201e74f43b9c5fa173339eb36de515370e6973reed@google.com        SkPaint* p = paint.writable();
836fe63045f075165b1be5d3e7fc5c710021d85f53breed        p->setShader(nullptr);
837fe63045f075165b1be5d3e7fc5c710021d85f53breed        shader = nullptr;
838d053ce9c54d4e5937a142278359e5a4cde18095ereed        p->setColorFilter(nullptr);
839d053ce9c54d4e5937a142278359e5a4cde18095ereed        cf = nullptr;
840374772bd61951f01bf84fe17bf53d8867681c9aereed        p->setBlendMode(mode = SkBlendMode::kSrc);
84113201e74f43b9c5fa173339eb36de515370e6973reed@google.com        p->setColor(0);
84213201e74f43b9c5fa173339eb36de515370e6973reed@google.com    }
84313201e74f43b9c5fa173339eb36de515370e6973reed@google.com
844e71b167dbd4d8da76495ca85db83d1a3b49aaabdMike Klein    if (kAlpha_8_SkColorType == device.colorType() && drawCoverage) {
845e71b167dbd4d8da76495ca85db83d1a3b49aaabdMike Klein        SkASSERT(nullptr == shader);
846e71b167dbd4d8da76495ca85db83d1a3b49aaabdMike Klein        SkASSERT(paint->isSrcOver());
84783e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        return alloc->make<SkA8_Coverage_Blitter>(device, *paint);
848e71b167dbd4d8da76495ca85db83d1a3b49aaabdMike Klein    }
849e71b167dbd4d8da76495ca85db83d1a3b49aaabdMike Klein
85025834ffc5a4f6c45830dded7d5d135df157870e6Matt Sarett    if (SkBlitter* blitter = SkCreateRasterPipelineBlitter(device, *paint, matrix, alloc)) {
8519a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein        return blitter;
8529a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein    }
8539a5c47f4effba3b48a9a8c7c144b72b532d06efemtklein
85496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    if (nullptr == shader) {
855374772bd61951f01bf84fe17bf53d8867681c9aereed        if (mode != SkBlendMode::kSrcOver) {
8566b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // xfermodes (and filters) require shaders for our current blitters
857fe63045f075165b1be5d3e7fc5c710021d85f53breed            paint.writable()->setShader(SkShader::MakeColorShader(paint->getColor()));
85876a3b2abd02841c4ae786ac4cf59c3a51c545f73commit-bot@chromium.org            paint.writable()->setAlpha(0xFF);
859fe63045f075165b1be5d3e7fc5c710021d85f53breed            shader = paint->getShader();
8606b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        } else if (cf) {
8616b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // if no shader && no xfermode, we just apply the colorfilter to
8626b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com            // our color and move on.
8635dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com            SkPaint* writablePaint = paint.writable();
8645dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com            writablePaint->setColor(cf->filterColor(paint->getColor()));
86596fcdcc219d2a0d3579719b84b28bede76efba64halcanary            writablePaint->setColorFilter(nullptr);
86696fcdcc219d2a0d3579719b84b28bede76efba64halcanary            cf = nullptr;
8676b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com        }
8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
86982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
8706b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com    if (cf) {
8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT(shader);
872d053ce9c54d4e5937a142278359e5a4cde18095ereed        paint.writable()->setShader(shader->makeWithColorFilter(sk_ref_sp(cf)));
873150835e779ceb24e2b540f58958cbff2a0ab9942reed        shader = paint->getShader();
8741fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // blitters should ignore the presence/absence of a filter, since
8751fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com        // if there is one, the shader will take care of it.
8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
87782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
878a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com    /*
87987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org     *  We create a SkShader::Context object, and store it on the blitter.
880a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com     */
88196fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkShader::Context* shaderContext = nullptr;
88287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    if (shader) {
883d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita        const SkShader::ContextRec rec(*paint, matrix, nullptr,
88411970e56c10b49ad06adbe9e835d32c00a63dd7dBrian Osman                                       PreferredShaderDest(device.info()),
88511970e56c10b49ad06adbe9e835d32c00a63dd7dBrian Osman                                       device.colorSpace());
88683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        // Try to create the ShaderContext
88783e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        shaderContext = shader->makeContext(rec, alloc);
88883e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        if (!shaderContext) {
88983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby            return alloc->make<SkNullBlitter>();
89087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        }
89183e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        SkASSERT(shaderContext);
8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
89496fcdcc219d2a0d3579719b84b28bede76efba64halcanary    SkBlitter*  blitter = nullptr;
895900ecf2f1579d42c9d2959831787af0346320f86reed@google.com    switch (device.colorType()) {
896900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        case kAlpha_8_SkColorType:
897e71b167dbd4d8da76495ca85db83d1a3b49aaabdMike Klein            SkASSERT(!drawCoverage);  // Handled above.
898e71b167dbd4d8da76495ca85db83d1a3b49aaabdMike Klein            if (shader) {
89983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                blitter = alloc->make<SkA8_Shader_Blitter>(device, *paint, shaderContext);
90082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            } else {
90183e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                blitter = alloc->make<SkA8_Blitter>(device, *paint);
90282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
90382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
90482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
905900ecf2f1579d42c9d2959831787af0346320f86reed@google.com        case kRGB_565_SkColorType:
90683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby            blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, alloc);
90782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
90882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
90928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org        case kN32_SkColorType:
910a34be68a7eff0ae475b194f8a29975460cf3e456reed#ifdef SK_FORCE_PM4f_FOR_L32_BLITS
911a34be68a7eff0ae475b194f8a29975460cf3e456reed            if (true)
912a34be68a7eff0ae475b194f8a29975460cf3e456reed#else
913960b2d69bbae19dc814f06d841b94ef71e291b48reed            if (device.info().gammaCloseToSRGB())
914a34be68a7eff0ae475b194f8a29975460cf3e456reed#endif
915a34be68a7eff0ae475b194f8a29975460cf3e456reed            {
91683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                blitter = SkBlitter_ARGB32_Create(device, *paint, shaderContext, alloc);
917a34be68a7eff0ae475b194f8a29975460cf3e456reed            } else {
918a34be68a7eff0ae475b194f8a29975460cf3e456reed                if (shader) {
91983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                        blitter = alloc->make<SkARGB32_Shader_Blitter>(
920a34be68a7eff0ae475b194f8a29975460cf3e456reed                                device, *paint, shaderContext);
921a34be68a7eff0ae475b194f8a29975460cf3e456reed                } else if (paint->getColor() == SK_ColorBLACK) {
92283e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                    blitter = alloc->make<SkARGB32_Black_Blitter>(device, *paint);
923a34be68a7eff0ae475b194f8a29975460cf3e456reed                } else if (paint->getAlpha() == 0xFF) {
92483e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                    blitter = alloc->make<SkARGB32_Opaque_Blitter>(device, *paint);
925395eabeb0e72334c45324874c6e009b54634df21reed                } else {
92683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby                    blitter = alloc->make<SkARGB32_Blitter>(device, *paint);
927395eabeb0e72334c45324874c6e009b54634df21reed                }
92882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            }
92982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
93082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com
931a34be68a7eff0ae475b194f8a29975460cf3e456reed        case kRGBA_F16_SkColorType:
93283e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby            blitter = SkBlitter_F16_Create(device, *paint, shaderContext, alloc);
933a34be68a7eff0ae475b194f8a29975460cf3e456reed            break;
934a34be68a7eff0ae475b194f8a29975460cf3e456reed
93582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com        default:
93682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com            break;
9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
939129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (!blitter) {
94083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        blitter = alloc->make<SkNullBlitter>();
941129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
942129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
94382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com    if (shader3D) {
944a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        SkBlitter* innerBlitter = blitter;
94583e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        // FIXME - comment about allocator
946a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org        // innerBlitter was allocated by allocator, which will delete it.
947cc0e3110bde60201882a2c512a5cdd73c838f351reed        // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to
948cc0e3110bde60201882a2c512a5cdd73c838f351reed        // wrapper the blitter to notify it when we see an emboss mask.
94983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby        blitter = alloc->make<Sk3DBlitter>(innerBlitter, shaderContext);
9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return blitter;
9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
95482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com///////////////////////////////////////////////////////////////////////////////
9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
95656263c78d86cb536d463b8d46f00ac44cad3defbreedclass SkZeroShaderContext : public SkShader::Context {
957ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgpublic:
95856263c78d86cb536d463b8d46f00ac44cad3defbreed    SkZeroShaderContext(const SkShader& shader, const SkShader::ContextRec& rec)
959ca76c55d60dfe041e30e210d41fa0feb7fb54a1fscroggo        // Override rec with the identity matrix, so it is guaranteed to be invertible.
960d0c4e092d54d281991ecfdc2e4ddd5217e45b42afmalita        : INHERITED(shader, SkShader::ContextRec(*rec.fPaint, SkMatrix::I(), nullptr,
96111970e56c10b49ad06adbe9e835d32c00a63dd7dBrian Osman                                                 rec.fPreferredDstType, rec.fDstColorSpace)) {}
962ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org
96336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein    void shadeSpan(int x, int y, SkPMColor colors[], int count) override {
964ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org        sk_bzero(colors, count * sizeof(SkPMColor));
965ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    }
966ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org
967ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgprivate:
968ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org    typedef SkShader::Context INHERITED;
969ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org};
970ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org
97141e010cb901c0da9066c4df562030808c9ccd7f8reedSkShaderBlitter::SkShaderBlitter(const SkPixmap& device, const SkPaint& paint,
97287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org                                 SkShader::Context* shaderContext)
97387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        : INHERITED(device)
97487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        , fShader(paint.getShader())
97587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org        , fShaderContext(shaderContext) {
9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(fShader);
97787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    SkASSERT(fShaderContext);
9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->ref();
98087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org    fShaderFlags = fShaderContext->getFlags();
981a34be68a7eff0ae475b194f8a29975460cf3e456reed    fConstInY = SkToBool(fShaderFlags & SkShader::kConstInY32_Flag);
9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
9845119bdb952025a30f115b9c6a187173956e55097reed@android.comSkShaderBlitter::~SkShaderBlitter() {
9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    fShader->unref();
9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
98787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org
98828930b46487fc94fde206d1283623204c595b0f1Mike Reed///////////////////////////////////////////////////////////////////////////////////////////////////
98928930b46487fc94fde206d1283623204c595b0f1Mike Reed
99028930b46487fc94fde206d1283623204c595b0f1Mike Reed#ifdef SK_DEBUG
99128930b46487fc94fde206d1283623204c595b0f1Mike Reed
99228930b46487fc94fde206d1283623204c595b0f1Mike Reedvoid SkRectClipCheckBlitter::blitH(int x, int y, int width) {
99328930b46487fc94fde206d1283623204c595b0f1Mike Reed    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
99428930b46487fc94fde206d1283623204c595b0f1Mike Reed    fBlitter->blitH(x, y, width);
99528930b46487fc94fde206d1283623204c595b0f1Mike Reed}
99628930b46487fc94fde206d1283623204c595b0f1Mike Reed
99728930b46487fc94fde206d1283623204c595b0f1Mike Reedvoid SkRectClipCheckBlitter::blitAntiH(int x, int y, const SkAlpha aa[], const int16_t runs[]) {
99828930b46487fc94fde206d1283623204c595b0f1Mike Reed    const int16_t* iter = runs;
99928930b46487fc94fde206d1283623204c595b0f1Mike Reed    for (; *iter; iter += *iter)
100028930b46487fc94fde206d1283623204c595b0f1Mike Reed        ;
100128930b46487fc94fde206d1283623204c595b0f1Mike Reed    int width = iter - runs;
100228930b46487fc94fde206d1283623204c595b0f1Mike Reed    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, 1)));
100328930b46487fc94fde206d1283623204c595b0f1Mike Reed    fBlitter->blitAntiH(x, y, aa, runs);
100428930b46487fc94fde206d1283623204c595b0f1Mike Reed}
100528930b46487fc94fde206d1283623204c595b0f1Mike Reed
100628930b46487fc94fde206d1283623204c595b0f1Mike Reedvoid SkRectClipCheckBlitter::blitV(int x, int y, int height, SkAlpha alpha) {
100728930b46487fc94fde206d1283623204c595b0f1Mike Reed    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, height)));
100828930b46487fc94fde206d1283623204c595b0f1Mike Reed    fBlitter->blitV(x, y, height, alpha);
100928930b46487fc94fde206d1283623204c595b0f1Mike Reed}
101028930b46487fc94fde206d1283623204c595b0f1Mike Reed
101128930b46487fc94fde206d1283623204c595b0f1Mike Reedvoid SkRectClipCheckBlitter::blitRect(int x, int y, int width, int height) {
101228930b46487fc94fde206d1283623204c595b0f1Mike Reed    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, width, height)));
101328930b46487fc94fde206d1283623204c595b0f1Mike Reed    fBlitter->blitRect(x, y, width, height);
101428930b46487fc94fde206d1283623204c595b0f1Mike Reed}
101528930b46487fc94fde206d1283623204c595b0f1Mike Reed
101628930b46487fc94fde206d1283623204c595b0f1Mike Reedvoid SkRectClipCheckBlitter::blitAntiRect(int x, int y, int width, int height,
101728930b46487fc94fde206d1283623204c595b0f1Mike Reed                                     SkAlpha leftAlpha, SkAlpha rightAlpha) {
10188b9a725823fb195f24a85b5004b988e42fa82ef8Yuqian Li    bool skipLeft = !leftAlpha;
10198b9a725823fb195f24a85b5004b988e42fa82ef8Yuqian Li    bool skipRight = !rightAlpha;
10208b9a725823fb195f24a85b5004b988e42fa82ef8Yuqian Li    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x + skipLeft, y,
10218b9a725823fb195f24a85b5004b988e42fa82ef8Yuqian Li            width + 2 - skipRight - skipLeft, height)));
102228930b46487fc94fde206d1283623204c595b0f1Mike Reed    fBlitter->blitAntiRect(x, y, width, height, leftAlpha, rightAlpha);
102328930b46487fc94fde206d1283623204c595b0f1Mike Reed}
102428930b46487fc94fde206d1283623204c595b0f1Mike Reed
102528930b46487fc94fde206d1283623204c595b0f1Mike Reedvoid SkRectClipCheckBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {
102628930b46487fc94fde206d1283623204c595b0f1Mike Reed    SkASSERT(mask.fBounds.contains(clip));
102728930b46487fc94fde206d1283623204c595b0f1Mike Reed    SkASSERT(fClipRect.contains(clip));
102828930b46487fc94fde206d1283623204c595b0f1Mike Reed    fBlitter->blitMask(mask, clip);
102928930b46487fc94fde206d1283623204c595b0f1Mike Reed}
103028930b46487fc94fde206d1283623204c595b0f1Mike Reed
103128930b46487fc94fde206d1283623204c595b0f1Mike Reedconst SkPixmap* SkRectClipCheckBlitter::justAnOpaqueColor(uint32_t* value) {
103228930b46487fc94fde206d1283623204c595b0f1Mike Reed    return fBlitter->justAnOpaqueColor(value);
103328930b46487fc94fde206d1283623204c595b0f1Mike Reed}
103428930b46487fc94fde206d1283623204c595b0f1Mike Reed
103599bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Livoid SkRectClipCheckBlitter::blitAntiH2(int x, int y, U8CPU a0, U8CPU a1) {
103699bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 2, 1)));
103799bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li    fBlitter->blitAntiH2(x, y, a0, a1);
103899bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li}
103999bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li
104099bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Livoid SkRectClipCheckBlitter::blitAntiV2(int x, int y, U8CPU a0, U8CPU a1) {
104199bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li    SkASSERT(fClipRect.contains(SkIRect::MakeXYWH(x, y, 1, 2)));
104299bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li    fBlitter->blitAntiV2(x, y, a0, a1);
104399bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li}
104499bba9ea829323a7941d4f3a9c98da7a76432d1bYuqian Li
104528930b46487fc94fde206d1283623204c595b0f1Mike Reed#endif
1046