1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkDraw.h"
9#include "SkBlitter.h"
10#include "SkBounder.h"
11#include "SkCanvas.h"
12#include "SkColorPriv.h"
13#include "SkDevice.h"
14#include "SkDeviceLooper.h"
15#include "SkFixed.h"
16#include "SkMaskFilter.h"
17#include "SkPaint.h"
18#include "SkPathEffect.h"
19#include "SkRasterClip.h"
20#include "SkRasterizer.h"
21#include "SkRRect.h"
22#include "SkScan.h"
23#include "SkShader.h"
24#include "SkString.h"
25#include "SkStroke.h"
26#include "SkTemplatesPriv.h"
27#include "SkTLazy.h"
28#include "SkUtils.h"
29
30#include "SkAutoKern.h"
31#include "SkBitmapProcShader.h"
32#include "SkDrawProcs.h"
33#include "SkMatrixUtils.h"
34
35bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
36    // we don't cache hairlines in the cache
37    if (SkPaint::kStroke_Style == paint.getStyle() &&
38            0 == paint.getStrokeWidth()) {
39        return true;
40    }
41
42    // we don't cache perspective
43    if (ctm.hasPerspective()) {
44        return true;
45    }
46
47    SkMatrix textM;
48    return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
49}
50
51//#define TRACE_BITMAP_DRAWS
52
53#define kBlitterStorageLongCount    (sizeof(SkBitmapProcShader) >> 2)
54
55/** Helper for allocating small blitters on the stack.
56 */
57class SkAutoBlitterChoose : SkNoncopyable {
58public:
59    SkAutoBlitterChoose() {
60        fBlitter = NULL;
61    }
62    SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
63                        const SkPaint& paint) {
64        fBlitter = SkBlitter::Choose(device, matrix, paint,
65                                     fStorage, sizeof(fStorage));
66    }
67
68    ~SkAutoBlitterChoose();
69
70    SkBlitter*  operator->() { return fBlitter; }
71    SkBlitter*  get() const { return fBlitter; }
72
73    void choose(const SkBitmap& device, const SkMatrix& matrix,
74                const SkPaint& paint) {
75        SkASSERT(!fBlitter);
76        fBlitter = SkBlitter::Choose(device, matrix, paint,
77                                     fStorage, sizeof(fStorage));
78    }
79
80private:
81    SkBlitter*  fBlitter;
82    uint32_t    fStorage[kBlitterStorageLongCount];
83};
84
85SkAutoBlitterChoose::~SkAutoBlitterChoose() {
86    if ((void*)fBlitter == (void*)fStorage) {
87        fBlitter->~SkBlitter();
88    } else {
89        SkDELETE(fBlitter);
90    }
91}
92
93/**
94 *  Since we are providing the storage for the shader (to avoid the perf cost
95 *  of calling new) we insist that in our destructor we can account for all
96 *  owners of the shader.
97 */
98class SkAutoBitmapShaderInstall : SkNoncopyable {
99public:
100    SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
101            : fPaint(paint) /* makes a copy of the paint */ {
102        fPaint.setShader(SkShader::CreateBitmapShader(src,
103                           SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
104                           fStorage, sizeof(fStorage)));
105        // we deliberately left the shader with an owner-count of 2
106        SkASSERT(2 == fPaint.getShader()->getRefCnt());
107    }
108
109    ~SkAutoBitmapShaderInstall() {
110        SkShader* shader = fPaint.getShader();
111        // since we manually destroy shader, we insist that owners == 2
112        SkASSERT(2 == shader->getRefCnt());
113
114        fPaint.setShader(NULL); // unref the shader by 1
115
116        // now destroy to take care of the 2nd owner-count
117        if ((void*)shader == (void*)fStorage) {
118            shader->~SkShader();
119        } else {
120            SkDELETE(shader);
121        }
122    }
123
124    // return the new paint that has the shader applied
125    const SkPaint& paintWithShader() const { return fPaint; }
126
127private:
128    SkPaint     fPaint; // copy of caller's paint (which we then modify)
129    uint32_t    fStorage[kBlitterStorageLongCount];
130};
131
132///////////////////////////////////////////////////////////////////////////////
133
134SkDraw::SkDraw() {
135    sk_bzero(this, sizeof(*this));
136}
137
138SkDraw::SkDraw(const SkDraw& src) {
139    memcpy(this, &src, sizeof(*this));
140}
141
142bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
143    if (fRC->isEmpty()) {
144        return false;
145    }
146
147    SkMatrix inverse;
148    if (!fMatrix->invert(&inverse)) {
149        return false;
150    }
151
152    SkIRect devBounds = fRC->getBounds();
153    // outset to have slop for antialasing and hairlines
154    devBounds.outset(1, 1);
155    inverse.mapRect(localBounds, SkRect::Make(devBounds));
156    return true;
157}
158
159///////////////////////////////////////////////////////////////////////////////
160
161typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
162
163static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
164    sk_bzero(pixels, bytes);
165}
166
167static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
168
169static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
170    sk_memset32((uint32_t*)pixels, data, bytes >> 2);
171}
172
173static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
174    sk_memset16((uint16_t*)pixels, data, bytes >> 1);
175}
176
177static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
178    memset(pixels, data, bytes);
179}
180
181static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
182                                           const SkPaint& paint,
183                                           uint32_t* data) {
184    // todo: we can apply colorfilter up front if no shader, so we wouldn't
185    // need to abort this fastpath
186    if (paint.getShader() || paint.getColorFilter()) {
187        return NULL;
188    }
189
190    SkXfermode::Mode mode;
191    if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
192        return NULL;
193    }
194
195    SkColor color = paint.getColor();
196
197    // collaps modes based on color...
198    if (SkXfermode::kSrcOver_Mode == mode) {
199        unsigned alpha = SkColorGetA(color);
200        if (0 == alpha) {
201            mode = SkXfermode::kDst_Mode;
202        } else if (0xFF == alpha) {
203            mode = SkXfermode::kSrc_Mode;
204        }
205    }
206
207    switch (mode) {
208        case SkXfermode::kClear_Mode:
209//            SkDebugf("--- D_Clear_BitmapXferProc\n");
210            return D_Clear_BitmapXferProc;  // ignore data
211        case SkXfermode::kDst_Mode:
212//            SkDebugf("--- D_Dst_BitmapXferProc\n");
213            return D_Dst_BitmapXferProc;    // ignore data
214        case SkXfermode::kSrc_Mode: {
215            /*
216                should I worry about dithering for the lower depths?
217            */
218            SkPMColor pmc = SkPreMultiplyColor(color);
219            switch (bitmap.config()) {
220                case SkBitmap::kARGB_8888_Config:
221                    if (data) {
222                        *data = pmc;
223                    }
224//                    SkDebugf("--- D32_Src_BitmapXferProc\n");
225                    return D32_Src_BitmapXferProc;
226                case SkBitmap::kRGB_565_Config:
227                    if (data) {
228                        *data = SkPixel32ToPixel16(pmc);
229                    }
230//                    SkDebugf("--- D16_Src_BitmapXferProc\n");
231                    return D16_Src_BitmapXferProc;
232                case SkBitmap::kA8_Config:
233                    if (data) {
234                        *data = SkGetPackedA32(pmc);
235                    }
236//                    SkDebugf("--- DA8_Src_BitmapXferProc\n");
237                    return DA8_Src_BitmapXferProc;
238                default:
239                    break;
240            }
241            break;
242        }
243        default:
244            break;
245    }
246    return NULL;
247}
248
249static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
250                               BitmapXferProc proc, uint32_t procData) {
251    int shiftPerPixel;
252    switch (bitmap.config()) {
253        case SkBitmap::kARGB_8888_Config:
254            shiftPerPixel = 2;
255            break;
256        case SkBitmap::kRGB_565_Config:
257            shiftPerPixel = 1;
258            break;
259        case SkBitmap::kA8_Config:
260            shiftPerPixel = 0;
261            break;
262        default:
263            SkDEBUGFAIL("Can't use xferproc on this config");
264            return;
265    }
266
267    uint8_t* pixels = (uint8_t*)bitmap.getPixels();
268    SkASSERT(pixels);
269    const size_t rowBytes = bitmap.rowBytes();
270    const int widthBytes = rect.width() << shiftPerPixel;
271
272    // skip down to the first scanline and X position
273    pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel);
274    for (int scans = rect.height() - 1; scans >= 0; --scans) {
275        proc(pixels, widthBytes, procData);
276        pixels += rowBytes;
277    }
278}
279
280void SkDraw::drawPaint(const SkPaint& paint) const {
281    SkDEBUGCODE(this->validate();)
282
283    if (fRC->isEmpty()) {
284        return;
285    }
286
287    SkIRect    devRect;
288    devRect.set(0, 0, fBitmap->width(), fBitmap->height());
289    if (fBounder && !fBounder->doIRect(devRect)) {
290        return;
291    }
292
293    if (fRC->isBW()) {
294        /*  If we don't have a shader (i.e. we're just a solid color) we may
295            be faster to operate directly on the device bitmap, rather than invoking
296            a blitter. Esp. true for xfermodes, which require a colorshader to be
297            present, which is just redundant work. Since we're drawing everywhere
298            in the clip, we don't have to worry about antialiasing.
299        */
300        uint32_t procData = 0;  // to avoid the warning
301        BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData);
302        if (proc) {
303            if (D_Dst_BitmapXferProc == proc) { // nothing to do
304                return;
305            }
306
307            SkRegion::Iterator iter(fRC->bwRgn());
308            while (!iter.done()) {
309                CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData);
310                iter.next();
311            }
312            return;
313        }
314    }
315
316    // normal case: use a blitter
317    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
318    SkScan::FillIRect(devRect, *fRC, blitter.get());
319}
320
321///////////////////////////////////////////////////////////////////////////////
322
323struct PtProcRec {
324    SkCanvas::PointMode fMode;
325    const SkPaint*  fPaint;
326    const SkRegion* fClip;
327    const SkRasterClip* fRC;
328
329    // computed values
330    SkFixed fRadius;
331
332    typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count,
333                         SkBlitter*);
334
335    bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix,
336              const SkRasterClip*);
337    Proc chooseProc(SkBlitter** blitter);
338
339private:
340    SkAAClipBlitterWrapper fWrapper;
341};
342
343static void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
344                                 int count, SkBlitter* blitter) {
345    SkASSERT(rec.fClip->isRect());
346    const SkIRect& r = rec.fClip->getBounds();
347
348    for (int i = 0; i < count; i++) {
349        int x = SkScalarFloorToInt(devPts[i].fX);
350        int y = SkScalarFloorToInt(devPts[i].fY);
351        if (r.contains(x, y)) {
352            blitter->blitH(x, y, 1);
353        }
354    }
355}
356
357static void bw_pt_rect_16_hair_proc(const PtProcRec& rec,
358                                    const SkPoint devPts[], int count,
359                                    SkBlitter* blitter) {
360    SkASSERT(rec.fRC->isRect());
361    const SkIRect& r = rec.fRC->getBounds();
362    uint32_t value;
363    const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
364    SkASSERT(bitmap);
365
366    uint16_t* addr = bitmap->getAddr16(0, 0);
367    size_t    rb = bitmap->rowBytes();
368
369    for (int i = 0; i < count; i++) {
370        int x = SkScalarFloorToInt(devPts[i].fX);
371        int y = SkScalarFloorToInt(devPts[i].fY);
372        if (r.contains(x, y)) {
373            ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value);
374        }
375    }
376}
377
378static void bw_pt_rect_32_hair_proc(const PtProcRec& rec,
379                                    const SkPoint devPts[], int count,
380                                    SkBlitter* blitter) {
381    SkASSERT(rec.fRC->isRect());
382    const SkIRect& r = rec.fRC->getBounds();
383    uint32_t value;
384    const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
385    SkASSERT(bitmap);
386
387    SkPMColor* addr = bitmap->getAddr32(0, 0);
388    size_t     rb = bitmap->rowBytes();
389
390    for (int i = 0; i < count; i++) {
391        int x = SkScalarFloorToInt(devPts[i].fX);
392        int y = SkScalarFloorToInt(devPts[i].fY);
393        if (r.contains(x, y)) {
394            ((SkPMColor*)((char*)addr + y * rb))[x] = value;
395        }
396    }
397}
398
399static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
400                            int count, SkBlitter* blitter) {
401    for (int i = 0; i < count; i++) {
402        int x = SkScalarFloor(devPts[i].fX);
403        int y = SkScalarFloor(devPts[i].fY);
404        if (rec.fClip->contains(x, y)) {
405            blitter->blitH(x, y, 1);
406        }
407    }
408}
409
410static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
411                              int count, SkBlitter* blitter) {
412    for (int i = 0; i < count; i += 2) {
413        SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
414    }
415}
416
417static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
418                              int count, SkBlitter* blitter) {
419    for (int i = 0; i < count - 1; i++) {
420        SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
421    }
422}
423
424// aa versions
425
426static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
427                              int count, SkBlitter* blitter) {
428    for (int i = 0; i < count; i += 2) {
429        SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
430    }
431}
432
433static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
434                              int count, SkBlitter* blitter) {
435    for (int i = 0; i < count - 1; i++) {
436        SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter);
437    }
438}
439
440// square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
441
442static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[],
443                           int count, SkBlitter* blitter) {
444    const SkFixed radius = rec.fRadius;
445    for (int i = 0; i < count; i++) {
446        SkFixed x = SkScalarToFixed(devPts[i].fX);
447        SkFixed y = SkScalarToFixed(devPts[i].fY);
448
449        SkXRect r;
450        r.fLeft = x - radius;
451        r.fTop = y - radius;
452        r.fRight = x + radius;
453        r.fBottom = y + radius;
454
455        SkScan::FillXRect(r, *rec.fRC, blitter);
456    }
457}
458
459static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[],
460                           int count, SkBlitter* blitter) {
461    const SkFixed radius = rec.fRadius;
462    for (int i = 0; i < count; i++) {
463        SkFixed x = SkScalarToFixed(devPts[i].fX);
464        SkFixed y = SkScalarToFixed(devPts[i].fY);
465
466        SkXRect r;
467        r.fLeft = x - radius;
468        r.fTop = y - radius;
469        r.fRight = x + radius;
470        r.fBottom = y + radius;
471
472        SkScan::AntiFillXRect(r, *rec.fRC, blitter);
473    }
474}
475
476// If this guy returns true, then chooseProc() must return a valid proc
477bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint,
478                     const SkMatrix* matrix, const SkRasterClip* rc) {
479    if (paint.getPathEffect()) {
480        return false;
481    }
482    SkScalar width = paint.getStrokeWidth();
483    if (0 == width) {
484        fMode = mode;
485        fPaint = &paint;
486        fClip = NULL;
487        fRC = rc;
488        fRadius = SK_FixedHalf;
489        return true;
490    }
491    if (paint.getStrokeCap() != SkPaint::kRound_Cap &&
492            matrix->rectStaysRect() && SkCanvas::kPoints_PointMode == mode) {
493        SkScalar sx = matrix->get(SkMatrix::kMScaleX);
494        SkScalar sy = matrix->get(SkMatrix::kMScaleY);
495        if (SkScalarNearlyZero(sx - sy)) {
496            if (sx < 0) {
497                sx = -sx;
498            }
499
500            fMode = mode;
501            fPaint = &paint;
502            fClip = NULL;
503            fRC = rc;
504            fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1;
505            return true;
506        }
507    }
508    return false;
509}
510
511PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
512    Proc proc = NULL;
513
514    SkBlitter* blitter = *blitterPtr;
515    if (fRC->isBW()) {
516        fClip = &fRC->bwRgn();
517    } else {
518        fWrapper.init(*fRC, blitter);
519        fClip = &fWrapper.getRgn();
520        blitter = fWrapper.getBlitter();
521        *blitterPtr = blitter;
522    }
523
524    // for our arrays
525    SkASSERT(0 == SkCanvas::kPoints_PointMode);
526    SkASSERT(1 == SkCanvas::kLines_PointMode);
527    SkASSERT(2 == SkCanvas::kPolygon_PointMode);
528    SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode);
529
530    if (fPaint->isAntiAlias()) {
531        if (0 == fPaint->getStrokeWidth()) {
532            static const Proc gAAProcs[] = {
533                aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc
534            };
535            proc = gAAProcs[fMode];
536        } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) {
537            SkASSERT(SkCanvas::kPoints_PointMode == fMode);
538            proc = aa_square_proc;
539        }
540    } else {    // BW
541        if (fRadius <= SK_FixedHalf) {    // small radii and hairline
542            if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
543                uint32_t value;
544                const SkBitmap* bm = blitter->justAnOpaqueColor(&value);
545                if (bm && SkBitmap::kRGB_565_Config == bm->config()) {
546                    proc = bw_pt_rect_16_hair_proc;
547                } else if (bm && SkBitmap::kARGB_8888_Config == bm->config()) {
548                    proc = bw_pt_rect_32_hair_proc;
549                } else {
550                    proc = bw_pt_rect_hair_proc;
551                }
552            } else {
553                static Proc gBWProcs[] = {
554                    bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc
555                };
556                proc = gBWProcs[fMode];
557            }
558        } else {
559            proc = bw_square_proc;
560        }
561    }
562    return proc;
563}
564
565static bool bounder_points(SkBounder* bounder, SkCanvas::PointMode mode,
566                           size_t count, const SkPoint pts[],
567                           const SkPaint& paint, const SkMatrix& matrix) {
568    SkIRect ibounds;
569    SkRect bounds;
570    SkScalar inset = paint.getStrokeWidth();
571
572    bounds.set(pts, count);
573    bounds.inset(-inset, -inset);
574    matrix.mapRect(&bounds);
575
576    bounds.roundOut(&ibounds);
577    return bounder->doIRect(ibounds);
578}
579
580// each of these costs 8-bytes of stack space, so don't make it too large
581// must be even for lines/polygon to work
582#define MAX_DEV_PTS     32
583
584void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
585                        const SkPoint pts[], const SkPaint& paint,
586                        bool forceUseDevice) const {
587    // if we're in lines mode, force count to be even
588    if (SkCanvas::kLines_PointMode == mode) {
589        count &= ~(size_t)1;
590    }
591
592    if ((long)count <= 0) {
593        return;
594    }
595
596    SkASSERT(pts != NULL);
597    SkDEBUGCODE(this->validate();)
598
599     // nothing to draw
600    if (fRC->isEmpty()) {
601        return;
602    }
603
604    if (fBounder) {
605        if (!bounder_points(fBounder, mode, count, pts, paint, *fMatrix)) {
606            return;
607        }
608
609        // clear the bounder and call this again, so we don't invoke the bounder
610        // later if we happen to call ourselves for drawRect, drawPath, etc.
611        SkDraw noBounder(*this);
612        noBounder.fBounder = NULL;
613        noBounder.drawPoints(mode, count, pts, paint, forceUseDevice);
614        return;
615    }
616
617    PtProcRec rec;
618    if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) {
619        SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
620
621        SkPoint             devPts[MAX_DEV_PTS];
622        const SkMatrix*     matrix = fMatrix;
623        SkBlitter*          bltr = blitter.get();
624        PtProcRec::Proc     proc = rec.chooseProc(&bltr);
625        // we have to back up subsequent passes if we're in polygon mode
626        const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
627
628        do {
629            size_t n = count;
630            if (n > MAX_DEV_PTS) {
631                n = MAX_DEV_PTS;
632            }
633            matrix->mapPoints(devPts, pts, n);
634            proc(rec, devPts, n, bltr);
635            pts += n - backup;
636            SkASSERT(count >= n);
637            count -= n;
638            if (count > 0) {
639                count += backup;
640            }
641        } while (count != 0);
642    } else {
643        switch (mode) {
644            case SkCanvas::kPoints_PointMode: {
645                // temporarily mark the paint as filling.
646                SkPaint newPaint(paint);
647                newPaint.setStyle(SkPaint::kFill_Style);
648
649                SkScalar width = newPaint.getStrokeWidth();
650                SkScalar radius = SkScalarHalf(width);
651
652                if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
653                    SkPath      path;
654                    SkMatrix    preMatrix;
655
656                    path.addCircle(0, 0, radius);
657                    for (size_t i = 0; i < count; i++) {
658                        preMatrix.setTranslate(pts[i].fX, pts[i].fY);
659                        // pass true for the last point, since we can modify
660                        // then path then
661                        if (fDevice) {
662                            fDevice->drawPath(*this, path, newPaint, &preMatrix,
663                                              (count-1) == i);
664                        } else {
665                            this->drawPath(path, newPaint, &preMatrix,
666                                           (count-1) == i);
667                        }
668                    }
669                } else {
670                    SkRect  r;
671
672                    for (size_t i = 0; i < count; i++) {
673                        r.fLeft = pts[i].fX - radius;
674                        r.fTop = pts[i].fY - radius;
675                        r.fRight = r.fLeft + width;
676                        r.fBottom = r.fTop + width;
677                        if (fDevice) {
678                            fDevice->drawRect(*this, r, newPaint);
679                        } else {
680                            this->drawRect(r, newPaint);
681                        }
682                    }
683                }
684                break;
685            }
686            case SkCanvas::kLines_PointMode:
687#ifndef SK_DISABLE_DASHING_OPTIMIZATION
688                if (2 == count && NULL != paint.getPathEffect()) {
689                    // most likely a dashed line - see if it is one of the ones
690                    // we can accelerate
691                    SkStrokeRec rec(paint);
692                    SkPathEffect::PointData pointData;
693
694                    SkPath path;
695                    path.moveTo(pts[0]);
696                    path.lineTo(pts[1]);
697
698                    SkRect cullRect = SkRect::Make(fRC->getBounds());
699
700                    if (paint.getPathEffect()->asPoints(&pointData, path, rec,
701                                                        *fMatrix, &cullRect)) {
702                        // 'asPoints' managed to find some fast path
703
704                        SkPaint newP(paint);
705                        newP.setPathEffect(NULL);
706                        newP.setStyle(SkPaint::kFill_Style);
707
708                        if (!pointData.fFirst.isEmpty()) {
709                            if (fDevice) {
710                                fDevice->drawPath(*this, pointData.fFirst, newP);
711                            } else {
712                                this->drawPath(pointData.fFirst, newP);
713                            }
714                        }
715
716                        if (!pointData.fLast.isEmpty()) {
717                            if (fDevice) {
718                                fDevice->drawPath(*this, pointData.fLast, newP);
719                            } else {
720                                this->drawPath(pointData.fLast, newP);
721                            }
722                        }
723
724                        if (pointData.fSize.fX == pointData.fSize.fY) {
725                            // The rest of the dashed line can just be drawn as points
726                            SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth()));
727
728                            if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) {
729                                newP.setStrokeCap(SkPaint::kRound_Cap);
730                            } else {
731                                newP.setStrokeCap(SkPaint::kButt_Cap);
732                            }
733
734                            if (fDevice) {
735                                fDevice->drawPoints(*this,
736                                                    SkCanvas::kPoints_PointMode,
737                                                    pointData.fNumPoints,
738                                                    pointData.fPoints,
739                                                    newP);
740                            } else {
741                                this->drawPoints(SkCanvas::kPoints_PointMode,
742                                                 pointData.fNumPoints,
743                                                 pointData.fPoints,
744                                                 newP,
745                                                 forceUseDevice);
746                            }
747                            break;
748                        } else {
749                            // The rest of the dashed line must be drawn as rects
750                            SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag &
751                                      pointData.fFlags));
752
753                            SkRect r;
754
755                            for (int i = 0; i < pointData.fNumPoints; ++i) {
756                                r.set(pointData.fPoints[i].fX - pointData.fSize.fX,
757                                      pointData.fPoints[i].fY - pointData.fSize.fY,
758                                      pointData.fPoints[i].fX + pointData.fSize.fX,
759                                      pointData.fPoints[i].fY + pointData.fSize.fY);
760                                if (fDevice) {
761                                    fDevice->drawRect(*this, r, newP);
762                                } else {
763                                    this->drawRect(r, newP);
764                                }
765                            }
766                        }
767
768                        break;
769                    }
770                }
771#endif // DISABLE_DASHING_OPTIMIZATION
772                // couldn't take fast path so fall through!
773            case SkCanvas::kPolygon_PointMode: {
774                count -= 1;
775                SkPath path;
776                SkPaint p(paint);
777                p.setStyle(SkPaint::kStroke_Style);
778                size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
779                for (size_t i = 0; i < count; i += inc) {
780                    path.moveTo(pts[i]);
781                    path.lineTo(pts[i+1]);
782                    if (fDevice) {
783                        fDevice->drawPath(*this, path, p, NULL, true);
784                    } else {
785                        this->drawPath(path, p, NULL, true);
786                    }
787                    path.rewind();
788                }
789                break;
790            }
791        }
792    }
793}
794
795static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix,
796                           SkPoint* strokeSize) {
797    if (SkPaint::kMiter_Join != paint.getStrokeJoin() ||
798        paint.getStrokeMiter() < SK_ScalarSqrt2) {
799        return false;
800    }
801
802    SkASSERT(matrix.rectStaysRect());
803    SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
804    matrix.mapVectors(strokeSize, &pt, 1);
805    strokeSize->fX = SkScalarAbs(strokeSize->fX);
806    strokeSize->fY = SkScalarAbs(strokeSize->fY);
807    return true;
808}
809
810SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
811                                         const SkMatrix& matrix,
812                                         SkPoint* strokeSize) {
813    RectType rtype;
814    const SkScalar width = paint.getStrokeWidth();
815    const bool zeroWidth = (0 == width);
816    SkPaint::Style style = paint.getStyle();
817
818    if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
819        style = SkPaint::kFill_Style;
820    }
821
822    if (paint.getPathEffect() || paint.getMaskFilter() ||
823        paint.getRasterizer() || !matrix.rectStaysRect() ||
824        SkPaint::kStrokeAndFill_Style == style) {
825        rtype = kPath_RectType;
826    } else if (SkPaint::kFill_Style == style) {
827        rtype = kFill_RectType;
828    } else if (zeroWidth) {
829        rtype = kHair_RectType;
830    } else if (easy_rect_join(paint, matrix, strokeSize)) {
831        rtype = kStroke_RectType;
832    } else {
833        rtype = kPath_RectType;
834    }
835    return rtype;
836}
837
838static const SkPoint* rect_points(const SkRect& r) {
839    return SkTCast<const SkPoint*>(&r);
840}
841
842static SkPoint* rect_points(SkRect& r) {
843    return SkTCast<SkPoint*>(&r);
844}
845
846void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
847    SkDEBUGCODE(this->validate();)
848
849    // nothing to draw
850    if (fRC->isEmpty()) {
851        return;
852    }
853
854    SkPoint strokeSize;
855    RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize);
856
857    if (kPath_RectType == rtype) {
858        SkPath  tmp;
859        tmp.addRect(rect);
860        tmp.setFillType(SkPath::kWinding_FillType);
861        this->drawPath(tmp, paint, NULL, true);
862        return;
863    }
864
865    const SkMatrix& matrix = *fMatrix;
866    SkRect          devRect;
867
868    // transform rect into devRect
869    matrix.mapPoints(rect_points(devRect), rect_points(rect), 2);
870    devRect.sort();
871
872    if (fBounder && !fBounder->doRect(devRect, paint)) {
873        return;
874    }
875
876    // look for the quick exit, before we build a blitter
877    SkIRect ir;
878    devRect.roundOut(&ir);
879    if (paint.getStyle() != SkPaint::kFill_Style) {
880        // extra space for hairlines
881        ir.inset(-1, -1);
882    }
883    if (fRC->quickReject(ir)) {
884        return;
885    }
886
887    SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
888    while (looper.next()) {
889        SkRect localDevRect;
890        looper.mapRect(&localDevRect, devRect);
891        SkMatrix localMatrix;
892        looper.mapMatrix(&localMatrix, matrix);
893
894        SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix,
895                                           paint);
896        const SkRasterClip& clip = looper.getRC();
897        SkBlitter*          blitter = blitterStorage.get();
898
899        // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
900        // case we are also hairline (if we've gotten to here), which devolves to
901        // effectively just kFill
902        switch (rtype) {
903            case kFill_RectType:
904                if (paint.isAntiAlias()) {
905                    SkScan::AntiFillRect(localDevRect, clip, blitter);
906                } else {
907                    SkScan::FillRect(localDevRect, clip, blitter);
908                }
909                break;
910            case kStroke_RectType:
911                if (paint.isAntiAlias()) {
912                    SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
913                } else {
914                    SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
915                }
916                break;
917            case kHair_RectType:
918                if (paint.isAntiAlias()) {
919                    SkScan::AntiHairRect(localDevRect, clip, blitter);
920                } else {
921                    SkScan::HairRect(localDevRect, clip, blitter);
922                }
923                break;
924            default:
925                SkDEBUGFAIL("bad rtype");
926        }
927    }
928}
929
930void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
931    if (srcM.fBounds.isEmpty()) {
932        return;
933    }
934
935    const SkMask* mask = &srcM;
936
937    SkMask dstM;
938    if (paint.getMaskFilter() &&
939            paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
940        mask = &dstM;
941    } else {
942        dstM.fImage = NULL;
943    }
944    SkAutoMaskFreeImage ami(dstM.fImage);
945
946    if (fBounder && !fBounder->doIRect(mask->fBounds)) {
947        return;
948    }
949
950    SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
951    SkBlitter* blitter = blitterChooser.get();
952
953    SkAAClipBlitterWrapper wrapper;
954    const SkRegion* clipRgn;
955
956    if (fRC->isBW()) {
957        clipRgn = &fRC->bwRgn();
958    } else {
959        wrapper.init(*fRC, blitter);
960        clipRgn = &wrapper.getRgn();
961        blitter = wrapper.getBlitter();
962    }
963    blitter->blitMaskRegion(*mask, *clipRgn);
964}
965
966static SkScalar fast_len(const SkVector& vec) {
967    SkScalar x = SkScalarAbs(vec.fX);
968    SkScalar y = SkScalarAbs(vec.fY);
969    if (x < y) {
970        SkTSwap(x, y);
971    }
972    return x + SkScalarHalf(y);
973}
974
975static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
976    SkXfermode::Coeff dc;
977    if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) {
978        return false;
979    }
980
981    switch (dc) {
982        case SkXfermode::kOne_Coeff:
983        case SkXfermode::kISA_Coeff:
984        case SkXfermode::kISC_Coeff:
985            return true;
986        default:
987            return false;
988    }
989}
990
991bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
992                           SkScalar* coverage) {
993    SkASSERT(coverage);
994    if (SkPaint::kStroke_Style != paint.getStyle()) {
995        return false;
996    }
997    SkScalar strokeWidth = paint.getStrokeWidth();
998    if (0 == strokeWidth) {
999        *coverage = SK_Scalar1;
1000        return true;
1001    }
1002
1003    // if we get here, we need to try to fake a thick-stroke with a modulated
1004    // hairline
1005
1006    if (!paint.isAntiAlias()) {
1007        return false;
1008    }
1009    if (matrix.hasPerspective()) {
1010        return false;
1011    }
1012
1013    SkVector src[2], dst[2];
1014    src[0].set(strokeWidth, 0);
1015    src[1].set(0, strokeWidth);
1016    matrix.mapVectors(dst, src, 2);
1017    SkScalar len0 = fast_len(dst[0]);
1018    SkScalar len1 = fast_len(dst[1]);
1019    if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
1020        *coverage = SkScalarAve(len0, len1);
1021        return true;
1022    }
1023    return false;
1024}
1025
1026void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
1027    SkDEBUGCODE(this->validate());
1028
1029    if (fRC->isEmpty()) {
1030        return;
1031    }
1032
1033    {
1034        // TODO: Investigate optimizing these options. They are in the same
1035        // order as SkDraw::drawPath, which handles each case. It may be
1036        // that there is no way to optimize for these using the SkRRect path.
1037        SkScalar coverage;
1038        if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) {
1039            goto DRAW_PATH;
1040        }
1041
1042        if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
1043            goto DRAW_PATH;
1044        }
1045
1046        if (paint.getRasterizer()) {
1047            goto DRAW_PATH;
1048        }
1049    }
1050
1051    if (paint.getMaskFilter()) {
1052        // Transform the rrect into device space.
1053        SkRRect devRRect;
1054        if (rrect.transform(*fMatrix, &devRRect)) {
1055            SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
1056            if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC,
1057                                                   fBounder, blitter.get(),
1058                                                   SkPaint::kFill_Style)) {
1059                return; // filterRRect() called the blitter, so we're done
1060            }
1061        }
1062    }
1063
1064DRAW_PATH:
1065    // Now fall back to the default case of using a path.
1066    SkPath path;
1067    path.addRRect(rrect);
1068    this->drawPath(path, paint, NULL, true);
1069}
1070
1071void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
1072                      const SkMatrix* prePathMatrix, bool pathIsMutable) const {
1073    SkDEBUGCODE(this->validate();)
1074
1075    // nothing to draw
1076    if (fRC->isEmpty()) {
1077        return;
1078    }
1079
1080    SkPath*         pathPtr = (SkPath*)&origSrcPath;
1081    bool            doFill = true;
1082    SkPath          tmpPath;
1083    SkMatrix        tmpMatrix;
1084    const SkMatrix* matrix = fMatrix;
1085
1086    if (prePathMatrix) {
1087        if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
1088                origPaint.getRasterizer()) {
1089            SkPath* result = pathPtr;
1090
1091            if (!pathIsMutable) {
1092                result = &tmpPath;
1093                pathIsMutable = true;
1094            }
1095            pathPtr->transform(*prePathMatrix, result);
1096            pathPtr = result;
1097        } else {
1098            if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
1099                // overflow
1100                return;
1101            }
1102            matrix = &tmpMatrix;
1103        }
1104    }
1105    // at this point we're done with prePathMatrix
1106    SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
1107
1108    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
1109
1110    {
1111        SkScalar coverage;
1112        if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
1113            if (SK_Scalar1 == coverage) {
1114                paint.writable()->setStrokeWidth(0);
1115            } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
1116                U8CPU newAlpha;
1117#if 0
1118                newAlpha = SkToU8(SkScalarRoundToInt(coverage *
1119                                                     origPaint.getAlpha()));
1120#else
1121                // this is the old technique, which we preserve for now so
1122                // we don't change previous results (testing)
1123                // the new way seems fine, its just (a tiny bit) different
1124                int scale = (int)SkScalarMul(coverage, 256);
1125                newAlpha = origPaint.getAlpha() * scale >> 8;
1126#endif
1127                SkPaint* writablePaint = paint.writable();
1128                writablePaint->setStrokeWidth(0);
1129                writablePaint->setAlpha(newAlpha);
1130            }
1131        }
1132    }
1133
1134    if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
1135        SkRect cullRect;
1136        const SkRect* cullRectPtr = NULL;
1137        if (this->computeConservativeLocalClipBounds(&cullRect)) {
1138            cullRectPtr = &cullRect;
1139        }
1140        doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr);
1141        pathPtr = &tmpPath;
1142    }
1143
1144    if (paint->getRasterizer()) {
1145        SkMask  mask;
1146        if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
1147                            &fRC->getBounds(), paint->getMaskFilter(), &mask,
1148                            SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
1149            this->drawDevMask(mask, *paint);
1150            SkMask::FreeImage(mask.fImage);
1151        }
1152        return;
1153    }
1154
1155    // avoid possibly allocating a new path in transform if we can
1156    SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
1157
1158    // transform the path into device space
1159    pathPtr->transform(*matrix, devPathPtr);
1160
1161    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint);
1162
1163    if (paint->getMaskFilter()) {
1164        SkPaint::Style style = doFill ? SkPaint::kFill_Style :
1165            SkPaint::kStroke_Style;
1166        if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC,
1167                                               fBounder, blitter.get(),
1168                                               style)) {
1169            return; // filterPath() called the blitter, so we're done
1170        }
1171    }
1172
1173    if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) {
1174        return;
1175    }
1176
1177    void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
1178    if (doFill) {
1179        if (paint->isAntiAlias()) {
1180            proc = SkScan::AntiFillPath;
1181        } else {
1182            proc = SkScan::FillPath;
1183        }
1184    } else {    // hairline
1185        if (paint->isAntiAlias()) {
1186            proc = SkScan::AntiHairPath;
1187        } else {
1188            proc = SkScan::HairPath;
1189        }
1190    }
1191    proc(*devPathPtr, *fRC, blitter.get());
1192}
1193
1194/** For the purposes of drawing bitmaps, if a matrix is "almost" translate
1195    go ahead and treat it as if it were, so that subsequent code can go fast.
1196 */
1197static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
1198    unsigned bits = 0;  // TODO: find a way to allow the caller to tell us to
1199                        // respect filtering.
1200    return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
1201}
1202
1203void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
1204                              const SkPaint& paint) const {
1205    SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config);
1206
1207    if (just_translate(*fMatrix, bitmap)) {
1208        int ix = SkScalarRound(fMatrix->getTranslateX());
1209        int iy = SkScalarRound(fMatrix->getTranslateY());
1210
1211        SkAutoLockPixels alp(bitmap);
1212        if (!bitmap.readyToDraw()) {
1213            return;
1214        }
1215
1216        SkMask  mask;
1217        mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1218        mask.fFormat = SkMask::kA8_Format;
1219        mask.fRowBytes = SkToU32(bitmap.rowBytes());
1220        mask.fImage = bitmap.getAddr8(0, 0);
1221
1222        this->drawDevMask(mask, paint);
1223    } else {    // need to xform the bitmap first
1224        SkRect  r;
1225        SkMask  mask;
1226
1227        r.set(0, 0,
1228              SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
1229        fMatrix->mapRect(&r);
1230        r.round(&mask.fBounds);
1231
1232        // set the mask's bounds to the transformed bitmap-bounds,
1233        // clipped to the actual device
1234        {
1235            SkIRect    devBounds;
1236            devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
1237            // need intersect(l, t, r, b) on irect
1238            if (!mask.fBounds.intersect(devBounds)) {
1239                return;
1240            }
1241        }
1242
1243        mask.fFormat = SkMask::kA8_Format;
1244        mask.fRowBytes = SkAlign4(mask.fBounds.width());
1245        size_t size = mask.computeImageSize();
1246        if (0 == size) {
1247            // the mask is too big to allocated, draw nothing
1248            return;
1249        }
1250
1251        // allocate (and clear) our temp buffer to hold the transformed bitmap
1252        SkAutoMalloc    storage(size);
1253        mask.fImage = (uint8_t*)storage.get();
1254        memset(mask.fImage, 0, size);
1255
1256        // now draw our bitmap(src) into mask(dst), transformed by the matrix
1257        {
1258            SkBitmap    device;
1259            device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
1260                             mask.fBounds.height(), mask.fRowBytes);
1261            device.setPixels(mask.fImage);
1262
1263            SkCanvas c(device);
1264            // need the unclipped top/left for the translate
1265            c.translate(-SkIntToScalar(mask.fBounds.fLeft),
1266                        -SkIntToScalar(mask.fBounds.fTop));
1267            c.concat(*fMatrix);
1268
1269            // We can't call drawBitmap, or we'll infinitely recurse. Instead
1270            // we manually build a shader and draw that into our new mask
1271            SkPaint tmpPaint;
1272            tmpPaint.setFlags(paint.getFlags());
1273            SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
1274            SkRect rr;
1275            rr.set(0, 0, SkIntToScalar(bitmap.width()),
1276                   SkIntToScalar(bitmap.height()));
1277            c.drawRect(rr, install.paintWithShader());
1278        }
1279        this->drawDevMask(mask, paint);
1280    }
1281}
1282
1283static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
1284                        const SkRect& srcR) {
1285    SkRect  dstR;
1286    SkIRect devIR;
1287
1288    m.mapRect(&dstR, srcR);
1289    dstR.roundOut(&devIR);
1290    return c.quickReject(devIR);
1291}
1292
1293static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
1294                        int width, int height) {
1295    SkRect  r;
1296    r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1297    return clipped_out(matrix, clip, r);
1298}
1299
1300static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
1301                              const SkBitmap& bitmap) {
1302    return clip.isBW() ||
1303           clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
1304}
1305
1306void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1307                        const SkPaint& origPaint) const {
1308    SkDEBUGCODE(this->validate();)
1309
1310    // nothing to draw
1311    if (fRC->isEmpty() ||
1312            bitmap.width() == 0 || bitmap.height() == 0 ||
1313            bitmap.getConfig() == SkBitmap::kNo_Config) {
1314        return;
1315    }
1316
1317    SkPaint paint(origPaint);
1318    paint.setStyle(SkPaint::kFill_Style);
1319
1320    SkMatrix matrix;
1321    if (!matrix.setConcat(*fMatrix, prematrix)) {
1322        return;
1323    }
1324
1325    if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
1326        return;
1327    }
1328
1329    if (fBounder && just_translate(matrix, bitmap)) {
1330        SkIRect ir;
1331        int32_t ix = SkScalarRound(matrix.getTranslateX());
1332        int32_t iy = SkScalarRound(matrix.getTranslateY());
1333        ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1334        if (!fBounder->doIRect(ir)) {
1335            return;
1336        }
1337    }
1338
1339    if (bitmap.getConfig() != SkBitmap::kA8_Config &&
1340            just_translate(matrix, bitmap)) {
1341        //
1342        // It is safe to call lock pixels now, since we know the matrix is
1343        // (more or less) identity.
1344        //
1345        SkAutoLockPixels alp(bitmap);
1346        if (!bitmap.readyToDraw()) {
1347            return;
1348        }
1349        int ix = SkScalarRound(matrix.getTranslateX());
1350        int iy = SkScalarRound(matrix.getTranslateY());
1351        if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
1352            uint32_t    storage[kBlitterStorageLongCount];
1353            SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1354                                                ix, iy, storage, sizeof(storage));
1355            if (blitter) {
1356                SkAutoTPlacementDelete<SkBlitter>   ad(blitter, storage);
1357
1358                SkIRect    ir;
1359                ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1360
1361                SkScan::FillIRect(ir, *fRC, blitter);
1362                return;
1363            }
1364        }
1365    }
1366
1367    // now make a temp draw on the stack, and use it
1368    //
1369    SkDraw draw(*this);
1370    draw.fMatrix = &matrix;
1371
1372    if (bitmap.getConfig() == SkBitmap::kA8_Config) {
1373        draw.drawBitmapAsMask(bitmap, paint);
1374    } else {
1375        SkAutoBitmapShaderInstall install(bitmap, paint);
1376
1377        SkRect  r;
1378        r.set(0, 0, SkIntToScalar(bitmap.width()),
1379              SkIntToScalar(bitmap.height()));
1380        // is this ok if paint has a rasterizer?
1381        draw.drawRect(r, install.paintWithShader());
1382    }
1383}
1384
1385void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1386                        const SkPaint& origPaint) const {
1387    SkDEBUGCODE(this->validate();)
1388
1389    // nothing to draw
1390    if (fRC->isEmpty() ||
1391            bitmap.width() == 0 || bitmap.height() == 0 ||
1392            bitmap.getConfig() == SkBitmap::kNo_Config) {
1393        return;
1394    }
1395
1396    SkIRect    bounds;
1397    bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1398
1399    if (fRC->quickReject(bounds)) {
1400        return; // nothing to draw
1401    }
1402
1403    SkPaint paint(origPaint);
1404    paint.setStyle(SkPaint::kFill_Style);
1405
1406    if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
1407        uint32_t    storage[kBlitterStorageLongCount];
1408        SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1409                                                x, y, storage, sizeof(storage));
1410
1411        if (blitter) {
1412            SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
1413
1414            if (fBounder && !fBounder->doIRect(bounds)) {
1415                return;
1416            }
1417
1418            SkScan::FillIRect(bounds, *fRC, blitter);
1419            return;
1420        }
1421    }
1422
1423    SkAutoBitmapShaderInstall install(bitmap, paint);
1424    const SkPaint& shaderPaint = install.paintWithShader();
1425
1426    SkMatrix        matrix;
1427    SkRect          r;
1428
1429    // get a scalar version of our rect
1430    r.set(bounds);
1431
1432    // tell the shader our offset
1433    matrix.setTranslate(r.fLeft, r.fTop);
1434    shaderPaint.getShader()->setLocalMatrix(matrix);
1435
1436    SkDraw draw(*this);
1437    matrix.reset();
1438    draw.fMatrix = &matrix;
1439    // call ourself with a rect
1440    // is this OK if paint has a rasterizer?
1441    draw.drawRect(r, shaderPaint);
1442}
1443
1444///////////////////////////////////////////////////////////////////////////////
1445
1446#include "SkScalerContext.h"
1447#include "SkGlyphCache.h"
1448#include "SkTextToPathIter.h"
1449#include "SkUtils.h"
1450
1451static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1452                const char text[], size_t byteLength, SkVector* stopVector) {
1453    SkFixed     x = 0, y = 0;
1454    const char* stop = text + byteLength;
1455
1456    SkAutoKern  autokern;
1457
1458    while (text < stop) {
1459        // don't need x, y here, since all subpixel variants will have the
1460        // same advance
1461        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1462
1463        x += autokern.adjust(glyph) + glyph.fAdvanceX;
1464        y += glyph.fAdvanceY;
1465    }
1466    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1467
1468    SkASSERT(text == stop);
1469}
1470
1471void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1472                              SkScalar x, SkScalar y,
1473                              const SkPaint& paint) const {
1474    SkDEBUGCODE(this->validate();)
1475
1476    SkTextToPathIter iter(text, byteLength, paint, true);
1477
1478    SkMatrix    matrix;
1479    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1480    matrix.postTranslate(x, y);
1481
1482    const SkPath* iterPath;
1483    SkScalar xpos, prevXPos = 0;
1484
1485    while (iter.next(&iterPath, &xpos)) {
1486        matrix.postTranslate(xpos - prevXPos, 0);
1487        if (iterPath) {
1488            const SkPaint& pnt = iter.getPaint();
1489            if (fDevice) {
1490                fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
1491            } else {
1492                this->drawPath(*iterPath, pnt, &matrix, false);
1493            }
1494        }
1495        prevXPos = xpos;
1496    }
1497}
1498
1499// disable warning : local variable used without having been initialized
1500#if defined _WIN32 && _MSC_VER >= 1300
1501#pragma warning ( push )
1502#pragma warning ( disable : 4701 )
1503#endif
1504
1505//////////////////////////////////////////////////////////////////////////////
1506
1507static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
1508                                   SkFixed fx, SkFixed fy,
1509                                   const SkGlyph& glyph) {
1510    int left = SkFixedFloor(fx);
1511    int top = SkFixedFloor(fy);
1512    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1513    SkASSERT(NULL == state.fBounder);
1514    SkASSERT((NULL == state.fClip && state.fAAClip) ||
1515             (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
1516
1517    left += glyph.fLeft;
1518    top  += glyph.fTop;
1519
1520    int right   = left + glyph.fWidth;
1521    int bottom  = top + glyph.fHeight;
1522
1523    SkMask        mask;
1524    SkIRect        storage;
1525    SkIRect*    bounds = &mask.fBounds;
1526
1527    mask.fBounds.set(left, top, right, bottom);
1528
1529    // this extra test is worth it, assuming that most of the time it succeeds
1530    // since we can avoid writing to storage
1531    if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1532        if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1533            return;
1534        bounds = &storage;
1535    }
1536
1537    uint8_t* aa = (uint8_t*)glyph.fImage;
1538    if (NULL == aa) {
1539        aa = (uint8_t*)state.fCache->findImage(glyph);
1540        if (NULL == aa) {
1541            return; // can't rasterize glyph
1542        }
1543    }
1544
1545    mask.fRowBytes = glyph.rowBytes();
1546    mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1547    mask.fImage = aa;
1548    state.blitMask(mask, *bounds);
1549}
1550
1551static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
1552                                  SkFixed fx, SkFixed fy,
1553                                  const SkGlyph& glyph) {
1554    int left = SkFixedFloor(fx);
1555    int top = SkFixedFloor(fy);
1556    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1557    SkASSERT(!state.fClip->isRect());
1558    SkASSERT(NULL == state.fBounder);
1559
1560    SkMask  mask;
1561
1562    left += glyph.fLeft;
1563    top  += glyph.fTop;
1564
1565    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1566    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1567
1568    if (!clipper.done()) {
1569        const SkIRect&  cr = clipper.rect();
1570        const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1571        if (NULL == aa) {
1572            aa = (uint8_t*)state.fCache->findImage(glyph);
1573            if (NULL == aa) {
1574                return;
1575            }
1576        }
1577
1578        mask.fRowBytes = glyph.rowBytes();
1579        mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1580        mask.fImage = (uint8_t*)aa;
1581        do {
1582            state.blitMask(mask, cr);
1583            clipper.next();
1584        } while (!clipper.done());
1585    }
1586}
1587
1588static void D1G_Bounder(const SkDraw1Glyph& state,
1589                        SkFixed fx, SkFixed fy,
1590                        const SkGlyph& glyph) {
1591    int left = SkFixedFloor(fx);
1592    int top = SkFixedFloor(fy);
1593    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1594
1595    SkMask  mask;
1596
1597    left += glyph.fLeft;
1598    top  += glyph.fTop;
1599
1600    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1601    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1602
1603    if (!clipper.done()) {
1604        const SkIRect&  cr = clipper.rect();
1605        const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1606        if (NULL == aa) {
1607            aa = (uint8_t*)state.fCache->findImage(glyph);
1608            if (NULL == aa) {
1609                return;
1610            }
1611        }
1612
1613        // we need to pass the origin, which we approximate with our
1614        // (unadjusted) left,top coordinates (the caller called fixedfloor)
1615        if (state.fBounder->doIRectGlyph(cr,
1616                                         left - glyph.fLeft,
1617                                         top - glyph.fTop, glyph)) {
1618            mask.fRowBytes = glyph.rowBytes();
1619            mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1620            mask.fImage = (uint8_t*)aa;
1621            do {
1622                state.blitMask(mask, cr);
1623                clipper.next();
1624            } while (!clipper.done());
1625        }
1626    }
1627}
1628
1629static void D1G_Bounder_AAClip(const SkDraw1Glyph& state,
1630                               SkFixed fx, SkFixed fy,
1631                               const SkGlyph& glyph) {
1632    int left = SkFixedFloor(fx);
1633    int top = SkFixedFloor(fy);
1634    SkIRect bounds;
1635    bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1636
1637    if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) {
1638        D1G_NoBounder_RectClip(state, fx, fy, glyph);
1639    }
1640}
1641
1642static bool hasCustomD1GProc(const SkDraw& draw) {
1643    return draw.fProcs && draw.fProcs->fD1GProc;
1644}
1645
1646static bool needsRasterTextBlit(const SkDraw& draw) {
1647    return !hasCustomD1GProc(draw);
1648}
1649
1650SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
1651                                      SkGlyphCache* cache, const SkPaint& pnt) {
1652    fDraw = draw;
1653    fBounder = draw->fBounder;
1654    fBlitter = blitter;
1655    fCache = cache;
1656    fPaint = &pnt;
1657
1658    if (cache->isSubpixel()) {
1659        fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
1660    } else {
1661        fHalfSampleX = fHalfSampleY = SK_FixedHalf;
1662    }
1663
1664    if (hasCustomD1GProc(*draw)) {
1665        // todo: fix this assumption about clips w/ custom
1666        fClip = draw->fClip;
1667        fClipBounds = fClip->getBounds();
1668        return draw->fProcs->fD1GProc;
1669    }
1670
1671    if (draw->fRC->isBW()) {
1672        fAAClip = NULL;
1673        fClip = &draw->fRC->bwRgn();
1674        fClipBounds = fClip->getBounds();
1675        if (NULL == fBounder) {
1676            if (fClip->isRect()) {
1677                return D1G_NoBounder_RectClip;
1678            } else {
1679                return D1G_NoBounder_RgnClip;
1680            }
1681        } else {
1682            return D1G_Bounder;
1683        }
1684    } else {    // aaclip
1685        fAAClip = &draw->fRC->aaRgn();
1686        fClip = NULL;
1687        fClipBounds = fAAClip->getBounds();
1688        if (NULL == fBounder) {
1689            return D1G_NoBounder_RectClip;
1690        } else {
1691            return D1G_Bounder_AAClip;
1692        }
1693    }
1694}
1695
1696void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1697    SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1698
1699    SkBitmap bm;
1700    bm.setConfig(SkBitmap::kARGB_8888_Config,
1701                 mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
1702    bm.setPixels((SkPMColor*)mask.fImage);
1703
1704    fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1705}
1706
1707///////////////////////////////////////////////////////////////////////////////
1708
1709void SkDraw::drawText(const char text[], size_t byteLength,
1710                      SkScalar x, SkScalar y, const SkPaint& paint) const {
1711    SkASSERT(byteLength == 0 || text != NULL);
1712
1713    SkDEBUGCODE(this->validate();)
1714
1715    // nothing to draw
1716    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1717        return;
1718    }
1719
1720    // SkScalarRec doesn't currently have a way of representing hairline stroke and
1721    // will fill if its frame-width is 0.
1722    if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1723        this->drawText_asPaths(text, byteLength, x, y, paint);
1724        return;
1725    }
1726
1727    SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1728
1729    SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
1730    SkGlyphCache*       cache = autoCache.getCache();
1731
1732    // transform our starting point
1733    {
1734        SkPoint loc;
1735        fMatrix->mapXY(x, y, &loc);
1736        x = loc.fX;
1737        y = loc.fY;
1738    }
1739
1740    // need to measure first
1741    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1742        SkVector    stop;
1743
1744        measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1745
1746        SkScalar    stopX = stop.fX;
1747        SkScalar    stopY = stop.fY;
1748
1749        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1750            stopX = SkScalarHalf(stopX);
1751            stopY = SkScalarHalf(stopY);
1752        }
1753        x -= stopX;
1754        y -= stopY;
1755    }
1756
1757    const char* stop = text + byteLength;
1758
1759    SkAAClipBlitter     aaBlitter;
1760    SkAutoBlitterChoose blitterChooser;
1761    SkBlitter*          blitter = NULL;
1762    if (needsRasterTextBlit(*this)) {
1763        blitterChooser.choose(*fBitmap, *fMatrix, paint);
1764        blitter = blitterChooser.get();
1765        if (fRC->isAA()) {
1766            aaBlitter.init(blitter, &fRC->aaRgn());
1767            blitter = &aaBlitter;
1768        }
1769    }
1770
1771    SkAutoKern          autokern;
1772    SkDraw1Glyph        d1g;
1773    SkDraw1Glyph::Proc  proc = d1g.init(this, blitter, cache, paint);
1774
1775    SkFixed fxMask = ~0;
1776    SkFixed fyMask = ~0;
1777    if (cache->isSubpixel()) {
1778        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1779        if (kX_SkAxisAlignment == baseline) {
1780            fyMask = 0;
1781            d1g.fHalfSampleY = SK_FixedHalf;
1782        } else if (kY_SkAxisAlignment == baseline) {
1783            fxMask = 0;
1784            d1g.fHalfSampleX = SK_FixedHalf;
1785        }
1786    }
1787
1788    SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX;
1789    SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY;
1790
1791    while (text < stop) {
1792        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1793
1794        fx += autokern.adjust(glyph);
1795
1796        if (glyph.fWidth) {
1797            proc(d1g, fx, fy, glyph);
1798        }
1799        fx += glyph.fAdvanceX;
1800        fy += glyph.fAdvanceY;
1801    }
1802}
1803
1804// last parameter is interpreted as SkFixed [x, y]
1805// return the fixed position, which may be rounded or not by the caller
1806//   e.g. subpixel doesn't round
1807typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1808
1809static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1810                          SkIPoint* dst) {
1811    dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1812}
1813
1814static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1815                            SkIPoint* dst) {
1816    dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1817             SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1818}
1819
1820static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1821                           SkIPoint* dst) {
1822    dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1823             SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1824}
1825
1826static AlignProc pick_align_proc(SkPaint::Align align) {
1827    static const AlignProc gProcs[] = {
1828        leftAlignProc, centerAlignProc, rightAlignProc
1829    };
1830
1831    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1832
1833    return gProcs[align];
1834}
1835
1836class TextMapState {
1837public:
1838    mutable SkPoint fLoc;
1839
1840    TextMapState(const SkMatrix& matrix, SkScalar y)
1841        : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1842
1843    typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1844
1845    Proc pickProc(int scalarsPerPosition);
1846
1847private:
1848    const SkMatrix&     fMatrix;
1849    SkMatrix::MapXYProc fProc;
1850    SkScalar            fY; // ignored by MapXYProc
1851    // these are only used by Only... procs
1852    SkScalar            fScaleX, fTransX, fTransformedY;
1853
1854    static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1855        state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1856    }
1857
1858    static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1859        state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1860    }
1861
1862    static void MapOnlyScaleXProc(const TextMapState& state,
1863                                  const SkScalar pos[]) {
1864        state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1865                       state.fTransformedY);
1866    }
1867
1868    static void MapOnlyTransXProc(const TextMapState& state,
1869                                  const SkScalar pos[]) {
1870        state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1871    }
1872};
1873
1874TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1875    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1876
1877    if (1 == scalarsPerPosition) {
1878        unsigned mtype = fMatrix.getType();
1879        if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1880            return MapXProc;
1881        } else {
1882            fScaleX = fMatrix.getScaleX();
1883            fTransX = fMatrix.getTranslateX();
1884            fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1885                            fMatrix.getTranslateY();
1886            return (mtype & SkMatrix::kScale_Mask) ?
1887                        MapOnlyScaleXProc : MapOnlyTransXProc;
1888        }
1889    } else {
1890        return MapXYProc;
1891    }
1892}
1893
1894//////////////////////////////////////////////////////////////////////////////
1895
1896void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1897                                 const SkScalar pos[], SkScalar constY,
1898                                 int scalarsPerPosition,
1899                                 const SkPaint& origPaint) const {
1900    // setup our std paint, in hopes of getting hits in the cache
1901    SkPaint paint(origPaint);
1902    SkScalar matrixScale = paint.setupForAsPaths();
1903
1904    SkMatrix matrix;
1905    matrix.setScale(matrixScale, matrixScale);
1906
1907    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1908    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
1909    SkGlyphCache*       cache = autoCache.getCache();
1910
1911    const char*        stop = text + byteLength;
1912    AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
1913    TextMapState       tms(SkMatrix::I(), constY);
1914    TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1915
1916    while (text < stop) {
1917        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1918        if (glyph.fWidth) {
1919            const SkPath* path = cache->findPath(glyph);
1920            if (path) {
1921                tmsProc(tms, pos);
1922                SkIPoint fixedLoc;
1923                alignProc(tms.fLoc, glyph, &fixedLoc);
1924
1925                matrix[SkMatrix::kMTransX] = SkFixedToScalar(fixedLoc.fX);
1926                matrix[SkMatrix::kMTransY] = SkFixedToScalar(fixedLoc.fY);
1927                if (fDevice) {
1928                    fDevice->drawPath(*this, *path, paint, &matrix, false);
1929                } else {
1930                    this->drawPath(*path, paint, &matrix, false);
1931                }
1932            }
1933        }
1934        pos += scalarsPerPosition;
1935    }
1936}
1937
1938void SkDraw::drawPosText(const char text[], size_t byteLength,
1939                         const SkScalar pos[], SkScalar constY,
1940                         int scalarsPerPosition, const SkPaint& paint) const {
1941    SkASSERT(byteLength == 0 || text != NULL);
1942    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1943
1944    SkDEBUGCODE(this->validate();)
1945
1946    // nothing to draw
1947    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1948        return;
1949    }
1950
1951    if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1952        this->drawPosText_asPaths(text, byteLength, pos, constY,
1953                                  scalarsPerPosition, paint);
1954        return;
1955    }
1956
1957    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1958    SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
1959    SkGlyphCache*       cache = autoCache.getCache();
1960
1961    SkAAClipBlitterWrapper wrapper;
1962    SkAutoBlitterChoose blitterChooser;
1963    SkBlitter* blitter = NULL;
1964    if (needsRasterTextBlit(*this)) {
1965        blitterChooser.choose(*fBitmap, *fMatrix, paint);
1966        blitter = blitterChooser.get();
1967        if (fRC->isAA()) {
1968            wrapper.init(*fRC, blitter);
1969            blitter = wrapper.getBlitter();
1970        }
1971    }
1972
1973    const char*        stop = text + byteLength;
1974    AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
1975    SkDraw1Glyph       d1g;
1976    SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
1977    TextMapState       tms(*fMatrix, constY);
1978    TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1979
1980    if (cache->isSubpixel()) {
1981        // maybe we should skip the rounding if linearText is set
1982        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1983
1984        SkFixed fxMask = ~0;
1985        SkFixed fyMask = ~0;
1986        if (kX_SkAxisAlignment == baseline) {
1987            fyMask = 0;
1988#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
1989            d1g.fHalfSampleY = SK_FixedHalf;
1990#endif
1991        } else if (kY_SkAxisAlignment == baseline) {
1992            fxMask = 0;
1993#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
1994            d1g.fHalfSampleX = SK_FixedHalf;
1995#endif
1996        }
1997
1998        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1999            while (text < stop) {
2000                tmsProc(tms, pos);
2001
2002                SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX;
2003                SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY;
2004
2005                const SkGlyph& glyph = glyphCacheProc(cache, &text,
2006                                                      fx & fxMask, fy & fyMask);
2007
2008                if (glyph.fWidth) {
2009                    proc(d1g, fx, fy, glyph);
2010                }
2011                pos += scalarsPerPosition;
2012            }
2013        } else {
2014            while (text < stop) {
2015                const char* currentText = text;
2016                const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
2017
2018                if (metricGlyph.fWidth) {
2019                    SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
2020                    SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
2021
2022                    tmsProc(tms, pos);
2023                    SkIPoint fixedLoc;
2024                    alignProc(tms.fLoc, metricGlyph, &fixedLoc);
2025
2026                    SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
2027                    SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
2028
2029                    // have to call again, now that we've been "aligned"
2030                    const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
2031                                                          fx & fxMask, fy & fyMask);
2032                    // the assumption is that the metrics haven't changed
2033                    SkASSERT(prevAdvX == glyph.fAdvanceX);
2034                    SkASSERT(prevAdvY == glyph.fAdvanceY);
2035                    SkASSERT(glyph.fWidth);
2036
2037                    proc(d1g, fx, fy, glyph);
2038                }
2039                pos += scalarsPerPosition;
2040            }
2041        }
2042    } else {    // not subpixel
2043        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
2044            while (text < stop) {
2045                // the last 2 parameters are ignored
2046                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2047
2048                if (glyph.fWidth) {
2049                    tmsProc(tms, pos);
2050
2051                    proc(d1g,
2052                         SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
2053                         SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
2054                         glyph);
2055                }
2056                pos += scalarsPerPosition;
2057            }
2058        } else {
2059            while (text < stop) {
2060                // the last 2 parameters are ignored
2061                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2062
2063                if (glyph.fWidth) {
2064                    tmsProc(tms, pos);
2065
2066                    SkIPoint fixedLoc;
2067                    alignProc(tms.fLoc, glyph, &fixedLoc);
2068
2069                    proc(d1g,
2070                         fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
2071                         fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY,
2072                         glyph);
2073                }
2074                pos += scalarsPerPosition;
2075            }
2076        }
2077    }
2078}
2079
2080#if defined _WIN32 && _MSC_VER >= 1300
2081#pragma warning ( pop )
2082#endif
2083
2084///////////////////////////////////////////////////////////////////////////////
2085
2086#include "SkPathMeasure.h"
2087
2088static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
2089                        SkPathMeasure& meas, const SkMatrix& matrix) {
2090    SkMatrix::MapXYProc proc = matrix.getMapXYProc();
2091
2092    for (int i = 0; i < count; i++) {
2093        SkPoint pos;
2094        SkVector tangent;
2095
2096        proc(matrix, src[i].fX, src[i].fY, &pos);
2097        SkScalar sx = pos.fX;
2098        SkScalar sy = pos.fY;
2099
2100        if (!meas.getPosTan(sx, &pos, &tangent)) {
2101            // set to 0 if the measure failed, so that we just set dst == pos
2102            tangent.set(0, 0);
2103        }
2104
2105        /*  This is the old way (that explains our approach but is way too slow
2106            SkMatrix    matrix;
2107            SkPoint     pt;
2108
2109            pt.set(sx, sy);
2110            matrix.setSinCos(tangent.fY, tangent.fX);
2111            matrix.preTranslate(-sx, 0);
2112            matrix.postTranslate(pos.fX, pos.fY);
2113            matrix.mapPoints(&dst[i], &pt, 1);
2114        */
2115        dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
2116                   pos.fY + SkScalarMul(tangent.fX, sy));
2117    }
2118}
2119
2120/*  TODO
2121
2122    Need differentially more subdivisions when the follow-path is curvy. Not sure how to
2123    determine that, but we need it. I guess a cheap answer is let the caller tell us,
2124    but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
2125*/
2126static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
2127                      const SkMatrix& matrix) {
2128    SkPath::Iter    iter(src, false);
2129    SkPoint         srcP[4], dstP[3];
2130    SkPath::Verb    verb;
2131
2132    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
2133        switch (verb) {
2134            case SkPath::kMove_Verb:
2135                morphpoints(dstP, srcP, 1, meas, matrix);
2136                dst->moveTo(dstP[0]);
2137                break;
2138            case SkPath::kLine_Verb:
2139                // turn lines into quads to look bendy
2140                srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
2141                srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
2142                morphpoints(dstP, srcP, 2, meas, matrix);
2143                dst->quadTo(dstP[0], dstP[1]);
2144                break;
2145            case SkPath::kQuad_Verb:
2146                morphpoints(dstP, &srcP[1], 2, meas, matrix);
2147                dst->quadTo(dstP[0], dstP[1]);
2148                break;
2149            case SkPath::kCubic_Verb:
2150                morphpoints(dstP, &srcP[1], 3, meas, matrix);
2151                dst->cubicTo(dstP[0], dstP[1], dstP[2]);
2152                break;
2153            case SkPath::kClose_Verb:
2154                dst->close();
2155                break;
2156            default:
2157                SkDEBUGFAIL("unknown verb");
2158                break;
2159        }
2160    }
2161}
2162
2163void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
2164                            const SkPath& follow, const SkMatrix* matrix,
2165                            const SkPaint& paint) const {
2166    SkASSERT(byteLength == 0 || text != NULL);
2167
2168    // nothing to draw
2169    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2170        return;
2171    }
2172
2173    SkTextToPathIter    iter(text, byteLength, paint, true);
2174    SkPathMeasure       meas(follow, false);
2175    SkScalar            hOffset = 0;
2176
2177    // need to measure first
2178    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
2179        SkScalar pathLen = meas.getLength();
2180        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2181            pathLen = SkScalarHalf(pathLen);
2182        }
2183        hOffset += pathLen;
2184    }
2185
2186    const SkPath*   iterPath;
2187    SkScalar        xpos;
2188    SkMatrix        scaledMatrix;
2189    SkScalar        scale = iter.getPathScale();
2190
2191    scaledMatrix.setScale(scale, scale);
2192
2193    while (iter.next(&iterPath, &xpos)) {
2194        if (iterPath) {
2195            SkPath      tmp;
2196            SkMatrix    m(scaledMatrix);
2197
2198            m.postTranslate(xpos + hOffset, 0);
2199            if (matrix) {
2200                m.postConcat(*matrix);
2201            }
2202            morphpath(&tmp, *iterPath, meas, m);
2203            if (fDevice) {
2204                fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
2205            } else {
2206                this->drawPath(tmp, iter.getPaint(), NULL, true);
2207            }
2208        }
2209    }
2210}
2211
2212#ifdef SK_BUILD_FOR_ANDROID
2213void SkDraw::drawPosTextOnPath(const char text[], size_t byteLength,
2214                               const SkPoint pos[], const SkPaint& paint,
2215                               const SkPath& path, const SkMatrix* matrix) const {
2216    // nothing to draw
2217    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2218        return;
2219    }
2220
2221    SkMatrix scaledMatrix;
2222    SkPathMeasure meas(path, false);
2223
2224    SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(
2225            SkPaint::kForward_TextBufferDirection, true);
2226
2227    // Copied (modified) from SkTextToPathIter constructor to setup paint
2228    SkPaint tempPaint(paint);
2229
2230    tempPaint.setLinearText(true);
2231    tempPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2232
2233    if (tempPaint.getPathEffect() == NULL && !(tempPaint.getStrokeWidth() > 0
2234            && tempPaint.getStyle() != SkPaint::kFill_Style)) {
2235        tempPaint.setStyle(SkPaint::kFill_Style);
2236        tempPaint.setPathEffect(NULL);
2237    }
2238    // End copied from SkTextToPathIter constructor
2239
2240    // detach cache
2241    SkGlyphCache* cache = tempPaint.detachCache(NULL, NULL);
2242
2243    // Must set scale, even if 1
2244    SkScalar scale = SK_Scalar1;
2245    scaledMatrix.setScale(scale, scale);
2246
2247    // Loop over all glyph ids
2248    for (const char* stop = text + byteLength; text < stop; pos++) {
2249
2250        const SkGlyph& glyph = glyphCacheProc(cache, &text);
2251        SkPath tmp;
2252
2253        const SkPath* glyphPath = cache->findPath(glyph);
2254        if (glyphPath == NULL) {
2255            continue;
2256        }
2257
2258        SkMatrix m(scaledMatrix);
2259        m.postTranslate(pos->fX, 0);
2260
2261        if (matrix) {
2262            m.postConcat(*matrix);
2263        }
2264
2265        morphpath(&tmp, *glyphPath, meas, m);
2266        this->drawPath(tmp, tempPaint);
2267
2268    }
2269
2270    // re-attach cache
2271    SkGlyphCache::AttachCache(cache);
2272}
2273#endif
2274
2275///////////////////////////////////////////////////////////////////////////////
2276
2277struct VertState {
2278    int f0, f1, f2;
2279
2280    VertState(int vCount, const uint16_t indices[], int indexCount)
2281            : fIndices(indices) {
2282        fCurrIndex = 0;
2283        if (indices) {
2284            fCount = indexCount;
2285        } else {
2286            fCount = vCount;
2287        }
2288    }
2289
2290    typedef bool (*Proc)(VertState*);
2291    Proc chooseProc(SkCanvas::VertexMode mode);
2292
2293private:
2294    int             fCount;
2295    int             fCurrIndex;
2296    const uint16_t* fIndices;
2297
2298    static bool Triangles(VertState*);
2299    static bool TrianglesX(VertState*);
2300    static bool TriangleStrip(VertState*);
2301    static bool TriangleStripX(VertState*);
2302    static bool TriangleFan(VertState*);
2303    static bool TriangleFanX(VertState*);
2304};
2305
2306bool VertState::Triangles(VertState* state) {
2307    int index = state->fCurrIndex;
2308    if (index + 3 > state->fCount) {
2309        return false;
2310    }
2311    state->f0 = index + 0;
2312    state->f1 = index + 1;
2313    state->f2 = index + 2;
2314    state->fCurrIndex = index + 3;
2315    return true;
2316}
2317
2318bool VertState::TrianglesX(VertState* state) {
2319    const uint16_t* indices = state->fIndices;
2320    int index = state->fCurrIndex;
2321    if (index + 3 > state->fCount) {
2322        return false;
2323    }
2324    state->f0 = indices[index + 0];
2325    state->f1 = indices[index + 1];
2326    state->f2 = indices[index + 2];
2327    state->fCurrIndex = index + 3;
2328    return true;
2329}
2330
2331bool VertState::TriangleStrip(VertState* state) {
2332    int index = state->fCurrIndex;
2333    if (index + 3 > state->fCount) {
2334        return false;
2335    }
2336    state->f2 = index + 2;
2337    if (index & 1) {
2338        state->f0 = index + 1;
2339        state->f1 = index + 0;
2340    } else {
2341        state->f0 = index + 0;
2342        state->f1 = index + 1;
2343    }
2344    state->fCurrIndex = index + 1;
2345    return true;
2346}
2347
2348bool VertState::TriangleStripX(VertState* state) {
2349    const uint16_t* indices = state->fIndices;
2350    int index = state->fCurrIndex;
2351    if (index + 3 > state->fCount) {
2352        return false;
2353    }
2354    state->f2 = indices[index + 2];
2355    if (index & 1) {
2356        state->f0 = indices[index + 1];
2357        state->f1 = indices[index + 0];
2358    } else {
2359        state->f0 = indices[index + 0];
2360        state->f1 = indices[index + 1];
2361    }
2362    state->fCurrIndex = index + 1;
2363    return true;
2364}
2365
2366bool VertState::TriangleFan(VertState* state) {
2367    int index = state->fCurrIndex;
2368    if (index + 3 > state->fCount) {
2369        return false;
2370    }
2371    state->f0 = 0;
2372    state->f1 = index + 1;
2373    state->f2 = index + 2;
2374    state->fCurrIndex = index + 1;
2375    return true;
2376}
2377
2378bool VertState::TriangleFanX(VertState* state) {
2379    const uint16_t* indices = state->fIndices;
2380    int index = state->fCurrIndex;
2381    if (index + 3 > state->fCount) {
2382        return false;
2383    }
2384    state->f0 = indices[0];
2385    state->f1 = indices[index + 1];
2386    state->f2 = indices[index + 2];
2387    state->fCurrIndex = index + 1;
2388    return true;
2389}
2390
2391VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
2392    switch (mode) {
2393        case SkCanvas::kTriangles_VertexMode:
2394            return fIndices ? TrianglesX : Triangles;
2395        case SkCanvas::kTriangleStrip_VertexMode:
2396            return fIndices ? TriangleStripX : TriangleStrip;
2397        case SkCanvas::kTriangleFan_VertexMode:
2398            return fIndices ? TriangleFanX : TriangleFan;
2399        default:
2400            return NULL;
2401    }
2402}
2403
2404typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
2405                         SkBlitter*);
2406
2407static HairProc ChooseHairProc(bool doAntiAlias) {
2408    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
2409}
2410
2411static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
2412                              const SkPoint texs[], SkMatrix* matrix) {
2413    SkPoint src[3], dst[3];
2414
2415    src[0] = texs[state.f0];
2416    src[1] = texs[state.f1];
2417    src[2] = texs[state.f2];
2418    dst[0] = verts[state.f0];
2419    dst[1] = verts[state.f1];
2420    dst[2] = verts[state.f2];
2421    return matrix->setPolyToPoly(src, dst, 3);
2422}
2423
2424class SkTriColorShader : public SkShader {
2425public:
2426    SkTriColorShader() {}
2427
2428    bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2429
2430    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
2431
2432    SK_DEVELOPER_TO_STRING()
2433    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
2434
2435protected:
2436    SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
2437
2438private:
2439    SkMatrix    fDstToUnit;
2440    SkPMColor   fColors[3];
2441
2442    typedef SkShader INHERITED;
2443};
2444
2445bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
2446                             int index0, int index1, int index2) {
2447
2448    fColors[0] = SkPreMultiplyColor(colors[index0]);
2449    fColors[1] = SkPreMultiplyColor(colors[index1]);
2450    fColors[2] = SkPreMultiplyColor(colors[index2]);
2451
2452    SkMatrix m, im;
2453    m.reset();
2454    m.set(0, pts[index1].fX - pts[index0].fX);
2455    m.set(1, pts[index2].fX - pts[index0].fX);
2456    m.set(2, pts[index0].fX);
2457    m.set(3, pts[index1].fY - pts[index0].fY);
2458    m.set(4, pts[index2].fY - pts[index0].fY);
2459    m.set(5, pts[index0].fY);
2460    if (!m.invert(&im)) {
2461        return false;
2462    }
2463    return fDstToUnit.setConcat(im, this->getTotalInverse());
2464}
2465
2466#include "SkColorPriv.h"
2467#include "SkComposeShader.h"
2468
2469static int ScalarTo256(SkScalar v) {
2470    int scale = SkScalarToFixed(v) >> 8;
2471    if (scale < 0) {
2472        scale = 0;
2473    }
2474    if (scale > 255) {
2475        scale = 255;
2476    }
2477    return SkAlpha255To256(scale);
2478}
2479
2480void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2481    SkPoint src;
2482
2483    for (int i = 0; i < count; i++) {
2484        fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2485        x += 1;
2486
2487        int scale1 = ScalarTo256(src.fX);
2488        int scale2 = ScalarTo256(src.fY);
2489        int scale0 = 256 - scale1 - scale2;
2490        if (scale0 < 0) {
2491            if (scale1 > scale2) {
2492                scale2 = 256 - scale1;
2493            } else {
2494                scale1 = 256 - scale2;
2495            }
2496            scale0 = 0;
2497        }
2498
2499        dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2500        SkAlphaMulQ(fColors[1], scale1) +
2501        SkAlphaMulQ(fColors[2], scale2);
2502    }
2503}
2504
2505#ifdef SK_DEVELOPER
2506void SkTriColorShader::toString(SkString* str) const {
2507    str->append("SkTriColorShader: (");
2508
2509    this->INHERITED::toString(str);
2510
2511    str->append(")");
2512}
2513#endif
2514
2515void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2516                          const SkPoint vertices[], const SkPoint textures[],
2517                          const SkColor colors[], SkXfermode* xmode,
2518                          const uint16_t indices[], int indexCount,
2519                          const SkPaint& paint) const {
2520    SkASSERT(0 == count || NULL != vertices);
2521
2522    // abort early if there is nothing to draw
2523    if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
2524        return;
2525    }
2526
2527    // transform out vertices into device coordinates
2528    SkAutoSTMalloc<16, SkPoint> storage(count);
2529    SkPoint* devVerts = storage.get();
2530    fMatrix->mapPoints(devVerts, vertices, count);
2531
2532    if (fBounder) {
2533        SkRect bounds;
2534        bounds.set(devVerts, count);
2535        if (!fBounder->doRect(bounds, paint)) {
2536            return;
2537        }
2538    }
2539
2540    /*
2541        We can draw the vertices in 1 of 4 ways:
2542
2543        - solid color (no shader/texture[], no colors[])
2544        - just colors (no shader/texture[], has colors[])
2545        - just texture (has shader/texture[], no colors[])
2546        - colors * texture (has shader/texture[], has colors[])
2547
2548        Thus for texture drawing, we need both texture[] and a shader.
2549    */
2550
2551    SkTriColorShader triShader; // must be above declaration of p
2552    SkPaint p(paint);
2553
2554    SkShader* shader = p.getShader();
2555    if (NULL == shader) {
2556        // if we have no shader, we ignore the texture coordinates
2557        textures = NULL;
2558    } else if (NULL == textures) {
2559        // if we don't have texture coordinates, ignore the shader
2560        p.setShader(NULL);
2561        shader = NULL;
2562    }
2563
2564    // setup the custom shader (if needed)
2565    if (NULL != colors) {
2566        if (NULL == textures) {
2567            // just colors (no texture)
2568            shader = p.setShader(&triShader);
2569        } else {
2570            // colors * texture
2571            SkASSERT(shader);
2572            bool releaseMode = false;
2573            if (NULL == xmode) {
2574                xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
2575                releaseMode = true;
2576            }
2577            SkShader* compose = SkNEW_ARGS(SkComposeShader,
2578                                           (&triShader, shader, xmode));
2579            p.setShader(compose)->unref();
2580            if (releaseMode) {
2581                xmode->unref();
2582            }
2583            shader = compose;
2584        }
2585    }
2586
2587    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2588    // important that we abort early, as below we may manipulate the shader
2589    // and that is only valid if the shader returned true from setContext.
2590    // If it returned false, then our blitter will be the NullBlitter.
2591    if (blitter->isNullBlitter()) {
2592        return;
2593    }
2594
2595    // setup our state and function pointer for iterating triangles
2596    VertState       state(count, indices, indexCount);
2597    VertState::Proc vertProc = state.chooseProc(vmode);
2598
2599    if (NULL != textures || NULL != colors) {
2600        SkMatrix  tempM;
2601        SkMatrix  savedLocalM;
2602        if (shader) {
2603            savedLocalM = shader->getLocalMatrix();
2604        }
2605
2606        // setContext has already been called and verified to return true
2607        // by the constructor of SkAutoBlitterChoose
2608        bool prevContextSuccess = true;
2609        while (vertProc(&state)) {
2610            if (NULL != textures) {
2611                if (texture_to_matrix(state, vertices, textures, &tempM)) {
2612                    tempM.postConcat(savedLocalM);
2613                    shader->setLocalMatrix(tempM);
2614                    // Need to recall setContext since we changed the local matrix.
2615                    // However, we also need to balance the calls this with a
2616                    // call to endContext which requires tracking the result of
2617                    // the previous call to setContext.
2618                    if (prevContextSuccess) {
2619                        shader->endContext();
2620                    }
2621                    prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix);
2622                    if (!prevContextSuccess) {
2623                        continue;
2624                    }
2625                }
2626            }
2627            if (NULL != colors) {
2628                if (!triShader.setup(vertices, colors,
2629                                     state.f0, state.f1, state.f2)) {
2630                    continue;
2631                }
2632            }
2633
2634            SkPoint tmp[] = {
2635                devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
2636            };
2637            SkScan::FillTriangle(tmp, *fRC, blitter.get());
2638        }
2639
2640        // now restore the shader's original local matrix
2641        if (NULL != shader) {
2642            shader->setLocalMatrix(savedLocalM);
2643        }
2644
2645        // If the final call to setContext fails we must make it suceed so that the
2646        // call to endContext in the destructor for SkAutoBlitterChoose is balanced.
2647        if (!prevContextSuccess) {
2648            prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I());
2649            SkASSERT(prevContextSuccess);
2650        }
2651    } else {
2652        // no colors[] and no texture
2653        HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2654        const SkRasterClip& clip = *fRC;
2655        while (vertProc(&state)) {
2656            hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
2657            hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
2658            hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
2659        }
2660    }
2661}
2662
2663///////////////////////////////////////////////////////////////////////////////
2664///////////////////////////////////////////////////////////////////////////////
2665
2666#ifdef SK_DEBUG
2667
2668void SkDraw::validate() const {
2669    SkASSERT(fBitmap != NULL);
2670    SkASSERT(fMatrix != NULL);
2671    SkASSERT(fClip != NULL);
2672    SkASSERT(fRC != NULL);
2673
2674    const SkIRect&  cr = fRC->getBounds();
2675    SkIRect         br;
2676
2677    br.set(0, 0, fBitmap->width(), fBitmap->height());
2678    SkASSERT(cr.isEmpty() || br.contains(cr));
2679}
2680
2681#endif
2682
2683///////////////////////////////////////////////////////////////////////////////
2684
2685SkBounder::SkBounder() {
2686    // initialize up front. This gets reset by SkCanvas before each draw call.
2687    fClip = &SkRegion::GetEmptyRegion();
2688}
2689
2690bool SkBounder::doIRect(const SkIRect& r) {
2691    SkIRect    rr;
2692    return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
2693}
2694
2695// TODO: change the prototype to take fixed, and update the callers
2696bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
2697                             const SkGlyph& glyph) {
2698    SkIRect    rr;
2699    if (!rr.intersect(fClip->getBounds(), r)) {
2700        return false;
2701    }
2702    GlyphRec rec;
2703    rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
2704    rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
2705                 rec.fLSB.fY + glyph.fAdvanceY);
2706    rec.fGlyphID = glyph.getGlyphID();
2707    rec.fFlags = 0;
2708    return this->onIRectGlyph(rr, rec);
2709}
2710
2711bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
2712                           const SkPaint& paint) {
2713    SkIRect     r;
2714    SkScalar    v0, v1;
2715
2716    v0 = pt0.fX;
2717    v1 = pt1.fX;
2718    if (v0 > v1) {
2719        SkTSwap<SkScalar>(v0, v1);
2720    }
2721    r.fLeft     = SkScalarFloor(v0);
2722    r.fRight    = SkScalarCeil(v1);
2723
2724    v0 = pt0.fY;
2725    v1 = pt1.fY;
2726    if (v0 > v1) {
2727        SkTSwap<SkScalar>(v0, v1);
2728    }
2729    r.fTop      = SkScalarFloor(v0);
2730    r.fBottom   = SkScalarCeil(v1);
2731
2732    if (paint.isAntiAlias()) {
2733        r.inset(-1, -1);
2734    }
2735    return this->doIRect(r);
2736}
2737
2738bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
2739    SkIRect    r;
2740
2741    if (paint.getStyle() == SkPaint::kFill_Style) {
2742        rect.round(&r);
2743    } else {
2744        int rad = -1;
2745        rect.roundOut(&r);
2746        if (paint.isAntiAlias()) {
2747            rad = -2;
2748        }
2749        r.inset(rad, rad);
2750    }
2751    return this->doIRect(r);
2752}
2753
2754bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
2755    SkIRect       r;
2756    const SkRect& bounds = path.getBounds();
2757
2758    if (doFill) {
2759        bounds.round(&r);
2760    } else {    // hairline
2761        bounds.roundOut(&r);
2762    }
2763
2764    if (paint.isAntiAlias()) {
2765        r.inset(-1, -1);
2766    }
2767    return this->doIRect(r);
2768}
2769
2770void SkBounder::commit() {
2771    // override in subclass
2772}
2773
2774////////////////////////////////////////////////////////////////////////////////////////////////
2775
2776#include "SkPath.h"
2777#include "SkDraw.h"
2778#include "SkRegion.h"
2779#include "SkBlitter.h"
2780
2781static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2782                       const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2783                           SkIRect* bounds) {
2784    if (devPath.isEmpty()) {
2785        return false;
2786    }
2787
2788    //  init our bounds from the path
2789    {
2790        SkRect pathBounds = devPath.getBounds();
2791        pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2792        pathBounds.roundOut(bounds);
2793    }
2794
2795    SkIPoint margin = SkIPoint::Make(0, 0);
2796    if (filter) {
2797        SkASSERT(filterMatrix);
2798
2799        SkMask srcM, dstM;
2800
2801        srcM.fBounds = *bounds;
2802        srcM.fFormat = SkMask::kA8_Format;
2803        srcM.fImage = NULL;
2804        if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2805            return false;
2806        }
2807    }
2808
2809    // (possibly) trim the bounds to reflect the clip
2810    // (plus whatever slop the filter needs)
2811    if (clipBounds) {
2812        SkIRect tmp = *clipBounds;
2813        // Ugh. Guard against gigantic margins from wacky filters. Without this
2814        // check we can request arbitrary amounts of slop beyond our visible
2815        // clip, and bring down the renderer (at least on finite RAM machines
2816        // like handsets, etc.). Need to balance this invented value between
2817        // quality of large filters like blurs, and the corresponding memory
2818        // requests.
2819        static const int MAX_MARGIN = 128;
2820        tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2821                  -SkMin32(margin.fY, MAX_MARGIN));
2822        if (!bounds->intersect(tmp)) {
2823            return false;
2824        }
2825    }
2826
2827    return true;
2828}
2829
2830static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
2831                           SkPaint::Style style) {
2832    SkBitmap        bm;
2833    SkDraw          draw;
2834    SkRasterClip    clip;
2835    SkMatrix        matrix;
2836    SkPaint         paint;
2837
2838    bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
2839    bm.setPixels(mask.fImage);
2840
2841    clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
2842    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2843                        -SkIntToScalar(mask.fBounds.fTop));
2844
2845    draw.fBitmap    = &bm;
2846    draw.fRC        = &clip;
2847    draw.fClip      = &clip.bwRgn();
2848    draw.fMatrix    = &matrix;
2849    draw.fBounder   = NULL;
2850    paint.setAntiAlias(true);
2851    paint.setStyle(style);
2852    draw.drawPath(devPath, paint);
2853}
2854
2855bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2856                        const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2857                        SkMask* mask, SkMask::CreateMode mode,
2858                        SkPaint::Style style) {
2859    if (SkMask::kJustRenderImage_CreateMode != mode) {
2860        if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2861            return false;
2862    }
2863
2864    if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2865        mask->fFormat = SkMask::kA8_Format;
2866        mask->fRowBytes = mask->fBounds.width();
2867        size_t size = mask->computeImageSize();
2868        if (0 == size) {
2869            // we're too big to allocate the mask, abort
2870            return false;
2871        }
2872        mask->fImage = SkMask::AllocImage(size);
2873        memset(mask->fImage, 0, mask->computeImageSize());
2874    }
2875
2876    if (SkMask::kJustComputeBounds_CreateMode != mode) {
2877        draw_into_mask(*mask, devPath, style);
2878    }
2879
2880    return true;
2881}
2882
2883