SkDraw.cpp revision ea033606a06d05d2d42aa7118409fee798e53167
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 dst;
665
666                    SkPath path;
667                    path.moveTo(pts[0]);
668                    path.lineTo(pts[1]);
669
670                    if (paint.getPathEffect()->asPoints(&dst, path, rec, *fMatrix) &&
671                        SK_Scalar1 == dst.fSize.fX && SK_Scalar1 == dst.fSize.fY &&
672                        !(SkPathEffect::PointData::kUsePath_PointFlag & dst.fFlags)) {
673                        SkPaint newP(paint);
674                        newP.setPathEffect(NULL);
675                        newP.setStyle(SkPaint::kFill_Style);
676
677                        if (SkPathEffect::PointData::kCircles_PointFlag & dst.fFlags) {
678                            newP.setStrokeCap(SkPaint::kRound_Cap);
679                        } else {
680                            newP.setStrokeCap(SkPaint::kButt_Cap);
681                        }
682                        if (fDevice) {
683                            fDevice->drawPoints(*this,
684                                                SkCanvas::kPoints_PointMode,
685                                                dst.fNumPoints,
686                                                dst.fPoints,
687                                                newP);
688                        } else {
689                            this->drawPoints(SkCanvas::kPoints_PointMode,
690                                             dst.fNumPoints,
691                                             dst.fPoints,
692                                             newP,
693                                             forceUseDevice);
694                        }
695                        break;
696                    }
697                }
698#endif // DISABLE_DASHING_OPTIMIZATION
699                // couldn't take fast path so fall through!
700            case SkCanvas::kPolygon_PointMode: {
701                count -= 1;
702                SkPath path;
703                SkPaint p(paint);
704                p.setStyle(SkPaint::kStroke_Style);
705                size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
706                for (size_t i = 0; i < count; i += inc) {
707                    path.moveTo(pts[i]);
708                    path.lineTo(pts[i+1]);
709                    if (fDevice) {
710                        fDevice->drawPath(*this, path, p, NULL, true);
711                    } else {
712                        this->drawPath(path, p, NULL, true);
713                    }
714                    path.rewind();
715                }
716                break;
717            }
718        }
719    }
720}
721
722static inline SkPoint* as_lefttop(SkRect* r) {
723    return (SkPoint*)(void*)r;
724}
725
726static inline SkPoint* as_rightbottom(SkRect* r) {
727    return ((SkPoint*)(void*)r) + 1;
728}
729
730static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix,
731                           SkPoint* strokeSize) {
732    if (SkPaint::kMiter_Join != paint.getStrokeJoin() ||
733        paint.getStrokeMiter() < SK_ScalarSqrt2) {
734        return false;
735    }
736
737    SkASSERT(matrix.rectStaysRect());
738    SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
739    matrix.mapVectors(strokeSize, &pt, 1);
740    strokeSize->fX = SkScalarAbs(strokeSize->fX);
741    strokeSize->fY = SkScalarAbs(strokeSize->fY);
742    return true;
743}
744
745SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
746                                         const SkMatrix& matrix,
747                                         SkPoint* strokeSize) {
748    RectType rtype;
749    const SkScalar width = paint.getStrokeWidth();
750    const bool zeroWidth = (0 == width);
751    SkPaint::Style style = paint.getStyle();
752
753    if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
754        style = SkPaint::kFill_Style;
755    }
756
757    if (paint.getPathEffect() || paint.getMaskFilter() ||
758        paint.getRasterizer() || !matrix.rectStaysRect() ||
759        SkPaint::kStrokeAndFill_Style == style) {
760        rtype = kPath_RectType;
761    } else if (SkPaint::kFill_Style == style) {
762        rtype = kFill_RectType;
763    } else if (zeroWidth) {
764        rtype = kHair_RectType;
765    } else if (easy_rect_join(paint, matrix, strokeSize)) {
766        rtype = kStroke_RectType;
767    } else {
768        rtype = kPath_RectType;
769    }
770    return rtype;
771}
772
773static const SkPoint* rect_points(const SkRect& r) {
774    return (const SkPoint*)(void*)&r;
775}
776
777static SkPoint* rect_points(SkRect& r) {
778    return (SkPoint*)(void*)&r;
779}
780
781void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
782    SkDEBUGCODE(this->validate();)
783
784    // nothing to draw
785    if (fRC->isEmpty()) {
786        return;
787    }
788
789    SkPoint strokeSize;
790    RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize);
791
792    if (kPath_RectType == rtype) {
793        SkPath  tmp;
794        tmp.addRect(rect);
795        tmp.setFillType(SkPath::kWinding_FillType);
796        this->drawPath(tmp, paint, NULL, true);
797        return;
798    }
799
800    const SkMatrix& matrix = *fMatrix;
801    SkRect          devRect;
802
803    // transform rect into devRect
804    matrix.mapPoints(rect_points(devRect), rect_points(rect), 2);
805    devRect.sort();
806
807    if (fBounder && !fBounder->doRect(devRect, paint)) {
808        return;
809    }
810
811    // look for the quick exit, before we build a blitter
812    if (true) {
813        SkIRect ir;
814        devRect.roundOut(&ir);
815        if (paint.getStyle() != SkPaint::kFill_Style) {
816            // extra space for hairlines
817            ir.inset(-1, -1);
818        }
819        if (fRC->quickReject(ir))
820            return;
821    }
822
823    SkAutoBlitterChoose blitterStorage(*fBitmap, matrix, paint);
824    const SkRasterClip& clip = *fRC;
825    SkBlitter*          blitter = blitterStorage.get();
826
827    // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
828    // case we are also hairline (if we've gotten to here), which devolves to
829    // effectively just kFill
830    switch (rtype) {
831        case kFill_RectType:
832            if (paint.isAntiAlias()) {
833                SkScan::AntiFillRect(devRect, clip, blitter);
834            } else {
835                SkScan::FillRect(devRect, clip, blitter);
836            }
837            break;
838        case kStroke_RectType:
839            if (paint.isAntiAlias()) {
840                SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter);
841            } else {
842                SkScan::FrameRect(devRect, strokeSize, clip, blitter);
843            }
844            break;
845        case kHair_RectType:
846            if (paint.isAntiAlias()) {
847                SkScan::AntiHairRect(devRect, clip, blitter);
848            } else {
849                SkScan::HairRect(devRect, clip, blitter);
850            }
851            break;
852        default:
853            SkDEBUGFAIL("bad rtype");
854    }
855}
856
857void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
858    if (srcM.fBounds.isEmpty()) {
859        return;
860    }
861
862    const SkMask* mask = &srcM;
863
864    SkMask dstM;
865    if (paint.getMaskFilter() &&
866            paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
867        mask = &dstM;
868    } else {
869        dstM.fImage = NULL;
870    }
871    SkAutoMaskFreeImage ami(dstM.fImage);
872
873    if (fBounder && !fBounder->doIRect(mask->fBounds)) {
874        return;
875    }
876
877    SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
878    SkBlitter* blitter = blitterChooser.get();
879
880    SkAAClipBlitterWrapper wrapper;
881    const SkRegion* clipRgn;
882
883    if (fRC->isBW()) {
884        clipRgn = &fRC->bwRgn();
885    } else {
886        wrapper.init(*fRC, blitter);
887        clipRgn = &wrapper.getRgn();
888        blitter = wrapper.getBlitter();
889    }
890    blitter->blitMaskRegion(*mask, *clipRgn);
891}
892
893static SkScalar fast_len(const SkVector& vec) {
894    SkScalar x = SkScalarAbs(vec.fX);
895    SkScalar y = SkScalarAbs(vec.fY);
896    if (x < y) {
897        SkTSwap(x, y);
898    }
899    return x + SkScalarHalf(y);
900}
901
902static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
903    SkXfermode::Coeff dc;
904    if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) {
905        return false;
906    }
907
908    switch (dc) {
909        case SkXfermode::kOne_Coeff:
910        case SkXfermode::kISA_Coeff:
911        case SkXfermode::kISC_Coeff:
912            return true;
913        default:
914            return false;
915    }
916}
917
918bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
919                           SkScalar* coverage) {
920    SkASSERT(coverage);
921    if (SkPaint::kStroke_Style != paint.getStyle()) {
922        return false;
923    }
924    SkScalar strokeWidth = paint.getStrokeWidth();
925    if (0 == strokeWidth) {
926        *coverage = SK_Scalar1;
927        return true;
928    }
929
930    // if we get here, we need to try to fake a thick-stroke with a modulated
931    // hairline
932
933    if (!paint.isAntiAlias()) {
934        return false;
935    }
936    if (matrix.hasPerspective()) {
937        return false;
938    }
939
940    SkVector src[2], dst[2];
941    src[0].set(strokeWidth, 0);
942    src[1].set(0, strokeWidth);
943    matrix.mapVectors(dst, src, 2);
944    SkScalar len0 = fast_len(dst[0]);
945    SkScalar len1 = fast_len(dst[1]);
946    if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
947        *coverage = SkScalarAve(len0, len1);
948        return true;
949    }
950    return false;
951}
952
953void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
954                      const SkMatrix* prePathMatrix, bool pathIsMutable) const {
955    SkDEBUGCODE(this->validate();)
956
957    // nothing to draw
958    if (fRC->isEmpty()) {
959        return;
960    }
961
962    SkPath*         pathPtr = (SkPath*)&origSrcPath;
963    bool            doFill = true;
964    SkPath          tmpPath;
965    SkMatrix        tmpMatrix;
966    const SkMatrix* matrix = fMatrix;
967
968    if (prePathMatrix) {
969        if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
970                origPaint.getRasterizer()) {
971            SkPath* result = pathPtr;
972
973            if (!pathIsMutable) {
974                result = &tmpPath;
975                pathIsMutable = true;
976            }
977            pathPtr->transform(*prePathMatrix, result);
978            pathPtr = result;
979        } else {
980            if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
981                // overflow
982                return;
983            }
984            matrix = &tmpMatrix;
985        }
986    }
987    // at this point we're done with prePathMatrix
988    SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
989
990    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
991
992    {
993        SkScalar coverage;
994        if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
995            if (SK_Scalar1 == coverage) {
996                paint.writable()->setStrokeWidth(0);
997            } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
998                U8CPU newAlpha;
999#if 0
1000                newAlpha = SkToU8(SkScalarRoundToInt(coverage *
1001                                                     origPaint.getAlpha()));
1002#else
1003                // this is the old technique, which we preserve for now so
1004                // we don't change previous results (testing)
1005                // the new way seems fine, its just (a tiny bit) different
1006                int scale = (int)SkScalarMul(coverage, 256);
1007                newAlpha = origPaint.getAlpha() * scale >> 8;
1008#endif
1009                SkPaint* writablePaint = paint.writable();
1010                writablePaint->setStrokeWidth(0);
1011                writablePaint->setAlpha(newAlpha);
1012            }
1013        }
1014    }
1015
1016    if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
1017        doFill = paint->getFillPath(*pathPtr, &tmpPath);
1018        pathPtr = &tmpPath;
1019    }
1020
1021    if (paint->getRasterizer()) {
1022        SkMask  mask;
1023        if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
1024                            &fRC->getBounds(), paint->getMaskFilter(), &mask,
1025                            SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
1026            this->drawDevMask(mask, *paint);
1027            SkMask::FreeImage(mask.fImage);
1028        }
1029        return;
1030    }
1031
1032    // avoid possibly allocating a new path in transform if we can
1033    SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
1034
1035    // transform the path into device space
1036    pathPtr->transform(*matrix, devPathPtr);
1037
1038    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint);
1039
1040    if (paint->getMaskFilter()) {
1041        SkPaint::Style style = doFill ? SkPaint::kFill_Style :
1042            SkPaint::kStroke_Style;
1043        if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC,
1044                                               fBounder, blitter.get(),
1045                                               style)) {
1046            return; // filterPath() called the blitter, so we're done
1047        }
1048    }
1049
1050    if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) {
1051        return;
1052    }
1053
1054    void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
1055    if (doFill) {
1056        if (paint->isAntiAlias()) {
1057            proc = SkScan::AntiFillPath;
1058        } else {
1059            proc = SkScan::FillPath;
1060        }
1061    } else {    // hairline
1062        if (paint->isAntiAlias()) {
1063            proc = SkScan::AntiHairPath;
1064        } else {
1065            proc = SkScan::HairPath;
1066        }
1067    }
1068    proc(*devPathPtr, *fRC, blitter.get());
1069}
1070
1071/** For the purposes of drawing bitmaps, if a matrix is "almost" translate
1072    go ahead and treat it as if it were, so that subsequent code can go fast.
1073 */
1074static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
1075    SkMatrix::TypeMask mask = matrix.getType();
1076
1077    if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1078        return false;
1079    }
1080    if (mask & SkMatrix::kScale_Mask) {
1081        SkScalar sx = matrix[SkMatrix::kMScaleX];
1082        SkScalar sy = matrix[SkMatrix::kMScaleY];
1083        int w = bitmap.width();
1084        int h = bitmap.height();
1085        int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w)));
1086        int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h)));
1087        return sw == w && sh == h;
1088    }
1089    // if we got here, we're either kTranslate_Mask or identity
1090    return true;
1091}
1092
1093void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
1094                              const SkPaint& paint) const {
1095    SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config);
1096
1097    if (just_translate(*fMatrix, bitmap)) {
1098        int ix = SkScalarRound(fMatrix->getTranslateX());
1099        int iy = SkScalarRound(fMatrix->getTranslateY());
1100
1101        SkAutoLockPixels alp(bitmap);
1102        if (!bitmap.readyToDraw()) {
1103            return;
1104        }
1105
1106        SkMask  mask;
1107        mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1108        mask.fFormat = SkMask::kA8_Format;
1109        mask.fRowBytes = bitmap.rowBytes();
1110        mask.fImage = bitmap.getAddr8(0, 0);
1111
1112        this->drawDevMask(mask, paint);
1113    } else {    // need to xform the bitmap first
1114        SkRect  r;
1115        SkMask  mask;
1116
1117        r.set(0, 0,
1118              SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
1119        fMatrix->mapRect(&r);
1120        r.round(&mask.fBounds);
1121
1122        // set the mask's bounds to the transformed bitmap-bounds,
1123        // clipped to the actual device
1124        {
1125            SkIRect    devBounds;
1126            devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
1127            // need intersect(l, t, r, b) on irect
1128            if (!mask.fBounds.intersect(devBounds)) {
1129                return;
1130            }
1131        }
1132
1133        mask.fFormat = SkMask::kA8_Format;
1134        mask.fRowBytes = SkAlign4(mask.fBounds.width());
1135        size_t size = mask.computeImageSize();
1136        if (0 == size) {
1137            // the mask is too big to allocated, draw nothing
1138            return;
1139        }
1140
1141        // allocate (and clear) our temp buffer to hold the transformed bitmap
1142        SkAutoMalloc    storage(size);
1143        mask.fImage = (uint8_t*)storage.get();
1144        memset(mask.fImage, 0, size);
1145
1146        // now draw our bitmap(src) into mask(dst), transformed by the matrix
1147        {
1148            SkBitmap    device;
1149            device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
1150                             mask.fBounds.height(), mask.fRowBytes);
1151            device.setPixels(mask.fImage);
1152
1153            SkCanvas c(device);
1154            // need the unclipped top/left for the translate
1155            c.translate(-SkIntToScalar(mask.fBounds.fLeft),
1156                        -SkIntToScalar(mask.fBounds.fTop));
1157            c.concat(*fMatrix);
1158
1159            // We can't call drawBitmap, or we'll infinitely recurse. Instead
1160            // we manually build a shader and draw that into our new mask
1161            SkPaint tmpPaint;
1162            tmpPaint.setFlags(paint.getFlags());
1163            SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
1164            SkRect rr;
1165            rr.set(0, 0, SkIntToScalar(bitmap.width()),
1166                   SkIntToScalar(bitmap.height()));
1167            c.drawRect(rr, install.paintWithShader());
1168        }
1169        this->drawDevMask(mask, paint);
1170    }
1171}
1172
1173static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
1174                        const SkRect& srcR) {
1175    SkRect  dstR;
1176    SkIRect devIR;
1177
1178    m.mapRect(&dstR, srcR);
1179    dstR.roundOut(&devIR);
1180    return c.quickReject(devIR);
1181}
1182
1183static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
1184                        int width, int height) {
1185    SkRect  r;
1186    r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1187    return clipped_out(matrix, clip, r);
1188}
1189
1190static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
1191                              const SkBitmap& bitmap) {
1192    return clip.isBW() ||
1193           clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
1194}
1195
1196void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1197                        const SkPaint& origPaint) const {
1198    SkDEBUGCODE(this->validate();)
1199
1200    // nothing to draw
1201    if (fRC->isEmpty() ||
1202            bitmap.width() == 0 || bitmap.height() == 0 ||
1203            bitmap.getConfig() == SkBitmap::kNo_Config) {
1204        return;
1205    }
1206
1207#ifndef SK_ALLOW_OVER_32K_BITMAPS
1208    // run away on too-big bitmaps for now (exceed 16.16)
1209    if (bitmap.width() > 32767 || bitmap.height() > 32767) {
1210        return;
1211    }
1212#endif
1213
1214    SkPaint paint(origPaint);
1215    paint.setStyle(SkPaint::kFill_Style);
1216
1217    SkMatrix matrix;
1218    if (!matrix.setConcat(*fMatrix, prematrix)) {
1219        return;
1220    }
1221
1222    if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
1223        return;
1224    }
1225
1226    if (fBounder && just_translate(matrix, bitmap)) {
1227        SkIRect ir;
1228        int32_t ix = SkScalarRound(matrix.getTranslateX());
1229        int32_t iy = SkScalarRound(matrix.getTranslateY());
1230        ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1231        if (!fBounder->doIRect(ir)) {
1232            return;
1233        }
1234    }
1235
1236    if (bitmap.getConfig() != SkBitmap::kA8_Config &&
1237            just_translate(matrix, bitmap)) {
1238        int ix = SkScalarRound(matrix.getTranslateX());
1239        int iy = SkScalarRound(matrix.getTranslateY());
1240        if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
1241            uint32_t    storage[kBlitterStorageLongCount];
1242            SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1243                                                ix, iy, storage, sizeof(storage));
1244            if (blitter) {
1245                SkAutoTPlacementDelete<SkBlitter>   ad(blitter, storage);
1246
1247                SkIRect    ir;
1248                ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1249
1250                SkScan::FillIRect(ir, *fRC, blitter);
1251                return;
1252            }
1253        }
1254    }
1255
1256    // now make a temp draw on the stack, and use it
1257    //
1258    SkDraw draw(*this);
1259    draw.fMatrix = &matrix;
1260
1261    if (bitmap.getConfig() == SkBitmap::kA8_Config) {
1262        draw.drawBitmapAsMask(bitmap, paint);
1263    } else {
1264        SkAutoBitmapShaderInstall install(bitmap, paint);
1265
1266        SkRect  r;
1267        r.set(0, 0, SkIntToScalar(bitmap.width()),
1268              SkIntToScalar(bitmap.height()));
1269        // is this ok if paint has a rasterizer?
1270        draw.drawRect(r, install.paintWithShader());
1271    }
1272}
1273
1274void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1275                        const SkPaint& origPaint) const {
1276    SkDEBUGCODE(this->validate();)
1277
1278    // nothing to draw
1279    if (fRC->isEmpty() ||
1280            bitmap.width() == 0 || bitmap.height() == 0 ||
1281            bitmap.getConfig() == SkBitmap::kNo_Config) {
1282        return;
1283    }
1284
1285    SkIRect    bounds;
1286    bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1287
1288    if (fRC->quickReject(bounds)) {
1289        return; // nothing to draw
1290    }
1291
1292    SkPaint paint(origPaint);
1293    paint.setStyle(SkPaint::kFill_Style);
1294
1295    if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
1296        uint32_t    storage[kBlitterStorageLongCount];
1297        SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1298                                                x, y, storage, sizeof(storage));
1299
1300        if (blitter) {
1301            SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
1302
1303            if (fBounder && !fBounder->doIRect(bounds)) {
1304                return;
1305            }
1306
1307            SkScan::FillIRect(bounds, *fRC, blitter);
1308            return;
1309        }
1310    }
1311
1312    SkAutoBitmapShaderInstall install(bitmap, paint);
1313    const SkPaint& shaderPaint = install.paintWithShader();
1314
1315    SkMatrix        matrix;
1316    SkRect          r;
1317
1318    // get a scalar version of our rect
1319    r.set(bounds);
1320
1321    // tell the shader our offset
1322    matrix.setTranslate(r.fLeft, r.fTop);
1323    shaderPaint.getShader()->setLocalMatrix(matrix);
1324
1325    SkDraw draw(*this);
1326    matrix.reset();
1327    draw.fMatrix = &matrix;
1328    // call ourself with a rect
1329    // is this OK if paint has a rasterizer?
1330    draw.drawRect(r, shaderPaint);
1331}
1332
1333///////////////////////////////////////////////////////////////////////////////
1334
1335#include "SkScalerContext.h"
1336#include "SkGlyphCache.h"
1337#include "SkTextToPathIter.h"
1338#include "SkUtils.h"
1339
1340static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1341                const char text[], size_t byteLength, SkVector* stopVector) {
1342    SkFixed     x = 0, y = 0;
1343    const char* stop = text + byteLength;
1344
1345    SkAutoKern  autokern;
1346
1347    while (text < stop) {
1348        // don't need x, y here, since all subpixel variants will have the
1349        // same advance
1350        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1351
1352        x += autokern.adjust(glyph) + glyph.fAdvanceX;
1353        y += glyph.fAdvanceY;
1354    }
1355    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1356
1357    SkASSERT(text == stop);
1358}
1359
1360void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1361                              SkScalar x, SkScalar y,
1362                              const SkPaint& paint) const {
1363    SkDEBUGCODE(this->validate();)
1364
1365    SkTextToPathIter iter(text, byteLength, paint, true);
1366
1367    SkMatrix    matrix;
1368    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1369    matrix.postTranslate(x, y);
1370
1371    const SkPath* iterPath;
1372    SkScalar xpos, prevXPos = 0;
1373
1374    while (iter.next(&iterPath, &xpos)) {
1375        matrix.postTranslate(xpos - prevXPos, 0);
1376        if (iterPath) {
1377            const SkPaint& pnt = iter.getPaint();
1378            if (fDevice) {
1379                fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
1380            } else {
1381                this->drawPath(*iterPath, pnt, &matrix, false);
1382            }
1383        }
1384        prevXPos = xpos;
1385    }
1386}
1387
1388// disable warning : local variable used without having been initialized
1389#if defined _WIN32 && _MSC_VER >= 1300
1390#pragma warning ( push )
1391#pragma warning ( disable : 4701 )
1392#endif
1393
1394//////////////////////////////////////////////////////////////////////////////
1395
1396static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
1397                                   SkFixed fx, SkFixed fy,
1398                                   const SkGlyph& glyph) {
1399    int left = SkFixedFloor(fx);
1400    int top = SkFixedFloor(fy);
1401    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1402    SkASSERT(NULL == state.fBounder);
1403    SkASSERT((NULL == state.fClip && state.fAAClip) ||
1404             (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
1405
1406    left += glyph.fLeft;
1407    top  += glyph.fTop;
1408
1409    int right   = left + glyph.fWidth;
1410    int bottom  = top + glyph.fHeight;
1411
1412    SkMask        mask;
1413    SkIRect        storage;
1414    SkIRect*    bounds = &mask.fBounds;
1415
1416    mask.fBounds.set(left, top, right, bottom);
1417
1418    // this extra test is worth it, assuming that most of the time it succeeds
1419    // since we can avoid writing to storage
1420    if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1421        if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1422            return;
1423        bounds = &storage;
1424    }
1425
1426    uint8_t* aa = (uint8_t*)glyph.fImage;
1427    if (NULL == aa) {
1428        aa = (uint8_t*)state.fCache->findImage(glyph);
1429        if (NULL == aa) {
1430            return; // can't rasterize glyph
1431        }
1432    }
1433
1434    mask.fRowBytes = glyph.rowBytes();
1435    mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1436    mask.fImage = aa;
1437    state.fBlitter->blitMask(mask, *bounds);
1438}
1439
1440static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
1441                                  SkFixed fx, SkFixed fy,
1442                                  const SkGlyph& glyph) {
1443    int left = SkFixedFloor(fx);
1444    int top = SkFixedFloor(fy);
1445    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1446    SkASSERT(!state.fClip->isRect());
1447    SkASSERT(NULL == state.fBounder);
1448
1449    SkMask  mask;
1450
1451    left += glyph.fLeft;
1452    top  += glyph.fTop;
1453
1454    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1455    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1456
1457    if (!clipper.done()) {
1458        const SkIRect&  cr = clipper.rect();
1459        const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1460        if (NULL == aa) {
1461            aa = (uint8_t*)state.fCache->findImage(glyph);
1462            if (NULL == aa) {
1463                return;
1464            }
1465        }
1466
1467        mask.fRowBytes = glyph.rowBytes();
1468        mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1469        mask.fImage = (uint8_t*)aa;
1470        do {
1471            state.fBlitter->blitMask(mask, cr);
1472            clipper.next();
1473        } while (!clipper.done());
1474    }
1475}
1476
1477static void D1G_Bounder(const SkDraw1Glyph& state,
1478                        SkFixed fx, SkFixed fy,
1479                        const SkGlyph& glyph) {
1480    int left = SkFixedFloor(fx);
1481    int top = SkFixedFloor(fy);
1482    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1483
1484    SkMask  mask;
1485
1486    left += glyph.fLeft;
1487    top  += glyph.fTop;
1488
1489    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1490    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1491
1492    if (!clipper.done()) {
1493        const SkIRect&  cr = clipper.rect();
1494        const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1495        if (NULL == aa) {
1496            aa = (uint8_t*)state.fCache->findImage(glyph);
1497            if (NULL == aa) {
1498                return;
1499            }
1500        }
1501
1502        // we need to pass the origin, which we approximate with our
1503        // (unadjusted) left,top coordinates (the caller called fixedfloor)
1504        if (state.fBounder->doIRectGlyph(cr,
1505                                         left - glyph.fLeft,
1506                                         top - glyph.fTop, glyph)) {
1507            mask.fRowBytes = glyph.rowBytes();
1508            mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1509            mask.fImage = (uint8_t*)aa;
1510            do {
1511                state.fBlitter->blitMask(mask, cr);
1512                clipper.next();
1513            } while (!clipper.done());
1514        }
1515    }
1516}
1517
1518static void D1G_Bounder_AAClip(const SkDraw1Glyph& state,
1519                               SkFixed fx, SkFixed fy,
1520                               const SkGlyph& glyph) {
1521    int left = SkFixedFloor(fx);
1522    int top = SkFixedFloor(fy);
1523    SkIRect bounds;
1524    bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1525
1526    if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) {
1527        D1G_NoBounder_RectClip(state, fx, fy, glyph);
1528    }
1529}
1530
1531static bool hasCustomD1GProc(const SkDraw& draw) {
1532    return draw.fProcs && draw.fProcs->fD1GProc;
1533}
1534
1535static bool needsRasterTextBlit(const SkDraw& draw) {
1536    return !hasCustomD1GProc(draw);
1537}
1538
1539SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
1540                                      SkGlyphCache* cache) {
1541    fDraw = draw;
1542    fBounder = draw->fBounder;
1543    fBlitter = blitter;
1544    fCache = cache;
1545
1546    if (hasCustomD1GProc(*draw)) {
1547        // todo: fix this assumption about clips w/ custom
1548        fClip = draw->fClip;
1549        fClipBounds = fClip->getBounds();
1550        return draw->fProcs->fD1GProc;
1551    }
1552
1553    if (draw->fRC->isBW()) {
1554        fAAClip = NULL;
1555        fClip = &draw->fRC->bwRgn();
1556        fClipBounds = fClip->getBounds();
1557        if (NULL == fBounder) {
1558            if (fClip->isRect()) {
1559                return D1G_NoBounder_RectClip;
1560            } else {
1561                return D1G_NoBounder_RgnClip;
1562            }
1563        } else {
1564            return D1G_Bounder;
1565        }
1566    } else {    // aaclip
1567        fAAClip = &draw->fRC->aaRgn();
1568        fClip = NULL;
1569        fClipBounds = fAAClip->getBounds();
1570        if (NULL == fBounder) {
1571            return D1G_NoBounder_RectClip;
1572        } else {
1573            return D1G_Bounder_AAClip;
1574        }
1575    }
1576}
1577
1578///////////////////////////////////////////////////////////////////////////////
1579
1580void SkDraw::drawText(const char text[], size_t byteLength,
1581                      SkScalar x, SkScalar y, const SkPaint& paint) const {
1582    SkASSERT(byteLength == 0 || text != NULL);
1583
1584    SkDEBUGCODE(this->validate();)
1585
1586    // nothing to draw
1587    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1588        return;
1589    }
1590
1591    // SkScalarRec doesn't currently have a way of representing hairline stroke and
1592    // will fill if its frame-width is 0.
1593    if (/*paint.isLinearText() ||*/
1594        (fMatrix->hasPerspective()) ||
1595        (0 == paint.getStrokeWidth() && SkPaint::kStroke_Style == paint.getStyle())) {
1596        this->drawText_asPaths(text, byteLength, x, y, paint);
1597        return;
1598    }
1599
1600    SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1601
1602    const SkMatrix* matrix = fMatrix;
1603
1604    SkAutoGlyphCache    autoCache(paint, matrix);
1605    SkGlyphCache*       cache = autoCache.getCache();
1606
1607    // transform our starting point
1608    {
1609        SkPoint loc;
1610        matrix->mapXY(x, y, &loc);
1611        x = loc.fX;
1612        y = loc.fY;
1613    }
1614
1615    // need to measure first
1616    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1617        SkVector    stop;
1618
1619        measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1620
1621        SkScalar    stopX = stop.fX;
1622        SkScalar    stopY = stop.fY;
1623
1624        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1625            stopX = SkScalarHalf(stopX);
1626            stopY = SkScalarHalf(stopY);
1627        }
1628        x -= stopX;
1629        y -= stopY;
1630    }
1631
1632    SkFixed fx = SkScalarToFixed(x);
1633    SkFixed fy = SkScalarToFixed(y);
1634    const char* stop = text + byteLength;
1635
1636    SkFixed fxMask = ~0;
1637    SkFixed fyMask = ~0;
1638    if (cache->isSubpixel()) {
1639        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*matrix);
1640        if (kX_SkAxisAlignment == baseline) {
1641            fyMask = 0;
1642        } else if (kY_SkAxisAlignment == baseline) {
1643            fxMask = 0;
1644        }
1645
1646    // apply bias here to avoid adding 1/2 the sampling frequency in the loop
1647        fx += SK_FixedHalf >> SkGlyph::kSubBits;
1648        fy += SK_FixedHalf >> SkGlyph::kSubBits;
1649    } else {
1650        fx += SK_FixedHalf;
1651        fy += SK_FixedHalf;
1652    }
1653
1654    SkAAClipBlitter     aaBlitter;
1655    SkAutoBlitterChoose blitterChooser;
1656    SkBlitter*          blitter = NULL;
1657    if (needsRasterTextBlit(*this)) {
1658        blitterChooser.choose(*fBitmap, *matrix, paint);
1659        blitter = blitterChooser.get();
1660        if (fRC->isAA()) {
1661            aaBlitter.init(blitter, &fRC->aaRgn());
1662            blitter = &aaBlitter;
1663        }
1664    }
1665
1666    SkAutoKern          autokern;
1667    SkDraw1Glyph        d1g;
1668    SkDraw1Glyph::Proc  proc = d1g.init(this, blitter, cache);
1669
1670    while (text < stop) {
1671        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1672
1673        fx += autokern.adjust(glyph);
1674
1675        if (glyph.fWidth) {
1676            proc(d1g, fx, fy, glyph);
1677        }
1678        fx += glyph.fAdvanceX;
1679        fy += glyph.fAdvanceY;
1680    }
1681}
1682
1683// last parameter is interpreted as SkFixed [x, y]
1684// return the fixed position, which may be rounded or not by the caller
1685//   e.g. subpixel doesn't round
1686typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1687
1688static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1689                          SkIPoint* dst) {
1690    dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1691}
1692
1693static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1694                            SkIPoint* dst) {
1695    dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1696             SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1697}
1698
1699static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1700                           SkIPoint* dst) {
1701    dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1702             SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1703}
1704
1705static AlignProc pick_align_proc(SkPaint::Align align) {
1706    static const AlignProc gProcs[] = {
1707        leftAlignProc, centerAlignProc, rightAlignProc
1708    };
1709
1710    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1711
1712    return gProcs[align];
1713}
1714
1715class TextMapState {
1716public:
1717    mutable SkPoint fLoc;
1718
1719    TextMapState(const SkMatrix& matrix, SkScalar y)
1720        : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1721
1722    typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1723
1724    Proc pickProc(int scalarsPerPosition);
1725
1726private:
1727    const SkMatrix&     fMatrix;
1728    SkMatrix::MapXYProc fProc;
1729    SkScalar            fY; // ignored by MapXYProc
1730    // these are only used by Only... procs
1731    SkScalar            fScaleX, fTransX, fTransformedY;
1732
1733    static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1734        state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1735    }
1736
1737    static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1738        state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1739    }
1740
1741    static void MapOnlyScaleXProc(const TextMapState& state,
1742                                  const SkScalar pos[]) {
1743        state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1744                       state.fTransformedY);
1745    }
1746
1747    static void MapOnlyTransXProc(const TextMapState& state,
1748                                  const SkScalar pos[]) {
1749        state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1750    }
1751};
1752
1753TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1754    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1755
1756    if (1 == scalarsPerPosition) {
1757        unsigned mtype = fMatrix.getType();
1758        if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1759            return MapXProc;
1760        } else {
1761            fScaleX = fMatrix.getScaleX();
1762            fTransX = fMatrix.getTranslateX();
1763            fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1764                            fMatrix.getTranslateY();
1765            return (mtype & SkMatrix::kScale_Mask) ?
1766                        MapOnlyScaleXProc : MapOnlyTransXProc;
1767        }
1768    } else {
1769        return MapXYProc;
1770    }
1771}
1772
1773//////////////////////////////////////////////////////////////////////////////
1774
1775void SkDraw::drawPosText(const char text[], size_t byteLength,
1776                         const SkScalar pos[], SkScalar constY,
1777                         int scalarsPerPosition, const SkPaint& paint) const {
1778    SkASSERT(byteLength == 0 || text != NULL);
1779    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1780
1781    SkDEBUGCODE(this->validate();)
1782
1783    // nothing to draw
1784    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1785        return;
1786    }
1787
1788    if (/*paint.isLinearText() ||*/
1789        (fMatrix->hasPerspective())) {
1790        // TODO !!!!
1791//      this->drawText_asPaths(text, byteLength, x, y, paint);
1792        return;
1793    }
1794
1795    const SkMatrix* matrix = fMatrix;
1796
1797    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1798    SkAutoGlyphCache    autoCache(paint, matrix);
1799    SkGlyphCache*       cache = autoCache.getCache();
1800
1801    SkAAClipBlitterWrapper wrapper;
1802    SkAutoBlitterChoose blitterChooser;
1803    SkBlitter* blitter = NULL;
1804    if (needsRasterTextBlit(*this)) {
1805        blitterChooser.choose(*fBitmap, *matrix, paint);
1806        blitter = blitterChooser.get();
1807        if (fRC->isAA()) {
1808            wrapper.init(*fRC, blitter);
1809            blitter = wrapper.getBlitter();
1810        }
1811    }
1812
1813    const char*        stop = text + byteLength;
1814    AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
1815    SkDraw1Glyph       d1g;
1816    SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache);
1817    TextMapState       tms(*matrix, constY);
1818    TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1819
1820    if (cache->isSubpixel()) {
1821        // maybe we should skip the rounding if linearText is set
1822        SkAxisAlignment roundBaseline = SkComputeAxisAlignmentForHText(*matrix);
1823
1824        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1825            while (text < stop) {
1826
1827                tmsProc(tms, pos);
1828
1829#ifdef SK_DRAW_POS_TEXT_IGNORE_SUBPIXEL_LEFT_ALIGN_FIX
1830                SkFixed fx = SkScalarToFixed(tms.fLoc.fX);
1831                SkFixed fy = SkScalarToFixed(tms.fLoc.fY);
1832#else
1833                SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + (SK_FixedHalf >> SkGlyph::kSubBits);
1834                SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + (SK_FixedHalf >> SkGlyph::kSubBits);
1835#endif
1836                SkFixed fxMask = ~0;
1837                SkFixed fyMask = ~0;
1838
1839                if (kX_SkAxisAlignment == roundBaseline) {
1840                    fyMask = 0;
1841                } else if (kY_SkAxisAlignment == roundBaseline) {
1842                    fxMask = 0;
1843                }
1844
1845                const SkGlyph& glyph = glyphCacheProc(cache, &text,
1846                                                      fx & fxMask, fy & fyMask);
1847
1848                if (glyph.fWidth) {
1849                    proc(d1g, fx, fy, glyph);
1850                }
1851                pos += scalarsPerPosition;
1852            }
1853        } else {
1854            while (text < stop) {
1855                const char* currentText = text;
1856                const SkGlyph* glyph = &glyphCacheProc(cache, &text, 0, 0);
1857
1858                if (glyph->fWidth) {
1859                    SkDEBUGCODE(SkFixed prevAdvX = glyph->fAdvanceX;)
1860                    SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;)
1861
1862                    SkFixed fx, fy;
1863                    SkFixed fxMask = ~0;
1864                    SkFixed fyMask = ~0;
1865                    tmsProc(tms, pos);
1866
1867                    {
1868                        SkIPoint fixedLoc;
1869                        alignProc(tms.fLoc, *glyph, &fixedLoc);
1870                        fx = fixedLoc.fX + (SK_FixedHalf >> SkGlyph::kSubBits);
1871                        fy = fixedLoc.fY + (SK_FixedHalf >> SkGlyph::kSubBits);
1872
1873                        if (kX_SkAxisAlignment == roundBaseline) {
1874                            fyMask = 0;
1875                        } else if (kY_SkAxisAlignment == roundBaseline) {
1876                            fxMask = 0;
1877                        }
1878                    }
1879
1880                    // have to call again, now that we've been "aligned"
1881                    glyph = &glyphCacheProc(cache, &currentText,
1882                                            fx & fxMask, fy & fyMask);
1883                    // the assumption is that the advance hasn't changed
1884                    SkASSERT(prevAdvX == glyph->fAdvanceX);
1885                    SkASSERT(prevAdvY == glyph->fAdvanceY);
1886
1887                    proc(d1g, fx, fy, *glyph);
1888                }
1889                pos += scalarsPerPosition;
1890            }
1891        }
1892    } else {    // not subpixel
1893        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1894            while (text < stop) {
1895                // the last 2 parameters are ignored
1896                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1897
1898                if (glyph.fWidth) {
1899                    tmsProc(tms, pos);
1900
1901                    proc(d1g,
1902                         SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf,
1903                         SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf,
1904                         glyph);
1905                }
1906                pos += scalarsPerPosition;
1907            }
1908        } else {
1909            while (text < stop) {
1910                // the last 2 parameters are ignored
1911                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1912
1913                if (glyph.fWidth) {
1914                    tmsProc(tms, pos);
1915
1916                    SkIPoint fixedLoc;
1917                    alignProc(tms.fLoc, glyph, &fixedLoc);
1918
1919                    proc(d1g,
1920                         fixedLoc.fX + SK_FixedHalf,
1921                         fixedLoc.fY + SK_FixedHalf,
1922                         glyph);
1923                }
1924                pos += scalarsPerPosition;
1925            }
1926        }
1927    }
1928}
1929
1930#if defined _WIN32 && _MSC_VER >= 1300
1931#pragma warning ( pop )
1932#endif
1933
1934///////////////////////////////////////////////////////////////////////////////
1935
1936#include "SkPathMeasure.h"
1937
1938static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
1939                        SkPathMeasure& meas, const SkMatrix& matrix) {
1940    SkMatrix::MapXYProc proc = matrix.getMapXYProc();
1941
1942    for (int i = 0; i < count; i++) {
1943        SkPoint pos;
1944        SkVector tangent;
1945
1946        proc(matrix, src[i].fX, src[i].fY, &pos);
1947        SkScalar sx = pos.fX;
1948        SkScalar sy = pos.fY;
1949
1950        if (!meas.getPosTan(sx, &pos, &tangent)) {
1951            // set to 0 if the measure failed, so that we just set dst == pos
1952            tangent.set(0, 0);
1953        }
1954
1955        /*  This is the old way (that explains our approach but is way too slow
1956            SkMatrix    matrix;
1957            SkPoint     pt;
1958
1959            pt.set(sx, sy);
1960            matrix.setSinCos(tangent.fY, tangent.fX);
1961            matrix.preTranslate(-sx, 0);
1962            matrix.postTranslate(pos.fX, pos.fY);
1963            matrix.mapPoints(&dst[i], &pt, 1);
1964        */
1965        dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
1966                   pos.fY + SkScalarMul(tangent.fX, sy));
1967    }
1968}
1969
1970/*  TODO
1971
1972    Need differentially more subdivisions when the follow-path is curvy. Not sure how to
1973    determine that, but we need it. I guess a cheap answer is let the caller tell us,
1974    but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
1975*/
1976static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
1977                      const SkMatrix& matrix) {
1978    SkPath::Iter    iter(src, false);
1979    SkPoint         srcP[4], dstP[3];
1980    SkPath::Verb    verb;
1981
1982    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
1983        switch (verb) {
1984            case SkPath::kMove_Verb:
1985                morphpoints(dstP, srcP, 1, meas, matrix);
1986                dst->moveTo(dstP[0]);
1987                break;
1988            case SkPath::kLine_Verb:
1989                // turn lines into quads to look bendy
1990                srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
1991                srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
1992                morphpoints(dstP, srcP, 2, meas, matrix);
1993                dst->quadTo(dstP[0], dstP[1]);
1994                break;
1995            case SkPath::kQuad_Verb:
1996                morphpoints(dstP, &srcP[1], 2, meas, matrix);
1997                dst->quadTo(dstP[0], dstP[1]);
1998                break;
1999            case SkPath::kCubic_Verb:
2000                morphpoints(dstP, &srcP[1], 3, meas, matrix);
2001                dst->cubicTo(dstP[0], dstP[1], dstP[2]);
2002                break;
2003            case SkPath::kClose_Verb:
2004                dst->close();
2005                break;
2006            default:
2007                SkDEBUGFAIL("unknown verb");
2008                break;
2009        }
2010    }
2011}
2012
2013void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
2014                            const SkPath& follow, const SkMatrix* matrix,
2015                            const SkPaint& paint) const {
2016    SkASSERT(byteLength == 0 || text != NULL);
2017
2018    // nothing to draw
2019    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2020        return;
2021    }
2022
2023    SkTextToPathIter    iter(text, byteLength, paint, true);
2024    SkPathMeasure       meas(follow, false);
2025    SkScalar            hOffset = 0;
2026
2027    // need to measure first
2028    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
2029        SkScalar pathLen = meas.getLength();
2030        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2031            pathLen = SkScalarHalf(pathLen);
2032        }
2033        hOffset += pathLen;
2034    }
2035
2036    const SkPath*   iterPath;
2037    SkScalar        xpos;
2038    SkMatrix        scaledMatrix;
2039    SkScalar        scale = iter.getPathScale();
2040
2041    scaledMatrix.setScale(scale, scale);
2042
2043    while (iter.next(&iterPath, &xpos)) {
2044        if (iterPath) {
2045            SkPath      tmp;
2046            SkMatrix    m(scaledMatrix);
2047
2048            m.postTranslate(xpos + hOffset, 0);
2049            if (matrix) {
2050                m.postConcat(*matrix);
2051            }
2052            morphpath(&tmp, *iterPath, meas, m);
2053            if (fDevice) {
2054                fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
2055            } else {
2056                this->drawPath(tmp, iter.getPaint(), NULL, true);
2057            }
2058        }
2059    }
2060}
2061
2062#ifdef SK_BUILD_FOR_ANDROID
2063void SkDraw::drawPosTextOnPath(const char text[], size_t byteLength,
2064                               const SkPoint pos[], const SkPaint& paint,
2065                               const SkPath& path, const SkMatrix* matrix) const {
2066    // nothing to draw
2067    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2068        return;
2069    }
2070
2071    SkMatrix scaledMatrix;
2072    SkPathMeasure meas(path, false);
2073
2074    SkMeasureCacheProc glyphCacheProc = paint.getMeasureCacheProc(
2075            SkPaint::kForward_TextBufferDirection, true);
2076
2077    // Copied (modified) from SkTextToPathIter constructor to setup paint
2078    SkPaint tempPaint(paint);
2079
2080    tempPaint.setLinearText(true);
2081    tempPaint.setMaskFilter(NULL); // don't want this affecting our path-cache lookup
2082
2083    if (tempPaint.getPathEffect() == NULL && !(tempPaint.getStrokeWidth() > 0
2084            && tempPaint.getStyle() != SkPaint::kFill_Style)) {
2085        tempPaint.setStyle(SkPaint::kFill_Style);
2086        tempPaint.setPathEffect(NULL);
2087    }
2088    // End copied from SkTextToPathIter constructor
2089
2090    // detach cache
2091    SkGlyphCache* cache = tempPaint.detachCache(NULL);
2092
2093    // Must set scale, even if 1
2094    SkScalar scale = SK_Scalar1;
2095    scaledMatrix.setScale(scale, scale);
2096
2097    // Loop over all glyph ids
2098    for (const char* stop = text + byteLength; text < stop; pos++) {
2099
2100        const SkGlyph& glyph = glyphCacheProc(cache, &text);
2101        SkPath tmp;
2102
2103        const SkPath* glyphPath = cache->findPath(glyph);
2104        if (glyphPath == NULL) {
2105            continue;
2106        }
2107
2108        SkMatrix m(scaledMatrix);
2109        m.postTranslate(pos->fX, 0);
2110
2111        if (matrix) {
2112            m.postConcat(*matrix);
2113        }
2114
2115        morphpath(&tmp, *glyphPath, meas, m);
2116        this->drawPath(tmp, tempPaint);
2117
2118    }
2119
2120    // re-attach cache
2121    SkGlyphCache::AttachCache(cache);
2122}
2123#endif
2124
2125///////////////////////////////////////////////////////////////////////////////
2126
2127struct VertState {
2128    int f0, f1, f2;
2129
2130    VertState(int vCount, const uint16_t indices[], int indexCount)
2131            : fIndices(indices) {
2132        fCurrIndex = 0;
2133        if (indices) {
2134            fCount = indexCount;
2135        } else {
2136            fCount = vCount;
2137        }
2138    }
2139
2140    typedef bool (*Proc)(VertState*);
2141    Proc chooseProc(SkCanvas::VertexMode mode);
2142
2143private:
2144    int             fCount;
2145    int             fCurrIndex;
2146    const uint16_t* fIndices;
2147
2148    static bool Triangles(VertState*);
2149    static bool TrianglesX(VertState*);
2150    static bool TriangleStrip(VertState*);
2151    static bool TriangleStripX(VertState*);
2152    static bool TriangleFan(VertState*);
2153    static bool TriangleFanX(VertState*);
2154};
2155
2156bool VertState::Triangles(VertState* state) {
2157    int index = state->fCurrIndex;
2158    if (index + 3 > state->fCount) {
2159        return false;
2160    }
2161    state->f0 = index + 0;
2162    state->f1 = index + 1;
2163    state->f2 = index + 2;
2164    state->fCurrIndex = index + 3;
2165    return true;
2166}
2167
2168bool VertState::TrianglesX(VertState* state) {
2169    const uint16_t* indices = state->fIndices;
2170    int index = state->fCurrIndex;
2171    if (index + 3 > state->fCount) {
2172        return false;
2173    }
2174    state->f0 = indices[index + 0];
2175    state->f1 = indices[index + 1];
2176    state->f2 = indices[index + 2];
2177    state->fCurrIndex = index + 3;
2178    return true;
2179}
2180
2181bool VertState::TriangleStrip(VertState* state) {
2182    int index = state->fCurrIndex;
2183    if (index + 3 > state->fCount) {
2184        return false;
2185    }
2186    state->f2 = index + 2;
2187    if (index & 1) {
2188        state->f0 = index + 1;
2189        state->f1 = index + 0;
2190    } else {
2191        state->f0 = index + 0;
2192        state->f1 = index + 1;
2193    }
2194    state->fCurrIndex = index + 1;
2195    return true;
2196}
2197
2198bool VertState::TriangleStripX(VertState* state) {
2199    const uint16_t* indices = state->fIndices;
2200    int index = state->fCurrIndex;
2201    if (index + 3 > state->fCount) {
2202        return false;
2203    }
2204    state->f2 = indices[index + 2];
2205    if (index & 1) {
2206        state->f0 = indices[index + 1];
2207        state->f1 = indices[index + 0];
2208    } else {
2209        state->f0 = indices[index + 0];
2210        state->f1 = indices[index + 1];
2211    }
2212    state->fCurrIndex = index + 1;
2213    return true;
2214}
2215
2216bool VertState::TriangleFan(VertState* state) {
2217    int index = state->fCurrIndex;
2218    if (index + 3 > state->fCount) {
2219        return false;
2220    }
2221    state->f0 = 0;
2222    state->f1 = index + 1;
2223    state->f2 = index + 2;
2224    state->fCurrIndex = index + 1;
2225    return true;
2226}
2227
2228bool VertState::TriangleFanX(VertState* state) {
2229    const uint16_t* indices = state->fIndices;
2230    int index = state->fCurrIndex;
2231    if (index + 3 > state->fCount) {
2232        return false;
2233    }
2234    state->f0 = indices[0];
2235    state->f1 = indices[index + 1];
2236    state->f2 = indices[index + 2];
2237    state->fCurrIndex = index + 1;
2238    return true;
2239}
2240
2241VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
2242    switch (mode) {
2243        case SkCanvas::kTriangles_VertexMode:
2244            return fIndices ? TrianglesX : Triangles;
2245        case SkCanvas::kTriangleStrip_VertexMode:
2246            return fIndices ? TriangleStripX : TriangleStrip;
2247        case SkCanvas::kTriangleFan_VertexMode:
2248            return fIndices ? TriangleFanX : TriangleFan;
2249        default:
2250            return NULL;
2251    }
2252}
2253
2254typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
2255                         SkBlitter*);
2256
2257static HairProc ChooseHairProc(bool doAntiAlias) {
2258    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
2259}
2260
2261static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
2262                              const SkPoint texs[], SkMatrix* matrix) {
2263    SkPoint src[3], dst[3];
2264
2265    src[0] = texs[state.f0];
2266    src[1] = texs[state.f1];
2267    src[2] = texs[state.f2];
2268    dst[0] = verts[state.f0];
2269    dst[1] = verts[state.f1];
2270    dst[2] = verts[state.f2];
2271    return matrix->setPolyToPoly(src, dst, 3);
2272}
2273
2274class SkTriColorShader : public SkShader {
2275public:
2276    SkTriColorShader() {}
2277
2278    bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2279
2280    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
2281
2282    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
2283
2284protected:
2285    SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
2286
2287private:
2288    SkMatrix    fDstToUnit;
2289    SkPMColor   fColors[3];
2290
2291    typedef SkShader INHERITED;
2292};
2293
2294bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
2295                             int index0, int index1, int index2) {
2296
2297    fColors[0] = SkPreMultiplyColor(colors[index0]);
2298    fColors[1] = SkPreMultiplyColor(colors[index1]);
2299    fColors[2] = SkPreMultiplyColor(colors[index2]);
2300
2301    SkMatrix m, im;
2302    m.reset();
2303    m.set(0, pts[index1].fX - pts[index0].fX);
2304    m.set(1, pts[index2].fX - pts[index0].fX);
2305    m.set(2, pts[index0].fX);
2306    m.set(3, pts[index1].fY - pts[index0].fY);
2307    m.set(4, pts[index2].fY - pts[index0].fY);
2308    m.set(5, pts[index0].fY);
2309    if (!m.invert(&im)) {
2310        return false;
2311    }
2312    return fDstToUnit.setConcat(im, this->getTotalInverse());
2313}
2314
2315#include "SkColorPriv.h"
2316#include "SkComposeShader.h"
2317
2318static int ScalarTo256(SkScalar v) {
2319    int scale = SkScalarToFixed(v) >> 8;
2320    if (scale < 0) {
2321        scale = 0;
2322    }
2323    if (scale > 255) {
2324        scale = 255;
2325    }
2326    return SkAlpha255To256(scale);
2327}
2328
2329void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2330    SkPoint src;
2331
2332    for (int i = 0; i < count; i++) {
2333        fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2334        x += 1;
2335
2336        int scale1 = ScalarTo256(src.fX);
2337        int scale2 = ScalarTo256(src.fY);
2338        int scale0 = 256 - scale1 - scale2;
2339        if (scale0 < 0) {
2340            if (scale1 > scale2) {
2341                scale2 = 256 - scale1;
2342            } else {
2343                scale1 = 256 - scale2;
2344            }
2345            scale0 = 0;
2346        }
2347
2348        dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2349        SkAlphaMulQ(fColors[1], scale1) +
2350        SkAlphaMulQ(fColors[2], scale2);
2351    }
2352}
2353
2354void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2355                          const SkPoint vertices[], const SkPoint textures[],
2356                          const SkColor colors[], SkXfermode* xmode,
2357                          const uint16_t indices[], int indexCount,
2358                          const SkPaint& paint) const {
2359    SkASSERT(0 == count || NULL != vertices);
2360
2361    // abort early if there is nothing to draw
2362    if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
2363        return;
2364    }
2365
2366    // transform out vertices into device coordinates
2367    SkAutoSTMalloc<16, SkPoint> storage(count);
2368    SkPoint* devVerts = storage.get();
2369    fMatrix->mapPoints(devVerts, vertices, count);
2370
2371    if (fBounder) {
2372        SkRect bounds;
2373        bounds.set(devVerts, count);
2374        if (!fBounder->doRect(bounds, paint)) {
2375            return;
2376        }
2377    }
2378
2379    /*
2380        We can draw the vertices in 1 of 4 ways:
2381
2382        - solid color (no shader/texture[], no colors[])
2383        - just colors (no shader/texture[], has colors[])
2384        - just texture (has shader/texture[], no colors[])
2385        - colors * texture (has shader/texture[], has colors[])
2386
2387        Thus for texture drawing, we need both texture[] and a shader.
2388    */
2389
2390    SkTriColorShader triShader; // must be above declaration of p
2391    SkPaint p(paint);
2392
2393    SkShader* shader = p.getShader();
2394    if (NULL == shader) {
2395        // if we have no shader, we ignore the texture coordinates
2396        textures = NULL;
2397    } else if (NULL == textures) {
2398        // if we don't have texture coordinates, ignore the shader
2399        p.setShader(NULL);
2400        shader = NULL;
2401    }
2402
2403    // setup the custom shader (if needed)
2404    if (NULL != colors) {
2405        if (NULL == textures) {
2406            // just colors (no texture)
2407            shader = p.setShader(&triShader);
2408        } else {
2409            // colors * texture
2410            SkASSERT(shader);
2411            bool releaseMode = false;
2412            if (NULL == xmode) {
2413                xmode = SkXfermode::Create(SkXfermode::kMultiply_Mode);
2414                releaseMode = true;
2415            }
2416            SkShader* compose = SkNEW_ARGS(SkComposeShader,
2417                                           (&triShader, shader, xmode));
2418            p.setShader(compose)->unref();
2419            if (releaseMode) {
2420                xmode->unref();
2421            }
2422            shader = compose;
2423        }
2424    }
2425
2426    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2427    // important that we abort early, as below we may manipulate the shader
2428    // and that is only valid if the shader returned true from setContext.
2429    // If it returned false, then our blitter will be the NullBlitter.
2430    if (blitter->isNullBlitter()) {
2431        return;
2432    }
2433
2434    // setup our state and function pointer for iterating triangles
2435    VertState       state(count, indices, indexCount);
2436    VertState::Proc vertProc = state.chooseProc(vmode);
2437
2438    if (NULL != textures || NULL != colors) {
2439        SkMatrix  tempM;
2440        SkMatrix  savedLocalM;
2441        if (shader) {
2442            savedLocalM = shader->getLocalMatrix();
2443        }
2444
2445        while (vertProc(&state)) {
2446            if (NULL != textures) {
2447                if (texture_to_matrix(state, vertices, textures, &tempM)) {
2448                    tempM.postConcat(savedLocalM);
2449                    shader->setLocalMatrix(tempM);
2450                    // need to recal setContext since we changed the local matrix
2451                    shader->endContext();
2452                    if (!shader->setContext(*fBitmap, p, *fMatrix)) {
2453                        continue;
2454                    }
2455                }
2456            }
2457            if (NULL != colors) {
2458                if (!triShader.setup(vertices, colors,
2459                                     state.f0, state.f1, state.f2)) {
2460                    continue;
2461                }
2462            }
2463
2464            SkPoint tmp[] = {
2465                devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
2466            };
2467            SkScan::FillTriangle(tmp, *fRC, blitter.get());
2468        }
2469        // now restore the shader's original local matrix
2470        if (NULL != shader) {
2471            shader->setLocalMatrix(savedLocalM);
2472        }
2473    } else {
2474        // no colors[] and no texture
2475        HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2476        const SkRasterClip& clip = *fRC;
2477        while (vertProc(&state)) {
2478            hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
2479            hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
2480            hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
2481        }
2482    }
2483}
2484
2485///////////////////////////////////////////////////////////////////////////////
2486///////////////////////////////////////////////////////////////////////////////
2487
2488#ifdef SK_DEBUG
2489
2490void SkDraw::validate() const {
2491    SkASSERT(fBitmap != NULL);
2492    SkASSERT(fMatrix != NULL);
2493    SkASSERT(fClip != NULL);
2494    SkASSERT(fRC != NULL);
2495
2496    const SkIRect&  cr = fRC->getBounds();
2497    SkIRect         br;
2498
2499    br.set(0, 0, fBitmap->width(), fBitmap->height());
2500    SkASSERT(cr.isEmpty() || br.contains(cr));
2501}
2502
2503#endif
2504
2505///////////////////////////////////////////////////////////////////////////////
2506
2507SkBounder::SkBounder() {
2508    // initialize up front. This gets reset by SkCanvas before each draw call.
2509    fClip = &SkRegion::GetEmptyRegion();
2510}
2511
2512bool SkBounder::doIRect(const SkIRect& r) {
2513    SkIRect    rr;
2514    return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
2515}
2516
2517// TODO: change the prototype to take fixed, and update the callers
2518bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
2519                             const SkGlyph& glyph) {
2520    SkIRect    rr;
2521    if (!rr.intersect(fClip->getBounds(), r)) {
2522        return false;
2523    }
2524    GlyphRec rec;
2525    rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
2526    rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
2527                 rec.fLSB.fY + glyph.fAdvanceY);
2528    rec.fGlyphID = glyph.getGlyphID();
2529    rec.fFlags = 0;
2530    return this->onIRectGlyph(rr, rec);
2531}
2532
2533bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
2534                           const SkPaint& paint) {
2535    SkIRect     r;
2536    SkScalar    v0, v1;
2537
2538    v0 = pt0.fX;
2539    v1 = pt1.fX;
2540    if (v0 > v1) {
2541        SkTSwap<SkScalar>(v0, v1);
2542    }
2543    r.fLeft     = SkScalarFloor(v0);
2544    r.fRight    = SkScalarCeil(v1);
2545
2546    v0 = pt0.fY;
2547    v1 = pt1.fY;
2548    if (v0 > v1) {
2549        SkTSwap<SkScalar>(v0, v1);
2550    }
2551    r.fTop      = SkScalarFloor(v0);
2552    r.fBottom   = SkScalarCeil(v1);
2553
2554    if (paint.isAntiAlias()) {
2555        r.inset(-1, -1);
2556    }
2557    return this->doIRect(r);
2558}
2559
2560bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
2561    SkIRect    r;
2562
2563    if (paint.getStyle() == SkPaint::kFill_Style) {
2564        rect.round(&r);
2565    } else {
2566        int rad = -1;
2567        rect.roundOut(&r);
2568        if (paint.isAntiAlias()) {
2569            rad = -2;
2570        }
2571        r.inset(rad, rad);
2572    }
2573    return this->doIRect(r);
2574}
2575
2576bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
2577    SkIRect       r;
2578    const SkRect& bounds = path.getBounds();
2579
2580    if (doFill) {
2581        bounds.round(&r);
2582    } else {    // hairline
2583        bounds.roundOut(&r);
2584    }
2585
2586    if (paint.isAntiAlias()) {
2587        r.inset(-1, -1);
2588    }
2589    return this->doIRect(r);
2590}
2591
2592void SkBounder::commit() {
2593    // override in subclass
2594}
2595
2596////////////////////////////////////////////////////////////////////////////////////////////////
2597
2598#include "SkPath.h"
2599#include "SkDraw.h"
2600#include "SkRegion.h"
2601#include "SkBlitter.h"
2602
2603static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2604                           SkMaskFilter* filter, const SkMatrix* filterMatrix,
2605                           SkIRect* bounds) {
2606    if (devPath.isEmpty()) {
2607        return false;
2608    }
2609
2610    //  init our bounds from the path
2611    {
2612        SkRect pathBounds = devPath.getBounds();
2613        pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2614        pathBounds.roundOut(bounds);
2615    }
2616
2617    SkIPoint margin = SkIPoint::Make(0, 0);
2618    if (filter) {
2619        SkASSERT(filterMatrix);
2620
2621        SkMask srcM, dstM;
2622
2623        srcM.fBounds = *bounds;
2624        srcM.fFormat = SkMask::kA8_Format;
2625        srcM.fImage = NULL;
2626        if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2627            return false;
2628        }
2629    }
2630
2631    // (possibly) trim the bounds to reflect the clip
2632    // (plus whatever slop the filter needs)
2633    if (clipBounds) {
2634        SkIRect tmp = *clipBounds;
2635        // Ugh. Guard against gigantic margins from wacky filters. Without this
2636        // check we can request arbitrary amounts of slop beyond our visible
2637        // clip, and bring down the renderer (at least on finite RAM machines
2638        // like handsets, etc.). Need to balance this invented value between
2639        // quality of large filters like blurs, and the corresponding memory
2640        // requests.
2641        static const int MAX_MARGIN = 128;
2642        tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2643                  -SkMin32(margin.fY, MAX_MARGIN));
2644        if (!bounds->intersect(tmp)) {
2645            return false;
2646        }
2647    }
2648
2649    return true;
2650}
2651
2652static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
2653                           SkPaint::Style style) {
2654    SkBitmap        bm;
2655    SkDraw          draw;
2656    SkRasterClip    clip;
2657    SkMatrix        matrix;
2658    SkPaint         paint;
2659
2660    bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
2661    bm.setPixels(mask.fImage);
2662
2663    clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
2664    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2665                        -SkIntToScalar(mask.fBounds.fTop));
2666
2667    draw.fBitmap    = &bm;
2668    draw.fRC        = &clip;
2669    draw.fClip      = &clip.bwRgn();
2670    draw.fMatrix    = &matrix;
2671    draw.fBounder   = NULL;
2672    paint.setAntiAlias(true);
2673    paint.setStyle(style);
2674    draw.drawPath(devPath, paint);
2675}
2676
2677bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2678                        SkMaskFilter* filter, const SkMatrix* filterMatrix,
2679                        SkMask* mask, SkMask::CreateMode mode,
2680                        SkPaint::Style style) {
2681    if (SkMask::kJustRenderImage_CreateMode != mode) {
2682        if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2683            return false;
2684    }
2685
2686    if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2687        mask->fFormat = SkMask::kA8_Format;
2688        mask->fRowBytes = mask->fBounds.width();
2689        size_t size = mask->computeImageSize();
2690        if (0 == size) {
2691            // we're too big to allocate the mask, abort
2692            return false;
2693        }
2694        mask->fImage = SkMask::AllocImage(size);
2695        memset(mask->fImage, 0, mask->computeImageSize());
2696    }
2697
2698    if (SkMask::kJustComputeBounds_CreateMode != mode) {
2699        draw_into_mask(*mask, devPath, style);
2700    }
2701
2702    return true;
2703}
2704