SkDraw.cpp revision 41e010cb901c0da9066c4df562030808c9ccd7f8
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7903dcb08b146cbaf81420a734a64692038b467cabungeman#define __STDC_LIMIT_MACROS 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDevice.h" 141c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#include "SkDeviceLooper.h" 152211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com#include "SkFixed.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathEffect.h" 19045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkRasterClip.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRasterizer.h" 21a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScan.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h" 24a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org#include "SkSmallAllocator.h" 2576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#include "SkString.h" 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStroke.h" 27cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen#include "SkTextMapStateProc.h" 2832e5d97ccf60f859db063ebd6e903c362e625767reed@google.com#include "SkTLazy.h" 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 30559a8833f0eae4af37dc0ffc3ee97e1fb14817b1commit-bot@chromium.org#include "SkVertState.h" 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAutoKern.h" 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcShader.h" 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawProcs.h" 35ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com#include "SkMatrixUtils.h" 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define TRACE_BITMAP_DRAWS 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 40fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com/** Helper for allocating small blitters on the stack. 41fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com */ 4240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.comclass SkAutoBlitterChoose : SkNoncopyable { 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 441d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkAutoBlitterChoose() { 451d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com fBlitter = NULL; 461d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 4741e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose(const SkPixmap& dst, const SkMatrix& matrix, 48126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkPaint& paint, bool drawCoverage = false) { 4941e010cb901c0da9066c4df562030808c9ccd7f8reed fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAllocator, drawCoverage); 50e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org } 5141e010cb901c0da9066c4df562030808c9ccd7f8reed 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* operator->() { return fBlitter; } 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* get() const { return fBlitter; } 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5541e010cb901c0da9066c4df562030808c9ccd7f8reed void choose(const SkPixmap& dst, const SkMatrix& matrix, 5653f0959fc024c56dc55fe6bf86380127b59abec9krajcevski const SkPaint& paint, bool drawCoverage = false) { 571d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkASSERT(!fBlitter); 5841e010cb901c0da9066c4df562030808c9ccd7f8reed fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAllocator, drawCoverage); 591d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 601d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 62a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // Owned by fAllocator, which will handle the delete. 63a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkBlitter* fBlitter; 64a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator fAllocator; 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 66e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose) 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com/** 6940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com * Since we are providing the storage for the shader (to avoid the perf cost 7040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com * of calling new) we insist that in our destructor we can account for all 7140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com * owners of the shader. 7240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com */ 7340c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.comclass SkAutoBitmapShaderInstall : SkNoncopyable { 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 759c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint, 769c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org const SkMatrix* localMatrix = NULL) 7740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com : fPaint(paint) /* makes a copy of the paint */ { 787ef849d45a4de02697697ea213bfae7c215a0c38mtklein fPaint.setShader(SkCreateBitmapShader(src, SkShader::kClamp_TileMode, 797ef849d45a4de02697697ea213bfae7c215a0c38mtklein SkShader::kClamp_TileMode, 807ef849d45a4de02697697ea213bfae7c215a0c38mtklein localMatrix, &fAllocator)); 8140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com // we deliberately left the shader with an owner-count of 2 8240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkASSERT(2 == fPaint.getShader()->getRefCnt()); 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8482065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBitmapShaderInstall() { 86a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // since fAllocator will destroy shader, we insist that owners == 2 87a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkASSERT(2 == fPaint.getShader()->getRefCnt()); 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com fPaint.setShader(NULL); // unref the shader by 1 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9282065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 9340c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com // return the new paint that has the shader applied 9440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com const SkPaint& paintWithShader() const { return fPaint; } 9582065d667f64e232bcde2ad849756a6096fcbe6freed@google.com 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 97a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // copy of caller's paint (which we then modify) 98a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkPaint fPaint; 99a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // Stores the shader. 100a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator fAllocator; 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 102e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall) 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 106f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDraw::SkDraw() { 107f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com sk_bzero(this, sizeof(*this)); 108f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 109f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDraw::SkDraw(const SkDraw& src) { 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(this, &src, sizeof(*this)); 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1144bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.combool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const { 1154bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (fRC->isEmpty()) { 1164bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return false; 1174bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 1184bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1194bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkMatrix inverse; 1204bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (!fMatrix->invert(&inverse)) { 1214bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return false; 1224bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 1234bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1244bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkIRect devBounds = fRC->getBounds(); 1254bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com // outset to have slop for antialasing and hairlines 1264bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com devBounds.outset(1, 1); 1274bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com inverse.mapRect(localBounds, SkRect::Make(devBounds)); 1284bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return true; 1294bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com} 1304bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) { 1364516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(pixels, bytes); 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {} 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 142a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2)); 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 146a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1)); 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(pixels, data, bytes); 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15341e010cb901c0da9066c4df562030808c9ccd7f8reedstatic BitmapXferProc ChooseBitmapXferProc(const SkPixmap& dst, const SkPaint& paint, 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t* data) { 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // todo: we can apply colorfilter up front if no shader, so we wouldn't 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to abort this fastpath 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getShader() || paint.getColorFilter()) { 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 161845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode; 162be2aa2aa1f8bf73d974bdd9438fc741bbf0cfbe6mike@reedtribe.org if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 165a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColor color = paint.getColor(); 167a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // collaps modes based on color... 169845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode == mode) { 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned alpha = SkColorGetA(color); 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == alpha) { 172845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com mode = SkXfermode::kDst_Mode; 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (0xFF == alpha) { 174845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com mode = SkXfermode::kSrc_Mode; 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 177a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 179845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kClear_Mode: 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Clear_BitmapXferProc\n"); 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Clear_BitmapXferProc; // ignore data 182845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kDst_Mode: 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Dst_BitmapXferProc\n"); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Dst_BitmapXferProc; // ignore data 185845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kSrc_Mode: { 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 187a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com should I worry about dithering for the lower depths? 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor pmc = SkPreMultiplyColor(color); 19041e010cb901c0da9066c4df562030808c9ccd7f8reed switch (dst.colorType()) { 19128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = pmc; 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D32_Src_BitmapXferProc\n"); 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D32_Src_BitmapXferProc; 197900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkPixel32ToPixel16(pmc); 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D16_Src_BitmapXferProc\n"); 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D16_Src_BitmapXferProc; 203900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkGetPackedA32(pmc); 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- DA8_Src_BitmapXferProc\n"); 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return DA8_Src_BitmapXferProc; 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22041e010cb901c0da9066c4df562030808c9ccd7f8reedstatic void CallBitmapXferProc(const SkPixmap& dst, const SkIRect& rect, BitmapXferProc proc, 22141e010cb901c0da9066c4df562030808c9ccd7f8reed uint32_t procData) { 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int shiftPerPixel; 22341e010cb901c0da9066c4df562030808c9ccd7f8reed switch (dst.colorType()) { 22428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 2; 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 227900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 1; 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 230900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 0; 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2340c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("Can't use xferproc on this config"); 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23841e010cb901c0da9066c4df562030808c9ccd7f8reed uint8_t* pixels = (uint8_t*)dst.writable_addr(); 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pixels); 24041e010cb901c0da9066c4df562030808c9ccd7f8reed const size_t rowBytes = dst.rowBytes(); 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int widthBytes = rect.width() << shiftPerPixel; 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip down to the first scanline and X position 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel); 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int scans = rect.height() - 1; scans >= 0; --scans) { 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(pixels, widthBytes, procData); 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rowBytes; 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPaint(const SkPaint& paint) const { 252f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 254045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devRect; 25941e010cb901c0da9066c4df562030808c9ccd7f8reed devRect.set(0, 0, fDst.width(), fDst.height()); 260a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 261045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 262045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com /* If we don't have a shader (i.e. we're just a solid color) we may 263045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com be faster to operate directly on the device bitmap, rather than invoking 264045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a blitter. Esp. true for xfermodes, which require a colorshader to be 265045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com present, which is just redundant work. Since we're drawing everywhere 266045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com in the clip, we don't have to worry about antialiasing. 267045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 268045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint32_t procData = 0; // to avoid the warning 26941e010cb901c0da9066c4df562030808c9ccd7f8reed BitmapXferProc proc = ChooseBitmapXferProc(fDst, paint, &procData); 270045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (proc) { 271045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (D_Dst_BitmapXferProc == proc) { // nothing to do 272045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 273045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 274a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 275045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRegion::Iterator iter(fRC->bwRgn()); 276045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 27741e010cb901c0da9066c4df562030808c9ccd7f8reed CallBitmapXferProc(fDst, iter.rect(), proc, procData); 278045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 279045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 280045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 283045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 284045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // normal case: use a blitter 28541e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 286045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(devRect, *fRC, blitter.get()); 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct PtProcRec { 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::PointMode fMode; 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* fClip; 295045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip* fRC; 296a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // computed values 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fRadius; 299a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter*); 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix, 304045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip*); 305045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Proc chooseProc(SkBlitter** blitter); 306045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 307045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 308045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper fWrapper; 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec.fClip->isRect()); 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = rec.fClip->getBounds(); 315a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3172d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3182d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_16_hair_proc(const PtProcRec& rec, 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint devPts[], int count, 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter) { 328045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rec.fRC->isRect()); 329045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 33141e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 33241e010cb901c0da9066c4df562030808c9ccd7f8reed SkASSERT(dst); 333c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 33441e010cb901c0da9066c4df562030808c9ccd7f8reed uint16_t* addr = dst->writable_addr16(0, 0); 33541e010cb901c0da9066c4df562030808c9ccd7f8reed size_t rb = dst->rowBytes(); 336c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3382d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3392d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value); 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3462d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.comstatic void bw_pt_rect_32_hair_proc(const PtProcRec& rec, 3472d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkPoint devPts[], int count, 3482d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkBlitter* blitter) { 3492d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(rec.fRC->isRect()); 3502d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3512d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com uint32_t value; 35241e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 35341e010cb901c0da9066c4df562030808c9ccd7f8reed SkASSERT(dst); 354c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 35541e010cb901c0da9066c4df562030808c9ccd7f8reed SkPMColor* addr = dst->writable_addr32(0, 0); 35641e010cb901c0da9066c4df562030808c9ccd7f8reed size_t rb = dst->rowBytes(); 357c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3582d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com for (int i = 0; i < count; i++) { 3592d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3602d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3612d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (r.contains(x, y)) { 3622d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com ((SkPMColor*)((char*)addr + y * rb))[x] = value; 3632d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3642d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3652d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com} 3662d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 370e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 371e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec.fClip->contains(x, y)) { 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 3815dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter); 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3875dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairLine(devPts, count, *rec.fRC, blitter); 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// aa versions 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 3955dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter); 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4015dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter); 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 412c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 418c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 419045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillXRect(r, *rec.fRC, blitter); 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 429a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 435a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 436045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::AntiFillXRect(r, *rec.fRC, blitter); 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 440b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com// If this guy returns true, then chooseProc() must return a valid proc 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 442045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMatrix* matrix, const SkRasterClip* rc) { 4433ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang if ((unsigned)mode > (unsigned)SkCanvas::kPolygon_PointMode) { 4443ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang return false; 4453ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang } 4463ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect()) { 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width = paint.getStrokeWidth(); 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == width) { 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 454045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = NULL; 455045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 4562d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com fRadius = SK_FixedHalf; 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 459b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com if (paint.getStrokeCap() != SkPaint::kRound_Cap && 4609f2251c73ed6f417dd1057d487bf523e04488440robertphillips matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) { 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = matrix->get(SkMatrix::kMScaleX); 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = matrix->get(SkMatrix::kMScaleY); 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(sx - sy)) { 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sx < 0) { 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sx = -sx; 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 470045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = NULL; 471045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1; 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 479045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comPtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { 480b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com Proc proc = NULL; 481a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 482045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = *blitterPtr; 483045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 484045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fRC->bwRgn(); 485045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 486045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fWrapper.init(*fRC, blitter); 487045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fWrapper.getRgn(); 488045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = fWrapper.getBlitter(); 489045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *blitterPtr = blitter; 490045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 491045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for our arrays 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == SkCanvas::kPoints_PointMode); 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == SkCanvas::kLines_PointMode); 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(2 == SkCanvas::kPolygon_PointMode); 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4982d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fPaint->isAntiAlias()) { 4992d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (0 == fPaint->getStrokeWidth()) { 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const Proc gAAProcs[] = { 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gAAProcs[fMode]; 5042d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 5052d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(SkCanvas::kPoints_PointMode == fMode); 5062d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = aa_square_proc; 5072d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 5082d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else { // BW 5092d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fRadius <= SK_FixedHalf) { // small radii and hairline 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 51241e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* bm = blitter->justAnOpaqueColor(&value); 513900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (bm && kRGB_565_SkColorType == bm->colorType()) { 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_16_hair_proc; 51528fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org } else if (bm && kN32_SkColorType == bm->colorType()) { 5162d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = bw_pt_rect_32_hair_proc; 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_hair_proc; 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static Proc gBWProcs[] = { 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gBWProcs[fMode]; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_square_proc; 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return proc; 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// each of these costs 8-bytes of stack space, so don't make it too large 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// must be even for lines/polygon to work 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_DEV_PTS 32 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 538f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkPoint pts[], const SkPaint& paint, 539f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com bool forceUseDevice) const { 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're in lines mode, force count to be even 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kLines_PointMode == mode) { 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count &= ~(size_t)1; 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 548a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 550f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 551a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 553045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PtProcRec rec; 558045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) { 55941e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint devPts[MAX_DEV_PTS]; 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* bltr = blitter.get(); 564045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com PtProcRec::Proc proc = rec.chooseProc(&bltr); 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we have to back up subsequent passes if we're in polygon mode 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 567a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 569a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org int n = SkToInt(count); 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (n > MAX_DEV_PTS) { 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = MAX_DEV_PTS; 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->mapPoints(devPts, pts, n); 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(rec, devPts, n, bltr); 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts += n - backup; 576a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org SkASSERT(SkToInt(count) >= n); 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= n; 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += backup; 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count != 0); 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPoints_PointMode: { 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // temporarily mark the paint as filling. 58640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint newPaint(paint); 58740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com newPaint.setStyle(SkPaint::kFill_Style); 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 58940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkScalar width = newPaint.getStrokeWidth(); 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar radius = SkScalarHalf(width); 591a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 59240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) { 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix preMatrix; 5957ef849d45a4de02697697ea213bfae7c215a0c38mtklein 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addCircle(0, 0, radius); 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com preMatrix.setTranslate(pts[i].fX, pts[i].fY); 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // pass true for the last point, since we can modify 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // then path then 601b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile((count-1) == i); 602f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 60340c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com fDevice->drawPath(*this, path, newPaint, &preMatrix, 604f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com (count-1) == i); 605f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 60640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com this->drawPath(path, newPaint, &preMatrix, 60740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com (count-1) == i); 608f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 612a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = pts[i].fX - radius; 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = pts[i].fY - radius; 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = r.fLeft + width; 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = r.fTop + width; 618f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 61940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com fDevice->drawRect(*this, r, newPaint); 620f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 62140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com this->drawRect(r, newPaint); 622f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kLines_PointMode: 62849f085dddff10473b6ebf832a974288300224e60bsalomon if (2 == count && paint.getPathEffect()) { 629629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // most likely a dashed line - see if it is one of the ones 630629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // we can accelerate 631629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkStrokeRec rec(paint); 6326d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkPathEffect::PointData pointData; 633629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 634629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPath path; 635629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.moveTo(pts[0]); 636629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.lineTo(pts[1]); 637629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6384bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect = SkRect::Make(fRC->getBounds()); 6394024f32d99b63a599c544a49f526e53c25135159skia.committer@gmail.com 6404bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (paint.getPathEffect()->asPoints(&pointData, path, rec, 6414bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com *fMatrix, &cullRect)) { 6426d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // 'asPoints' managed to find some fast path 6436d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 644629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPaint newP(paint); 645629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com newP.setPathEffect(NULL); 646935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com newP.setStyle(SkPaint::kFill_Style); 647629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6486d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fFirst.isEmpty()) { 6496d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6506d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawPath(*this, pointData.fFirst, newP); 6516d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6526d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fFirst, newP); 6536d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 654629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 6556d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6566d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fLast.isEmpty()) { 6576d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6586d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawPath(*this, pointData.fLast, newP); 6596d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6606d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fLast, newP); 6616d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6626d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6636d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6646d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (pointData.fSize.fX == pointData.fSize.fY) { 6656d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line can just be drawn as points 6666d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth())); 6676d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6686d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) { 6696d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kRound_Cap); 6706d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6716d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kButt_Cap); 6726d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6736d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6746d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6757a03d86a3d9adcb13432fbd82039725149487c97skia.committer@gmail.com fDevice->drawPoints(*this, 6766d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkCanvas::kPoints_PointMode, 6776d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fNumPoints, 6786d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints, 6796d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP); 6806d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6816d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPoints(SkCanvas::kPoints_PointMode, 6826d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fNumPoints, 6836d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints, 6846d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP, 6856d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com forceUseDevice); 6866d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6876d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com break; 688935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } else { 6896d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line must be drawn as rects 6907a03d86a3d9adcb13432fbd82039725149487c97skia.committer@gmail.com SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag & 6916d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fFlags)); 6926d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6936d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkRect r; 6946d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6956d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com for (int i = 0; i < pointData.fNumPoints; ++i) { 6966d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com r.set(pointData.fPoints[i].fX - pointData.fSize.fX, 6976d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY - pointData.fSize.fY, 6986d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fX + pointData.fSize.fX, 6996d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY + pointData.fSize.fY); 7006d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 7016d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawRect(*this, r, newP); 7026d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 7036d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawRect(r, newP); 7046d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 7056d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 706935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } 7076d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 708629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com break; 709629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 710629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 711629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // couldn't take fast path so fall through! 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPolygon_PointMode: { 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= 1; 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setStyle(SkPaint::kStroke_Style); 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 718b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile(true); 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i += inc) { 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(pts[i]); 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.lineTo(pts[i+1]); 722f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 723f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDevice->drawPath(*this, path, p, NULL, true); 724f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 725f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->drawPath(path, p, NULL, true); 726f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.rewind(); 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7351a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalitastatic inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) { 7361a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkASSERT(matrix.rectStaysRect()); 7371a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkASSERT(SkPaint::kFill_Style != paint.getStyle()); 7381a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 7391a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkVector size; 7401a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; 7411a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita matrix.mapVectors(&size, &pt, 1); 7421a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY)); 7431a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita} 7441a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 745761fb62b0eb174783316d2a8b933fba896ca6355reed@google.comstatic bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, 746761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com SkPoint* strokeSize) { 747761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com if (SkPaint::kMiter_Join != paint.getStrokeJoin() || 748761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com paint.getStrokeMiter() < SK_ScalarSqrt2) { 749761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return false; 750761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com } 751fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7521a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita *strokeSize = compute_stroke_size(paint, matrix); 753761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return true; 7547ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org} 7557ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 75662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.comSkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, 75762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const SkMatrix& matrix, 75862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint* strokeSize) { 7597ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org RectType rtype; 7607ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org const SkScalar width = paint.getStrokeWidth(); 76162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const bool zeroWidth = (0 == width); 7627ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::Style style = paint.getStyle(); 763fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7647ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { 7657ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org style = SkPaint::kFill_Style; 7667ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 767fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect() || paint.getMaskFilter() || 76962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com paint.getRasterizer() || !matrix.rectStaysRect() || 7707ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::kStrokeAndFill_Style == style) { 77162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com rtype = kPath_RectType; 77262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (SkPaint::kFill_Style == style) { 7737ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kFill_RectType; 7747ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else if (zeroWidth) { 7757ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kHair_RectType; 77662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (easy_rect_join(paint, matrix, strokeSize)) { 7777ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kStroke_RectType; 7787ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else { 7797ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kPath_RectType; 7807ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 78162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return rtype; 78262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com} 78362ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 7847324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic const SkPoint* rect_points(const SkRect& r) { 785fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<const SkPoint*>(&r); 7867324415759fe0c5a0902877b664aa942a89bd940reed@google.com} 7877324415759fe0c5a0902877b664aa942a89bd940reed@google.com 7887324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic SkPoint* rect_points(SkRect& r) { 789fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<SkPoint*>(&r); 79040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com} 79140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com 7920393912de72bc3d8b3640c122c53470dd0da1e6dreedvoid SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint, 7930393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkMatrix* paintMatrix, const SkRect* postPaintRect) const { 79462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkDEBUGCODE(this->validate();) 7957ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 79662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com // nothing to draw 797045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 79862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return; 79962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } 80062ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 8010393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkMatrix* matrix; 8020393912de72bc3d8b3640c122c53470dd0da1e6dreed SkMatrix combinedMatrixStorage; 8030393912de72bc3d8b3640c122c53470dd0da1e6dreed if (paintMatrix) { 8040393912de72bc3d8b3640c122c53470dd0da1e6dreed SkASSERT(postPaintRect); 8050393912de72bc3d8b3640c122c53470dd0da1e6dreed combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix); 8060393912de72bc3d8b3640c122c53470dd0da1e6dreed matrix = &combinedMatrixStorage; 8070393912de72bc3d8b3640c122c53470dd0da1e6dreed } else { 8080393912de72bc3d8b3640c122c53470dd0da1e6dreed SkASSERT(!postPaintRect); 8090393912de72bc3d8b3640c122c53470dd0da1e6dreed matrix = fMatrix; 8100393912de72bc3d8b3640c122c53470dd0da1e6dreed } 8110393912de72bc3d8b3640c122c53470dd0da1e6dreed 81262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint strokeSize; 81362ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); 81462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 8157ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if (kPath_RectType == rtype) { 8160393912de72bc3d8b3640c122c53470dd0da1e6dreed SkDraw draw(*this); 8170393912de72bc3d8b3640c122c53470dd0da1e6dreed if (paintMatrix) { 8180393912de72bc3d8b3640c122c53470dd0da1e6dreed draw.fMatrix = matrix; 8190393912de72bc3d8b3640c122c53470dd0da1e6dreed } 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmp; 8210393912de72bc3d8b3640c122c53470dd0da1e6dreed tmp.addRect(prePaintRect); 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setFillType(SkPath::kWinding_FillType); 8230393912de72bc3d8b3640c122c53470dd0da1e6dreed draw.drawPath(tmp, paint, NULL, true); 8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8270393912de72bc3d8b3640c122c53470dd0da1e6dreed SkRect devRect; 8281a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect; 8291a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita // skip the paintMatrix when transforming the rect by the CTM 8301a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita fMatrix->mapPoints(rect_points(devRect), rect_points(paintRect), 2); 8317324415759fe0c5a0902877b664aa942a89bd940reed@google.com devRect.sort(); 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for the quick exit, before we build a blitter 8341a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkRect bbox = devRect; 8351c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.getStyle() != SkPaint::kFill_Style) { 8361c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // extra space for hairlines 837b3eba478d5bed5fb2b5f0f224738c8c292cebf36george if (paint.getStrokeWidth() == 0) { 8381a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita bbox.outset(1, 1); 839b3eba478d5bed5fb2b5f0f224738c8c292cebf36george } else { 8401a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita // For kStroke_RectType, strokeSize is already computed. 8411a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita const SkPoint& ssize = (kStroke_RectType == rtype) 8421a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita ? strokeSize 8431a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita : compute_stroke_size(paint, *fMatrix); 8441a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y())); 845b3eba478d5bed5fb2b5f0f224738c8c292cebf36george } 8461c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8471a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 8481a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkIRect ir = bbox.roundOut(); 8491c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (fRC->quickReject(ir)) { 8501c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com return; 8518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 85341e010cb901c0da9066c4df562030808c9ccd7f8reed SkDeviceLooper looper(fDst, *fRC, ir, paint.isAntiAlias()); 8541c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com while (looper.next()) { 8551c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkRect localDevRect; 8561c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com looper.mapRect(&localDevRect, devRect); 8571c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkMatrix localMatrix; 8580393912de72bc3d8b3640c122c53470dd0da1e6dreed looper.mapMatrix(&localMatrix, *matrix); 8591c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 86041e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitterStorage(looper.getPixmap(), localMatrix, paint); 8611c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com const SkRasterClip& clip = looper.getRC(); 8621c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkBlitter* blitter = blitterStorage.get(); 8631c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 8641c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter 8651c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // case we are also hairline (if we've gotten to here), which devolves to 8661c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // effectively just kFill 8671c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com switch (rtype) { 8681c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kFill_RectType: 8691c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8701c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFillRect(localDevRect, clip, blitter); 8711c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8721c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FillRect(localDevRect, clip, blitter); 8731c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8741c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8751c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kStroke_RectType: 8761c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8771c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); 8781c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8791c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); 8801c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8811c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8821c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kHair_RectType: 8831c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8841c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiHairRect(localDevRect, clip, blitter); 8851c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8861c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::HairRect(localDevRect, clip, blitter); 8871c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8881c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8891c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com default: 8901c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkDEBUGFAIL("bad rtype"); 8911c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (srcM.fBounds.isEmpty()) { 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9000a60b3d32eae945688b69599f11679662657f751bungeman@google.com const SkMask* mask = &srcM; 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9020a60b3d32eae945688b69599f11679662657f751bungeman@google.com SkMask dstM; 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getMaskFilter() && 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) { 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask = &dstM; 906bf2ac7e52f84095368dc50600fd6e78cc96044e3bungeman@google.com } else { 907bf2ac7e52f84095368dc50600fd6e78cc96044e3bungeman@google.com dstM.fImage = NULL; 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 90902f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com SkAutoMaskFreeImage ami(dstM.fImage); 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 91141e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 912045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = blitterChooser.get(); 913045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 914045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper wrapper; 915045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRegion* clipRgn; 9168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 917045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 918045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &fRC->bwRgn(); 919045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 920045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com wrapper.init(*fRC, blitter); 921045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &wrapper.getRgn(); 922045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = wrapper.getBlitter(); 923045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 924045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter->blitMaskRegion(*mask, *clipRgn); 9258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 927ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.comstatic SkScalar fast_len(const SkVector& vec) { 928ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar x = SkScalarAbs(vec.fX); 929ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar y = SkScalarAbs(vec.fY); 930ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (x < y) { 931ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkTSwap(x, y); 932ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 933ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return x + SkScalarHalf(y); 934ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 935ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 936e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.orgbool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, 937e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkScalar* coverage) { 938e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkASSERT(strokeWidth > 0); 939e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org // We need to try to fake a thick-stroke with a modulated hairline. 940ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 9418d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (matrix.hasPerspective()) { 942ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 943ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 944ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 945ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkVector src[2], dst[2]; 946ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[0].set(strokeWidth, 0); 947ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[1].set(0, strokeWidth); 948ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com matrix.mapVectors(dst, src, 2); 949ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len0 = fast_len(dst[0]); 950ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len1 = fast_len(dst[1]); 951652807bbc8c57e5fa9622126b51fd369f5c67935agl@chromium.org if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { 95249f085dddff10473b6ebf832a974288300224e60bsalomon if (coverage) { 953e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org *coverage = SkScalarAve(len0, len1); 954e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 955ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return true; 956ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 957ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 958ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 959ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 960a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comvoid SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const { 961a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkDEBUGCODE(this->validate()); 962a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 963a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (fRC->isEmpty()) { 964a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; 965a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 966a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 967a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com { 968a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: Investigate optimizing these options. They are in the same 969a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // order as SkDraw::drawPath, which handles each case. It may be 970a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // that there is no way to optimize for these using the SkRRect path. 971a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkScalar coverage; 972a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) { 973a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 974a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 975a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 976a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 977a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 978a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 979a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 980a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getRasterizer()) { 981a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 982a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 983a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 984a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 985a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getMaskFilter()) { 986a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Transform the rrect into device space. 987a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRRect devRRect; 988a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (rrect.transform(*fMatrix, &devRRect)) { 98941e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 990868074b50b0fc3e460d2aa97c1096827fe0a1935reed if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get(), 991a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPaint::kFill_Style)) { 992a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; // filterRRect() called the blitter, so we're done 993a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 994a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 995a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 996a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 997a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comDRAW_PATH: 998a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Now fall back to the default case of using a path. 999a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPath path; 1000a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com path.addRRect(rrect); 1001a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com this->drawPath(path, paint, NULL, true); 1002a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 1003a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 100405d9044de4f1c6e791df66a425638752daac4c6breedstatic SkScalar compute_res_scale_for_stroking(const SkMatrix& matrix) { 100505d9044de4f1c6e791df66a425638752daac4c6breed if (!matrix.hasPerspective()) { 100605d9044de4f1c6e791df66a425638752daac4c6breed SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]); 100705d9044de4f1c6e791df66a425638752daac4c6breed SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY]); 100805d9044de4f1c6e791df66a425638752daac4c6breed if (SkScalarsAreFinite(sx, sy)) { 100905d9044de4f1c6e791df66a425638752daac4c6breed return SkTMax(sx, sy); 101005d9044de4f1c6e791df66a425638752daac4c6breed } 101105d9044de4f1c6e791df66a425638752daac4c6breed } 101205d9044de4f1c6e791df66a425638752daac4c6breed return 1; 101305d9044de4f1c6e791df66a425638752daac4c6breed} 101405d9044de4f1c6e791df66a425638752daac4c6breed 101532e5d97ccf60f859db063ebd6e903c362e625767reed@google.comvoid SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, 1016126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkMatrix* prePathMatrix, bool pathIsMutable, 101753f0959fc024c56dc55fe6bf86380127b59abec9krajcevski bool drawCoverage, SkBlitter* customBlitter) const { 1018f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1021045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* pathPtr = (SkPath*)&origSrcPath; 10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool doFill = true; 10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmpPath; 10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmpMatrix; 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 1030b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth tmpPath.setIsVolatile(true); 10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prePathMatrix) { 103332e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style || 103432e5d97ccf60f859db063ebd6e903c362e625767reed@google.com origPaint.getRasterizer()) { 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* result = pathPtr; 1036a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!pathIsMutable) { 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = &tmpPath; 10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathIsMutable = true; 10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*prePathMatrix, result); 10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = result; 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 104492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmpMatrix.setConcat(*matrix, *prePathMatrix); 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix = &tmpMatrix; 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // at this point we're done with prePathMatrix 10498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 1050a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 10515dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1052a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1053ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com { 1054dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com SkScalar coverage; 1055dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { 1056dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SK_Scalar1 == coverage) { 10575dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setStrokeWidth(0); 1058dcfb7cf336cafffd8d149c908b615e1deaa3a49begdaniel } else if (SkXfermode::SupportsCoverageAsAlpha(origPaint.getXfermode())) { 1059dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com U8CPU newAlpha; 1060dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#if 0 1061dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = SkToU8(SkScalarRoundToInt(coverage * 1062dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com origPaint.getAlpha())); 1063dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#else 1064dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // this is the old technique, which we preserve for now so 1065dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // we don't change previous results (testing) 1066dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // the new way seems fine, its just (a tiny bit) different 1067dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com int scale = (int)SkScalarMul(coverage, 256); 1068dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = origPaint.getAlpha() * scale >> 8; 1069dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#endif 10705dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkPaint* writablePaint = paint.writable(); 10715dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setStrokeWidth(0); 10725dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setAlpha(newAlpha); 1073dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com } 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1076a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 107732e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { 10784bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect; 10794bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com const SkRect* cullRectPtr = NULL; 10804bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (this->computeConservativeLocalClipBounds(&cullRect)) { 10814bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com cullRectPtr = &cullRect; 10824bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 108305d9044de4f1c6e791df66a425638752daac4c6breed doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr, 108405d9044de4f1c6e791df66a425638752daac4c6breed compute_res_scale_for_stroking(*fMatrix)); 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = &tmpPath; 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1087a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 108832e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()) { 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 109032e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()->rasterize(*pathPtr, *matrix, 1091045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com &fRC->getBounds(), paint->getMaskFilter(), &mask, 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 109332e5d97ccf60f859db063ebd6e903c362e625767reed@google.com this->drawDevMask(mask, *paint); 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(mask.fImage); 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // avoid possibly allocating a new path in transform if we can 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform the path into device space 11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*matrix, devPathPtr); 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 110553f0959fc024c56dc55fe6bf86380127b59abec9krajcevski SkBlitter* blitter = NULL; 110653f0959fc024c56dc55fe6bf86380127b59abec9krajcevski SkAutoBlitterChoose blitterStorage; 110753f0959fc024c56dc55fe6bf86380127b59abec9krajcevski if (NULL == customBlitter) { 110841e010cb901c0da9066c4df562030808c9ccd7f8reed blitterStorage.choose(fDst, *fMatrix, *paint, drawCoverage); 110953f0959fc024c56dc55fe6bf86380127b59abec9krajcevski blitter = blitterStorage.get(); 111053f0959fc024c56dc55fe6bf86380127b59abec9krajcevski } else { 111153f0959fc024c56dc55fe6bf86380127b59abec9krajcevski blitter = customBlitter; 111253f0959fc024c56dc55fe6bf86380127b59abec9krajcevski } 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11142ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org if (paint->getMaskFilter()) { 1115fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkPaint::Style style = doFill ? SkPaint::kFill_Style : 11162ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkPaint::kStroke_Style; 111753f0959fc024c56dc55fe6bf86380127b59abec9krajcevski if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, blitter, style)) { 11182ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org return; // filterPath() called the blitter, so we're done 11192ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org } 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1122045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*); 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (doFill) { 112432e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->isAntiAlias()) { 1125045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::AntiFillPath; 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1127045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::FillPath; 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // hairline 113032e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->isAntiAlias()) { 1131045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::AntiHairPath; 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::HairPath; 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 113653f0959fc024c56dc55fe6bf86380127b59abec9krajcevski proc(*devPathPtr, *fRC, blitter); 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11390baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com/** For the purposes of drawing bitmaps, if a matrix is "almost" translate 11400baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com go ahead and treat it as if it were, so that subsequent code can go fast. 11410baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com */ 11420baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.comstatic bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) { 1143070dcd8ad37a4c5b8a9015938409b27bb3ce3ab9reed@google.com unsigned bits = 0; // TODO: find a way to allow the caller to tell us to 1144070dcd8ad37a4c5b8a9015938409b27bb3ce3ab9reed@google.com // respect filtering. 1145070dcd8ad37a4c5b8a9015938409b27bb3ce3ab9reed@google.com return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits); 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, 11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 1150900ecf2f1579d42c9d2959831787af0346320f86reed@google.com SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType); 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1152a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com if (just_translate(*fMatrix, bitmap)) { 1153e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(fMatrix->getTranslateX()); 1154e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(fMatrix->getTranslateY()); 11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 115692fc2ae58331662ec411a048686cb4801e0a909areed SkAutoPixmapUnlock result; 115792fc2ae58331662ec411a048686cb4801e0a909areed if (!bitmap.requestLock(&result)) { 1158a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com return; 1159a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com } 116092fc2ae58331662ec411a048686cb4801e0a909areed const SkPixmap& pmap = result.pixmap(); 11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 116292fc2ae58331662ec411a048686cb4801e0a909areed mask.fBounds.set(ix, iy, ix + pmap.width(), iy + pmap.height()); 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 116492fc2ae58331662ec411a048686cb4801e0a909areed mask.fRowBytes = SkToU32(pmap.rowBytes()); 116592fc2ae58331662ec411a048686cb4801e0a909areed // fImage is typed as writable, but in this case it is used read-only 116692fc2ae58331662ec411a048686cb4801e0a909areed mask.fImage = (uint8_t*)pmap.addr8(0, 0); 1167a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // need to xform the bitmap first 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 1172a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapRect(&r); 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&mask.fBounds); 1177a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // set the mask's bounds to the transformed bitmap-bounds, 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // clipped to the actual device 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devBounds; 118241e010cb901c0da9066c4df562030808c9ccd7f8reed devBounds.set(0, 0, fDst.width(), fDst.height()); 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need intersect(l, t, r, b) on irect 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!mask.fBounds.intersect(devBounds)) { 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1188543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = SkAlign4(mask.fBounds.width()); 1191543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask.computeImageSize(); 1192543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 1193543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // the mask is too big to allocated, draw nothing 1194543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return; 1195543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // allocate (and clear) our temp buffer to hold the transformed bitmap 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMalloc storage(size); 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = (uint8_t*)storage.get(); 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask.fImage, 0, size); 1201a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now draw our bitmap(src) into mask(dst), transformed by the matrix 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap device; 1205a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()), 1206a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org mask.fImage, mask.fRowBytes); 1207a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas c(device); 12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need the unclipped top/left for the translate 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.translate(-SkIntToScalar(mask.fBounds.fLeft), 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.concat(*fMatrix); 12133469c76c40790b409621fd7eff34f56240718549reed@android.com 12143469c76c40790b409621fd7eff34f56240718549reed@android.com // We can't call drawBitmap, or we'll infinitely recurse. Instead 1215fb12c3e6ba84f95dc15fbaddc239dede0ba1d60ereed@android.com // we manually build a shader and draw that into our new mask 12163469c76c40790b409621fd7eff34f56240718549reed@android.com SkPaint tmpPaint; 12173469c76c40790b409621fd7eff34f56240718549reed@android.com tmpPaint.setFlags(paint.getFlags()); 121840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkAutoBitmapShaderInstall install(bitmap, tmpPaint); 12193469c76c40790b409621fd7eff34f56240718549reed@android.com SkRect rr; 12203469c76c40790b409621fd7eff34f56240718549reed@android.com rr.set(0, 0, SkIntToScalar(bitmap.width()), 12213469c76c40790b409621fd7eff34f56240718549reed@android.com SkIntToScalar(bitmap.height())); 122240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com c.drawRect(rr, install.paintWithShader()); 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1228045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipped_out(const SkMatrix& m, const SkRasterClip& c, 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& srcR) { 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect dstR; 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.mapRect(&dstR, srcR); 1232b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed return c.quickReject(dstR.roundOut()); 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1235045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip, 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width, int height) { 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return clipped_out(matrix, clip, r); 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1242c240e719b2bebd3711ade4e6fe056921aa7b0521reedstatic bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, const SkPixmap& pmap) { 1243c240e719b2bebd3711ade4e6fe056921aa7b0521reed return clip.isBW() || clip.quickContains(x, y, x + pmap.width(), y + pmap.height()); 1244045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1245045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 12470393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkRect* dstBounds, const SkPaint& origPaint) const { 1248f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1251045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1253900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1256a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 125740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint paint(origPaint); 125840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com paint.setStyle(SkPaint::kFill_Style); 1259a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 126192362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org matrix.setConcat(*fMatrix, prematrix); 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1263045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) { 12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1267868074b50b0fc3e460d2aa97c1096827fe0a1935reed if (bitmap.colorType() != kAlpha_8_SkColorType && just_translate(matrix, bitmap)) { 1268f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 1269f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // It is safe to call lock pixels now, since we know the matrix is 1270f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // (more or less) identity. 1271f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 1272c240e719b2bebd3711ade4e6fe056921aa7b0521reed SkAutoPixmapUnlock unlocker; 1273c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (!bitmap.requestLock(&unlocker)) { 1274f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com return; 1275f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com } 1276c240e719b2bebd3711ade4e6fe056921aa7b0521reed const SkPixmap& pmap = unlocker.pixmap(); 1277e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(matrix.getTranslateX()); 1278e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(matrix.getTranslateY()); 1279c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (clipHandlesSprite(*fRC, ix, iy, pmap)) { 1280a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator allocator; 1281a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 128241e010cb901c0da9066c4df562030808c9ccd7f8reed SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, paint, pmap, ix, iy, &allocator); 1283045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (blitter) { 1284c240e719b2bebd3711ade4e6fe056921aa7b0521reed SkScan::FillIRect(SkIRect::MakeXYWH(ix, iy, pmap.width(), pmap.height()), 1285c240e719b2bebd3711ade4e6fe056921aa7b0521reed *fRC, blitter); 1286045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1288c240e719b2bebd3711ade4e6fe056921aa7b0521reed // if !blitter, then we fall-through to the slower case 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1291a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now make a temp draw on the stack, and use it 12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 1296a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1297900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (bitmap.colorType() == kAlpha_8_SkColorType) { 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawBitmapAsMask(bitmap, paint); 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 130040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkAutoBitmapShaderInstall install(bitmap, paint); 13010393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkPaint& paintWithShader = install.paintWithShader(); 13020393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height()); 13030393912de72bc3d8b3640c122c53470dd0da1e6dreed if (dstBounds) { 13040393912de72bc3d8b3640c122c53470dd0da1e6dreed this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds); 13050393912de72bc3d8b3640c122c53470dd0da1e6dreed } else { 13060393912de72bc3d8b3640c122c53470dd0da1e6dreed draw.drawRect(srcBounds, paintWithShader); 13070393912de72bc3d8b3640c122c53470dd0da1e6dreed } 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1311c240e719b2bebd3711ade4e6fe056921aa7b0521reedvoid SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& origPaint) const { 1312f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 1313a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1315045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1317900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1321c240e719b2bebd3711ade4e6fe056921aa7b0521reed const SkIRect bounds = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1323045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->quickReject(bounds)) { 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // nothing to draw 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 132740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint paint(origPaint); 132840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com paint.setStyle(SkPaint::kFill_Style); 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1330c240e719b2bebd3711ade4e6fe056921aa7b0521reed SkAutoPixmapUnlock unlocker; 1331c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (!bitmap.requestLock(&unlocker)) { 1332c240e719b2bebd3711ade4e6fe056921aa7b0521reed return; 1333c240e719b2bebd3711ade4e6fe056921aa7b0521reed } 1334c240e719b2bebd3711ade4e6fe056921aa7b0521reed const SkPixmap& pmap = unlocker.pixmap(); 1335c240e719b2bebd3711ade4e6fe056921aa7b0521reed 1336c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, pmap)) { 1337a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator allocator; 1338a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 133941e010cb901c0da9066c4df562030808c9ccd7f8reed SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, paint, pmap, x, y, &allocator); 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (blitter) { 1341045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(bounds, *fRC, blitter); 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get a scalar version of our rect 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(bounds); 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13529c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org // create shader with offset 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(r.fLeft, r.fTop); 13549c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkAutoBitmapShaderInstall install(bitmap, paint, &matrix); 13559c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org const SkPaint& shaderPaint = install.paintWithShader(); 1356a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call ourself with a rect 1361a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com // is this OK if paint has a rasterizer? 136240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com draw.drawRect(r, shaderPaint); 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h" 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h" 1369e69137620ab0b5b40d230318c8e11b822f63cb9dreed@google.com#include "SkTextToPathIter.h" 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, 13738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char text[], size_t byteLength, SkVector* stopVector) { 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = 0, y = 0; 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoKern autokern; 1378a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't need x, y here, since all subpixel variants will have the 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // same advance 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += autokern.adjust(glyph) + glyph.fAdvanceX; 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y += glyph.fAdvanceY; 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(text == stop); 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13928128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.orgbool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) { 13938128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // hairline glyphs are fast enough so we don't need to cache them 13948128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 13958128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 13968128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 13978128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 13988128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // we don't cache perspective 13998128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (ctm.hasPerspective()) { 14008128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 14018128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 14028128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14038128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org SkMatrix textM; 14048128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM)); 14058128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org} 14068128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText_asPaths(const char text[], size_t byteLength, 14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 1410f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1412166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com SkTextToPathIter iter(text, byteLength, paint, true); 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setScale(iter.getPathScale(), iter.getPathScale()); 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(x, y); 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath* iterPath; 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar xpos, prevXPos = 0; 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14217b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com while (iter.next(&iterPath, &xpos)) { 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(xpos - prevXPos, 0); 14237b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (iterPath) { 14247b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com const SkPaint& pnt = iter.getPaint(); 14257b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (fDevice) { 14267b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com fDevice->drawPath(*this, *iterPath, pnt, &matrix, false); 14277b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } else { 14287b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com this->drawPath(*iterPath, pnt, &matrix, false); 14297b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } 1430f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevXPos = xpos; 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// disable warning : local variable used without having been initialized 1436a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#if defined _WIN32 && _MSC_VER >= 1300 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 ) 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 144379738cc7bf12d212bef4ff80591d1bf6f383663dbungemanstatic void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, const SkGlyph& glyph) { 1444d095f2bf06ca810844233bea9fb06de585643b32bungeman // Prevent glyphs from being drawn outside of or straddling the edge of device space. 1445d095f2bf06ca810844233bea9fb06de585643b32bungeman if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || 1446d095f2bf06ca810844233bea9fb06de585643b32bungeman (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) || 1447d095f2bf06ca810844233bea9fb06de585643b32bungeman (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || 1448d095f2bf06ca810844233bea9fb06de585643b32bungeman (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) 1449d095f2bf06ca810844233bea9fb06de585643b32bungeman { 1450d095f2bf06ca810844233bea9fb06de585643b32bungeman return; 1451d095f2bf06ca810844233bea9fb06de585643b32bungeman } 1452d095f2bf06ca810844233bea9fb06de585643b32bungeman 145379738cc7bf12d212bef4ff80591d1bf6f383663dbungeman int left = Sk48Dot16FloorToInt(fx); 145479738cc7bf12d212bef4ff80591d1bf6f383663dbungeman int top = Sk48Dot16FloorToInt(fy); 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 145683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkASSERT((NULL == state.fClip && state.fAAClip) || 145783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com (state.fClip && NULL == state.fAAClip && state.fClip->isRect())); 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int right = left + glyph.fWidth; 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bottom = top + glyph.fHeight; 14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1465fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkMask mask; 1466fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkIRect storage; 1467fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkIRect* bounds = &mask.fBounds; 146883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 146983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fBounds.set(left, top, right, bottom); 147083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 147183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com // this extra test is worth it, assuming that most of the time it succeeds 147283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com // since we can avoid writing to storage 147383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) { 147483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds)) 147583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com return; 147683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com bounds = &storage; 147783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 147883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 147983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com uint8_t* aa = (uint8_t*)glyph.fImage; 148083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 148183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com aa = (uint8_t*)state.fCache->findImage(glyph); 148283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 148383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com return; // can't rasterize glyph 14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 148583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 148783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fRowBytes = glyph.rowBytes(); 148883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 148983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fImage = aa; 14905bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com state.blitMask(mask, *bounds); 14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 149379738cc7bf12d212bef4ff80591d1bf6f383663dbungemanstatic void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, const SkGlyph& glyph) { 149479738cc7bf12d212bef4ff80591d1bf6f383663dbungeman int left = Sk48Dot16FloorToInt(fx); 149579738cc7bf12d212bef4ff80591d1bf6f383663dbungeman int top = Sk48Dot16FloorToInt(fy); 14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 149783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkASSERT(!state.fClip->isRect()); 14988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 150583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 150683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 150783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (!clipper.done()) { 150883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const SkIRect& cr = clipper.rect(); 150983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const uint8_t* aa = (const uint8_t*)glyph.fImage; 151083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 151183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com aa = (uint8_t*)state.fCache->findImage(glyph); 151283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 1513fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return; 15148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 151583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 151683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 151783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fRowBytes = glyph.rowBytes(); 151883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 151983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fImage = (uint8_t*)aa; 152083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com do { 15215bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com state.blitMask(mask, cr); 152283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com clipper.next(); 152383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } while (!clipper.done()); 152483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 15258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1527fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.comstatic bool hasCustomD1GProc(const SkDraw& draw) { 1528fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com return draw.fProcs && draw.fProcs->fD1GProc; 1529fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com} 1530fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com 1531fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.comstatic bool needsRasterTextBlit(const SkDraw& draw) { 1532fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com return !hasCustomD1GProc(draw); 1533fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com} 1534fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com 1535868074b50b0fc3e460d2aa97c1096827fe0a1935reedSkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, 1536868074b50b0fc3e460d2aa97c1096827fe0a1935reed const SkPaint& pnt) { 15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDraw = draw; 15382211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com fBlitter = blitter; 15392211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com fCache = cache; 15405bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com fPaint = &pnt; 15418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15429447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (cache->isSubpixel()) { 154379738cc7bf12d212bef4ff80591d1bf6f383663dbungeman fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); 15449447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } else { 154579738cc7bf12d212bef4ff80591d1bf6f383663dbungeman fHalfSampleX = fHalfSampleY = SK_ScalarHalf; 15469447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 15479447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 15481d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com if (hasCustomD1GProc(*draw)) { 1549045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // todo: fix this assumption about clips w/ custom 1550045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = draw->fClip; 1551045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipBounds = fClip->getBounds(); 15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return draw->fProcs->fD1GProc; 15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1555045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (draw->fRC->isBW()) { 1556045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fAAClip = NULL; 1557045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &draw->fRC->bwRgn(); 1558045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipBounds = fClip->getBounds(); 1559868074b50b0fc3e460d2aa97c1096827fe0a1935reed if (fClip->isRect()) { 1560868074b50b0fc3e460d2aa97c1096827fe0a1935reed return D1G_RectClip; 1561045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1562868074b50b0fc3e460d2aa97c1096827fe0a1935reed return D1G_RgnClip; 1563045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1564045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { // aaclip 1565045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fAAClip = &draw->fRC->aaRgn(); 1566045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = NULL; 1567045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipBounds = fAAClip->getBounds(); 1568868074b50b0fc3e460d2aa97c1096827fe0a1935reed return D1G_RectClip; 15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15725bdfb331ac650cf464baa96a49e2473ee10a515creed@google.comvoid SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const { 15735bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkASSERT(SkMask::kARGB32_Format == mask.fFormat); 15745bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 15755bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkBitmap bm; 1576a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()), 1577a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org (SkPMColor*)mask.fImage, mask.fRowBytes); 15785bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 15795bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint); 15805bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com} 15815bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText(const char text[], size_t byteLength, 15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) const { 15868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1588f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1591045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 15928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 15938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 159536d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // SkScalarRec doesn't currently have a way of representing hairline stroke and 159636d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // will fill if its frame-width is 0. 1597ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 15988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawText_asPaths(text, byteLength, x, y, paint); 15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1604e010f1c2a0e6fe9cbaa73be01c7d878308b5166creed SkAutoGlyphCache autoCache(paint, &fDevice->getLeakyProperties(), fMatrix); 16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkGlyphCache* cache = autoCache.getCache(); 1606a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 16078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform our starting point 16088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint loc; 16109447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fMatrix->mapXY(x, y, &loc); 16118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x = loc.fX; 16128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y = loc.fY; 16138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to measure first 16168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() != SkPaint::kLeft_Align) { 16178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector stop; 16188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com measure_text(cache, glyphCacheProc, text, byteLength, &stop); 16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar stopX = stop.fX; 16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar stopY = stop.fY; 16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 16258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopX = SkScalarHalf(stopX); 16268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopY = SkScalarHalf(stopY); 16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x -= stopX; 16298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y -= stopY; 16308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1631a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1634045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitter aaBlitter; 1635045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoBlitterChoose blitterChooser; 1636045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = NULL; 16371d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com if (needsRasterTextBlit(*this)) { 163841e010cb901c0da9066c4df562030808c9ccd7f8reed blitterChooser.choose(fDst, *fMatrix, paint); 1639045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = blitterChooser.get(); 1640045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isAA()) { 1641045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com aaBlitter.init(blitter, &fRC->aaRgn()); 1642045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = &aaBlitter; 1643045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 16441d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 16451d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com 16468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoKern autokern; 164752c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkDraw1Glyph d1g; 16485bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 16498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16509447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fxMask = ~0; 16519447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fyMask = ~0; 16529447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (cache->isSubpixel()) { 16539447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); 16549447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (kX_SkAxisAlignment == baseline) { 16559447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fyMask = 0; 165679738cc7bf12d212bef4ff80591d1bf6f383663dbungeman d1g.fHalfSampleY = SK_ScalarHalf; 16579447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } else if (kY_SkAxisAlignment == baseline) { 16589447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fxMask = 0; 165979738cc7bf12d212bef4ff80591d1bf6f383663dbungeman d1g.fHalfSampleX = SK_ScalarHalf; 16609447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 16619447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 16629447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 166379738cc7bf12d212bef4ff80591d1bf6f383663dbungeman Sk48Dot16 fx = SkScalarTo48Dot16(x + d1g.fHalfSampleX); 166479738cc7bf12d212bef4ff80591d1bf6f383663dbungeman Sk48Dot16 fy = SkScalarTo48Dot16(y + d1g.fHalfSampleY); 16659447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 16668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 16672211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); 16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx += autokern.adjust(glyph); 16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph.fWidth) { 167252c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com proc(d1g, fx, fy, glyph); 16738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1674d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 16758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx += glyph.fAdvanceX; 16768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy += glyph.fAdvanceY; 16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 16818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1682ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comvoid SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 168305c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkScalar pos[], int scalarsPerPosition, 168405c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkPoint& offset, const SkPaint& origPaint) const { 1685ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com // setup our std paint, in hopes of getting hits in the cache 1686ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkPaint paint(origPaint); 1687ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkScalar matrixScale = paint.setupForAsPaths(); 1688ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 16895a64902ee92847f53dfc5b211da19d074179be64reed@google.com SkMatrix matrix; 16905a64902ee92847f53dfc5b211da19d074179be64reed@google.com matrix.setScale(matrixScale, matrixScale); 16918f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 16924e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 16934e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setStyle(SkPaint::kFill_Style); 16944e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setPathEffect(NULL); 16954e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org 1696ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1697ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkAutoGlyphCache autoCache(paint, NULL, NULL); 1698ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkGlyphCache* cache = autoCache.getCache(); 1699ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 1700ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const char* stop = text + byteLength; 170179738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkTextAlignProc alignProc(paint.getTextAlign()); 170205c4a4322e7d4f3417b7df33825bab8603d52051fmalita SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 17038f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 17044e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org // Now restore the original settings, so we "draw" with whatever style/stroking. 17054e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setStyle(origPaint.getStyle()); 17064e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setPathEffect(origPaint.getPathEffect()); 17074e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org 1708ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com while (text < stop) { 1709ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1710ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (glyph.fWidth) { 1711ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkPath* path = cache->findPath(glyph); 1712ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (path) { 1713cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkPoint tmsLoc; 1714cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen tmsProc(pos, &tmsLoc); 1715cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com SkPoint loc; 1716cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen alignProc(tmsLoc, glyph, &loc); 17178f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 1718cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransX] = loc.fX; 1719cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransY] = loc.fY; 17205a64902ee92847f53dfc5b211da19d074179be64reed@google.com if (fDevice) { 17215a64902ee92847f53dfc5b211da19d074179be64reed@google.com fDevice->drawPath(*this, *path, paint, &matrix, false); 17225a64902ee92847f53dfc5b211da19d074179be64reed@google.com } else { 17235a64902ee92847f53dfc5b211da19d074179be64reed@google.com this->drawPath(*path, paint, &matrix, false); 17245a64902ee92847f53dfc5b211da19d074179be64reed@google.com } 1725ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1726ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1727ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com pos += scalarsPerPosition; 1728ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1729ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com} 1730ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPosText(const char text[], size_t byteLength, 173205c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkScalar pos[], int scalarsPerPosition, 173305c4a4322e7d4f3417b7df33825bab8603d52051fmalita const SkPoint& offset, const SkPaint& paint) const { 17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 17368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1737f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 17388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1740045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 17418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1744ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 174505c4a4322e7d4f3417b7df33825bab8603d52051fmalita this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, offset, paint); 17468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 17478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1750e010f1c2a0e6fe9cbaa73be01c7d878308b5166creed SkAutoGlyphCache autoCache(paint, &fDevice->getLeakyProperties(), fMatrix); 17518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkGlyphCache* cache = autoCache.getCache(); 1752a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1753045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper wrapper; 1754045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoBlitterChoose blitterChooser; 1755045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = NULL; 17561d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com if (needsRasterTextBlit(*this)) { 175741e010cb901c0da9066c4df562030808c9ccd7f8reed blitterChooser.choose(fDst, *fMatrix, paint); 1758045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = blitterChooser.get(); 1759045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isAA()) { 1760045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com wrapper.init(*fRC, blitter); 1761045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = wrapper.getBlitter(); 1762045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 17631d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 1764fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 1766cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkTextAlignProc alignProc(paint.getTextAlign()); 17672211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com SkDraw1Glyph d1g; 17685bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 176905c4a4322e7d4f3417b7df33825bab8603d52051fmalita SkTextMapStateProc tmsProc(*fMatrix, offset, scalarsPerPosition); 17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17712211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com if (cache->isSubpixel()) { 17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // maybe we should skip the rounding if linearText is set 17739447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); 17749447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 17759447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fxMask = ~0; 17769447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fyMask = ~0; 17779447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (kX_SkAxisAlignment == baseline) { 17789447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fyMask = 0; 177979738cc7bf12d212bef4ff80591d1bf6f383663dbungeman d1g.fHalfSampleY = SK_ScalarHalf; 17809447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } else if (kY_SkAxisAlignment == baseline) { 17819447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fxMask = 0; 178279738cc7bf12d212bef4ff80591d1bf6f383663dbungeman d1g.fHalfSampleX = SK_ScalarHalf; 17839447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 17848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkPaint::kLeft_Align == paint.getTextAlign()) { 17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 1787cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkPoint tmsLoc; 1788cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen tmsProc(pos, &tmsLoc); 1789a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 179079738cc7bf12d212bef4ff80591d1bf6f383663dbungeman Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + d1g.fHalfSampleX); 179179738cc7bf12d212bef4ff80591d1bf6f383663dbungeman Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + d1g.fHalfSampleY); 179279738cc7bf12d212bef4ff80591d1bf6f383663dbungeman 179379738cc7bf12d212bef4ff80591d1bf6f383663dbungeman const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); 1794a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph.fWidth) { 1796f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com proc(d1g, fx, fy, glyph); 17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos += scalarsPerPosition; 17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 18029330cfe851b14b8985acc14caa3dc5ad20b0b2a8bungeman@google.com const char* currentText = text; 18039447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); 1804a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18059447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (metricGlyph.fWidth) { 18069447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) 18079447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) 1808cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkPoint tmsLoc; 1809cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen tmsProc(pos, &tmsLoc); 1810a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 181179738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkPoint alignLoc; 181279738cc7bf12d212bef4ff80591d1bf6f383663dbungeman alignProc(tmsLoc, metricGlyph, &alignLoc); 181379738cc7bf12d212bef4ff80591d1bf6f383663dbungeman 181479738cc7bf12d212bef4ff80591d1bf6f383663dbungeman Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + d1g.fHalfSampleX); 181579738cc7bf12d212bef4ff80591d1bf6f383663dbungeman Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + d1g.fHalfSampleY); 1816a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // have to call again, now that we've been "aligned" 18189447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, 18199447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fx & fxMask, fy & fyMask); 18209447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com // the assumption is that the metrics haven't changed 18219447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkASSERT(prevAdvX == glyph.fAdvanceX); 18229447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkASSERT(prevAdvY == glyph.fAdvanceY); 18239447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkASSERT(glyph.fWidth); 1824a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18259447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com proc(d1g, fx, fy, glyph); 18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos += scalarsPerPosition; 18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // not subpixel 1831aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com if (SkPaint::kLeft_Align == paint.getTextAlign()) { 1832aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com while (text < stop) { 1833aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com // the last 2 parameters are ignored 1834aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1835fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1836aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com if (glyph.fWidth) { 1837cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkPoint tmsLoc; 1838cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen tmsProc(pos, &tmsLoc); 1839a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1840aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com proc(d1g, 184179738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkScalarTo48Dot16(tmsLoc.fX + SK_ScalarHalf), //d1g.fHalfSampleX, 184279738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf), //d1g.fHalfSampleY, 1843aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com glyph); 1844aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } 1845aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com pos += scalarsPerPosition; 1846aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } 1847aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } else { 1848aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com while (text < stop) { 1849aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com // the last 2 parameters are ignored 1850aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1851a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1852aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com if (glyph.fWidth) { 1853cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkPoint tmsLoc; 1854cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen tmsProc(pos, &tmsLoc); 1855a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 185679738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkPoint alignLoc; 185779738cc7bf12d212bef4ff80591d1bf6f383663dbungeman alignProc(tmsLoc, glyph, &alignLoc); 1858aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com 1859aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com proc(d1g, 186079738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkScalarTo48Dot16(alignLoc.fX + SK_ScalarHalf), //d1g.fHalfSampleX, 186179738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf), //d1g.fHalfSampleY, 1862aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com glyph); 1863aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } 1864aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com pos += scalarsPerPosition; 18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18765dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreedstatic SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) { 18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 18788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool texture_to_matrix(const VertState& state, const SkPoint verts[], 18818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint texs[], SkMatrix* matrix) { 18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src[3], dst[3]; 1883a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[0] = texs[state.f0]; 18858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[1] = texs[state.f1]; 18868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[2] = texs[state.f2]; 18878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[0] = verts[state.f0]; 18888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[1] = verts[state.f1]; 18898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[2] = verts[state.f2]; 18908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return matrix->setPolyToPoly(src, dst, 3); 18918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkTriColorShader : public SkShader { 18948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTriColorShader() {} 18968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 189736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein size_t contextSize() const override; 1898a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 189987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org class TriColorShaderContext : public SkShader::Context { 190087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org public: 1901e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&); 190287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual ~TriColorShaderContext(); 190387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 190487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 190587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 190636352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void shadeSpan(int x, int y, SkPMColor dstC[], int count) override; 190787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 190887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org private: 190987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkMatrix fDstToUnit; 191087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor fColors[3]; 191187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 191287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org typedef SkShader::Context INHERITED; 191387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org }; 1914a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19150f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 19167e44bb191633e225fd0455c267dbf67f9ee8633emtklein 19177e44bb191633e225fd0455c267dbf67f9ee8633emtklein // For serialization. This will never be called. 191836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein Factory getFactory() const override { sk_throw(); return NULL; } 1919ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com 19208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 192136352bf5e38f45a70ee4f4fc132a38048d38206dmtklein Context* onCreateContext(const ContextRec& rec, void* storage) const override { 1922ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec)); 1923ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 1924ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org 19258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 19268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShader INHERITED; 19278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 19288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 192987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgbool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], 193087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int index0, int index1, int index2) { 1931a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[0] = SkPreMultiplyColor(colors[index0]); 19338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[1] = SkPreMultiplyColor(colors[index1]); 19348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[2] = SkPreMultiplyColor(colors[index2]); 1935a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m, im; 19378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.reset(); 19388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(0, pts[index1].fX - pts[index0].fX); 19398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(1, pts[index2].fX - pts[index0].fX); 19408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(2, pts[index0].fX); 19418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(3, pts[index1].fY - pts[index0].fY); 19428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(4, pts[index2].fY - pts[index0].fY); 19438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(5, pts[index0].fY); 19448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!m.invert(&im)) { 19458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 194780116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix 194880116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org // as our interators are intrinsically tied to the vertices, and nothing else. 194980116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org SkMatrix ctmInv; 195080116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org if (!this->getCTM().invert(&ctmInv)) { 195180116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org return false; 195280116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org } 195380116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org fDstToUnit.setConcat(im, ctmInv); 195492362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return true; 19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 1958689411a87ca7d19abe04b5c9baff26bd96b2123ereed@android.com#include "SkComposeShader.h" 19598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int ScalarTo256(SkScalar v) { 19618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale = SkScalarToFixed(v) >> 8; 19628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale < 0) { 19638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale = 0; 19648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale > 255) { 19668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale = 255; 19678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkAlpha255To256(scale); 19698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 197187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 1972e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader, 1973e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const ContextRec& rec) 1974e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) {} 197587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 197687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} 197787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 197887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkTriColorShader::contextSize() const { 197987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(TriColorShaderContext); 198087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 198187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 198206a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org const int alphaScale = Sk255To256(this->getPaintAlpha()); 198306a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 19848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src; 1985a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); 19888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += 1; 1989a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale1 = ScalarTo256(src.fX); 19918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale2 = ScalarTo256(src.fY); 19928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale0 = 256 - scale1 - scale2; 19938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale0 < 0) { 19948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale1 > scale2) { 19958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale2 = 256 - scale1; 19968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale1 = 256 - scale2; 19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale0 = 0; 20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2001a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 200206a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org if (256 != alphaScale) { 200306a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale0 = SkAlphaMul(scale0, alphaScale); 200406a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale1 = SkAlphaMul(scale1, alphaScale); 200506a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale2 = SkAlphaMul(scale2, alphaScale); 200606a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org } 200706a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 20088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 200906a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[1], scale1) + 201006a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[2], scale2); 20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20140f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 201576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkTriColorShader::toString(SkString* str) const { 201676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkTriColorShader: ("); 201776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 201876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 201976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 202076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 202176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 202276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 202376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, 20258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint vertices[], const SkPoint textures[], 20268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 20278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 202949f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(0 == count || vertices); 2030a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // abort early if there is nothing to draw 2032045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { 20338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 20348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2035a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform out vertices into device coordinates 20378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoSTMalloc<16, SkPoint> storage(count); 20388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* devVerts = storage.get(); 20398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapPoints(devVerts, vertices, count); 2040a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 20428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com We can draw the vertices in 1 of 4 ways: 20438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - solid color (no shader/texture[], no colors[]) 20458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just colors (no shader/texture[], has colors[]) 20468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just texture (has shader/texture[], no colors[]) 20478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - colors * texture (has shader/texture[], has colors[]) 2048a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Thus for texture drawing, we need both texture[] and a shader. 20508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 20518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTriColorShader triShader; // must be above declaration of p 20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 20548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = p.getShader(); 20568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == shader) { 20578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we have no shader, we ignore the texture coordinates 20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com textures = NULL; 20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (NULL == textures) { 20608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we don't have texture coordinates, ignore the shader 20618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setShader(NULL); 20628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader = NULL; 20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup the custom shader (if needed) 206687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkAutoTUnref<SkComposeShader> composeShader; 206749f085dddff10473b6ebf832a974288300224e60bsalomon if (colors) { 20688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == textures) { 20698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // just colors (no texture) 2070a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com shader = p.setShader(&triShader); 20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 20728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // colors * texture 20738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(shader); 20748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool releaseMode = false; 20758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == xmode) { 20768d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com xmode = SkXfermode::Create(SkXfermode::kModulate_Mode); 20778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com releaseMode = true; 20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 207987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode))); 208087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org p.setShader(composeShader); 20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (releaseMode) { 20828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com xmode->unref(); 20838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 208741e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, p); 208887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Abort early if we failed to create a shader context. 2089ea033606a06d05d2d42aa7118409fee798e53167reed@google.com if (blitter->isNullBlitter()) { 2090ea033606a06d05d2d42aa7118409fee798e53167reed@google.com return; 2091ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 2092ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 20938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup our state and function pointer for iterating triangles 20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState state(count, indices, indexCount); 20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState::Proc vertProc = state.chooseProc(vmode); 2096a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 209749f085dddff10473b6ebf832a974288300224e60bsalomon if (textures || colors) { 20988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 209949f085dddff10473b6ebf832a974288300224e60bsalomon if (textures) { 210080116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org SkMatrix tempM; 21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (texture_to_matrix(state, vertices, textures, &tempM)) { 210256263c78d86cb536d463b8d46f00ac44cad3defbreed SkShader::ContextRec rec(p, *fMatrix, &tempM); 210380116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org if (!blitter->resetShaderContext(rec)) { 21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 210849f085dddff10473b6ebf832a974288300224e60bsalomon if (colors) { 210987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Find the context for triShader. 211087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkTriColorShader::TriColorShaderContext* triColorShaderContext; 211187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 211287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext = blitter->getShaderContext(); 211387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(shaderContext); 211487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (p.getShader() == &triShader) { 211587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org triColorShaderContext = 211687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext); 211787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else { 211887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // The shader is a compose shader and triShader is its first shader. 211987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(p.getShader() == composeShader); 212087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(composeShader->getShaderA() == &triShader); 212187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkComposeShader::ComposeShaderContext* composeShaderContext = 212287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext); 212387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA(); 212487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org triColorShaderContext = 212587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA); 212687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 212787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 212887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (!triColorShaderContext->setup(vertices, colors, 212987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org state.f0, state.f1, state.f2)) { 21308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2133045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2134045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPoint tmp[] = { 2135045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 2136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com }; 2137045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillTriangle(tmp, *fRC, blitter.get()); 21388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2140559a8833f0eae4af37dc0ffc3ee97e1fb14817b1commit-bot@chromium.org // no colors[] and no texture, stroke hairlines with paint's color. 21415dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias()); 2142045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip& clip = *fRC; 21438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 21445dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkPoint array[] = { 21455dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0] 21465dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed }; 21475dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed hairProc(array, 4, clip, blitter.get()); 21488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21520a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 21530a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 21548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2157f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkDraw::validate() const { 21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMatrix != NULL); 21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fClip != NULL); 2160045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fRC != NULL); 21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2162045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& cr = fRC->getBounds(); 21638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect br; 21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 216541e010cb901c0da9066c4df562030808c9ccd7f8reed br.set(0, 0, fDst.width(), fDst.height()); 21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cr.isEmpty() || br.contains(cr)); 21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////////// 21728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 21758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h" 21768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 21778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 2179b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed const SkMaskFilter* filter, const SkMatrix* filterMatrix, 21808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect* bounds) { 21818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (devPath.isEmpty()) { 21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 21838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // init our bounds from the path 218611fa2247b747eb75e2f158dc7571d458ed6c0115reed *bounds = devPath.getBounds().makeOutset(SK_ScalarHalf, SK_ScalarHalf).roundOut(); 2187a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21886db75fc2c393ba86a3f533597a8bcd348477e79ctomhudson@google.com SkIPoint margin = SkIPoint::Make(0, 0); 21898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (filter) { 21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(filterMatrix); 2191a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21925af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkMask srcM, dstM; 2193a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fBounds = *bounds; 21958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fFormat = SkMask::kA8_Format; 21968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fImage = NULL; 21978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 21988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 21998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2201a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 22025af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com // (possibly) trim the bounds to reflect the clip 22038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (plus whatever slop the filter needs) 22045af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (clipBounds) { 22053555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // Ugh. Guard against gigantic margins from wacky filters. Without this 22063555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // check we can request arbitrary amounts of slop beyond our visible 22073555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // clip, and bring down the renderer (at least on finite RAM machines 22083555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // like handsets, etc.). Need to balance this invented value between 22093555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // quality of large filters like blurs, and the corresponding memory 22103555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // requests. 22113555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com static const int MAX_MARGIN = 128; 221211fa2247b747eb75e2f158dc7571d458ed6c0115reed if (!bounds->intersect(clipBounds->makeOutset(SkMin32(margin.fX, MAX_MARGIN), 221311fa2247b747eb75e2f158dc7571d458ed6c0115reed SkMin32(margin.fY, MAX_MARGIN)))) { 22145af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com return false; 22155af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 22198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 222141e010cb901c0da9066c4df562030808c9ccd7f8reedstatic void draw_into_mask(const SkMask& mask, const SkPath& devPath, SkPaint::Style style) { 222241e010cb901c0da9066c4df562030808c9ccd7f8reed SkDraw draw; 222341e010cb901c0da9066c4df562030808c9ccd7f8reed if (!draw.fDst.reset(mask)) { 222441e010cb901c0da9066c4df562030808c9ccd7f8reed return; 222541e010cb901c0da9066c4df562030808c9ccd7f8reed } 222641e010cb901c0da9066c4df562030808c9ccd7f8reed 2227045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip clip; 2228045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMatrix matrix; 2229045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPaint paint; 22308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2231045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height())); 22328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 22338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 22348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2235045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com draw.fRC = &clip; 2236045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com draw.fClip = &clip.bwRgn(); 22378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setAntiAlias(true); 22392ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org paint.setStyle(style); 22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawPath(devPath, paint); 22418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 224430711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com const SkMaskFilter* filter, const SkMatrix* filterMatrix, 22452ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkMask* mask, SkMask::CreateMode mode, 22462ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkPaint::Style style) { 22478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustRenderImage_CreateMode != mode) { 22488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 22498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2251a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 22528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fFormat = SkMask::kA8_Format; 22548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fRowBytes = mask->fBounds.width(); 2255543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask->computeImageSize(); 2256543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 2257543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // we're too big to allocate the mask, abort 2258543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; 2259543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 2260543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com mask->fImage = SkMask::AllocImage(size); 22618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask->fImage, 0, mask->computeImageSize()); 22628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustComputeBounds_CreateMode != mode) { 22652ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org draw_into_mask(*mask, devPath, style); 22668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2267a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 22688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2270