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