SkDraw.cpp revision 7120b2d577d3aab1f51c5af1530a68c57ca51696
1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */ 7903dcb08b146cbaf81420a734a64692038b467cabungeman#define __STDC_LIMIT_MACROS 8ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 1083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby 1183e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby#include "SkArenaAlloc.h" 12374772bd61951f01bf84fe17bf53d8867681c9aereed#include "SkBlendModePriv.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 164b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita#include "SkColorShader.h" 17986480a71f4e860663ced7ad90a1fe346a164afbMike Reed#include "SkDevice.h" 181c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com#include "SkDeviceLooper.h" 19e5911c9c5b859d60208f4b9ac4bf2a638f4bc35fherb#include "SkFindAndPlaceGlyph.h" 202211b623274e24d0025763cfa855c9eb53d5b900bungeman@google.com#include "SkFixed.h" 2100dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita#include "SkLocalMatrixShader.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h" 23f553e4e09cd2baf15fc041daab8a08bd46e352f0herb#include "SkMatrix.h" 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathEffect.h" 26045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com#include "SkRasterClip.h" 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRasterizer.h" 28a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com#include "SkRRect.h" 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScan.h" 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h" 3176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#include "SkString.h" 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStroke.h" 33435657fd62960ceffb1c3c63f63e836373560bc5halcanary#include "SkStrokeRec.h" 34f553e4e09cd2baf15fc041daab8a08bd46e352f0herb#include "SkTemplates.h" 35cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen#include "SkTextMapStateProc.h" 3632e5d97ccf60f859db063ebd6e903c362e625767reed@google.com#include "SkTLazy.h" 374b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita#include "SkUnPreMultiply.h" 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 39559a8833f0eae4af37dc0ffc3ee97e1fb14817b1commit-bot@chromium.org#include "SkVertState.h" 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcShader.h" 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawProcs.h" 43ae57358447bac678e3fc458fa2857a349a6a7081reed@google.com#include "SkMatrixUtils.h" 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define TRACE_BITMAP_DRAWS 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 47d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// Helper function to fix code gen bug on ARM64. 48d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb// See SkFindAndPlaceGlyph.h for more details. 49d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbvoid FixGCC49Arm64Bug(int v) { } 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 51fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com/** Helper for allocating small blitters on the stack. 52fd4236ecc1d5eb1bb48ca9dc33df5e9051c3036ereed@google.com */ 5340c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.comclass SkAutoBlitterChoose : SkNoncopyable { 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 551d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkAutoBlitterChoose() { 5696fcdcc219d2a0d3579719b84b28bede76efba64halcanary fBlitter = nullptr; 571d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 5841e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose(const SkPixmap& dst, const SkMatrix& matrix, 59126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkPaint& paint, bool drawCoverage = false) { 6083e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAlloc, drawCoverage); 61e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org } 62e59124ed1a62f1fec79679c38cabed622a756f75herb 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* operator->() { return fBlitter; } 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* get() const { return fBlitter; } 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6641e010cb901c0da9066c4df562030808c9ccd7f8reed void choose(const SkPixmap& dst, const SkMatrix& matrix, 6753f0959fc024c56dc55fe6bf86380127b59abec9krajcevski const SkPaint& paint, bool drawCoverage = false) { 681d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com SkASSERT(!fBlitter); 6983e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby fBlitter = SkBlitter::Choose(dst, matrix, paint, &fAlloc, drawCoverage); 701d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com } 711d6ee0bd4db7f3b676209341214641d9af5a965freed@google.com 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 7334e91ca5ccd9aa1d13838631212e26ef5fadf71aHerb Derby // Owned by fAlloc, which will handle the delete. 74a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org SkBlitter* fBlitter; 7583e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby 76c464035f81caa06dab12a2761d24cfc8d9e598dbMike Reed char fStorage[kSkBlitterContextSize]; 77c464035f81caa06dab12a2761d24cfc8d9e598dbMike Reed SkArenaAlloc fAlloc{fStorage}; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 79e61a86cfa00ea393ecc4a71fca94e1d476a37ecccommit-bot@chromium.org#define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose) 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 814bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derbystatic SkPaint make_paint_with_image( 824bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby const SkPaint& origPaint, const SkBitmap& bitmap, SkMatrix* matrix = nullptr) { 834bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby SkPaint paint(origPaint); 844bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby paint.setShader(SkMakeBitmapShader(bitmap, SkShader::kClamp_TileMode, 854bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby SkShader::kClamp_TileMode, matrix, 864bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby kNever_SkCopyPixelsMode)); 874bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby return paint; 884bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby} 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 92f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comSkDraw::SkDraw() { 93f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com sk_bzero(this, sizeof(*this)); 94f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com} 95f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com 964bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.combool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const { 974bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (fRC->isEmpty()) { 984bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return false; 994bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 1004bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1014bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkMatrix inverse; 1024bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (!fMatrix->invert(&inverse)) { 1034bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return false; 1044bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 1054bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1064bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkIRect devBounds = fRC->getBounds(); 1074bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com // outset to have slop for antialasing and hairlines 1084bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com devBounds.outset(1, 1); 1094bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com inverse.mapRect(localBounds, SkRect::Make(devBounds)); 1104bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com return true; 1114bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com} 1124bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) { 1184516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(pixels, bytes); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {} 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 124a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2)); 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 128a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1)); 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(pixels, data, bytes); 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13541e010cb901c0da9066c4df562030808c9ccd7f8reedstatic BitmapXferProc ChooseBitmapXferProc(const SkPixmap& dst, const SkPaint& paint, 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t* data) { 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // todo: we can apply colorfilter up front if no shader, so we wouldn't 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to abort this fastpath 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getShader() || paint.getColorFilter()) { 14096fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 143374772bd61951f01bf84fe17bf53d8867681c9aereed SkBlendMode mode = paint.getBlendMode(); 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColor color = paint.getColor(); 145a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // collaps modes based on color... 147374772bd61951f01bf84fe17bf53d8867681c9aereed if (SkBlendMode::kSrcOver == mode) { 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned alpha = SkColorGetA(color); 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == alpha) { 150374772bd61951f01bf84fe17bf53d8867681c9aereed mode = SkBlendMode::kDst; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (0xFF == alpha) { 152374772bd61951f01bf84fe17bf53d8867681c9aereed mode = SkBlendMode::kSrc; 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 155a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 157374772bd61951f01bf84fe17bf53d8867681c9aereed case SkBlendMode::kClear: 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Clear_BitmapXferProc\n"); 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Clear_BitmapXferProc; // ignore data 160374772bd61951f01bf84fe17bf53d8867681c9aereed case SkBlendMode::kDst: 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Dst_BitmapXferProc\n"); 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Dst_BitmapXferProc; // ignore data 163374772bd61951f01bf84fe17bf53d8867681c9aereed case SkBlendMode::kSrc: { 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 165a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com should I worry about dithering for the lower depths? 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor pmc = SkPreMultiplyColor(color); 16841e010cb901c0da9066c4df562030808c9ccd7f8reed switch (dst.colorType()) { 16928fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = pmc; 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D32_Src_BitmapXferProc\n"); 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D32_Src_BitmapXferProc; 175900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkPixel32ToPixel16(pmc); 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D16_Src_BitmapXferProc\n"); 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D16_Src_BitmapXferProc; 181900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkGetPackedA32(pmc); 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- DA8_Src_BitmapXferProc\n"); 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return DA8_Src_BitmapXferProc; 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return nullptr; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19841e010cb901c0da9066c4df562030808c9ccd7f8reedstatic void CallBitmapXferProc(const SkPixmap& dst, const SkIRect& rect, BitmapXferProc proc, 19941e010cb901c0da9066c4df562030808c9ccd7f8reed uint32_t procData) { 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int shiftPerPixel; 20141e010cb901c0da9066c4df562030808c9ccd7f8reed switch (dst.colorType()) { 20228fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org case kN32_SkColorType: 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 2; 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 205900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kRGB_565_SkColorType: 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 1; 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 208900ecf2f1579d42c9d2959831787af0346320f86reed@google.com case kAlpha_8_SkColorType: 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 0; 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2120c00f21fee3f5cfa3aa7e5d46ff94cb8cf340451tomhudson@google.com SkDEBUGFAIL("Can't use xferproc on this config"); 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21641e010cb901c0da9066c4df562030808c9ccd7f8reed uint8_t* pixels = (uint8_t*)dst.writable_addr(); 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pixels); 21841e010cb901c0da9066c4df562030808c9ccd7f8reed const size_t rowBytes = dst.rowBytes(); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int widthBytes = rect.width() << shiftPerPixel; 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip down to the first scanline and X position 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel); 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int scans = rect.height() - 1; scans >= 0; --scans) { 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(pixels, widthBytes, procData); 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rowBytes; 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPaint(const SkPaint& paint) const { 230f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 232045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devRect; 23741e010cb901c0da9066c4df562030808c9ccd7f8reed devRect.set(0, 0, fDst.width(), fDst.height()); 238a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 239045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 240045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com /* If we don't have a shader (i.e. we're just a solid color) we may 241045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com be faster to operate directly on the device bitmap, rather than invoking 242045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com a blitter. Esp. true for xfermodes, which require a colorshader to be 243045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com present, which is just redundant work. Since we're drawing everywhere 244045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com in the clip, we don't have to worry about antialiasing. 245045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com */ 246045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com uint32_t procData = 0; // to avoid the warning 24741e010cb901c0da9066c4df562030808c9ccd7f8reed BitmapXferProc proc = ChooseBitmapXferProc(fDst, paint, &procData); 248045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (proc) { 249045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (D_Dst_BitmapXferProc == proc) { // nothing to do 250045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 251045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 252a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 253045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRegion::Iterator iter(fRC->bwRgn()); 254045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com while (!iter.done()) { 25541e010cb901c0da9066c4df562030808c9ccd7f8reed CallBitmapXferProc(fDst, iter.rect(), proc, procData); 256045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com iter.next(); 257045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 258045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 261045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 262045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com // normal case: use a blitter 26341e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 264045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(devRect, *fRC, blitter.get()); 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct PtProcRec { 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::PointMode fMode; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* fClip; 273045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip* fRC; 274a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // computed values 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fRadius; 277a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter*); 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix, 282045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip*); 283045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com Proc chooseProc(SkBlitter** blitter); 284045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 285045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comprivate: 286045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper fWrapper; 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec.fClip->isRect()); 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = rec.fClip->getBounds(); 293a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 2952d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 2962d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_16_hair_proc(const PtProcRec& rec, 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint devPts[], int count, 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter) { 306045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkASSERT(rec.fRC->isRect()); 307045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 30941e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 31041e010cb901c0da9066c4df562030808c9ccd7f8reed SkASSERT(dst); 311c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 31241e010cb901c0da9066c4df562030808c9ccd7f8reed uint16_t* addr = dst->writable_addr16(0, 0); 31341e010cb901c0da9066c4df562030808c9ccd7f8reed size_t rb = dst->rowBytes(); 314c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3162d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3172d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value); 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3242d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.comstatic void bw_pt_rect_32_hair_proc(const PtProcRec& rec, 3252d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkPoint devPts[], int count, 3262d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkBlitter* blitter) { 3272d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(rec.fRC->isRect()); 3282d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com const SkIRect& r = rec.fRC->getBounds(); 3292d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com uint32_t value; 33041e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 33141e010cb901c0da9066c4df562030808c9ccd7f8reed SkASSERT(dst); 332c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 33341e010cb901c0da9066c4df562030808c9ccd7f8reed SkPMColor* addr = dst->writable_addr32(0, 0); 33441e010cb901c0da9066c4df562030808c9ccd7f8reed size_t rb = dst->rowBytes(); 335c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3362d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com for (int i = 0; i < count; i++) { 3372d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 3382d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3392d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (r.contains(x, y)) { 3402d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com ((SkPMColor*)((char*)addr + y * rb))[x] = value; 3412d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3422d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 3432d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com} 3442d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 348e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int x = SkScalarFloorToInt(devPts[i].fX); 349e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int y = SkScalarFloorToInt(devPts[i].fY); 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec.fClip->contains(x, y)) { 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 3595dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter); 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3655dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairLine(devPts, count, *rec.fRC, blitter); 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// aa versions 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 3735dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter); 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3795dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter); 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 390c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 396c3d7d90973528527131c72549b10c2a21300e0acskia.committer@gmail.com 397045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillXRect(r, *rec.fRC, blitter); 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 407a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 413a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 414045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::AntiFillXRect(r, *rec.fRC, blitter); 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 418b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com// If this guy returns true, then chooseProc() must return a valid proc 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 420045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkMatrix* matrix, const SkRasterClip* rc) { 4213ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang if ((unsigned)mode > (unsigned)SkCanvas::kPolygon_PointMode) { 4223ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang return false; 4233ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang } 4243ece53ed30b934894c87c8adb2a77cfdf2ecfcfeochang 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect()) { 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width = paint.getStrokeWidth(); 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == width) { 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 43296fcdcc219d2a0d3579719b84b28bede76efba64halcanary fClip = nullptr; 433045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 4342d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com fRadius = SK_FixedHalf; 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 437b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com if (paint.getStrokeCap() != SkPaint::kRound_Cap && 4389f2251c73ed6f417dd1057d487bf523e04488440robertphillips matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) { 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = matrix->get(SkMatrix::kMScaleX); 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = matrix->get(SkMatrix::kMScaleY); 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(sx - sy)) { 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sx < 0) { 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sx = -sx; 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 44896fcdcc219d2a0d3579719b84b28bede76efba64halcanary fClip = nullptr; 449045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fRC = rc; 450a99b6ceff92183b424634f2e7276b9ea1d59e69dMike Reed fRadius = SkScalarToFixed(width * sx) >> 1; 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 457045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comPtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { 45896fcdcc219d2a0d3579719b84b28bede76efba64halcanary Proc proc = nullptr; 459a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 460045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = *blitterPtr; 461045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 462045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fRC->bwRgn(); 463045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 464045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fWrapper.init(*fRC, blitter); 465045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com fClip = &fWrapper.getRgn(); 466045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = fWrapper.getBlitter(); 467045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com *blitterPtr = blitter; 468045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 469045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for our arrays 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == SkCanvas::kPoints_PointMode); 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == SkCanvas::kLines_PointMode); 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(2 == SkCanvas::kPolygon_PointMode); 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4762d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fPaint->isAntiAlias()) { 4772d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (0 == fPaint->getStrokeWidth()) { 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const Proc gAAProcs[] = { 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gAAProcs[fMode]; 4822d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 4832d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com SkASSERT(SkCanvas::kPoints_PointMode == fMode); 4842d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = aa_square_proc; 4852d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } 4862d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com } else { // BW 4872d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com if (fRadius <= SK_FixedHalf) { // small radii and hairline 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 49041e010cb901c0da9066c4df562030808c9ccd7f8reed const SkPixmap* bm = blitter->justAnOpaqueColor(&value); 491900ecf2f1579d42c9d2959831787af0346320f86reed@google.com if (bm && kRGB_565_SkColorType == bm->colorType()) { 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_16_hair_proc; 49328fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org } else if (bm && kN32_SkColorType == bm->colorType()) { 4942d47a21b27035798d53de4d5cb8ac7c03534ab27reed@google.com proc = bw_pt_rect_32_hair_proc; 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_hair_proc; 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static Proc gBWProcs[] = { 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gBWProcs[fMode]; 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_square_proc; 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return proc; 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// each of these costs 8-bytes of stack space, so don't make it too large 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// must be even for lines/polygon to work 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_DEV_PTS 32 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 516f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com const SkPoint pts[], const SkPaint& paint, 51799330ba6227137866a0dbd63478d36f335203ebdMike Reed SkBaseDevice* device) const { 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're in lines mode, force count to be even 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kLines_PointMode == mode) { 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count &= ~(size_t)1; 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 526a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 52796fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(pts != nullptr); 528f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 529a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 531045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PtProcRec rec; 53699330ba6227137866a0dbd63478d36f335203ebdMike Reed if (!device && rec.init(mode, paint, fMatrix, fRC)) { 53741e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint devPts[MAX_DEV_PTS]; 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* bltr = blitter.get(); 542045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com PtProcRec::Proc proc = rec.chooseProc(&bltr); 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we have to back up subsequent passes if we're in polygon mode 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 545a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 547a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org int n = SkToInt(count); 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (n > MAX_DEV_PTS) { 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = MAX_DEV_PTS; 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->mapPoints(devPts, pts, n); 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(rec, devPts, n, bltr); 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts += n - backup; 554a8c7f7702fb4bbedb615031bc653c5cd161a038ecommit-bot@chromium.org SkASSERT(SkToInt(count) >= n); 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= n; 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += backup; 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count != 0); 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPoints_PointMode: { 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // temporarily mark the paint as filling. 56440c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint newPaint(paint); 56540c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com newPaint.setStyle(SkPaint::kFill_Style); 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 56740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkScalar width = newPaint.getStrokeWidth(); 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar radius = SkScalarHalf(width); 569a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 57040c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) { 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix preMatrix; 5737ef849d45a4de02697697ea213bfae7c215a0c38mtklein 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addCircle(0, 0, radius); 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com preMatrix.setTranslate(pts[i].fX, pts[i].fY); 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // pass true for the last point, since we can modify 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // then path then 579b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile((count-1) == i); 58099330ba6227137866a0dbd63478d36f335203ebdMike Reed if (device) { 581a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed device->drawPath(path, newPaint, &preMatrix, (count-1) == i); 582f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 583a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed this->drawPath(path, newPaint, &preMatrix, (count-1) == i); 584f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 588a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = pts[i].fX - radius; 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = pts[i].fY - radius; 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = r.fLeft + width; 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = r.fTop + width; 59499330ba6227137866a0dbd63478d36f335203ebdMike Reed if (device) { 595a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed device->drawRect(r, newPaint); 596f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 59740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com this->drawRect(r, newPaint); 598f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kLines_PointMode: 60449f085dddff10473b6ebf832a974288300224e60bsalomon if (2 == count && paint.getPathEffect()) { 605629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // most likely a dashed line - see if it is one of the ones 606629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // we can accelerate 607629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkStrokeRec rec(paint); 6086d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkPathEffect::PointData pointData; 609629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 610629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPath path; 611629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.moveTo(pts[0]); 612629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com path.lineTo(pts[1]); 613629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6144bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect = SkRect::Make(fRC->getBounds()); 6154024f32d99b63a599c544a49f526e53c25135159skia.committer@gmail.com 6164bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (paint.getPathEffect()->asPoints(&pointData, path, rec, 6174bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com *fMatrix, &cullRect)) { 6186d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // 'asPoints' managed to find some fast path 6196d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 620629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com SkPaint newP(paint); 62196fcdcc219d2a0d3579719b84b28bede76efba64halcanary newP.setPathEffect(nullptr); 622935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com newP.setStyle(SkPaint::kFill_Style); 623629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com 6246d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fFirst.isEmpty()) { 62599330ba6227137866a0dbd63478d36f335203ebdMike Reed if (device) { 626a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed device->drawPath(pointData.fFirst, newP); 6276d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6286d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fFirst, newP); 6296d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 630629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 6316d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6326d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (!pointData.fLast.isEmpty()) { 63399330ba6227137866a0dbd63478d36f335203ebdMike Reed if (device) { 634a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed device->drawPath(pointData.fLast, newP); 6356d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6366d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPath(pointData.fLast, newP); 6376d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6386d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6396d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6406d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (pointData.fSize.fX == pointData.fSize.fY) { 6416d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line can just be drawn as points 6426d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth())); 6436d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6446d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) { 6456d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kRound_Cap); 6466d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6476d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP.setStrokeCap(SkPaint::kButt_Cap); 6486d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6496d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 65099330ba6227137866a0dbd63478d36f335203ebdMike Reed if (device) { 651a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed device->drawPoints(SkCanvas::kPoints_PointMode, 652a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed pointData.fNumPoints, 653a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed pointData.fPoints, 654a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed newP); 6556d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6566d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawPoints(SkCanvas::kPoints_PointMode, 6576d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fNumPoints, 6586d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints, 6596d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com newP, 66099330ba6227137866a0dbd63478d36f335203ebdMike Reed device); 6616d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6626d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com break; 663935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } else { 6646d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com // The rest of the dashed line must be drawn as rects 6657a03d86a3d9adcb13432fbd82039725149487c97skia.committer@gmail.com SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag & 6666d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fFlags)); 6676d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6686d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com SkRect r; 6696d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 6706d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com for (int i = 0; i < pointData.fNumPoints; ++i) { 6716d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com r.set(pointData.fPoints[i].fX - pointData.fSize.fX, 6726d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY - pointData.fSize.fY, 6736d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fX + pointData.fSize.fX, 6746d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com pointData.fPoints[i].fY + pointData.fSize.fY); 67599330ba6227137866a0dbd63478d36f335203ebdMike Reed if (device) { 676a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed device->drawRect(r, newP); 6776d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } else { 6786d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com this->drawRect(r, newP); 6796d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 6806d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com } 681935ad026826fb7d31d562ff7326b84ec3a827456robertphillips@google.com } 6826d87557278052c131957e5d6e093d3a675162d22robertphillips@google.com 683629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com break; 684629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 685629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com } 686629ab540667422d3edcb97c51e9628b7051e1ba4robertphillips@google.com // couldn't take fast path so fall through! 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPolygon_PointMode: { 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= 1; 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setStyle(SkPaint::kStroke_Style); 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 693b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile(true); 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i += inc) { 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(pts[i]); 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.lineTo(pts[i+1]); 69799330ba6227137866a0dbd63478d36f335203ebdMike Reed if (device) { 698a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed device->drawPath(path, p, nullptr, true); 699f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } else { 70096fcdcc219d2a0d3579719b84b28bede76efba64halcanary this->drawPath(path, p, nullptr, true); 701f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.rewind(); 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7101a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalitastatic inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) { 7111a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkASSERT(matrix.rectStaysRect()); 7121a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkASSERT(SkPaint::kFill_Style != paint.getStyle()); 7131a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 7141a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkVector size; 7151a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; 7161a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita matrix.mapVectors(&size, &pt, 1); 7171a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY)); 7181a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita} 7191a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 720761fb62b0eb174783316d2a8b933fba896ca6355reed@google.comstatic bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, 721761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com SkPoint* strokeSize) { 722761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com if (SkPaint::kMiter_Join != paint.getStrokeJoin() || 723761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com paint.getStrokeMiter() < SK_ScalarSqrt2) { 724761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return false; 725761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com } 726fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7271a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita *strokeSize = compute_stroke_size(paint, matrix); 728761fb62b0eb174783316d2a8b933fba896ca6355reed@google.com return true; 7297ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org} 7307ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 73162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.comSkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, 73262ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const SkMatrix& matrix, 73362ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint* strokeSize) { 7347ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org RectType rtype; 7357ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org const SkScalar width = paint.getStrokeWidth(); 73662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com const bool zeroWidth = (0 == width); 7377ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::Style style = paint.getStyle(); 738fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7397ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { 7407ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org style = SkPaint::kFill_Style; 7417ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 742fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect() || paint.getMaskFilter() || 74462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com paint.getRasterizer() || !matrix.rectStaysRect() || 7457ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org SkPaint::kStrokeAndFill_Style == style) { 74662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com rtype = kPath_RectType; 74762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (SkPaint::kFill_Style == style) { 7487ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kFill_RectType; 7497ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else if (zeroWidth) { 7507ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kHair_RectType; 75162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } else if (easy_rect_join(paint, matrix, strokeSize)) { 7527ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kStroke_RectType; 7537ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } else { 7547ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org rtype = kPath_RectType; 7557ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org } 75662ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return rtype; 75762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com} 75862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 7597324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic const SkPoint* rect_points(const SkRect& r) { 760fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<const SkPoint*>(&r); 7617324415759fe0c5a0902877b664aa942a89bd940reed@google.com} 7627324415759fe0c5a0902877b664aa942a89bd940reed@google.com 7637324415759fe0c5a0902877b664aa942a89bd940reed@google.comstatic SkPoint* rect_points(SkRect& r) { 764fc2f0d0e6e6f72503ff9504296556dc637059c15reed@google.com return SkTCast<SkPoint*>(&r); 76540c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com} 76640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com 7670393912de72bc3d8b3640c122c53470dd0da1e6dreedvoid SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint, 7680393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkMatrix* paintMatrix, const SkRect* postPaintRect) const { 76962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkDEBUGCODE(this->validate();) 7707ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org 77162ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com // nothing to draw 772045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 77362ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com return; 77462ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com } 77562ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 7760393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkMatrix* matrix; 7770393912de72bc3d8b3640c122c53470dd0da1e6dreed SkMatrix combinedMatrixStorage; 7780393912de72bc3d8b3640c122c53470dd0da1e6dreed if (paintMatrix) { 7790393912de72bc3d8b3640c122c53470dd0da1e6dreed SkASSERT(postPaintRect); 7800393912de72bc3d8b3640c122c53470dd0da1e6dreed combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix); 7810393912de72bc3d8b3640c122c53470dd0da1e6dreed matrix = &combinedMatrixStorage; 7820393912de72bc3d8b3640c122c53470dd0da1e6dreed } else { 7830393912de72bc3d8b3640c122c53470dd0da1e6dreed SkASSERT(!postPaintRect); 7840393912de72bc3d8b3640c122c53470dd0da1e6dreed matrix = fMatrix; 7850393912de72bc3d8b3640c122c53470dd0da1e6dreed } 7860393912de72bc3d8b3640c122c53470dd0da1e6dreed 78762ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com SkPoint strokeSize; 78862ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); 78962ab7addb06bbc5b93460eaf2f70a9f8399308d3reed@google.com 7907ff678bc1618dc669648198a7bdca8adfb189505mike@reedtribe.org if (kPath_RectType == rtype) { 7910393912de72bc3d8b3640c122c53470dd0da1e6dreed SkDraw draw(*this); 7920393912de72bc3d8b3640c122c53470dd0da1e6dreed if (paintMatrix) { 7930393912de72bc3d8b3640c122c53470dd0da1e6dreed draw.fMatrix = matrix; 7940393912de72bc3d8b3640c122c53470dd0da1e6dreed } 7958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmp; 7960393912de72bc3d8b3640c122c53470dd0da1e6dreed tmp.addRect(prePaintRect); 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setFillType(SkPath::kWinding_FillType); 79896fcdcc219d2a0d3579719b84b28bede76efba64halcanary draw.drawPath(tmp, paint, nullptr, true); 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8020393912de72bc3d8b3640c122c53470dd0da1e6dreed SkRect devRect; 8031a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect; 8041a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita // skip the paintMatrix when transforming the rect by the CTM 8051a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita fMatrix->mapPoints(rect_points(devRect), rect_points(paintRect), 2); 8067324415759fe0c5a0902877b664aa942a89bd940reed@google.com devRect.sort(); 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for the quick exit, before we build a blitter 8091a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkRect bbox = devRect; 8101c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.getStyle() != SkPaint::kFill_Style) { 8111c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // extra space for hairlines 812b3eba478d5bed5fb2b5f0f224738c8c292cebf36george if (paint.getStrokeWidth() == 0) { 8131a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita bbox.outset(1, 1); 814b3eba478d5bed5fb2b5f0f224738c8c292cebf36george } else { 8151a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita // For kStroke_RectType, strokeSize is already computed. 8161a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita const SkPoint& ssize = (kStroke_RectType == rtype) 8171a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita ? strokeSize 8181a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita : compute_stroke_size(paint, *fMatrix); 8191a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y())); 820b3eba478d5bed5fb2b5f0f224738c8c292cebf36george } 8211c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8221a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita 8231a178ca6dd2ff7f62c684f7d0ee94e54fc31c91bfmalita SkIRect ir = bbox.roundOut(); 8241c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (fRC->quickReject(ir)) { 8251c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com return; 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 82841e010cb901c0da9066c4df562030808c9ccd7f8reed SkDeviceLooper looper(fDst, *fRC, ir, paint.isAntiAlias()); 8291c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com while (looper.next()) { 8301c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkRect localDevRect; 8311c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com looper.mapRect(&localDevRect, devRect); 8321c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkMatrix localMatrix; 8330393912de72bc3d8b3640c122c53470dd0da1e6dreed looper.mapMatrix(&localMatrix, *matrix); 8341c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 83541e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitterStorage(looper.getPixmap(), localMatrix, paint); 8361c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com const SkRasterClip& clip = looper.getRC(); 8371c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkBlitter* blitter = blitterStorage.get(); 8381c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com 8391c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter 8401c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // case we are also hairline (if we've gotten to here), which devolves to 8411c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com // effectively just kFill 8421c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com switch (rtype) { 8431c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kFill_RectType: 8441c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8451c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFillRect(localDevRect, clip, blitter); 8461c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8471c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FillRect(localDevRect, clip, blitter); 8481c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8491c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8501c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kStroke_RectType: 8511c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8521c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); 8531c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8541c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); 8551c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8561c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8571c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com case kHair_RectType: 8581c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com if (paint.isAntiAlias()) { 8591c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::AntiHairRect(localDevRect, clip, blitter); 8601c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } else { 8611c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkScan::HairRect(localDevRect, clip, blitter); 8621c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8631c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com break; 8641c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com default: 8651c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com SkDEBUGFAIL("bad rtype"); 8661c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com } 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (srcM.fBounds.isEmpty()) { 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8750a60b3d32eae945688b69599f11679662657f751bungeman@google.com const SkMask* mask = &srcM; 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8770a60b3d32eae945688b69599f11679662657f751bungeman@google.com SkMask dstM; 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getMaskFilter() && 879e80eb928ba0248a5a5dea6e1f0005aa08ecf8740robertphillips paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, nullptr)) { 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask = &dstM; 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 88202f55841854ae32f21a13417e9ee711463e488cfbungeman@google.com SkAutoMaskFreeImage ami(dstM.fImage); 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 88441e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 885045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkBlitter* blitter = blitterChooser.get(); 886045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 887045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkAAClipBlitterWrapper wrapper; 888045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRegion* clipRgn; 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 890045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isBW()) { 891045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &fRC->bwRgn(); 892045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 893045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com wrapper.init(*fRC, blitter); 894045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clipRgn = &wrapper.getRgn(); 895045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter = wrapper.getBlitter(); 896045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 897045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com blitter->blitMaskRegion(*mask, *clipRgn); 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 900ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.comstatic SkScalar fast_len(const SkVector& vec) { 901ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar x = SkScalarAbs(vec.fX); 902ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar y = SkScalarAbs(vec.fY); 903ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (x < y) { 904ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkTSwap(x, y); 905ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 906ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return x + SkScalarHalf(y); 907ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 908ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 909e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.orgbool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, 910e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkScalar* coverage) { 911e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org SkASSERT(strokeWidth > 0); 912e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org // We need to try to fake a thick-stroke with a modulated hairline. 913ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 9148d430185e08d2067584837a76b7193b803fee7a0tomhudson@google.com if (matrix.hasPerspective()) { 915ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 916ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 917ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com 918ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkVector src[2], dst[2]; 919ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[0].set(strokeWidth, 0); 920ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com src[1].set(0, strokeWidth); 921ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com matrix.mapVectors(dst, src, 2); 922ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len0 = fast_len(dst[0]); 923ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len1 = fast_len(dst[1]); 924652807bbc8c57e5fa9622126b51fd369f5c67935agl@chromium.org if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { 92549f085dddff10473b6ebf832a974288300224e60bsalomon if (coverage) { 926e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org *coverage = SkScalarAve(len0, len1); 927e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org } 928ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return true; 929ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 930ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 931ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 932ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 933a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comvoid SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const { 934a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkDEBUGCODE(this->validate()); 935a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 936a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (fRC->isEmpty()) { 937a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; 938a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 939a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 940a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com { 941a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // TODO: Investigate optimizing these options. They are in the same 942a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // order as SkDraw::drawPath, which handles each case. It may be 943a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // that there is no way to optimize for these using the SkRRect path. 944a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkScalar coverage; 945a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) { 946a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 947a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 948a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 949a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 950a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 951a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 952a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 953a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getRasterizer()) { 954a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com goto DRAW_PATH; 955a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 956a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 957a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 958a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (paint.getMaskFilter()) { 959a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Transform the rrect into device space. 960a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkRRect devRRect; 961a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com if (rrect.transform(*fMatrix, &devRRect)) { 96241e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 963055e192adc0072ae2548ef5431ceee652945f9c2bsalomon if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get())) { 964a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com return; // filterRRect() called the blitter, so we're done 965a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 966a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 967a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com } 968a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 969a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.comDRAW_PATH: 970a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com // Now fall back to the default case of using a path. 971a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com SkPath path; 972a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com path.addRRect(rrect); 97396fcdcc219d2a0d3579719b84b28bede76efba64halcanary this->drawPath(path, paint, nullptr, true); 974a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com} 975a8e33a92e27ca1523601226cad83c79a7e00c93bscroggo@google.com 9761a7eb266644d2e1b0968dbca606ca0a91903419dcaryclarkSkScalar SkDraw::ComputeResScaleForStroking(const SkMatrix& matrix) { 97705d9044de4f1c6e791df66a425638752daac4c6breed if (!matrix.hasPerspective()) { 97805d9044de4f1c6e791df66a425638752daac4c6breed SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]); 97905d9044de4f1c6e791df66a425638752daac4c6breed SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY]); 98005d9044de4f1c6e791df66a425638752daac4c6breed if (SkScalarsAreFinite(sx, sy)) { 981a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman SkScalar scale = SkTMax(sx, sy); 982a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman if (scale > 0) { 983a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman return scale; 984a4b8704e76cb2136a3ff8c1553690f30b96870e0lsalzman } 98505d9044de4f1c6e791df66a425638752daac4c6breed } 98605d9044de4f1c6e791df66a425638752daac4c6breed } 98705d9044de4f1c6e791df66a425638752daac4c6breed return 1; 98805d9044de4f1c6e791df66a425638752daac4c6breed} 98905d9044de4f1c6e791df66a425638752daac4c6breed 99082595b6fa4733e1525f357bdcac22db058790550reedvoid SkDraw::drawDevPath(const SkPath& devPath, const SkPaint& paint, bool drawCoverage, 99182595b6fa4733e1525f357bdcac22db058790550reed SkBlitter* customBlitter, bool doFill) const { 99201a2ff8a325e17221b139968e337413df0c2e60creed // Do a conservative quick-reject test, since a looper or other modifier may have moved us 99301a2ff8a325e17221b139968e337413df0c2e60creed // out of range. 99401a2ff8a325e17221b139968e337413df0c2e60creed if (!devPath.isInverseFillType()) { 99501a2ff8a325e17221b139968e337413df0c2e60creed // If we're a H or V line, our bounds will be empty. So we bloat here just so we don't 99601a2ff8a325e17221b139968e337413df0c2e60creed // appear empty to the intersects call. This also gives us slop in case we're antialiasing 99701a2ff8a325e17221b139968e337413df0c2e60creed SkRect pathBounds = devPath.getBounds().makeOutset(1, 1); 99801a2ff8a325e17221b139968e337413df0c2e60creed 99901a2ff8a325e17221b139968e337413df0c2e60creed if (paint.getMaskFilter()) { 100001a2ff8a325e17221b139968e337413df0c2e60creed paint.getMaskFilter()->computeFastBounds(pathBounds, &pathBounds); 100101a2ff8a325e17221b139968e337413df0c2e60creed 100201a2ff8a325e17221b139968e337413df0c2e60creed // Need to outset the path to work-around a bug in blurmaskfilter. When that is fixed 100301a2ff8a325e17221b139968e337413df0c2e60creed // we can remove this hack. See skbug.com/5542 100401a2ff8a325e17221b139968e337413df0c2e60creed pathBounds.outset(7, 7); 100501a2ff8a325e17221b139968e337413df0c2e60creed } 100601a2ff8a325e17221b139968e337413df0c2e60creed 100701a2ff8a325e17221b139968e337413df0c2e60creed // Now compare against the clip's bounds 100801a2ff8a325e17221b139968e337413df0c2e60creed if (!SkRect::Make(fRC->getBounds()).intersects(pathBounds)) { 100901a2ff8a325e17221b139968e337413df0c2e60creed return; 101001a2ff8a325e17221b139968e337413df0c2e60creed } 101101a2ff8a325e17221b139968e337413df0c2e60creed } 101201a2ff8a325e17221b139968e337413df0c2e60creed 101382595b6fa4733e1525f357bdcac22db058790550reed SkBlitter* blitter = nullptr; 101482595b6fa4733e1525f357bdcac22db058790550reed SkAutoBlitterChoose blitterStorage; 101582595b6fa4733e1525f357bdcac22db058790550reed if (nullptr == customBlitter) { 101682595b6fa4733e1525f357bdcac22db058790550reed blitterStorage.choose(fDst, *fMatrix, paint, drawCoverage); 101782595b6fa4733e1525f357bdcac22db058790550reed blitter = blitterStorage.get(); 101882595b6fa4733e1525f357bdcac22db058790550reed } else { 101982595b6fa4733e1525f357bdcac22db058790550reed blitter = customBlitter; 102082595b6fa4733e1525f357bdcac22db058790550reed } 102182595b6fa4733e1525f357bdcac22db058790550reed 102282595b6fa4733e1525f357bdcac22db058790550reed if (paint.getMaskFilter()) { 102382595b6fa4733e1525f357bdcac22db058790550reed SkStrokeRec::InitStyle style = doFill ? SkStrokeRec::kFill_InitStyle 102482595b6fa4733e1525f357bdcac22db058790550reed : SkStrokeRec::kHairline_InitStyle; 102582595b6fa4733e1525f357bdcac22db058790550reed if (paint.getMaskFilter()->filterPath(devPath, *fMatrix, *fRC, blitter, style)) { 102682595b6fa4733e1525f357bdcac22db058790550reed return; // filterPath() called the blitter, so we're done 102782595b6fa4733e1525f357bdcac22db058790550reed } 102882595b6fa4733e1525f357bdcac22db058790550reed } 102982595b6fa4733e1525f357bdcac22db058790550reed 103082595b6fa4733e1525f357bdcac22db058790550reed void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*); 103182595b6fa4733e1525f357bdcac22db058790550reed if (doFill) { 103282595b6fa4733e1525f357bdcac22db058790550reed if (paint.isAntiAlias()) { 103382595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiFillPath; 103482595b6fa4733e1525f357bdcac22db058790550reed } else { 103582595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::FillPath; 103682595b6fa4733e1525f357bdcac22db058790550reed } 103782595b6fa4733e1525f357bdcac22db058790550reed } else { // hairline 103882595b6fa4733e1525f357bdcac22db058790550reed if (paint.isAntiAlias()) { 103982595b6fa4733e1525f357bdcac22db058790550reed switch (paint.getStrokeCap()) { 104082595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kButt_Cap: 104182595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiHairPath; 104282595b6fa4733e1525f357bdcac22db058790550reed break; 104382595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kSquare_Cap: 104482595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiHairSquarePath; 104582595b6fa4733e1525f357bdcac22db058790550reed break; 104682595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kRound_Cap: 104782595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::AntiHairRoundPath; 104882595b6fa4733e1525f357bdcac22db058790550reed break; 104982595b6fa4733e1525f357bdcac22db058790550reed default: 105082595b6fa4733e1525f357bdcac22db058790550reed proc SK_INIT_TO_AVOID_WARNING; 105182595b6fa4733e1525f357bdcac22db058790550reed SkDEBUGFAIL("unknown paint cap type"); 105282595b6fa4733e1525f357bdcac22db058790550reed } 105382595b6fa4733e1525f357bdcac22db058790550reed } else { 105482595b6fa4733e1525f357bdcac22db058790550reed switch (paint.getStrokeCap()) { 105582595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kButt_Cap: 105682595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::HairPath; 105782595b6fa4733e1525f357bdcac22db058790550reed break; 105882595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kSquare_Cap: 105982595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::HairSquarePath; 106082595b6fa4733e1525f357bdcac22db058790550reed break; 106182595b6fa4733e1525f357bdcac22db058790550reed case SkPaint::kRound_Cap: 106282595b6fa4733e1525f357bdcac22db058790550reed proc = SkScan::HairRoundPath; 106382595b6fa4733e1525f357bdcac22db058790550reed break; 106482595b6fa4733e1525f357bdcac22db058790550reed default: 106582595b6fa4733e1525f357bdcac22db058790550reed proc SK_INIT_TO_AVOID_WARNING; 106682595b6fa4733e1525f357bdcac22db058790550reed SkDEBUGFAIL("unknown paint cap type"); 106782595b6fa4733e1525f357bdcac22db058790550reed } 106882595b6fa4733e1525f357bdcac22db058790550reed } 106982595b6fa4733e1525f357bdcac22db058790550reed } 107082595b6fa4733e1525f357bdcac22db058790550reed proc(devPath, *fRC, blitter); 107182595b6fa4733e1525f357bdcac22db058790550reed} 107282595b6fa4733e1525f357bdcac22db058790550reed 107332e5d97ccf60f859db063ebd6e903c362e625767reed@google.comvoid SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, 1074126f7f5244502c0cbf1e5fec1d2ad7a0f2eb6c34reed@google.com const SkMatrix* prePathMatrix, bool pathIsMutable, 107553f0959fc024c56dc55fe6bf86380127b59abec9krajcevski bool drawCoverage, SkBlitter* customBlitter) const { 1076f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1079045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty()) { 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* pathPtr = (SkPath*)&origSrcPath; 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool doFill = true; 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmpPath; 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmpMatrix; 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 1088b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth tmpPath.setIsVolatile(true); 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prePathMatrix) { 109132e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style || 109232e5d97ccf60f859db063ebd6e903c362e625767reed@google.com origPaint.getRasterizer()) { 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* result = pathPtr; 1094a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!pathIsMutable) { 10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = &tmpPath; 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathIsMutable = true; 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*prePathMatrix, result); 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = result; 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 110292362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org tmpMatrix.setConcat(*matrix, *prePathMatrix); 11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix = &tmpMatrix; 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // at this point we're done with prePathMatrix 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 1108a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11095dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1110a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1111ecadf99c8450646dfd9c2754f3e845245beab8b6reed@google.com { 1112dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com SkScalar coverage; 1113dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { 1114dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com if (SK_Scalar1 == coverage) { 11155dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com paint.writable()->setStrokeWidth(0); 1116374772bd61951f01bf84fe17bf53d8867681c9aereed } else if (SkBlendMode_SupportsCoverageAsAlpha(origPaint.getBlendMode())) { 1117dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com U8CPU newAlpha; 1118dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#if 0 1119dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = SkToU8(SkScalarRoundToInt(coverage * 1120dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com origPaint.getAlpha())); 1121dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#else 1122dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // this is the old technique, which we preserve for now so 1123dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // we don't change previous results (testing) 1124dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com // the new way seems fine, its just (a tiny bit) different 1125a99b6ceff92183b424634f2e7276b9ea1d59e69dMike Reed int scale = (int)(coverage * 256); 1126dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com newAlpha = origPaint.getAlpha() * scale >> 8; 1127dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com#endif 11285dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com SkPaint* writablePaint = paint.writable(); 11295dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setStrokeWidth(0); 11305dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com writablePaint->setAlpha(newAlpha); 1131dd1be60702b3622f49d97651e31d13eaf2175cf8bsalomon@google.com } 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1134a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 113532e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { 11364bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com SkRect cullRect; 113796fcdcc219d2a0d3579719b84b28bede76efba64halcanary const SkRect* cullRectPtr = nullptr; 11384bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com if (this->computeConservativeLocalClipBounds(&cullRect)) { 11394bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com cullRectPtr = &cullRect; 11404bbdeac58cc928dc66296bde3bd06e78070d96b7reed@google.com } 114105d9044de4f1c6e791df66a425638752daac4c6breed doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr, 11421a7eb266644d2e1b0968dbca606ca0a91903419dcaryclark ComputeResScaleForStroking(*fMatrix)); 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = &tmpPath; 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1145a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 114632e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()) { 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 114832e5d97ccf60f859db063ebd6e903c362e625767reed@google.com if (paint->getRasterizer()->rasterize(*pathPtr, *matrix, 1149045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com &fRC->getBounds(), paint->getMaskFilter(), &mask, 11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 115132e5d97ccf60f859db063ebd6e903c362e625767reed@google.com this->drawDevMask(mask, *paint); 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(mask.fImage); 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // avoid possibly allocating a new path in transform if we can 11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform the path into device space 11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*matrix, devPathPtr); 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 116382595b6fa4733e1525f357bdcac22db058790550reed this->drawDevPath(*devPathPtr, *paint, drawCoverage, customBlitter, doFill); 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 116682595b6fa4733e1525f357bdcac22db058790550reedvoid SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, const SkPaint& paint) const { 1167900ecf2f1579d42c9d2959831787af0346320f86reed@google.com SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType); 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1169c7e211acd0c9201688de7ff0c9a2271c67440adffmalita if (SkTreatAsSprite(*fMatrix, bitmap.dimensions(), paint)) { 1170e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(fMatrix->getTranslateX()); 1171e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(fMatrix->getTranslateY()); 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11734edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed SkPixmap pmap; 11744edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed if (!bitmap.peekPixels(&pmap)) { 1175a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com return; 1176a641f3f18e5319773989812a888f3fad49e4f2adreed@google.com } 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 117892fc2ae58331662ec411a048686cb4801e0a909areed mask.fBounds.set(ix, iy, ix + pmap.width(), iy + pmap.height()); 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 118092fc2ae58331662ec411a048686cb4801e0a909areed mask.fRowBytes = SkToU32(pmap.rowBytes()); 118192fc2ae58331662ec411a048686cb4801e0a909areed // fImage is typed as writable, but in this case it is used read-only 118292fc2ae58331662ec411a048686cb4801e0a909areed mask.fImage = (uint8_t*)pmap.addr8(0, 0); 1183a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // need to xform the bitmap first 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 1188a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapRect(&r); 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&mask.fBounds); 1193a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // set the mask's bounds to the transformed bitmap-bounds, 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // clipped to the actual device 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devBounds; 119841e010cb901c0da9066c4df562030808c9ccd7f8reed devBounds.set(0, 0, fDst.width(), fDst.height()); 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need intersect(l, t, r, b) on irect 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!mask.fBounds.intersect(devBounds)) { 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1204543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = SkAlign4(mask.fBounds.width()); 1207543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask.computeImageSize(); 1208543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 1209543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // the mask is too big to allocated, draw nothing 1210543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return; 1211543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // allocate (and clear) our temp buffer to hold the transformed bitmap 1214565901db954c231840750ea955ed31b820b9ade8scroggo SkAutoTMalloc<uint8_t> storage(size); 1215565901db954c231840750ea955ed31b820b9ade8scroggo mask.fImage = storage.get(); 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask.fImage, 0, size); 1217a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now draw our bitmap(src) into mask(dst), transformed by the matrix 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap device; 1221a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()), 1222a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org mask.fImage, mask.fRowBytes); 1223a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas c(device); 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need the unclipped top/left for the translate 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.translate(-SkIntToScalar(mask.fBounds.fLeft), 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.concat(*fMatrix); 12293469c76c40790b409621fd7eff34f56240718549reed@android.com 12303469c76c40790b409621fd7eff34f56240718549reed@android.com // We can't call drawBitmap, or we'll infinitely recurse. Instead 1231fb12c3e6ba84f95dc15fbaddc239dede0ba1d60ereed@android.com // we manually build a shader and draw that into our new mask 12323469c76c40790b409621fd7eff34f56240718549reed@android.com SkPaint tmpPaint; 12333469c76c40790b409621fd7eff34f56240718549reed@android.com tmpPaint.setFlags(paint.getFlags()); 123466a96d07d5583cc018cb70127bd5483799b69d0ebrianosman tmpPaint.setFilterQuality(paint.getFilterQuality()); 12354bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby SkPaint paintWithShader = make_paint_with_image(tmpPaint, bitmap); 12363469c76c40790b409621fd7eff34f56240718549reed@android.com SkRect rr; 12373469c76c40790b409621fd7eff34f56240718549reed@android.com rr.set(0, 0, SkIntToScalar(bitmap.width()), 12383469c76c40790b409621fd7eff34f56240718549reed@android.com SkIntToScalar(bitmap.height())); 12394bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby c.drawRect(rr, paintWithShader); 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1245045e62d715f5ee9b03deb5af3c750f8318096179reed@google.comstatic bool clipped_out(const SkMatrix& m, const SkRasterClip& c, 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& srcR) { 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect dstR; 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.mapRect(&dstR, srcR); 1249b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed return c.quickReject(dstR.roundOut()); 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 1259c240e719b2bebd3711ade4e6fe056921aa7b0521reedstatic bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, const SkPixmap& pmap) { 1260c240e719b2bebd3711ade4e6fe056921aa7b0521reed return clip.isBW() || clip.quickContains(x, y, x + pmap.width(), y + pmap.height()); 1261045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com} 1262045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 12640393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkRect* dstBounds, const SkPaint& origPaint) const { 1265f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1268045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1270900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1273a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1274f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1275f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita if (origPaint.getStyle() != SkPaint::kFill_Style) { 1276f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita paint.writable()->setStyle(SkPaint::kFill_Style); 1277f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita } 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 1286c7e211acd0c9201688de7ff0c9a2271c67440adffmalita if (bitmap.colorType() != kAlpha_8_SkColorType 1287f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita && SkTreatAsSprite(matrix, bitmap.dimensions(), *paint)) { 1288f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 1289f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // It is safe to call lock pixels now, since we know the matrix is 1290f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // (more or less) identity. 1291f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com // 12924edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed SkPixmap pmap; 12934edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed if (!bitmap.peekPixels(&pmap)) { 1294f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com return; 1295f7ef56d9104fc651769760df9d5f861ef36de658reed@google.com } 1296e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int ix = SkScalarRoundToInt(matrix.getTranslateX()); 1297e1ca705cac4b946993f6cbf798e2a0ba27e739f3reed@google.com int iy = SkScalarRoundToInt(matrix.getTranslateY()); 1298c240e719b2bebd3711ade4e6fe056921aa7b0521reed if (clipHandlesSprite(*fRC, ix, iy, pmap)) { 129957bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby char storage[kSkBlitterContextSize]; 130057bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby SkArenaAlloc allocator{storage}; 1301a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 1302f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, *paint, pmap, ix, iy, &allocator); 1303045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (blitter) { 1304c240e719b2bebd3711ade4e6fe056921aa7b0521reed SkScan::FillIRect(SkIRect::MakeXYWH(ix, iy, pmap.width(), pmap.height()), 1305c240e719b2bebd3711ade4e6fe056921aa7b0521reed *fRC, blitter); 1306045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com return; 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1308c240e719b2bebd3711ade4e6fe056921aa7b0521reed // if !blitter, then we fall-through to the slower case 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1311a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now make a temp draw on the stack, and use it 13138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 1316a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 131770ac8a9d091d385bf5244125159c4d8509a0c470Matt Sarett if (bitmap.colorType() == kAlpha_8_SkColorType && !paint->getColorFilter()) { 1318f85d2a4fa1b71e6ee28518431e2a34df5683bc81fmalita draw.drawBitmapAsMask(bitmap, *paint); 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 13204bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby SkPaint paintWithShader = make_paint_with_image(*paint, bitmap); 13210393912de72bc3d8b3640c122c53470dd0da1e6dreed const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height()); 13220393912de72bc3d8b3640c122c53470dd0da1e6dreed if (dstBounds) { 13230393912de72bc3d8b3640c122c53470dd0da1e6dreed this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds); 13240393912de72bc3d8b3640c122c53470dd0da1e6dreed } else { 13250393912de72bc3d8b3640c122c53470dd0da1e6dreed draw.drawRect(srcBounds, paintWithShader); 13260393912de72bc3d8b3640c122c53470dd0da1e6dreed } 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1330c240e719b2bebd3711ade4e6fe056921aa7b0521reedvoid SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& origPaint) const { 1331f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 1332a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 1334045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->isEmpty() || 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 1336900ecf2f1579d42c9d2959831787af0346320f86reed@google.com bitmap.colorType() == kUnknown_SkColorType) { 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1340c240e719b2bebd3711ade4e6fe056921aa7b0521reed const SkIRect bounds = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1342045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (fRC->quickReject(bounds)) { 13438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // nothing to draw 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 134640c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com SkPaint paint(origPaint); 134740c2ba27b6e5c6a4b6c073264f8c0a7c86355abereed@google.com paint.setStyle(SkPaint::kFill_Style); 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13494edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed SkPixmap pmap; 13504edb5d219eb99aa1e8fbe5e37260d3b34314e54bMike Reed if (!bitmap.peekPixels(&pmap)) { 1351c240e719b2bebd3711ade4e6fe056921aa7b0521reed return; 1352c240e719b2bebd3711ade4e6fe056921aa7b0521reed } 1353c240e719b2bebd3711ade4e6fe056921aa7b0521reed 135496fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, pmap)) { 1355a5572e5bb2a2bbeeb59de0741c2527869d365a0ccommit-bot@chromium.org // blitter will be owned by the allocator. 135657bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby char storage[kSkBlitterContextSize]; 135757bfa0209e3379385b7ef6217cafb22ca83836c8Herb Derby SkArenaAlloc allocator{storage}; 135841e010cb901c0da9066c4df562030808c9ccd7f8reed SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, paint, pmap, x, y, &allocator); 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (blitter) { 1360045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkScan::FillIRect(bounds, *fRC, blitter); 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get a scalar version of our rect 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(bounds); 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13719c9005a347e9996f357bd79591bd34f74f8bbc66commit-bot@chromium.org // create shader with offset 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(r.fLeft, r.fTop); 13734bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby SkPaint paintWithShader = make_paint_with_image(paint, bitmap, &matrix); 13748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 13758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 13768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 13778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call ourself with a rect 1378a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com // is this OK if paint has a rasterizer? 13794bf560a056d7ba5b3051ebc87e687d4997928ff6Herb Derby draw.drawRect(r, paintWithShader); 13808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13847120b2d577d3aab1f51c5af1530a68c57ca51696Mike Reed#include "SkPaintPriv.h" 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h" 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h" 1387e69137620ab0b5b40d230318c8e11b822f63cb9dreed@google.com#include "SkTextToPathIter.h" 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13908128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.orgbool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) { 13918128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // hairline glyphs are fast enough so we don't need to cache them 13928128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 13938128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 13948128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 13958128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 13968128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org // we don't cache perspective 13978128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org if (ctm.hasPerspective()) { 13988128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org return true; 13998128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org } 14008128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 14018128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org SkMatrix textM; 14027120b2d577d3aab1f51c5af1530a68c57ca51696Mike Reed SkPaintPriv::MakeTextMatrix(&textM, paint); 14037120b2d577d3aab1f51c5af1530a68c57ca51696Mike Reed return SkPaint::TooBigToUseCache(ctm, textM); 14048128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org} 14058128d8c119382279918b90ad8d80ccb3aaebb8a0commit-bot@chromium.org 140699330ba6227137866a0dbd63478d36f335203ebdMike Reedvoid SkDraw::drawText_asPaths(const char text[], size_t byteLength, SkScalar x, SkScalar y, 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 1408f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1410166e653f67f3fffc3846184a25ce45ab083f07a2djsollen@google.com SkTextToPathIter iter(text, byteLength, paint, true); 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setScale(iter.getPathScale(), iter.getPathScale()); 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(x, y); 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath* iterPath; 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar xpos, prevXPos = 0; 14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14197b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com while (iter.next(&iterPath, &xpos)) { 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(xpos - prevXPos, 0); 14217b4531f64cbd85d32a77ceab1bdec8335c5a7864reed@google.com if (iterPath) { 1422a1361364e64138adda3dc5f71d50d7503838bb6dMike Reed this->drawPath(*iterPath, iter.getPaint(), &matrix, false); 1423f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com } 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevXPos = xpos; 14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// disable warning : local variable used without having been initialized 1429d7dc76f7e99309cbd09a5420c22e55b951067debbungeman#if defined _WIN32 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 ) 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1434f553e4e09cd2baf15fc041daab8a08bd46e352f0herb//////////////////////////////////////////////////////////////////////////////////////////////////// 14352e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1436d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbclass DrawOneGlyph { 1437d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbpublic: 1438d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter) 1439d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb : fUseRegionToDraw(UsingRegionToDraw(draw.fRC)) 1440d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fGlyphCache(cache) 1441d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fBlitter(blitter) 1442d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr) 1443d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fDraw(draw) 1444d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fPaint(paint) 1445d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb , fClipBounds(PickClipBounds(draw)) { } 1446d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 1447d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) { 1448d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb position += rounding; 1449d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // Prevent glyphs from being drawn outside of or straddling the edge of device space. 1450875e13ca0990e32da9db639743a913efe77f7e89mtklein // Comparisons written a little weirdly so that NaN coordinates are treated safely. 1451875e13ca0990e32da9db639743a913efe77f7e89mtklein auto gt = [](float a, int b) { return !(a <= (float)b); }; 1452875e13ca0990e32da9db639743a913efe77f7e89mtklein auto lt = [](float a, int b) { return !(a >= (float)b); }; 1453875e13ca0990e32da9db639743a913efe77f7e89mtklein if (gt(position.fX, INT_MAX - (INT16_MAX + UINT16_MAX)) || 1454875e13ca0990e32da9db639743a913efe77f7e89mtklein lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) || 1455875e13ca0990e32da9db639743a913efe77f7e89mtklein gt(position.fY, INT_MAX - (INT16_MAX + UINT16_MAX)) || 1456875e13ca0990e32da9db639743a913efe77f7e89mtklein lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))) { 1457d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return; 1458d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1459d095f2bf06ca810844233bea9fb06de585643b32bungeman 146077a9cc1dead147fc547895d3725d9ee2150cda73benjaminwagner int left = SkScalarFloorToInt(position.fX); 146177a9cc1dead147fc547895d3725d9ee2150cda73benjaminwagner int top = SkScalarFloorToInt(position.fY); 1462d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1464d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb left += glyph.fLeft; 1465d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb top += glyph.fTop; 14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1467d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb int right = left + glyph.fWidth; 1468d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb int bottom = top + glyph.fHeight; 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1470d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkMask mask; 1471d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask.fBounds.set(left, top, right, bottom); 1472875e13ca0990e32da9db639743a913efe77f7e89mtklein SkASSERT(!mask.fBounds.isEmpty()); 147383a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 1474d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (fUseRegionToDraw) { 1475d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkRegion::Cliperator clipper(*fClip, mask.fBounds); 147683a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 1477d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (!clipper.done() && this->getImageData(glyph, &mask)) { 1478d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkIRect& cr = clipper.rect(); 1479d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb do { 1480d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb this->blitMask(mask, cr); 1481d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb clipper.next(); 1482d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } while (!clipper.done()); 1483d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1484d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } else { 1485d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkIRect storage; 1486d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkIRect* bounds = &mask.fBounds; 1487d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 1488d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // this extra test is worth it, assuming that most of the time it succeeds 1489d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb // since we can avoid writing to storage 1490d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) { 1491d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds)) 1492d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return; 1493d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb bounds = &storage; 1494d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 149583a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com 1496d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (this->getImageData(glyph, &mask)) { 1497d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb this->blitMask(mask, *bounds); 1498d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1499cd7f03597475ea423aa819bdae03996b26874dd5herb } 150083a444602ec580a0040713eed588c245b4ae0ee9tomhudson@google.com } 15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1502d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herbprivate: 1503d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb static bool UsingRegionToDraw(const SkRasterClip* rClip) { 1504d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return rClip->isBW() && !rClip->isRect(); 1505d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 15062e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1507d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb static SkIRect PickClipBounds(const SkDraw& draw) { 1508d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkRasterClip& rasterClip = *draw.fRC; 15092e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1510d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (rasterClip.isBW()) { 1511d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return rasterClip.bwRgn().getBounds(); 1512d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } else { 1513d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return rasterClip.aaRgn().getBounds(); 1514001e74426672e00f3f2783ccf728031662d4a358herb } 15159447103029273a9f8dd7f5997e8af7a1e3ee7488bungeman@google.com } 1516001e74426672e00f3f2783ccf728031662d4a358herb 1517d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb bool getImageData(const SkGlyph& glyph, SkMask* mask) { 1518d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph)); 1519d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (nullptr == bits) { 1520d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return false; // can't rasterize glyph 1521d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb } 1522d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask->fImage = bits; 1523d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask->fRowBytes = glyph.rowBytes(); 1524d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1525d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb return true; 15262e8fec79658baef06f4a9fca5e91a4e116b47b3dherb } 15272e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1528d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb void blitMask(const SkMask& mask, const SkIRect& clip) const { 1529d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb if (SkMask::kARGB32_Format == mask.fFormat) { 1530d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkBitmap bm; 1531d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb bm.installPixels( 1532d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()), 1533d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb (SkPMColor*)mask.fImage, mask.fRowBytes); 1534d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 1535d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint); 1536045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } else { 1537d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb fBlitter->blitMask(mask, clip); 1538045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com } 15398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15405bdfb331ac650cf464baa96a49e2473ee10a515creed@google.com 1541d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const bool fUseRegionToDraw; 1542d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkGlyphCache * const fGlyphCache; 1543d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkBlitter * const fBlitter; 1544d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkRegion* const fClip; 1545d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkDraw& fDraw; 1546d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkPaint& fPaint; 1547d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb const SkIRect fClipBounds; 1548d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb}; 15492e8fec79658baef06f4a9fca5e91a4e116b47b3dherb 1550d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb//////////////////////////////////////////////////////////////////////////////////////////////////// 15518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1552a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosmanuint32_t SkDraw::scalerContextFlags() const { 1553a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman uint32_t flags = SkPaint::kBoostContrast_ScalerContextFlag; 155499330ba6227137866a0dbd63478d36f335203ebdMike Reed if (!fDst.colorSpace()) { 1555a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman flags |= SkPaint::kFakeGamma_ScalerContextFlag; 1556a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman } 1557a1e8f8d8f1a0b7141136d7d49df1cc2fec0528dfbrianosman return flags; 1558f6d1e605317917146362706ed460b5ed6624fcc5bungeman} 1559f6d1e605317917146362706ed460b5ed6624fcc5bungeman 156099330ba6227137866a0dbd63478d36f335203ebdMike Reedvoid SkDraw::drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y, 156199330ba6227137866a0dbd63478d36f335203ebdMike Reed const SkPaint& paint, const SkSurfaceProps* props) const { 156296fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(byteLength == 0 || text != nullptr); 15638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1564f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 15658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 156796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 15688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 157136d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // SkScalarRec doesn't currently have a way of representing hairline stroke and 157236d6edac9f3e63d9a5f499d0076550d08b80eacabsalomon@google.com // will fill if its frame-width is 0. 1573ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 15748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawText_asPaths(text, byteLength, x, y, paint); 15758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 157899330ba6227137866a0dbd63478d36f335203ebdMike Reed SkAutoGlyphCache cache(paint, props, this->scalerContextFlags(), fMatrix); 157911a7f7f5998cb3d5605741e37a7f12f7477d480cherb 158011a7f7f5998cb3d5605741e37a7f12f7477d480cherb // The Blitter Choose needs to be live while using the blitter below. 158111a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 158211a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1583f6d1e605317917146362706ed460b5ed6624fcc5bungeman DrawOneGlyph drawOneGlyph(*this, paint, cache.get(), wrapper.getBlitter()); 15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1585e59124ed1a62f1fec79679c38cabed622a756f75herb SkFindAndPlaceGlyph::ProcessText( 15864c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb paint.getTextEncoding(), text, byteLength, 1587f6d1e605317917146362706ed460b5ed6624fcc5bungeman {x, y}, *fMatrix, paint.getTextAlign(), cache.get(), drawOneGlyph); 15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 15918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 159299330ba6227137866a0dbd63478d36f335203ebdMike Reedvoid SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, const SkScalar pos[], 159399330ba6227137866a0dbd63478d36f335203ebdMike Reed int scalarsPerPosition, const SkPoint& offset, 159499330ba6227137866a0dbd63478d36f335203ebdMike Reed const SkPaint& origPaint, const SkSurfaceProps* props) const { 1595ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com // setup our std paint, in hopes of getting hits in the cache 1596ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkPaint paint(origPaint); 1597ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com SkScalar matrixScale = paint.setupForAsPaths(); 1598ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 15995a64902ee92847f53dfc5b211da19d074179be64reed@google.com SkMatrix matrix; 16005a64902ee92847f53dfc5b211da19d074179be64reed@google.com matrix.setScale(matrixScale, matrixScale); 16018f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 16024e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 16034e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setStyle(SkPaint::kFill_Style); 160496fcdcc219d2a0d3579719b84b28bede76efba64halcanary paint.setPathEffect(nullptr); 16054e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org 1606e34f17d23699abfc672289f51319b37294b3c257robertphillips SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(), 1607e34f17d23699abfc672289f51319b37294b3c257robertphillips paint.isDevKernText(), 1608e34f17d23699abfc672289f51319b37294b3c257robertphillips true); 160999330ba6227137866a0dbd63478d36f335203ebdMike Reed SkAutoGlyphCache cache(paint, props, this->scalerContextFlags(), nullptr); 1610ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 1611ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const char* stop = text + byteLength; 161279738cc7bf12d212bef4ff80591d1bf6f383663dbungeman SkTextAlignProc alignProc(paint.getTextAlign()); 161305c4a4322e7d4f3417b7df33825bab8603d52051fmalita SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 16148f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 16154e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org // Now restore the original settings, so we "draw" with whatever style/stroking. 16164e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org paint.setStyle(origPaint.getStyle()); 1617693fdbd6b81a860657612e7604430dd55d6e721bMike Reed paint.setPathEffect(origPaint.refPathEffect()); 16184e82cdb90abb34a2ab60fcdb26e7bfc17e8e4da9commit-bot@chromium.org 1619ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com while (text < stop) { 1620d936f63c35fb7dfb2b6c20802206adbfc3cc48d0benjaminwagner const SkGlyph& glyph = glyphCacheProc(cache.get(), &text); 1621ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (glyph.fWidth) { 1622ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com const SkPath* path = cache->findPath(glyph); 1623ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (path) { 1624cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen SkPoint tmsLoc; 1625cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen tmsProc(pos, &tmsLoc); 1626cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com SkPoint loc; 1627cb9a2c8934f009b6ee1ca73d662ac18b285085d9kkinnunen alignProc(tmsLoc, glyph, &loc); 16288f6ef4010f6835c5ce9ede180e50a6a58512a81eskia.committer@gmail.com 1629cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransX] = loc.fX; 1630cfd90d6073baef9841dcb6e7b25d244f06ceeeaabungeman@google.com matrix[SkMatrix::kMTransY] = loc.fY; 163199330ba6227137866a0dbd63478d36f335203ebdMike Reed this->drawPath(*path, paint, &matrix, false); 1632ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1633ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1634ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com pos += scalarsPerPosition; 1635ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com } 1636ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com} 1637ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com 163899330ba6227137866a0dbd63478d36f335203ebdMike Reedvoid SkDraw::drawPosText(const char text[], size_t byteLength, const SkScalar pos[], 163999330ba6227137866a0dbd63478d36f335203ebdMike Reed int scalarsPerPosition, const SkPoint& offset, const SkPaint& paint, 164099330ba6227137866a0dbd63478d36f335203ebdMike Reed const SkSurfaceProps* props) const { 164196fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(byteLength == 0 || text != nullptr); 16428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 16438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1644f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.com SkDEBUGCODE(this->validate();) 16458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 164796fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 16488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1651ed43dffbf140cebc0575bed7b4dff1b32430ad21reed@google.com if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 165299330ba6227137866a0dbd63478d36f335203ebdMike Reed this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, offset, paint, props); 16538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 165699330ba6227137866a0dbd63478d36f335203ebdMike Reed SkAutoGlyphCache cache(paint, props, this->scalerContextFlags(), fMatrix); 1657d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb 16589be5ff6f9871ef22740094e7c25dd67329a73d20herb // The Blitter Choose needs to be live while using the blitter below. 165911a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 166011a7f7f5998cb3d5605741e37a7f12f7477d480cherb SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1661f6d1e605317917146362706ed460b5ed6624fcc5bungeman DrawOneGlyph drawOneGlyph(*this, paint, cache.get(), wrapper.getBlitter()); 1662d4c24f67496ff2e5e83bc7ce7945cbb85484bfa6herb SkPaint::Align textAlignment = paint.getTextAlign(); 16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16649be5ff6f9871ef22740094e7c25dd67329a73d20herb SkFindAndPlaceGlyph::ProcessPosText( 16654c11b3f8a2d9919a21110dbdd29e67e5cbaa41fbherb paint.getTextEncoding(), text, byteLength, 1666f6d1e605317917146362706ed460b5ed6624fcc5bungeman offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache.get(), drawOneGlyph); 16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1669d7dc76f7e99309cbd09a5420c22e55b951067debbungeman#if defined _WIN32 16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 16728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 16748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16755dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreedstatic SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) { 16768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool texture_to_matrix(const VertState& state, const SkPoint verts[], 16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint texs[], SkMatrix* matrix) { 16818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src[3], dst[3]; 1682a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[0] = texs[state.f0]; 16848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[1] = texs[state.f1]; 16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[2] = texs[state.f2]; 16868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[0] = verts[state.f0]; 16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[1] = verts[state.f1]; 16888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[2] = verts[state.f2]; 16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return matrix->setPolyToPoly(src, dst, 3); 16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkTriColorShader : public SkShader { 16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 169488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic SkTriColorShader(); 16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 169687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org class TriColorShaderContext : public SkShader::Context { 169787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org public: 1698e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&); 1699d3b65972aad96453ff4510caa3e25a2b847c6d1eBrian Salomon ~TriColorShaderContext() override; 170036352bf5e38f45a70ee4f4fc132a38048d38206dmtklein void shadeSpan(int x, int y, SkPMColor dstC[], int count) override; 17014c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed void shadeSpan4f(int x, int y, SkPM4f dstC[], int count) override; 170287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 170387fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org private: 170488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 170588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 170687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkMatrix fDstToUnit; 170787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org SkPMColor fColors[3]; 170888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic bool fSetup; 170987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 17104c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed SkPM4f fC0, fC10, fC20, fDC; 171187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org typedef SkShader::Context INHERITED; 171287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org }; 1713a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 171488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic struct TriColorShaderData { 171588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic const SkPoint* pts; 171688cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic const SkColor* colors; 171788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic const VertState *state; 171888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic }; 171988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 17200f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org SK_TO_STRING_OVERRIDE() 17217e44bb191633e225fd0455c267dbf67f9ee8633emtklein 17227e44bb191633e225fd0455c267dbf67f9ee8633emtklein // For serialization. This will never be called. 172396fcdcc219d2a0d3579719b84b28bede76efba64halcanary Factory getFactory() const override { sk_throw(); return nullptr; } 1724ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com 172588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // Supply setup data to context from drawing setup 172688cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic void bindSetupData(TriColorShaderData* setupData) { fSetupData = setupData; } 172788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 172888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // Take the setup data from context when needed. 172988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData* takeSetupData() { 173088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData *data = fSetupData; 173188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic fSetupData = NULL; 173288cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic return data; 173388cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic } 173488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 173683e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override { 173783e939bcb79790f5ae3b28c398fbcf034675a6e5Herb Derby return alloc->make<TriColorShaderContext>(*this, rec); 1738ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org } 1739ce56d965069c1649afe14319cb239e6ad670682acommit-bot@chromium.org 17408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 174188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData *fSetupData; 174288cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShader INHERITED; 17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 17458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 174687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgbool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], 174787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org int index0, int index1, int index2) { 1748a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[0] = SkPreMultiplyColor(colors[index0]); 17508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[1] = SkPreMultiplyColor(colors[index1]); 17518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[2] = SkPreMultiplyColor(colors[index2]); 1752a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 17538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m, im; 17548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.reset(); 17558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(0, pts[index1].fX - pts[index0].fX); 17568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(1, pts[index2].fX - pts[index0].fX); 17578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(2, pts[index0].fX); 17588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(3, pts[index1].fY - pts[index0].fY); 17598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(4, pts[index2].fY - pts[index0].fY); 17608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(5, pts[index0].fY); 17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!m.invert(&im)) { 17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 176480116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix 176580116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org // as our interators are intrinsically tied to the vertices, and nothing else. 176680116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org SkMatrix ctmInv; 176780116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org if (!this->getCTM().invert(&ctmInv)) { 176880116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org return false; 176980116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org } 177088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // TODO replace INV(m) * INV(ctm) with INV(ctm * m) 177180116dcf1e1baf9817ae42d0aca51f7eabaa2880commit-bot@chromium.org fDstToUnit.setConcat(im, ctmInv); 17724c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 17734c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed fC0 = SkPM4f::FromPMColor(fColors[0]); 17744c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 17754c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed Sk4f alpha(this->getPaintAlpha() * (1.0f / 255)), 17764c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed c0 = fC0.to4f() * alpha, 17774c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed c1 = SkPM4f::FromPMColor(fColors[1]).to4f() * alpha, 17784c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed c2 = SkPM4f::FromPMColor(fColors[2]).to4f() * alpha, 17794c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed dx(fDstToUnit.getScaleX()), 17804c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed dy(fDstToUnit.getSkewY()); 17814c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 17824c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed Sk4f c10 = c1 - c0, 17834c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed c20 = c2 - c0; 17844c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 17854c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed fDC = SkPM4f::From4f(dx * c10 + dy * c20); 17864c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed fC10 = SkPM4f::From4f(c10); 17874c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed fC20 = SkPM4f::From4f(c20); 178892362383a4de7b0d819c88fa8b74242bb2507602commit-bot@chromium.org return true; 17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 1792689411a87ca7d19abe04b5c9baff26bd96b2123ereed@android.com#include "SkComposeShader.h" 17938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int ScalarTo256(SkScalar v) { 179543437c2f1928073a30c2bab6d32df854658235ecbenjaminwagner return static_cast<int>(SkScalarPin(v, 0, 1) * 256 + 0.5); 17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 179888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovicSkTriColorShader::SkTriColorShader() 179988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic : INHERITED(NULL) 180088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic , fSetupData(NULL) {} 180187fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 1802e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader, 1803e901b6de3ef8dea842008a08fc81e92fb1478d61commit-bot@chromium.org const ContextRec& rec) 180488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic : INHERITED(shader, rec) 180588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic , fSetup(false) {} 180687fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 180787fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgSkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} 180887fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org 180987fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.orgvoid SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 181088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic SkTriColorShader* parent = static_cast<SkTriColorShader*>(const_cast<SkShader*>(&fShader)); 181188cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic TriColorShaderData* set = parent->takeSetupData(); 181288cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic if (set) { 181388cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic fSetup = setup(set->pts, set->colors, set->state->f0, set->state->f1, set->state->f2); 181488cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic } 181588cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 181688cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic if (!fSetup) { 181788cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic // Invalid matrices. Not checked before so no need to assert. 181888cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic return; 181988cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic } 182088cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 182106a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org const int alphaScale = Sk255To256(this->getPaintAlpha()); 182206a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src; 1824a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 1825ad15264f9ad2aa62e1da1ab3105887503ddeb4e9Mike Reed fDstToUnit.mapXY(SkIntToScalar(x) + 0.5, SkIntToScalar(y) + 0.5, &src); 18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale1 = ScalarTo256(src.fX); 18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale2 = ScalarTo256(src.fY); 18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale0 = 256 - scale1 - scale2; 18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale0 < 0) { 18318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale1 > scale2) { 18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale2 = 256 - scale1; 18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale1 = 256 - scale2; 18358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale0 = 0; 18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1838a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 183906a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org if (256 != alphaScale) { 184006a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale0 = SkAlphaMul(scale0, alphaScale); 184106a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale1 = SkAlphaMul(scale1, alphaScale); 184206a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org scale2 = SkAlphaMul(scale2, alphaScale); 184306a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org } 184406a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org 18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 184606a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[1], scale1) + 184706a32062620daee7a93742f553829a8d4f93f720commit-bot@chromium.org SkAlphaMulQ(fColors[2], scale2); 1848ad15264f9ad2aa62e1da1ab3105887503ddeb4e9Mike Reed 1849ad15264f9ad2aa62e1da1ab3105887503ddeb4e9Mike Reed src.fX += fDstToUnit.getScaleX(); 1850ad15264f9ad2aa62e1da1ab3105887503ddeb4e9Mike Reed src.fY += fDstToUnit.getSkewY(); 18518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18544c6e4103a246c27bdd1302a9c7fba64367758dccMike Reedvoid SkTriColorShader::TriColorShaderContext::shadeSpan4f(int x, int y, SkPM4f dstC[], int count) { 18554c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed SkTriColorShader* parent = static_cast<SkTriColorShader*>(const_cast<SkShader*>(&fShader)); 18564c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed TriColorShaderData* set = parent->takeSetupData(); 18574c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed if (set) { 18584c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed fSetup = setup(set->pts, set->colors, set->state->f0, set->state->f1, set->state->f2); 18594c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed } 18604c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 18614c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed if (!fSetup) { 18624c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed // Invalid matrices. Not checked before so no need to assert. 18634c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed return; 18644c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed } 18654c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 18664c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed SkPoint src; 18674c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed fDstToUnit.mapXY(SkIntToScalar(x) + 0.5, SkIntToScalar(y) + 0.5, &src); 18684c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 18694c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed Sk4f c = fC0.to4f() + src.fX * fC10.to4f() + src.fY * fC20.to4f(), 18704c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed dc = fDC.to4f(); 18714c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 18724c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed for (int i = 0; i < count; i++) { 18734c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed c.store(dstC[i].fVec); 18744c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed c += dc; 18754c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed } 18764c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed} 18774c6e4103a246c27bdd1302a9c7fba64367758dccMike Reed 18780f10f7bf1fb43ca6346dc220a076773b1f19a367commit-bot@chromium.org#ifndef SK_IGNORE_TO_STRING 187976f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.comvoid SkTriColorShader::toString(SkString* str) const { 188076f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append("SkTriColorShader: ("); 188176f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 188276f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com this->INHERITED::toString(str); 188376f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 188476f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com str->append(")"); 188576f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com} 188676f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com#endif 188776f9e938df0b5826fd4c80b854ceafaf385cfbe1robertphillips@google.com 1888f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malitanamespace { 1889f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1890f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita// Similar to SkLocalMatrixShader, but composes the local matrix with the CTM (instead 1891f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita// of composing with the inherited local matrix): 1892f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita// 1893f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita// rec' = {rec.ctm x localMatrix, rec.localMatrix} 1894f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita// 1895f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita// (as opposed to rec' = {rec.ctm, rec.localMatrix x localMatrix}) 1896f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita// 1897f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malitaclass SkLocalInnerMatrixShader final : public SkShader { 1898f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malitapublic: 1899f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita SkLocalInnerMatrixShader(sk_sp<SkShader> proxy, const SkMatrix& localMatrix) 1900f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita : INHERITED(&localMatrix) 1901f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita , fProxyShader(std::move(proxy)) {} 1902f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1903f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita Factory getFactory() const override { 1904f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita SkASSERT(false); 1905f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita return nullptr; 1906f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita } 1907f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1908f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malitaprotected: 1909f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita void flatten(SkWriteBuffer&) const override { 1910f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita SkASSERT(false); 1911f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita } 1912f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1913f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita Context* onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const override { 1914f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita SkMatrix adjustedCTM = SkMatrix::Concat(*rec.fMatrix, this->getLocalMatrix()); 1915f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita ContextRec newRec(rec); 1916f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita newRec.fMatrix = &adjustedCTM; 1917f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita return fProxyShader->makeContext(newRec, alloc); 1918f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita } 1919f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1920f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita bool onAppendStages(SkRasterPipeline* p, SkColorSpace* cs, SkArenaAlloc* alloc, 1921f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita const SkMatrix& ctm, const SkPaint& paint, 1922f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita const SkMatrix* localM) const override { 1923f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita // We control the shader graph ancestors, so we know there's no local matrix being 1924f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita // injected before this. 1925f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita SkASSERT(!localM); 1926f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1927f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita SkMatrix adjustedCTM = SkMatrix::Concat(ctm, this->getLocalMatrix()); 1928f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita return fProxyShader->appendStages(p, cs, alloc, adjustedCTM, paint); 1929f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita } 1930f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1931f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malitaprivate: 1932f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita sk_sp<SkShader> fProxyShader; 1933f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1934f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita typedef SkShader INHERITED; 1935f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita}; 1936f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1937f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malitask_sp<SkShader> MakeTextureShader(const VertState& state, const SkPoint verts[], 19384b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita const SkPoint texs[], const SkPaint& paint, 19394b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkColorSpace* dstColorSpace, 19404b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkArenaAlloc* alloc) { 19414b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkASSERT(paint.getShader()); 19424b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19434b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita const auto& p0 = texs[state.f0], 19444b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita p1 = texs[state.f1], 19454b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita p2 = texs[state.f2]; 19464b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19474b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita if (p0 != p1 || p0 != p2) { 19484b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // Common case (non-collapsed texture coordinates). 19494b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // Map the texture to vertices using a local transform. 1950f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1951f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita // We cannot use a plain SkLocalMatrix shader, because we need the texture matrix 1952f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita // to compose next to the CTM. 19534b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkMatrix localMatrix; 19544b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita return texture_to_matrix(state, verts, texs, &localMatrix) 1955f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita ? alloc->makeSkSp<SkLocalInnerMatrixShader>(paint.refShader(), localMatrix) 19564b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita : nullptr; 19574b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita } 19584b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19594b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // Collapsed texture coordinates special case. 19604b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // The texture is a solid color, sampled at the given point. 19614b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkMatrix shaderInvLocalMatrix; 19624b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkAssertResult(paint.getShader()->getLocalMatrix().invert(&shaderInvLocalMatrix)); 19634b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19644b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita const auto sample = SkPoint::Make(0.5f, 0.5f); 19654b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita const auto mappedSample = shaderInvLocalMatrix.mapXY(sample.x(), sample.y()), 19664b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita mappedPoint = shaderInvLocalMatrix.mapXY(p0.x(), p0.y()); 19674b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita const auto localMatrix = SkMatrix::MakeTrans(mappedSample.x() - mappedPoint.x(), 19684b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita mappedSample.y() - mappedPoint.y()); 19694b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19704b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkShader::ContextRec rec(paint, SkMatrix::I(), &localMatrix, 19714b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkShader::ContextRec::kPMColor_DstType, dstColorSpace); 19724b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita auto* ctx = paint.getShader()->makeContext(rec, alloc); 19734b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita if (!ctx) { 19744b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita return nullptr; 19754b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita } 19764b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19774b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkPMColor pmColor; 19784b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita ctx->shadeSpan(SkScalarFloorToInt(sample.x()), SkScalarFloorToInt(sample.y()), &pmColor, 1); 19794b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19804b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // no need to keep this temp context around. 19814b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita alloc->reset(); 19824b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 19834b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita return alloc->makeSkSp<SkColorShader>(SkUnPreMultiply::PMColorToColor(pmColor)); 19844b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita} 19854b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita 1986f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita} // anonymous ns 1987f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita 1988887cdf112809727c51890ba8b98b3ddce22249f0Mike Reedvoid SkDraw::drawVertices(SkVertices::VertexMode vmode, int count, 19898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint vertices[], const SkPoint textures[], 19907d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed const SkColor colors[], SkBlendMode bmode, 19918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 19928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 199349f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(0 == count || vertices); 1994a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 19958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // abort early if there is nothing to draw 1996045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { 19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1999a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform out vertices into device coordinates 20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoSTMalloc<16, SkPoint> storage(count); 20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* devVerts = storage.get(); 20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapPoints(devVerts, vertices, count); 2004a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 20068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com We can draw the vertices in 1 of 4 ways: 20078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - solid color (no shader/texture[], no colors[]) 20098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just colors (no shader/texture[], has colors[]) 20108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just texture (has shader/texture[], no colors[]) 20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - colors * texture (has shader/texture[], has colors[]) 2012a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Thus for texture drawing, we need both texture[] and a shader. 20148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 20158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20168a21c9fe7f5fef9e87115defef27bd7218419f28reed auto triShader = sk_make_sp<SkTriColorShader>(); 20178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 20188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = p.getShader(); 202096fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == shader) { 20218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we have no shader, we ignore the texture coordinates 202296fcdcc219d2a0d3579719b84b28bede76efba64halcanary textures = nullptr; 202396fcdcc219d2a0d3579719b84b28bede76efba64halcanary } else if (nullptr == textures) { 20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we don't have texture coordinates, ignore the shader 202596fcdcc219d2a0d3579719b84b28bede76efba64halcanary p.setShader(nullptr); 202696fcdcc219d2a0d3579719b84b28bede76efba64halcanary shader = nullptr; 20278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup the custom shader (if needed) 203049f085dddff10473b6ebf832a974288300224e60bsalomon if (colors) { 203196fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (nullptr == textures) { 20328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // just colors (no texture) 20338a21c9fe7f5fef9e87115defef27bd7218419f28reed p.setShader(triShader); 20348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 20358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // colors * texture 20368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(shader); 20377d954ad797176afedb9262fdea4507d0fc60eb9dMike Reed p.setShader(SkShader::MakeComposeShader(triShader, sk_ref_sp(shader), bmode)); 20388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 204141e010cb901c0da9066c4df562030808c9ccd7f8reed SkAutoBlitterChoose blitter(fDst, *fMatrix, p); 204287fcd950198a16211b3988610beebb5ca5bcf323commit-bot@chromium.org // Abort early if we failed to create a shader context. 2043ea033606a06d05d2d42aa7118409fee798e53167reed@google.com if (blitter->isNullBlitter()) { 2044ea033606a06d05d2d42aa7118409fee798e53167reed@google.com return; 2045ea033606a06d05d2d42aa7118409fee798e53167reed@google.com } 2046ea033606a06d05d2d42aa7118409fee798e53167reed@google.com 20478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup our state and function pointer for iterating triangles 20488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState state(count, indices, indexCount); 20498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState::Proc vertProc = state.chooseProc(vmode); 2050a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 205149f085dddff10473b6ebf832a974288300224e60bsalomon if (textures || colors) { 205288cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic SkTriColorShader::TriColorShaderData verticesSetup = { vertices, colors, &state }; 205388cb82246a5dc141cb9f49a3b9187abb515cd49daleksandar.stojiljkovic 20548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 205500dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita auto* blitterPtr = blitter.get(); 205600dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita 20574b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // We're going to allocate at most 20584b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // 20594b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // * one SkLocalMatrixShader OR one SkColorShader 20604b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // * one SkComposeShader 20614b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // * one SkAutoBlitterChoose 20624b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita // 20634b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita static constexpr size_t kAllocSize = 20644b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita sizeof(SkAutoBlitterChoose) + sizeof(SkComposeShader) + 2065f614ba2ddc7e0805616bd40e104021695ff7d767Florin Malita SkTMax(sizeof(SkLocalInnerMatrixShader), sizeof(SkColorShader)); 20664b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita char allocBuffer[kAllocSize]; 20674b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita SkArenaAlloc alloc(allocBuffer); 206800dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita 206949f085dddff10473b6ebf832a974288300224e60bsalomon if (textures) { 20704b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita sk_sp<SkShader> texShader = MakeTextureShader(state, vertices, textures, paint, 20714b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita fDst.colorSpace(), &alloc); 20724b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita if (texShader) { 207300dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita SkPaint localPaint(p); 20744b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita localPaint.setShader(colors 20754b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita ? alloc.makeSkSp<SkComposeShader>(triShader, std::move(texShader), bmode) 20764b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita : std::move(texShader)); 207700dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita 20784b66512a6384d32c1a89396bd4a229c03cce67a0Florin Malita blitterPtr = alloc.make<SkAutoBlitterChoose>(fDst, *fMatrix, localPaint)->get(); 207900dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita if (blitterPtr->isNullBlitter()) { 20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 208449f085dddff10473b6ebf832a974288300224e60bsalomon if (colors) { 20858a21c9fe7f5fef9e87115defef27bd7218419f28reed triShader->bindSetupData(&verticesSetup); 20868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2087045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com 2088045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPoint tmp[] = { 2089045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 2090045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com }; 209100dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita SkScan::FillTriangle(tmp, *fRC, blitterPtr); 209200dca8cb09aaeca067cac022e97c4af31e656b37Florin Malita triShader->bindSetupData(nullptr); 20938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2095559a8833f0eae4af37dc0ffc3ee97e1fb14817b1commit-bot@chromium.org // no colors[] and no texture, stroke hairlines with paint's color. 20965dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias()); 2097045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkRasterClip& clip = *fRC; 20988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 20995dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed SkPoint array[] = { 21005dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0] 21015dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed }; 21025dc6b7d1a8bc591d62366ff83c434ff74f3e10fcreed hairProc(array, 4, clip, blitter.get()); 21038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21070a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 21080a0a236c3ba241046d38caaf78226ec68ff9c998reed@google.com/////////////////////////////////////////////////////////////////////////////// 21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 21118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2112f2b98d67dcb6fcb3120feede9c72016fc7b3ead8reed@android.comvoid SkDraw::validate() const { 211396fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(fMatrix != nullptr); 211496fcdcc219d2a0d3579719b84b28bede76efba64halcanary SkASSERT(fRC != nullptr); 21158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2116045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com const SkIRect& cr = fRC->getBounds(); 21178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect br; 21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 211941e010cb901c0da9066c4df562030808c9ccd7f8reed br.set(0, 0, fDst.width(), fDst.height()); 21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cr.isEmpty() || br.contains(cr)); 21218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 21248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////////// 21268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 21288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 21298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h" 21308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 2133b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed const SkMaskFilter* filter, const SkMatrix* filterMatrix, 21348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect* bounds) { 21358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (devPath.isEmpty()) { 21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 21378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // init our bounds from the path 214011fa2247b747eb75e2f158dc7571d458ed6c0115reed *bounds = devPath.getBounds().makeOutset(SK_ScalarHalf, SK_ScalarHalf).roundOut(); 2141a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21426db75fc2c393ba86a3f533597a8bcd348477e79ctomhudson@google.com SkIPoint margin = SkIPoint::Make(0, 0); 21438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (filter) { 21448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(filterMatrix); 2145a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21465af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com SkMask srcM, dstM; 2147a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fBounds = *bounds; 21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fFormat = SkMask::kA8_Format; 21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 21518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 21528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2154a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 21555af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com // (possibly) trim the bounds to reflect the clip 21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (plus whatever slop the filter needs) 21575af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com if (clipBounds) { 21583555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // Ugh. Guard against gigantic margins from wacky filters. Without this 21593555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // check we can request arbitrary amounts of slop beyond our visible 21603555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // clip, and bring down the renderer (at least on finite RAM machines 21613555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // like handsets, etc.). Need to balance this invented value between 21623555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // quality of large filters like blurs, and the corresponding memory 21633555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // requests. 21643555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com static const int MAX_MARGIN = 128; 216511fa2247b747eb75e2f158dc7571d458ed6c0115reed if (!bounds->intersect(clipBounds->makeOutset(SkMin32(margin.fX, MAX_MARGIN), 216611fa2247b747eb75e2f158dc7571d458ed6c0115reed SkMin32(margin.fY, MAX_MARGIN)))) { 21675af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com return false; 21685af16f8d670b3ce1c7644a4737e02e2e2257614ebungeman@google.com } 21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 21728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2174055e192adc0072ae2548ef5431ceee652945f9c2bsalomonstatic void draw_into_mask(const SkMask& mask, const SkPath& devPath, 2175055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkStrokeRec::InitStyle style) { 217641e010cb901c0da9066c4df562030808c9ccd7f8reed SkDraw draw; 217741e010cb901c0da9066c4df562030808c9ccd7f8reed if (!draw.fDst.reset(mask)) { 217841e010cb901c0da9066c4df562030808c9ccd7f8reed return; 217941e010cb901c0da9066c4df562030808c9ccd7f8reed } 218041e010cb901c0da9066c4df562030808c9ccd7f8reed 2181045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkRasterClip clip; 2182045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkMatrix matrix; 2183045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com SkPaint paint; 21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2185045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height())); 21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 21878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2189045e62d715f5ee9b03deb5af3c750f8318096179reed@google.com draw.fRC = &clip; 21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setAntiAlias(true); 2192055e192adc0072ae2548ef5431ceee652945f9c2bsalomon switch (style) { 2193055e192adc0072ae2548ef5431ceee652945f9c2bsalomon case SkStrokeRec::kHairline_InitStyle: 2194055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkASSERT(!paint.getStrokeWidth()); 2195055e192adc0072ae2548ef5431ceee652945f9c2bsalomon paint.setStyle(SkPaint::kStroke_Style); 2196055e192adc0072ae2548ef5431ceee652945f9c2bsalomon break; 2197055e192adc0072ae2548ef5431ceee652945f9c2bsalomon case SkStrokeRec::kFill_InitStyle: 2198055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkASSERT(paint.getStyle() == SkPaint::kFill_Style); 2199055e192adc0072ae2548ef5431ceee652945f9c2bsalomon break; 2200055e192adc0072ae2548ef5431ceee652945f9c2bsalomon 2201055e192adc0072ae2548ef5431ceee652945f9c2bsalomon } 22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawPath(devPath, paint); 22038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 220630711b764be6bbb58caa30a0ac5d1474c894efe7reed@google.com const SkMaskFilter* filter, const SkMatrix* filterMatrix, 22072ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org SkMask* mask, SkMask::CreateMode mode, 2208055e192adc0072ae2548ef5431ceee652945f9c2bsalomon SkStrokeRec::InitStyle style) { 22098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustRenderImage_CreateMode != mode) { 22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2213a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 22158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fFormat = SkMask::kA8_Format; 22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fRowBytes = mask->fBounds.width(); 2217543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask->computeImageSize(); 2218543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 2219543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // we're too big to allocate the mask, abort 2220543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; 2221543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 2222543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com mask->fImage = SkMask::AllocImage(size); 22238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask->fImage, 0, mask->computeImageSize()); 22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustComputeBounds_CreateMode != mode) { 22272ac4ef5e6e0c9c95c9200408ba25a95ca758eac2junov@chromium.org draw_into_mask(*mask, devPath, style); 22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2229a76de3d1a92134c3e95ad7fce99234f92fa48268reed@google.com 22308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 22318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2232