SkDraw.cpp revision d055c1fde2128514167b315f4d104b177e04a3de
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/sgl/SkDraw.cpp 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Copyright 2006, The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Licensed under the Apache License, Version 2.0 (the "License"); 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** you may not use this file except in compliance with the License. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** You may obtain a copy of the License at 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** http://www.apache.org/licenses/LICENSE-2.0 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Unless required by applicable law or agreed to in writing, software 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** distributed under the License is distributed on an "AS IS" BASIS, 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** See the License for the specific language governing permissions and 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** limitations under the License. 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBounder.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCanvas.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDevice.h" 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkMaskFilter.h" 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPaint.h" 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathEffect.h" 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRasterizer.h" 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScan.h" 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h" 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkStroke.h" 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkTemplatesPriv.h" 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkAutoKern.h" 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcShader.h" 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDrawProcs.h" 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//#define TRACE_BITMAP_DRAWS 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoRestoreBounder : SkNoncopyable { 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // note: initializing fBounder is done only to fix a warning 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoRestoreBounder() : fDraw(NULL), fBounder(NULL) {} 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoRestoreBounder() { 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDraw) { 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDraw->fBounder = fBounder; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void clearBounder(const SkDraw* draw) { 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDraw = const_cast<SkDraw*>(draw); 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = draw->fBounder; 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDraw->fBounder = NULL; 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw* fDraw; 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBounder* fBounder; 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic SkPoint* rect_points(SkRect& r, int index) { 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)index < 2); 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return &((SkPoint*)(void*)&r)[index]; 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** Helper for allocating small blitters on the stack. 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2) 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBlitterChoose { 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix, 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter = SkBlitter::Choose(device, matrix, paint, 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStorage, sizeof(fStorage)); 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBlitterChoose(); 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* operator->() { return fBlitter; } 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* get() const { return fBlitter; } 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* fBlitter; 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fStorage[kBlitterStorageLongCount]; 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkAutoBlitterChoose::~SkAutoBlitterChoose() { 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((void*)fBlitter == (void*)fStorage) { 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter->~SkBlitter(); 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(fBlitter); 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoBitmapShaderInstall { 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint* paint) 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fPaint((SkPaint*)paint) { 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevShader = paint->getShader(); 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevShader->safeRef(); 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint->setShader(SkShader::CreateBitmapShader( src, 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStorage, sizeof(fStorage))); 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoBitmapShaderInstall() { 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = fPaint->getShader(); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint->setShader(fPrevShader); 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPrevShader->safeUnref(); 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((void*)shader == (void*)fStorage) { 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->~SkShader(); 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDELETE(shader); 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint* fPaint; 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* fPrevShader; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t fStorage[kBlitterStorageLongCount]; 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoPaintStyleRestore { 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintStyleRestore(const SkPaint& paint, SkPaint::Style style) 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fPaint((SkPaint&)paint) { 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fStyle = paint.getStyle(); // record the old 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint.setStyle(style); // change it to the specified style 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoPaintStyleRestore() { 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint.setStyle(fStyle); // restore the old 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint& fPaint; 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint::Style fStyle; 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // illegal 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintStyleRestore(const SkAutoPaintStyleRestore&); 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintStyleRestore& operator=(const SkAutoPaintStyleRestore&); 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDraw::SkDraw(const SkDraw& src) { 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memcpy(this, &src, sizeof(*this)); 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) { 1544516f4786f5dda1b86a8f825b9e8e910d9c2363creed@android.com sk_bzero(pixels, bytes); 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {} 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset32((uint32_t*)pixels, data, bytes >> 2); 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset16((uint16_t*)pixels, data, bytes >> 1); 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(pixels, data, bytes); 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap, 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint, 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t* data) { 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // todo: we can apply colorfilter up front if no shader, so we wouldn't 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to abort this fastpath 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getShader() || paint.getColorFilter()) { 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 180845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com SkXfermode::Mode mode; 181845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (!SkXfermode::IsMode(paint.getXfermode(), &mode)) { 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColor color = paint.getColor(); 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // collaps modes based on color... 188845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com if (SkXfermode::kSrcOver_Mode == mode) { 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned alpha = SkColorGetA(color); 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == alpha) { 191845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com mode = SkXfermode::kDst_Mode; 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (0xFF == alpha) { 193845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com mode = SkXfermode::kSrc_Mode; 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 198845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kClear_Mode: 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Clear_BitmapXferProc\n"); 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Clear_BitmapXferProc; // ignore data 201845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kDst_Mode: 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D_Dst_BitmapXferProc\n"); 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D_Dst_BitmapXferProc; // ignore data 204845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com case SkXfermode::kSrc_Mode: { 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com should I worry about dithering for the lower depths? 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor pmc = SkPreMultiplyColor(color); 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (bitmap.config()) { 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kARGB_8888_Config: 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = pmc; 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D32_Src_BitmapXferProc\n"); 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D32_Src_BitmapXferProc; 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kARGB_4444_Config: 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkPixel32ToPixel4444(pmc); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D16_Src_BitmapXferProc\n"); 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D16_Src_BitmapXferProc; 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kRGB_565_Config: 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkPixel32ToPixel16(pmc); 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- D16_Src_BitmapXferProc\n"); 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D16_Src_BitmapXferProc; 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kA8_Config: 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (data) { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *data = SkGetPackedA32(pmc); 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// SkDebugf("--- DA8_Src_BitmapXferProc\n"); 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return DA8_Src_BitmapXferProc; 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect, 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BitmapXferProc proc, uint32_t procData) { 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int shiftPerPixel; 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (bitmap.config()) { 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kARGB_8888_Config: 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 2; 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kARGB_4444_Config: 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kRGB_565_Config: 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 1; 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkBitmap::kA8_Config: 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shiftPerPixel = 0; 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!"Can't use xferproc on this config"); 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* pixels = (uint8_t*)bitmap.getPixels(); 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pixels); 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t rowBytes = bitmap.rowBytes(); 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int widthBytes = rect.width() << shiftPerPixel; 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // skip down to the first scanline and X position 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel); 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int scans = rect.height() - 1; scans >= 0; --scans) { 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(pixels, widthBytes, procData); 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pixels += rowBytes; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPaint(const SkPaint& paint) const { 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->isEmpty()) { 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devRect; 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com devRect.set(0, 0, fBitmap->width(), fBitmap->height()); 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doIRect(devRect)) { 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* If we don't have a shader (i.e. we're just a solid color) we may 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com be faster to operate directly on the device bitmap, rather than invoking 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com a blitter. Esp. true for xfermodes, which require a colorshader to be 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com present, which is just redundant work. Since we're drawing everywhere 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com in the clip, we don't have to worry about antialiasing. 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t procData = 0; // to avoid the warning 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData); 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (proc) { 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (D_Dst_BitmapXferProc == proc) { // nothing to do 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Iterator iter(*fClip); 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (!iter.done()) { 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData); 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com iter.next(); 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // normal case: use a blitter 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::FillIRect(devRect, fClip, blitter.get()); 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct PtProcRec { 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas::PointMode fMode; 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint* fPaint; 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* fClip; 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // computed values 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fRadius; 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter*); 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix, 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* clip); 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Proc chooseProc(SkBlitter* blitter); 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec.fClip->isRect()); 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = rec.fClip->getBounds(); 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = SkScalarFloor(devPts[i].fX); 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = SkScalarFloor(devPts[i].fY); 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_rect_16_hair_proc(const PtProcRec& rec, 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint devPts[], int count, 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter) { 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(rec.fClip->isRect()); 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& r = rec.fClip->getBounds(); 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value); 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bitmap); 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* addr = bitmap->getAddr16(0, 0); 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rb = bitmap->rowBytes(); 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = SkScalarFloor(devPts[i].fX); 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = SkScalarFloor(devPts[i].fY); 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (r.contains(x, y)) { 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// *bitmap->getAddr16(x, y) = SkToU16(value); 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value); 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int x = SkScalarFloor(devPts[i].fX); 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int y = SkScalarFloor(devPts[i].fY); 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec.fClip->contains(x, y)) { 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitH(x, y, 1); 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::HairLine(devPts[i], devPts[i+1], rec.fClip, blitter); 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count - 1; i++) { 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::HairLine(devPts[i], devPts[i+1], rec.fClip, blitter); 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// aa versions 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i += 2) { 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::AntiHairLine(devPts[i], devPts[i+1], rec.fClip, blitter); 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count - 1; i++) { 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::AntiHairLine(devPts[i], devPts[i+1], rec.fClip, blitter); 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::FillXRect(r, rec.fClip, blitter); 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count, SkBlitter* blitter) { 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkFixed radius = rec.fRadius; 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = SkScalarToFixed(devPts[i].fX); 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed y = SkScalarToFixed(devPts[i].fY); 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXRect r; 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = x - radius; 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = y - radius; 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = x + radius; 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = y + radius; 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::AntiFillXRect(r, rec.fClip, blitter); 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 446b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com// If this guy returns true, then chooseProc() must return a valid proc 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix, const SkRegion* clip) { 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect()) { 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width = paint.getStrokeWidth(); 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == width) { 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = clip; 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = SK_Fixed1 >> 1; 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 460b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com if (paint.getStrokeCap() != SkPaint::kRound_Cap && 461b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com matrix->rectStaysRect() && SkCanvas::kPoints_PointMode == mode) { 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = matrix->get(SkMatrix::kMScaleX); 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = matrix->get(SkMatrix::kMScaleY); 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkScalarNearlyZero(sx - sy)) { 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (sx < 0) { 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sx = -sx; 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMode = mode; 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = &paint; 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = clip; 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1; 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comPtProcRec::Proc PtProcRec::chooseProc(SkBlitter* blitter) { 480b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com Proc proc = NULL; 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for our arrays 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == SkCanvas::kPoints_PointMode); 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == SkCanvas::kLines_PointMode); 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(2 == SkCanvas::kPolygon_PointMode); 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // first check for hairlines 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == fPaint->getStrokeWidth()) { 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fPaint->isAntiAlias()) { 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const Proc gAAProcs[] = { 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gAAProcs[fMode]; 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t value; 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap* bm = blitter->justAnOpaqueColor(&value); 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bm && bm->config() == SkBitmap::kRGB_565_Config) { 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_16_hair_proc; 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_pt_rect_hair_proc; 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static Proc gBWProcs[] = { 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = gBWProcs[fMode]; 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 511b4f404ac4195e5b1f49e49c591bd69f98b246f9breed@android.com } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkCanvas::kPoints_PointMode == fMode); 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fPaint->isAntiAlias()) { 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = aa_square_proc; 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc = bw_square_proc; 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return proc; 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode, 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t count, const SkPoint pts[], 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint, const SkMatrix& matrix) { 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ibounds; 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect bounds; 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar inset = paint.getStrokeWidth(); 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(pts, count); 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.inset(-inset, -inset); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.mapRect(&bounds); 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.roundOut(&ibounds); 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return bounder->doIRect(ibounds); 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// each of these costs 8-bytes of stack space, so don't make it too large 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// must be even for lines/polygon to work 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAX_DEV_PTS 32 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint pts[], const SkPaint& paint) const { 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're in lines mode, force count to be even 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkCanvas::kLines_PointMode == mode) { 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count &= ~(size_t)1; 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((long)count <= 0) { 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoRestoreBounder arb; 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) { 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // clear the bounder for the rest of this function, so we don't call it 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // again later if we happen to call ourselves for drawRect, drawPath, 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // etc. 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com arb.clearBounder(this); 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(pts != NULL); 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->isEmpty() || 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PtProcRec rec; 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (rec.init(mode, paint, fMatrix, fClip)) { 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint devPts[MAX_DEV_PTS]; 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* bltr = blitter.get(); 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com PtProcRec::Proc proc = rec.chooseProc(bltr); 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we have to back up subsequent passes if we're in polygon mode 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t n = count; 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (n > MAX_DEV_PTS) { 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com n = MAX_DEV_PTS; 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix->mapPoints(devPts, pts, n); 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(rec, devPts, n, bltr); 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pts += n - backup; 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= n); 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= n; 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += backup; 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (count != 0); 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPoints_PointMode: { 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // temporarily mark the paint as filling. 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width = paint.getStrokeWidth(); 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar radius = SkScalarHalf(width); 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getStrokeCap() == SkPaint::kRound_Cap) { 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix preMatrix; 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.addCircle(0, 0, radius); 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com preMatrix.setTranslate(pts[i].fX, pts[i].fY); 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // pass true for the last point, since we can modify 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // then path then 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, paint, &preMatrix, (count-1) == i); 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i++) { 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = pts[i].fX - radius; 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = pts[i].fY - radius; 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = r.fLeft + width; 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = r.fTop + width; 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawRect(r, paint); 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kLines_PointMode: 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kPolygon_PointMode: { 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= 1; 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath path; 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setStyle(SkPaint::kStroke_Style); 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (size_t i = 0; i < count; i += inc) { 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.moveTo(pts[i]); 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.lineTo(pts[i+1]); 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(path, p, NULL, true); 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com path.rewind(); 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPoint* as_lefttop(SkRect* r) { 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (SkPoint*)(void*)r; 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline SkPoint* as_rightbottom(SkRect* r) { 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return ((SkPoint*)(void*)r) + 1; 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->isEmpty() || 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // complex enough to draw as a path 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect() || paint.getMaskFilter() || 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getRasterizer() || !fMatrix->rectStaysRect() || 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getStyle() != SkPaint::kFill_Style && 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarHalf(paint.getStrokeWidth()) > 0)) { 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmp; 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.addRect(rect); 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmp.setFillType(SkPath::kWinding_FillType); 675187d5595901d1120d9425851e5afdd773f574502reed@android.com this->drawPath(tmp, paint, NULL, true); 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix = *fMatrix; 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect devRect; 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform rect into devRect 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.mapXY(rect.fLeft, rect.fTop, rect_points(devRect, 0)); 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.mapXY(rect.fRight, rect.fBottom, rect_points(devRect, 1)); 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com devRect.sort(); 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doRect(devRect, paint)) { 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // look for the quick exit, before we build a blitter 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com devRect.roundOut(&ir); 69755e76b209c9249308a9ba3d75c2472dd55e9d298reed@android.com if (paint.getStyle() != SkPaint::kFill_Style) { 69855e76b209c9249308a9ba3d75c2472dd55e9d298reed@android.com // extra space for hairlines 69955e76b209c9249308a9ba3d75c2472dd55e9d298reed@android.com ir.inset(-1, -1); 70055e76b209c9249308a9ba3d75c2472dd55e9d298reed@android.com } 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->quickReject(ir)) 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitterStorage(*fBitmap, matrix, paint); 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter = blitterStorage.get(); 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRegion* clip = fClip; 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getStyle() == SkPaint::kFill_Style) { 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::AntiFillRect(devRect, clip, blitter); 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::FillRect(devRect, clip, blitter); 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::AntiHairRect(devRect, clip, blitter); 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::HairRect(devRect, clip, blitter); 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (srcM.fBounds.isEmpty()) { 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask dstM; 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMask* mask = &srcM; 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dstM.fImage = NULL; 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMaskImage ami(&dstM, false); 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getMaskFilter() && 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) { 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask = &dstM; 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doIRect(mask->fBounds)) { 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitMaskRegion(*mask, *fClip); 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkAutoPaintRestoreColorStrokeWidth { 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintRestoreColorStrokeWidth(const SkPaint& paint) { 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint = (SkPaint*)&paint; 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColor = paint.getColor(); 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fWidth = paint.getStrokeWidth(); 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ~SkAutoPaintRestoreColorStrokeWidth() { 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint->setColor(fColor); 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fPaint->setStrokeWidth(fWidth); 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint* fPaint; 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColor fColor; 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar fWidth; 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 767ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.comstatic SkScalar fast_len(const SkVector& vec) { 768ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar x = SkScalarAbs(vec.fX); 769ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar y = SkScalarAbs(vec.fY); 770ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (x < y) { 771ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkTSwap(x, y); 772ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 773ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return x + SkScalarHalf(y); 774ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 775ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 776ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com// our idea is to return true if there is no appreciable skew or non-square scale 777ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com// for that we'll transform (0,1) and (1,0), and check that the resulting dot-prod 778ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com// is nearly one 779ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.comstatic bool map_radius(const SkMatrix& matrix, SkScalar* value) { 780ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (matrix.getType() & SkMatrix::kPerspective_Mask) { 781ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 782ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 783ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkVector src[2], dst[2]; 784ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com src[0].set(*value, 0); 785ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com src[1].set(0, *value); 786ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com matrix.mapVectors(dst, src, 2); 787ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len0 = fast_len(dst[0]); 788ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com SkScalar len1 = fast_len(dst[1]); 789ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (len0 < SK_Scalar1 && len1 < SK_Scalar1) { 790ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com *value = SkScalarAve(len0, len1); 791ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return true; 792ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com } 793ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com return false; 794ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com} 795ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 7968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint, 7978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* prePathMatrix, bool pathIsMutable) const { 7988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 7998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 8018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->isEmpty() || 8028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 8038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* pathPtr = (SkPath*)&origSrcPath; 8078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool doFill = true; 8088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmpPath; 8098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix tmpMatrix; 8108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix* matrix = fMatrix; 8118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (prePathMatrix) { 8138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style || 8148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getRasterizer()) { 8158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* result = pathPtr; 8168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!pathIsMutable) { 8188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result = &tmpPath; 8198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathIsMutable = true; 8208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*prePathMatrix, result); 8228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = result; 8238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 8248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) { 8258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // overflow 8268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix = &tmpMatrix; 8298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // at this point we're done with prePathMatrix 8328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 8338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 8358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com If the device thickness < 1.0, then make it a hairline, and 8368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com modulate alpha if the thickness is even smaller (e.g. thickness == 0.5 8378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com should modulate the alpha by 1/2) 8388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 8398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintRestoreColorStrokeWidth aprc(paint); 8418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 842ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com // can we approximate a thin (but not hairline) stroke with an alpha-modulated 843ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com // hairline? Only if the matrix scales evenly in X and Y, and the device-width is 844ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com // less than a pixel 845ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) { 8468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width = paint.getStrokeWidth(); 847ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com if (width > 0 && map_radius(*matrix, &width)) { 848ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com int scale = (int)SkScalarMul(width, 256); 849ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com int alpha = paint.getAlpha() * scale >> 8; 850ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com 851ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com // pretend to be a hairline, with a modulated alpha 852ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com ((SkPaint*)&paint)->setAlpha(alpha); 853ebdeeb8a018f2df01e190fd961d68a94f0e0fcb9reed@android.com ((SkPaint*)&paint)->setStrokeWidth(0); 8548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 8588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com doFill = paint.getFillPath(*pathPtr, &tmpPath); 8598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr = &tmpPath; 8608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getRasterizer()) { 8638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 8648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getRasterizer()->rasterize(*pathPtr, *matrix, 8658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com &fClip->getBounds(), paint.getMaskFilter(), &mask, 8668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 8678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 8688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask::FreeImage(mask.fImage); 8698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // avoid possibly allocating a new path in transform if we can 8748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 8758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform the path into device space 8778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathPtr->transform(*matrix, devPathPtr); 8788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 8808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // how does filterPath() know to fill or hairline the path??? <mrr> 8828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getMaskFilter() && 8838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fClip, 8848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder, blitter.get())) { 8858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // filterPath() called the blitter, so we're done 8868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doPath(*devPathPtr, paint, doFill)) { 8898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 8908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 8928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (doFill) { 8938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 8948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::AntiFillPath(*devPathPtr, *fClip, blitter.get()); 8958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 8968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::FillPath(*devPathPtr, *fClip, blitter.get()); 8978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 8988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // hairline 8998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 9008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::AntiHairPath(*devPathPtr, fClip, blitter.get()); 9018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 9028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::HairPath(*devPathPtr, fClip, blitter.get()); 9038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9070baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com/** For the purposes of drawing bitmaps, if a matrix is "almost" translate 9080baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com go ahead and treat it as if it were, so that subsequent code can go fast. 9090baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com */ 9100baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.comstatic bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) { 9110baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com SkMatrix::TypeMask mask = matrix.getType(); 9120baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com 9130baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 9140baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com return false; 9150baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com } 9160baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com if (mask & SkMatrix::kScale_Mask) { 9170baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com SkScalar sx = matrix[SkMatrix::kMScaleX]; 9180baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com SkScalar sy = matrix[SkMatrix::kMScaleY]; 9190baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com int w = bitmap.width(); 9200baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com int h = bitmap.height(); 9210baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w))); 9220baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h))); 9230baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com return sw == w && sh == h; 9240baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com } 9250baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com // if we got here, we're either kTranslate_Mask or identity 9260baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com return true; 9278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 9288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, 9308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 9318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config); 9328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9330baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com if (just_translate(*fMatrix, bitmap)) { 9348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ix = SkScalarRound(fMatrix->getTranslateX()); 9358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int iy = SkScalarRound(fMatrix->getTranslateY()); 9368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 9388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 9398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 9408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = bitmap.rowBytes(); 9418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = bitmap.getAddr8(0, 0); 9428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 9448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // need to xform the bitmap first 9458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 9468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 9478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, 9498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 9508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapRect(&r); 9518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.round(&mask.fBounds); 9528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // set the mask's bounds to the transformed bitmap-bounds, 9548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // clipped to the actual device 9558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 9568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devBounds; 9578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com devBounds.set(0, 0, fBitmap->width(), fBitmap->height()); 9588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need intersect(l, t, r, b) on irect 9598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!mask.fBounds.intersect(devBounds)) { 9608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 9618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 9628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 963543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com 9648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fFormat = SkMask::kA8_Format; 9658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = SkAlign4(mask.fBounds.width()); 966543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask.computeImageSize(); 967543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 968543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // the mask is too big to allocated, draw nothing 969543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return; 970543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 9718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // allocate (and clear) our temp buffer to hold the transformed bitmap 9738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoMalloc storage(size); 9748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = (uint8_t*)storage.get(); 9758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask.fImage, 0, size); 9768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now draw our bitmap(src) into mask(dst), transformed by the matrix 9788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 9798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap device; 9808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), 9818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.height(), mask.fRowBytes); 9828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device.setPixels(mask.fImage); 9838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 9848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkCanvas c(device); 9858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need the unclipped top/left for the translate 9868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.translate(-SkIntToScalar(mask.fBounds.fLeft), 9878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 9888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com c.concat(*fMatrix); 9893469c76c40790b409621fd7eff34f56240718549reed@android.com 9903469c76c40790b409621fd7eff34f56240718549reed@android.com // We can't call drawBitmap, or we'll infinitely recurse. Instead 991fb12c3e6ba84f95dc15fbaddc239dede0ba1d60ereed@android.com // we manually build a shader and draw that into our new mask 9923469c76c40790b409621fd7eff34f56240718549reed@android.com SkPaint tmpPaint; 9933469c76c40790b409621fd7eff34f56240718549reed@android.com tmpPaint.setFlags(paint.getFlags()); 9943469c76c40790b409621fd7eff34f56240718549reed@android.com SkAutoBitmapShaderInstall install(bitmap, &tmpPaint); 9953469c76c40790b409621fd7eff34f56240718549reed@android.com SkRect rr; 9963469c76c40790b409621fd7eff34f56240718549reed@android.com rr.set(0, 0, SkIntToScalar(bitmap.width()), 9973469c76c40790b409621fd7eff34f56240718549reed@android.com SkIntToScalar(bitmap.height())); 9983469c76c40790b409621fd7eff34f56240718549reed@android.com c.drawRect(rr, tmpPaint); 9998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawDevMask(mask, paint); 10018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool clipped_out(const SkMatrix& m, const SkRegion& c, 10058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& srcR) { 10068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect dstR; 10078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect devIR; 10088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.mapRect(&dstR, srcR); 10108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dstR.roundOut(&devIR); 10118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return c.quickReject(devIR); 10128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool clipped_out(const SkMatrix& matrix, const SkRegion& clip, 10158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width, int height) { 10168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 10178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 10188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return clipped_out(matrix, clip, r); 10198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 10208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 10228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 10238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 10248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 10268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->isEmpty() || 10278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 10288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.getConfig() == SkBitmap::kNo_Config || 10298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 10308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // run away on too-big bitmaps for now (exceed 16.16) 10348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.width() > 32767 || bitmap.height() > 32767) { 10358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); 10398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 10418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!matrix.setConcat(*fMatrix, prematrix)) { 10428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clipped_out(matrix, *fClip, bitmap.width(), bitmap.height())) { 10468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1049218521e15706c4377b1be49d931c4d7c8d597445reed@android.com if (fBounder && just_translate(matrix, bitmap)) { 1050218521e15706c4377b1be49d931c4d7c8d597445reed@android.com SkIRect ir; 1051218521e15706c4377b1be49d931c4d7c8d597445reed@android.com int32_t ix = SkScalarRound(matrix.getTranslateX()); 1052218521e15706c4377b1be49d931c4d7c8d597445reed@android.com int32_t iy = SkScalarRound(matrix.getTranslateY()); 1053218521e15706c4377b1be49d931c4d7c8d597445reed@android.com ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 1054218521e15706c4377b1be49d931c4d7c8d597445reed@android.com if (!fBounder->doIRect(ir)) { 1055218521e15706c4377b1be49d931c4d7c8d597445reed@android.com return; 1056218521e15706c4377b1be49d931c4d7c8d597445reed@android.com } 1057218521e15706c4377b1be49d931c4d7c8d597445reed@android.com } 1058218521e15706c4377b1be49d931c4d7c8d597445reed@android.com 1059218521e15706c4377b1be49d931c4d7c8d597445reed@android.com // only lock the pixels if we passed the clip and bounder tests 10608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoLockPixels alp(bitmap); 10618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // after the lock, check if we are valid 10628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!bitmap.readyToDraw()) { 10638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10660baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com if (bitmap.getConfig() != SkBitmap::kA8_Config && 10670baf19375466cfc24c96532df406e7c5b1d1aae8reed@android.com just_translate(matrix, bitmap)) { 10688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ix = SkScalarRound(matrix.getTranslateX()); 10698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int iy = SkScalarRound(matrix.getTranslateY()); 10708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t storage[kBlitterStorageLongCount]; 10718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 10728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ix, iy, storage, sizeof(storage)); 10738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (blitter) { 10748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage); 10758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect ir; 10778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 10788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator iter(*fClip, ir); 10808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = iter.rect(); 10818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (; !iter.done(); iter.next()) { 10838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!cr.isEmpty()); 10848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 10858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 10878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 10898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDebugf("---- MISSING sprite case: config=%d [%d %d], device=%d, xfer=%p, alpha=0x%X colorFilter=%p\n", 10908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.config(), bitmap.width(), bitmap.height(), fBitmap->config(), 10918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getXfermode(), paint.getAlpha(), paint.getColorFilter()); 10928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 10938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 10948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 10958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now make a temp draw on the stack, and use it 10968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // 10978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 10988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 10998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bitmap.getConfig() == SkBitmap::kA8_Config) { 11018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawBitmapAsMask(bitmap, paint); 11028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 11038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBitmapShaderInstall install(bitmap, &paint); 11048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 11068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(0, 0, SkIntToScalar(bitmap.width()), 11078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIntToScalar(bitmap.height())); 11088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // is this ok if paint has a rasterizer? 11098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawRect(r, paint); 11108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, 11148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 11158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 11168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 11188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->isEmpty() || 11198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.width() == 0 || bitmap.height() == 0 || 11208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bitmap.getConfig() == SkBitmap::kNo_Config || 11218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 11228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect bounds; 11268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(x, y, x + bitmap.width(), y + bitmap.height()); 11278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->quickReject(bounds)) { 11298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // nothing to draw 11308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); 11338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == paint.getColorFilter()) { 11358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t storage[kBlitterStorageLongCount]; 11368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 11378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x, y, storage, sizeof(storage)); 11388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (blitter) { 11408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage); 11418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder && !fBounder->doIRect(bounds)) { 11438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator iter(*fClip, bounds); 11478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = iter.rect(); 11488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (; !iter.done(); iter.next()) { 11508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!cr.isEmpty()); 11518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 11528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 11548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBitmapShaderInstall install(bitmap, &paint); 11588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 11608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 11618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // get a scalar version of our rect 11638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.set(bounds); 11648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // tell the shader our offset 11668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(r.fLeft, r.fTop); 11678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.getShader()->setLocalMatrix(matrix); 11688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw(*this); 11708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.reset(); 11718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 11728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // call ourself with a rect 11738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // is this OK if paint has a rasterizer? 11748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawRect(r, paint); 11758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 11768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 11788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkScalerContext.h" 11808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkGlyphCache.h" 11818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 11828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, 11848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char text[], size_t byteLength, SkVector* stopVector) { 11858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed x = 0, y = 0; 11868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 11878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoKern autokern; 11898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 11918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't need x, y here, since all subpixel variants will have the 11928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // same advance 11938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 11948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 11958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += autokern.adjust(glyph) + glyph.fAdvanceX; 11968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y += glyph.fAdvanceY; 11978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 11988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); 11998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(text == stop); 12018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText_asPaths(const char text[], size_t byteLength, 12048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, 12058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 12068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 12078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTextToPathIter iter(text, byteLength, paint, true, true); 12098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 12118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setScale(iter.getPathScale(), iter.getPathScale()); 12128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(x, y); 12138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath* iterPath; 12158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar xpos, prevXPos = 0; 12168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((iterPath = iter.next(&xpos)) != NULL) { 12188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(xpos - prevXPos, 0); 12198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(*iterPath, iter.getPaint(), &matrix, false); 12208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com prevXPos = xpos; 12218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kStdStrikeThru_Offset (-SK_Scalar1 * 6 / 21) 12258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kStdUnderline_Offset (SK_Scalar1 / 9) 12268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define kStdUnderline_Thickness (SK_Scalar1 / 18) 12278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void draw_paint_rect(const SkDraw* draw, const SkPaint& paint, 12298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkRect& r, SkScalar textSize) { 12308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getStyle() == SkPaint::kFill_Style) { 12318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw->drawRect(r, paint); 12328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 12338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 12348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 12358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw->drawRect(r, p); 12368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void handle_aftertext(const SkDraw* draw, const SkPaint& paint, 12408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar width, const SkPoint& start) { 12418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t flags = paint.getFlags(); 12428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & (SkPaint::kUnderlineText_Flag | 12448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint::kStrikeThruText_Flag)) { 12458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar textSize = paint.getTextSize(); 12468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 12478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect r; 12488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = start.fX; 12508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = start.fX + width; 12518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkPaint::kUnderlineText_Flag) { 12538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 12548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com start.fY); 12558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = offset; 12568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = offset + height; 12578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw_paint_rect(draw, paint, r, textSize); 12588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (flags & SkPaint::kStrikeThruText_Flag) { 12608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 12618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com start.fY); 12628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = offset; 12638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = offset + height; 12648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw_paint_rect(draw, paint, r, textSize); 12658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 12678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 12688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// disable warning : local variable used without having been initialized 12708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 12718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( push ) 12728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( disable : 4701 ) 12738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 12748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 12768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D1G_NoBounder_RectClip(const SkDraw1Glyph& state, 12788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph, int left, int top) { 12798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 12808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(state.fClip->isRect()); 12818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(NULL == state.fBounder); 12828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(state.fClipBounds == state.fClip->getBounds()); 12838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 12858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 12868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int right = left + glyph.fWidth; 12888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int bottom = top + glyph.fHeight; 12898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 12918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect storage; 12928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect* bounds = &mask.fBounds; 12938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(left, top, right, bottom); 12958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 12968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // this extra test is worth it, assuming that most of the time it succeeds 12978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // since we can avoid writing to storage 12988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) { 12998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds)) 13008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds = &storage; 13028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* aa = (uint8_t*)glyph.fImage; 13058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == aa) { 13068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = (uint8_t*)state.fCache->findImage(glyph); 13078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == aa) { 13088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; // can't rasterize glyph 13098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = glyph.rowBytes(); 13136c14b43a840c791699747ba4cc0ed5abf2bda218reed@android.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 13148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = aa; 13158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fBlitter->blitMask(mask, *bounds); 13168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state, 13198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph, int left, int top) { 13208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 13218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!state.fClip->isRect()); 13228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(NULL == state.fBounder); 13238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 13258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 13278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 13288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 13308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 13318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!clipper.done()) { 13338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = clipper.rect(); 13348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t* aa = (const uint8_t*)glyph.fImage; 13358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == aa) { 13368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = (uint8_t*)state.fCache->findImage(glyph); 13378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == aa) { 13388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = glyph.rowBytes(); 13436c14b43a840c791699747ba4cc0ed5abf2bda218reed@android.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 13448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = (uint8_t*)aa; 13458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 13468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fBlitter->blitMask(mask, cr); 13478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clipper.next(); 13488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (!clipper.done()); 13498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void D1G_Bounder(const SkDraw1Glyph& state, 13538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph, int left, int top) { 13548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 13558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask mask; 13578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com left += glyph.fLeft; 13598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com top += glyph.fTop; 13608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 13628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 13638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!clipper.done()) { 13658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = clipper.rect(); 13668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t* aa = (const uint8_t*)glyph.fImage; 13678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == aa) { 13688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = (uint8_t*)state.fCache->findImage(glyph); 13698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == aa) { 13708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 13718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1373d055c1fde2128514167b315f4d104b177e04a3dereed@android.com 1374d055c1fde2128514167b315f4d104b177e04a3dereed@android.com // we need to pass the origin, which we approximate with our 1375d055c1fde2128514167b315f4d104b177e04a3dereed@android.com // (unadjusted) left,top coordinates (the caller called fixedfloor) 1376d055c1fde2128514167b315f4d104b177e04a3dereed@android.com if (state.fBounder->doIRectGlyph(cr, 1377d055c1fde2128514167b315f4d104b177e04a3dereed@android.com left - glyph.fLeft, 1378d055c1fde2128514167b315f4d104b177e04a3dereed@android.com top - glyph.fTop, glyph)) { 13798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fRowBytes = glyph.rowBytes(); 13806c14b43a840c791699747ba4cc0ed5abf2bda218reed@android.com mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 13818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask.fImage = (uint8_t*)aa; 13828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 13838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fBlitter->blitMask(mask, cr); 13848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clipper.next(); 13858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (!clipper.done()); 13868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 13888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 13898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, 13918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkGlyphCache* cache) { 13928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDraw = draw; 13938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBounder = draw->fBounder; 13948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip = draw->fClip; 13958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClipBounds = fClip->getBounds(); 13968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBlitter = blitter; 13978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCache = cache; 13988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 13998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (draw->fProcs && draw->fProcs->fD1GProc) { 14008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return draw->fProcs->fD1GProc; 14018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == fBounder) { 14048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fClip->isRect()) { 14058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D1G_NoBounder_RectClip; 14068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 14078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D1G_NoBounder_RgnClip; 14088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 14108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return D1G_Bounder; 14118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comenum RoundBaseline { 14158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kDont_Round_Baseline, 14168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kRound_X_Baseline, 14178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com kRound_Y_Baseline 14188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 14198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic RoundBaseline computeRoundBaseline(const SkMatrix& mat) { 14218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mat[1] == 0 && mat[3] == 0) { 14228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we're 0 or 180 degrees, round the y coordinate of the baseline 14238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kRound_Y_Baseline; 14248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (mat[0] == 0 && mat[4] == 0) { 14258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // we're 90 or 270 degrees, round the x coordinate of the baseline 14268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kRound_X_Baseline; 14278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 14288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return kDont_Round_Baseline; 14298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 14318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 14338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawText(const char text[], size_t byteLength, 14358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar x, SkScalar y, const SkPaint& paint) const { 14368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 14378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 14398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 14418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (text == NULL || byteLength == 0 || 14428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip->isEmpty() || 14438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 14448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar underlineWidth = 0; 14488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint underlineStart; 14498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com underlineStart.set(0, 0); // to avoid warning 14518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 14528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint::kStrikeThruText_Flag)) { 14538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com underlineWidth = paint.measureText(text, byteLength); 14548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar offsetX = 0; 14568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 14578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com offsetX = SkScalarHalf(underlineWidth); 14588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 14598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com offsetX = underlineWidth; 14608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com underlineStart.set(x - offsetX, y); 14628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (/*paint.isLinearText() ||*/ 14658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (fMatrix->getType() & SkMatrix::kPerspective_Mask)) { 14668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawText_asPaths(text, byteLength, x, y, paint); 14678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com handle_aftertext(this, paint, underlineWidth, underlineStart); 14688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 14698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 14728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoGlyphCache autoCache(paint, fMatrix); 14748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkGlyphCache* cache = autoCache.getCache(); 14758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 14768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform our starting point 14788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 14798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint loc; 14808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapXY(x, y, &loc); 14818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x = loc.fX; 14828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y = loc.fY; 14838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to measure first 14868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() != SkPaint::kLeft_Align) { 14878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector stop; 14888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com measure_text(cache, glyphCacheProc, text, byteLength, &stop); 14908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar stopX = stop.fX; 14928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar stopY = stop.fY; 14938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 14948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 14958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopX = SkScalarHalf(stopX); 14968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com stopY = SkScalarHalf(stopY); 14978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 14988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x -= stopX; 14998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com y -= stopY; 15008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fx = SkScalarToFixed(x); 15038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fy = SkScalarToFixed(y); 15048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 15058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isSubpixelText()) { 15078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix); 15088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (kRound_Y_Baseline == roundBaseline) { 15098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy = (fy + 0x8000) & ~0xFFFF; 15108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (kRound_X_Baseline == roundBaseline) { 15118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx = (fx + 0x8000) & ~0xFFFF; 15128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 15148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // apply the bias here, so we don't have to add 1/2 in the loop 15158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx += SK_Fixed1/2; 15168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy += SK_Fixed1/2; 15178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoKern autokern; 15208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw1Glyph d1g; 15218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache); 15228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 15248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); 15258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx += autokern.adjust(glyph); 15278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph.fWidth) { 15298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy)); 15308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx += glyph.fAdvanceX; 15328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy += glyph.fAdvanceY; 15338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (underlineWidth) { 15368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com autoCache.release(); // release this now to free up the RAM 15378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com handle_aftertext(this, paint, underlineWidth, underlineStart); 15388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// last parameter is interpreted as SkFixed [x, y] 15428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// return the fixed position, which may be rounded or not by the caller 15438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// e.g. subpixel doesn't round 15448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); 15458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, 15478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIPoint* dst) { 15488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); 15498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, 15528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIPoint* dst) { 15538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1), 15548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1)); 15558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, 15588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIPoint* dst) { 15598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX, 15608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalarToFixed(loc.fY) - glyph.fAdvanceY); 15618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic AlignProc pick_align_proc(SkPaint::Align align) { 15648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static const AlignProc gProcs[] = { 15658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com leftAlignProc, centerAlignProc, rightAlignProc 15668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com }; 15678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs)); 15698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return gProcs[align]; 15718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 15728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass TextMapState { 15748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 15758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mutable SkPoint fLoc; 15768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TextMapState(const SkMatrix& matrix, SkScalar y) 15788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {} 15798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef void (*Proc)(const TextMapState&, const SkScalar pos[]); 15818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Proc pickProc(int scalarsPerPosition); 15838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 15858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& fMatrix; 15868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::MapXYProc fProc; 15878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar fY; // ignored by MapXYProc 15888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // these are only used by Only... procs 15898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar fScaleX, fTransX, fTransformedY; 15908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapXProc(const TextMapState& state, const SkScalar pos[]) { 15928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc); 15938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapXYProc(const TextMapState& state, const SkScalar pos[]) { 15968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc); 15978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 15988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 15998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapOnlyScaleXProc(const TextMapState& state, 16008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar pos[]) { 16018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX, 16028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fTransformedY); 16038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static void MapOnlyTransXProc(const TextMapState& state, 16068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar pos[]) { 16078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.fLoc.set(*pos + state.fTransX, state.fTransformedY); 16088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 16108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comTextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) { 16128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 16138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (1 == scalarsPerPosition) { 16158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned mtype = fMatrix.getType(); 16168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 16178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return MapXProc; 16188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 16198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fScaleX = fMatrix.getScaleX(); 16208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTransX = fMatrix.getTranslateX(); 16218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) + 16228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix.getTranslateY(); 16238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return (mtype & SkMatrix::kScale_Mask) ? 16248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com MapOnlyScaleXProc : MapOnlyTransXProc; 16258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 16278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return MapXYProc; 16288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 16308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////// 16328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawPosText(const char text[], size_t byteLength, 16348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkScalar pos[], SkScalar constY, 16358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scalarsPerPosition, const SkPaint& paint) const { 16368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 16378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 16388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(this->validate();) 16408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 16428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (text == NULL || byteLength == 0 || 16438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip->isEmpty() || 16448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 16458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (/*paint.isLinearText() ||*/ 16498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (fMatrix->getType() & SkMatrix::kPerspective_Mask)) { 16508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TODO !!!! 16518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// this->drawText_asPaths(text, byteLength, x, y, paint); 16528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 16538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 16568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoGlyphCache autoCache(paint, fMatrix); 16578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkGlyphCache* cache = autoCache.getCache(); 16588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 16598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char* stop = text + byteLength; 16618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com AlignProc alignProc = pick_align_proc(paint.getTextAlign()); 16628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw1Glyph d1g; 16638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache); 16648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TextMapState tms(*fMatrix, constY); 16658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); 16668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isSubpixelText()) { 16688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // maybe we should skip the rounding if linearText is set 16698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix); 16708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkPaint::kLeft_Align == paint.getTextAlign()) { 16728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 16738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmsProc(tms, pos); 16748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fx = SkScalarToFixed(tms.fLoc.fX); 16768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fy = SkScalarToFixed(tms.fLoc.fY); 16778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (kRound_Y_Baseline == roundBaseline) { 16798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy = (fy + 0x8000) & ~0xFFFF; 16808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (kRound_X_Baseline == roundBaseline) { 16818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx = (fx + 0x8000) & ~0xFFFF; 16828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); 16858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph.fWidth) { 16878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy)); 16888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos += scalarsPerPosition; 16908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 16918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 16928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 16938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph* glyph = &glyphCacheProc(cache, &text, 0, 0); 16948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph->fWidth) { 16968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(SkFixed prevAdvX = glyph->fAdvanceX;) 16978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;) 16988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 16998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixed fx, fy; 17008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmsProc(tms, pos); 17018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 17038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIPoint fixedLoc; 17048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alignProc(tms.fLoc, *glyph, &fixedLoc); 17058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx = fixedLoc.fX; 17068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy = fixedLoc.fY; 17078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (kRound_Y_Baseline == roundBaseline) { 17098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fy = (fy + 0x8000) & ~0xFFFF; 17108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (kRound_X_Baseline == roundBaseline) { 17118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fx = (fx + 0x8000) & ~0xFFFF; 17128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // have to call again, now that we've been "aligned" 17168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com glyph = &glyphCacheProc(cache, &text, fx, fy); 17178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the assumption is that the advance hasn't changed 17188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(prevAdvX == glyph->fAdvanceX); 17198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(prevAdvY == glyph->fAdvanceY); 17208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(d1g, *glyph, SkFixedFloor(fx), SkFixedFloor(fy)); 17228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos += scalarsPerPosition; 17248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // not subpixel 17278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (text < stop) { 17288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // the last 2 parameters are ignored 17298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 17308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (glyph.fWidth) { 17328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tmsProc(tms, pos); 17338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIPoint fixedLoc; 17358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alignProc(tms.fLoc, glyph, &fixedLoc); 17368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(d1g, glyph, 17388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFixedRound(fixedLoc.fX), SkFixedRound(fixedLoc.fY)); 17398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos += scalarsPerPosition; 17418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if defined _WIN32 && _MSC_VER >= 1300 17468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#pragma warning ( pop ) 17478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 17488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 17508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPathMeasure.h" 17528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void morphpoints(SkPoint dst[], const SkPoint src[], int count, 17548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPathMeasure& meas, const SkMatrix& matrix) { 17558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix::MapXYProc proc = matrix.getMapXYProc(); 17568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 17588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pos; 17598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkVector tangent; 17608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(matrix, src[i].fX, src[i].fY, &pos); 17628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sx = pos.fX; 17638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar sy = pos.fY; 17648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com meas.getPosTan(sx, &pos, &tangent); 17668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* This is the old way (that explains our approach but is way too slow 17688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 17698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint pt; 17708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pt.set(sx, sy); 17728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setSinCos(tangent.fY, tangent.fX); 17738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.preTranslate(-sx, 0); 17748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.postTranslate(pos.fX, pos.fY); 17758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.mapPoints(&dst[i], &pt, 1); 17768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 17778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy), 17788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pos.fY + SkScalarMul(tangent.fX, sy)); 17798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 17808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 17818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* TODO 17838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Need differentially more subdivisions when the follow-path is curvy. Not sure how to 17858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com determine that, but we need it. I guess a cheap answer is let the caller tell us, 17868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out. 17878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 17888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas, 17898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkMatrix& matrix) { 17908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Iter iter(src, false); 17918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint srcP[4], dstP[3]; 17928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath::Verb verb; 17938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 17948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) { 17958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (verb) { 17968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kMove_Verb: 17978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, srcP, 1, meas, matrix); 17988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->moveTo(dstP[0]); 17998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 18008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kLine_Verb: 18018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // turn lines into quads to look bendy 18028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX); 18038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY); 18048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, srcP, 2, meas, matrix); 18058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->quadTo(dstP[0], dstP[1]); 18068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 18078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kQuad_Verb: 18088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, &srcP[1], 2, meas, matrix); 18098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->quadTo(dstP[0], dstP[1]); 18108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 18118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kCubic_Verb: 18128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpoints(dstP, &srcP[1], 3, meas, matrix); 18138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->cubicTo(dstP[0], dstP[1], dstP[2]); 18148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 18158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkPath::kClose_Verb: 18168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst->close(); 18178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 18188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 18198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(!"unknown verb"); 18208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 18218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawTextOnPath(const char text[], size_t byteLength, 18268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath& follow, const SkMatrix* matrix, 18278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 18288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(byteLength == 0 || text != NULL); 18298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // nothing to draw 18318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (text == NULL || byteLength == 0 || 18328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fClip->isEmpty() || 18338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 18348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 18358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTextToPathIter iter(text, byteLength, paint, true, true); 18388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPathMeasure meas(follow, false); 18398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar hOffset = 0; 18408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to measure first 18428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() != SkPaint::kLeft_Align) { 18438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar pathLen = meas.getLength(); 18448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getTextAlign() == SkPaint::kCenter_Align) { 18458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathLen = SkScalarHalf(pathLen); 18468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com hOffset += pathLen; 18488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPath* iterPath; 18518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar xpos; 18528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix scaledMatrix; 18538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar scale = iter.getPathScale(); 18548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scaledMatrix.setScale(scale, scale); 18568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while ((iterPath = iter.next(&xpos)) != NULL) { 18588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPath tmp; 18598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m(scaledMatrix); 18608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.postTranslate(xpos + hOffset, 0); 18628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (matrix) { 18638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.postConcat(*matrix); 18648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com morphpath(&tmp, *iterPath, meas, m); 18668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com this->drawPath(tmp, iter.getPaint()); 18678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 18698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 18718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstruct VertState { 18738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int f0, f1, f2; 18748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState(int vCount, const uint16_t indices[], int indexCount) 18768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : fIndices(indices) { 18778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCurrIndex = 0; 18788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (indices) { 18798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCount = indexCount; 18808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 18818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fCount = vCount; 18828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 18848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef bool (*Proc)(VertState*); 18868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Proc chooseProc(SkCanvas::VertexMode mode); 18878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 18898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fCount; 18908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int fCurrIndex; 18918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* fIndices; 18928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 18938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool Triangles(VertState*); 18948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TrianglesX(VertState*); 18958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleStrip(VertState*); 18968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleStripX(VertState*); 18978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleFan(VertState*); 18988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static bool TriangleFanX(VertState*); 18998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 19008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::Triangles(VertState* state) { 19028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 19038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 19048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 19058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = index + 0; 19078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 1; 19088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = index + 2; 19098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 3; 19108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 19118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TrianglesX(VertState* state) { 19148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* indices = state->fIndices; 19158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 19168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 19178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 19188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[index + 0]; 19208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 1]; 19218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = indices[index + 2]; 19228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 3; 19238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 19248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleStrip(VertState* state) { 19278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 19288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 19298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 19308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = index + 2; 19328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index & 1) { 19338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = index + 1; 19348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 0; 19358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 19368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = index + 0; 19378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 1; 19388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 19408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 19418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleStripX(VertState* state) { 19448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* indices = state->fIndices; 19458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 19468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 19478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 19488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = indices[index + 2]; 19508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index & 1) { 19518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[index + 1]; 19528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 0]; 19538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 19548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[index + 0]; 19558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 1]; 19568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 19588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 19598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleFan(VertState* state) { 19628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 19638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 19648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 19658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = 0; 19678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = index + 1; 19688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = index + 2; 19698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 19708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 19718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool VertState::TriangleFanX(VertState* state) { 19748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t* indices = state->fIndices; 19758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index = state->fCurrIndex; 19768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (index + 3 > state->fCount) { 19778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 19788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f0 = indices[0]; 19808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f1 = indices[index + 1]; 19818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->f2 = indices[index + 2]; 19828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state->fCurrIndex = index + 1; 19838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 19848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comVertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) { 19878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com switch (mode) { 19888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kTriangles_VertexMode: 19898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fIndices ? TrianglesX : Triangles; 19908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kTriangleStrip_VertexMode: 19918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fIndices ? TriangleStripX : TriangleStrip; 19928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com case SkCanvas::kTriangleFan_VertexMode: 19938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fIndices ? TriangleFanX : TriangleFan; 19948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com default: 19958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 19968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 19978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 19988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 19998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comtypedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRegion*, 20008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitter*); 20018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic HairProc ChooseHairProc(bool doAntiAlias) { 20038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 20048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool texture_to_matrix(const VertState& state, const SkPoint verts[], 20078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint texs[], SkMatrix* matrix) { 20088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src[3], dst[3]; 20098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[0] = texs[state.f0]; 20118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[1] = texs[state.f1]; 20128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com src[2] = texs[state.f2]; 20138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[0] = verts[state.f0]; 20148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[1] = verts[state.f1]; 20158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[2] = verts[state.f2]; 20168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return matrix->setPolyToPoly(src, dst, 3); 20178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass SkTriColorShader : public SkShader { 20208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic: 20218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTriColorShader() {} 20228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 20248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count); 20268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprotected: 20288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {} 20298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com virtual Factory getFactory() { return CreateProc; } 20318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comprivate: 20338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix fDstToUnit; 20348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor fColors[3]; 20358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 20378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkNEW_ARGS(SkTriColorShader, (buffer)); 20388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com typedef SkShader INHERITED; 20408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}; 20418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[], 20438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int index0, int index1, int index2) { 20448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[0] = SkPreMultiplyColor(colors[index0]); 20468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[1] = SkPreMultiplyColor(colors[index1]); 20478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColors[2] = SkPreMultiplyColor(colors[index2]); 20488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix m, im; 20508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.reset(); 20518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(0, pts[index1].fX - pts[index0].fX); 20528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(1, pts[index2].fX - pts[index0].fX); 20538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(2, pts[index0].fX); 20548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(3, pts[index1].fY - pts[index0].fY); 20558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(4, pts[index2].fY - pts[index0].fY); 20568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com m.set(5, pts[index0].fY); 20578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!m.invert(&im)) { 20588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 20598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return fDstToUnit.setConcat(im, this->getTotalInverse()); 20618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 2064689411a87ca7d19abe04b5c9baff26bd96b2123ereed@android.com#include "SkComposeShader.h" 20658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int ScalarTo256(SkScalar v) { 20678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale = SkScalarToFixed(v) >> 8; 20688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale < 0) { 20698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale = 0; 20708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale > 255) { 20728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale = 255; 20738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkAlpha255To256(scale); 20758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 20768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 20788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint src; 20798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = 0; i < count; i++) { 20818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); 20828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += 1; 20838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale1 = ScalarTo256(src.fX); 20858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale2 = ScalarTo256(src.fY); 20868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int scale0 = 256 - scale1 - scale2; 20878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale0 < 0) { 20888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (scale1 > scale2) { 20898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale2 = 256 - scale1; 20908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 20918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale1 = 256 - scale2; 20928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale0 = 0; 20948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 20958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 20968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 20978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlphaMulQ(fColors[1], scale1) + 20988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlphaMulQ(fColors[2], scale2); 20998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 21018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, 21038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPoint vertices[], const SkPoint textures[], 21048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkColor colors[], SkXfermode* xmode, 21058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint16_t indices[], int indexCount, 21068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) const { 21078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(0 == count || NULL != vertices); 21088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // abort early if there is nothing to draw 21108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count < 3 || (indices && indexCount < 3) || fClip->isEmpty() || 21118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 21128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 21138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // transform out vertices into device coordinates 21168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoSTMalloc<16, SkPoint> storage(count); 21178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPoint* devVerts = storage.get(); 21188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fMatrix->mapPoints(devVerts, vertices, count); 21198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fBounder) { 21218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRect bounds; 21228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.set(devVerts, count); 21238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fBounder->doRect(bounds, paint)) { 21248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 21258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com /* 21298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com We can draw the vertices in 1 of 4 ways: 21308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - solid color (no shader/texture[], no colors[]) 21328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just colors (no shader/texture[], has colors[]) 21338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - just texture (has shader/texture[], no colors[]) 21348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com - colors * texture (has shader/texture[], has colors[]) 21358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com Thus for texture drawing, we need both texture[] and a shader. 21378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */ 21388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTriColorShader triShader; // must be above declaration of p 21408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint p(paint); 21418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = p.getShader(); 21438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == shader) { 21448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we have no shader, we ignore the texture coordinates 21458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com textures = NULL; 21468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (NULL == textures) { 21478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we don't have texture coordinates, ignore the shader 21488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setShader(NULL); 21498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader = NULL; 21508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup the custom shader (if needed) 21538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != colors) { 21548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == textures) { 21558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // just colors (no texture) 21568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setShader(&triShader); 21578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 21588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // colors * texture 21598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(shader); 21608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool releaseMode = false; 21618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL == xmode) { 2162845fdaca174f4675e9acc164b510e3a5ffa9053creed@android.com xmode = SkXfermode::Create(SkXfermode::kMultiply_Mode); 21638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com releaseMode = true; 21648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* compose = SkNEW_ARGS(SkComposeShader, 21668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (&triShader, shader, xmode)); 21678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com p.setShader(compose)->unref(); 21688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (releaseMode) { 21698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com xmode->unref(); 21708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); 21758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // setup our state and function pointer for iterating triangles 21768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState state(count, indices, indexCount); 21778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com VertState::Proc vertProc = state.chooseProc(vmode); 21788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != textures || NULL != colors) { 21808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix localM, tempM; 21818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bool hasLocalM = shader && shader->getLocalMatrix(&localM); 21828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != colors) { 21848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!triShader.setContext(*fBitmap, p, *fMatrix)) { 21858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com colors = NULL; 21868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 21898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 21908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != textures) { 21918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (texture_to_matrix(state, vertices, textures, &tempM)) { 21928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (hasLocalM) { 21938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com tempM.postConcat(localM); 21948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 21958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->setLocalMatrix(tempM); 21968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // need to recal setContext since we changed the local matrix 21978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!shader->setContext(*fBitmap, p, *fMatrix)) { 21988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 21998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != colors) { 22038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!triShader.setup(vertices, colors, 22048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com state.f0, state.f1, state.f2)) { 22058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 22068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScan::FillTriangle(devVerts[state.f0], devVerts[state.f1], 22098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com devVerts[state.f2], fClip, blitter.get()); 22108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // now restore the shader's original local matrix 22128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (NULL != shader) { 22138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (hasLocalM) { 22148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->setLocalMatrix(localM); 22158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 22168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->resetLocalMatrix(); 22178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 22208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // no colors[] and no texture 22218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); 22228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (vertProc(&state)) { 22238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com hairProc(devVerts[state.f0], devVerts[state.f1], fClip, blitter.get()); 22248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com hairProc(devVerts[state.f1], devVerts[state.f2], fClip, blitter.get()); 22258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com hairProc(devVerts[state.f2], devVerts[state.f0], fClip, blitter.get()); 22268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////// 22318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////// 22328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_DEBUG 22348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkDraw::validate() const { 22368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fBitmap != NULL); 22378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fMatrix != NULL); 22388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fClip != NULL); 22398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& cr = fClip->getBounds(); 22418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect br; 22428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com br.set(0, 0, fBitmap->width(), fBitmap->height()); 22448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(cr.isEmpty() || br.contains(cr)); 22458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 22488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////// 22508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doIRect(const SkIRect& r) { 22528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect rr; 22538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr); 22548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2256d055c1fde2128514167b315f4d104b177e04a3dereed@android.com// TODO: change the prototype to take fixed, and update the callers 2257d055c1fde2128514167b315f4d104b177e04a3dereed@android.combool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y, 2258d055c1fde2128514167b315f4d104b177e04a3dereed@android.com const SkGlyph& glyph) { 2259474a12c4976b3000174cad5df74c498cd723c5e2reed@android.com SkIRect rr; 2260d055c1fde2128514167b315f4d104b177e04a3dereed@android.com if (!rr.intersect(fClip->getBounds(), r)) { 2261d055c1fde2128514167b315f4d104b177e04a3dereed@android.com return false; 2262d055c1fde2128514167b315f4d104b177e04a3dereed@android.com } 2263d055c1fde2128514167b315f4d104b177e04a3dereed@android.com GlyphRec rec; 2264d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y)); 2265d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX, 2266d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fLSB.fY + glyph.fAdvanceY); 2267d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fGlyphID = glyph.getGlyphID(); 2268d055c1fde2128514167b315f4d104b177e04a3dereed@android.com rec.fFlags = 0; 2269d055c1fde2128514167b315f4d104b177e04a3dereed@android.com return this->onIRectGlyph(rr, rec); 2270474a12c4976b3000174cad5df74c498cd723c5e2reed@android.com} 2271474a12c4976b3000174cad5df74c498cd723c5e2reed@android.com 22728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1, 22738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) { 22748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect r; 22758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkScalar v0, v1; 22768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v0 = pt0.fX; 22788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v1 = pt1.fX; 22798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (v0 > v1) { 22808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<SkScalar>(v0, v1); 22818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fLeft = SkScalarFloor(v0); 22838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fRight = SkScalarCeil(v1); 22848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v0 = pt0.fY; 22868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com v1 = pt1.fY; 22878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (v0 > v1) { 22888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap<SkScalar>(v0, v1); 22898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fTop = SkScalarFloor(v0); 22918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.fBottom = SkScalarCeil(v1); 22928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 22948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.inset(-1, -1); 22958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 22968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->doIRect(r); 22978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 22988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 22998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) { 23008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect r; 23018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.getStyle() == SkPaint::kFill_Style) { 23038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rect.round(&r); 23048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 23058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int rad = -1; 23068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rect.roundOut(&r); 23078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 23088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com rad = -2; 23098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.inset(rad, rad); 23118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->doIRect(r); 23138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) { 2316d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkIRect r; 2317d252db03d9650013b545ef9781fe993c07f8f314reed@android.com const SkRect& bounds = path.getBounds(); 23188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (doFill) { 23208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.round(&r); 23218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // hairline 23228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bounds.roundOut(&r); 23238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isAntiAlias()) { 23268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com r.inset(-1, -1); 23278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return this->doIRect(r); 23298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkBounder::commit() { 23328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // override in subclass 23338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////////////////////// 23368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPath.h" 23388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDraw.h" 23398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRegion.h" 23408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitter.h" 23418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 23438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMaskFilter* filter, const SkMatrix* filterMatrix, 23448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect* bounds) { 23458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (devPath.isEmpty()) { 23468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 23478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIPoint margin; 23508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com margin.set(0, 0); 23518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // init our bounds from the path 23538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com { 2354d252db03d9650013b545ef9781fe993c07f8f314reed@android.com SkRect pathBounds = devPath.getBounds(); 23558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf); 23568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com pathBounds.roundOut(bounds); 23578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (filter) { 23608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(filterMatrix); 23618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask srcM, dstM; 23638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fBounds = *bounds; 23658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fFormat = SkMask::kA8_Format; 23668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com srcM.fImage = NULL; 23678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 23688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 23698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *bounds = dstM.fBounds; 23718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clipBounds && !SkIRect::Intersects(*clipBounds, *bounds)) { 23748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 23758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (possibly) trim the srcM bounds to reflect the clip 23788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (plus whatever slop the filter needs) 23798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (clipBounds && !clipBounds->contains(*bounds)) { 23808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkIRect tmp = *bounds; 23818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)tmp.intersect(*clipBounds); 23823555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // Ugh. Guard against gigantic margins from wacky filters. Without this 23833555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // check we can request arbitrary amounts of slop beyond our visible 23843555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // clip, and bring down the renderer (at least on finite RAM machines 23853555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // like handsets, etc.). Need to balance this invented value between 23863555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // quality of large filters like blurs, and the corresponding memory 23873555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com // requests. 23883555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com static const int MAX_MARGIN = 128; 23893555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com tmp.inset(-SkMin32(margin.fX, MAX_MARGIN), 23903555591c158c242b071c7ec92ad75b6e4cb74af2reed@android.com -SkMin32(margin.fY, MAX_MARGIN)); 23918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com (void)bounds->intersect(tmp); 23928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 23938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 23958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 23968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 23978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic void draw_into_mask(const SkMask& mask, const SkPath& devPath) { 23988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap bm; 23998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkDraw draw; 24008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRegion clipRgn; 24018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMatrix matrix; 24028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPaint paint; 24038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes); 24058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com bm.setPixels(mask.fImage); 24068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com clipRgn.setRect(0, 0, mask.fBounds.width(), mask.fBounds.height()); 24088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 24098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com -SkIntToScalar(mask.fBounds.fTop)); 24108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fBitmap = &bm; 24128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fClip = &clipRgn; 24138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fMatrix = &matrix; 24148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.fBounder = NULL; 24158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com paint.setAntiAlias(true); 24168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw.drawPath(devPath, paint); 24178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 24188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.combool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 24208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMaskFilter* filter, const SkMatrix* filterMatrix, 24218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkMask* mask, SkMask::CreateMode mode) { 24228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustRenderImage_CreateMode != mode) { 24238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 24248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return false; 24258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 24268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 24288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fFormat = SkMask::kA8_Format; 24298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mask->fRowBytes = mask->fBounds.width(); 2430543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com size_t size = mask->computeImageSize(); 2431543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com if (0 == size) { 2432543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com // we're too big to allocate the mask, abort 2433543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com return false; 2434543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com } 2435543ed9352c7dfd93071c08b14930cca2e82a08d4reed@android.com mask->fImage = SkMask::AllocImage(size); 24368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(mask->fImage, 0, mask->computeImageSize()); 24378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 24388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (SkMask::kJustComputeBounds_CreateMode != mode) { 24408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com draw_into_mask(*mask, devPath); 24418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 24428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 24438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return true; 24448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2445