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