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