1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAntiRun.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColor.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorFilter.h" 12a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkCoreBlitters.h" 1302f65f2d9168f2304a09d784dbcfeefb7669c8b4reed@google.com#include "SkFilterShader.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 158b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMask.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h" 18a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkString.h" 19458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com#include "SkTLazy.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.comSkBlitter::~SkBlitter() {} 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25ea033606a06d05d2d42aa7118409fee798e53167reed@google.combool SkBlitter::isNullBlitter() const { return false; } 26ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 2780116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.orgbool SkBlitter::resetShaderContext(const SkShader::ContextRec&) { 2887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return true; 2987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 3087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 3187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkShader::Context* SkBlitter::getShaderContext() const { 3287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return NULL; 3387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 3487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 3582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) { 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitH(int x, int y, int width) { 400c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unimplemented"); 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 4482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const int16_t runs[]) { 450c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unimplemented"); 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 4982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (alpha == 255) { 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->blitRect(x, y, 1, height); 5182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int16_t runs[2]; 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs[0] = 1; 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs[1] = 0; 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->blitAntiH(x, y++, &alpha, runs); 5882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitRect(int x, int y, int width, int height) { 63a31ac73b8e261f02c4bd6ae1d622c4bd00226b80tomhudson@google.com SkASSERT(width > 0); 6482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->blitH(x, y++, width); 6682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6949eac192faa35159752525b23345563252721c64tomhudson@google.com/// Default implementation doesn't check for any easy optimizations 7049eac192faa35159752525b23345563252721c64tomhudson@google.com/// such as alpha == 0 or 255; also uses blitV(), which some subclasses 7149eac192faa35159752525b23345563252721c64tomhudson@google.com/// may not support. 7249eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkBlitter::blitAntiRect(int x, int y, int width, int height, 7349eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 744714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com this->blitV(x++, y, height, leftAlpha); 75a31ac73b8e261f02c4bd6ae1d622c4bd00226b80tomhudson@google.com if (width > 0) { 764714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com this->blitRect(x, y, width, height); 774714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com x += width; 784714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com } 794714359ec091b34a4f88eb9708868a58a22177d3tomhudson@google.com this->blitV(x, y, height, rightAlpha); 8049eac192faa35159752525b23345563252721c64tomhudson@google.com} 8149eac192faa35159752525b23345563252721c64tomhudson@google.com 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline void bits_to_runs(SkBlitter* blitter, int x, int y, 8582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const uint8_t bits[], 8682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com U8CPU left_mask, int rowBytes, 8782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com U8CPU right_mask) { 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int inFill = 0; 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int pos = 0; 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--rowBytes >= 0) { 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned b = *bits++ & left_mask; 9382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (rowBytes == 0) { 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com b &= right_mask; 9582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (unsigned test = 0x80; test != 0; test >>= 1) { 9882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (b & test) { 9982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (!inFill) { 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos = x; 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inFill = true; 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 10482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (inFill) { 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(pos, y, x - pos); 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com inFill = false; 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += 1; 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left_mask = 0xFF; 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // final cleanup 11582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (inFill) { 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(pos, y, x - pos); 11782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12082065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(mask.fBounds.contains(clip)); 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (mask.fFormat == SkMask::kBW_Format) { 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int cx = clip.fLeft; 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int cy = clip.fTop; 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int maskLeft = mask.fBounds.fLeft; 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int mask_rowBytes = mask.fRowBytes; 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = clip.height(); 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t* bits = mask.getAddr1(cx, cy); 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) { 13382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF); 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bits += mask_rowBytes; 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cy += 1; 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int left_edge = cx - maskLeft; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(left_edge >= 0); 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rite_edge = clip.fRight - maskLeft; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rite_edge > left_edge); 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int left_mask = 0xFF >> (left_edge & 7); 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rite_mask = 0xFF << (8 - (rite_edge & 7)); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3); 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 148a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com // check for empty right mask, so we don't read off the end (or go slower than we need to) 14982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (rite_mask == 0) { 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(full_runs >= 0); 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com full_runs -= 1; 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rite_mask = 0xFF; 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (left_mask == 0xFF) { 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com full_runs -= 1; 15682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 158a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com // back up manually so we can keep in sync with our byte-aligned src 159a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com // have cx reflect our actual starting x-coord 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cx -= left_edge & 7; 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (full_runs < 0) { 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((left_mask & rite_mask) != 0); 16482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask); 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bits += mask_rowBytes; 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cy += 1; 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 17082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 171a89c77b5cafcc13d76cb07c3240e48705cb30d8freed@google.com bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask); 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bits += mask_rowBytes; 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com cy += 1; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = clip.width(); 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoSTMalloc<64, int16_t> runStorage(width + 1); 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int16_t* runs = runStorage.get(); 1817989186dab6bc2f1c1927daf91bddd32b7fd8d0creed@google.com const uint8_t* aa = mask.getAddr8(clip.fLeft, clip.fTop); 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset16((uint16_t*)runs, 1, width); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs[width] = 0; 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = clip.height(); 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = clip.fTop; 18882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (--height >= 0) { 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->blitAntiH(clip.fLeft, y, aa, runs); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa += mask.fRowBytes; 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y += 1; 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////// these guys are not virtual, just a helpers 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) { 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clip.quickReject(mask.fBounds)) { 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator clipper(clip, mask.fBounds); 20482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (!clipper.done()) { 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = clipper.rect(); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->blitMask(mask, cr); 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clipper.next(); 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) { 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator clipper(clip, rect); 21482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (!clipper.done()) { 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = clipper.rect(); 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clipper.next(); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBlitter::blitRegion(const SkRegion& clip) { 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Iterator iter(clip); 22482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (!iter.done()) { 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = iter.rect(); 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.next(); 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitH(int x, int y, int width) {} 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 23782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const int16_t runs[]) {} 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {} 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitRect(int x, int y, int width, int height) {} 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {} 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24582065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) { 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 249ea033606a06d05d2d42aa7118409fee798e53167reed@google.combool SkNullBlitter::isNullBlitter() const { return true; } 250ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 25182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic int compute_anti_width(const int16_t runs[]) { 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = 0; 25582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 25682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com for (;;) { 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = runs[0]; 25882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= 0); 26082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (count == 0) { 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 26282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com width += count; 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return width; 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) { 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27382065d667f64e232bcde2ad849756a6096fcbe6freed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) { 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27782065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitH(int left, int y, int width) { 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(width > 0); 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (!y_in_rect(y, fClipRect)) { 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 28282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int right = left + width; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (left < fClipRect.fLeft) { 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left = fClipRect.fLeft; 28882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 28982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (right > fClipRect.fRight) { 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com right = fClipRect.fRight; 29182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com width = right - left; 29482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (width > 0) { 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitH(left, y, width); 29682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 29982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[], 30082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const int16_t runs[]) { 30182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) { 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 30382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x0 = left; 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x1 = left + compute_anti_width(runs); 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 30882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (x1 <= fClipRect.fLeft) { 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 31082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x0 < x1); 31382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (x0 < fClipRect.fLeft) { 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dx = fClipRect.fLeft - x0; 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx); 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += dx; 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa += dx; 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x0 = fClipRect.fLeft; 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 32282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (x1 > fClipRect.fRight) { 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x1 = fClipRect.fRight; 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0); 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((int16_t*)runs)[x1 - x0] = 0; 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(compute_anti_width(runs) == x1 - x0); 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitAntiH(x0, y, aa, runs); 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 33482065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(height > 0); 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 33782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (!x_in_rect(x, fClipRect)) { 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 33982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y0 = y; 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y1 = y + height; 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 34482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (y0 < fClipRect.fTop) { 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y0 = fClipRect.fTop; 34682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 34782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (y1 > fClipRect.fBottom) { 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y1 = fClipRect.fBottom; 34982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 35182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (y0 < y1) { 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitV(x, y0, y1 - y0, alpha); 35382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 35682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) { 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect r; 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(left, y, left + width, y + height); 36082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (r.intersect(fClipRect)) { 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 36282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 36549eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height, 36649eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 36749eac192faa35159752525b23345563252721c64tomhudson@google.com SkIRect r; 36849eac192faa35159752525b23345563252721c64tomhudson@google.com 36949eac192faa35159752525b23345563252721c64tomhudson@google.com // The *true* width of the rectangle blitted is width+2: 37049eac192faa35159752525b23345563252721c64tomhudson@google.com r.set(left, y, left + width + 2, y + height); 37149eac192faa35159752525b23345563252721c64tomhudson@google.com if (r.intersect(fClipRect)) { 37249eac192faa35159752525b23345563252721c64tomhudson@google.com if (r.fLeft != left) { 37349eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(r.fLeft > left); 37449eac192faa35159752525b23345563252721c64tomhudson@google.com leftAlpha = 255; 37549eac192faa35159752525b23345563252721c64tomhudson@google.com } 37649eac192faa35159752525b23345563252721c64tomhudson@google.com if (r.fRight != left + width + 2) { 37749eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(r.fRight < left + width + 2); 37849eac192faa35159752525b23345563252721c64tomhudson@google.com rightAlpha = 255; 37949eac192faa35159752525b23345563252721c64tomhudson@google.com } 38049eac192faa35159752525b23345563252721c64tomhudson@google.com if (255 == leftAlpha && 255 == rightAlpha) { 38149eac192faa35159752525b23345563252721c64tomhudson@google.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 38249eac192faa35159752525b23345563252721c64tomhudson@google.com } else if (1 == r.width()) { 38349eac192faa35159752525b23345563252721c64tomhudson@google.com if (r.fLeft == left) { 38449eac192faa35159752525b23345563252721c64tomhudson@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha); 38549eac192faa35159752525b23345563252721c64tomhudson@google.com } else { 38649eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(r.fLeft == left + width + 1); 38749eac192faa35159752525b23345563252721c64tomhudson@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha); 38849eac192faa35159752525b23345563252721c64tomhudson@google.com } 38949eac192faa35159752525b23345563252721c64tomhudson@google.com } else { 39049eac192faa35159752525b23345563252721c64tomhudson@google.com fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 39149eac192faa35159752525b23345563252721c64tomhudson@google.com leftAlpha, rightAlpha); 39249eac192faa35159752525b23345563252721c64tomhudson@google.com } 39349eac192faa35159752525b23345563252721c64tomhudson@google.com } 39449eac192faa35159752525b23345563252721c64tomhudson@google.com} 39549eac192faa35159752525b23345563252721c64tomhudson@google.com 39682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(mask.fBounds.contains(clip)); 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect r = clip; 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 40182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (r.intersect(fClipRect)) { 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitMask(mask, r); 40382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 40682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) { 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fBlitter->justAnOpaqueColor(value); 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 41082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 41282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitH(int x, int y, int width) { 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Spanerator span(*fRgn, y, x, x + width); 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int left, right; 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 41682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (span.next(&left, &right)) { 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(left < right); 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitH(left, y, right - left); 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 42282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 42382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const int16_t runs[]) { 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = compute_anti_width(runs); 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Spanerator span(*fRgn, y, x, x + width); 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int left, right; 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();) 42882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int prevRite = x; 43082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (span.next(&left, &right)) { 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x <= left); 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(left < right); 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(left >= bounds.fLeft && right <= bounds.fRight); 43482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left); 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now zero before left 43882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (left > prevRite) { 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = prevRite - x; 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((uint8_t*)aa)[index] = 0; // skip runs after right 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((int16_t*)runs)[index] = SkToS16(left - prevRite); 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 44382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevRite = right; 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 44682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 44782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (prevRite > x) { 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((int16_t*)runs)[prevRite - x] = 0; 44982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (x < 0) { 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int skip = runs[0]; 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(skip >= -x); 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa += skip; 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += skip; 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += skip; 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitAntiH(x, y, aa, runs); 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 46182065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(x, y, x + 1, y + height); 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator iter(*fRgn, bounds); 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 46782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (!iter.done()) { 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = iter.rect(); 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bounds.contains(r)); 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitV(x, r.fTop, r.height(), alpha); 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.next(); 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 47682065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) { 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(x, y, x + width, y + height); 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator iter(*fRgn, bounds); 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 48282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (!iter.done()) { 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = iter.rect(); 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bounds.contains(r)); 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.next(); 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 49149eac192faa35159752525b23345563252721c64tomhudson@google.comvoid SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height, 49249eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 49349eac192faa35159752525b23345563252721c64tomhudson@google.com // The *true* width of the rectangle to blit is width + 2 49449eac192faa35159752525b23345563252721c64tomhudson@google.com SkIRect bounds; 49549eac192faa35159752525b23345563252721c64tomhudson@google.com bounds.set(x, y, x + width + 2, y + height); 49649eac192faa35159752525b23345563252721c64tomhudson@google.com 49749eac192faa35159752525b23345563252721c64tomhudson@google.com SkRegion::Cliperator iter(*fRgn, bounds); 49849eac192faa35159752525b23345563252721c64tomhudson@google.com 49949eac192faa35159752525b23345563252721c64tomhudson@google.com while (!iter.done()) { 50049eac192faa35159752525b23345563252721c64tomhudson@google.com const SkIRect& r = iter.rect(); 50149eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(bounds.contains(r)); 50249eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(r.fLeft >= x); 50331bab3934c773c2bd4c1e5e9ba8eb87c1c623b09tomhudson@google.com SkASSERT(r.fRight <= x + width + 2); 50449eac192faa35159752525b23345563252721c64tomhudson@google.com 50549eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255; 50649eac192faa35159752525b23345563252721c64tomhudson@google.com SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ? 50749eac192faa35159752525b23345563252721c64tomhudson@google.com rightAlpha : 255; 50849eac192faa35159752525b23345563252721c64tomhudson@google.com 50949eac192faa35159752525b23345563252721c64tomhudson@google.com if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) { 51049eac192faa35159752525b23345563252721c64tomhudson@google.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 51149eac192faa35159752525b23345563252721c64tomhudson@google.com } else if (1 == r.width()) { 51249eac192faa35159752525b23345563252721c64tomhudson@google.com if (r.fLeft == x) { 513fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), 51449eac192faa35159752525b23345563252721c64tomhudson@google.com effectiveLeftAlpha); 51549eac192faa35159752525b23345563252721c64tomhudson@google.com } else { 51649eac192faa35159752525b23345563252721c64tomhudson@google.com SkASSERT(r.fLeft == x + width + 1); 51749eac192faa35159752525b23345563252721c64tomhudson@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), 51849eac192faa35159752525b23345563252721c64tomhudson@google.com effectiveRightAlpha); 51949eac192faa35159752525b23345563252721c64tomhudson@google.com } 52049eac192faa35159752525b23345563252721c64tomhudson@google.com } else { 52149eac192faa35159752525b23345563252721c64tomhudson@google.com fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 52249eac192faa35159752525b23345563252721c64tomhudson@google.com effectiveLeftAlpha, effectiveRightAlpha); 52349eac192faa35159752525b23345563252721c64tomhudson@google.com } 52449eac192faa35159752525b23345563252721c64tomhudson@google.com iter.next(); 52549eac192faa35159752525b23345563252721c64tomhudson@google.com } 52649eac192faa35159752525b23345563252721c64tomhudson@google.com} 52749eac192faa35159752525b23345563252721c64tomhudson@google.com 52849eac192faa35159752525b23345563252721c64tomhudson@google.com 52982065d667f64e232bcde2ad849756a6096fcbe6freed@google.comvoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(mask.fBounds.contains(clip)); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator iter(*fRgn, clip); 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = iter.rect(); 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter = fBlitter; 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 53682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com while (!iter.done()) { 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitMask(mask, r); 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.next(); 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 54282065d667f64e232bcde2ad849756a6096fcbe6freed@google.comconst SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) { 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fBlitter->justAnOpaqueColor(value); 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 54682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 54882065d667f64e232bcde2ad849756a6096fcbe6freed@google.comSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, 54982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const SkIRect* ir) { 55082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (clip) { 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& clipR = clip->getBounds(); 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 55382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) { 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = &fNullBlitter; 55582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else if (clip->isRect()) { 55682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (ir == NULL || !clipR.contains(*ir)) { 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRectBlitter.init(blitter, clipR); 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = &fRectBlitter; 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 56082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRgnBlitter.init(blitter, clip); 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter = &fRgnBlitter; 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return blitter; 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 56882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorShader.h" 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DShader : public SkShader { 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 57582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com Sk3DShader(SkShader* proxy) : fProxy(proxy) { 57682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeRef(proxy); 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 57882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 57982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com virtual ~Sk3DShader() { 58082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com SkSafeUnref(fProxy); 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 58282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 58387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual size_t contextSize() const SK_OVERRIDE { 58487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org size_t size = sizeof(Sk3DShaderContext); 58587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (fProxy) { 58687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org size += fProxy->contextSize(); 58787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 58887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return size; 58987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 591ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org virtual Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE { 592ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org SkShader::Context* proxyContext = NULL; 593a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com if (fProxy) { 59487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org char* proxyContextStorage = (char*) storage + sizeof(Sk3DShaderContext); 595e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org proxyContext = fProxy->createContext(rec, proxyContextStorage); 596ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org if (!proxyContext) { 597ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org return NULL; 598ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 599a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com } 600e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, Sk3DShaderContext, (*this, rec, proxyContext)); 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 60282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 60387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org class Sk3DShaderContext : public SkShader::Context { 60487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org public: 60587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Calls proxyContext's destructor but will NOT free its memory. 606e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org Sk3DShaderContext(const Sk3DShader& shader, const ContextRec& rec, 607e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org SkShader::Context* proxyContext) 608e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) 60987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org , fMask(NULL) 61087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org , fProxyContext(proxyContext) 61187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org { 61287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (!fProxyContext) { 613e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org fPMColor = SkPreMultiplyColor(rec.fPaint->getColor()); 61487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 61582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 61787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual ~Sk3DShaderContext() { 61887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (fProxyContext) { 61987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org fProxyContext->~Context(); 62082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6239f23a27ed9961fd4575864e590eda328452895e7reed virtual void set3DMask(const SkMask* mask) SK_OVERRIDE { fMask = mask; } 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 62587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { 62687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (fProxyContext) { 62787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org fProxyContext->shadeSpan(x, y, span, count); 62887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 63087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (fMask == NULL) { 63187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (fProxyContext == NULL) { 63287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org sk_memset32(span, fPMColor, count); 63387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 63487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return; 63587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 63787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(fMask->fBounds.contains(x, y)); 63887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(fMask->fBounds.contains(x + count - 1, y)); 63987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 64087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org size_t size = fMask->computeImageSize(); 64187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const uint8_t* alpha = fMask->getAddr8(x, y); 64287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const uint8_t* mulp = alpha + size; 64387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const uint8_t* addp = mulp + size; 64487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 64587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (fProxyContext) { 64687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org for (int i = 0; i < count; i++) { 64787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (alpha[i]) { 64887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor c = span[i]; 64987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (c) { 65087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned a = SkGetPackedA32(c); 65187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned r = SkGetPackedR32(c); 65287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned g = SkGetPackedG32(c); 65387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned b = SkGetPackedB32(c); 65487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 65587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned mul = SkAlpha255To256(mulp[i]); 65687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned add = addp[i]; 65787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 65887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org r = SkFastMin32(SkAlphaMul(r, mul) + add, a); 65987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org g = SkFastMin32(SkAlphaMul(g, mul) + add, a); 66087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org b = SkFastMin32(SkAlphaMul(b, mul) + add, a); 66187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 66287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org span[i] = SkPackARGB32(a, r, g, b); 66387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 66487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else { 66587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org span[i] = 0; 66687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 66787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 66887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else { // color 66987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned a = SkGetPackedA32(fPMColor); 67087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned r = SkGetPackedR32(fPMColor); 67187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned g = SkGetPackedG32(fPMColor); 67287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org unsigned b = SkGetPackedB32(fPMColor); 67387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org for (int i = 0; i < count; i++) { 67487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (alpha[i]) { 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned mul = SkAlpha255To256(mulp[i]); 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned add = addp[i]; 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 67887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org span[i] = SkPackARGB32( a, 67987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkFastMin32(SkAlphaMul(r, mul) + add, a), 68087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkFastMin32(SkAlphaMul(g, mul) + add, a), 68187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkFastMin32(SkAlphaMul(b, mul) + add, a)); 68287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else { 68387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org span[i] = 0; 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 68582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 68887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 68987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org private: 69087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Unowned. 69187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org const SkMask* fMask; 69287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Memory is unowned, but we need to call the destructor. 69387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* fProxyContext; 69487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor fPMColor; 69587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 69687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org typedef SkShader::Context INHERITED; 69787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org }; 69882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 6990f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 70076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com virtual void toString(SkString* str) const SK_OVERRIDE { 70176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("Sk3DShader: ("); 70276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 70376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com if (NULL != fProxy) { 70476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("Proxy: "); 70576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com fProxy->toString(str); 70676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com } 70776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 70876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 70976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 71076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 71176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com } 71276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 71376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 714ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader) 715ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 7178b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org Sk3DShader(SkReadBuffer& buffer) : INHERITED(buffer) { 718353482251e61971a8cf3a60bbb6910f482be634freed@google.com fProxy = buffer.readShader(); 71987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Leaving this here until we bump the picture version, though this 72087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // shader should never be recorded. 72187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org buffer.readColor(); 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 72382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 7248b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->INHERITED::flatten(buffer); 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com buffer.writeFlattenable(fProxy); 72787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Leaving this here until we bump the picture version, though this 72887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // shader should never be recorded. 72987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org buffer.writeColor(SkColor()); 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 73182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* fProxy; 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShader INHERITED; 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass Sk3DBlitter : public SkBlitter { 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 7409f23a27ed9961fd4575864e590eda328452895e7reed Sk3DBlitter(SkBlitter* proxy, SkShader::Context* shaderContext) 741a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org : fProxy(proxy) 7429f23a27ed9961fd4575864e590eda328452895e7reed , fShaderContext(shaderContext) 743a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org {} 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 74582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com virtual void blitH(int x, int y, int width) { 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fProxy->blitH(x, y, width); 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 74882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 74982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 75082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com const int16_t runs[]) { 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fProxy->blitAntiH(x, y, antialias, runs); 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 75382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 75482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com virtual void blitV(int x, int y, int height, SkAlpha alpha) { 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fProxy->blitV(x, y, height, alpha); 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 75782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 75882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com virtual void blitRect(int x, int y, int width, int height) { 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fProxy->blitRect(x, y, width, height); 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 76182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 76282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com virtual void blitMask(const SkMask& mask, const SkIRect& clip) { 76382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (mask.fFormat == SkMask::k3D_Format) { 7649f23a27ed9961fd4575864e590eda328452895e7reed fShaderContext->set3DMask(&mask); 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fProxy->blitMask(mask, clip); 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7709f23a27ed9961fd4575864e590eda328452895e7reed fShaderContext->set3DMask(NULL); 77182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fProxy->blitMask(mask, clip); 77382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 77582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 77787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Both pointers are unowned. They will be deleted by SkSmallAllocator. 7789f23a27ed9961fd4575864e590eda328452895e7reed SkBlitter* fProxy; 7799f23a27ed9961fd4575864e590eda328452895e7reed SkShader::Context* fShaderContext; 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 78282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 7838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h" 7858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 786d252db03d9650013b545ef9781fe993c07f8f314reed@android.comstatic bool just_solid_color(const SkPaint& paint) { 787d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) { 788d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkShader* shader = paint.getShader(); 78987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (NULL == shader) { 790d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return true; 791d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 792d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 793d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return false; 794d252db03d9650013b545ef9781fe993c07f8f314reed@android.com} 79582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 796d252db03d9650013b545ef9781fe993c07f8f314reed@android.com/** By analyzing the paint (with an xfermode), we may decide we can take 797d252db03d9650013b545ef9781fe993c07f8f314reed@android.com special action. This enum lists our possible actions 798d252db03d9650013b545ef9781fe993c07f8f314reed@android.com */ 799d252db03d9650013b545ef9781fe993c07f8f314reed@android.comenum XferInterp { 800d252db03d9650013b545ef9781fe993c07f8f314reed@android.com kNormal_XferInterp, // no special interpretation, draw normally 801d252db03d9650013b545ef9781fe993c07f8f314reed@android.com kSrcOver_XferInterp, // draw as if in srcover mode 802d252db03d9650013b545ef9781fe993c07f8f314reed@android.com kSkipDrawing_XferInterp // draw nothing 803d252db03d9650013b545ef9781fe993c07f8f314reed@android.com}; 804d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 805d252db03d9650013b545ef9781fe993c07f8f314reed@android.comstatic XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer, 806900ecf2f1579d42c9d2959831787af0346320f86reed@google.com SkColorType deviceCT) { 807845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode; 80882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 809be2aa2aa1f8bf73d974bdd9438fc741bbf0cfbe6mike@reedtribe.org if (SkXfermode::AsMode(xfer, &mode)) { 810d252db03d9650013b545ef9781fe993c07f8f314reed@android.com switch (mode) { 811845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kSrc_Mode: 812d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (just_solid_color(paint)) { 813d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return kSrcOver_XferInterp; 814d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 815d252db03d9650013b545ef9781fe993c07f8f314reed@android.com break; 816845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kDst_Mode: 817d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return kSkipDrawing_XferInterp; 818845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kSrcOver_Mode: 819d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return kSrcOver_XferInterp; 820845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kDstOver_Mode: 821900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (kRGB_565_SkColorType == deviceCT) { 822d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return kSkipDrawing_XferInterp; 823d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 824d252db03d9650013b545ef9781fe993c07f8f314reed@android.com break; 825845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kSrcIn_Mode: 826900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (kRGB_565_SkColorType == deviceCT && 827d252db03d9650013b545ef9781fe993c07f8f314reed@android.com just_solid_color(paint)) { 828d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return kSrcOver_XferInterp; 829d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 830d252db03d9650013b545ef9781fe993c07f8f314reed@android.com break; 831845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kDstIn_Mode: 832d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (just_solid_color(paint)) { 833d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return kSkipDrawing_XferInterp; 834d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 835d252db03d9650013b545ef9781fe993c07f8f314reed@android.com break; 836d252db03d9650013b545ef9781fe993c07f8f314reed@android.com default: 837d252db03d9650013b545ef9781fe993c07f8f314reed@android.com break; 838d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 839d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 840d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return kNormal_XferInterp; 841d252db03d9650013b545ef9781fe993c07f8f314reed@android.com} 842d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkBlitter* SkBlitter::Choose(const SkBitmap& device, 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix, 8456b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com const SkPaint& origPaint, 846a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator* allocator, 847126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com bool drawCoverage) { 848a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkASSERT(allocator != NULL); 8498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter = NULL; 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // which check, in case we're being called by a client with a dummy device 8538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (e.g. they have a bounder that always aborts the draw) 854900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (kUnknown_SkColorType == device.colorType() || 855900ecf2f1579d42c9d2959831787af0346320f86reed@google.com (drawCoverage && (kAlpha_8_SkColorType != device.colorType()))) { 856a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkNullBlitter>(); 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return blitter; 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 860458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com SkShader* shader = origPaint.getShader(); 861458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com SkColorFilter* cf = origPaint.getColorFilter(); 862458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com SkXfermode* mode = origPaint.getXfermode(); 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Sk3DShader* shader3D = NULL; 864458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com 8655dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 866fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 867458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com if (origPaint.getMaskFilter() != NULL && 868458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) { 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader3D = SkNEW_ARGS(Sk3DShader, (shader)); 870458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com // we know we haven't initialized lazyPaint yet, so just do it 8715dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setShader(shader3D)->unref(); 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader = shader3D; 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 875d252db03d9650013b545ef9781fe993c07f8f314reed@android.com if (NULL != mode) { 876900ecf2f1579d42c9d2959831787af0346320f86reed@google.com switch (interpret_xfermode(*paint, mode, device.colorType())) { 877d252db03d9650013b545ef9781fe993c07f8f314reed@android.com case kSrcOver_XferInterp: 878d252db03d9650013b545ef9781fe993c07f8f314reed@android.com mode = NULL; 8795dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setXfermode(NULL); 880d252db03d9650013b545ef9781fe993c07f8f314reed@android.com break; 881a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org case kSkipDrawing_XferInterp:{ 882a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkNullBlitter>(); 883d252db03d9650013b545ef9781fe993c07f8f314reed@android.com return blitter; 884a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org } 885d252db03d9650013b545ef9781fe993c07f8f314reed@android.com default: 886d252db03d9650013b545ef9781fe993c07f8f314reed@android.com break; 887d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 888d252db03d9650013b545ef9781fe993c07f8f314reed@android.com } 889d252db03d9650013b545ef9781fe993c07f8f314reed@android.com 89013201e74f43b9c5fa173339eb36de515370e6973reed@google.com /* 89113201e74f43b9c5fa173339eb36de515370e6973reed@google.com * If the xfermode is CLEAR, then we can completely ignore the installed 89213201e74f43b9c5fa173339eb36de515370e6973reed@google.com * color/shader/colorfilter, and just pretend we're SRC + color==0. This 89313201e74f43b9c5fa173339eb36de515370e6973reed@google.com * will fall into our optimizations for SRC mode. 89413201e74f43b9c5fa173339eb36de515370e6973reed@google.com */ 89513201e74f43b9c5fa173339eb36de515370e6973reed@google.com if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) { 89613201e74f43b9c5fa173339eb36de515370e6973reed@google.com SkPaint* p = paint.writable(); 89713201e74f43b9c5fa173339eb36de515370e6973reed@google.com shader = p->setShader(NULL); 89813201e74f43b9c5fa173339eb36de515370e6973reed@google.com cf = p->setColorFilter(NULL); 89913201e74f43b9c5fa173339eb36de515370e6973reed@google.com mode = p->setXfermodeMode(SkXfermode::kSrc_Mode); 90013201e74f43b9c5fa173339eb36de515370e6973reed@google.com p->setColor(0); 90113201e74f43b9c5fa173339eb36de515370e6973reed@google.com } 90213201e74f43b9c5fa173339eb36de515370e6973reed@google.com 9036b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com if (NULL == shader) { 9046b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com if (mode) { 9056b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com // xfermodes (and filters) require shaders for our current blitters 90676a3b2abd02841c4ae786ac4cf59c3a51c545f73commit-bot@chromium.org shader = SkNEW_ARGS(SkColorShader, (paint->getColor())); 9075dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setShader(shader)->unref(); 90876a3b2abd02841c4ae786ac4cf59c3a51c545f73commit-bot@chromium.org paint.writable()->setAlpha(0xFF); 9096b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com } else if (cf) { 9106b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com // if no shader && no xfermode, we just apply the colorfilter to 9116b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com // our color and move on. 9125dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkPaint* writablePaint = paint.writable(); 9135dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setColor(cf->filterColor(paint->getColor())); 9145dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setColorFilter(NULL); 9156b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com cf = NULL; 9166b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com } 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 91882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 9196b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com if (cf) { 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(shader); 9216b7aee387d3b4b2df5894b51fa1c0baf649c6540reed@google.com shader = SkNEW_ARGS(SkFilterShader, (shader, cf)); 9225dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setShader(shader)->unref(); 9231fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com // blitters should ignore the presence/absence of a filter, since 9241fc4c605def61d9e10489f9cd63dc378baa6ade3reed@android.com // if there is one, the shader will take care of it. 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 92682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 927a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com /* 92887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org * We create a SkShader::Context object, and store it on the blitter. 929a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com */ 93087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext; 93187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (shader) { 932e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org SkShader::ContextRec rec(device, *paint, matrix); 93387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Try to create the ShaderContext 93487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org void* storage = allocator->reserveT<SkShader::Context>(shader->contextSize()); 935e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org shaderContext = shader->createContext(rec, storage); 93687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (!shaderContext) { 93787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org allocator->freeLast(); 93887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org blitter = allocator->createT<SkNullBlitter>(); 93987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return blitter; 94087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 94187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(shaderContext); 94287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT((void*) shaderContext == storage); 94387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else { 94487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org shaderContext = NULL; 9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 947ab7442c8d733e0642d1cd80af23cdab43d77039eskia.committer@gmail.com 948900ecf2f1579d42c9d2959831787af0346320f86reed@google.com switch (device.colorType()) { 949900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 950126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com if (drawCoverage) { 951126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(NULL == shader); 952126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkASSERT(NULL == paint->getXfermode()); 953a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint); 954126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com } else if (shader) { 95587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext); 95682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 957a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkA8_Blitter>(device, *paint); 95882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 95982065d667f64e232bcde2ad849756a6096fcbe6freed@google.com break; 96082065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 961900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 96287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org blitter = SkBlitter_ChooseD565(device, *paint, shaderContext, allocator); 96382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com break; 96482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 96528fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 96682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (shader) { 96787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org blitter = allocator->createT<SkARGB32_Shader_Blitter>( 96887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org device, *paint, shaderContext); 969458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com } else if (paint->getColor() == SK_ColorBLACK) { 970a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint); 971458849004892c05fa1dcbcf6d355dfcce028d77areed@google.com } else if (paint->getAlpha() == 0xFF) { 972a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkARGB32_Opaque_Blitter>(device, *paint); 97382065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } else { 974a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkARGB32_Blitter>(device, *paint); 97582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com } 97682065d667f64e232bcde2ad849756a6096fcbe6freed@google.com break; 97782065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 97882065d667f64e232bcde2ad849756a6096fcbe6freed@google.com default: 9790c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unsupported device config"); 980a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org blitter = allocator->createT<SkNullBlitter>(); 98182065d667f64e232bcde2ad849756a6096fcbe6freed@google.com break; 9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 98482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com if (shader3D) { 985a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkBlitter* innerBlitter = blitter; 986a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // innerBlitter was allocated by allocator, which will delete it. 9879f23a27ed9961fd4575864e590eda328452895e7reed // We know shaderContext or its proxies is of type Sk3DShaderContext, so we need to 9889f23a27ed9961fd4575864e590eda328452895e7reed // wrapper the blitter to notify it when we see an emboss mask. 9899f23a27ed9961fd4575864e590eda328452895e7reed blitter = allocator->createT<Sk3DBlitter>(innerBlitter, shaderContext); 9908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return blitter; 9928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 99482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com/////////////////////////////////////////////////////////////////////////////// 9958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 996ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgclass SkTransparentShaderContext : public SkShader::Context { 997ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgpublic: 998ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org SkTransparentShaderContext(const SkShader& shader, const SkShader::ContextRec& rec) 999ca76c55d60dfe041e30e210d41fa0feb7fb54a1fscroggo // Override rec with the identity matrix, so it is guaranteed to be invertible. 1000ca76c55d60dfe041e30e210d41fa0feb7fb54a1fscroggo : INHERITED(shader, SkShader::ContextRec(*rec.fDevice, *rec.fPaint, SkMatrix::I())) {} 1001ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org 1002ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org virtual void shadeSpan(int x, int y, SkPMColor colors[], int count) SK_OVERRIDE { 1003ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org sk_bzero(colors, count * sizeof(SkPMColor)); 1004ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 1005ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org 1006ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.orgprivate: 1007ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org typedef SkShader::Context INHERITED; 1008ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org}; 1009ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org 101087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint, 101187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext) 101287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org : INHERITED(device) 101387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org , fShader(paint.getShader()) 101487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org , fShaderContext(shaderContext) { 10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fShader); 101687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(fShaderContext); 10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShader->ref(); 101987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org fShaderFlags = fShaderContext->getFlags(); 10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10225119bdb952025a30f115b9c6a187173956e55097reed@android.comSkShaderBlitter::~SkShaderBlitter() { 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShader->unref(); 10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 102587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 102680116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.orgbool SkShaderBlitter::resetShaderContext(const SkShader::ContextRec& rec) { 102787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Only destroy the old context if we have a new one. We need to ensure to have a 102887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // live context in fShaderContext because the storage is owned by an SkSmallAllocator 102987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // outside of this class. 103087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // The new context will be of the same size as the old one because we use the same 103187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // shader to create it. It is therefore safe to re-use the storage. 103287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org fShaderContext->~Context(); 1033ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org SkShader::Context* ctx = fShader->createContext(rec, (void*)fShaderContext); 1034ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org if (NULL == ctx) { 1035ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org // Need a valid context in fShaderContext's storage, so we can later (or our caller) call 1036ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org // the in-place destructor. 1037ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org SkNEW_PLACEMENT_ARGS(fShaderContext, SkTransparentShaderContext, (*fShader, rec)); 103880116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org return false; 1039ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 104080116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org return true; 104187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 1042