1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/* 2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2006 The Android Open Source Project 3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * 4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be 5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file. 6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define __STDC_LIMIT_MACROS 9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkArenaAlloc.h" 11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkAutoBlitterChoose.h" 12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBlendModePriv.h" 13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBlitter.h" 14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkCanvas.h" 15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkColorData.h" 16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDevice.h" 17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDeviceLooper.h" 18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDraw.h" 19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDrawProcs.h" 20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkFindAndPlaceGlyph.h" 21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMaskFilterBase.h" 22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMatrix.h" 23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkMatrixUtils.h" 24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaint.h" 25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPathEffect.h" 26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRasterClip.h" 27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRectPriv.h" 28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRRect.h" 29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkScalerContext.h" 30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkScan.h" 31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkShader.h" 32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkString.h" 33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStroke.h" 34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkStrokeRec.h" 35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTemplates.h" 36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextMapStateProc.h" 37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTLazy.h" 38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkUtils.h" 39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkPaint make_paint_with_image( 41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& origPaint, const SkBitmap& bitmap, SkMatrix* matrix = nullptr) { 42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paint(origPaint); 43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setShader(SkMakeBitmapShader(bitmap, SkShader::kClamp_TileMode, 44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkShader::kClamp_TileMode, matrix, 45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot kNever_SkCopyPixelsMode)); 46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return paint; 47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkDraw::SkDraw() { 52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(this, sizeof(*this)); 53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const { 56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty()) { 57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix inverse; 61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fMatrix->invert(&inverse)) { 62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect devBounds = fRC->getBounds(); 66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // outset to have slop for antialasing and hairlines 67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot devBounds.outset(1, 1); 68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot inverse.mapRect(localBounds, SkRect::Make(devBounds)); 69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robottypedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); 75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) { 77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_bzero(pixels, bytes); 78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {} 81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2)); 84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1)); 88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memset(pixels, data, bytes); 92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic BitmapXferProc ChooseBitmapXferProc(const SkPixmap& dst, const SkPaint& paint, 95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t* data) { 96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // todo: we can apply colorfilter up front if no shader, so we wouldn't 97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // need to abort this fastpath 98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getShader() || paint.getColorFilter() || dst.colorSpace()) { 99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlendMode mode = paint.getBlendMode(); 103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkColor color = paint.getColor(); 104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // collaps modes based on color... 106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkBlendMode::kSrcOver == mode) { 107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot unsigned alpha = SkColorGetA(color); 108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == alpha) { 109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mode = SkBlendMode::kDst; 110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (0xFF == alpha) { 111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mode = SkBlendMode::kSrc; 112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (mode) { 116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkBlendMode::kClear: 117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("--- D_Clear_BitmapXferProc\n"); 118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return D_Clear_BitmapXferProc; // ignore data 119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkBlendMode::kDst: 120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("--- D_Dst_BitmapXferProc\n"); 121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return D_Dst_BitmapXferProc; // ignore data 122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkBlendMode::kSrc: { 123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* 124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot should I worry about dithering for the lower depths? 125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPMColor pmc = SkPreMultiplyColor(color); 127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (dst.colorType()) { 128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kN32_SkColorType: 129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (data) { 130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *data = pmc; 131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("--- D32_Src_BitmapXferProc\n"); 133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return D32_Src_BitmapXferProc; 134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kRGB_565_SkColorType: 135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (data) { 136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *data = SkPixel32ToPixel16(pmc); 137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("--- D16_Src_BitmapXferProc\n"); 139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return D16_Src_BitmapXferProc; 140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAlpha_8_SkColorType: 141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (data) { 142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *data = SkGetPackedA32(pmc); 143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// SkDebugf("--- DA8_Src_BitmapXferProc\n"); 145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return DA8_Src_BitmapXferProc; 146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return nullptr; 155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void CallBitmapXferProc(const SkPixmap& dst, const SkIRect& rect, BitmapXferProc proc, 158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t procData) { 159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int shiftPerPixel; 160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (dst.colorType()) { 161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kN32_SkColorType: 162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shiftPerPixel = 2; 163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kRGB_565_SkColorType: 165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shiftPerPixel = 1; 166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kAlpha_8_SkColorType: 168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot shiftPerPixel = 0; 169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("Can't use xferproc on this config"); 172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t* pixels = (uint8_t*)dst.writable_addr(); 176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(pixels); 177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const size_t rowBytes = dst.rowBytes(); 178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const int widthBytes = rect.width() << shiftPerPixel; 179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // skip down to the first scanline and X position 181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel); 182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int scans = rect.height() - 1; scans >= 0; --scans) { 183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc(pixels, widthBytes, procData); 184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pixels += rowBytes; 185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawPaint(const SkPaint& paint) const { 189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty()) { 192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect devRect; 196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot devRect.set(0, 0, fDst.width(), fDst.height()); 197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isBW()) { 199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot /* If we don't have a shader (i.e. we're just a solid color) we may 200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot be faster to operate directly on the device bitmap, rather than invoking 201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot a blitter. Esp. true for xfermodes, which require a colorshader to be 202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot present, which is just redundant work. Since we're drawing everywhere 203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot in the clip, we don't have to worry about antialiasing. 204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */ 205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t procData = 0; // to avoid the warning 206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot BitmapXferProc proc = ChooseBitmapXferProc(fDst, paint, &procData); 207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (proc) { 208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (D_Dst_BitmapXferProc == proc) { // nothing to do 209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRegion::Iterator iter(fRC->bwRgn()); 213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (!iter.done()) { 214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot CallBitmapXferProc(fDst, iter.rect(), proc, procData); 215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot iter.next(); 216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // normal case: use a blitter 222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FillIRect(devRect, *fRC, blitter.get()); 224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstruct PtProcRec { 229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCanvas::PointMode fMode; 230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint* fPaint; 231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRegion* fClip; 232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRasterClip* fRC; 233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // computed values 235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixed fRadius; 236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count, 238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter*); 239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix, 241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRasterClip*); 242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Proc chooseProc(SkBlitter** blitter); 243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAAClipBlitterWrapper fWrapper; 246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(rec.fClip->isRect()); 251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& r = rec.fClip->getBounds(); 252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i++) { 254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int x = SkScalarFloorToInt(devPts[i].fX); 255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int y = SkScalarFloorToInt(devPts[i].fY); 256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (r.contains(x, y)) { 257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitter->blitH(x, y, 1); 258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void bw_pt_rect_16_hair_proc(const PtProcRec& rec, 263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint devPts[], int count, 264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter) { 265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(rec.fRC->isRect()); 266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& r = rec.fRC->getBounds(); 267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t value; 268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(dst); 270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint16_t* addr = dst->writable_addr16(0, 0); 272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t rb = dst->rowBytes(); 273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i++) { 275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int x = SkScalarFloorToInt(devPts[i].fX); 276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int y = SkScalarFloorToInt(devPts[i].fY); 277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (r.contains(x, y)) { 278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value); 279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void bw_pt_rect_32_hair_proc(const PtProcRec& rec, 284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint devPts[], int count, 285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter) { 286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(rec.fRC->isRect()); 287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& r = rec.fRC->getBounds(); 288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t value; 289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPixmap* dst = blitter->justAnOpaqueColor(&value); 290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(dst); 291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPMColor* addr = dst->writable_addr32(0, 0); 293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t rb = dst->rowBytes(); 294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i++) { 296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int x = SkScalarFloorToInt(devPts[i].fX); 297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int y = SkScalarFloorToInt(devPts[i].fY); 298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (r.contains(x, y)) { 299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ((SkPMColor*)((char*)addr + y * rb))[x] = value; 300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i++) { 307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int x = SkScalarFloorToInt(devPts[i].fX); 308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int y = SkScalarFloorToInt(devPts[i].fY); 309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (rec.fClip->contains(x, y)) { 310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitter->blitH(x, y, 1); 311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i += 2) { 318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter); 319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::HairLine(devPts, count, *rec.fRC, blitter); 325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// aa versions 328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i += 2) { 332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter); 333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter); 339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkFixed radius = rec.fRadius; 346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i++) { 347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixed x = SkScalarToFixed(devPts[i].fX); 348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixed y = SkScalarToFixed(devPts[i].fY); 349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkXRect r; 351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fLeft = x - radius; 352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fTop = y - radius; 353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fRight = x + radius; 354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fBottom = y + radius; 355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FillXRect(r, *rec.fRC, blitter); 357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int count, SkBlitter* blitter) { 362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkFixed radius = rec.fRadius; 363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < count; i++) { 364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixed x = SkScalarToFixed(devPts[i].fX); 365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFixed y = SkScalarToFixed(devPts[i].fY); 366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkXRect r; 368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fLeft = x - radius; 369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fTop = y - radius; 370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fRight = x + radius; 371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fBottom = y + radius; 372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::AntiFillXRect(r, *rec.fRC, blitter); 374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// If this guy returns true, then chooseProc() must return a valid proc 378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* matrix, const SkRasterClip* rc) { 380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((unsigned)mode > (unsigned)SkCanvas::kPolygon_PointMode) { 381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getPathEffect()) { 384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar width = paint.getStrokeWidth(); 387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar radius = -1; // sentinel value, a "valid" value must be > 0 388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == width) { 390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot radius = 0.5f; 391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (paint.getStrokeCap() != SkPaint::kRound_Cap && 392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) { 393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar sx = matrix->get(SkMatrix::kMScaleX); 394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar sy = matrix->get(SkMatrix::kMScaleY); 395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarNearlyZero(sx - sy)) { 396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot radius = SkScalarHalf(width * SkScalarAbs(sx)); 397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (radius > 0) { 400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if we return true, the caller may assume that the constructed shapes can be represented 401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // using SkFixed, so we preflight that here, looking at the radius and clip-bounds 402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkRectPriv::FitsInFixed(SkRect::Make(rc->getBounds()).makeOutset(radius, radius))) { 403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMode = mode; 406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fPaint = &paint; 407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fClip = nullptr; 408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRC = rc; 409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fRadius = SkScalarToFixed(radius); 410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotPtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { 416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot Proc proc = nullptr; 417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter = *blitterPtr; 419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isBW()) { 420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fClip = &fRC->bwRgn(); 421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fWrapper.init(*fRC, blitter); 423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fClip = &fWrapper.getRgn(); 424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitter = fWrapper.getBlitter(); 425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *blitterPtr = blitter; 426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // for our arrays 429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(0 == SkCanvas::kPoints_PointMode); 430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(1 == SkCanvas::kLines_PointMode); 431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(2 == SkCanvas::kPolygon_PointMode); 432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fPaint->isAntiAlias()) { 435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == fPaint->getStrokeWidth()) { 436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const Proc gAAProcs[] = { 437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = gAAProcs[fMode]; 440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkCanvas::kPoints_PointMode == fMode); 442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = aa_square_proc; 443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { // BW 445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRadius <= SK_FixedHalf) { // small radii and hairline 446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint32_t value; 448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPixmap* bm = blitter->justAnOpaqueColor(&value); 449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (bm && kRGB_565_SkColorType == bm->colorType()) { 450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = bw_pt_rect_16_hair_proc; 451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (bm && kN32_SkColorType == bm->colorType()) { 452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = bw_pt_rect_32_hair_proc; 453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = bw_pt_rect_hair_proc; 455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static Proc gBWProcs[] = { 458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot }; 460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = gBWProcs[fMode]; 461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = bw_square_proc; 464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return proc; 467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// each of these costs 8-bytes of stack space, so don't make it too large 470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// must be even for lines/polygon to work 471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define MAX_DEV_PTS 32 472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint pts[], const SkPaint& paint, 475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBaseDevice* device) const { 476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if we're in lines mode, force count to be even 477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkCanvas::kLines_PointMode == mode) { 478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count &= ~(size_t)1; 479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((long)count <= 0) { 482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(pts != nullptr); 486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // nothing to draw 489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty()) { 490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PtProcRec rec; 494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!device && rec.init(mode, paint, fMatrix, fRC)) { 495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint devPts[MAX_DEV_PTS]; 498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* matrix = fMatrix; 499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* bltr = blitter.get(); 500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot PtProcRec::Proc proc = rec.chooseProc(&bltr); 501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we have to back up subsequent passes if we're in polygon mode 502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int n = SkToInt(count); 506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (n > MAX_DEV_PTS) { 507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot n = MAX_DEV_PTS; 508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix->mapPoints(devPts, pts, n); 510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc(rec, devPts, n, bltr); 511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pts += n - backup; 512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkToInt(count) >= n); 513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count -= n; 514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (count > 0) { 515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count += backup; 516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (count != 0); 518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (mode) { 520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkCanvas::kPoints_PointMode: { 521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // temporarily mark the paint as filling. 522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint newPaint(paint); 523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newPaint.setStyle(SkPaint::kFill_Style); 524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar width = newPaint.getStrokeWidth(); 526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar radius = SkScalarHalf(width); 527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) { 529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath path; 530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix preMatrix; 531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.addCircle(0, 0, radius); 533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < count; i++) { 534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot preMatrix.setTranslate(pts[i].fX, pts[i].fY); 535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // pass true for the last point, since we can modify 536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // then path then 537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.setIsVolatile((count-1) == i); 538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (device) { 539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device->drawPath(path, newPaint, &preMatrix, (count-1) == i); 540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPath(path, newPaint, &preMatrix, (count-1) == i); 542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect r; 546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < count; i++) { 548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fLeft = pts[i].fX - radius; 549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fTop = pts[i].fY - radius; 550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fRight = r.fLeft + width; 551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.fBottom = r.fTop + width; 552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (device) { 553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device->drawRect(r, newPaint); 554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawRect(r, newPaint); 556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkCanvas::kLines_PointMode: 562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (2 == count && paint.getPathEffect()) { 563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // most likely a dashed line - see if it is one of the ones 564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we can accelerate 565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStrokeRec rec(paint); 566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPathEffect::PointData pointData; 567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath path; 569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.moveTo(pts[0]); 570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.lineTo(pts[1]); 571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect cullRect = SkRect::Make(fRC->getBounds()); 573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getPathEffect()->asPoints(&pointData, path, rec, 575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *fMatrix, &cullRect)) { 576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 'asPoints' managed to find some fast path 577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint newP(paint); 579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newP.setPathEffect(nullptr); 580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newP.setStyle(SkPaint::kFill_Style); 581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!pointData.fFirst.isEmpty()) { 583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (device) { 584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device->drawPath(pointData.fFirst, newP); 585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPath(pointData.fFirst, newP); 587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!pointData.fLast.isEmpty()) { 591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (device) { 592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device->drawPath(pointData.fLast, newP); 593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPath(pointData.fLast, newP); 595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (pointData.fSize.fX == pointData.fSize.fY) { 599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The rest of the dashed line can just be drawn as points 600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth())); 601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) { 603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newP.setStrokeCap(SkPaint::kRound_Cap); 604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newP.setStrokeCap(SkPaint::kButt_Cap); 606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (device) { 609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device->drawPoints(SkCanvas::kPoints_PointMode, 610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fNumPoints, 611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fPoints, 612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newP); 613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPoints(SkCanvas::kPoints_PointMode, 615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fNumPoints, 616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fPoints, 617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newP, 618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device); 619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The rest of the dashed line must be drawn as rects 623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag & 624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fFlags)); 625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect r; 627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (int i = 0; i < pointData.fNumPoints; ++i) { 629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.set(pointData.fPoints[i].fX - pointData.fSize.fX, 630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fPoints[i].fY - pointData.fSize.fY, 631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fPoints[i].fX + pointData.fSize.fX, 632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pointData.fPoints[i].fY + pointData.fSize.fY); 633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (device) { 634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device->drawRect(r, newP); 635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawRect(r, newP); 637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // couldn't take fast path so fall through! 645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkCanvas::kPolygon_PointMode: { 646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot count -= 1; 647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath path; 648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint p(paint); 649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot p.setStyle(SkPaint::kStroke_Style); 650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.setIsVolatile(true); 652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot for (size_t i = 0; i < count; i += inc) { 653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.moveTo(pts[i]); 654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.lineTo(pts[i+1]); 655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (device) { 656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device->drawPath(path, p, nullptr, true); 657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPath(path, p, nullptr, true); 659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.rewind(); 661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) { 669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(matrix.rectStaysRect()); 670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(SkPaint::kFill_Style != paint.getStyle()); 671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkVector size; 673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; 674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.mapVectors(&size, &pt, 1); 675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY)); 676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, 679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint* strokeSize) { 680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkPaint::kMiter_Join != paint.getStrokeJoin() || 681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.getStrokeMiter() < SK_ScalarSqrt2) { 682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *strokeSize = compute_stroke_size(paint, matrix); 686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, 690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix& matrix, 691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint* strokeSize) { 692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RectType rtype; 693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkScalar width = paint.getStrokeWidth(); 694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const bool zeroWidth = (0 == width); 695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint::Style style = paint.getStyle(); 696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { 698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot style = SkPaint::kFill_Style; 699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getPathEffect() || paint.getMaskFilter() || 702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot !matrix.rectStaysRect() || SkPaint::kStrokeAndFill_Style == style) { 703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rtype = kPath_RectType; 704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (SkPaint::kFill_Style == style) { 705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rtype = kFill_RectType; 706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (zeroWidth) { 707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rtype = kHair_RectType; 708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (easy_rect_join(paint, matrix, strokeSize)) { 709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rtype = kStroke_RectType; 710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rtype = kPath_RectType; 712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rtype; 714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic const SkPoint* rect_points(const SkRect& r) { 717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkTCast<const SkPoint*>(&r); 718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkPoint* rect_points(SkRect& r) { 721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkTCast<SkPoint*>(&r); 722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_rect_as_path(const SkDraw& orig, const SkRect& prePaintRect, 725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& paint, const SkMatrix* matrix) { 726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDraw draw(orig); 727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.fMatrix = matrix; 728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath tmp; 729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmp.addRect(prePaintRect); 730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmp.setFillType(SkPath::kWinding_FillType); 731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.drawPath(tmp, paint, nullptr, true); 732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint, 735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* paintMatrix, const SkRect* postPaintRect) const { 736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // nothing to draw 739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty()) { 740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* matrix; 744fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix combinedMatrixStorage; 745fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paintMatrix) { 746fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(postPaintRect); 747fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix); 748fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix = &combinedMatrixStorage; 749fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 750fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!postPaintRect); 751fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix = fMatrix; 752fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 753fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 754fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint strokeSize; 755fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); 756fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 757fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (kPath_RectType == rtype) { 758fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_rect_as_path(*this, prePaintRect, paint, matrix); 759fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 760fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 761fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 762fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect devRect; 763fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect; 764fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // skip the paintMatrix when transforming the rect by the CTM 765fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix->mapPoints(rect_points(devRect), rect_points(paintRect), 2); 766fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot devRect.sort(); 767fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 768fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // look for the quick exit, before we build a blitter 769fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect bbox = devRect; 770fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getStyle() != SkPaint::kFill_Style) { 771fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // extra space for hairlines 772fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getStrokeWidth() == 0) { 773fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox.outset(1, 1); 774fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 775fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // For kStroke_RectType, strokeSize is already computed. 776fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPoint& ssize = (kStroke_RectType == rtype) 777fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ? strokeSize 778fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : compute_stroke_size(paint, *fMatrix); 779fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y())); 780fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 781fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 782fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 783fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkRectPriv::MakeLargeS32().contains(bbox)) { 784fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // bbox.roundOut() is undefined; use slow path. 785fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_rect_as_path(*this, prePaintRect, paint, matrix); 786fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 787fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 788fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 789fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect ir = bbox.roundOut(); 790fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->quickReject(ir)) { 791fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 792fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 793fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 794fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDeviceLooper looper(fDst, *fRC, ir, paint.isAntiAlias()); 795fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (looper.next()) { 796fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect localDevRect; 797fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot looper.mapRect(&localDevRect, devRect); 798fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix localMatrix; 799fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot looper.mapMatrix(&localMatrix, *matrix); 800fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 801fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitterStorage(looper.getPixmap(), localMatrix, paint); 802fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRasterClip& clip = looper.getRC(); 803fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter = blitterStorage.get(); 804fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 805fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter 806fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // case we are also hairline (if we've gotten to here), which devolves to 807fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // effectively just kFill 808fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (rtype) { 809fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kFill_RectType: 810fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.isAntiAlias()) { 811fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::AntiFillRect(localDevRect, clip, blitter); 812fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 813fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FillRect(localDevRect, clip, blitter); 814fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 815fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 816fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kStroke_RectType: 817fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.isAntiAlias()) { 818fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); 819fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 820fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); 821fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 822fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 823fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case kHair_RectType: 824fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.isAntiAlias()) { 825fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::AntiHairRect(localDevRect, clip, blitter); 826fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 827fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::HairRect(localDevRect, clip, blitter); 828fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 829fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 830fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 831fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("bad rtype"); 832fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 833fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 834fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 835fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 836fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 837fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (srcM.fBounds.isEmpty()) { 838fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 839fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 840fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 841fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMask* mask = &srcM; 842fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 843fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMask dstM; 844fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getMaskFilter() && 845fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot as_MFB(paint.getMaskFilter())->filterMask(&dstM, srcM, *fMatrix, nullptr)) { 846fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask = &dstM; 847fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 848fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoMaskFreeImage ami(dstM.fImage); 849fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 850fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 851fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter = blitterChooser.get(); 852fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 853fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAAClipBlitterWrapper wrapper; 854fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRegion* clipRgn; 855fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 856fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isBW()) { 857fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clipRgn = &fRC->bwRgn(); 858fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 859fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot wrapper.init(*fRC, blitter); 860fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clipRgn = &wrapper.getRgn(); 861fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitter = wrapper.getBlitter(); 862fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 863fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitter->blitMaskRegion(*mask, *clipRgn); 864fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 865fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 866fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic SkScalar fast_len(const SkVector& vec) { 867fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar x = SkScalarAbs(vec.fX); 868fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar y = SkScalarAbs(vec.fY); 869fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (x < y) { 870fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTSwap(x, y); 871fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 872fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return x + SkScalarHalf(y); 873fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 874fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 875fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, 876fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar* coverage) { 877fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(strokeWidth > 0); 878fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We need to try to fake a thick-stroke with a modulated hairline. 879fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 880fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (matrix.hasPerspective()) { 881fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 882fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 883fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 884fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkVector src[2], dst[2]; 885fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot src[0].set(strokeWidth, 0); 886fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot src[1].set(0, strokeWidth); 887fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.mapVectors(dst, src, 2); 888fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar len0 = fast_len(dst[0]); 889fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar len1 = fast_len(dst[1]); 890fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { 891fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (coverage) { 892fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *coverage = SkScalarAve(len0, len1); 893fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 894fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 895fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 896fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 897fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 898fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 899fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const { 900fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate()); 901fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 902fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty()) { 903fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 904fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 905fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 906fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 907fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // TODO: Investigate optimizing these options. They are in the same 908fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // order as SkDraw::drawPath, which handles each case. It may be 909fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // that there is no way to optimize for these using the SkRRect path. 910fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar coverage; 911fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) { 912fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto DRAW_PATH; 913fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 914fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 915fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 916fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot goto DRAW_PATH; 917fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 918fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 919fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 920fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getMaskFilter()) { 921fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Transform the rrect into device space. 922fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRRect devRRect; 923fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (rrect.transform(*fMatrix, &devRRect)) { 924fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitter(fDst, *fMatrix, paint); 925fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (as_MFB(paint.getMaskFilter())->filterRRect(devRRect, *fMatrix, 926fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *fRC, blitter.get())) { 927fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; // filterRRect() called the blitter, so we're done 928fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 929fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 930fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 931fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 932fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotDRAW_PATH: 933fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now fall back to the default case of using a path. 934fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath path; 935fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot path.addRRect(rrect); 936fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPath(path, paint, nullptr, true); 937fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 938fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 939fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkScalar SkDraw::ComputeResScaleForStroking(const SkMatrix& matrix) { 940fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!matrix.hasPerspective()) { 941fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]); 942fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX], matrix[SkMatrix::kMScaleY]); 943fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkScalarsAreFinite(sx, sy)) { 944fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar scale = SkTMax(sx, sy); 945fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (scale > 0) { 946fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return scale; 947fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 948fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 949fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 950fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return 1; 951fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 952fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 953fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawDevPath(const SkPath& devPath, const SkPaint& paint, bool drawCoverage, 954fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* customBlitter, bool doFill) const { 955fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Do a conservative quick-reject test, since a looper or other modifier may have moved us 956fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // out of range. 957fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!devPath.isInverseFillType()) { 958fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // If we're a H or V line, our bounds will be empty. So we bloat here just so we don't 959fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // appear empty to the intersects call. This also gives us slop in case we're antialiasing 960fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect pathBounds = devPath.getBounds().makeOutset(1, 1); 961fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 962fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getMaskFilter()) { 963fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot as_MFB(paint.getMaskFilter())->computeFastBounds(pathBounds, &pathBounds); 964fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 965fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Need to outset the path to work-around a bug in blurmaskfilter. When that is fixed 966fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we can remove this hack. See skbug.com/5542 967fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pathBounds.outset(7, 7); 968fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 969fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 970fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now compare against the clip's bounds 971fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!SkRect::Make(fRC->getBounds()).intersects(pathBounds)) { 972fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 973fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 974fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 975fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 976fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter = nullptr; 977fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitterStorage; 978fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == customBlitter) { 979fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitterStorage.choose(fDst, *fMatrix, paint, drawCoverage); 980fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitter = blitterStorage.get(); 981fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 982fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot blitter = customBlitter; 983fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 984fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 985fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.getMaskFilter()) { 986fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStrokeRec::InitStyle style = doFill ? SkStrokeRec::kFill_InitStyle 987fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : SkStrokeRec::kHairline_InitStyle; 988fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (as_MFB(paint.getMaskFilter())->filterPath(devPath, *fMatrix, *fRC, blitter, style)) { 989fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; // filterPath() called the blitter, so we're done 990fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 991fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 992fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 993fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*); 994fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (doFill) { 995fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.isAntiAlias()) { 996fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::AntiFillPath; 997fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 998fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::FillPath; 999fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1000fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { // hairline 1001fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint.isAntiAlias()) { 1002fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (paint.getStrokeCap()) { 1003fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kButt_Cap: 1004fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::AntiHairPath; 1005fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1006fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kSquare_Cap: 1007fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::AntiHairSquarePath; 1008fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1009fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kRound_Cap: 1010fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::AntiHairRoundPath; 1011fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1012fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1013fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc SK_INIT_TO_AVOID_WARNING; 1014fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("unknown paint cap type"); 1015fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1016fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1017fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (paint.getStrokeCap()) { 1018fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kButt_Cap: 1019fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::HairPath; 1020fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1021fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kSquare_Cap: 1022fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::HairSquarePath; 1023fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1024fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkPaint::kRound_Cap: 1025fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc = SkScan::HairRoundPath; 1026fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1027fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot default: 1028fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc SK_INIT_TO_AVOID_WARNING; 1029fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGFAIL("unknown paint cap type"); 1030fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1031fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1032fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1033fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot proc(devPath, *fRC, blitter); 1034fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1035fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1036fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, 1037fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* prePathMatrix, bool pathIsMutable, 1038fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool drawCoverage, SkBlitter* customBlitter) const { 1039fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 1040fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1041fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // nothing to draw 1042fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty()) { 1043fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1044fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1045fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1046fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath* pathPtr = (SkPath*)&origSrcPath; 1047fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool doFill = true; 1048fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath tmpPath; 1049fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix tmpMatrix; 1050fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMatrix* matrix = fMatrix; 1051fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmpPath.setIsVolatile(true); 1052fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1053fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (prePathMatrix) { 1054fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style) { 1055fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath* result = pathPtr; 1056fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1057fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!pathIsMutable) { 1058fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot result = &tmpPath; 1059fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pathIsMutable = true; 1060fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1061fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pathPtr->transform(*prePathMatrix, result); 1062fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pathPtr = result; 1063fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1064fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmpMatrix.setConcat(*matrix, *prePathMatrix); 1065fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix = &tmpMatrix; 1066fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1067fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1068fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // at this point we're done with prePathMatrix 1069fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 1070fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1071fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1072fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1073fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 1074fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar coverage; 1075fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { 1076fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SK_Scalar1 == coverage) { 1077fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.writable()->setStrokeWidth(0); 1078fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else if (SkBlendMode_SupportsCoverageAsAlpha(origPaint.getBlendMode())) { 1079fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot U8CPU newAlpha; 1080fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if 0 1081fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newAlpha = SkToU8(SkScalarRoundToInt(coverage * 1082fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot origPaint.getAlpha())); 1083fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#else 1084fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // this is the old technique, which we preserve for now so 1085fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we don't change previous results (testing) 1086fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the new way seems fine, its just (a tiny bit) different 1087fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int scale = (int)(coverage * 256); 1088fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot newAlpha = origPaint.getAlpha() * scale >> 8; 1089fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1090fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint* writablePaint = paint.writable(); 1091fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writablePaint->setStrokeWidth(0); 1092fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot writablePaint->setAlpha(newAlpha); 1093fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1094fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1095fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1096fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1097fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { 1098fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect cullRect; 1099fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect* cullRectPtr = nullptr; 1100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->computeConservativeLocalClipBounds(&cullRect)) { 1101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot cullRectPtr = &cullRect; 1102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr, 1104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot ComputeResScaleForStroking(*fMatrix)); 1105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pathPtr = &tmpPath; 1106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // avoid possibly allocating a new path in transform if we can 1109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 1110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // transform the path into device space 1112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pathPtr->transform(*matrix, devPathPtr); 1113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawDevPath(*devPathPtr, *paint, drawCoverage, customBlitter, doFill); 1115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, const SkPaint& paint) const { 1118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType); 1119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkTreatAsSprite(*fMatrix, bitmap.dimensions(), paint)) { 1121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int ix = SkScalarRoundToInt(fMatrix->getTranslateX()); 1122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int iy = SkScalarRoundToInt(fMatrix->getTranslateY()); 1123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPixmap pmap; 1125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!bitmap.peekPixels(&pmap)) { 1126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMask mask; 1129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fBounds.set(ix, iy, ix + pmap.width(), iy + pmap.height()); 1130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fFormat = SkMask::kA8_Format; 1131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fRowBytes = SkToU32(pmap.rowBytes()); 1132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // fImage is typed as writable, but in this case it is used read-only 1133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fImage = (uint8_t*)pmap.addr8(0, 0); 1134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawDevMask(mask, paint); 1136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { // need to xform the bitmap first 1137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect r; 1138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMask mask; 1139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.set(0, 0, 1141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 1142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fMatrix->mapRect(&r); 1143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.round(&mask.fBounds); 1144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // set the mask's bounds to the transformed bitmap-bounds, 1146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // clipped to the actual device 1147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 1148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect devBounds; 1149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot devBounds.set(0, 0, fDst.width(), fDst.height()); 1150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // need intersect(l, t, r, b) on irect 1151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!mask.fBounds.intersect(devBounds)) { 1152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fFormat = SkMask::kA8_Format; 1157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fRowBytes = SkAlign4(mask.fBounds.width()); 1158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t size = mask.computeImageSize(); 1159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == size) { 1160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // the mask is too big to allocated, draw nothing 1161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // allocate (and clear) our temp buffer to hold the transformed bitmap 1165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoTMalloc<uint8_t> storage(size); 1166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fImage = storage.get(); 1167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot memset(mask.fImage, 0, size); 1168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // now draw our bitmap(src) into mask(dst), transformed by the matrix 1170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot { 1171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap device; 1172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()), 1173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fImage, mask.fRowBytes); 1174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1175fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkCanvas c(device); 1176fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // need the unclipped top/left for the translate 1177fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c.translate(-SkIntToScalar(mask.fBounds.fLeft), 1178fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot -SkIntToScalar(mask.fBounds.fTop)); 1179fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c.concat(*fMatrix); 1180fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1181fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // We can't call drawBitmap, or we'll infinitely recurse. Instead 1182fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we manually build a shader and draw that into our new mask 1183fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint tmpPaint; 1184fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmpPaint.setFlags(paint.getFlags()); 1185fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmpPaint.setFilterQuality(paint.getFilterQuality()); 1186fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paintWithShader = make_paint_with_image(tmpPaint, bitmap); 1187fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect rr; 1188fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot rr.set(0, 0, SkIntToScalar(bitmap.width()), 1189fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIntToScalar(bitmap.height())); 1190fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot c.drawRect(rr, paintWithShader); 1191fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1192fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawDevMask(mask, paint); 1193fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1194fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1195fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1196fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool clipped_out(const SkMatrix& m, const SkRasterClip& c, 1197fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect& srcR) { 1198fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect dstR; 1199fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot m.mapRect(&dstR, srcR); 1200fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return c.quickReject(dstR.roundOut()); 1201fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1202fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1203fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip, 1204fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int width, int height) { 1205fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect r; 1206fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 1207fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return clipped_out(matrix, clip, r); 1208fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1209fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1210fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, const SkPixmap& pmap) { 1211fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return clip.isBW() || clip.quickContains(x, y, x + pmap.width(), y + pmap.height()); 1212fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1213fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1214fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 1215fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect* dstBounds, const SkPaint& origPaint) const { 1216fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 1217fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1218fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // nothing to draw 1219fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty() || 1220fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap.width() == 0 || bitmap.height() == 0 || 1221fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap.colorType() == kUnknown_SkColorType) { 1222fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1223fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1224fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1225fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1226fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (origPaint.getStyle() != SkPaint::kFill_Style) { 1227fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.writable()->setStyle(SkPaint::kFill_Style); 1228fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1229fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1230fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix matrix; 1231fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.setConcat(*fMatrix, prematrix); 1232fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1233fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) { 1234fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1235fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1236fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1237fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (bitmap.colorType() != kAlpha_8_SkColorType 1238fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot && SkTreatAsSprite(matrix, bitmap.dimensions(), *paint)) { 1239fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 1240fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // It is safe to call lock pixels now, since we know the matrix is 1241fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // (more or less) identity. 1242fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 1243fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPixmap pmap; 1244fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!bitmap.peekPixels(&pmap)) { 1245fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1246fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1247fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int ix = SkScalarRoundToInt(matrix.getTranslateX()); 1248fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int iy = SkScalarRoundToInt(matrix.getTranslateY()); 1249fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (clipHandlesSprite(*fRC, ix, iy, pmap)) { 1250fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArenaAlloc<kSkBlitterContextSize> allocator; 1251fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // blitter will be owned by the allocator. 1252fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, *paint, pmap, ix, iy, &allocator); 1253fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (blitter) { 1254fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FillIRect(SkIRect::MakeXYWH(ix, iy, pmap.width(), pmap.height()), 1255fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *fRC, blitter); 1256fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1257fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1258fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // if !blitter, then we fall-through to the slower case 1259fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1260fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1261fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1262fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // now make a temp draw on the stack, and use it 1263fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // 1264fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDraw draw(*this); 1265fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.fMatrix = &matrix; 1266fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1267fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (bitmap.colorType() == kAlpha_8_SkColorType && !paint->getColorFilter()) { 1268fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.drawBitmapAsMask(bitmap, *paint); 1269fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1270fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paintWithShader = make_paint_with_image(*paint, bitmap); 1271fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height()); 1272fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (dstBounds) { 1273fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds); 1274fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1275fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.drawRect(srcBounds, paintWithShader); 1276fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1277fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1278fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1279fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1280fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& origPaint) const { 1281fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 1282fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1283fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // nothing to draw 1284fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->isEmpty() || 1285fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap.width() == 0 || bitmap.height() == 0 || 1286fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bitmap.colorType() == kUnknown_SkColorType) { 1287fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1288fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1289fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1290fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect bounds = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height()); 1291fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1292fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fRC->quickReject(bounds)) { 1293fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; // nothing to draw 1294fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1295fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1296fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paint(origPaint); 1297fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setStyle(SkPaint::kFill_Style); 1298fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1299fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPixmap pmap; 1300fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!bitmap.peekPixels(&pmap)) { 1301fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1302fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1303fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1304fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, pmap)) { 1305fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // blitter will be owned by the allocator. 1306fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkSTArenaAlloc<kSkBlitterContextSize> allocator; 1307fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter* blitter = SkBlitter::ChooseSprite(fDst, paint, pmap, x, y, &allocator); 1308fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (blitter) { 1309fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScan::FillIRect(bounds, *fRC, blitter); 1310fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1311fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1312fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1313fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1314fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix matrix; 1315fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRect r; 1316fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1317fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // get a scalar version of our rect 1318fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot r.set(bounds); 1319fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1320fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // create shader with offset 1321fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.setTranslate(r.fLeft, r.fTop); 1322fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paintWithShader = make_paint_with_image(paint, bitmap, &matrix); 1323fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDraw draw(*this); 1324fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.reset(); 1325fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.fMatrix = &matrix; 1326fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // call ourself with a rect 1327fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.drawRect(r, paintWithShader); 1328fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1329fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1330fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/////////////////////////////////////////////////////////////////////////////// 1331fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1332fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPaintPriv.h" 1333fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkScalerContext.h" 1334fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkGlyphCache.h" 1335fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkTextToPathIter.h" 1336fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkUtils.h" 1337fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1338fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm, SkScalar sizeLimit) { 1339fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // hairline glyphs are fast enough so we don't need to cache them 1340fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 1341fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1342fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1343fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1344fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we don't cache perspective 1345fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ctm.hasPerspective()) { 1346fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1347fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1348fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1349fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix textM; 1350fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaintPriv::MakeTextMatrix(&textM, paint); 1351fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return SkPaint::TooBigToUseCache(ctm, textM, sizeLimit); 1352fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1353fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1354fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawText_asPaths(const char text[], size_t byteLength, SkScalar x, SkScalar y, 1355fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& paint) const { 1356fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 1357fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1358fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTextToPathIter iter(text, byteLength, paint, true); 1359fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1360fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix matrix; 1361fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1362fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postTranslate(x, y); 1363fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1364fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPath* iterPath; 1365fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar xpos, prevXPos = 0; 1366fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1367fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (iter.next(&iterPath, &xpos)) { 1368fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.postTranslate(xpos - prevXPos, 0); 1369fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (iterPath) { 1370fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPath(*iterPath, iter.getPaint(), &matrix, false); 1371fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1372fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot prevXPos = xpos; 1373fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1374fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1375fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1376fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot// disable warning : local variable used without having been initialized 1377fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined _WIN32 1378fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#pragma warning ( push ) 1379fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#pragma warning ( disable : 4701 ) 1380fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1381fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1382fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////////// 1383fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1384fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotclass DrawOneGlyph { 1385fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotpublic: 1386fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter) 1387fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot : fUseRegionToDraw(UsingRegionToDraw(draw.fRC)) 1388fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fGlyphCache(cache) 1389fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fBlitter(blitter) 1390fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr) 1391fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fDraw(draw) 1392fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fPaint(paint) 1393fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot , fClipBounds(PickClipBounds(draw)) { } 1394fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1395fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) { 1396fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot position += rounding; 1397fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Prevent glyphs from being drawn outside of or straddling the edge of device space. 1398fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Comparisons written a little weirdly so that NaN coordinates are treated safely. 1399fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto gt = [](float a, int b) { return !(a <= (float)b); }; 1400fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot auto lt = [](float a, int b) { return !(a >= (float)b); }; 1401fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (gt(position.fX, INT_MAX - (INT16_MAX + UINT16_MAX)) || 1402fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) || 1403fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot gt(position.fY, INT_MAX - (INT16_MAX + UINT16_MAX)) || 1404fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))) { 1405fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1406fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1407fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1408fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int left = SkScalarFloorToInt(position.fX); 1409fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int top = SkScalarFloorToInt(position.fY); 1410fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1411fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1412fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot left += glyph.fLeft; 1413fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot top += glyph.fTop; 1414fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1415fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int right = left + glyph.fWidth; 1416fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int bottom = top + glyph.fHeight; 1417fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1418fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMask mask; 1419fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask.fBounds.set(left, top, right, bottom); 1420fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!mask.fBounds.isEmpty()); 1421fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1422fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (fUseRegionToDraw) { 1423fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRegion::Cliperator clipper(*fClip, mask.fBounds); 1424fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1425fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!clipper.done() && this->getImageData(glyph, &mask)) { 1426fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& cr = clipper.rect(); 1427fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot do { 1428fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->blitMask(mask, cr); 1429fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clipper.next(); 1430fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } while (!clipper.done()); 1431fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1432fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1433fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect storage; 1434fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect* bounds = &mask.fBounds; 1435fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1436fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // this extra test is worth it, assuming that most of the time it succeeds 1437fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // since we can avoid writing to storage 1438fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) { 1439fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds)) 1440fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1441fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bounds = &storage; 1442fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1443fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1444fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (this->getImageData(glyph, &mask)) { 1445fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->blitMask(mask, *bounds); 1446fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1447fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1448fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1449fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1450fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotprivate: 1451fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static bool UsingRegionToDraw(const SkRasterClip* rClip) { 1452fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rClip->isBW() && !rClip->isRect(); 1453fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1454fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1455fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static SkIRect PickClipBounds(const SkDraw& draw) { 1456fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRasterClip& rasterClip = *draw.fRC; 1457fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1458fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (rasterClip.isBW()) { 1459fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rasterClip.bwRgn().getBounds(); 1460fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1461fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return rasterClip.aaRgn().getBounds(); 1462fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1463fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1464fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1465fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bool getImageData(const SkGlyph& glyph, SkMask* mask) { 1466fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph)); 1467fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (nullptr == bits) { 1468fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; // can't rasterize glyph 1469fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1470fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask->fImage = bits; 1471fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask->fRowBytes = glyph.rowBytes(); 1472fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1473fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1474fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1475fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1476fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot void blitMask(const SkMask& mask, const SkIRect& clip) const { 1477fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkMask::kARGB32_Format == mask.fFormat) { 1478fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBitmap bm; 1479fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot bm.installPixels( 1480fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()), 1481fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot (SkPMColor*)mask.fImage, mask.fRowBytes); 1482fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1483fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint); 1484fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } else { 1485fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot fBlitter->blitMask(mask, clip); 1486fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1487fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1488fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1489fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const bool fUseRegionToDraw; 1490fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkGlyphCache * const fGlyphCache; 1491fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkBlitter * const fBlitter; 1492fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkRegion* const fClip; 1493fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkDraw& fDraw; 1494fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& fPaint; 1495fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect fClipBounds; 1496fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}; 1497fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1498fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////////// 1499fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1500fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotSkScalerContextFlags SkDraw::scalerContextFlags() const { 1501fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalerContextFlags flags = SkScalerContextFlags::kBoostContrast; 1502fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!fDst.colorSpace()) { 1503fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot flags = kFakeGammaAndBoostContrast; 1504fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1505fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return flags; 1506fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1507fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1508fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawText(const char text[], size_t byteLength, SkScalar x, SkScalar y, 1509fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& paint, const SkSurfaceProps* props) const { 1510fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(byteLength == 0 || text != nullptr); 1511fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1512fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 1513fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1514fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // nothing to draw 1515fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1516fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1517fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1518fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1519fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // SkScalarRec doesn't currently have a way of representing hairline stroke and 1520fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // will fill if its frame-width is 0. 1521fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1522fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawText_asPaths(text, byteLength, x, y, paint); 1523fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1524fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1525fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1526fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoGlyphCache cache(paint, props, this->scalerContextFlags(), fMatrix); 1527fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1528fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The Blitter Choose needs to be live while using the blitter below. 1529fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1530fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1531fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DrawOneGlyph drawOneGlyph(*this, paint, cache.get(), wrapper.getBlitter()); 1532fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1533fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFindAndPlaceGlyph::ProcessText( 1534fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.getTextEncoding(), text, byteLength, 1535fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot {x, y}, *fMatrix, paint.getTextAlign(), cache.get(), drawOneGlyph); 1536fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1537fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1538fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot////////////////////////////////////////////////////////////////////////////// 1539fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1540fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, const SkScalar pos[], 1541fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int scalarsPerPosition, const SkPoint& offset, 1542fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPaint& origPaint, const SkSurfaceProps* props) const { 1543fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // setup our std paint, in hopes of getting hits in the cache 1544fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paint(origPaint); 1545fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkScalar matrixScale = paint.setupForAsPaths(); 1546fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1547fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix matrix; 1548fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.setScale(matrixScale, matrixScale); 1549fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1550fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 1551fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setStyle(SkPaint::kFill_Style); 1552fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setPathEffect(nullptr); 1553fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1554fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(paint.getTextEncoding(), 1555fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.isDevKernText(), 1556fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot true); 1557fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoGlyphCache cache(paint, props, this->scalerContextFlags(), nullptr); 1558fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1559fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const char* stop = text + byteLength; 1560fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTextAlignProc alignProc(paint.getTextAlign()); 1561fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 1562fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1563fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Now restore the original settings, so we "draw" with whatever style/stroking. 1564fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setStyle(origPaint.getStyle()); 1565fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setPathEffect(origPaint.refPathEffect()); 1566fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1567fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot while (text < stop) { 1568fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkGlyph& glyph = glyphCacheProc(cache.get(), &text); 1569fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (glyph.fWidth) { 1570fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkPath* path = cache->findPath(glyph); 1571fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (path) { 1572fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint tmsLoc; 1573fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot tmsProc(pos, &tmsLoc); 1574fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPoint loc; 1575fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot alignProc(tmsLoc, glyph, &loc); 1576fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1577fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix[SkMatrix::kMTransX] = loc.fX; 1578fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix[SkMatrix::kMTransY] = loc.fY; 1579fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPath(*path, paint, &matrix, false); 1580fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1581fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1582fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot pos += scalarsPerPosition; 1583fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1584fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1585fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1586fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::drawPosText(const char text[], size_t byteLength, const SkScalar pos[], 1587fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot int scalarsPerPosition, const SkPoint& offset, const SkPaint& paint, 1588fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkSurfaceProps* props) const { 1589fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(byteLength == 0 || text != nullptr); 1590fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 1591fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1592fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDEBUGCODE(this->validate();) 1593fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1594fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // nothing to draw 1595fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1596fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1597fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1598fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1599fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1600fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, offset, paint, props); 1601fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1602fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1603fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1604fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoGlyphCache cache(paint, props, this->scalerContextFlags(), fMatrix); 1605fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1606fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // The Blitter Choose needs to be live while using the blitter below. 1607fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1608fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1609fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot DrawOneGlyph drawOneGlyph(*this, paint, cache.get(), wrapper.getBlitter()); 1610fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint::Align textAlignment = paint.getTextAlign(); 1611fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1612fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkFindAndPlaceGlyph::ProcessPosText( 1613fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.getTextEncoding(), text, byteLength, 1614fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache.get(), drawOneGlyph); 1615fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1616fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1617fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#if defined _WIN32 1618fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#pragma warning ( pop ) 1619fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1620fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1621fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////// 1622fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1623fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#ifdef SK_DEBUG 1624fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1625fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid SkDraw::validate() const { 1626fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fMatrix != nullptr); 1627fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(fRC != nullptr); 1628fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1629fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkIRect& cr = fRC->getBounds(); 1630fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect br; 1631fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1632fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot br.set(0, 0, fDst.width(), fDst.height()); 1633fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(cr.isEmpty() || br.contains(cr)); 1634fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1635fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1636fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#endif 1637fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1638fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot//////////////////////////////////////////////////////////////////////////////////////////////// 1639fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1640fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkPath.h" 1641fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkDraw.h" 1642fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkRegion.h" 1643fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkBlitter.h" 1644fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1645fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 1646fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMaskFilter* filter, const SkMatrix* filterMatrix, 1647fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIRect* bounds) { 1648fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (devPath.isEmpty()) { 1649fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1650fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1651fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1652fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // init our bounds from the path 1653fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *bounds = devPath.getBounds().makeOutset(SK_ScalarHalf, SK_ScalarHalf).roundOut(); 1654fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1655fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkIPoint margin = SkIPoint::Make(0, 0); 1656fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (filter) { 1657fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(filterMatrix); 1658fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1659fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMask srcM, dstM; 1660fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1661fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot srcM.fBounds = *bounds; 1662fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot srcM.fFormat = SkMask::kA8_Format; 1663fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!as_MFB(filter)->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 1664fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1665fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1666fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1667fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1668fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // (possibly) trim the bounds to reflect the clip 1669fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // (plus whatever slop the filter needs) 1670fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (clipBounds) { 1671fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // Ugh. Guard against gigantic margins from wacky filters. Without this 1672fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // check we can request arbitrary amounts of slop beyond our visible 1673fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // clip, and bring down the renderer (at least on finite RAM machines 1674fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // like handsets, etc.). Need to balance this invented value between 1675fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // quality of large filters like blurs, and the corresponding memory 1676fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // requests. 1677fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot static const int MAX_MARGIN = 128; 1678fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!bounds->intersect(clipBounds->makeOutset(SkMin32(margin.fX, MAX_MARGIN), 1679fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMin32(margin.fY, MAX_MARGIN)))) { 1680fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1681fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1682fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1683fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1684fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1685fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1686fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1687fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotstatic void draw_into_mask(const SkMask& mask, const SkPath& devPath, 1688fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStrokeRec::InitStyle style) { 1689fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkDraw draw; 1690fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!draw.fDst.reset(mask)) { 1691fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return; 1692fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1693fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1694fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkRasterClip clip; 1695fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMatrix matrix; 1696fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkPaint paint; 1697fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1698fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height())); 1699fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 1700fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot -SkIntToScalar(mask.fBounds.fTop)); 1701fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1702fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.fRC = &clip; 1703fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.fMatrix = &matrix; 1704fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setAntiAlias(true); 1705fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot switch (style) { 1706fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkStrokeRec::kHairline_InitStyle: 1707fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(!paint.getStrokeWidth()); 1708fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot paint.setStyle(SkPaint::kStroke_Style); 1709fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1710fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot case SkStrokeRec::kFill_InitStyle: 1711fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkASSERT(paint.getStyle() == SkPaint::kFill_Style); 1712fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot break; 1713fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1714fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1715fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw.drawPath(devPath, paint); 1716fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1717fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1718fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 1719fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot const SkMaskFilter* filter, const SkMatrix* filterMatrix, 1720fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkMask* mask, SkMask::CreateMode mode, 1721fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot SkStrokeRec::InitStyle style) { 1722fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkMask::kJustRenderImage_CreateMode != mode) { 1723fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 1724fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1725fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1726fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1727fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 1728fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask->fFormat = SkMask::kA8_Format; 1729fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask->fRowBytes = mask->fBounds.width(); 1730fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot size_t size = mask->computeImageSize(); 1731fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (0 == size) { 1732fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot // we're too big to allocate the mask, abort 1733fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return false; 1734fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1735fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot mask->fImage = SkMask::AllocImage(size, SkMask::kZeroInit_Alloc); 1736fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1737fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1738fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot if (SkMask::kJustComputeBounds_CreateMode != mode) { 1739fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot draw_into_mask(*mask, devPath, style); 1740fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot } 1741fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot 1742fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot return true; 1743fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot} 1744