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