1685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 2685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com/* 3685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Copyright 2006 The Android Open Source Project 4685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * 5685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * Use of this source code is governed by a BSD-style license that can be 6685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com * found in the LICENSE file. 7685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com */ 8685cfc0ee13d7c355ae2f4f3d225ad45e945763fepoger@google.com 9bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlitter.h" 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkAntiRun.h" 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColor.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorFilter.h" 14e54ef29a2cc707807a3b5581fc01f49f75a3bf86reed@google.com#include "SkFilterShader.h" 159ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com#include "SkFlattenableBuffers.h" 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMask.h" 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMaskFilter.h" 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkTemplatesPriv.h" 19c29484063de303a04774d87c060434c8b496f7b0reed@google.com#include "SkTLazy.h" 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkUtils.h" 21bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkXfermode.h" 22bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#include "SkString.h" 23bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 244130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.comSkBlitter::~SkBlitter() {} 25bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 269c5343d6390ef1f4d6daee484524d7d616167f20reed@google.combool SkBlitter::isNullBlitter() const { return false; } 279c5343d6390ef1f4d6daee484524d7d616167f20reed@google.com 28919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) { 29bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return NULL; 30bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 31bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 32919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitH(int x, int y, int width) { 332d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unimplemented"); 34bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 35bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 36919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 37919114813d58933c9d9433b141e0222c34b700b1reed@google.com const int16_t runs[]) { 382d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unimplemented"); 39bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 40bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 41919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 42919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (alpha == 255) { 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->blitRect(x, y, 1, height); 44919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int16_t runs[2]; 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com runs[0] = 1; 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com runs[1] = 0; 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 49919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (--height >= 0) { 50bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->blitAntiH(x, y++, &alpha, runs); 51919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 52bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 53bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 55919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitRect(int x, int y, int width, int height) { 560182ae97e654d95b82ce36e34c7049e949427298tomhudson@google.com SkASSERT(width > 0); 57919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (--height >= 0) { 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->blitH(x, y++, width); 59919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 626130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com/// Default implementation doesn't check for any easy optimizations 636130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com/// such as alpha == 0 or 255; also uses blitV(), which some subclasses 646130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com/// may not support. 656130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.comvoid SkBlitter::blitAntiRect(int x, int y, int width, int height, 666130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 6767b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com this->blitV(x++, y, height, leftAlpha); 680182ae97e654d95b82ce36e34c7049e949427298tomhudson@google.com if (width > 0) { 6967b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com this->blitRect(x, y, width, height); 7067b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com x += width; 7167b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com } 7267b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com this->blitV(x, y, height, rightAlpha); 736130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com} 746130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 75bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com////////////////////////////////////////////////////////////////////////////// 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 77919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic inline void bits_to_runs(SkBlitter* blitter, int x, int y, 78919114813d58933c9d9433b141e0222c34b700b1reed@google.com const uint8_t bits[], 79919114813d58933c9d9433b141e0222c34b700b1reed@google.com U8CPU left_mask, int rowBytes, 80919114813d58933c9d9433b141e0222c34b700b1reed@google.com U8CPU right_mask) { 81bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int inFill = 0; 82bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int pos = 0; 83bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 84919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (--rowBytes >= 0) { 85bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned b = *bits++ & left_mask; 86919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (rowBytes == 0) { 87bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b &= right_mask; 88919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 90919114813d58933c9d9433b141e0222c34b700b1reed@google.com for (unsigned test = 0x80; test != 0; test >>= 1) { 91919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (b & test) { 92919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (!inFill) { 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com pos = x; 94bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com inFill = true; 95bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 96919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 97919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (inFill) { 98bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter->blitH(pos, y, x - pos); 99bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com inFill = false; 100bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x += 1; 103bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com left_mask = 0xFF; 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // final cleanup 108919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (inFill) { 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter->blitH(pos, y, x - pos); 110919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 113919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 114bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(mask.fBounds.contains(clip)); 115bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 116919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (mask.fFormat == SkMask::kBW_Format) { 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int cx = clip.fLeft; 118bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int cy = clip.fTop; 119bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int maskLeft = mask.fBounds.fLeft; 120bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int mask_rowBytes = mask.fRowBytes; 121bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int height = clip.height(); 122bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 123bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint8_t* bits = mask.getAddr1(cx, cy); 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 125919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (cx == maskLeft && clip.fRight == mask.fBounds.fRight) { 126919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (--height >= 0) { 127bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bits_to_runs(this, cx, cy, bits, 0xFF, mask_rowBytes, 0xFF); 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bits += mask_rowBytes; 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cy += 1; 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 131919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int left_edge = cx - maskLeft; 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(left_edge >= 0); 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int rite_edge = clip.fRight - maskLeft; 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(rite_edge > left_edge); 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int left_mask = 0xFF >> (left_edge & 7); 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int rite_mask = 0xFF << (8 - (rite_edge & 7)); 139bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3); 140bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 141b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com // check for empty right mask, so we don't read off the end (or go slower than we need to) 142919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (rite_mask == 0) { 143bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(full_runs >= 0); 144bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com full_runs -= 1; 145bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com rite_mask = 0xFF; 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 147919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (left_mask == 0xFF) { 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com full_runs -= 1; 149919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 151b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com // back up manually so we can keep in sync with our byte-aligned src 152b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com // have cx reflect our actual starting x-coord 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cx -= left_edge & 7; 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 155919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (full_runs < 0) { 156bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT((left_mask & rite_mask) != 0); 157919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (--height >= 0) { 158bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bits_to_runs(this, cx, cy, bits, left_mask, 1, rite_mask); 159bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bits += mask_rowBytes; 160bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cy += 1; 161bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 162919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 163919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (--height >= 0) { 164b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com bits_to_runs(this, cx, cy, bits, left_mask, full_runs + 2, rite_mask); 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bits += mask_rowBytes; 166bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com cy += 1; 167bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 170919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 171bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int width = clip.width(); 172bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAutoSTMalloc<64, int16_t> runStorage(width + 1); 173bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int16_t* runs = runStorage.get(); 174e2961f787751b880e535e893ca068af71218ba32reed@google.com const uint8_t* aa = mask.getAddr8(clip.fLeft, clip.fTop); 175bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 176bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_memset16((uint16_t*)runs, 1, width); 177bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com runs[width] = 0; 178bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 179bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int height = clip.height(); 180bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int y = clip.fTop; 181919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (--height >= 0) { 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->blitAntiH(clip.fLeft, y, aa, runs); 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa += mask.fRowBytes; 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com y += 1; 185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 187bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////// these guys are not virtual, just a helpers 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBlitter::blitMaskRegion(const SkMask& mask, const SkRegion& clip) { 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (clip.quickReject(mask.fBounds)) { 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 195919114813d58933c9d9433b141e0222c34b700b1reed@google.com 196bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Cliperator clipper(clip, mask.fBounds); 197919114813d58933c9d9433b141e0222c34b700b1reed@google.com 198bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (!clipper.done()) { 199bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& cr = clipper.rect(); 200bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->blitMask(mask, cr); 201bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com clipper.next(); 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBlitter::blitRectRegion(const SkIRect& rect, const SkRegion& clip) { 206bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Cliperator clipper(clip, rect); 207919114813d58933c9d9433b141e0222c34b700b1reed@google.com 208bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (!clipper.done()) { 209bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& cr = clipper.rect(); 210bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 211bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com clipper.next(); 212bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 213bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 214bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 215bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comvoid SkBlitter::blitRegion(const SkRegion& clip) { 216bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Iterator iter(clip); 217919114813d58933c9d9433b141e0222c34b700b1reed@google.com 218bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com while (!iter.done()) { 219bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& cr = iter.rect(); 220bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 221bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com iter.next(); 222bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 223bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 225919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 226bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 227919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitH(int x, int y, int width) {} 228bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 229919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitAntiH(int x, int y, const SkAlpha antialias[], 230919114813d58933c9d9433b141e0222c34b700b1reed@google.com const int16_t runs[]) {} 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 232919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitV(int x, int y, int height, SkAlpha alpha) {} 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 234919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitRect(int x, int y, int width, int height) {} 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 236919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkNullBlitter::blitMask(const SkMask& mask, const SkIRect& clip) {} 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 238919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) { 239bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return NULL; 240bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 241bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2429c5343d6390ef1f4d6daee484524d7d616167f20reed@google.combool SkNullBlitter::isNullBlitter() const { return true; } 2439c5343d6390ef1f4d6daee484524d7d616167f20reed@google.com 244919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 245bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 246919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic int compute_anti_width(const int16_t runs[]) { 247bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int width = 0; 248919114813d58933c9d9433b141e0222c34b700b1reed@google.com 249919114813d58933c9d9433b141e0222c34b700b1reed@google.com for (;;) { 250bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int count = runs[0]; 251919114813d58933c9d9433b141e0222c34b700b1reed@google.com 252bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(count >= 0); 253919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (count == 0) { 254bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com break; 255919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 256bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com width += count; 257bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com runs += count; 258bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 259bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return width; 260bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 261bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 262919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic inline bool y_in_rect(int y, const SkIRect& rect) { 263bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (unsigned)(y - rect.fTop) < (unsigned)rect.height(); 264bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 265bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 266919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic inline bool x_in_rect(int x, const SkIRect& rect) { 267bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (unsigned)(x - rect.fLeft) < (unsigned)rect.width(); 268bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 269bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 270919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitH(int left, int y, int width) { 271bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(width > 0); 272bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 273919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (!y_in_rect(y, fClipRect)) { 274bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 275919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 276bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 277bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int right = left + width; 278bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 279919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (left < fClipRect.fLeft) { 280bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com left = fClipRect.fLeft; 281919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 282919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (right > fClipRect.fRight) { 283bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com right = fClipRect.fRight; 284919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 285bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 286bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com width = right - left; 287919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (width > 0) { 288bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitH(left, y, width); 289919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 290bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 291bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 292919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitAntiH(int left, int y, const SkAlpha aa[], 293919114813d58933c9d9433b141e0222c34b700b1reed@google.com const int16_t runs[]) { 294919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (!y_in_rect(y, fClipRect) || left >= fClipRect.fRight) { 295bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 296919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 297bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 298bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int x0 = left; 299bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int x1 = left + compute_anti_width(runs); 300bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 301919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (x1 <= fClipRect.fLeft) { 302bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 303919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 304bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 305bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(x0 < x1); 306919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (x0 < fClipRect.fLeft) { 307bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int dx = fClipRect.fLeft - x0; 308bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, dx); 309bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com runs += dx; 310bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa += dx; 311bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x0 = fClipRect.fLeft; 312bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 313bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 314bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 315919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (x1 > fClipRect.fRight) { 316bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x1 = fClipRect.fRight; 317bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAlphaRuns::BreakAt((int16_t*)runs, (uint8_t*)aa, x1 - x0); 318bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((int16_t*)runs)[x1 - x0] = 0; 319bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 320bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 321bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(x0 < x1 && runs[x1 - x0] == 0); 322bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(compute_anti_width(runs) == x1 - x0); 323bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 324bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitAntiH(x0, y, aa, runs); 325bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 326bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 327919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 328bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(height > 0); 329bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 330919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (!x_in_rect(x, fClipRect)) { 331bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 332919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 333bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 334bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int y0 = y; 335bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int y1 = y + height; 336bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 337919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (y0 < fClipRect.fTop) { 338bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com y0 = fClipRect.fTop; 339919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 340919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (y1 > fClipRect.fBottom) { 341bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com y1 = fClipRect.fBottom; 342919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 343bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 344919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (y0 < y1) { 345bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitV(x, y0, y1 - y0, alpha); 346919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 347bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 348bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 349919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitRect(int left, int y, int width, int height) { 350bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect r; 351bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 352bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r.set(left, y, left + width, y + height); 353919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (r.intersect(fClipRect)) { 354bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 355919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 356bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 357bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 3586130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.comvoid SkRectClipBlitter::blitAntiRect(int left, int y, int width, int height, 3596130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 3606130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkIRect r; 3616130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 3626130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // The *true* width of the rectangle blitted is width+2: 3636130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com r.set(left, y, left + width + 2, y + height); 3646130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (r.intersect(fClipRect)) { 3656130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (r.fLeft != left) { 3666130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(r.fLeft > left); 3676130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com leftAlpha = 255; 3686130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 3696130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (r.fRight != left + width + 2) { 3706130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(r.fRight < left + width + 2); 3716130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com rightAlpha = 255; 3726130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 3736130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (255 == leftAlpha && 255 == rightAlpha) { 3746130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 3756130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } else if (1 == r.width()) { 3766130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (r.fLeft == left) { 3776130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), leftAlpha); 3786130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } else { 3796130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(r.fLeft == left + width + 1); 3806130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), rightAlpha); 3816130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 3826130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } else { 3836130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 3846130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com leftAlpha, rightAlpha); 3856130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 3866130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 3876130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com} 3886130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 389919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRectClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 390bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(mask.fBounds.contains(clip)); 391bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 392bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect r = clip; 393bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 394919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (r.intersect(fClipRect)) { 395bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitMask(mask, r); 396919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 397bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 399919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkRectClipBlitter::justAnOpaqueColor(uint32_t* value) { 400bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fBlitter->justAnOpaqueColor(value); 401bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 402bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 403919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 405919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitH(int x, int y, int width) { 406bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Spanerator span(*fRgn, y, x, x + width); 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int left, right; 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 409919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (span.next(&left, &right)) { 410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(left < right); 411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitH(left, y, right - left); 412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 415919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitAntiH(int x, int y, const SkAlpha aa[], 416919114813d58933c9d9433b141e0222c34b700b1reed@google.com const int16_t runs[]) { 417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int width = compute_anti_width(runs); 418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Spanerator span(*fRgn, y, x, x + width); 419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int left, right; 420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(const SkIRect& bounds = fRgn->getBounds();) 421919114813d58933c9d9433b141e0222c34b700b1reed@google.com 422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int prevRite = x; 423919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (span.next(&left, &right)) { 424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(x <= left); 425bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(left < right); 426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(left >= bounds.fLeft && right <= bounds.fRight); 427919114813d58933c9d9433b141e0222c34b700b1reed@google.com 428bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAlphaRuns::Break((int16_t*)runs, (uint8_t*)aa, left - x, right - left); 429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now zero before left 431919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (left > prevRite) { 432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int index = prevRite - x; 433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((uint8_t*)aa)[index] = 0; // skip runs after right 434bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((int16_t*)runs)[index] = SkToS16(left - prevRite); 435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 436919114813d58933c9d9433b141e0222c34b700b1reed@google.com 437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com prevRite = right; 438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 439919114813d58933c9d9433b141e0222c34b700b1reed@google.com 440919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (prevRite > x) { 441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((int16_t*)runs)[prevRite - x] = 0; 442919114813d58933c9d9433b141e0222c34b700b1reed@google.com 443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (x < 0) { 444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int skip = runs[0]; 445bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(skip >= -x); 446bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa += skip; 447bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com runs += skip; 448bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x += skip; 449bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 450bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitAntiH(x, y, aa, runs); 451bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 452bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 453bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 454919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitV(int x, int y, int height, SkAlpha alpha) { 455bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect bounds; 456bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bounds.set(x, y, x + 1, y + height); 457bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 458bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Cliperator iter(*fRgn, bounds); 459bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 460919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (!iter.done()) { 461bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& r = iter.rect(); 462bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(bounds.contains(r)); 463bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 464bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitV(x, r.fTop, r.height(), alpha); 465bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com iter.next(); 466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 468bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 469919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitRect(int x, int y, int width, int height) { 470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect bounds; 471bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com bounds.set(x, y, x + width, y + height); 472bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 473bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Cliperator iter(*fRgn, bounds); 474bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 475919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (!iter.done()) { 476bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& r = iter.rect(); 477bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(bounds.contains(r)); 478bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 479bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 480bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com iter.next(); 481bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 482bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 483bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 4846130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.comvoid SkRgnClipBlitter::blitAntiRect(int x, int y, int width, int height, 4856130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkAlpha leftAlpha, SkAlpha rightAlpha) { 4866130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // The *true* width of the rectangle to blit is width + 2 4876130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkIRect bounds; 4886130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com bounds.set(x, y, x + width + 2, y + height); 4896130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 4906130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkRegion::Cliperator iter(*fRgn, bounds); 4916130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 4926130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com while (!iter.done()) { 4936130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com const SkIRect& r = iter.rect(); 4946130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(bounds.contains(r)); 4956130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(r.fLeft >= x); 496d5a4a434a91cf65e53807785ac6a3d3747726fcetomhudson@google.com SkASSERT(r.fRight <= x + width + 2); 4976130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 4986130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkAlpha effectiveLeftAlpha = (r.fLeft == x) ? leftAlpha : 255; 4996130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkAlpha effectiveRightAlpha = (r.fRight == x + width + 2) ? 5006130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com rightAlpha : 255; 5016130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 5026130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (255 == effectiveLeftAlpha && 255 == effectiveRightAlpha) { 5036130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fBlitter->blitRect(r.fLeft, r.fTop, r.width(), r.height()); 5046130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } else if (1 == r.width()) { 5056130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (r.fLeft == x) { 506935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), 5076130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com effectiveLeftAlpha); 5086130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } else { 5096130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(r.fLeft == x + width + 1); 5106130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fBlitter->blitV(r.fLeft, r.fTop, r.height(), 5116130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com effectiveRightAlpha); 5126130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 5136130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } else { 5146130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fBlitter->blitAntiRect(r.fLeft, r.fTop, r.width() - 2, r.height(), 5156130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com effectiveLeftAlpha, effectiveRightAlpha); 5166130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 5176130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com iter.next(); 5186130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 5196130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com} 5206130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 5216130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 522919114813d58933c9d9433b141e0222c34b700b1reed@google.comvoid SkRgnClipBlitter::blitMask(const SkMask& mask, const SkIRect& clip) { 523bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(mask.fBounds.contains(clip)); 524bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 525bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkRegion::Cliperator iter(*fRgn, clip); 526bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& r = iter.rect(); 527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlitter* blitter = fBlitter; 528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 529919114813d58933c9d9433b141e0222c34b700b1reed@google.com while (!iter.done()) { 530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter->blitMask(mask, r); 531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com iter.next(); 532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 535919114813d58933c9d9433b141e0222c34b700b1reed@google.comconst SkBitmap* SkRgnClipBlitter::justAnOpaqueColor(uint32_t* value) { 536bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return fBlitter->justAnOpaqueColor(value); 537bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 538bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 539919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 540bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 541919114813d58933c9d9433b141e0222c34b700b1reed@google.comSkBlitter* SkBlitterClipper::apply(SkBlitter* blitter, const SkRegion* clip, 542919114813d58933c9d9433b141e0222c34b700b1reed@google.com const SkIRect* ir) { 543919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (clip) { 544bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect& clipR = clip->getBounds(); 545bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 546919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (clip->isEmpty() || (ir && !SkIRect::Intersects(clipR, *ir))) { 547bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = &fNullBlitter; 548919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else if (clip->isRect()) { 549919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (ir == NULL || !clipR.contains(*ir)) { 550bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRectBlitter.init(blitter, clipR); 551bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = &fRectBlitter; 552bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 553919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 554bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRgnBlitter.init(blitter, clip); 555bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = &fRgnBlitter; 556bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 557bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 558bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return blitter; 559bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 560bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 561919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 562bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 563bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorShader.h" 564bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkColorPriv.h" 565bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 566bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass Sk3DShader : public SkShader { 567bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 568919114813d58933c9d9433b141e0222c34b700b1reed@google.com Sk3DShader(SkShader* proxy) : fProxy(proxy) { 569919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkSafeRef(proxy); 570bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMask = NULL; 571bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 572919114813d58933c9d9433b141e0222c34b700b1reed@google.com 573919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual ~Sk3DShader() { 574919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkSafeUnref(fProxy); 575bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 576919114813d58933c9d9433b141e0222c34b700b1reed@google.com 577bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void setMask(const SkMask* mask) { fMask = mask; } 578bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 579919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual bool setContext(const SkBitmap& device, const SkPaint& paint, 580bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com const SkMatrix& matrix) SK_OVERRIDE { 581bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com if (!this->INHERITED::setContext(device, paint, matrix)) { 582bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com return false; 583bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com } 584919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (fProxy) { 585bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com if (!fProxy->setContext(device, paint, matrix)) { 586bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com // must keep our set/end context calls balanced 587bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com this->INHERITED::endContext(); 588bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com return false; 589bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com } 590919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 591bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fPMColor = SkPreMultiplyColor(paint.getColor()); 592bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 593bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com return true; 594bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com } 5951fa5c44bd02b1cb42ad2fcc20ab1bb06d9ca7fbbskia.committer@gmail.com 596bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com virtual void endContext() SK_OVERRIDE { 597bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com if (fProxy) { 598bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com fProxy->endContext(); 599bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com } 600bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com this->INHERITED::endContext(); 601bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 602919114813d58933c9d9433b141e0222c34b700b1reed@google.com 603bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { 604919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (fProxy) { 605bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProxy->shadeSpan(x, y, span, count); 606919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 607bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 608919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (fMask == NULL) { 609919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (fProxy == NULL) { 610bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_memset32(span, fPMColor, count); 611919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 612bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 613bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 614bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 615bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fMask->fBounds.contains(x, y)); 616bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fMask->fBounds.contains(x + count - 1, y)); 617bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 618bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com size_t size = fMask->computeImageSize(); 619e2961f787751b880e535e893ca068af71218ba32reed@google.com const uint8_t* alpha = fMask->getAddr8(x, y); 620bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint8_t* mulp = alpha + size; 621bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const uint8_t* addp = mulp + size; 622bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 623919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (fProxy) { 624919114813d58933c9d9433b141e0222c34b700b1reed@google.com for (int i = 0; i < count; i++) { 625919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (alpha[i]) { 626bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPMColor c = span[i]; 627919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (c) { 628bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned a = SkGetPackedA32(c); 629bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned r = SkGetPackedR32(c); 630bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned g = SkGetPackedG32(c); 631bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned b = SkGetPackedB32(c); 632bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 633bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned mul = SkAlpha255To256(mulp[i]); 634bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned add = addp[i]; 635bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 636bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com r = SkFastMin32(SkAlphaMul(r, mul) + add, a); 637bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com g = SkFastMin32(SkAlphaMul(g, mul) + add, a); 638bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com b = SkFastMin32(SkAlphaMul(b, mul) + add, a); 639bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 640bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com span[i] = SkPackARGB32(a, r, g, b); 641bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 642919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 643bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com span[i] = 0; 644919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 645bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 646919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { // color 647bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned a = SkGetPackedA32(fPMColor); 648bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned r = SkGetPackedR32(fPMColor); 649bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned g = SkGetPackedG32(fPMColor); 650bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned b = SkGetPackedB32(fPMColor); 651919114813d58933c9d9433b141e0222c34b700b1reed@google.com for (int i = 0; i < count; i++) { 652919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (alpha[i]) { 653bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned mul = SkAlpha255To256(mulp[i]); 654bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned add = addp[i]; 655bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 656bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com span[i] = SkPackARGB32( a, 657919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkFastMin32(SkAlphaMul(r, mul) + add, a), 658919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkFastMin32(SkAlphaMul(g, mul) + add, a), 659919114813d58933c9d9433b141e0222c34b700b1reed@google.com SkFastMin32(SkAlphaMul(b, mul) + add, a)); 660919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 661bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com span[i] = 0; 662919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 663bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 664bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 665bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 666919114813d58933c9d9433b141e0222c34b700b1reed@google.com 667bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#ifdef SK_DEVELOPER 668bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com virtual void toString(SkString* str) const SK_OVERRIDE { 669bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append("Sk3DShader: ("); 670bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 671bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com if (NULL != fProxy) { 672bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append("Proxy: "); 673bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com fProxy->toString(str); 674bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } 675bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 676bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com this->INHERITED::toString(str); 677bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 678bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com str->append(")"); 679bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com } 680bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com#endif 681bc0c7b3fc892adc21eeac2d56b02a525ee811fdbrobertphillips@google.com 6824d1d95c61576960796347e1dd5006d878e9d2dc0djsollen@google.com SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader) 6834d1d95c61576960796347e1dd5006d878e9d2dc0djsollen@google.com 684bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprotected: 685cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.com Sk3DShader(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { 6865e901c8c1bea70be7fc2c39112746891e38f72c9reed@google.com fProxy = buffer.readShader(); 6879ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com fPMColor = buffer.readColor(); 688bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMask = NULL; 689bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 690919114813d58933c9d9433b141e0222c34b700b1reed@google.com 691cd2e444e946f5cfec4723f5bc46e9487d82e8e54djsollen@google.com virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { 692bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->INHERITED::flatten(buffer); 693bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com buffer.writeFlattenable(fProxy); 6949ce78f26f529fd3e10a3eb4f044bc3f0037ead56djsollen@google.com buffer.writeColor(fPMColor); 695bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 696919114813d58933c9d9433b141e0222c34b700b1reed@google.com 697bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 698bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkShader* fProxy; 699bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkPMColor fPMColor; 700bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkMask* fMask; 701bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 702bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com typedef SkShader INHERITED; 703bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 704bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 705bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass Sk3DBlitter : public SkBlitter { 706bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 707bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk3DBlitter(SkBlitter* proxy, Sk3DShader* shader, void (*killProc)(void*)) 708919114813d58933c9d9433b141e0222c34b700b1reed@google.com : fProxy(proxy), f3DShader(shader), fKillProc(killProc) { 709bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shader->ref(); 710bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 711919114813d58933c9d9433b141e0222c34b700b1reed@google.com 712919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual ~Sk3DBlitter() { 713bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com f3DShader->unref(); 714bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fKillProc(fProxy); 715bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 716bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 717919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual void blitH(int x, int y, int width) { 718bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProxy->blitH(x, y, width); 719bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 720919114813d58933c9d9433b141e0222c34b700b1reed@google.com 721919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 722919114813d58933c9d9433b141e0222c34b700b1reed@google.com const int16_t runs[]) { 723bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProxy->blitAntiH(x, y, antialias, runs); 724bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 725919114813d58933c9d9433b141e0222c34b700b1reed@google.com 726919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual void blitV(int x, int y, int height, SkAlpha alpha) { 727bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProxy->blitV(x, y, height, alpha); 728bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 729919114813d58933c9d9433b141e0222c34b700b1reed@google.com 730919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual void blitRect(int x, int y, int width, int height) { 731bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProxy->blitRect(x, y, width, height); 732bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 733919114813d58933c9d9433b141e0222c34b700b1reed@google.com 734919114813d58933c9d9433b141e0222c34b700b1reed@google.com virtual void blitMask(const SkMask& mask, const SkIRect& clip) { 735919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (mask.fFormat == SkMask::k3D_Format) { 736bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com f3DShader->setMask(&mask); 737bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 738bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((SkMask*)&mask)->fFormat = SkMask::kA8_Format; 739bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProxy->blitMask(mask, clip); 740bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((SkMask*)&mask)->fFormat = SkMask::k3D_Format; 741bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 742bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com f3DShader->setMask(NULL); 743919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 744bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProxy->blitMask(mask, clip); 745919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 746bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 747919114813d58933c9d9433b141e0222c34b700b1reed@google.com 748bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 749bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlitter* fProxy; 750bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk3DShader* f3DShader; 751bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void (*fKillProc)(void*); 752bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 753bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 754919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 755bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 756bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkCoreBlitters.h" 757bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 758bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SkAutoCallProc { 759bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 760bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com typedef void (*Proc)(void*); 761919114813d58933c9d9433b141e0222c34b700b1reed@google.com 762bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAutoCallProc(void* obj, Proc proc) 763919114813d58933c9d9433b141e0222c34b700b1reed@google.com : fObj(obj), fProc(proc) {} 764919114813d58933c9d9433b141e0222c34b700b1reed@google.com 765919114813d58933c9d9433b141e0222c34b700b1reed@google.com ~SkAutoCallProc() { 766919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (fObj && fProc) { 767bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fProc(fObj); 768919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 769bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 770919114813d58933c9d9433b141e0222c34b700b1reed@google.com 771bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* get() const { return fObj; } 772919114813d58933c9d9433b141e0222c34b700b1reed@google.com 773919114813d58933c9d9433b141e0222c34b700b1reed@google.com void* detach() { 774bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* obj = fObj; 775bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fObj = NULL; 776bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return obj; 777bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 778919114813d58933c9d9433b141e0222c34b700b1reed@google.com 779bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 780bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void* fObj; 781bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Proc fProc; 782bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 7837345112995b14b457ec7d67e3d1211dd7a7597b0commit-bot@chromium.org#define SkAutoCallProc(...) SK_REQUIRE_LOCAL_VAR(SkAutoCallProc) 784bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 785919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic void destroy_blitter(void* blitter) { 786bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com ((SkBlitter*)blitter)->~SkBlitter(); 787bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 788bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 789919114813d58933c9d9433b141e0222c34b700b1reed@google.comstatic void delete_blitter(void* blitter) { 790bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDELETE((SkBlitter*)blitter); 791bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 792bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 793155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.comstatic bool just_solid_color(const SkPaint& paint) { 794155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com if (paint.getAlpha() == 0xFF && paint.getColorFilter() == NULL) { 795155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com SkShader* shader = paint.getShader(); 796155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com if (NULL == shader || 797155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com (shader->getFlags() & SkShader::kOpaqueAlpha_Flag)) { 798155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return true; 799155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 800155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 801155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return false; 802155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com} 803919114813d58933c9d9433b141e0222c34b700b1reed@google.com 804155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com/** By analyzing the paint (with an xfermode), we may decide we can take 805155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com special action. This enum lists our possible actions 806155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com */ 807155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.comenum XferInterp { 808155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com kNormal_XferInterp, // no special interpretation, draw normally 809155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com kSrcOver_XferInterp, // draw as if in srcover mode 810155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com kSkipDrawing_XferInterp // draw nothing 811155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com}; 812155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com 813155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.comstatic XferInterp interpret_xfermode(const SkPaint& paint, SkXfermode* xfer, 814155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com SkBitmap::Config deviceConfig) { 8154130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com SkXfermode::Mode mode; 816919114813d58933c9d9433b141e0222c34b700b1reed@google.com 8177152b7b11a143fdfb7eb8d185df0ce124d853011mike@reedtribe.org if (SkXfermode::AsMode(xfer, &mode)) { 818155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com switch (mode) { 8194130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com case SkXfermode::kSrc_Mode: 820155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com if (just_solid_color(paint)) { 821155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return kSrcOver_XferInterp; 822155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 823155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com break; 8244130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com case SkXfermode::kDst_Mode: 825155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return kSkipDrawing_XferInterp; 8264130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com case SkXfermode::kSrcOver_Mode: 827155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return kSrcOver_XferInterp; 8284130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com case SkXfermode::kDstOver_Mode: 829155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com if (SkBitmap::kRGB_565_Config == deviceConfig) { 830155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return kSkipDrawing_XferInterp; 831155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 832155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com break; 8334130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com case SkXfermode::kSrcIn_Mode: 834155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com if (SkBitmap::kRGB_565_Config == deviceConfig && 835155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com just_solid_color(paint)) { 836155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return kSrcOver_XferInterp; 837155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 838155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com break; 8394130a1b1e00dd2d3bd156af9af42e1f0b2585a8freed@android.com case SkXfermode::kDstIn_Mode: 840155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com if (just_solid_color(paint)) { 841155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return kSkipDrawing_XferInterp; 842155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 843155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com break; 844155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com default: 845155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com break; 846155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 847155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 848155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return kNormal_XferInterp; 849155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com} 850155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com 851bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkBlitter* SkBlitter::Choose(const SkBitmap& device, 852bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkMatrix& matrix, 85315477316c7e77f3adf05b922dfc144237bde141dreed@google.com const SkPaint& origPaint, 8540ae872fff20fdac8efed4cac5894a392360bd919reed@google.com void* storage, size_t storageSize, 8550ae872fff20fdac8efed4cac5894a392360bd919reed@google.com bool drawCoverage) { 856bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(storageSize == 0 || storage != NULL); 857bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 858bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlitter* blitter = NULL; 859bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 860bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // which check, in case we're being called by a client with a dummy device 861bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // (e.g. they have a bounder that always aborts the draw) 8620ae872fff20fdac8efed4cac5894a392360bd919reed@google.com if (SkBitmap::kNo_Config == device.config() || 8630ae872fff20fdac8efed4cac5894a392360bd919reed@google.com (drawCoverage && (SkBitmap::kA8_Config != device.config()))) { 864bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); 865bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return blitter; 866bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 867bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 868c29484063de303a04774d87c060434c8b496f7b0reed@google.com SkShader* shader = origPaint.getShader(); 869c29484063de303a04774d87c060434c8b496f7b0reed@google.com SkColorFilter* cf = origPaint.getColorFilter(); 870c29484063de303a04774d87c060434c8b496f7b0reed@google.com SkXfermode* mode = origPaint.getXfermode(); 871bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com Sk3DShader* shader3D = NULL; 872c29484063de303a04774d87c060434c8b496f7b0reed@google.com 873d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 874935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 875c29484063de303a04774d87c060434c8b496f7b0reed@google.com if (origPaint.getMaskFilter() != NULL && 876c29484063de303a04774d87c060434c8b496f7b0reed@google.com origPaint.getMaskFilter()->getFormat() == SkMask::k3D_Format) { 877bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shader3D = SkNEW_ARGS(Sk3DShader, (shader)); 878c29484063de303a04774d87c060434c8b496f7b0reed@google.com // we know we haven't initialized lazyPaint yet, so just do it 879d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com paint.writable()->setShader(shader3D)->unref(); 880bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com shader = shader3D; 881bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 882bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 883155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com if (NULL != mode) { 884c29484063de303a04774d87c060434c8b496f7b0reed@google.com switch (interpret_xfermode(*paint, mode, device.config())) { 885155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com case kSrcOver_XferInterp: 886155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com mode = NULL; 887d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com paint.writable()->setXfermode(NULL); 888155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com break; 889155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com case kSkipDrawing_XferInterp: 890155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); 891155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com return blitter; 892155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com default: 893155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com break; 894155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 895155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com } 896155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com 897e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com /* 898e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com * If the xfermode is CLEAR, then we can completely ignore the installed 899e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com * color/shader/colorfilter, and just pretend we're SRC + color==0. This 900e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com * will fall into our optimizations for SRC mode. 901e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com */ 902e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) { 903e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com SkPaint* p = paint.writable(); 904e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com shader = p->setShader(NULL); 905e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com cf = p->setColorFilter(NULL); 906e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com mode = p->setXfermodeMode(SkXfermode::kSrc_Mode); 907e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com p->setColor(0); 908e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com } 909e86b0de924a4d5c053aae451f4b41fb42aa9a921reed@google.com 91015477316c7e77f3adf05b922dfc144237bde141dreed@google.com if (NULL == shader) { 91115477316c7e77f3adf05b922dfc144237bde141dreed@google.com if (mode) { 91215477316c7e77f3adf05b922dfc144237bde141dreed@google.com // xfermodes (and filters) require shaders for our current blitters 91315477316c7e77f3adf05b922dfc144237bde141dreed@google.com shader = SkNEW(SkColorShader); 914d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com paint.writable()->setShader(shader)->unref(); 91515477316c7e77f3adf05b922dfc144237bde141dreed@google.com } else if (cf) { 91615477316c7e77f3adf05b922dfc144237bde141dreed@google.com // if no shader && no xfermode, we just apply the colorfilter to 91715477316c7e77f3adf05b922dfc144237bde141dreed@google.com // our color and move on. 918d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com SkPaint* writablePaint = paint.writable(); 919d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com writablePaint->setColor(cf->filterColor(paint->getColor())); 920d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com writablePaint->setColorFilter(NULL); 92115477316c7e77f3adf05b922dfc144237bde141dreed@google.com cf = NULL; 92215477316c7e77f3adf05b922dfc144237bde141dreed@google.com } 923bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 924919114813d58933c9d9433b141e0222c34b700b1reed@google.com 92515477316c7e77f3adf05b922dfc144237bde141dreed@google.com if (cf) { 926bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(shader); 92715477316c7e77f3adf05b922dfc144237bde141dreed@google.com shader = SkNEW_ARGS(SkFilterShader, (shader, cf)); 928d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com paint.writable()->setShader(shader)->unref(); 929ad6f8bba9429d18d5974f0716dc2113b8fb73001reed@android.com // blitters should ignore the presence/absence of a filter, since 930ad6f8bba9429d18d5974f0716dc2113b8fb73001reed@android.com // if there is one, the shader will take care of it. 931bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 932919114813d58933c9d9433b141e0222c34b700b1reed@google.com 933bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com /* 934bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com * We need to have balanced calls to the shader: 935bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com * setContext 936bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com * endContext 937bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com * We make the first call here, in case it fails we can abort the draw. 938bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com * The endContext() call is made by the blitter (assuming setContext did 939bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com * not fail) in its destructor. 940bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com */ 941c29484063de303a04774d87c060434c8b496f7b0reed@google.com if (shader && !shader->setContext(device, *paint, matrix)) { 942bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); 943bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com return blitter; 944bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 945bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 9467a59bd231c10eb208b4a4a1633dd301f516bf1bbskia.committer@gmail.com 947bb6a0d330cd7dae11f94aff99c001d4d1eca0716reed@google.com switch (device.config()) { 948919114813d58933c9d9433b141e0222c34b700b1reed@google.com case SkBitmap::kA8_Config: 9490ae872fff20fdac8efed4cac5894a392360bd919reed@google.com if (drawCoverage) { 9500ae872fff20fdac8efed4cac5894a392360bd919reed@google.com SkASSERT(NULL == shader); 9510ae872fff20fdac8efed4cac5894a392360bd919reed@google.com SkASSERT(NULL == paint->getXfermode()); 9520ae872fff20fdac8efed4cac5894a392360bd919reed@google.com SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Coverage_Blitter, 9530ae872fff20fdac8efed4cac5894a392360bd919reed@google.com storage, storageSize, (device, *paint)); 9540ae872fff20fdac8efed4cac5894a392360bd919reed@google.com } else if (shader) { 955919114813d58933c9d9433b141e0222c34b700b1reed@google.com SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Shader_Blitter, 956c29484063de303a04774d87c060434c8b496f7b0reed@google.com storage, storageSize, (device, *paint)); 957919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 958919114813d58933c9d9433b141e0222c34b700b1reed@google.com SK_PLACEMENT_NEW_ARGS(blitter, SkA8_Blitter, 959c29484063de303a04774d87c060434c8b496f7b0reed@google.com storage, storageSize, (device, *paint)); 960919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 961919114813d58933c9d9433b141e0222c34b700b1reed@google.com break; 962919114813d58933c9d9433b141e0222c34b700b1reed@google.com 963919114813d58933c9d9433b141e0222c34b700b1reed@google.com case SkBitmap::kRGB_565_Config: 964c29484063de303a04774d87c060434c8b496f7b0reed@google.com blitter = SkBlitter_ChooseD565(device, *paint, storage, storageSize); 965919114813d58933c9d9433b141e0222c34b700b1reed@google.com break; 966919114813d58933c9d9433b141e0222c34b700b1reed@google.com 967919114813d58933c9d9433b141e0222c34b700b1reed@google.com case SkBitmap::kARGB_8888_Config: 968919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (shader) { 969919114813d58933c9d9433b141e0222c34b700b1reed@google.com SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Shader_Blitter, 970c29484063de303a04774d87c060434c8b496f7b0reed@google.com storage, storageSize, (device, *paint)); 971c29484063de303a04774d87c060434c8b496f7b0reed@google.com } else if (paint->getColor() == SK_ColorBLACK) { 972919114813d58933c9d9433b141e0222c34b700b1reed@google.com SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Black_Blitter, 973c29484063de303a04774d87c060434c8b496f7b0reed@google.com storage, storageSize, (device, *paint)); 974c29484063de303a04774d87c060434c8b496f7b0reed@google.com } else if (paint->getAlpha() == 0xFF) { 975919114813d58933c9d9433b141e0222c34b700b1reed@google.com SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Opaque_Blitter, 976c29484063de303a04774d87c060434c8b496f7b0reed@google.com storage, storageSize, (device, *paint)); 977919114813d58933c9d9433b141e0222c34b700b1reed@google.com } else { 978919114813d58933c9d9433b141e0222c34b700b1reed@google.com SK_PLACEMENT_NEW_ARGS(blitter, SkARGB32_Blitter, 979c29484063de303a04774d87c060434c8b496f7b0reed@google.com storage, storageSize, (device, *paint)); 980919114813d58933c9d9433b141e0222c34b700b1reed@google.com } 981919114813d58933c9d9433b141e0222c34b700b1reed@google.com break; 982919114813d58933c9d9433b141e0222c34b700b1reed@google.com 983919114813d58933c9d9433b141e0222c34b700b1reed@google.com default: 9842d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("unsupported device config"); 985919114813d58933c9d9433b141e0222c34b700b1reed@google.com SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); 986919114813d58933c9d9433b141e0222c34b700b1reed@google.com break; 987bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 988bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 989919114813d58933c9d9433b141e0222c34b700b1reed@google.com if (shader3D) { 990bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void (*proc)(void*) = ((void*)storage == (void*)blitter) ? destroy_blitter : delete_blitter; 991bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAutoCallProc tmp(blitter, proc); 992bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 993bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = SkNEW_ARGS(Sk3DBlitter, (blitter, shader3D, proc)); 994bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com (void)tmp.detach(); 995bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 996bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return blitter; 997bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 998bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 999919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 1000bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1001bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst uint16_t gMask_0F0F = 0xF0F; 1002bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comconst uint32_t gMask_00FF00FF = 0xFF00FF; 1003bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1004919114813d58933c9d9433b141e0222c34b700b1reed@google.com/////////////////////////////////////////////////////////////////////////////// 1005bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1006bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint) 10079ed8f76ef95fdda704a60a0e787395612bc70443reed@android.com : INHERITED(device) { 1008bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fShader = paint.getShader(); 1009bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(fShader); 1010bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com SkASSERT(fShader->setContextHasBeenCalled()); 1011bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 1012bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fShader->ref(); 10139ed8f76ef95fdda704a60a0e787395612bc70443reed@android.com fShaderFlags = fShader->getFlags(); 1014bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1015bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10169ed8f76ef95fdda704a60a0e787395612bc70443reed@android.comSkShaderBlitter::~SkShaderBlitter() { 1017bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com SkASSERT(fShader->setContextHasBeenCalled()); 1018bd370925b712814b8467a32e31f9d7d921f9f476reed@google.com fShader->endContext(); 1019bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fShader->unref(); 1020bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 1021