11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/* 31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project 41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * 51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be 61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file. 71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDraw.h" 110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlitter.h" 120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBounder.h" 130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkCanvas.h" 140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h" 150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDevice.h" 164f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkFixed.h" 170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkMaskFilter.h" 180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPaint.h" 190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathEffect.h" 201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkRasterClip.h" 210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRasterizer.h" 220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScan.h" 230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkShader.h" 240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkStroke.h" 250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkTemplatesPriv.h" 261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkTLazy.h" 270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkUtils.h" 280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkAutoKern.h" 300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmapProcShader.h" 310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDrawProcs.h" 320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//#define TRACE_BITMAP_DRAWS 340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define kBlitterStorageLongCount (sizeof(SkBitmapProcShader) >> 2) 360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 37df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger/** Helper for allocating small blitters on the stack. 38df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger */ 39df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenbergerclass SkAutoBlitterChoose : SkNoncopyable { 400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 41df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkAutoBlitterChoose() { 42df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger fBlitter = NULL; 43df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger } 440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix, 450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint) { 460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fBlitter = SkBlitter::Choose(device, matrix, paint, 470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStorage, sizeof(fStorage)); 480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 49df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ~SkAutoBlitterChoose(); 510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter* operator->() { return fBlitter; } 530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter* get() const { return fBlitter; } 540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 55df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger void choose(const SkBitmap& device, const SkMatrix& matrix, 56df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger const SkPaint& paint) { 57df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkASSERT(!fBlitter); 58df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger fBlitter = SkBlitter::Choose(device, matrix, paint, 59df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger fStorage, sizeof(fStorage)); 60df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger } 61df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter* fBlitter; 640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t fStorage[kBlitterStorageLongCount]; 650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkAutoBlitterChoose::~SkAutoBlitterChoose() { 680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if ((void*)fBlitter == (void*)fStorage) { 690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fBlitter->~SkBlitter(); 700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDELETE(fBlitter); 720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 75df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger/** 76df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger * Since we are providing the storage for the shader (to avoid the perf cost 77df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger * of calling new) we insist that in our destructor we can account for all 78df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger * owners of the shader. 79df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger */ 80df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenbergerclass SkAutoBitmapShaderInstall : SkNoncopyable { 810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 82df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint) 83df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger : fPaint(paint) /* makes a copy of the paint */ { 84df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger fPaint.setShader(SkShader::CreateBitmapShader(src, 850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkShader::kClamp_TileMode, SkShader::kClamp_TileMode, 860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fStorage, sizeof(fStorage))); 87df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger // we deliberately left the shader with an owner-count of 2 88df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkASSERT(2 == fPaint.getShader()->getRefCnt()); 890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ~SkAutoBitmapShaderInstall() { 92df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkShader* shader = fPaint.getShader(); 93df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger // since we manually destroy shader, we insist that owners == 2 94df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkASSERT(2 == shader->getRefCnt()); 950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 96df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger fPaint.setShader(NULL); // unref the shader by 1 970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 98df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger // now destroy to take care of the 2nd owner-count 990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if ((void*)shader == (void*)fStorage) { 1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shader->~SkShader(); 1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDELETE(shader); 1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 106df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger // return the new paint that has the shader applied 107df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger const SkPaint& paintWithShader() const { return fPaint; } 10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 110df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkPaint fPaint; // copy of caller's paint (which we then modify) 111df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger uint32_t fStorage[kBlitterStorageLongCount]; 1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek SollenbergerSkDraw::SkDraw() { 11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger sk_bzero(this, sizeof(*this)); 11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger} 11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkDraw::SkDraw(const SkDraw& src) { 1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memcpy(this, &src, sizeof(*this)); 1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttypedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); 1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) { 129a8c52de60de1d2471206b3c81e9243e2c76f2edbMike Reed sk_bzero(pixels, bytes); 1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {} 1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_memset32((uint32_t*)pixels, data, bytes >> 2); 1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sk_memset16((uint16_t*)pixels, data, bytes >> 1); 1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(pixels, data, bytes); 1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap, 1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint, 1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t* data) { 1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // todo: we can apply colorfilter up front if no shader, so we wouldn't 1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need to abort this fastpath 1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getShader() || paint.getColorFilter()) { 1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return NULL; 1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15559f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed SkXfermode::Mode mode; 1561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { 1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return NULL; 1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkColor color = paint.getColor(); 16140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // collaps modes based on color... 16359f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed if (SkXfermode::kSrcOver_Mode == mode) { 1640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned alpha = SkColorGetA(color); 1650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (0 == alpha) { 16659f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed mode = SkXfermode::kDst_Mode; 1670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else if (0xFF == alpha) { 16859f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed mode = SkXfermode::kSrc_Mode; 1690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 17140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (mode) { 17359f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed case SkXfermode::kClear_Mode: 1740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// SkDebugf("--- D_Clear_BitmapXferProc\n"); 1750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return D_Clear_BitmapXferProc; // ignore data 17659f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed case SkXfermode::kDst_Mode: 1770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// SkDebugf("--- D_Dst_BitmapXferProc\n"); 1780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return D_Dst_BitmapXferProc; // ignore data 17959f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed case SkXfermode::kSrc_Mode: { 1800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* 18140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger should I worry about dithering for the lower depths? 1820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 1830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPMColor pmc = SkPreMultiplyColor(color); 1840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (bitmap.config()) { 1850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kARGB_8888_Config: 1860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (data) { 1870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *data = pmc; 1880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// SkDebugf("--- D32_Src_BitmapXferProc\n"); 1900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return D32_Src_BitmapXferProc; 1910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kARGB_4444_Config: 1920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (data) { 1930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *data = SkPixel32ToPixel4444(pmc); 1940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// SkDebugf("--- D16_Src_BitmapXferProc\n"); 1960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return D16_Src_BitmapXferProc; 1970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kRGB_565_Config: 1980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (data) { 1990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *data = SkPixel32ToPixel16(pmc); 2000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// SkDebugf("--- D16_Src_BitmapXferProc\n"); 2020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return D16_Src_BitmapXferProc; 2030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kA8_Config: 2040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (data) { 2050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project *data = SkGetPackedA32(pmc); 2060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// SkDebugf("--- DA8_Src_BitmapXferProc\n"); 2080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return DA8_Src_BitmapXferProc; 2090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return NULL; 2180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect, 2210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project BitmapXferProc proc, uint32_t procData) { 2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int shiftPerPixel; 2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (bitmap.config()) { 2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kARGB_8888_Config: 2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shiftPerPixel = 2; 2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kARGB_4444_Config: 2280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kRGB_565_Config: 2290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shiftPerPixel = 1; 2300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkBitmap::kA8_Config: 2320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shiftPerPixel = 0; 2330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 2340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 2351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("Can't use xferproc on this config"); 2360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint8_t* pixels = (uint8_t*)bitmap.getPixels(); 2400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(pixels); 2410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const size_t rowBytes = bitmap.rowBytes(); 2420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const int widthBytes = rect.width() << shiftPerPixel; 2430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // skip down to the first scanline and X position 2450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel); 2460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int scans = rect.height() - 1; scans >= 0; --scans) { 2470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc(pixels, widthBytes, procData); 2480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pixels += rowBytes; 2490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawPaint(const SkPaint& paint) const { 2530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 2540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isEmpty()) { 2560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect devRect; 2600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project devRect.set(0, 0, fBitmap->width(), fBitmap->height()); 2610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBounder && !fBounder->doIRect(devRect)) { 2620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 2630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 26440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isBW()) { 2661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger /* If we don't have a shader (i.e. we're just a solid color) we may 2671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger be faster to operate directly on the device bitmap, rather than invoking 2681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger a blitter. Esp. true for xfermodes, which require a colorshader to be 2691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger present, which is just redundant work. Since we're drawing everywhere 2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger in the clip, we don't have to worry about antialiasing. 2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */ 2721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger uint32_t procData = 0; // to avoid the warning 2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData); 2741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (proc) { 2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (D_Dst_BitmapXferProc == proc) { // nothing to do 2761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 2771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 27840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 2791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkRegion::Iterator iter(fRC->bwRgn()); 2801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger while (!iter.done()) { 2811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData); 2821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger iter.next(); 2831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 2841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 2850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 2871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 2881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // normal case: use a blitter 2891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 2901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::FillIRect(devRect, *fRC, blitter.get()); 2910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 2940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 2950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstruct PtProcRec { 2960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkCanvas::PointMode fMode; 2970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint* fPaint; 2980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkRegion* fClip; 2991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRasterClip* fRC; 30040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // computed values 3020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed fRadius; 30340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, 3050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter*); 3060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix, 3081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRasterClip*); 3091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger Proc chooseProc(SkBlitter** blitter); 3101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 3111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerprivate: 3121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitterWrapper fWrapper; 3130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 3140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(rec.fClip->isRect()); 3180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkIRect& r = rec.fClip->getBounds(); 31940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 3210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int x = SkScalarFloor(devPts[i].fX); 3220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int y = SkScalarFloor(devPts[i].fY); 3230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (r.contains(x, y)) { 3240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitH(x, y, 1); 3250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void bw_pt_rect_16_hair_proc(const PtProcRec& rec, 3300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint devPts[], int count, 3310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter* blitter) { 3321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(rec.fRC->isRect()); 3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkIRect& r = rec.fRC->getBounds(); 3340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t value; 3350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value); 3360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(bitmap); 33740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 3380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint16_t* addr = bitmap->getAddr16(0, 0); 3390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int rb = bitmap->rowBytes(); 3400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 3420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int x = SkScalarFloor(devPts[i].fX); 3430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int y = SkScalarFloor(devPts[i].fY); 3440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (r.contains(x, y)) { 3450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// *bitmap->getAddr16(x, y) = SkToU16(value); 3460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value); 3470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 3530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 3540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int x = SkScalarFloor(devPts[i].fX); 3550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int y = SkScalarFloor(devPts[i].fY); 3560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (rec.fClip->contains(x, y)) { 3570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project blitter->blitH(x, y, 1); 3580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 3640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i += 2) { 3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 3660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 3710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count - 1; i++) { 3721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 3730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// aa versions 3770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 3800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i += 2) { 3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 3820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 3860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 3870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count - 1; i++) { 3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 3890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 3900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 3910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 3930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 3940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 3950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 3960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkFixed radius = rec.fRadius; 3970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 3980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed x = SkScalarToFixed(devPts[i].fX); 3990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed y = SkScalarToFixed(devPts[i].fY); 40040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkXRect r; 4020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fLeft = x - radius; 4030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fTop = y - radius; 4040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fRight = x + radius; 4050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fBottom = y + radius; 40640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::FillXRect(r, *rec.fRC, blitter); 4080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 4120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int count, SkBlitter* blitter) { 4130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkFixed radius = rec.fRadius; 4140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 4150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed x = SkScalarToFixed(devPts[i].fX); 4160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed y = SkScalarToFixed(devPts[i].fY); 41740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkXRect r; 4190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fLeft = x - radius; 4200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fTop = y - radius; 4210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fRight = x + radius; 4220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fBottom = y + radius; 42340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::AntiFillXRect(r, *rec.fRC, blitter); 4250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 428a9e3ccf51a8b974637e81010ca73fabd3761833fMike Reed// If this guy returns true, then chooseProc() must return a valid proc 4290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 4301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkMatrix* matrix, const SkRasterClip* rc) { 4310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getPathEffect()) { 4320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 4330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar width = paint.getStrokeWidth(); 4350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (0 == width) { 4360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMode = mode; 4370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPaint = &paint; 4381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClip = NULL; 4391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fRC = rc; 4400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fRadius = SK_Fixed1 >> 1; 4410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 4420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 443a9e3ccf51a8b974637e81010ca73fabd3761833fMike Reed if (paint.getStrokeCap() != SkPaint::kRound_Cap && 444a9e3ccf51a8b974637e81010ca73fabd3761833fMike Reed matrix->rectStaysRect() && SkCanvas::kPoints_PointMode == mode) { 4450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sx = matrix->get(SkMatrix::kMScaleX); 4460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sy = matrix->get(SkMatrix::kMScaleY); 4470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkScalarNearlyZero(sx - sy)) { 4480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (sx < 0) { 4490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project sx = -sx; 4500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMode = mode; 4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fPaint = &paint; 4541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClip = NULL; 4551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fRC = rc; 4560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1; 4570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 4580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 4610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 4620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4631cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerPtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { 464a9e3ccf51a8b974637e81010ca73fabd3761833fMike Reed Proc proc = NULL; 46540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 4661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkBlitter* blitter = *blitterPtr; 4671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isBW()) { 4681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClip = &fRC->bwRgn(); 4691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 4701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fWrapper.init(*fRC, blitter); 4711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClip = &fWrapper.getRgn(); 4721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = fWrapper.getBlitter(); 4731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *blitterPtr = blitter; 4741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 4751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 4760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // for our arrays 4770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(0 == SkCanvas::kPoints_PointMode); 4780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(1 == SkCanvas::kLines_PointMode); 4790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(2 == SkCanvas::kPolygon_PointMode); 4800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 4810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 4820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // first check for hairlines 4830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (0 == fPaint->getStrokeWidth()) { 4840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fPaint->isAntiAlias()) { 4850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static const Proc gAAProcs[] = { 4860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 4870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project }; 4880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc = gAAProcs[fMode]; 4890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 4900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 4910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t value; 4920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkBitmap* bm = blitter->justAnOpaqueColor(&value); 4930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bm && bm->config() == SkBitmap::kRGB_565_Config) { 4940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc = bw_pt_rect_16_hair_proc; 4950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 4960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc = bw_pt_rect_hair_proc; 4970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 4980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 4990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static Proc gBWProcs[] = { 5000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 5010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project }; 5020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc = gBWProcs[fMode]; 5030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 505a9e3ccf51a8b974637e81010ca73fabd3761833fMike Reed } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 5060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(SkCanvas::kPoints_PointMode == fMode); 5070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fPaint->isAntiAlias()) { 5080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc = aa_square_proc; 5090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 5100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc = bw_square_proc; 5110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return proc; 5140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode, 5170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t count, const SkPoint pts[], 5180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint, const SkMatrix& matrix) { 5190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect ibounds; 5200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect bounds; 5210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar inset = paint.getStrokeWidth(); 5220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds.set(pts, count); 5240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds.inset(-inset, -inset); 5250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.mapRect(&bounds); 5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds.roundOut(&ibounds); 5280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return bounder->doIRect(ibounds); 5290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 5300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// each of these costs 8-bytes of stack space, so don't make it too large 5320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// must be even for lines/polygon to work 5330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define MAX_DEV_PTS 32 5340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 53640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const SkPoint pts[], const SkPaint& paint, 53740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger bool forceUseDevice) const { 5380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // if we're in lines mode, force count to be even 5390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkCanvas::kLines_PointMode == mode) { 5400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project count &= ~(size_t)1; 5410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if ((long)count <= 0) { 5440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 5450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 54640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(pts != NULL); 5480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 54940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 5511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isEmpty()) { 5520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 5530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 555df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (fBounder) { 556df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) { 557df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger return; 558df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger } 559df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 560df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger // clear the bounder and call this again, so we don't invoke the bounder 561df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger // later if we happen to call ourselves for drawRect, drawPath, etc. 562df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkDraw noBounder(*this); 563df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger noBounder.fBounder = NULL; 564df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger noBounder.drawPoints(mode, count, pts, paint, forceUseDevice); 565df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger return; 566df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger } 567df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 5680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project PtProcRec rec; 5691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) { 5700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 5710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 5720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint devPts[MAX_DEV_PTS]; 5730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkMatrix* matrix = fMatrix; 5740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter* bltr = blitter.get(); 5751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger PtProcRec::Proc proc = rec.chooseProc(&bltr); 5760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // we have to back up subsequent passes if we're in polygon mode 5770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 57840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 5790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project do { 5800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t n = count; 5810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (n > MAX_DEV_PTS) { 5820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project n = MAX_DEV_PTS; 5830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix->mapPoints(devPts, pts, n); 5850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc(rec, devPts, n, bltr); 5860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pts += n - backup; 5870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(count >= n); 5880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project count -= n; 5890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (count > 0) { 5900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project count += backup; 5910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 5920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } while (count != 0); 5930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 5940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (mode) { 5950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkCanvas::kPoints_PointMode: { 5960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // temporarily mark the paint as filling. 597df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkPaint newPaint(paint); 598df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger newPaint.setStyle(SkPaint::kFill_Style); 5990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 600df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkScalar width = newPaint.getStrokeWidth(); 6010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar radius = SkScalarHalf(width); 60240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 603df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) { 6040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath path; 6050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix preMatrix; 60640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.addCircle(0, 0, radius); 6080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (size_t i = 0; i < count; i++) { 6090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project preMatrix.setTranslate(pts[i].fX, pts[i].fY); 6100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // pass true for the last point, since we can modify 6110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // then path then 61240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fDevice) { 613df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger fDevice->drawPath(*this, path, newPaint, &preMatrix, 61440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger (count-1) == i); 61540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 616df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger this->drawPath(path, newPaint, &preMatrix, 617df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger (count-1) == i); 61840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 6190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 6210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect r; 62240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 6230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (size_t i = 0; i < count; i++) { 6240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fLeft = pts[i].fX - radius; 6250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fTop = pts[i].fY - radius; 6260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fRight = r.fLeft + width; 6270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fBottom = r.fTop + width; 62840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fDevice) { 629df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger fDevice->drawRect(*this, r, newPaint); 63040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 631df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger this->drawRect(r, newPaint); 63240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 6330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 6360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkCanvas::kLines_PointMode: 6380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkCanvas::kPolygon_PointMode: { 6390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project count -= 1; 6400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath path; 6410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPaint p(paint); 6420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project p.setStyle(SkPaint::kStroke_Style); 6430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 6440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (size_t i = 0; i < count; i += inc) { 6450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.moveTo(pts[i]); 6460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.lineTo(pts[i+1]); 64740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fDevice) { 64840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fDevice->drawPath(*this, path, p, NULL, true); 64940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 65040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->drawPath(path, p, NULL, true); 65140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 6520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project path.rewind(); 6530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 6550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 6580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkPoint* as_lefttop(SkRect* r) { 6610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (SkPoint*)(void*)r; 6620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 6640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline SkPoint* as_rightbottom(SkRect* r) { 6650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return ((SkPoint*)(void*)r) + 1; 6660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 6670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 66887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenbergerstatic bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, 66987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkPoint* strokeSize) { 67087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (SkPaint::kMiter_Join != paint.getStrokeJoin() || 67187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger paint.getStrokeMiter() < SK_ScalarSqrt2) { 67287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger return false; 67387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 67487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 67587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkASSERT(matrix.rectStaysRect()); 67687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; 67787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger matrix.mapVectors(strokeSize, &pt, 1); 67887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger strokeSize->fX = SkScalarAbs(strokeSize->fX); 67987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger strokeSize->fY = SkScalarAbs(strokeSize->fY); 68087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger return true; 68187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger} 68287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 68387b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, 68487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger const SkMatrix& matrix, 68587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkPoint* strokeSize) { 68687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger RectType rtype; 68787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger const SkScalar width = paint.getStrokeWidth(); 68887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger const bool zeroWidth = (0 == width); 68987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkPaint::Style style = paint.getStyle(); 69087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 69187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { 69287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger style = SkPaint::kFill_Style; 69387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 69487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 69587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (paint.getPathEffect() || paint.getMaskFilter() || 69687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger paint.getRasterizer() || !matrix.rectStaysRect() || 69787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkPaint::kStrokeAndFill_Style == style) { 69887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger rtype = kPath_RectType; 69987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } else if (SkPaint::kFill_Style == style) { 70087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger rtype = kFill_RectType; 70187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } else if (zeroWidth) { 70287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger rtype = kHair_RectType; 70387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } else if (easy_rect_join(paint, matrix, strokeSize)) { 70487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger rtype = kStroke_RectType; 70587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } else { 70687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger rtype = kPath_RectType; 70787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 70887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger return rtype; 70987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger} 71087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 711df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenbergerstatic SkPoint* rect_points(SkRect& r, int index) { 712df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkASSERT((unsigned)index < 2); 713df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger return &((SkPoint*)(void*)&r)[index]; 714df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger} 715df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 7160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { 7170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 7180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 7201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isEmpty()) { 7210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 7220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 72487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkPoint strokeSize; 72587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); 72687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 72787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#ifdef SK_DISABLE_FAST_AA_STROKE_RECT 72887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (kStroke_RectType == rtype && paint.isAntiAlias()) { 72987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger rtype = kPath_RectType; 73087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 73187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger#endif 7321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 73387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (kPath_RectType == rtype) { 7340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath tmp; 7350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.addRect(rect); 7360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmp.setFillType(SkPath::kWinding_FillType); 7379c762df18b8a4dae9969cb79eb3b1f53a749f5ebMike Reed this->drawPath(tmp, paint, NULL, true); 7380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 7390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkMatrix& matrix = *fMatrix; 7420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect devRect; 7430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // transform rect into devRect 7450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 7460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.mapXY(rect.fLeft, rect.fTop, rect_points(devRect, 0)); 7470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.mapXY(rect.fRight, rect.fBottom, rect_points(devRect, 1)); 7480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project devRect.sort(); 7490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBounder && !fBounder->doRect(devRect, paint)) { 7520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 7530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // look for the quick exit, before we build a blitter 7560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 7570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect ir; 7580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project devRect.roundOut(&ir); 759030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed if (paint.getStyle() != SkPaint::kFill_Style) { 760030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed // extra space for hairlines 761030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed ir.inset(-1, -1); 762030ffe05175291b1d91ec6808e1a32e862ee90cdMike Reed } 7631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->quickReject(ir)) 7640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 7650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 7670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoBlitterChoose blitterStorage(*fBitmap, matrix, paint); 7681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRasterClip& clip = *fRC; 7690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter* blitter = blitterStorage.get(); 7700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 77115b24eaf335059bc4162c00c6e75cda63f5510d1Mike Reed // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter 77215b24eaf335059bc4162c00c6e75cda63f5510d1Mike Reed // case we are also hairline (if we've gotten to here), which devolves to 77315b24eaf335059bc4162c00c6e75cda63f5510d1Mike Reed // effectively just kFill 77487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger switch (rtype) { 77587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger case kFill_RectType: 77687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (paint.isAntiAlias()) { 77787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScan::AntiFillRect(devRect, clip, blitter); 77887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } else { 77987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScan::FillRect(devRect, clip, blitter); 78087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 78187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger break; 78287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger case kStroke_RectType: 78387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (paint.isAntiAlias()) { 78487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter); 78587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } else { 78687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScan::FrameRect(devRect, strokeSize, clip, blitter); 78787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 78887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger break; 78987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger case kHair_RectType: 79087b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger if (paint.isAntiAlias()) { 79187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScan::AntiHairRect(devRect, clip, blitter); 79287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } else { 79387b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger SkScan::HairRect(devRect, clip, blitter); 79487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger } 79587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger break; 79687b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger default: 7971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("bad rtype"); 7980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 7990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 8000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 8020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (srcM.fBounds.isEmpty()) { 8030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 8040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkMask* mask = &srcM; 8070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkMask dstM; 8090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getMaskFilter() && 8100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) { 8110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask = &dstM; 8121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 8131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger dstM.fImage = NULL; 8140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoMaskFreeImage ami(dstM.fImage); 8160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBounder && !fBounder->doIRect(mask->fBounds)) { 8180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 8190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint); 8221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkBlitter* blitter = blitterChooser.get(); 8230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitterWrapper wrapper; 8251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRegion* clipRgn; 8260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isBW()) { 8281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipRgn = &fRC->bwRgn(); 8291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 8301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger wrapper.init(*fRC, blitter); 8311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipRgn = &wrapper.getRgn(); 8321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = wrapper.getBlitter(); 8330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 8341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter->blitMaskRegion(*mask, *clipRgn); 8351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 8360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 8377ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reedstatic SkScalar fast_len(const SkVector& vec) { 8387ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed SkScalar x = SkScalarAbs(vec.fX); 8397ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed SkScalar y = SkScalarAbs(vec.fY); 8407ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed if (x < y) { 8417ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed SkTSwap(x, y); 8427ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed } 8437ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed return x + SkScalarHalf(y); 8447ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed} 8457ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed 8461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) { 8471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkXfermode::Coeff dc; 8481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) { 8491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; 8501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 8511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 8521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger switch (dc) { 8531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case SkXfermode::kOne_Coeff: 8541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case SkXfermode::kISA_Coeff: 8551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger case SkXfermode::kISC_Coeff: 8561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return true; 8571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger default: 8581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; 8591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 8601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 8611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 8621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerbool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix, 8634f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar* coverage) { 8644f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkASSERT(coverage); 8651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (SkPaint::kStroke_Style != paint.getStyle()) { 8661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; 8671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 8681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScalar strokeWidth = paint.getStrokeWidth(); 8691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (0 == strokeWidth) { 8704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *coverage = SK_Scalar1; 8711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return true; 8721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 8731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 8741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // if we get here, we need to try to fake a thick-stroke with a modulated 8751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // hairline 8761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 8771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!paint.isAntiAlias()) { 8781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; 8791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 8800199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger if (matrix.hasPerspective()) { 8817ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed return false; 8827ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed } 8831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 8847ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed SkVector src[2], dst[2]; 8851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger src[0].set(strokeWidth, 0); 8861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger src[1].set(0, strokeWidth); 8877ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed matrix.mapVectors(dst, src, 2); 8887ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed SkScalar len0 = fast_len(dst[0]); 8897ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed SkScalar len1 = fast_len(dst[1]); 8904c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { 8914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *coverage = SkScalarAve(len0, len1); 8927ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed return true; 8937ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed } 8947ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed return false; 8957ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed} 8967ca7644aeec45833638d2ce965f4c6ec62e71adeMike Reed 8971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, 8980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkMatrix* prePathMatrix, bool pathIsMutable) const { 8990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 9000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 9021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isEmpty()) { 9030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 9040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath* pathPtr = (SkPath*)&origSrcPath; 9070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool doFill = true; 9080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath tmpPath; 9090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix tmpMatrix; 9100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkMatrix* matrix = fMatrix; 9110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (prePathMatrix) { 9131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style || 9141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger origPaint.getRasterizer()) { 9150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath* result = pathPtr; 91640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!pathIsMutable) { 9180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project result = &tmpPath; 9190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathIsMutable = true; 9200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathPtr->transform(*prePathMatrix, result); 9220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathPtr = result; 9230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 9240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) { 9250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // overflow 9260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 9270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix = &tmpMatrix; 9290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // at this point we're done with prePathMatrix 9320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 93340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkPaint* paint = &origPaint; 9351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkTLazy<SkPaint> lazyPaint; 9360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger { 9384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkScalar coverage; 9394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { 9404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (SK_Scalar1 == coverage) { 9414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger lazyPaint.set(origPaint); 9424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger lazyPaint.get()->setStrokeWidth(0); 9434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint = lazyPaint.get(); 9444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) { 9454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger U8CPU newAlpha; 9464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if 0 9474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger newAlpha = SkToU8(SkScalarRoundToInt(coverage * 9484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger origPaint.getAlpha())); 9494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else 9504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // this is the old technique, which we preserve for now so 9514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // we don't change previous results (testing) 9524f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // the new way seems fine, its just (a tiny bit) different 9534f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger int scale = (int)SkScalarMul(coverage, 256); 9544f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger newAlpha = origPaint.getAlpha() * scale >> 8; 9554f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 9564f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger lazyPaint.set(origPaint); 9574f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger lazyPaint.get()->setStrokeWidth(0); 9584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger lazyPaint.get()->setAlpha(newAlpha); 9594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger paint = lazyPaint.get(); 9604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } 9610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 96340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { 9651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger doFill = paint->getFillPath(*pathPtr, &tmpPath); 9660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathPtr = &tmpPath; 9670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 96840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 9691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (paint->getRasterizer()) { 9700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask mask; 9711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (paint->getRasterizer()->rasterize(*pathPtr, *matrix, 9721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger &fRC->getBounds(), paint->getMaskFilter(), &mask, 9730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 9741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger this->drawDevMask(mask, *paint); 9750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask::FreeImage(mask.fImage); 9760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 9780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // avoid possibly allocating a new path in transform if we can 9810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 9820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // transform the path into device space 9840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathPtr->transform(*matrix, devPathPtr); 9850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint); 9870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // how does filterPath() know to fill or hairline the path??? <mrr> 9891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (paint->getMaskFilter() && 9901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, 9911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fBounder, blitter.get())) { 9920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; // filterPath() called the blitter, so we're done 9930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) { 9960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 9970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 9980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 9991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*); 10000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (doFill) { 10011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (paint->isAntiAlias()) { 10021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger proc = SkScan::AntiFillPath; 10030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 10041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger proc = SkScan::FillPath; 10050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { // hairline 10071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (paint->isAntiAlias()) { 10081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger proc = SkScan::AntiHairPath; 10090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 10101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger proc = SkScan::HairPath; 10110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger proc(*devPathPtr, *fRC, blitter.get()); 10140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 10150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 101603f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed/** For the purposes of drawing bitmaps, if a matrix is "almost" translate 101703f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed go ahead and treat it as if it were, so that subsequent code can go fast. 101803f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed */ 101903f42ddd729377f21719a140c027a1f8cc5c2152Mike Reedstatic bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) { 102003f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed SkMatrix::TypeMask mask = matrix.getType(); 102103f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed 102203f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 102303f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed return false; 102403f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed } 102503f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed if (mask & SkMatrix::kScale_Mask) { 102603f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed SkScalar sx = matrix[SkMatrix::kMScaleX]; 102703f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed SkScalar sy = matrix[SkMatrix::kMScaleY]; 102803f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed int w = bitmap.width(); 102903f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed int h = bitmap.height(); 103003f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w))); 103103f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h))); 103203f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed return sw == w && sh == h; 103303f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed } 103403f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed // if we got here, we're either kTranslate_Mask or identity 103503f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed return true; 10360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 10370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, 10390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint) const { 10400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config); 10410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 104240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (just_translate(*fMatrix, bitmap)) { 10430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int ix = SkScalarRound(fMatrix->getTranslateX()); 10440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int iy = SkScalarRound(fMatrix->getTranslateY()); 10450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask mask; 10470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 10480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fFormat = SkMask::kA8_Format; 10490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fRowBytes = bitmap.rowBytes(); 10500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fImage = bitmap.getAddr8(0, 0); 105140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 10520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->drawDevMask(mask, paint); 10530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { // need to xform the bitmap first 10540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect r; 10550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask mask; 105640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 10570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.set(0, 0, 10580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 10590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMatrix->mapRect(&r); 10600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.round(&mask.fBounds); 106140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 10620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // set the mask's bounds to the transformed bitmap-bounds, 10630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // clipped to the actual device 10640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 10650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect devBounds; 10660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project devBounds.set(0, 0, fBitmap->width(), fBitmap->height()); 10670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need intersect(l, t, r, b) on irect 10680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!mask.fBounds.intersect(devBounds)) { 10690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 10700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 10710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 1072eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed 10730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fFormat = SkMask::kA8_Format; 10740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fRowBytes = SkAlign4(mask.fBounds.width()); 1075eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed size_t size = mask.computeImageSize(); 1076eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed if (0 == size) { 1077eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed // the mask is too big to allocated, draw nothing 1078eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed return; 1079eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed } 10800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // allocate (and clear) our temp buffer to hold the transformed bitmap 10820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoMalloc storage(size); 10830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fImage = (uint8_t*)storage.get(); 10840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(mask.fImage, 0, size); 108540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 10860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now draw our bitmap(src) into mask(dst), transformed by the matrix 10870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 10880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBitmap device; 10890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), 10900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fBounds.height(), mask.fRowBytes); 10910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project device.setPixels(mask.fImage); 109240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 10930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkCanvas c(device); 10940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need the unclipped top/left for the translate 10950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project c.translate(-SkIntToScalar(mask.fBounds.fLeft), 10960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project -SkIntToScalar(mask.fBounds.fTop)); 10970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project c.concat(*fMatrix); 10980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 10990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // We can't call drawBitmap, or we'll infinitely recurse. Instead 11000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // we manually build a shader and draw that into our new mask 11010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPaint tmpPaint; 11020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmpPaint.setFlags(paint.getFlags()); 1103df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkAutoBitmapShaderInstall install(bitmap, tmpPaint); 11040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect rr; 11050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rr.set(0, 0, SkIntToScalar(bitmap.width()), 11060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIntToScalar(bitmap.height())); 1107df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger c.drawRect(rr, install.paintWithShader()); 11080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->drawDevMask(mask, paint); 11100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 11120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool clipped_out(const SkMatrix& m, const SkRasterClip& c, 11140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkRect& srcR) { 11150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect dstR; 11160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect devIR; 111740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 11180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.mapRect(&dstR, srcR); 111940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger dstR.roundOut(&devIR); 11200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return c.quickReject(devIR); 11210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 11220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip, 11240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int width, int height) { 11250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect r; 11260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 11270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return clipped_out(matrix, clip, r); 11280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 11290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, 11311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkBitmap& bitmap) { 11321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return clip.isBW() || 11331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height()); 11341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 11351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 11360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 1137df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger const SkPaint& origPaint) const { 11380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 11390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 11411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isEmpty() || 11420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bitmap.width() == 0 || bitmap.height() == 0 || 11431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bitmap.getConfig() == SkBitmap::kNo_Config) { 11440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 11450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 114640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 114740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifndef SK_ALLOW_OVER_32K_BITMAPS 11480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // run away on too-big bitmaps for now (exceed 16.16) 11490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bitmap.width() > 32767 || bitmap.height() > 32767) { 11500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 11510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 115240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif 115340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 1154df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkPaint paint(origPaint); 1155df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger paint.setStyle(SkPaint::kFill_Style); 115640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 11570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 11580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!matrix.setConcat(*fMatrix, prematrix)) { 11590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 11600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) { 11630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 11640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 11660d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed if (fBounder && just_translate(matrix, bitmap)) { 11670d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed SkIRect ir; 11680d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed int32_t ix = SkScalarRound(matrix.getTranslateX()); 11690d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed int32_t iy = SkScalarRound(matrix.getTranslateY()); 11700d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 11710d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed if (!fBounder->doIRect(ir)) { 11720d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed return; 11730d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed } 11740d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed } 11750d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed 11760d8b9985975678c153f5d04c076c8d9c0315f277Mike Reed // only lock the pixels if we passed the clip and bounder tests 11770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoLockPixels alp(bitmap); 11780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // after the lock, check if we are valid 11790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!bitmap.readyToDraw()) { 11800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 11810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 11820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 118303f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed if (bitmap.getConfig() != SkBitmap::kA8_Config && 118403f42ddd729377f21719a140c027a1f8cc5c2152Mike Reed just_translate(matrix, bitmap)) { 11851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int ix = SkScalarRound(matrix.getTranslateX()); 11861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int iy = SkScalarRound(matrix.getTranslateY()); 11871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (clipHandlesSprite(*fRC, ix, iy, bitmap)) { 11881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger uint32_t storage[kBlitterStorageLongCount]; 11891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 11901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ix, iy, storage, sizeof(storage)); 11911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (blitter) { 11921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage); 11931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 11941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIRect ir; 11951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 11961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 11971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::FillIRect(ir, *fRC, blitter); 11981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 11990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 120240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now make a temp draw on the stack, and use it 12040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // 12050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDraw draw(*this); 12060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw.fMatrix = &matrix; 120740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (bitmap.getConfig() == SkBitmap::kA8_Config) { 12090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw.drawBitmapAsMask(bitmap, paint); 12100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 1211df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkAutoBitmapShaderInstall install(bitmap, paint); 12120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect r; 12140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.set(0, 0, SkIntToScalar(bitmap.width()), 12150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIntToScalar(bitmap.height())); 121640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // is this ok if paint has a rasterizer? 1217df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger draw.drawRect(r, install.paintWithShader()); 12180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 12200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, 1222df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger const SkPaint& origPaint) const { 12230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 122440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 12261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isEmpty() || 12270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bitmap.width() == 0 || bitmap.height() == 0 || 12281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bitmap.getConfig() == SkBitmap::kNo_Config) { 12290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 12300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect bounds; 12330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds.set(x, y, x + bitmap.width(), y + bitmap.height()); 12340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->quickReject(bounds)) { 12360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; // nothing to draw 12370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1239df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkPaint paint(origPaint); 1240df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger paint.setStyle(SkPaint::kFill_Style); 12410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) { 12430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project uint32_t storage[kBlitterStorageLongCount]; 12440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 12450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project x, y, storage, sizeof(storage)); 12460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (blitter) { 12480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage); 12490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBounder && !fBounder->doIRect(bounds)) { 12510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 12520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::FillIRect(bounds, *fRC, blitter); 12550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 12560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 12580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1259df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger SkAutoBitmapShaderInstall install(bitmap, paint); 1260df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger const SkPaint& shaderPaint = install.paintWithShader(); 12610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 12630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect r; 12640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // get a scalar version of our rect 12660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.set(bounds); 12670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // tell the shader our offset 12690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setTranslate(r.fLeft, r.fTop); 1270df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger shaderPaint.getShader()->setLocalMatrix(matrix); 127140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDraw draw(*this); 12730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.reset(); 12740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw.fMatrix = &matrix; 12750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // call ourself with a rect 127640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // is this OK if paint has a rasterizer? 1277df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger draw.drawRect(r, shaderPaint); 12780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 12790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 12810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkScalerContext.h" 12830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkGlyphCache.h" 12840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkUtils.h" 12850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, 12870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const char text[], size_t byteLength, SkVector* stopVector) { 12880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed x = 0, y = 0; 12890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const char* stop = text + byteLength; 12900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoKern autokern; 129240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 12930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (text < stop) { 12940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // don't need x, y here, since all subpixel variants will have the 12950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // same advance 12960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 12970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 12980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project x += autokern.adjust(glyph) + glyph.fAdvanceX; 12990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project y += glyph.fAdvanceY; 13000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); 13020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(text == stop); 13040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 13050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawText_asPaths(const char text[], size_t byteLength, 13070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar x, SkScalar y, 13080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint) const { 13090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 13100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTextToPathIter iter(text, byteLength, paint, true, true); 13120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 13140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setScale(iter.getPathScale(), iter.getPathScale()); 13150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.postTranslate(x, y); 13160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPath* iterPath; 13180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar xpos, prevXPos = 0; 13190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while ((iterPath = iter.next(&xpos)) != NULL) { 13210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.postTranslate(xpos - prevXPos, 0); 132240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const SkPaint& pnt = iter.getPaint(); 132340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fDevice) { 132440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fDevice->drawPath(*this, *iterPath, pnt, &matrix, false); 132540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 132640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->drawPath(*iterPath, pnt, &matrix, false); 132740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 13280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project prevXPos = xpos; 13290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 13310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// disable warning : local variable used without having been initialized 133340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#if defined _WIN32 && _MSC_VER >= 1300 13340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#pragma warning ( push ) 13350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#pragma warning ( disable : 4701 ) 13360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 13370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project////////////////////////////////////////////////////////////////////////////// 13390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void D1G_NoBounder_RectClip(const SkDraw1Glyph& state, 134140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fx, SkFixed fy, 134240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const SkGlyph& glyph) { 134340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger int left = SkFixedFloor(fx); 134440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger int top = SkFixedFloor(fy); 13450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 13461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(NULL == state.fBounder); 13471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT((NULL == state.fClip && state.fAAClip) || 13481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger (state.fClip && NULL == state.fAAClip && state.fClip->isRect())); 13490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project left += glyph.fLeft; 13510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project top += glyph.fTop; 13520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int right = left + glyph.fWidth; 13540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int bottom = top + glyph.fHeight; 13550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkMask mask; 13571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIRect storage; 13581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIRect* bounds = &mask.fBounds; 13591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 13601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fBounds.set(left, top, right, bottom); 13611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 13621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // this extra test is worth it, assuming that most of the time it succeeds 13631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // since we can avoid writing to storage 13641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) { 13651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds)) 13661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 13671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bounds = &storage; 13681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 13691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 13701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger uint8_t* aa = (uint8_t*)glyph.fImage; 13711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == aa) { 13721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger aa = (uint8_t*)state.fCache->findImage(glyph); 13731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == aa) { 13741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; // can't rasterize glyph 13750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 13761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 13770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fRowBytes = glyph.rowBytes(); 13791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 13801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fImage = aa; 13811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger state.fBlitter->blitMask(mask, *bounds); 13820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 13830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state, 138540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fx, SkFixed fy, 13861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkGlyph& glyph) { 138740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger int left = SkFixedFloor(fx); 138840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger int top = SkFixedFloor(fy); 13890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 13901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(!state.fClip->isRect()); 13911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(NULL == state.fBounder); 13920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask mask; 13940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project left += glyph.fLeft; 13960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project top += glyph.fTop; 13970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 13980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 13991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 14001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!clipper.done()) { 14021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkIRect& cr = clipper.rect(); 14031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* aa = (const uint8_t*)glyph.fImage; 14041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == aa) { 14051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger aa = (uint8_t*)state.fCache->findImage(glyph); 14061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == aa) { 14071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 14080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 141040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 14111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fRowBytes = glyph.rowBytes(); 14121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 14131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fImage = (uint8_t*)aa; 14141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger do { 14151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger state.fBlitter->blitMask(mask, cr); 14161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipper.next(); 14171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } while (!clipper.done()); 14181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 14200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 14210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void D1G_Bounder(const SkDraw1Glyph& state, 142240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fx, SkFixed fy, 14231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkGlyph& glyph) { 142440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger int left = SkFixedFloor(fx); 142540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger int top = SkFixedFloor(fy); 14260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 14271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask mask; 14291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project left += glyph.fLeft; 14310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project top += glyph.fTop; 14321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 14340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 14351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!clipper.done()) { 14371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkIRect& cr = clipper.rect(); 14381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const uint8_t* aa = (const uint8_t*)glyph.fImage; 14391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == aa) { 14401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger aa = (uint8_t*)state.fCache->findImage(glyph); 14411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == aa) { 14421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return; 14430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 144686cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed // we need to pass the origin, which we approximate with our 144786cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed // (unadjusted) left,top coordinates (the caller called fixedfloor) 14481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (state.fBounder->doIRectGlyph(cr, 144986cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed left - glyph.fLeft, 145086cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed top - glyph.fTop, glyph)) { 14511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fRowBytes = glyph.rowBytes(); 14521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 14531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger mask.fImage = (uint8_t*)aa; 14541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger do { 14551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger state.fBlitter->blitMask(mask, cr); 14561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clipper.next(); 14571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } while (!clipper.done()); 14581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger} 14611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void D1G_Bounder_AAClip(const SkDraw1Glyph& state, 14631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkFixed fx, SkFixed fy, 14641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkGlyph& glyph) { 14651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int left = SkFixedFloor(fx); 14661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger int top = SkFixedFloor(fy); 14671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIRect bounds; 14681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 14691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 14701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) { 14711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger D1G_NoBounder_RectClip(state, fx, fy, glyph); 14721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 14730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 14740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1475df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenbergerstatic bool hasCustomD1GProc(const SkDraw& draw) { 1476df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger return draw.fProcs && draw.fProcs->fD1GProc; 1477df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger} 1478df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 1479df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenbergerstatic bool needsRasterTextBlit(const SkDraw& draw) { 1480df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger return !hasCustomD1GProc(draw); 1481df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger} 1482df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 14830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectSkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, 14840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkGlyphCache* cache) { 14850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fDraw = draw; 14864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fBounder = draw->fBounder; 14874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fBlitter = blitter; 14884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fCache = cache; 14890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 1490df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (hasCustomD1GProc(*draw)) { 14911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // todo: fix this assumption about clips w/ custom 14921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClip = draw->fClip; 14931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClipBounds = fClip->getBounds(); 14940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return draw->fProcs->fD1GProc; 14950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 14960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 14971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (draw->fRC->isBW()) { 14981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fAAClip = NULL; 14991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClip = &draw->fRC->bwRgn(); 15001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClipBounds = fClip->getBounds(); 15011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == fBounder) { 15021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fClip->isRect()) { 15031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return D1G_NoBounder_RectClip; 15041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 15051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return D1G_NoBounder_RgnClip; 15061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 15071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { 15081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return D1G_Bounder; 15091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 15101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else { // aaclip 15111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fAAClip = &draw->fRC->aaRgn(); 15121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClip = NULL; 15131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fClipBounds = fAAClip->getBounds(); 15141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (NULL == fBounder) { 15150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return D1G_NoBounder_RectClip; 15160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 15171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return D1G_Bounder_AAClip; 15180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 15210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 15230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawText(const char text[], size_t byteLength, 15250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar x, SkScalar y, const SkPaint& paint) const { 15260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(byteLength == 0 || text != NULL); 15270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 15290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 15311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 15320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 15330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (/*paint.isLinearText() ||*/ 15360199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger (fMatrix->hasPerspective())) { 15370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project this->drawText_asPaths(text, byteLength, x, y, paint); 15380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 15390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 15420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 154340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const SkMatrix* matrix = fMatrix; 1544df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (hasCustomD1GProc(*this)) { 154540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // only support the fMVMatrix (for now) for the GPU case, which also 154640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // sets the fD1GProc 154740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fMVMatrix) { 154840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger matrix = fMVMatrix; 154940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 155040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 155140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 155240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkAutoGlyphCache autoCache(paint, matrix); 15530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkGlyphCache* cache = autoCache.getCache(); 155440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // transform our starting point 15560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 15570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint loc; 155840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger matrix->mapXY(x, y, &loc); 15590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project x = loc.fX; 15600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project y = loc.fY; 15610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need to measure first 15640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getTextAlign() != SkPaint::kLeft_Align) { 15650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector stop; 15660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project measure_text(cache, glyphCacheProc, text, byteLength, &stop); 15680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar stopX = stop.fX; 15700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar stopY = stop.fY; 15710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 15720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getTextAlign() == SkPaint::kCenter_Align) { 15730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stopX = SkScalarHalf(stopX); 15740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project stopY = SkScalarHalf(stopY); 15750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project x -= stopX; 15770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project y -= stopY; 15780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 157940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 15800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed fx = SkScalarToFixed(x); 15810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed fy = SkScalarToFixed(y); 15820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const char* stop = text + byteLength; 15830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 158440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fxMask = ~0; 158540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fyMask = ~0; 15864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (cache->isSubpixel()) { 15871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*matrix); 15881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (kX_SkAxisAlignment == baseline) { 158940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fyMask = 0; 15901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else if (kY_SkAxisAlignment == baseline) { 159140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fxMask = 0; 15920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 15934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger 15944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger // apply bias here to avoid adding 1/2 the sampling frequency in the loop 15954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fx += SK_FixedHalf >> SkGlyph::kSubBits; 15964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fy += SK_FixedHalf >> SkGlyph::kSubBits; 15974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger } else { 15984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fx += SK_FixedHalf; 15994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fy += SK_FixedHalf; 16000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 16010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitter aaBlitter; 16031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoBlitterChoose blitterChooser; 16041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkBlitter* blitter = NULL; 1605df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (needsRasterTextBlit(*this)) { 16061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitterChooser.choose(*fBitmap, *matrix, paint); 16071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = blitterChooser.get(); 16081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isAA()) { 16091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger aaBlitter.init(blitter, &fRC->aaRgn()); 16101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = &aaBlitter; 16111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1612df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger } 1613df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 16140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoKern autokern; 16151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDraw1Glyph d1g; 16161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache); 16170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (text < stop) { 16194f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); 16200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fx += autokern.adjust(glyph); 16220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (glyph.fWidth) { 16241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger proc(d1g, fx, fy, glyph); 16250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 16260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fx += glyph.fAdvanceX; 16270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fy += glyph.fAdvanceY; 16280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 16290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// last parameter is interpreted as SkFixed [x, y] 16320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// return the fixed position, which may be rounded or not by the caller 16330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// e.g. subpixel doesn't round 16340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttypedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); 16350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, 16370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIPoint* dst) { 16380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); 16390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, 16420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIPoint* dst) { 16430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1), 16440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1)); 16450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, 16480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIPoint* dst) { 16490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX, 16500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalarToFixed(loc.fY) - glyph.fAdvanceY); 16510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic AlignProc pick_align_proc(SkPaint::Align align) { 16540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static const AlignProc gProcs[] = { 16550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project leftAlignProc, centerAlignProc, rightAlignProc 16560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project }; 165740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs)); 16590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return gProcs[align]; 16610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 16620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass TextMapState { 16640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 16650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mutable SkPoint fLoc; 166640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project TextMapState(const SkMatrix& matrix, SkScalar y) 16680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {} 16690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project typedef void (*Proc)(const TextMapState&, const SkScalar pos[]); 167140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Proc pickProc(int scalarsPerPosition); 167340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 16750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkMatrix& fMatrix; 16760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix::MapXYProc fProc; 16770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar fY; // ignored by MapXYProc 16780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // these are only used by Only... procs 16790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar fScaleX, fTransX, fTransformedY; 16800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 16810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static void MapXProc(const TextMapState& state, const SkScalar pos[]) { 16820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc); 16830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 168440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static void MapXYProc(const TextMapState& state, const SkScalar pos[]) { 16860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc); 16870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 168840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static void MapOnlyScaleXProc(const TextMapState& state, 16900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar pos[]) { 16910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX, 16920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state.fTransformedY); 16930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 169440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 16950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static void MapOnlyTransXProc(const TextMapState& state, 16960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar pos[]) { 16970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state.fLoc.set(*pos + state.fTransX, state.fTransformedY); 16980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 16990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 17000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectTextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) { 17020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 170340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (1 == scalarsPerPosition) { 17050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project unsigned mtype = fMatrix.getType(); 17060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 17070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return MapXProc; 17080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 17090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fScaleX = fMatrix.getScaleX(); 17100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fTransX = fMatrix.getTranslateX(); 17110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) + 17120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMatrix.getTranslateY(); 17130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return (mtype & SkMatrix::kScale_Mask) ? 17140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project MapOnlyScaleXProc : MapOnlyTransXProc; 17150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 17160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 17170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return MapXYProc; 17180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 17190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 17200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project////////////////////////////////////////////////////////////////////////////// 17220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawPosText(const char text[], size_t byteLength, 17240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkScalar pos[], SkScalar constY, 17250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int scalarsPerPosition, const SkPaint& paint) const { 17260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(byteLength == 0 || text != NULL); 17270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 17280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(this->validate();) 17300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 17321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 17330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 17340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 17350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (/*paint.isLinearText() ||*/ 17370199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger (fMatrix->hasPerspective())) { 17380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // TODO !!!! 17390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project// this->drawText_asPaths(text, byteLength, x, y, paint); 17400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 17410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 17420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 174340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const SkMatrix* matrix = fMatrix; 1744df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (hasCustomD1GProc(*this)) { 174540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // only support the fMVMatrix (for now) for the GPU case, which also 174640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // sets the fD1GProc 174740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fMVMatrix) { 174840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger matrix = fMVMatrix; 174940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 175040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 175140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 175340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkAutoGlyphCache autoCache(paint, matrix); 17540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkGlyphCache* cache = autoCache.getCache(); 175540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAAClipBlitterWrapper wrapper; 17571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAutoBlitterChoose blitterChooser; 17581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkBlitter* blitter = NULL; 1759df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger if (needsRasterTextBlit(*this)) { 17601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitterChooser.choose(*fBitmap, *matrix, paint); 17611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = blitterChooser.get(); 17621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (fRC->isAA()) { 17631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger wrapper.init(*fRC, blitter); 17641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger blitter = wrapper.getBlitter(); 17651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 1766df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger } 1767df9bcf50153969dcaaa2c869a1980724509bcc16Derek Sollenberger 17680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const char* stop = text + byteLength; 17690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project AlignProc alignProc = pick_align_proc(paint.getTextAlign()); 17704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkDraw1Glyph d1g; 17714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache); 177240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger TextMapState tms(*matrix, constY); 17730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); 17740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17754f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger if (cache->isSubpixel()) { 17760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // maybe we should skip the rounding if linearText is set 17771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkAxisAlignment roundBaseline = SkComputeAxisAlignmentForHText(*matrix); 17780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkPaint::kLeft_Align == paint.getTextAlign()) { 17800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (text < stop) { 178140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmsProc(tms, pos); 178340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 17844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#ifdef SK_DRAW_POS_TEXT_IGNORE_SUBPIXEL_LEFT_ALIGN_FIX 17850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed fx = SkScalarToFixed(tms.fLoc.fX); 17860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed fy = SkScalarToFixed(tms.fLoc.fY); 17874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#else 17884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + (SK_FixedHalf >> SkGlyph::kSubBits); 17894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + (SK_FixedHalf >> SkGlyph::kSubBits); 17904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif 179140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fxMask = ~0; 179240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fyMask = ~0; 17930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 17941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (kX_SkAxisAlignment == roundBaseline) { 179540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fyMask = 0; 17961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else if (kY_SkAxisAlignment == roundBaseline) { 179740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fxMask = 0; 17980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 179940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 180040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger const SkGlyph& glyph = glyphCacheProc(cache, &text, 180140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fx & fxMask, fy & fyMask); 180240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 18030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (glyph.fWidth) { 180440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger proc(d1g, fx, fy, glyph); 18050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pos += scalarsPerPosition; 18070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 18090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (text < stop) { 18101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const char* currentText = text; 18110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkGlyph* glyph = &glyphCacheProc(cache, &text, 0, 0); 181240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 18130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (glyph->fWidth) { 18140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(SkFixed prevAdvX = glyph->fAdvanceX;) 18150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;) 18160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkFixed fx, fy; 181840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fxMask = ~0; 181940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkFixed fyMask = ~0; 18200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmsProc(tms, pos); 182140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 18220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 18230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIPoint fixedLoc; 18240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project alignProc(tms.fLoc, *glyph, &fixedLoc); 18254f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fx = fixedLoc.fX + (SK_FixedHalf >> SkGlyph::kSubBits); 18264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fy = fixedLoc.fY + (SK_FixedHalf >> SkGlyph::kSubBits); 18270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (kX_SkAxisAlignment == roundBaseline) { 182940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fyMask = 0; 18301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } else if (kY_SkAxisAlignment == roundBaseline) { 183140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fxMask = 0; 18320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 183440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 18350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // have to call again, now that we've been "aligned" 18361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger glyph = &glyphCacheProc(cache, ¤tText, 18371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger fx & fxMask, fy & fyMask); 18380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // the assumption is that the advance hasn't changed 18390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(prevAdvX == glyph->fAdvanceX); 18400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(prevAdvY == glyph->fAdvanceY); 184140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 184240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger proc(d1g, fx, fy, *glyph); 18430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pos += scalarsPerPosition; 18450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { // not subpixel 18480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (text < stop) { 18490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // the last 2 parameters are ignored 18500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 185140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 18520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (glyph.fWidth) { 18530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tmsProc(tms, pos); 185440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 18550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIPoint fixedLoc; 18560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project alignProc(tms.fLoc, glyph, &fixedLoc); 185740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 18584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger proc(d1g, 18594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fixedLoc.fX + SK_FixedHalf, 18604f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger fixedLoc.fY + SK_FixedHalf, 18614f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger glyph); 18620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pos += scalarsPerPosition; 18640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 18660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 18670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#if defined _WIN32 && _MSC_VER >= 1300 18690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#pragma warning ( pop ) 18700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 18710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 18730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPathMeasure.h" 18750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void morphpoints(SkPoint dst[], const SkPoint src[], int count, 18770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPathMeasure& meas, const SkMatrix& matrix) { 18780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix::MapXYProc proc = matrix.getMapXYProc(); 18790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 18810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pos; 18820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkVector tangent; 18830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project proc(matrix, src[i].fX, src[i].fY, &pos); 18850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sx = pos.fX; 18860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar sy = pos.fY; 18870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project meas.getPosTan(sx, &pos, &tangent); 18890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* This is the old way (that explains our approach but is way too slow 18910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix matrix; 18920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint pt; 18930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 18940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pt.set(sx, sy); 18950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setSinCos(tangent.fY, tangent.fX); 18960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.preTranslate(-sx, 0); 18970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.postTranslate(pos.fX, pos.fY); 18980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.mapPoints(&dst[i], &pt, 1); 18990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 19000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy), 19010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pos.fY + SkScalarMul(tangent.fX, sy)); 19020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 19040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/* TODO 19060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Need differentially more subdivisions when the follow-path is curvy. Not sure how to 19080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project determine that, but we need it. I guess a cheap answer is let the caller tell us, 19090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out. 19100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project*/ 19110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas, 19120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkMatrix& matrix) { 19130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Iter iter(src, false); 19140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint srcP[4], dstP[3]; 19150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath::Verb verb; 19160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) { 19180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (verb) { 19190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kMove_Verb: 19200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project morphpoints(dstP, srcP, 1, meas, matrix); 19210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->moveTo(dstP[0]); 19220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 19230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kLine_Verb: 19240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // turn lines into quads to look bendy 19250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX); 19260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY); 19270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project morphpoints(dstP, srcP, 2, meas, matrix); 19280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(dstP[0], dstP[1]); 19290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 19300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kQuad_Verb: 19310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project morphpoints(dstP, &srcP[1], 2, meas, matrix); 19320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->quadTo(dstP[0], dstP[1]); 19330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 19340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kCubic_Verb: 19350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project morphpoints(dstP, &srcP[1], 3, meas, matrix); 19360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->cubicTo(dstP[0], dstP[1], dstP[2]); 19370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 19380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkPath::kClose_Verb: 19390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst->close(); 19400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 19410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 19421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDEBUGFAIL("unknown verb"); 19430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project break; 19440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 19470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawTextOnPath(const char text[], size_t byteLength, 19490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPath& follow, const SkMatrix* matrix, 19500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint) const { 19510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(byteLength == 0 || text != NULL); 19520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // nothing to draw 19541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 19550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 19560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTextToPathIter iter(text, byteLength, paint, true, true); 19590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPathMeasure meas(follow, false); 19600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar hOffset = 0; 19610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need to measure first 19630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getTextAlign() != SkPaint::kLeft_Align) { 19640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar pathLen = meas.getLength(); 19650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getTextAlign() == SkPaint::kCenter_Align) { 19660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathLen = SkScalarHalf(pathLen); 19670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project hOffset += pathLen; 19690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPath* iterPath; 19720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar xpos; 19730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix scaledMatrix; 19740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar scale = iter.getPathScale(); 19750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project scaledMatrix.setScale(scale, scale); 197740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 19780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while ((iterPath = iter.next(&xpos)) != NULL) { 19790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPath tmp; 19800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix m(scaledMatrix); 19810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.postTranslate(xpos + hOffset, 0); 19830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (matrix) { 19840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.postConcat(*matrix); 19850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project morphpath(&tmp, *iterPath, meas, m); 198740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger if (fDevice) { 198840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true); 198940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } else { 199040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger this->drawPath(tmp, iter.getPaint(), NULL, true); 199140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger } 19920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 19930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 19940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 19951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_ANDROID 1996a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglinvoid SkDraw::drawPosTextOnPath(const char text[], size_t byteLength, 1997a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin const SkPoint pos[], const SkPaint& paint, 1998a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin const SkPath& path, const SkMatrix* matrix) const { 1999a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin // nothing to draw 20001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 2001a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin return; 2002a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin } 2003a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2004a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkMatrix scaledMatrix; 2005a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkPathMeasure meas(path, false); 2006a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2007a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc( 2008a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkPaint::kForward_TextBufferDirection, true); 2009a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2010a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin // Copied (modified) from SkTextToPathIter constructor to setup paint 2011a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkPaint tempPaint(paint); 2012a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2013a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin tempPaint.setLinearText(true); 2014a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin tempPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup 2015a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2016a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin if (tempPaint.getPathEffect() == NULL && !(tempPaint.getStrokeWidth() > 0 2017a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin && tempPaint.getStyle() != SkPaint::kFill_Style)) { 2018a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin tempPaint.setStyle(SkPaint::kFill_Style); 2019a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin tempPaint.setPathEffect(NULL); 2020a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin } 2021a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin // End copied from SkTextToPathIter constructor 2022a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2023a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin // detach cache 2024a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkGlyphCache* cache = tempPaint.detachCache(NULL); 2025a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2026a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin // Must set scale, even if 1 2027a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkScalar scale = SK_Scalar1; 2028a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin scaledMatrix.setScale(scale, scale); 2029a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2030a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin // Loop over all glyph ids 2031a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin for (const char* stop = text + byteLength; text < stop; pos++) { 2032a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2033a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin const SkGlyph& glyph = glyphCacheProc(cache, &text); 2034a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkPath tmp; 2035a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2036a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin const SkPath* glyphPath = cache->findPath(glyph); 2037a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin if (glyphPath == NULL) { 2038a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin continue; 2039a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin } 2040a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2041a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkMatrix m(scaledMatrix); 2042a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin m.postTranslate(pos->fX, 0); 2043a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2044a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin if (matrix) { 2045a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin m.postConcat(*matrix); 2046a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin } 2047a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2048a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin morphpath(&tmp, *glyphPath, meas, m); 2049a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin this->drawPath(tmp, tempPaint); 2050a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2051a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin } 2052a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 2053a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin // re-attach cache 2054a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin SkGlyphCache::AttachCache(cache); 2055a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin} 205605b6b4d746867a9fb02e14edfe1bf3685abeb813Derek Sollenberger#endif 2057a2dfb00239c367c3663e8487a8213d0edad238baAndreas Borglin 20580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project/////////////////////////////////////////////////////////////////////////////// 20590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 20600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstruct VertState { 20610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int f0, f1, f2; 20620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 20630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project VertState(int vCount, const uint16_t indices[], int indexCount) 20640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project : fIndices(indices) { 20650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCurrIndex = 0; 20660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (indices) { 20670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCount = indexCount; 20680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 20690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fCount = vCount; 20700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 20710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 207240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 207340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger typedef bool (*Proc)(VertState*); 20740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Proc chooseProc(SkCanvas::VertexMode mode); 20750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 20760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 20770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int fCount; 20780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int fCurrIndex; 20790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint16_t* fIndices; 208040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 20810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static bool Triangles(VertState*); 20820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static bool TrianglesX(VertState*); 20830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static bool TriangleStrip(VertState*); 20840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static bool TriangleStripX(VertState*); 20850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static bool TriangleFan(VertState*); 20860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static bool TriangleFanX(VertState*); 20870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 20880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 20890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool VertState::Triangles(VertState* state) { 20900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = state->fCurrIndex; 20910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index + 3 > state->fCount) { 20920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 20930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 20940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = index + 0; 20950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = index + 1; 20960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f2 = index + 2; 20970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->fCurrIndex = index + 3; 20980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 20990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool VertState::TrianglesX(VertState* state) { 21020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint16_t* indices = state->fIndices; 21030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = state->fCurrIndex; 21040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index + 3 > state->fCount) { 21050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 21060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = indices[index + 0]; 21080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = indices[index + 1]; 21090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f2 = indices[index + 2]; 21100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->fCurrIndex = index + 3; 21110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 21120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool VertState::TriangleStrip(VertState* state) { 21150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = state->fCurrIndex; 21160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index + 3 > state->fCount) { 21170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 21180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f2 = index + 2; 21200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index & 1) { 21210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = index + 1; 21220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = index + 0; 21230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 21240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = index + 0; 21250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = index + 1; 21260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->fCurrIndex = index + 1; 21280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 21290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool VertState::TriangleStripX(VertState* state) { 21320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint16_t* indices = state->fIndices; 21330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = state->fCurrIndex; 21340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index + 3 > state->fCount) { 21350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 21360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f2 = indices[index + 2]; 21380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index & 1) { 21390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = indices[index + 1]; 21400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = indices[index + 0]; 21410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 21420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = indices[index + 0]; 21430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = indices[index + 1]; 21440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->fCurrIndex = index + 1; 21460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 21470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool VertState::TriangleFan(VertState* state) { 21500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = state->fCurrIndex; 21510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index + 3 > state->fCount) { 21520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 21530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = 0; 21550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = index + 1; 21560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f2 = index + 2; 21570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->fCurrIndex = index + 1; 21580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 21590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool VertState::TriangleFanX(VertState* state) { 21620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint16_t* indices = state->fIndices; 21630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index = state->fCurrIndex; 21640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (index + 3 > state->fCount) { 21650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 21660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f0 = indices[0]; 21680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f1 = indices[index + 1]; 21690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->f2 = indices[index + 2]; 21700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state->fCurrIndex = index + 1; 21710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 21720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source ProjectVertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) { 21750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project switch (mode) { 21760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkCanvas::kTriangles_VertexMode: 21770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fIndices ? TrianglesX : Triangles; 21780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkCanvas::kTriangleStrip_VertexMode: 21790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fIndices ? TriangleStripX : TriangleStrip; 21800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project case SkCanvas::kTriangleFan_VertexMode: 21810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fIndices ? TriangleFanX : TriangleFan; 21820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project default: 21830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return NULL; 21840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 21850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&, 21880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkBlitter*); 21890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic HairProc ChooseHairProc(bool doAntiAlias) { 21910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 21920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 21930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 21940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool texture_to_matrix(const VertState& state, const SkPoint verts[], 21950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint texs[], SkMatrix* matrix) { 21960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint src[3], dst[3]; 219740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 21980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project src[0] = texs[state.f0]; 21990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project src[1] = texs[state.f1]; 22000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project src[2] = texs[state.f2]; 22010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst[0] = verts[state.f0]; 22020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst[1] = verts[state.f1]; 22030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dst[2] = verts[state.f2]; 22040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return matrix->setPolyToPoly(src, dst, 3); 22050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 22060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkTriColorShader : public SkShader { 22080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic: 22090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTriColorShader() {} 22100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 221240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count); 221440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprotected: 22160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {} 221740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project virtual Factory getFactory() { return CreateProc; } 221940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprivate: 22210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix fDstToUnit; 22220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPMColor fColors[3]; 222340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 22250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkNEW_ARGS(SkTriColorShader, (buffer)); 22260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 22270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project typedef SkShader INHERITED; 22280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}; 22290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[], 22310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int index0, int index1, int index2) { 223240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fColors[0] = SkPreMultiplyColor(colors[index0]); 22340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fColors[1] = SkPreMultiplyColor(colors[index1]); 22350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fColors[2] = SkPreMultiplyColor(colors[index2]); 223640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix m, im; 22380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.reset(); 22390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.set(0, pts[index1].fX - pts[index0].fX); 22400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.set(1, pts[index2].fX - pts[index0].fX); 22410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.set(2, pts[index0].fX); 22420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.set(3, pts[index1].fY - pts[index0].fY); 22430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.set(4, pts[index2].fY - pts[index0].fY); 22440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project m.set(5, pts[index0].fY); 22450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!m.invert(&im)) { 22460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 22470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 22480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return fDstToUnit.setConcat(im, this->getTotalInverse()); 22490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 22500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkColorPriv.h" 22520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkComposeShader.h" 22530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic int ScalarTo256(SkScalar v) { 22550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int scale = SkScalarToFixed(v) >> 8; 22560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (scale < 0) { 22570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project scale = 0; 22580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 22590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (scale > 255) { 22600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project scale = 255; 22610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 22620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return SkAlpha255To256(scale); 22630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 22640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 22660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint src; 226740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project for (int i = 0; i < count; i++) { 22690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); 22700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project x += 1; 227140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int scale1 = ScalarTo256(src.fX); 22730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int scale2 = ScalarTo256(src.fY); 22740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int scale0 = 256 - scale1 - scale2; 22750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (scale0 < 0) { 22760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (scale1 > scale2) { 22770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project scale2 = 256 - scale1; 22780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 22790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project scale1 = 256 - scale2; 22800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 22810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project scale0 = 0; 22820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 228340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 22850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAlphaMulQ(fColors[1], scale1) + 22860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAlphaMulQ(fColors[2], scale2); 22870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 22880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 22890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 22900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, 22910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPoint vertices[], const SkPoint textures[], 22920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkColor colors[], SkXfermode* xmode, 22930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const uint16_t indices[], int indexCount, 22940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint) const { 22950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(0 == count || NULL != vertices); 229640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 22970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // abort early if there is nothing to draw 22981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { 22990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 23000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 230140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 23020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // transform out vertices into device coordinates 23030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoSTMalloc<16, SkPoint> storage(count); 23040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPoint* devVerts = storage.get(); 23050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project fMatrix->mapPoints(devVerts, vertices, count); 230640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 23070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (fBounder) { 23080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkRect bounds; 23090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds.set(devVerts, count); 23100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!fBounder->doRect(bounds, paint)) { 23110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return; 23120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 231440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 23150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project /* 23160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project We can draw the vertices in 1 of 4 ways: 23170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 23180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project - solid color (no shader/texture[], no colors[]) 23190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project - just colors (no shader/texture[], has colors[]) 23200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project - just texture (has shader/texture[], no colors[]) 23210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project - colors * texture (has shader/texture[], has colors[]) 232240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 23230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project Thus for texture drawing, we need both texture[] and a shader. 23240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project */ 23250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 23260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTriColorShader triShader; // must be above declaration of p 23270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkPaint p(paint); 23280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 23290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkShader* shader = p.getShader(); 23300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL == shader) { 23310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // if we have no shader, we ignore the texture coordinates 23320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project textures = NULL; 23330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else if (NULL == textures) { 23340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // if we don't have texture coordinates, ignore the shader 23350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project p.setShader(NULL); 23360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shader = NULL; 23370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 23390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // setup the custom shader (if needed) 23400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != colors) { 23410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL == textures) { 23420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // just colors (no texture) 23430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project p.setShader(&triShader); 23440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 23450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // colors * texture 23460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(shader); 23470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool releaseMode = false; 23480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL == xmode) { 234959f59bde0b05a6ac5ff28fdebc1942dbf0d43aabMike Reed xmode = SkXfermode::Create(SkXfermode::kMultiply_Mode); 23500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project releaseMode = true; 23510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkShader* compose = SkNEW_ARGS(SkComposeShader, 23530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project (&triShader, shader, xmode)); 23540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project p.setShader(compose)->unref(); 23550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (releaseMode) { 23560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project xmode->unref(); 23570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 23610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); 23620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // setup our state and function pointer for iterating triangles 23630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project VertState state(count, indices, indexCount); 23640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project VertState::Proc vertProc = state.chooseProc(vmode); 236540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 23660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != textures || NULL != colors) { 23670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMatrix localM, tempM; 23680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bool hasLocalM = shader && shader->getLocalMatrix(&localM); 236940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 23700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != colors) { 23710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!triShader.setContext(*fBitmap, p, *fMatrix)) { 23720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project colors = NULL; 23730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 237540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 23760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (vertProc(&state)) { 23770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != textures) { 23780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (texture_to_matrix(state, vertices, textures, &tempM)) { 23790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (hasLocalM) { 23800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project tempM.postConcat(localM); 23810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shader->setLocalMatrix(tempM); 23830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // need to recal setContext since we changed the local matrix 23840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!shader->setContext(*fBitmap, p, *fMatrix)) { 23850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project continue; 23860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != colors) { 23900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!triShader.setup(vertices, colors, 23910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project state.f0, state.f1, state.f2)) { 23920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project continue; 23930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 23951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger 23961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPoint tmp[] = { 23971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 23981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger }; 23991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkScan::FillTriangle(tmp, *fRC, blitter.get()); 24000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // now restore the shader's original local matrix 24020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (NULL != shader) { 24030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (hasLocalM) { 24040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shader->setLocalMatrix(localM); 24050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 24060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project shader->resetLocalMatrix(); 24070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 24100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // no colors[] and no texture 24110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); 24121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkRasterClip& clip = *fRC; 24130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project while (vertProc(&state)) { 24141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get()); 24151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get()); 24161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get()); 24170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 24200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 242187b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 242287b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 24230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_DEBUG 24250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkDraw::validate() const { 24270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fBitmap != NULL); 24280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fMatrix != NULL); 24290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(fClip != NULL); 24301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkASSERT(fRC != NULL); 24310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger const SkIRect& cr = fRC->getBounds(); 24330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect br; 24340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project br.set(0, 0, fBitmap->width(), fBitmap->height()); 24360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(cr.isEmpty() || br.contains(cr)); 243740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 243840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger // assert that both are null, or both are not-null 243940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger SkASSERT(!fMVMatrix == !fExtMatrix); 24400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 24410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif 24430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 244487b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger/////////////////////////////////////////////////////////////////////////////// 244587b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger 244687b8e645865f9633f410c02252a0fd3feb18f09bDerek SollenbergerSkBounder::SkBounder() { 244787b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger // initialize up front. This gets reset by SkCanvas before each draw call. 244887b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger fClip = &SkRegion::GetEmptyRegion(); 244987b8e645865f9633f410c02252a0fd3feb18f09bDerek Sollenberger} 24500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkBounder::doIRect(const SkIRect& r) { 24520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect rr; 24530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr); 24540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 24550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 245686cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed// TODO: change the prototype to take fixed, and update the callers 245786cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reedbool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y, 245886cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed const SkGlyph& glyph) { 2459091f227385b467090b5a7169a8e2faf19eca7105Mike Reed SkIRect rr; 246086cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed if (!rr.intersect(fClip->getBounds(), r)) { 246186cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed return false; 246286cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed } 246386cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed GlyphRec rec; 246486cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y)); 246586cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX, 246686cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed rec.fLSB.fY + glyph.fAdvanceY); 246786cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed rec.fGlyphID = glyph.getGlyphID(); 246886cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed rec.fFlags = 0; 246986cd5d6eb40d1bfbfa4eed24f28d8a0f485d63f4Mike Reed return this->onIRectGlyph(rr, rec); 2470091f227385b467090b5a7169a8e2faf19eca7105Mike Reed} 2471091f227385b467090b5a7169a8e2faf19eca7105Mike Reed 24720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1, 24730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project const SkPaint& paint) { 24740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect r; 24750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkScalar v0, v1; 24760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project v0 = pt0.fX; 24780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project v1 = pt1.fX; 24790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (v0 > v1) { 24800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTSwap<SkScalar>(v0, v1); 24810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fLeft = SkScalarFloor(v0); 24830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fRight = SkScalarCeil(v1); 24840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project v0 = pt0.fY; 24860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project v1 = pt1.fY; 24870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (v0 > v1) { 24880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkTSwap<SkScalar>(v0, v1); 24890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fTop = SkScalarFloor(v0); 24910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.fBottom = SkScalarCeil(v1); 24920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.isAntiAlias()) { 24940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.inset(-1, -1); 24950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 24960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return this->doIRect(r); 24970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 24980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 24990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) { 25000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect r; 25010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.getStyle() == SkPaint::kFill_Style) { 25030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.round(&r); 25040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { 25050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project int rad = -1; 25060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rect.roundOut(&r); 25070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.isAntiAlias()) { 25080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project rad = -2; 25090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 25100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.inset(rad, rad); 25110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 25120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return this->doIRect(r); 25130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 25140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) { 25160e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed SkIRect r; 25170e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed const SkRect& bounds = path.getBounds(); 25180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (doFill) { 25200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds.round(&r); 25210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } else { // hairline 25220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bounds.roundOut(&r); 25230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 25240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (paint.isAntiAlias()) { 25260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project r.inset(-1, -1); 25270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 25280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return this->doIRect(r); 25290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 25300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid SkBounder::commit() { 25320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // override in subclass 25330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 25340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////////////// 25360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPath.h" 25380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkDraw.h" 25390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkRegion.h" 25400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBlitter.h" 25410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 25430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMaskFilter* filter, const SkMatrix* filterMatrix, 25440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkIRect* bounds) { 25450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (devPath.isEmpty()) { 25460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 25470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 25480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // init our bounds from the path 25500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project { 25510e747d6d0a794242bd214fa44a6a179baeadfdf9Mike Reed SkRect pathBounds = devPath.getBounds(); 25520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf); 25530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project pathBounds.roundOut(bounds); 25540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 255540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 25561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIPoint margin; 25570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (filter) { 25580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkASSERT(filterMatrix); 255940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 25601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkMask srcM, dstM; 256140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 25620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcM.fBounds = *bounds; 25630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcM.fFormat = SkMask::kA8_Format; 25640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project srcM.fImage = NULL; 25650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 25660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 25670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 25680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 256940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 25701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger // (possibly) trim the bounds to reflect the clip 25710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project // (plus whatever slop the filter needs) 25721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (clipBounds) { 25731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkIRect tmp = *clipBounds; 2574af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project // Ugh. Guard against gigantic margins from wacky filters. Without this 2575af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project // check we can request arbitrary amounts of slop beyond our visible 2576af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project // clip, and bring down the renderer (at least on finite RAM machines 2577af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project // like handsets, etc.). Need to balance this invented value between 2578af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project // quality of large filters like blurs, and the corresponding memory 2579af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project // requests. 2580af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project static const int MAX_MARGIN = 128; 2581af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project tmp.inset(-SkMin32(margin.fX, MAX_MARGIN), 2582af527e02dce280c269d751322e9f60aac8cb97daThe Android Open Source Project -SkMin32(margin.fY, MAX_MARGIN)); 25831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger if (!bounds->intersect(tmp)) { 25841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger return false; 25851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger } 25860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 25870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 25890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 25900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic void draw_into_mask(const SkMask& mask, const SkPath& devPath) { 25921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkBitmap bm; 25931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkDraw draw; 25941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkRasterClip clip; 25951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkMatrix matrix; 25961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger SkPaint paint; 25970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 25980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes); 25990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project bm.setPixels(mask.fImage); 26000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 26011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height())); 26020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 26030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project -SkIntToScalar(mask.fBounds.fTop)); 26040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 26050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw.fBitmap = &bm; 26061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger draw.fRC = &clip; 26071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger draw.fClip = &clip.bwRgn(); 26080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw.fMatrix = &matrix; 26090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw.fBounder = NULL; 26100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project paint.setAntiAlias(true); 26110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw.drawPath(devPath, paint); 26120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 26130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 26140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectbool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 26150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMaskFilter* filter, const SkMatrix* filterMatrix, 26160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project SkMask* mask, SkMask::CreateMode mode) { 26170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkMask::kJustRenderImage_CreateMode != mode) { 26180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 26190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return false; 26200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 262140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 26220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 26230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask->fFormat = SkMask::kA8_Format; 26240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project mask->fRowBytes = mask->fBounds.width(); 2625eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed size_t size = mask->computeImageSize(); 2626eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed if (0 == size) { 2627eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed // we're too big to allocate the mask, abort 2628eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed return false; 2629eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed } 2630eba9f316916f3381d6a5dd5c1300fea6ec6da8dcMike Reed mask->fImage = SkMask::AllocImage(size); 26310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project memset(mask->fImage, 0, mask->computeImageSize()); 26320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 26330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project 26340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project if (SkMask::kJustComputeBounds_CreateMode != mode) { 26350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project draw_into_mask(*mask, devPath); 26360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project } 263740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger 26380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project return true; 26390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project} 2640