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