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