SkDraw.cpp revision 06a32062620daee7a93742f553829a8d4f93f720
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.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" 2732e5d97ccf60f859db063ebd6e903c362e625767reed@google.com#include "SkTLazy.h" 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAutoKern.h" 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcShader.h" 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawProcs.h" 33ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com#include "SkMatrixUtils.h" 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 35a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define TRACE_BITMAP_DRAWS 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 39fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com/** Helper for allocating small blitters on the stack. 40fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com */ 4140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.comclass SkAutoBlitterChoose : SkNoncopyable { 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 431d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkAutoBlitterChoose() { 441d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com fBlitter = NULL; 451d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix, 47126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkPaint& paint, bool drawCoverage = false) { 48a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator, 49a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org drawCoverage); 50e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org } 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* operator->() { return fBlitter; } 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* get() const { return fBlitter; } 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 551d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com void choose(const SkBitmap& device, const SkMatrix& matrix, 561d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com const SkPaint& paint) { 571d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkASSERT(!fBlitter); 58a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator); 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 */ { 78a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org fPaint.setShader(CreateBitmapShader(src, SkShader::kClamp_TileMode, 79a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkShader::kClamp_TileMode, 809c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org 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 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap, 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint, 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t* data) { 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // todo: we can apply colorfilter up front if no shader, so we wouldn't 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to abort this fastpath 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getShader() || paint.getColorFilter()) { 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 162845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode; 163be2aa2aa1f8bf73d974bdd9438fc741bbf0cfbe6mike@reedtribe.org if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 166a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColor color = paint.getColor(); 168a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // collaps modes based on color... 170845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode == mode) { 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned alpha = SkColorGetA(color); 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == alpha) { 173845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com mode = SkXfermode::kDst_Mode; 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (0xFF == alpha) { 175845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com mode = SkXfermode::kSrc_Mode; 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 178a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 180845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kClear_Mode: 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Clear_BitmapXferProc\n"); 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Clear_BitmapXferProc; // ignore data 183845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kDst_Mode: 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Dst_BitmapXferProc\n"); 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Dst_BitmapXferProc; // ignore data 186845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kSrc_Mode: { 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 188a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com should I worry about dithering for the lower depths? 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor pmc = SkPreMultiplyColor(color); 191900ecf2f1579d42c9d2959831787af0346320f86reed@google.com switch (bitmap.colorType()) { 19228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = pmc; 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D32_Src_BitmapXferProc\n"); 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D32_Src_BitmapXferProc; 198900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkPixel32ToPixel16(pmc); 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D16_Src_BitmapXferProc\n"); 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D16_Src_BitmapXferProc; 204900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkGetPackedA32(pmc); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- DA8_Src_BitmapXferProc\n"); 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return DA8_Src_BitmapXferProc; 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect, 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BitmapXferProc proc, uint32_t procData) { 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int shiftPerPixel; 224900ecf2f1579d42c9d2959831787af0346320f86reed@google.com switch (bitmap.colorType()) { 22528fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 2; 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 228900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 1; 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 231900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 0; 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2350c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("Can't use xferproc on this config"); 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* pixels = (uint8_t*)bitmap.getPixels(); 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pixels); 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t rowBytes = bitmap.rowBytes(); 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int widthBytes = rect.width() << shiftPerPixel; 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip down to the first scanline and X position 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel); 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int scans = rect.height() - 1; scans >= 0; --scans) { 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(pixels, widthBytes, procData); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rowBytes; 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPaint(const SkPaint& paint) const { 253f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 255045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devRect; 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com devRect.set(0, 0, fBitmap->width(), fBitmap->height()); 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doIRect(devRect)) { 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 264a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 265045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 266045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com /* If we don't have a shader (i.e. we're just a solid color) we may 267045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com be faster to operate directly on the device bitmap, rather than invoking 268045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a blitter. Esp. true for xfermodes, which require a colorshader to be 269045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com present, which is just redundant work. Since we're drawing everywhere 270045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com in the clip, we don't have to worry about antialiasing. 271045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 272045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint32_t procData = 0; // to avoid the warning 273045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData); 274045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (proc) { 275045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (D_Dst_BitmapXferProc == proc) { // nothing to do 276045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 277045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 278a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 279045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRegion::Iterator iter(fRC->bwRgn()); 280045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 281045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData); 282045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 283045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 284045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 287045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 288045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // normal case: use a blitter 289045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 290045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(devRect, *fRC, blitter.get()); 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct PtProcRec { 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::PointMode fMode; 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* fClip; 299045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip* fRC; 300a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // computed values 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fRadius; 303a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter*); 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix, 308045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip*); 309045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Proc chooseProc(SkBlitter** blitter); 310045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 311045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 312045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper fWrapper; 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec.fClip->isRect()); 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = rec.fClip->getBounds(); 319a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3212d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3222d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_16_hair_proc(const PtProcRec& rec, 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint devPts[], int count, 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter) { 332045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rec.fRC->isRect()); 333045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value); 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bitmap); 337c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* addr = bitmap->getAddr16(0, 0); 339e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com size_t rb = bitmap->rowBytes(); 340c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3422d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3432d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value); 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3502d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.comstatic void bw_pt_rect_32_hair_proc(const PtProcRec& rec, 3512d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkPoint devPts[], int count, 3522d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkBlitter* blitter) { 3532d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(rec.fRC->isRect()); 3542d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3552d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com uint32_t value; 3562d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value); 3572d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(bitmap); 358c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3592d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkPMColor* addr = bitmap->getAddr32(0, 0); 360e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com size_t rb = bitmap->rowBytes(); 361c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3622d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com for (int i = 0; i < count; i++) { 3632d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3642d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3652d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (r.contains(x, y)) { 3662d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com ((SkPMColor*)((char*)addr + y * rb))[x] = value; 3672d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3682d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3692d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com} 3702d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 374e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 375e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec.fClip->contains(x, y)) { 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 385045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count - 1; i++) { 392045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// aa versions 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 401045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count - 1; i++) { 408045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 420c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 426c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 427045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillXRect(r, *rec.fRC, blitter); 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 437a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 443a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 444045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::AntiFillXRect(r, *rec.fRC, blitter); 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 448b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com// If this guy returns true, then chooseProc() must return a valid proc 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 450045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMatrix* matrix, const SkRasterClip* rc) { 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect()) { 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width = paint.getStrokeWidth(); 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == width) { 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 458045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = NULL; 459045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 4602d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com fRadius = SK_FixedHalf; 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 463b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com if (paint.getStrokeCap() != SkPaint::kRound_Cap && 464b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com matrix->rectStaysRect() && SkCanvas::kPoints_PointMode == mode) { 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = matrix->get(SkMatrix::kMScaleX); 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = matrix->get(SkMatrix::kMScaleY); 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(sx - sy)) { 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sx < 0) { 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sx = -sx; 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 474045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = NULL; 475045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1; 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 483045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comPtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { 484b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com Proc proc = NULL; 485a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 486045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = *blitterPtr; 487045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 488045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fRC->bwRgn(); 489045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 490045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fWrapper.init(*fRC, blitter); 491045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fWrapper.getRgn(); 492045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = fWrapper.getBlitter(); 493045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *blitterPtr = blitter; 494045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 495045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for our arrays 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == SkCanvas::kPoints_PointMode); 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == SkCanvas::kLines_PointMode); 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(2 == SkCanvas::kPolygon_PointMode); 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5022d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fPaint->isAntiAlias()) { 5032d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (0 == fPaint->getStrokeWidth()) { 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const Proc gAAProcs[] = { 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gAAProcs[fMode]; 5082d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 5092d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(SkCanvas::kPoints_PointMode == fMode); 5102d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = aa_square_proc; 5112d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 5122d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else { // BW 5132d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fRadius <= SK_FixedHalf) { // small radii and hairline 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bm = blitter->justAnOpaqueColor(&value); 517900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (bm && kRGB_565_SkColorType == bm->colorType()) { 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_16_hair_proc; 51928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org } else if (bm && kN32_SkColorType == bm->colorType()) { 5202d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = bw_pt_rect_32_hair_proc; 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_hair_proc; 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static Proc gBWProcs[] = { 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gBWProcs[fMode]; 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_square_proc; 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return proc; 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode, 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t count, const SkPoint pts[], 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint, const SkMatrix& matrix) { 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ibounds; 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect bounds; 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar inset = paint.getStrokeWidth(); 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 544a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org bounds.set(pts, SkToInt(count)); 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.inset(-inset, -inset); 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.mapRect(&bounds); 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.roundOut(&ibounds); 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder->doIRect(ibounds); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// each of these costs 8-bytes of stack space, so don't make it too large 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// must be even for lines/polygon to work 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_DEV_PTS 32 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 557f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkPoint pts[], const SkPaint& paint, 558f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com bool forceUseDevice) const { 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're in lines mode, force count to be even 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kLines_PointMode == mode) { 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count &= ~(size_t)1; 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 567a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 569f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 570a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 572045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 576fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com if (fBounder) { 577fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) { 578fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com return; 579fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com } 580fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 581fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com // clear the bounder and call this again, so we don't invoke the bounder 582fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com // later if we happen to call ourselves for drawRect, drawPath, etc. 583fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com SkDraw noBounder(*this); 584fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com noBounder.fBounder = NULL; 585fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com noBounder.drawPoints(mode, count, pts, paint, forceUseDevice); 586fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com return; 587fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com } 588fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PtProcRec rec; 590045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) { 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint devPts[MAX_DEV_PTS]; 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* bltr = blitter.get(); 596045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com PtProcRec::Proc proc = rec.chooseProc(&bltr); 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we have to back up subsequent passes if we're in polygon mode 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 599a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 601a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org int n = SkToInt(count); 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (n > MAX_DEV_PTS) { 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = MAX_DEV_PTS; 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->mapPoints(devPts, pts, n); 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(rec, devPts, n, bltr); 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts += n - backup; 608a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org SkASSERT(SkToInt(count) >= n); 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= n; 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += backup; 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count != 0); 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPoints_PointMode: { 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // temporarily mark the paint as filling. 61840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint newPaint(paint); 61940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com newPaint.setStyle(SkPaint::kFill_Style); 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 62140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkScalar width = newPaint.getStrokeWidth(); 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar radius = SkScalarHalf(width); 623a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 62440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) { 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix preMatrix; 627a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addCircle(0, 0, radius); 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com preMatrix.setTranslate(pts[i].fX, pts[i].fY); 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // pass true for the last point, since we can modify 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // then path then 633f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 63440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com fDevice->drawPath(*this, path, newPaint, &preMatrix, 635f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com (count-1) == i); 636f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 63740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com this->drawPath(path, newPaint, &preMatrix, 63840c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com (count-1) == i); 639f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 643a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = pts[i].fX - radius; 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = pts[i].fY - radius; 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = r.fLeft + width; 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = r.fTop + width; 649f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 65040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com fDevice->drawRect(*this, r, newPaint); 651f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 65240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com this->drawRect(r, newPaint); 653f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kLines_PointMode: 659629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com#ifndef SK_DISABLE_DASHING_OPTIMIZATION 660629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com if (2 == count && NULL != paint.getPathEffect()) { 661629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // most likely a dashed line - see if it is one of the ones 662629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // we can accelerate 663629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkStrokeRec rec(paint); 6646d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkPathEffect::PointData pointData; 665629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 666629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPath path; 667629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.moveTo(pts[0]); 668629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.lineTo(pts[1]); 669629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6704bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect = SkRect::Make(fRC->getBounds()); 6714024f32d99b63a599c544a49f526e53c25135159skia.committer@gmail.com 6724bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (paint.getPathEffect()->asPoints(&pointData, path, rec, 6734bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com *fMatrix, &cullRect)) { 6746d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // 'asPoints' managed to find some fast path 6756d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 676629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPaint newP(paint); 677629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com newP.setPathEffect(NULL); 678935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com newP.setStyle(SkPaint::kFill_Style); 679629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6806d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fFirst.isEmpty()) { 6816d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6826d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawPath(*this, pointData.fFirst, newP); 6836d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6846d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fFirst, newP); 6856d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 686629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 6876d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6886d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fLast.isEmpty()) { 6896d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 6906d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawPath(*this, pointData.fLast, newP); 6916d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6926d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fLast, newP); 6936d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6946d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6956d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6966d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (pointData.fSize.fX == pointData.fSize.fY) { 6976d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line can just be drawn as points 6986d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth())); 6996d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 7006d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) { 7016d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kRound_Cap); 7026d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 7036d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kButt_Cap); 7046d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 7056d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 7066d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 7077a03d86a3d9adcb13432fbd82039725149487c97skia.committer@gmail.com fDevice->drawPoints(*this, 7086d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkCanvas::kPoints_PointMode, 7096d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fNumPoints, 7106d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints, 7116d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP); 7126d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 7136d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPoints(SkCanvas::kPoints_PointMode, 7146d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fNumPoints, 7156d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints, 7166d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP, 7176d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com forceUseDevice); 7186d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 7196d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com break; 720935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } else { 7216d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line must be drawn as rects 7227a03d86a3d9adcb13432fbd82039725149487c97skia.committer@gmail.com SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag & 7236d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fFlags)); 7246d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 7256d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkRect r; 7266d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 7276d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com for (int i = 0; i < pointData.fNumPoints; ++i) { 7286d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com r.set(pointData.fPoints[i].fX - pointData.fSize.fX, 7296d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY - pointData.fSize.fY, 7306d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fX + pointData.fSize.fX, 7316d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY + pointData.fSize.fY); 7326d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (fDevice) { 7336d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com fDevice->drawRect(*this, r, newP); 7346d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 7356d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawRect(r, newP); 7366d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 7376d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 738935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } 7396d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 740629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com break; 741629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 742629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 743629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com#endif // DISABLE_DASHING_OPTIMIZATION 744629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // couldn't take fast path so fall through! 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPolygon_PointMode: { 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= 1; 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setStyle(SkPaint::kStroke_Style); 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i += inc) { 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(pts[i]); 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.lineTo(pts[i+1]); 754f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com if (fDevice) { 755f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fDevice->drawPath(*this, path, p, NULL, true); 756f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 757f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com this->drawPath(path, p, NULL, true); 758f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.rewind(); 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 767761fb62b0eb174783316d2a8b933fba896ca6355reed@google.comstatic bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, 768761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com SkPoint* strokeSize) { 769761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com if (SkPaint::kMiter_Join != paint.getStrokeJoin() || 770761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com paint.getStrokeMiter() < SK_ScalarSqrt2) { 771761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return false; 772761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com } 773fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 774761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com SkASSERT(matrix.rectStaysRect()); 775761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; 776761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com matrix.mapVectors(strokeSize, &pt, 1); 7776115338c59799b4ef09cda187f23867dea093f6ereed@google.com strokeSize->fX = SkScalarAbs(strokeSize->fX); 7786115338c59799b4ef09cda187f23867dea093f6ereed@google.com strokeSize->fY = SkScalarAbs(strokeSize->fY); 779761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return true; 7807ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org} 7817ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 78262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.comSkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, 78362ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const SkMatrix& matrix, 78462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint* strokeSize) { 7857ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org RectType rtype; 7867ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org const SkScalar width = paint.getStrokeWidth(); 78762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const bool zeroWidth = (0 == width); 7887ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::Style style = paint.getStyle(); 789fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7907ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { 7917ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org style = SkPaint::kFill_Style; 7927ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 793fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect() || paint.getMaskFilter() || 79562ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com paint.getRasterizer() || !matrix.rectStaysRect() || 7967ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::kStrokeAndFill_Style == style) { 79762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com rtype = kPath_RectType; 79862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (SkPaint::kFill_Style == style) { 7997ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kFill_RectType; 8007ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else if (zeroWidth) { 8017ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kHair_RectType; 80262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (easy_rect_join(paint, matrix, strokeSize)) { 8037ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kStroke_RectType; 8047ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else { 8057ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kPath_RectType; 8067ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 80762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return rtype; 80862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com} 80962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 8107324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic const SkPoint* rect_points(const SkRect& r) { 811fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<const SkPoint*>(&r); 8127324415759fe0c5a0902877b664aa942a89bd940reed@google.com} 8137324415759fe0c5a0902877b664aa942a89bd940reed@google.com 8147324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic SkPoint* rect_points(SkRect& r) { 815fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<SkPoint*>(&r); 81640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com} 81740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com 81862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.comvoid SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { 81962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkDEBUGCODE(this->validate();) 8207ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 82162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com // nothing to draw 822045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 82362ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return; 82462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } 82562ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 82662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint strokeSize; 82762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); 82862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 8297ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if (kPath_RectType == rtype) { 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmp; 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.addRect(rect); 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setFillType(SkPath::kWinding_FillType); 833187d5595901d1120d9425851e5afdd773f574502reed@android.com this->drawPath(tmp, paint, NULL, true); 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix = *fMatrix; 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect devRect; 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform rect into devRect 8417324415759fe0c5a0902877b664aa942a89bd940reed@google.com matrix.mapPoints(rect_points(devRect), rect_points(rect), 2); 8427324415759fe0c5a0902877b664aa942a89bd940reed@google.com devRect.sort(); 8438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doRect(devRect, paint)) { 8458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for the quick exit, before we build a blitter 8491c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkIRect ir; 8501c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com devRect.roundOut(&ir); 8511c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.getStyle() != SkPaint::kFill_Style) { 8521c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // extra space for hairlines 8531c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com ir.inset(-1, -1); 8541c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8551c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (fRC->quickReject(ir)) { 8561c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com return; 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8591c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias()); 8601c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com while (looper.next()) { 8611c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkRect localDevRect; 8621c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com looper.mapRect(&localDevRect, devRect); 8631c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkMatrix localMatrix; 8641c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com looper.mapMatrix(&localMatrix, matrix); 8651c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 8661c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, 8671c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com paint); 8681c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com const SkRasterClip& clip = looper.getRC(); 8691c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkBlitter* blitter = blitterStorage.get(); 8701c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 8711c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter 8721c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // case we are also hairline (if we've gotten to here), which devolves to 8731c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // effectively just kFill 8741c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com switch (rtype) { 8751c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kFill_RectType: 8761c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8771c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFillRect(localDevRect, clip, blitter); 8781c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8791c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FillRect(localDevRect, clip, blitter); 8801c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8811c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8821c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kStroke_RectType: 8831c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8841c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); 8851c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8861c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); 8871c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8881c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8891c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kHair_RectType: 8901c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8911c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiHairRect(localDevRect, clip, blitter); 8921c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8931c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::HairRect(localDevRect, clip, blitter); 8941c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8951c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8961c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com default: 8971c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkDEBUGFAIL("bad rtype"); 8981c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (srcM.fBounds.isEmpty()) { 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9070a60b3d32eae945688b69599f11679662657f751bungeman@google.com const SkMask* mask = &srcM; 9088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9090a60b3d32eae945688b69599f11679662657f751bungeman@google.com SkMask dstM; 9108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getMaskFilter() && 9118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) { 9128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask = &dstM; 913bf2ac7e52f84095368dc50600fd6e78cc96044e3bungeman@google.com } else { 914bf2ac7e52f84095368dc50600fd6e78cc96044e3bungeman@google.com dstM.fImage = NULL; 9158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 91602f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com SkAutoMaskFreeImage ami(dstM.fImage); 9178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doIRect(mask->fBounds)) { 9198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 9208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 922045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint); 923045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = blitterChooser.get(); 924045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 925045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper wrapper; 926045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRegion* clipRgn; 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 928045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 929045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &fRC->bwRgn(); 930045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 931045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com wrapper.init(*fRC, blitter); 932045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &wrapper.getRgn(); 933045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = wrapper.getBlitter(); 934045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 935045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter->blitMaskRegion(*mask, *clipRgn); 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 938ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.comstatic SkScalar fast_len(const SkVector& vec) { 939ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar x = SkScalarAbs(vec.fX); 940ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar y = SkScalarAbs(vec.fY); 941ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (x < y) { 942ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkTSwap(x, y); 943ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 944ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return x + SkScalarHalf(y); 945ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 946ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 947ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.comstatic bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) { 948ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com SkXfermode::Coeff dc; 949ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) { 950ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com return false; 951ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com } 952fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 953ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com switch (dc) { 954ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com case SkXfermode::kOne_Coeff: 955ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com case SkXfermode::kISA_Coeff: 956ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com case SkXfermode::kISC_Coeff: 957ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com return true; 958ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com default: 959ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com return false; 960ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com } 961ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com} 962ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 963e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.orgbool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, 964e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkScalar* coverage) { 965e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkASSERT(strokeWidth > 0); 966e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org // We need to try to fake a thick-stroke with a modulated hairline. 967ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 9688d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (matrix.hasPerspective()) { 969ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 970ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 971ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 972ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkVector src[2], dst[2]; 973ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[0].set(strokeWidth, 0); 974ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[1].set(0, strokeWidth); 975ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com matrix.mapVectors(dst, src, 2); 976ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len0 = fast_len(dst[0]); 977ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len1 = fast_len(dst[1]); 978652807bbc8c57e5fa9622126b51fd369f5c67935agl@chromium.org if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { 979e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org if (NULL != coverage) { 980e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org *coverage = SkScalarAve(len0, len1); 981e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 982ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return true; 983ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 984ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 985ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 986ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 987a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comvoid SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const { 988a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkDEBUGCODE(this->validate()); 989a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 990a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (fRC->isEmpty()) { 991a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; 992a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 993a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 994a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com { 995a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: Investigate optimizing these options. They are in the same 996a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // order as SkDraw::drawPath, which handles each case. It may be 997a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // that there is no way to optimize for these using the SkRRect path. 998a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkScalar coverage; 999a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) { 1000a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 1001a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1002a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 1003a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 1004a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 1005a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1006a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 1007a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getRasterizer()) { 1008a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 1009a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1010a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1011a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 1012a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getMaskFilter()) { 1013a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Transform the rrect into device space. 1014a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRRect devRRect; 1015a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (rrect.transform(*fMatrix, &devRRect)) { 1016a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 1017a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, 1018a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com fBounder, blitter.get(), 1019a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPaint::kFill_Style)) { 1020a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; // filterRRect() called the blitter, so we're done 1021a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1022a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1023a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 1024a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 1025a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comDRAW_PATH: 1026a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Now fall back to the default case of using a path. 1027a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPath path; 1028a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com path.addRRect(rrect); 1029a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com this->drawPath(path, paint, NULL, true); 1030a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 1031a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 103232e5d97ccf60f859db063ebd6e903c362e625767reed@google.comvoid SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, 1033126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkMatrix* prePathMatrix, bool pathIsMutable, 1034126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com bool drawCoverage) const { 1035f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1038045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* pathPtr = (SkPath*)&origSrcPath; 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool doFill = true; 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmpPath; 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmpMatrix; 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prePathMatrix) { 104932e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style || 105032e5d97ccf60f859db063ebd6e903c362e625767reed@google.com origPaint.getRasterizer()) { 10518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* result = pathPtr; 1052a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 10538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!pathIsMutable) { 10548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = &tmpPath; 10558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathIsMutable = true; 10568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*prePathMatrix, result); 10588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = result; 10598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 106092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmpMatrix.setConcat(*matrix, *prePathMatrix); 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix = &tmpMatrix; 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // at this point we're done with prePathMatrix 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 1066a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 10675dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1068a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1069ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com { 1070dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com SkScalar coverage; 1071dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { 1072dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SK_Scalar1 == coverage) { 10735dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setStrokeWidth(0); 1074dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) { 1075dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com U8CPU newAlpha; 1076dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#if 0 1077dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = SkToU8(SkScalarRoundToInt(coverage * 1078dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com origPaint.getAlpha())); 1079dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#else 1080dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // this is the old technique, which we preserve for now so 1081dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // we don't change previous results (testing) 1082dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // the new way seems fine, its just (a tiny bit) different 1083dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com int scale = (int)SkScalarMul(coverage, 256); 1084dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = origPaint.getAlpha() * scale >> 8; 1085dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#endif 10865dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkPaint* writablePaint = paint.writable(); 10875dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setStrokeWidth(0); 10885dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setAlpha(newAlpha); 1089dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com } 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1092a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 109332e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { 10944bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect; 10954bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com const SkRect* cullRectPtr = NULL; 10964bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (this->computeConservativeLocalClipBounds(&cullRect)) { 10974bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com cullRectPtr = &cullRect; 10984bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 10994bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr); 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = &tmpPath; 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1102a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 110332e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()) { 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 110532e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()->rasterize(*pathPtr, *matrix, 1106045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com &fRC->getBounds(), paint->getMaskFilter(), &mask, 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 110832e5d97ccf60f859db063ebd6e903c362e625767reed@google.com this->drawDevMask(mask, *paint); 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(mask.fImage); 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // avoid possibly allocating a new path in transform if we can 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform the path into device space 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*matrix, devPathPtr); 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1120126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint, drawCoverage); 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11222ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org if (paint->getMaskFilter()) { 1123fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkPaint::Style style = doFill ? SkPaint::kFill_Style : 11242ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkPaint::kStroke_Style; 11252ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, 11262ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org fBounder, blitter.get(), 11272ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org style)) { 11282ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org return; // filterPath() called the blitter, so we're done 11292ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org } 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 113232e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) { 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1136045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*); 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (doFill) { 113832e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->isAntiAlias()) { 1139045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::AntiFillPath; 11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1141045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::FillPath; 11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // hairline 114432e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->isAntiAlias()) { 1145045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::AntiHairPath; 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1147045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc = SkScan::HairPath; 11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1150045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com proc(*devPathPtr, *fRC, blitter.get()); 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11530baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com/** For the purposes of drawing bitmaps, if a matrix is "almost" translate 11540baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com go ahead and treat it as if it were, so that subsequent code can go fast. 11550baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com */ 11560baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.comstatic bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) { 1157070dcd8ad37a4c5b8a9015938409b27bb3ce3ab9reed@google.com unsigned bits = 0; // TODO: find a way to allow the caller to tell us to 1158070dcd8ad37a4c5b8a9015938409b27bb3ce3ab9reed@google.com // respect filtering. 1159070dcd8ad37a4c5b8a9015938409b27bb3ce3ab9reed@google.com return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits); 11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 1164900ecf2f1579d42c9d2959831787af0346320f86reed@google.com SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType); 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1166a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com if (just_translate(*fMatrix, bitmap)) { 1167e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(fMatrix->getTranslateX()); 1168e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(fMatrix->getTranslateY()); 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1170a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com SkAutoLockPixels alp(bitmap); 1171a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com if (!bitmap.readyToDraw()) { 1172a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com return; 1173a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com } 1174a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 1178e5f48243bdbed2662be7a31be0888abc273b09e8scroggo@google.com mask.fRowBytes = SkToU32(bitmap.rowBytes()); 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = bitmap.getAddr8(0, 0); 1180a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // need to xform the bitmap first 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 1185a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapRect(&r); 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&mask.fBounds); 1190a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // set the mask's bounds to the transformed bitmap-bounds, 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // clipped to the actual device 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devBounds; 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com devBounds.set(0, 0, fBitmap->width(), fBitmap->height()); 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need intersect(l, t, r, b) on irect 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!mask.fBounds.intersect(devBounds)) { 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1201543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = SkAlign4(mask.fBounds.width()); 1204543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask.computeImageSize(); 1205543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 1206543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // the mask is too big to allocated, draw nothing 1207543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return; 1208543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // allocate (and clear) our temp buffer to hold the transformed bitmap 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMalloc storage(size); 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = (uint8_t*)storage.get(); 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask.fImage, 0, size); 1214a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now draw our bitmap(src) into mask(dst), transformed by the matrix 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap device; 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.height(), mask.fRowBytes); 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device.setPixels(mask.fImage); 1221a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas c(device); 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need the unclipped top/left for the translate 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.translate(-SkIntToScalar(mask.fBounds.fLeft), 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.concat(*fMatrix); 12273469c76c40790b409621fd7eff34f56240718549reed@android.com 12283469c76c40790b409621fd7eff34f56240718549reed@android.com // We can't call drawBitmap, or we'll infinitely recurse. Instead 1229fb12c3e6ba84f95dc15fbaddc239dede0ba1d60ereed@android.com // we manually build a shader and draw that into our new mask 12303469c76c40790b409621fd7eff34f56240718549reed@android.com SkPaint tmpPaint; 12313469c76c40790b409621fd7eff34f56240718549reed@android.com tmpPaint.setFlags(paint.getFlags()); 123240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkAutoBitmapShaderInstall install(bitmap, tmpPaint); 12333469c76c40790b409621fd7eff34f56240718549reed@android.com SkRect rr; 12343469c76c40790b409621fd7eff34f56240718549reed@android.com rr.set(0, 0, SkIntToScalar(bitmap.width()), 12353469c76c40790b409621fd7eff34f56240718549reed@android.com SkIntToScalar(bitmap.height())); 123640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com c.drawRect(rr, install.paintWithShader()); 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1242045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipped_out(const SkMatrix& m, const SkRasterClip& c, 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& srcR) { 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect dstR; 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devIR; 1246a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.mapRect(&dstR, srcR); 1248a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com dstR.roundOut(&devIR); 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return c.quickReject(devIR); 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1252045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip, 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width, int height) { 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return clipped_out(matrix, clip, r); 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1259045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, 1260045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkBitmap& bitmap) { 1261045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return clip.isBW() || 1262045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height()); 1263045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1264045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 126640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com const SkPaint& origPaint) const { 1267f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1270045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1272900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1275a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 127640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint paint(origPaint); 127740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com paint.setStyle(SkPaint::kFill_Style); 1278a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 128092362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org matrix.setConcat(*fMatrix, prematrix); 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1282045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) { 12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1286218521e15706c4377b1be49d931c4d7c8d597445reed@android.com if (fBounder && just_translate(matrix, bitmap)) { 1287218521e15706c4377b1be49d931c4d7c8d597445reed@android.com SkIRect ir; 1288e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int32_t ix = SkScalarRoundToInt(matrix.getTranslateX()); 1289e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int32_t iy = SkScalarRoundToInt(matrix.getTranslateY()); 1290218521e15706c4377b1be49d931c4d7c8d597445reed@android.com ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 1291218521e15706c4377b1be49d931c4d7c8d597445reed@android.com if (!fBounder->doIRect(ir)) { 1292218521e15706c4377b1be49d931c4d7c8d597445reed@android.com return; 1293218521e15706c4377b1be49d931c4d7c8d597445reed@android.com } 1294218521e15706c4377b1be49d931c4d7c8d597445reed@android.com } 1295218521e15706c4377b1be49d931c4d7c8d597445reed@android.com 1296900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (bitmap.colorType() != kAlpha_8_SkColorType && 12970baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com just_translate(matrix, bitmap)) { 1298f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 1299f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // It is safe to call lock pixels now, since we know the matrix is 1300f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // (more or less) identity. 1301f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 1302f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com SkAutoLockPixels alp(bitmap); 1303f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com if (!bitmap.readyToDraw()) { 1304f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com return; 1305f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com } 1306e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(matrix.getTranslateX()); 1307e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(matrix.getTranslateY()); 1308045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (clipHandlesSprite(*fRC, ix, iy, bitmap)) { 1309a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator allocator; 1310a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 1311a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 1312a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org ix, iy, &allocator); 1313045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (blitter) { 1314045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect ir; 1315045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 1316045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1317045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(ir, *fRC, blitter); 1318045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1322a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now make a temp draw on the stack, and use it 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 1327a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1328900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (bitmap.colorType() == kAlpha_8_SkColorType) { 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawBitmapAsMask(bitmap, paint); 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 133140c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkAutoBitmapShaderInstall install(bitmap, paint); 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, SkIntToScalar(bitmap.width()), 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(bitmap.height())); 1336a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com // is this ok if paint has a rasterizer? 133740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com draw.drawRect(r, install.paintWithShader()); 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, 134240c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com const SkPaint& origPaint) const { 1343f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 1344a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1346045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1348900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(x, y, x + bitmap.width(), y + bitmap.height()); 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1355045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->quickReject(bounds)) { 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // nothing to draw 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 135940c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint paint(origPaint); 136040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com paint.setStyle(SkPaint::kFill_Style); 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1362045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) { 1363a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkTBlitterAllocator allocator; 1364a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 1365a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 1366a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org x, y, &allocator); 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (blitter) { 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doIRect(bounds)) { 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1373045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(bounds, *fRC, blitter); 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get a scalar version of our rect 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(bounds); 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13849c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org // create shader with offset 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(r.fLeft, r.fTop); 13869c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org SkAutoBitmapShaderInstall install(bitmap, paint, &matrix); 13879c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org const SkPaint& shaderPaint = install.paintWithShader(); 1388a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call ourself with a rect 1393a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com // is this OK if paint has a rasterizer? 139440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com draw.drawRect(r, shaderPaint); 13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h" 14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h" 1401e69137620ab0b5b40d230318c8e11b822f63cb9dreed@google.com#include "SkTextToPathIter.h" 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char text[], size_t byteLength, SkVector* stopVector) { 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = 0, y = 0; 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoKern autokern; 1410a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't need x, y here, since all subpixel variants will have the 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // same advance 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += autokern.adjust(glyph) + glyph.fAdvanceX; 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y += glyph.fAdvanceY; 14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(text == stop); 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14248128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.orgbool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) { 14258128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // hairline glyphs are fast enough so we don't need to cache them 14268128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 14278128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 14288128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 14298128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14308128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // we don't cache perspective 14318128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (ctm.hasPerspective()) { 14328128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 14338128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 14348128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14358128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org SkMatrix textM; 14368128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM)); 14378128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org} 14388128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText_asPaths(const char text[], size_t byteLength, 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 1442f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1444166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com SkTextToPathIter iter(text, byteLength, paint, true); 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setScale(iter.getPathScale(), iter.getPathScale()); 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(x, y); 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath* iterPath; 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar xpos, prevXPos = 0; 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14537b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com while (iter.next(&iterPath, &xpos)) { 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(xpos - prevXPos, 0); 14557b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (iterPath) { 14567b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com const SkPaint& pnt = iter.getPaint(); 14577b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (fDevice) { 14587b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com fDevice->drawPath(*this, *iterPath, pnt, &matrix, false); 14597b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } else { 14607b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com this->drawPath(*iterPath, pnt, &matrix, false); 14617b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } 1462f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevXPos = xpos; 14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// disable warning : local variable used without having been initialized 1468a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com#if defined _WIN32 && _MSC_VER >= 1300 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 ) 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 14728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D1G_NoBounder_RectClip(const SkDraw1Glyph& state, 1476f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkFixed fx, SkFixed fy, 1477f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkGlyph& glyph) { 14789fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int left = SkFixedFloorToInt(fx); 14799fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int top = SkFixedFloorToInt(fy); 14808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 148183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkASSERT(NULL == state.fBounder); 148283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkASSERT((NULL == state.fClip && state.fAAClip) || 148383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com (state.fClip && NULL == state.fAAClip && state.fClip->isRect())); 14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int right = left + glyph.fWidth; 14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bottom = top + glyph.fHeight; 14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1491fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkMask mask; 1492fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkIRect storage; 1493fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com SkIRect* bounds = &mask.fBounds; 149483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 149583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fBounds.set(left, top, right, bottom); 149683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 149783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com // this extra test is worth it, assuming that most of the time it succeeds 149883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com // since we can avoid writing to storage 149983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) { 150083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds)) 150183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com return; 150283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com bounds = &storage; 150383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 150483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 150583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com uint8_t* aa = (uint8_t*)glyph.fImage; 150683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 150783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com aa = (uint8_t*)state.fCache->findImage(glyph); 150883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 150983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com return; // can't rasterize glyph 15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 151183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 15128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 151383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fRowBytes = glyph.rowBytes(); 151483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 151583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fImage = aa; 15165bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com state.blitMask(mask, *bounds); 15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state, 1520f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkFixed fx, SkFixed fy, 152183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const SkGlyph& glyph) { 15229fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int left = SkFixedFloorToInt(fx); 15239fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int top = SkFixedFloorToInt(fy); 15248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 152583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkASSERT(!state.fClip->isRect()); 152683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkASSERT(NULL == state.fBounder); 15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 15298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 15318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 15328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 153483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 153583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 153683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (!clipper.done()) { 153783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const SkIRect& cr = clipper.rect(); 153883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const uint8_t* aa = (const uint8_t*)glyph.fImage; 153983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 154083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com aa = (uint8_t*)state.fCache->findImage(glyph); 154183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 1542fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com return; 15438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 154483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 154583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 154683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fRowBytes = glyph.rowBytes(); 154783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 154883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fImage = (uint8_t*)aa; 154983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com do { 15505bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com state.blitMask(mask, cr); 155183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com clipper.next(); 155283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } while (!clipper.done()); 155383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 15548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D1G_Bounder(const SkDraw1Glyph& state, 1557f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkFixed fx, SkFixed fy, 155883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const SkGlyph& glyph) { 15599fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int left = SkFixedFloorToInt(fx); 15609fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int top = SkFixedFloorToInt(fy); 15618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1562fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 15638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 1564fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 15658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 15668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 1567fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 15688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 1570fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 157183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (!clipper.done()) { 157283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const SkIRect& cr = clipper.rect(); 157383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com const uint8_t* aa = (const uint8_t*)glyph.fImage; 157483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 157583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com aa = (uint8_t*)state.fCache->findImage(glyph); 157683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (NULL == aa) { 157783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com return; 15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1579fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 1580fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 1581d055c1fde2128514167b315f4d104b177e04a3dereed@android.com // we need to pass the origin, which we approximate with our 1582d055c1fde2128514167b315f4d104b177e04a3dereed@android.com // (unadjusted) left,top coordinates (the caller called fixedfloor) 158383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com if (state.fBounder->doIRectGlyph(cr, 1584d055c1fde2128514167b315f4d104b177e04a3dereed@android.com left - glyph.fLeft, 1585d055c1fde2128514167b315f4d104b177e04a3dereed@android.com top - glyph.fTop, glyph)) { 158683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fRowBytes = glyph.rowBytes(); 158783a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 158883a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com mask.fImage = (uint8_t*)aa; 158983a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com do { 15905bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com state.blitMask(mask, cr); 159183a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com clipper.next(); 159283a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } while (!clipper.done()); 159383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 159483a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 15958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1597045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic void D1G_Bounder_AAClip(const SkDraw1Glyph& state, 1598045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkFixed fx, SkFixed fy, 1599045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkGlyph& glyph) { 16009fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int left = SkFixedFloorToInt(fx); 16019fb00413ec55deb3a4953d4dff2dba3ec5cdb645mike@reedtribe.org int top = SkFixedFloorToInt(fy); 1602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkIRect bounds; 1603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 1604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1605045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) { 1606045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com D1G_NoBounder_RectClip(state, fx, fy, glyph); 1607045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1608045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1609045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 1610fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.comstatic bool hasCustomD1GProc(const SkDraw& draw) { 1611fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com return draw.fProcs && draw.fProcs->fD1GProc; 1612fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com} 1613fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com 1614fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.comstatic bool needsRasterTextBlit(const SkDraw& draw) { 1615fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com return !hasCustomD1GProc(draw); 1616fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com} 1617fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com 16188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, 16195bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkGlyphCache* cache, const SkPaint& pnt) { 16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDraw = draw; 16212211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com fBounder = draw->fBounder; 16222211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com fBlitter = blitter; 16232211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com fCache = cache; 16245bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com fPaint = &pnt; 16258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16269447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (cache->isSubpixel()) { 16279447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); 16289447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } else { 16299447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fHalfSampleX = fHalfSampleY = SK_FixedHalf; 16309447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 16319447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 16321d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com if (hasCustomD1GProc(*draw)) { 1633045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // todo: fix this assumption about clips w/ custom 1634045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = draw->fClip; 1635045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipBounds = fClip->getBounds(); 16368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return draw->fProcs->fD1GProc; 16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1639045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (draw->fRC->isBW()) { 1640045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fAAClip = NULL; 1641045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &draw->fRC->bwRgn(); 1642045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipBounds = fClip->getBounds(); 1643045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == fBounder) { 1644045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fClip->isRect()) { 1645045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return D1G_NoBounder_RectClip; 1646045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1647045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return D1G_NoBounder_RgnClip; 1648045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1649045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1650045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return D1G_Bounder; 1651045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 1652045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { // aaclip 1653045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fAAClip = &draw->fRC->aaRgn(); 1654045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = NULL; 1655045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClipBounds = fAAClip->getBounds(); 1656045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (NULL == fBounder) { 16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D1G_NoBounder_RectClip; 16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1659045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return D1G_Bounder_AAClip; 16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16645bdfb331ac650cf464baa96a49e2473ee10a515creed@google.comvoid SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const { 16655bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkASSERT(SkMask::kARGB32_Format == mask.fFormat); 16665bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 16675bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkBitmap bm; 16685bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com bm.setConfig(SkBitmap::kARGB_8888_Config, 16695bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes); 16705bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com bm.setPixels((SkPMColor*)mask.fImage); 16715bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 16725bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint); 16735bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com} 16745bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 16758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 16768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText(const char text[], size_t byteLength, 16788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) const { 16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1681f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1684045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 168836d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // SkScalarRec doesn't currently have a way of representing hairline stroke and 168936d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // will fill if its frame-width is 0. 1690ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawText_asPaths(text, byteLength, x, y, paint); 16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16979447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); 16988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkGlyphCache* cache = autoCache.getCache(); 1699a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform our starting point 17018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 17028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint loc; 17039447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fMatrix->mapXY(x, y, &loc); 17048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x = loc.fX; 17058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y = loc.fY; 17068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to measure first 17098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() != SkPaint::kLeft_Align) { 17108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector stop; 17118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com measure_text(cache, glyphCacheProc, text, byteLength, &stop); 17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar stopX = stop.fX; 17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar stopY = stop.fY; 17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopX = SkScalarHalf(stopX); 17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopY = SkScalarHalf(stopY); 17208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x -= stopX; 17228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y -= stopY; 17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1724a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1727045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitter aaBlitter; 1728045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoBlitterChoose blitterChooser; 1729045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = NULL; 17301d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com if (needsRasterTextBlit(*this)) { 17319447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com blitterChooser.choose(*fBitmap, *fMatrix, paint); 1732045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = blitterChooser.get(); 1733045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isAA()) { 1734045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com aaBlitter.init(blitter, &fRC->aaRgn()); 1735045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = &aaBlitter; 1736045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 17371d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 17381d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com 17398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoKern autokern; 174052c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com SkDraw1Glyph d1g; 17415bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17439447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fxMask = ~0; 17449447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fyMask = ~0; 17459447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (cache->isSubpixel()) { 17469447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); 17479447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (kX_SkAxisAlignment == baseline) { 17489447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fyMask = 0; 17499447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com d1g.fHalfSampleY = SK_FixedHalf; 17509447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } else if (kY_SkAxisAlignment == baseline) { 17519447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fxMask = 0; 17529447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com d1g.fHalfSampleX = SK_FixedHalf; 17539447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 17549447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 17559447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 17569447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX; 17579447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY; 17589447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 17598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 17602211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); 17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx += autokern.adjust(glyph); 17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph.fWidth) { 176552c748b1691f02f90b27c35bc05074fcef709e66bungeman@google.com proc(d1g, fx, fy, glyph); 17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1767d830d13c27437b4677a4a1abfa866d98dc2d2ab9jvanverth@google.com 17688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx += glyph.fAdvanceX; 17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy += glyph.fAdvanceY; 17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// last parameter is interpreted as SkFixed [x, y] 17748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// return the fixed position, which may be rounded or not by the caller 17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// e.g. subpixel doesn't round 17768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); 17778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1778cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comstatic void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) { 17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); 17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1782cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comstatic void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) { 17838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1), 17848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1)); 17858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1787cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comstatic void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) { 17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX, 17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarToFixed(loc.fY) - glyph.fAdvanceY); 17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic AlignProc pick_align_proc(SkPaint::Align align) { 17938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const AlignProc gProcs[] = { 17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com leftAlignProc, centerAlignProc, rightAlignProc 17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 1796a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs)); 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return gProcs[align]; 18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1802cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comtypedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*); 1803cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com 1804cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comstatic void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) { 1805cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com dst->set(loc.fX, loc.fY); 1806cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com} 1807cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com 1808cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comstatic void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) { 1809cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1), 1810cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1)); 1811cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com} 1812cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com 1813cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comstatic void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) { 1814cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX), 1815cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com loc.fY - SkFixedToScalar(glyph.fAdvanceY)); 1816cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com} 1817cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com 1818cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.comstatic AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) { 1819cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com static const AlignProc_scalar gProcs[] = { 1820cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar 1821cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com }; 1822cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com 1823cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs)); 1824cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com 1825cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com return gProcs[align]; 1826cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com} 1827cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com 18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass TextMapState { 18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable SkPoint fLoc; 1831a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TextMapState(const SkMatrix& matrix, SkScalar y) 18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {} 18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*Proc)(const TextMapState&, const SkScalar pos[]); 1836a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Proc pickProc(int scalarsPerPosition); 1838a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& fMatrix; 18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::MapXYProc fProc; 18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar fY; // ignored by MapXYProc 18438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // these are only used by Only... procs 18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar fScaleX, fTransX, fTransformedY; 18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapXProc(const TextMapState& state, const SkScalar pos[]) { 18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc); 18488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1849a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapXYProc(const TextMapState& state, const SkScalar pos[]) { 18518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc); 18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1853a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapOnlyScaleXProc(const TextMapState& state, 18558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar pos[]) { 18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX, 18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fTransformedY); 18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1859a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapOnlyTransXProc(const TextMapState& state, 18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar pos[]) { 18628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fLoc.set(*pos + state.fTransX, state.fTransformedY); 18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) { 18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 1868a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 18698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (1 == scalarsPerPosition) { 18708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned mtype = fMatrix.getType(); 18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return MapXProc; 18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fScaleX = fMatrix.getScaleX(); 18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTransX = fMatrix.getTranslateX(); 18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) + 18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix.getTranslateY(); 18788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (mtype & SkMatrix::kScale_Mask) ? 18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MapOnlyScaleXProc : MapOnlyTransXProc; 18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return MapXYProc; 18838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 18878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1888ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.comvoid SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 1889ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkScalar pos[], SkScalar constY, 1890ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com int scalarsPerPosition, 1891ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkPaint& origPaint) const { 1892ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com // setup our std paint, in hopes of getting hits in the cache 1893ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkPaint paint(origPaint); 1894ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkScalar matrixScale = paint.setupForAsPaths(); 1895ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 18965a64902ee92847f53dfc5b211da19d074179be64reed@google.com SkMatrix matrix; 18975a64902ee92847f53dfc5b211da19d074179be64reed@google.com matrix.setScale(matrixScale, matrixScale); 18988f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 1899ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1900ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkAutoGlyphCache autoCache(paint, NULL, NULL); 1901ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkGlyphCache* cache = autoCache.getCache(); 1902ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 1903ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const char* stop = text + byteLength; 1904cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com AlignProc_scalar alignProc = pick_align_proc_scalar(paint.getTextAlign()); 1905ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com TextMapState tms(SkMatrix::I(), constY); 1906ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); 19078f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 1908ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com while (text < stop) { 1909ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1910ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (glyph.fWidth) { 1911ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkPath* path = cache->findPath(glyph); 1912ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (path) { 1913ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com tmsProc(tms, pos); 1914cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com SkPoint loc; 1915cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com alignProc(tms.fLoc, glyph, &loc); 19168f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 1917cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransX] = loc.fX; 1918cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransY] = loc.fY; 19195a64902ee92847f53dfc5b211da19d074179be64reed@google.com if (fDevice) { 19205a64902ee92847f53dfc5b211da19d074179be64reed@google.com fDevice->drawPath(*this, *path, paint, &matrix, false); 19215a64902ee92847f53dfc5b211da19d074179be64reed@google.com } else { 19225a64902ee92847f53dfc5b211da19d074179be64reed@google.com this->drawPath(*path, paint, &matrix, false); 19235a64902ee92847f53dfc5b211da19d074179be64reed@google.com } 1924ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1925ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1926ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com pos += scalarsPerPosition; 1927ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1928ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com} 1929ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 19308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPosText(const char text[], size_t byteLength, 19318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar pos[], SkScalar constY, 19328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scalarsPerPosition, const SkPaint& paint) const { 19338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 19348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 19358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1936f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 19378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1939045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 19408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 19418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1943ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1944ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com this->drawPosText_asPaths(text, byteLength, pos, constY, 1945ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com scalarsPerPosition, paint); 19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 19478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 19509447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkAutoGlyphCache autoCache(paint, &fDevice->fLeakyProperties, fMatrix); 19518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkGlyphCache* cache = autoCache.getCache(); 1952a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1953045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper wrapper; 1954045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAutoBlitterChoose blitterChooser; 1955045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = NULL; 19561d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com if (needsRasterTextBlit(*this)) { 19579447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com blitterChooser.choose(*fBitmap, *fMatrix, paint); 1958045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = blitterChooser.get(); 1959045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isAA()) { 1960045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com wrapper.init(*fRC, blitter); 1961045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = wrapper.getBlitter(); 1962045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 19631d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 1964fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 19658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 19668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AlignProc alignProc = pick_align_proc(paint.getTextAlign()); 19672211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com SkDraw1Glyph d1g; 19685bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 19699447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com TextMapState tms(*fMatrix, constY); 19708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); 19718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19722211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com if (cache->isSubpixel()) { 19738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // maybe we should skip the rounding if linearText is set 19749447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); 19759447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com 19769447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fxMask = ~0; 19779447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fyMask = ~0; 19789447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (kX_SkAxisAlignment == baseline) { 19799447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fyMask = 0; 19809447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX 19819447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com d1g.fHalfSampleY = SK_FixedHalf; 19829447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com#endif 19839447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } else if (kY_SkAxisAlignment == baseline) { 19849447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fxMask = 0; 19859447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX 19869447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com d1g.fHalfSampleX = SK_FixedHalf; 19879447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com#endif 19889447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 19898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkPaint::kLeft_Align == paint.getTextAlign()) { 19918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 19928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmsProc(tms, pos); 19939447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX; 19949447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY; 1995a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1996f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 1997f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com fx & fxMask, fy & fyMask); 1998a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph.fWidth) { 2000f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com proc(d1g, fx, fy, glyph); 20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos += scalarsPerPosition; 20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 20069330cfe851b14b8985acc14caa3dc5ad20b0b2a8bungeman@google.com const char* currentText = text; 20079447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); 2008a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20099447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com if (metricGlyph.fWidth) { 20109447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) 20119447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) 20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmsProc(tms, pos); 20149447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkIPoint fixedLoc; 20159447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com alignProc(tms.fLoc, metricGlyph, &fixedLoc); 2016a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20179447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX; 20189447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY; 2019a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // have to call again, now that we've been "aligned" 20219447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, 20229447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fx & fxMask, fy & fyMask); 20239447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com // the assumption is that the metrics haven't changed 20249447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkASSERT(prevAdvX == glyph.fAdvanceX); 20259447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkASSERT(prevAdvY == glyph.fAdvanceY); 20269447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkASSERT(glyph.fWidth); 2027a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20289447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com proc(d1g, fx, fy, glyph); 20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos += scalarsPerPosition; 20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // not subpixel 2034aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com if (SkPaint::kLeft_Align == paint.getTextAlign()) { 2035aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com while (text < stop) { 2036aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com // the last 2 parameters are ignored 2037aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 2038fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 2039aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com if (glyph.fWidth) { 2040aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com tmsProc(tms, pos); 2041a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2042aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com proc(d1g, 20439447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX, 20449447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY, 2045aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com glyph); 2046aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } 2047aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com pos += scalarsPerPosition; 2048aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } 2049aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } else { 2050aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com while (text < stop) { 2051aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com // the last 2 parameters are ignored 2052aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 2053a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2054aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com if (glyph.fWidth) { 2055aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com tmsProc(tms, pos); 2056a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2057aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com SkIPoint fixedLoc; 2058aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com alignProc(tms.fLoc, glyph, &fixedLoc); 2059aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com 2060aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com proc(d1g, 20619447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX, 20629447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY, 2063aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com glyph); 2064aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com } 2065aeb07864052fde0acba0ae1a42a01db3407f1f6ereed@google.com pos += scalarsPerPosition; 20668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 20728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 20738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 20748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 20768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathMeasure.h" 20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void morphpoints(SkPoint dst[], const SkPoint src[], int count, 20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPathMeasure& meas, const SkMatrix& matrix) { 20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::MapXYProc proc = matrix.getMapXYProc(); 20828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 20848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pos; 20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector tangent; 20868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(matrix, src[i].fX, src[i].fY, &pos); 20888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = pos.fX; 20898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = pos.fY; 20908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20918f17b0d5e14fa336f65e33ecf30f15929aa75790reed@google.com if (!meas.getPosTan(sx, &pos, &tangent)) { 20928f17b0d5e14fa336f65e33ecf30f15929aa75790reed@google.com // set to 0 if the measure failed, so that we just set dst == pos 20938f17b0d5e14fa336f65e33ecf30f15929aa75790reed@google.com tangent.set(0, 0); 20948f17b0d5e14fa336f65e33ecf30f15929aa75790reed@google.com } 20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* This is the old way (that explains our approach but is way too slow 20978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 20988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 20998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(sx, sy); 21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setSinCos(tangent.fY, tangent.fX); 21028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.preTranslate(-sx, 0); 21038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(pos.fX, pos.fY); 21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.mapPoints(&dst[i], &pt, 1); 21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 21068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy), 21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos.fY + SkScalarMul(tangent.fX, sy)); 21088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* TODO 21128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Need differentially more subdivisions when the follow-path is curvy. Not sure how to 21148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com determine that, but we need it. I guess a cheap answer is let the caller tell us, 21158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out. 21168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 21178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas, 21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix) { 21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Iter iter(src, false); 21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint srcP[4], dstP[3]; 21218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Verb verb; 21228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) { 21248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (verb) { 21258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kMove_Verb: 21268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, srcP, 1, meas, matrix); 21278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(dstP[0]); 21288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 21298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kLine_Verb: 21308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // turn lines into quads to look bendy 21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX); 21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY); 21338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, srcP, 2, meas, matrix); 21348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->quadTo(dstP[0], dstP[1]); 21358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kQuad_Verb: 21378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, &srcP[1], 2, meas, matrix); 21388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->quadTo(dstP[0], dstP[1]); 21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 21408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kCubic_Verb: 21418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, &srcP[1], 3, meas, matrix); 21428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->cubicTo(dstP[0], dstP[1], dstP[2]); 21438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 21448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kClose_Verb: 21458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->close(); 21468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 21478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 21480c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("unknown verb"); 21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawTextOnPath(const char text[], size_t byteLength, 21558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& follow, const SkMatrix* matrix, 21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 21578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 2160045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 21628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2164166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com SkTextToPathIter iter(text, byteLength, paint, true); 21658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPathMeasure meas(follow, false); 21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar hOffset = 0; 21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to measure first 21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() != SkPaint::kLeft_Align) { 21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar pathLen = meas.getLength(); 21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 21728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathLen = SkScalarHalf(pathLen); 21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com hOffset += pathLen; 21758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath* iterPath; 21788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar xpos; 21798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix scaledMatrix; 21808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar scale = iter.getPathScale(); 21818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scaledMatrix.setScale(scale, scale); 2183a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21847b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com while (iter.next(&iterPath, &xpos)) { 21857b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (iterPath) { 21867b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com SkPath tmp; 21877b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com SkMatrix m(scaledMatrix); 21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21897b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com m.postTranslate(xpos + hOffset, 0); 21907b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (matrix) { 21917b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com m.postConcat(*matrix); 21927b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } 21937b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com morphpath(&tmp, *iterPath, meas, m); 21947b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (fDevice) { 21957b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true); 21967b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } else { 21977b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com this->drawPath(tmp, iter.getPaint(), NULL, true); 21987b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com } 2199f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct VertState { 22068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int f0, f1, f2; 22078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState(int vCount, const uint16_t indices[], int indexCount) 22098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fIndices(indices) { 22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrIndex = 0; 22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (indices) { 22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCount = indexCount; 22138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCount = vCount; 22158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2217a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2218a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com typedef bool (*Proc)(VertState*); 22198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Proc chooseProc(SkCanvas::VertexMode mode); 22208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 22228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fCount; 22238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fCurrIndex; 22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* fIndices; 2225a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool Triangles(VertState*); 22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TrianglesX(VertState*); 22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleStrip(VertState*); 22298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleStripX(VertState*); 22308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleFan(VertState*); 22318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleFanX(VertState*); 22328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 22338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::Triangles(VertState* state) { 22358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 22368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 22378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = index + 0; 22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 1; 22418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = index + 2; 22428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 3; 22438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 22448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TrianglesX(VertState* state) { 22478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* indices = state->fIndices; 22488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 22498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 22508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[index + 0]; 22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 1]; 22548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = indices[index + 2]; 22558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 3; 22568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 22578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleStrip(VertState* state) { 22608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 22618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 22628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = index + 2; 22658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index & 1) { 22668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = index + 1; 22678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 0; 22688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 22698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = index + 0; 22708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 1; 22718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 22738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 22748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleStripX(VertState* state) { 22778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* indices = state->fIndices; 22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = indices[index + 2]; 22838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index & 1) { 22848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[index + 1]; 22858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 0]; 22868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 22878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[index + 0]; 22888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 1]; 22898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 22918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 22928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleFan(VertState* state) { 22958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 22968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 22978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = 0; 23008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 1; 23018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = index + 2; 23028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 23038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 23048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleFanX(VertState* state) { 23078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* indices = state->fIndices; 23088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 23098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 23108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 23118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[0]; 23138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 1]; 23148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = indices[index + 2]; 23158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 23168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 23178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comVertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) { 23208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 23218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kTriangles_VertexMode: 23228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fIndices ? TrianglesX : Triangles; 23238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kTriangleStrip_VertexMode: 23248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fIndices ? TriangleStripX : TriangleStrip; 23258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kTriangleFan_VertexMode: 23268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fIndices ? TriangleFanX : TriangleFan; 23278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 23288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 23298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2332045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comtypedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&, 23338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter*); 23348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic HairProc ChooseHairProc(bool doAntiAlias) { 23368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 23378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool texture_to_matrix(const VertState& state, const SkPoint verts[], 23408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint texs[], SkMatrix* matrix) { 23418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src[3], dst[3]; 2342a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 23438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[0] = texs[state.f0]; 23448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[1] = texs[state.f1]; 23458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[2] = texs[state.f2]; 23468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[0] = verts[state.f0]; 23478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[1] = verts[state.f1]; 23488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[2] = verts[state.f2]; 23498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return matrix->setPolyToPoly(src, dst, 3); 23508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkTriColorShader : public SkShader { 23538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 23548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTriColorShader() {} 23558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 235687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual size_t contextSize() const SK_OVERRIDE; 2357a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 235887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org class TriColorShaderContext : public SkShader::Context { 235987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org public: 2360e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&); 236187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual ~TriColorShaderContext(); 236287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 236387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 236487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 236587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; 236687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 236787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org private: 236887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkMatrix fDstToUnit; 236987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor fColors[3]; 237087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 237187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org typedef SkShader::Context INHERITED; 237287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org }; 2373a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 23740f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 2375ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader) 2376ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com 23778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 23788b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org SkTriColorShader(SkReadBuffer& buffer) : SkShader(buffer) {} 2379a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2380ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org virtual Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE { 2381ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec)); 2382ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 2383ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org 23848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 23858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShader INHERITED; 23868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 23878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 238887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgbool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], 238987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int index0, int index1, int index2) { 2390a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 23918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[0] = SkPreMultiplyColor(colors[index0]); 23928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[1] = SkPreMultiplyColor(colors[index1]); 23938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[2] = SkPreMultiplyColor(colors[index2]); 2394a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 23958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m, im; 23968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.reset(); 23978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(0, pts[index1].fX - pts[index0].fX); 23988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(1, pts[index2].fX - pts[index0].fX); 23998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(2, pts[index0].fX); 24008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(3, pts[index1].fY - pts[index0].fY); 24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(4, pts[index2].fY - pts[index0].fY); 24028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(5, pts[index0].fY); 24038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!m.invert(&im)) { 24048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 24058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 240692362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org fDstToUnit.setConcat(im, this->getTotalInverse()); 240792362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return true; 24088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 24098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 2411689411a87ca7d19abe04b5c9baff26bd96b2123ereed@android.com#include "SkComposeShader.h" 24128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int ScalarTo256(SkScalar v) { 24148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale = SkScalarToFixed(v) >> 8; 24158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale < 0) { 24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale = 0; 24178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 24188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale > 255) { 24198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale = 255; 24208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 24218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkAlpha255To256(scale); 24228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 24238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 242487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 2425e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader, 2426e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const ContextRec& rec) 2427e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org : INHERITED(shader, rec) {} 242887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 242987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} 243087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 243187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgsize_t SkTriColorShader::contextSize() const { 243287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org return sizeof(TriColorShaderContext); 243387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org} 243487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 243506a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org const int alphaScale = Sk255To256(this->getPaintAlpha()); 243606a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 24378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src; 2438a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 24398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 24408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); 24418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += 1; 2442a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 24438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale1 = ScalarTo256(src.fX); 24448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale2 = ScalarTo256(src.fY); 24458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale0 = 256 - scale1 - scale2; 24468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale0 < 0) { 24478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale1 > scale2) { 24488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale2 = 256 - scale1; 24498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 24508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale1 = 256 - scale2; 24518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 24528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale0 = 0; 24538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2454a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 245506a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org if (256 != alphaScale) { 245606a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale0 = SkAlphaMul(scale0, alphaScale); 245706a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale1 = SkAlphaMul(scale1, alphaScale); 245806a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale2 = SkAlphaMul(scale2, alphaScale); 245906a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org } 246006a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 24618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 246206a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[1], scale1) + 246306a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[2], scale2); 24648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 24658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 24668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24670f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 246876f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkTriColorShader::toString(SkString* str) const { 246976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkTriColorShader: ("); 247076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 247176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 247276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 247376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 247476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 247576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 247676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 24778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, 24788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint vertices[], const SkPoint textures[], 24798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 24808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 24818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 24828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == count || NULL != vertices); 2483a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 24848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // abort early if there is nothing to draw 2485045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { 24868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 24878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2488a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 24898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform out vertices into device coordinates 24908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoSTMalloc<16, SkPoint> storage(count); 24918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* devVerts = storage.get(); 24928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapPoints(devVerts, vertices, count); 2493a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 24948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 24958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect bounds; 24968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(devVerts, count); 24978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fBounder->doRect(bounds, paint)) { 24988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 24998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2501a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 25028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 25038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com We can draw the vertices in 1 of 4 ways: 25048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - solid color (no shader/texture[], no colors[]) 25068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just colors (no shader/texture[], has colors[]) 25078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just texture (has shader/texture[], no colors[]) 25088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - colors * texture (has shader/texture[], has colors[]) 2509a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 25108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Thus for texture drawing, we need both texture[] and a shader. 25118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 25128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTriColorShader triShader; // must be above declaration of p 25148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 25158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = p.getShader(); 25178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == shader) { 25188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we have no shader, we ignore the texture coordinates 25198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com textures = NULL; 25208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (NULL == textures) { 25218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we don't have texture coordinates, ignore the shader 25228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setShader(NULL); 25238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader = NULL; 25248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup the custom shader (if needed) 252787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkAutoTUnref<SkComposeShader> composeShader; 25288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != colors) { 25298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == textures) { 25308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // just colors (no texture) 2531a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com shader = p.setShader(&triShader); 25328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 25338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // colors * texture 25348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(shader); 25358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool releaseMode = false; 25368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == xmode) { 25378d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com xmode = SkXfermode::Create(SkXfermode::kModulate_Mode); 25388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com releaseMode = true; 25398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 254087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode))); 254187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org p.setShader(composeShader); 25428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (releaseMode) { 25438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com xmode->unref(); 25448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 25488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); 254987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Abort early if we failed to create a shader context. 2550ea033606a06d05d2d42aa7118409fee798e53167reed@google.com if (blitter->isNullBlitter()) { 2551ea033606a06d05d2d42aa7118409fee798e53167reed@google.com return; 2552ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 2553ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 25548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup our state and function pointer for iterating triangles 25558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState state(count, indices, indexCount); 25568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState::Proc vertProc = state.chooseProc(vmode); 2557a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 25588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != textures || NULL != colors) { 2559f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com SkMatrix tempM; 2560f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com SkMatrix savedLocalM; 2561f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com if (shader) { 2562f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com savedLocalM = shader->getLocalMatrix(); 2563f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com } 2564a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 25658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 25668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != textures) { 25678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (texture_to_matrix(state, vertices, textures, &tempM)) { 2568f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com tempM.postConcat(savedLocalM); 25698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->setLocalMatrix(tempM); 257087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (!blitter->resetShaderContext(*fBitmap, p, *fMatrix)) { 25718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 25728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != colors) { 257687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Find the context for triShader. 257787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkTriColorShader::TriColorShaderContext* triColorShaderContext; 257887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 257987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContext = blitter->getShaderContext(); 258087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(shaderContext); 258187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (p.getShader() == &triShader) { 258287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org triColorShaderContext = 258387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext); 258487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } else { 258587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // The shader is a compose shader and triShader is its first shader. 258687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(p.getShader() == composeShader); 258787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkASSERT(composeShader->getShaderA() == &triShader); 258887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkComposeShader::ComposeShaderContext* composeShaderContext = 258987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext); 259087fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA(); 259187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org triColorShaderContext = 259287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA); 259387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org } 259487fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 259587fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org if (!triColorShaderContext->setup(vertices, colors, 259687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org state.f0, state.f1, state.f2)) { 25978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 25988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 25998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2600045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2601045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPoint tmp[] = { 2602045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 2603045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com }; 2604045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillTriangle(tmp, *fRC, blitter.get()); 26058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 260619376b80476b0fdbdcc8ac33bfdbae9b0d3fdce7djsollen@google.com 26078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now restore the shader's original local matrix 26088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != shader) { 2609f94b3a4cebd4adab09c40ebe23c02a615e10c394bsalomon@google.com shader->setLocalMatrix(savedLocalM); 26108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 26118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 26128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // no colors[] and no texture 26138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); 2614045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip& clip = *fRC; 26158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 2616045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get()); 2617045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get()); 2618045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get()); 26198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 26208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 26218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 26228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26230a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 26240a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 26258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 26278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2628f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkDraw::validate() const { 26298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fBitmap != NULL); 26308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMatrix != NULL); 26318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fClip != NULL); 2632045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(fRC != NULL); 26338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2634045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& cr = fRC->getBounds(); 26358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect br; 26368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2637f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com br.set(0, 0, fBitmap->width(), fBitmap->height()); 26388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cr.isEmpty() || br.contains(cr)); 26398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 26408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 26428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26430a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 26440a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com 26450a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.comSkBounder::SkBounder() { 26460a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com // initialize up front. This gets reset by SkCanvas before each draw call. 26470a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com fClip = &SkRegion::GetEmptyRegion(); 26480a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com} 26498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doIRect(const SkIRect& r) { 26518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect rr; 26528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr); 26538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 26548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2655d055c1fde2128514167b315f4d104b177e04a3dereed@android.com// TODO: change the prototype to take fixed, and update the callers 2656d055c1fde2128514167b315f4d104b177e04a3dereed@android.combool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y, 2657d055c1fde2128514167b315f4d104b177e04a3dereed@android.com const SkGlyph& glyph) { 2658474a12c4976b3000174cad5df74c498cd723c5e2reed@android.com SkIRect rr; 2659d055c1fde2128514167b315f4d104b177e04a3dereed@android.com if (!rr.intersect(fClip->getBounds(), r)) { 2660d055c1fde2128514167b315f4d104b177e04a3dereed@android.com return false; 2661d055c1fde2128514167b315f4d104b177e04a3dereed@android.com } 2662d055c1fde2128514167b315f4d104b177e04a3dereed@android.com GlyphRec rec; 2663d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y)); 2664d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX, 2665d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fLSB.fY + glyph.fAdvanceY); 2666d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fGlyphID = glyph.getGlyphID(); 2667d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fFlags = 0; 2668d055c1fde2128514167b315f4d104b177e04a3dereed@android.com return this->onIRectGlyph(rr, rec); 2669474a12c4976b3000174cad5df74c498cd723c5e2reed@android.com} 2670474a12c4976b3000174cad5df74c498cd723c5e2reed@android.com 26718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1, 26728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 26738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect r; 26748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar v0, v1; 26758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v0 = pt0.fX; 26778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v1 = pt1.fX; 26788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (v0 > v1) { 26798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<SkScalar>(v0, v1); 26808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2681e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com r.fLeft = SkScalarFloorToInt(v0); 2682e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com r.fRight = SkScalarCeilToInt(v1); 26838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v0 = pt0.fY; 26858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v1 = pt1.fY; 26868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (v0 > v1) { 26878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<SkScalar>(v0, v1); 26888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2689e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com r.fTop = SkScalarFloorToInt(v0); 2690e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com r.fBottom = SkScalarCeilToInt(v1); 26918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 26938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.inset(-1, -1); 26948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 26958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->doIRect(r); 26968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 26978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 26988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) { 26998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect r; 27008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getStyle() == SkPaint::kFill_Style) { 27028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rect.round(&r); 27038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 27048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rad = -1; 27058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rect.roundOut(&r); 27068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 27078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rad = -2; 27088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 27098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.inset(rad, rad); 27108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 27118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->doIRect(r); 27128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 27138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) { 2715d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkIRect r; 2716d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 27178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (doFill) { 27198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.round(&r); 27208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // hairline 27218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.roundOut(&r); 27228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 27238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 27258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.inset(-1, -1); 27268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 27278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->doIRect(r); 27288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 27298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBounder::commit() { 27318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // override in subclass 27328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 27338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////////// 27358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 27378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 27388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h" 27398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 27408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 274230711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com const SkMaskFilter* filter, const SkMatrix* filterMatrix, 27438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect* bounds) { 27448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (devPath.isEmpty()) { 27458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 27468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 27478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // init our bounds from the path 27498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2750d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect pathBounds = devPath.getBounds(); 27518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf); 27528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathBounds.roundOut(bounds); 27538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2754a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 27556db75fc2c393ba86a3f533597a8bcd348477e79ctomhudson@google.com SkIPoint margin = SkIPoint::Make(0, 0); 27568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (filter) { 27578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(filterMatrix); 2758a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 27595af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkMask srcM, dstM; 2760a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 27618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fBounds = *bounds; 27628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fFormat = SkMask::kA8_Format; 27638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fImage = NULL; 27648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 27658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 27668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 27678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2768a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 27695af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com // (possibly) trim the bounds to reflect the clip 27708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (plus whatever slop the filter needs) 27715af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (clipBounds) { 27725af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkIRect tmp = *clipBounds; 27733555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // Ugh. Guard against gigantic margins from wacky filters. Without this 27743555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // check we can request arbitrary amounts of slop beyond our visible 27753555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // clip, and bring down the renderer (at least on finite RAM machines 27763555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // like handsets, etc.). Need to balance this invented value between 27773555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // quality of large filters like blurs, and the corresponding memory 27783555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // requests. 27793555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com static const int MAX_MARGIN = 128; 27803555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com tmp.inset(-SkMin32(margin.fX, MAX_MARGIN), 27813555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com -SkMin32(margin.fY, MAX_MARGIN)); 27825af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (!bounds->intersect(tmp)) { 27835af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com return false; 27845af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 27858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 27868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 27888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 27898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27902ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.orgstatic void draw_into_mask(const SkMask& mask, const SkPath& devPath, 27912ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkPaint::Style style) { 2792045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBitmap bm; 2793045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkDraw draw; 2794045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip clip; 2795045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMatrix matrix; 2796045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPaint paint; 27978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 27988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes); 27998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bm.setPixels(mask.fImage); 28008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2801045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height())); 28028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 28038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 28048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fBitmap = &bm; 2806045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com draw.fRC = &clip; 2807045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com draw.fClip = &clip.bwRgn(); 28088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 28098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fBounder = NULL; 28108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setAntiAlias(true); 28112ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org paint.setStyle(style); 28128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawPath(devPath, paint); 28138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 28148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 281630711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com const SkMaskFilter* filter, const SkMatrix* filterMatrix, 28172ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkMask* mask, SkMask::CreateMode mode, 28182ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkPaint::Style style) { 28198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustRenderImage_CreateMode != mode) { 28208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 28218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 28228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2823a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 28248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 28258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fFormat = SkMask::kA8_Format; 28268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fRowBytes = mask->fBounds.width(); 2827543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask->computeImageSize(); 2828543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 2829543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // we're too big to allocate the mask, abort 2830543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; 2831543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 2832543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com mask->fImage = SkMask::AllocImage(size); 28338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask->fImage, 0, mask->computeImageSize()); 28348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 28358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 28368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustComputeBounds_CreateMode != mode) { 28372ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org draw_into_mask(*mask, devPath, style); 28388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2839a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 28408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 28418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2842