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