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