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 "SkScanPriv.h" 11bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkPath.h" 12bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkMatrix.h" 13bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkBlitter.h" 14bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkRegion.h" 15bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#include "SkAntiRun.h" 16bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 17bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SHIFT 2 18bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define SCALE (1 << SHIFT) 19bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#define MASK (SCALE - 1) 20bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2108d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com/** @file 2282e33805a561c6ce02383453c523749bbfc3e505reed@google.com We have two techniques for capturing the output of the supersampler: 2382e33805a561c6ce02383453c523749bbfc3e505reed@google.com - SUPERMASK, which records a large mask-bitmap 2482e33805a561c6ce02383453c523749bbfc3e505reed@google.com this is often faster for small, complex objects 2582e33805a561c6ce02383453c523749bbfc3e505reed@google.com - RLE, which records a rle-encoded scanline 2682e33805a561c6ce02383453c523749bbfc3e505reed@google.com this is often faster for large objects with big spans 2782e33805a561c6ce02383453c523749bbfc3e505reed@google.com 2808d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com These blitters use two coordinate systems: 2908d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com - destination coordinates, scale equal to the output - often 3008d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com abbreviated with 'i' or 'I' in variable names 3108d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com - supersampled coordinates, scale equal to the output * SCALE 3208d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com 33ef99ee0006a8a0a7e0d90f709591644f422f1b1ereed@google.com Enabling SK_USE_LEGACY_AA_COVERAGE keeps the aa coverage calculations as 34ef99ee0006a8a0a7e0d90f709591644f422f1b1ereed@google.com they were before the fix that unified the output of the RLE and MASK 35ef99ee0006a8a0a7e0d90f709591644f422f1b1ereed@google.com supersamplers. 3682e33805a561c6ce02383453c523749bbfc3e505reed@google.com */ 37ef99ee0006a8a0a7e0d90f709591644f422f1b1ereed@google.com 38d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com//#define FORCE_SUPERMASK 39d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com//#define FORCE_RLE 40c5ae188b05cacee87cf66255c8bfafafef87a1d9reed@google.com//#define SK_USE_LEGACY_AA_COVERAGE 41d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com 42d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com/////////////////////////////////////////////////////////////////////////////// 43bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 4408d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com/// Base class for a single-pass supersampled blitter. 45bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass BaseSuperBlitter : public SkBlitter { 46bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 47bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 48bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkRegion& clip); 49bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 5008d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Must be explicitly defined on subclasses. 51bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual void blitAntiH(int x, int y, const SkAlpha antialias[], 5272de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com const int16_t runs[]) SK_OVERRIDE { 532d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("How did I get here?"); 54bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 5508d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// May not be called on BaseSuperBlitter because it blits out of order. 5672de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com virtual void blitV(int x, int y, int height, SkAlpha alpha) SK_OVERRIDE { 572d7de2d243beab591671dfaf535a637b5d305735tomhudson@google.com SkDEBUGFAIL("How did I get here?"); 58bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 59bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 60bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprotected: 61bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkBlitter* fRealBlitter; 6208d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Current y coordinate, in destination coordinates. 63bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int fCurrIY; 6408d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Widest row of region to be blitted, in destination coordinates. 6508d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int fWidth; 6608d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Leftmost x coordinate in any row, in destination coordinates. 6708d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int fLeft; 6808d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Leftmost x coordinate in any row, in supersampled coordinates. 6908d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int fSuperLeft; 70bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 71bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(int fCurrX;) 7208d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Current y coordinate in supersampled coordinates. 73e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com int fCurrY; 7408d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Initial y coordinate (top of bounds). 7526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com int fTop; 76bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 77bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 78bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comBaseSuperBlitter::BaseSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 79bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkRegion& clip) { 80bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRealBlitter = realBlitter; 81434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 82a7cb04e6879f0f71deee156cce701a13124f6a7ereed@google.com /* 83a7cb04e6879f0f71deee156cce701a13124f6a7ereed@google.com * We use the clip bounds instead of the ir, since we may be asked to 84a7cb04e6879f0f71deee156cce701a13124f6a7ereed@google.com * draw outside of the rect if we're a inverse filltype 85a7cb04e6879f0f71deee156cce701a13124f6a7ereed@google.com */ 86a7cb04e6879f0f71deee156cce701a13124f6a7ereed@google.com const int left = clip.getBounds().fLeft; 87a7cb04e6879f0f71deee156cce701a13124f6a7ereed@google.com const int right = clip.getBounds().fRight; 88935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 89bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fLeft = left; 90bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fSuperLeft = left << SHIFT; 91bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fWidth = right - left; 9226f5a398c38318eb7eab44f72e024ef784d247fareed@google.com#if 0 93bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fCurrIY = -1; 9471f2996e36afd6a2f46ee09942169cee8edd392areed@google.com fCurrY = -1; 9526f5a398c38318eb7eab44f72e024ef784d247fareed@google.com#else 9626f5a398c38318eb7eab44f72e024ef784d247fareed@google.com fTop = ir.fTop; 9726f5a398c38318eb7eab44f72e024ef784d247fareed@google.com fCurrIY = ir.fTop - 1; 9826f5a398c38318eb7eab44f72e024ef784d247fareed@google.com fCurrY = (ir.fTop << SHIFT) - 1; 9926f5a398c38318eb7eab44f72e024ef784d247fareed@google.com#endif 10071f2996e36afd6a2f46ee09942169cee8edd392areed@google.com SkDEBUGCODE(fCurrX = -1;) 101bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 102bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 10308d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com/// Run-length-encoded supersampling antialiased blitter. 104bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass SuperBlitter : public BaseSuperBlitter { 105bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 106bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 107bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkRegion& clip); 108bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 109bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual ~SuperBlitter() { 110bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->flush(); 111bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com sk_free(fRuns.fRuns); 112bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 113bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 11408d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Once fRuns contains a complete supersampled row, flush() blits 11508d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// it out through the wrapped blitter. 116bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com void flush(); 117bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 11808d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Blits a row of pixels, with location and width specified 11908d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// in supersampled coordinates. 12072de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com virtual void blitH(int x, int y, int width) SK_OVERRIDE; 12108d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// Blits a rectangle of pixels, with location and size specified 12208d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com /// in supersampled coordinates. 12372de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE; 124bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 125bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 126bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkAlphaRuns fRuns; 127e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com int fOffsetX; 128bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 129bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 130bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comSuperBlitter::SuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 131bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkRegion& clip) 132bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com : BaseSuperBlitter(realBlitter, ir, clip) { 133bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const int width = fWidth; 134bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 135bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // extra one to store the zero at the end 136bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRuns.fRuns = (int16_t*)sk_malloc_throw((width + 1 + (width + 2)/2) * sizeof(int16_t)); 137bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRuns.fAlpha = (uint8_t*)(fRuns.fRuns + width + 1); 138bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRuns.reset(width); 139e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com 140e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com fOffsetX = 0; 141bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 142bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 143d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.comvoid SuperBlitter::flush() { 14426f5a398c38318eb7eab44f72e024ef784d247fareed@google.com if (fCurrIY >= fTop) { 145d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com if (!fRuns.empty()) { 146bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // SkDEBUGCODE(fRuns.dump();) 147bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRealBlitter->blitAntiH(fLeft, fCurrIY, fRuns.fAlpha, fRuns.fRuns); 148bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRuns.reset(fWidth); 149e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com fOffsetX = 0; 150bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 15126f5a398c38318eb7eab44f72e024ef784d247fareed@google.com fCurrIY = fTop - 1; 152bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkDEBUGCODE(fCurrX = -1;) 153bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 154bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 155bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 15654c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com/** coverage_to_partial_alpha() is being used by SkAlphaRuns, which 15754c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com *accumulates* SCALE pixels worth of "alpha" in [0,(256/SCALE)] 15854c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com to produce a final value in [0, 255] and handles clamping 256->255 15954c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com itself, with the same (alpha - (alpha >> 8)) correction as 16054c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com coverage_to_exact_alpha(). 16154c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com*/ 16254c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.comstatic inline int coverage_to_partial_alpha(int aa) { 163bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa <<= 8 - 2*SHIFT; 164ef99ee0006a8a0a7e0d90f709591644f422f1b1ereed@google.com#ifdef SK_USE_LEGACY_AA_COVERAGE 165bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com aa -= aa >> (8 - SHIFT - 1); 16654c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com#endif 167ef99ee0006a8a0a7e0d90f709591644f422f1b1ereed@google.com return aa; 168bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 169bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 17054c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com/** coverage_to_exact_alpha() is being used by our blitter, which wants 17154c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com a final value in [0, 255]. 17254c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com*/ 1736130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.comstatic inline int coverage_to_exact_alpha(int aa) { 174d5a4a434a91cf65e53807785ac6a3d3747726fcetomhudson@google.com int alpha = (256 >> SHIFT) * aa; 175d5a4a434a91cf65e53807785ac6a3d3747726fcetomhudson@google.com // clamp 256->255 176d5a4a434a91cf65e53807785ac6a3d3747726fcetomhudson@google.com return alpha - (alpha >> 8); 1776130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com} 1786130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 179d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.comvoid SuperBlitter::blitH(int x, int y, int width) { 18072de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com SkASSERT(width > 0); 18172de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 182bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int iy = y >> SHIFT; 183bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(iy >= fCurrIY); 184bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 185bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x -= fSuperLeft; 186bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // hack, until I figure out why my cubics (I think) go beyond the bounds 187d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com if (x < 0) { 188bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com width += x; 189bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x = 0; 190bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 191bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 192bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 193bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(y != fCurrY || x >= fCurrX); 194bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 195e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com SkASSERT(y >= fCurrY); 196e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com if (fCurrY != y) { 197e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com fOffsetX = 0; 198e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com fCurrY = y; 199e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com } 200935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 201d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com if (iy != fCurrIY) { // new scanline 202bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com this->flush(); 203bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fCurrIY = iy; 204bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 205bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 20697a08960d3d82b295c3fce90d74be44a9e735019reed@google.com int start = x; 20797a08960d3d82b295c3fce90d74be44a9e735019reed@google.com int stop = x + width; 20897a08960d3d82b295c3fce90d74be44a9e735019reed@google.com 20997a08960d3d82b295c3fce90d74be44a9e735019reed@google.com SkASSERT(start >= 0 && stop > start); 21008d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com // integer-pixel-aligned ends of blit, rounded out 21108d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int fb = start & MASK; 21208d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int fe = stop & MASK; 21397a08960d3d82b295c3fce90d74be44a9e735019reed@google.com int n = (stop >> SHIFT) - (start >> SHIFT) - 1; 21497a08960d3d82b295c3fce90d74be44a9e735019reed@google.com 21597a08960d3d82b295c3fce90d74be44a9e735019reed@google.com if (n < 0) { 21697a08960d3d82b295c3fce90d74be44a9e735019reed@google.com fb = fe - fb; 21797a08960d3d82b295c3fce90d74be44a9e735019reed@google.com n = 0; 21897a08960d3d82b295c3fce90d74be44a9e735019reed@google.com fe = 0; 21997a08960d3d82b295c3fce90d74be44a9e735019reed@google.com } else { 22097a08960d3d82b295c3fce90d74be44a9e735019reed@google.com if (fb == 0) { 22197a08960d3d82b295c3fce90d74be44a9e735019reed@google.com n += 1; 222d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com } else { 2236130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fb = SCALE - fb; 224bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 225bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 226e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com 22754c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com fOffsetX = fRuns.add(x >> SHIFT, coverage_to_partial_alpha(fb), 22854c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com n, coverage_to_partial_alpha(fe), 229e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT), 230e6af34a8082cc1f473aed6afe2cdeae796744717reed@google.com fOffsetX); 231bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 232bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 233bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRuns.assertValid(y & MASK, (1 << (8 - SHIFT))); 234bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fCurrX = x + width; 235bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 236bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 237bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 2385ed43fcd5836738045d50d2cbd77d494a321a20bcaryclark@google.com#if 0 // UNUSED 239b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.comstatic void set_left_rite_runs(SkAlphaRuns& runs, int ileft, U8CPU leftA, 240b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com int n, U8CPU riteA) { 241b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com SkASSERT(leftA <= 0xFF); 242b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com SkASSERT(riteA <= 0xFF); 243b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com 244b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com int16_t* run = runs.fRuns; 245b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com uint8_t* aa = runs.fAlpha; 246b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com 247b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com if (ileft > 0) { 248b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com run[0] = ileft; 249b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com aa[0] = 0; 250b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com run += ileft; 251b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com aa += ileft; 252b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com } 253b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com 254b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com SkASSERT(leftA < 0xFF); 255b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com if (leftA > 0) { 256b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com *run++ = 1; 257b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com *aa++ = leftA; 258b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com } 259b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com 260b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com if (n > 0) { 261b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com run[0] = n; 262b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com aa[0] = 0xFF; 263b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com run += n; 264b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com aa += n; 265b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com } 266b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com 267b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com SkASSERT(riteA < 0xFF); 268b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com if (riteA > 0) { 269b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com *run++ = 1; 270b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com *aa++ = riteA; 271b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com } 272b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com run[0] = 0; 273b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com} 2745ed43fcd5836738045d50d2cbd77d494a321a20bcaryclark@google.com#endif 275b575562fac6bbcc83c19bee8d4fbae67d5ebc4a4reed@google.com 27672de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.comvoid SuperBlitter::blitRect(int x, int y, int width, int height) { 27772de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com SkASSERT(width > 0); 27872de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com SkASSERT(height > 0); 27972de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 28008d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com // blit leading rows 28108d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com while ((y & MASK)) { 28272de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com this->blitH(x, y++, width); 28372de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com if (--height <= 0) { 28472de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com return; 28572de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com } 28672de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com } 28772de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com SkASSERT(height > 0); 28872de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 28908d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com // Since this is a rect, instead of blitting supersampled rows one at a 29008d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com // time and then resolving to the destination canvas, we can blit 29108d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com // directly to the destintion canvas one row per SCALE supersampled rows. 29272de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com int start_y = y >> SHIFT; 29372de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com int stop_y = (y + height) >> SHIFT; 29472de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com int count = stop_y - start_y; 29572de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com if (count > 0) { 29672de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com y += count << SHIFT; 29772de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com height -= count << SHIFT; 29872de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 29972de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com // save original X for our tail blitH() loop at the bottom 30072de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com int origX = x; 30172de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 30272de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com x -= fSuperLeft; 30372de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com // hack, until I figure out why my cubics (I think) go beyond the bounds 30472de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com if (x < 0) { 30572de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com width += x; 30672de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com x = 0; 30772de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com } 30872de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 3096130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // There is always a left column, a middle, and a right column. 3106130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // ileft is the destination x of the first pixel of the entire rect. 3116130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // xleft is (SCALE - # of covered supersampled pixels) in that 3126130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // destination pixel. 31372de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com int ileft = x >> SHIFT; 31408d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int xleft = x & MASK; 3156130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // irite is the destination x of the last pixel of the OPAQUE section. 3166130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // xrite is the number of supersampled pixels extending beyond irite; 3176130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // xrite/SCALE should give us alpha. 31872de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com int irite = (x + width) >> SHIFT; 31908d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int xrite = (x + width) & MASK; 3206130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com if (!xrite) { 3216130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com xrite = SCALE; 3226130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com irite--; 3236130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com } 3246130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 32567b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com // Need to call flush() to clean up pending draws before we 32667b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com // even consider blitV(), since otherwise it can look nonmonotonic. 32767b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com SkASSERT(start_y > fCurrIY); 32867b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com this->flush(); 32967b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com 33072de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com int n = irite - ileft - 1; 33172de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com if (n < 0) { 33267b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com // If n < 0, we'll only have a single partially-transparent column 33367b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com // of pixels to render. 33472de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com xleft = xrite - xleft; 3356130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(xleft <= SCALE); 3366130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com SkASSERT(xleft > 0); 33772de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com xrite = 0; 3386130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fRealBlitter->blitV(ileft + fLeft, start_y, count, 3396130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com coverage_to_exact_alpha(xleft)); 34072de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com } else { 34167b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com // With n = 0, we have two possibly-transparent columns of pixels 34267b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com // to render; with n > 0, we have opaque columns between them. 34367b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com 3446130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com xleft = SCALE - xleft; 34572de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 34667b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com // Using coverage_to_exact_alpha is not consistent with blitH() 34767b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com const int coverageL = coverage_to_exact_alpha(xleft); 34867b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com const int coverageR = coverage_to_exact_alpha(xrite); 3496130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com 35067b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com SkASSERT(coverageL > 0 || n > 0 || coverageR > 0); 35167b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com SkASSERT((coverageL != 0) + n + (coverageR != 0) <= fWidth); 35272de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 35367b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com fRealBlitter->blitAntiRect(ileft + fLeft, start_y, n, count, 35467b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com coverageL, coverageR); 35567b208a18899dc88de91c13182cd45f605fdc861tomhudson@google.com } 35672de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 35772de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com // preamble for our next call to blitH() 35872de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com fCurrIY = stop_y - 1; 35972de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com fOffsetX = 0; 36072de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com fCurrY = y - 1; 36172de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com fRuns.reset(fWidth); 36272de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com x = origX; 36372de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com } 36472de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 3656130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com // catch any remaining few rows 36608d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com SkASSERT(height <= MASK); 36772de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com while (--height >= 0) { 36872de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com this->blitH(x, y++, width); 36972de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com } 37072de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com} 37172de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com 372bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 373bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 37408d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com/// Masked supersampling antialiased blitter. 375bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comclass MaskSuperBlitter : public BaseSuperBlitter { 376bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.compublic: 377bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 378bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkRegion& clip); 379bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com virtual ~MaskSuperBlitter() { 380bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fRealBlitter->blitMask(fMask, fClipRect); 381bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 382bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 38372de73e8241cf6ac7b8f984caab52dbd038ad7cbreed@google.com virtual void blitH(int x, int y, int width) SK_OVERRIDE; 384bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 385d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com static bool CanHandleRect(const SkIRect& bounds) { 386d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com#ifdef FORCE_RLE 387d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com return false; 388d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com#endif 389bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int width = bounds.width(); 3900fd1581aef871cdbb38d29912e558cc4e2e04af5reed@google.com int64_t rb = SkAlign4(width); 3910fd1581aef871cdbb38d29912e558cc4e2e04af5reed@google.com // use 64bits to detect overflow 3920fd1581aef871cdbb38d29912e558cc4e2e04af5reed@google.com int64_t storage = rb * bounds.height(); 393434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 394bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return (width <= MaskSuperBlitter::kMAX_WIDTH) && 3950fd1581aef871cdbb38d29912e558cc4e2e04af5reed@google.com (storage <= MaskSuperBlitter::kMAX_STORAGE); 396bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 397434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 398bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comprivate: 399bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com enum { 400d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com#ifdef FORCE_SUPERMASK 401d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com kMAX_WIDTH = 2048, 402d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com kMAX_STORAGE = 1024 * 1024 * 2 403d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com#else 404bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kMAX_WIDTH = 32, // so we don't try to do very wide things, where the RLE blitter would be faster 405bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com kMAX_STORAGE = 1024 406d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com#endif 407bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com }; 408bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 409bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkMask fMask; 410bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect fClipRect; 411bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // we add 1 because add_aa_span can write (unchanged) 1 extra byte at the end, rather than 412bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // perform a test to see if stopAlpha != 0 413bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint32_t fStorage[(kMAX_STORAGE >> 2) + 1]; 414bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com}; 415bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 416bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.comMaskSuperBlitter::MaskSuperBlitter(SkBlitter* realBlitter, const SkIRect& ir, 417bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkRegion& clip) 418bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com : BaseSuperBlitter(realBlitter, ir, clip) { 419bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(CanHandleRect(ir)); 420bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 421bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMask.fImage = (uint8_t*)fStorage; 422bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMask.fBounds = ir; 423bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMask.fRowBytes = ir.width(); 424bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fMask.fFormat = SkMask::kA8_Format; 425935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 426bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fClipRect = ir; 427bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fClipRect.intersect(clip.getBounds()); 428434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 429bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // For valgrind, write 1 extra byte at the end so we don't read 430bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // uninitialized memory. See comment in add_aa_span and fStorage[]. 431bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com memset(fStorage, 0, fMask.fBounds.height() * fMask.fRowBytes + 1); 432bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 433bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 434d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.comstatic void add_aa_span(uint8_t* alpha, U8CPU startAlpha) { 435bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com /* I should be able to just add alpha[x] + startAlpha. 436bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com However, if the trailing edge of the previous span and the leading 437bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com edge of the current span round to the same super-sampled x value, 438bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com I might overflow to 256 with this add, hence the funny subtract. 439bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com */ 440bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com unsigned tmp = *alpha + startAlpha; 441bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(tmp <= 256); 442bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com *alpha = SkToU8(tmp - (tmp >> 8)); 443bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 444bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 445d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.comstatic inline uint32_t quadplicate_byte(U8CPU value) { 446d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com uint32_t pair = (value << 8) | value; 447d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com return (pair << 16) | pair; 448d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com} 449d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com 450335b90909ae2462290db6208f3ede204a74df33freed@google.com// Perform this tricky subtract, to avoid overflowing to 256. Our caller should 451335b90909ae2462290db6208f3ede204a74df33freed@google.com// only ever call us with at most enough to hit 256 (never larger), so it is 452335b90909ae2462290db6208f3ede204a74df33freed@google.com// enough to just subtract the high-bit. Actually clamping with a branch would 453335b90909ae2462290db6208f3ede204a74df33freed@google.com// be slower (e.g. if (tmp > 255) tmp = 255;) 454335b90909ae2462290db6208f3ede204a74df33freed@google.com// 455335b90909ae2462290db6208f3ede204a74df33freed@google.comstatic inline void saturated_add(uint8_t* ptr, U8CPU add) { 456335b90909ae2462290db6208f3ede204a74df33freed@google.com unsigned tmp = *ptr + add; 457335b90909ae2462290db6208f3ede204a74df33freed@google.com SkASSERT(tmp <= 256); 458335b90909ae2462290db6208f3ede204a74df33freed@google.com *ptr = SkToU8(tmp - (tmp >> 8)); 459335b90909ae2462290db6208f3ede204a74df33freed@google.com} 460335b90909ae2462290db6208f3ede204a74df33freed@google.com 461d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com// minimum count before we want to setup an inner loop, adding 4-at-a-time 462d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com#define MIN_COUNT_FOR_QUAD_LOOP 16 463d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com 464d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.comstatic void add_aa_span(uint8_t* alpha, U8CPU startAlpha, int middleCount, 465d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com U8CPU stopAlpha, U8CPU maxValue) { 466bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(middleCount >= 0); 467bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 468335b90909ae2462290db6208f3ede204a74df33freed@google.com saturated_add(alpha, startAlpha); 469335b90909ae2462290db6208f3ede204a74df33freed@google.com alpha += 1; 470bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 471d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com if (middleCount >= MIN_COUNT_FOR_QUAD_LOOP) { 472d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com // loop until we're quad-byte aligned 473d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com while (SkTCast<intptr_t>(alpha) & 0x3) { 474d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com alpha[0] = SkToU8(alpha[0] + maxValue); 475d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com alpha += 1; 476d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com middleCount -= 1; 477d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com } 478d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com 479d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com int bigCount = middleCount >> 2; 480d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com uint32_t* qptr = reinterpret_cast<uint32_t*>(alpha); 481d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com uint32_t qval = quadplicate_byte(maxValue); 482d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com do { 483d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com *qptr++ += qval; 484d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com } while (--bigCount > 0); 485d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com 486d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com middleCount &= 3; 487d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com alpha = reinterpret_cast<uint8_t*> (qptr); 488d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com // fall through to the following while-loop 489d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com } 490d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com 491d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com while (--middleCount >= 0) { 492bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha[0] = SkToU8(alpha[0] + maxValue); 493bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com alpha += 1; 494bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 495bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 496bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // potentially this can be off the end of our "legal" alpha values, but that 497bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // only happens if stopAlpha is also 0. Rather than test for stopAlpha != 0 498bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // every time (slow), we just do it, and ensure that we've allocated extra space 499bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // (see the + 1 comment in fStorage[] 500335b90909ae2462290db6208f3ede204a74df33freed@google.com saturated_add(alpha, stopAlpha); 501bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 502bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 503d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.comvoid MaskSuperBlitter::blitH(int x, int y, int width) { 504bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int iy = (y >> SHIFT); 505434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 506bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(iy >= fMask.fBounds.fTop && iy < fMask.fBounds.fBottom); 507bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com iy -= fMask.fBounds.fTop; // make it relative to 0 508bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 509300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org // This should never happen, but it does. Until the true cause is 510300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org // discovered, let's skip this span instead of crashing. 511300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org // See http://crbug.com/17569. 512300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org if (iy < 0) { 513300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org return; 514300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org } 515300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org 516bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 517bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com { 518bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int ix = x >> SHIFT; 519bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(ix >= fMask.fBounds.fLeft && ix < fMask.fBounds.fRight); 520bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 521bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 522434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 523bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x -= (fMask.fBounds.fLeft << SHIFT); 524bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 525bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // hack, until I figure out why my cubics (I think) go beyond the bounds 526d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com if (x < 0) { 527bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com width += x; 528bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com x = 0; 529bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 530bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 531bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com uint8_t* row = fMask.fImage + iy * fMask.fRowBytes + (x >> SHIFT); 532bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 533bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int start = x; 534bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int stop = x + width; 535bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 536bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkASSERT(start >= 0 && stop > start); 53708d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int fb = start & MASK; 53808d7e7c286339679d4189e2b9e05fd80830ee776tomhudson@google.com int fe = stop & MASK; 539bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com int n = (stop >> SHIFT) - (start >> SHIFT) - 1; 540bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 541bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 542d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com if (n < 0) { 543456468215617b3233ea162687b69d1445cb0cf4csenorblanco@chromium.org SkASSERT(row >= fMask.fImage); 544456468215617b3233ea162687b69d1445cb0cf4csenorblanco@chromium.org SkASSERT(row < fMask.fImage + kMAX_STORAGE + 1); 54554c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com add_aa_span(row, coverage_to_partial_alpha(fe - fb)); 546d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com } else { 5476130a9d1e6a8b20f7236d799786e9bd3e32658dctomhudson@google.com fb = SCALE - fb; 548456468215617b3233ea162687b69d1445cb0cf4csenorblanco@chromium.org SkASSERT(row >= fMask.fImage); 549456468215617b3233ea162687b69d1445cb0cf4csenorblanco@chromium.org SkASSERT(row + n + 1 < fMask.fImage + kMAX_STORAGE + 1); 55054c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com add_aa_span(row, coverage_to_partial_alpha(fb), 55154c999a5f46956e6be79cc93c6d39f437bef1b7etomhudson@google.com n, coverage_to_partial_alpha(fe), 552bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com (1 << (8 - SHIFT)) - (((y & MASK) + 1) >> SHIFT)); 553bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 554bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 555bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#ifdef SK_DEBUG 556bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com fCurrX = x + width; 557bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com#endif 558bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 559bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 560bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com/////////////////////////////////////////////////////////////////////////////// 561bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 562e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.comstatic bool fitsInsideLimit(const SkRect& r, SkScalar max) { 563e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com const SkScalar min = -max; 564e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com return r.fLeft > min && r.fTop > min && 565e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com r.fRight < max && r.fBottom < max; 566e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com} 567e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com 5686ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.comstatic int overflows_short_shift(int value, int shift) { 5696ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com const int s = 16 + shift; 5706ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com return (value << s >> s) - value; 5716ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com} 5726ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com 5736ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com/** 5746ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com Would any of the coordinates of this rectangle not fit in a short, 5756ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com when left-shifted by shift? 5766ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com*/ 5776ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.comstatic int rect_overflows_short_shift(SkIRect rect, int shift) { 5786ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com SkASSERT(!overflows_short_shift(8191, SHIFT)); 5796ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com SkASSERT(overflows_short_shift(8192, SHIFT)); 5806ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com SkASSERT(!overflows_short_shift(32767, 0)); 5816ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com SkASSERT(overflows_short_shift(32768, 0)); 5826ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com 5836ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // Since we expect these to succeed, we bit-or together 5846ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // for a tiny extra bit of speed. 5856ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com return overflows_short_shift(rect.fLeft, SHIFT) | 5866ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com overflows_short_shift(rect.fRight, SHIFT) | 5876ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com overflows_short_shift(rect.fTop, SHIFT) | 5886ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com overflows_short_shift(rect.fBottom, SHIFT); 5896ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com} 5906ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com 591e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.comstatic bool safeRoundOut(const SkRect& src, SkIRect* dst, int32_t maxInt) { 592e5e3655e289e2ab684f2ec49cbbe127ac6e22c6areed@google.com#ifdef SK_SCALAR_IS_FIXED 593e5e3655e289e2ab684f2ec49cbbe127ac6e22c6areed@google.com // the max-int (shifted) is exactly what we want to compare against, to know 594e5e3655e289e2ab684f2ec49cbbe127ac6e22c6areed@google.com // if we can survive shifting our fixed-point coordinates 595e5e3655e289e2ab684f2ec49cbbe127ac6e22c6areed@google.com const SkFixed maxScalar = maxInt; 596e5e3655e289e2ab684f2ec49cbbe127ac6e22c6areed@google.com#else 597e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com const SkScalar maxScalar = SkIntToScalar(maxInt); 598e5e3655e289e2ab684f2ec49cbbe127ac6e22c6areed@google.com#endif 599e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com if (fitsInsideLimit(src, maxScalar)) { 600e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com src.roundOut(dst); 601e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com return true; 602e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com } 603e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com return false; 604bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 605bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 606f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.comvoid SkScan::AntiFillPath(const SkPath& path, const SkRegion& origClip, 60750a8a51ccc3fa63409cd2059c5c2361ba8e642a1reed@google.com SkBlitter* blitter, bool forceRLE) { 608f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com if (origClip.isEmpty()) { 609bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 610bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 611bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 612155c4e804736576f9352aa60d70669ac3e3f9d52reed@android.com SkIRect ir; 613e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com 614e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com if (!safeRoundOut(path.getBounds(), &ir, SK_MaxS32 >> SHIFT)) { 615e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com#if 0 616e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com const SkRect& r = path.getBounds(); 617e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com SkDebugf("--- bounds can't fit in SkIRect\n", r.fLeft, r.fTop, r.fRight, r.fBottom); 618e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com#endif 619e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com return; 620e926306bfed506f3fa5e767c5ed1d41f72284ac3reed@google.com } 621bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (ir.isEmpty()) { 622273fc37241771f46adae5c4547b6f9afa90eb3bbreed@google.com if (path.isInverseFillType()) { 623f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com blitter->blitRegion(origClip); 624273fc37241771f46adae5c4547b6f9afa90eb3bbreed@google.com } 625bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 626bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 627bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 6286ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // If the intersection of the path bounds and the clip bounds 6296ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // will overflow 32767 when << by SHIFT, we can't supersample, 6306ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // so draw without antialiasing. 6316ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com SkIRect clippedIR; 6326ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com if (path.isInverseFillType()) { 6336ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // If the path is an inverse fill, it's going to fill the entire 6346ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // clip, and we care whether the entire clip exceeds our limits. 6356ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com clippedIR = origClip.getBounds(); 6366ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com } else { 6376ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com if (!clippedIR.intersect(ir, origClip.getBounds())) { 6386ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com return; 6396ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com } 6406ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com } 6416ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com if (rect_overflows_short_shift(clippedIR, SHIFT)) { 6426ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com SkScan::FillPath(path, origClip, blitter); 6436ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com return; 6446ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com } 6456ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com 646f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com // Our antialiasing can't handle a clip larger than 32767, so we restrict 647f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com // the clip to that limit here. (the runs[] uses int16_t for its index). 648f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com // 6496ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // A more general solution (one that could also eliminate the need to 6506ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // disable aa based on ir bounds (see overflows_short_shift) would be 6516ec256aa42b855a3086db1164a1086d4c0ca326ctomhudson@google.com // to tile the clip/target... 652f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com SkRegion tmpClipStorage; 653f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com const SkRegion* clipRgn = &origClip; 654f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com { 655f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com static const int32_t kMaxClipCoord = 32767; 656f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com const SkIRect& bounds = origClip.getBounds(); 657f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) { 658f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord }; 659f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op); 660f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com clipRgn = &tmpClipStorage; 661f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com } 662f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com } 663f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com // for here down, use clipRgn, not origClip 664f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com 665f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com SkScanClipper clipper(blitter, clipRgn, ir); 666bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com const SkIRect* clipRect = clipper.getClipRect(); 667bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 668bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (clipper.getBlitter() == NULL) { // clipped out 669bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (path.isInverseFillType()) { 670f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com blitter->blitRegion(*clipRgn); 671bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 672bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com return; 673bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 674434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 675bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // now use the (possibly wrapped) blitter 676bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com blitter = clipper.getBlitter(); 677bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 678bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com if (path.isInverseFillType()) { 679f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com sk_blit_above(blitter, ir, *clipRgn); 680bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 681bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 682bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com SkIRect superRect, *superClipRect = NULL; 683bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 684d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com if (clipRect) { 685bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com superRect.set( clipRect->fLeft << SHIFT, clipRect->fTop << SHIFT, 686bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com clipRect->fRight << SHIFT, clipRect->fBottom << SHIFT); 687bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com superClipRect = &superRect; 688bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 689bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com 690300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); 691300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org 692bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // MaskSuperBlitter can't handle drawing outside of ir, so we can't use it 693bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com // if we're an inverse filltype 69450a8a51ccc3fa63409cd2059c5c2361ba8e642a1reed@google.com if (!path.isInverseFillType() && MaskSuperBlitter::CanHandleRect(ir) && !forceRLE) { 695f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com MaskSuperBlitter superBlit(blitter, ir, *clipRgn); 696300cb7c6ae70259a3ea8c31c8a553e01fb43ec48senorblanco@chromium.org SkASSERT(SkIntToScalar(ir.fTop) <= path.getBounds().fTop); 697f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, *clipRgn); 698d310543736e5f3b12eef432d1ef2727ace4fe246reed@google.com } else { 699f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com SuperBlitter superBlit(blitter, ir, *clipRgn); 700f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com sk_fill_path(path, superClipRect, &superBlit, ir.fTop, ir.fBottom, SHIFT, *clipRgn); 701bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com } 702434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com 703434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com if (path.isInverseFillType()) { 704f3b3c41622fd2933e78170e6b4a8b9adb0b77617reed@google.com sk_blit_below(blitter, ir, *clipRgn); 705434433e916bd10326a9e4d47409b1e2e5d594a38reed@google.com } 706bcd4d5ab12df062500a4df90ec90d0f2d764931reed@android.com} 707d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com 708d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com/////////////////////////////////////////////////////////////////////////////// 709d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com 710d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com#include "SkRasterClip.h" 711d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com 712d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.comvoid SkScan::FillPath(const SkPath& path, const SkRasterClip& clip, 713d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkBlitter* blitter) { 714d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com if (clip.isEmpty()) { 715d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com return; 716d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com } 717935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 718d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com if (clip.isBW()) { 719d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com FillPath(path, clip.bwRgn(), blitter); 720d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com } else { 721d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkRegion tmp; 722d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkAAClipBlitter aaBlitter; 723935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 724d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com tmp.setRect(clip.getBounds()); 725d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com aaBlitter.init(blitter, &clip.aaRgn()); 726d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkScan::FillPath(path, tmp, &aaBlitter); 727d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com } 728d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com} 729d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com 730d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.comvoid SkScan::AntiFillPath(const SkPath& path, const SkRasterClip& clip, 731d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkBlitter* blitter) { 732d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com if (clip.isEmpty()) { 733d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com return; 734d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com } 735d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com 736d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com if (clip.isBW()) { 737d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com AntiFillPath(path, clip.bwRgn(), blitter); 738d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com } else { 739d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkRegion tmp; 740d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkAAClipBlitter aaBlitter; 741d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com 742d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com tmp.setRect(clip.getBounds()); 743d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com aaBlitter.init(blitter, &clip.aaRgn()); 744d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com SkScan::AntiFillPath(path, tmp, &aaBlitter, true); 745d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com } 746d48790d6ca44f1af207d36b3fcb191538fef24ebreed@google.com} 747