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