SkDraw.cpp revision d923288e50b5a69afb0bdd5c161191b24cab8345
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 kN32_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 kN32_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 && kN32_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            tmpMatrix.setConcat(*matrix, *prePathMatrix);
1060            matrix = &tmpMatrix;
1061        }
1062    }
1063    // at this point we're done with prePathMatrix
1064    SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
1065
1066    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
1067
1068    {
1069        SkScalar coverage;
1070        if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
1071            if (SK_Scalar1 == coverage) {
1072                paint.writable()->setStrokeWidth(0);
1073            } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
1074                U8CPU newAlpha;
1075#if 0
1076                newAlpha = SkToU8(SkScalarRoundToInt(coverage *
1077                                                     origPaint.getAlpha()));
1078#else
1079                // this is the old technique, which we preserve for now so
1080                // we don't change previous results (testing)
1081                // the new way seems fine, its just (a tiny bit) different
1082                int scale = (int)SkScalarMul(coverage, 256);
1083                newAlpha = origPaint.getAlpha() * scale >> 8;
1084#endif
1085                SkPaint* writablePaint = paint.writable();
1086                writablePaint->setStrokeWidth(0);
1087                writablePaint->setAlpha(newAlpha);
1088            }
1089        }
1090    }
1091
1092    if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
1093        SkRect cullRect;
1094        const SkRect* cullRectPtr = NULL;
1095        if (this->computeConservativeLocalClipBounds(&cullRect)) {
1096            cullRectPtr = &cullRect;
1097        }
1098        doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr);
1099        pathPtr = &tmpPath;
1100    }
1101
1102    if (paint->getRasterizer()) {
1103        SkMask  mask;
1104        if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
1105                            &fRC->getBounds(), paint->getMaskFilter(), &mask,
1106                            SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
1107            this->drawDevMask(mask, *paint);
1108            SkMask::FreeImage(mask.fImage);
1109        }
1110        return;
1111    }
1112
1113    // avoid possibly allocating a new path in transform if we can
1114    SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
1115
1116    // transform the path into device space
1117    pathPtr->transform(*matrix, devPathPtr);
1118
1119    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint, drawCoverage);
1120
1121    if (paint->getMaskFilter()) {
1122        SkPaint::Style style = doFill ? SkPaint::kFill_Style :
1123            SkPaint::kStroke_Style;
1124        if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC,
1125                                               fBounder, blitter.get(),
1126                                               style)) {
1127            return; // filterPath() called the blitter, so we're done
1128        }
1129    }
1130
1131    if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) {
1132        return;
1133    }
1134
1135    void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
1136    if (doFill) {
1137        if (paint->isAntiAlias()) {
1138            proc = SkScan::AntiFillPath;
1139        } else {
1140            proc = SkScan::FillPath;
1141        }
1142    } else {    // hairline
1143        if (paint->isAntiAlias()) {
1144            proc = SkScan::AntiHairPath;
1145        } else {
1146            proc = SkScan::HairPath;
1147        }
1148    }
1149    proc(*devPathPtr, *fRC, blitter.get());
1150}
1151
1152/** For the purposes of drawing bitmaps, if a matrix is "almost" translate
1153    go ahead and treat it as if it were, so that subsequent code can go fast.
1154 */
1155static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
1156    unsigned bits = 0;  // TODO: find a way to allow the caller to tell us to
1157                        // respect filtering.
1158    return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
1159}
1160
1161void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
1162                              const SkPaint& paint) const {
1163    SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType);
1164
1165    if (just_translate(*fMatrix, bitmap)) {
1166        int ix = SkScalarRoundToInt(fMatrix->getTranslateX());
1167        int iy = SkScalarRoundToInt(fMatrix->getTranslateY());
1168
1169        SkAutoLockPixels alp(bitmap);
1170        if (!bitmap.readyToDraw()) {
1171            return;
1172        }
1173
1174        SkMask  mask;
1175        mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1176        mask.fFormat = SkMask::kA8_Format;
1177        mask.fRowBytes = SkToU32(bitmap.rowBytes());
1178        mask.fImage = bitmap.getAddr8(0, 0);
1179
1180        this->drawDevMask(mask, paint);
1181    } else {    // need to xform the bitmap first
1182        SkRect  r;
1183        SkMask  mask;
1184
1185        r.set(0, 0,
1186              SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
1187        fMatrix->mapRect(&r);
1188        r.round(&mask.fBounds);
1189
1190        // set the mask's bounds to the transformed bitmap-bounds,
1191        // clipped to the actual device
1192        {
1193            SkIRect    devBounds;
1194            devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
1195            // need intersect(l, t, r, b) on irect
1196            if (!mask.fBounds.intersect(devBounds)) {
1197                return;
1198            }
1199        }
1200
1201        mask.fFormat = SkMask::kA8_Format;
1202        mask.fRowBytes = SkAlign4(mask.fBounds.width());
1203        size_t size = mask.computeImageSize();
1204        if (0 == size) {
1205            // the mask is too big to allocated, draw nothing
1206            return;
1207        }
1208
1209        // allocate (and clear) our temp buffer to hold the transformed bitmap
1210        SkAutoMalloc    storage(size);
1211        mask.fImage = (uint8_t*)storage.get();
1212        memset(mask.fImage, 0, size);
1213
1214        // now draw our bitmap(src) into mask(dst), transformed by the matrix
1215        {
1216            SkBitmap    device;
1217            device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
1218                             mask.fBounds.height(), mask.fRowBytes);
1219            device.setPixels(mask.fImage);
1220
1221            SkCanvas c(device);
1222            // need the unclipped top/left for the translate
1223            c.translate(-SkIntToScalar(mask.fBounds.fLeft),
1224                        -SkIntToScalar(mask.fBounds.fTop));
1225            c.concat(*fMatrix);
1226
1227            // We can't call drawBitmap, or we'll infinitely recurse. Instead
1228            // we manually build a shader and draw that into our new mask
1229            SkPaint tmpPaint;
1230            tmpPaint.setFlags(paint.getFlags());
1231            SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
1232            SkRect rr;
1233            rr.set(0, 0, SkIntToScalar(bitmap.width()),
1234                   SkIntToScalar(bitmap.height()));
1235            c.drawRect(rr, install.paintWithShader());
1236        }
1237        this->drawDevMask(mask, paint);
1238    }
1239}
1240
1241static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
1242                        const SkRect& srcR) {
1243    SkRect  dstR;
1244    SkIRect devIR;
1245
1246    m.mapRect(&dstR, srcR);
1247    dstR.roundOut(&devIR);
1248    return c.quickReject(devIR);
1249}
1250
1251static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
1252                        int width, int height) {
1253    SkRect  r;
1254    r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1255    return clipped_out(matrix, clip, r);
1256}
1257
1258static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
1259                              const SkBitmap& bitmap) {
1260    return clip.isBW() ||
1261           clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
1262}
1263
1264void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1265                        const SkPaint& origPaint) const {
1266    SkDEBUGCODE(this->validate();)
1267
1268    // nothing to draw
1269    if (fRC->isEmpty() ||
1270            bitmap.width() == 0 || bitmap.height() == 0 ||
1271            bitmap.colorType() == kUnknown_SkColorType) {
1272        return;
1273    }
1274
1275    SkPaint paint(origPaint);
1276    paint.setStyle(SkPaint::kFill_Style);
1277
1278    SkMatrix matrix;
1279    matrix.setConcat(*fMatrix, prematrix);
1280
1281    if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
1282        return;
1283    }
1284
1285    if (fBounder && just_translate(matrix, bitmap)) {
1286        SkIRect ir;
1287        int32_t ix = SkScalarRoundToInt(matrix.getTranslateX());
1288        int32_t iy = SkScalarRoundToInt(matrix.getTranslateY());
1289        ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1290        if (!fBounder->doIRect(ir)) {
1291            return;
1292        }
1293    }
1294
1295    if (bitmap.colorType() != kAlpha_8_SkColorType &&
1296            just_translate(matrix, bitmap)) {
1297        //
1298        // It is safe to call lock pixels now, since we know the matrix is
1299        // (more or less) identity.
1300        //
1301        SkAutoLockPixels alp(bitmap);
1302        if (!bitmap.readyToDraw()) {
1303            return;
1304        }
1305        int ix = SkScalarRoundToInt(matrix.getTranslateX());
1306        int iy = SkScalarRoundToInt(matrix.getTranslateY());
1307        if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
1308            SkTBlitterAllocator allocator;
1309            // blitter will be owned by the allocator.
1310            SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1311                                                         ix, iy, &allocator);
1312            if (blitter) {
1313                SkIRect    ir;
1314                ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1315
1316                SkScan::FillIRect(ir, *fRC, blitter);
1317                return;
1318            }
1319        }
1320    }
1321
1322    // now make a temp draw on the stack, and use it
1323    //
1324    SkDraw draw(*this);
1325    draw.fMatrix = &matrix;
1326
1327    if (bitmap.colorType() == kAlpha_8_SkColorType) {
1328        draw.drawBitmapAsMask(bitmap, paint);
1329    } else {
1330        SkAutoBitmapShaderInstall install(bitmap, paint);
1331
1332        SkRect  r;
1333        r.set(0, 0, SkIntToScalar(bitmap.width()),
1334              SkIntToScalar(bitmap.height()));
1335        // is this ok if paint has a rasterizer?
1336        draw.drawRect(r, install.paintWithShader());
1337    }
1338}
1339
1340void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1341                        const SkPaint& origPaint) const {
1342    SkDEBUGCODE(this->validate();)
1343
1344    // nothing to draw
1345    if (fRC->isEmpty() ||
1346            bitmap.width() == 0 || bitmap.height() == 0 ||
1347            bitmap.colorType() == kUnknown_SkColorType) {
1348        return;
1349    }
1350
1351    SkIRect    bounds;
1352    bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1353
1354    if (fRC->quickReject(bounds)) {
1355        return; // nothing to draw
1356    }
1357
1358    SkPaint paint(origPaint);
1359    paint.setStyle(SkPaint::kFill_Style);
1360
1361    if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
1362        SkTBlitterAllocator allocator;
1363        // blitter will be owned by the allocator.
1364        SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1365                                                     x, y, &allocator);
1366
1367        if (blitter) {
1368            if (fBounder && !fBounder->doIRect(bounds)) {
1369                return;
1370            }
1371
1372            SkScan::FillIRect(bounds, *fRC, blitter);
1373            return;
1374        }
1375    }
1376
1377    SkAutoBitmapShaderInstall install(bitmap, paint);
1378    const SkPaint& shaderPaint = install.paintWithShader();
1379
1380    SkMatrix        matrix;
1381    SkRect          r;
1382
1383    // get a scalar version of our rect
1384    r.set(bounds);
1385
1386    // tell the shader our offset
1387    matrix.setTranslate(r.fLeft, r.fTop);
1388    shaderPaint.getShader()->setLocalMatrix(matrix);
1389
1390    SkDraw draw(*this);
1391    matrix.reset();
1392    draw.fMatrix = &matrix;
1393    // call ourself with a rect
1394    // is this OK if paint has a rasterizer?
1395    draw.drawRect(r, shaderPaint);
1396}
1397
1398///////////////////////////////////////////////////////////////////////////////
1399
1400#include "SkScalerContext.h"
1401#include "SkGlyphCache.h"
1402#include "SkTextToPathIter.h"
1403#include "SkUtils.h"
1404
1405static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1406                const char text[], size_t byteLength, SkVector* stopVector) {
1407    SkFixed     x = 0, y = 0;
1408    const char* stop = text + byteLength;
1409
1410    SkAutoKern  autokern;
1411
1412    while (text < stop) {
1413        // don't need x, y here, since all subpixel variants will have the
1414        // same advance
1415        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1416
1417        x += autokern.adjust(glyph) + glyph.fAdvanceX;
1418        y += glyph.fAdvanceY;
1419    }
1420    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1421
1422    SkASSERT(text == stop);
1423}
1424
1425bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
1426    // hairline glyphs are fast enough so we don't need to cache them
1427    if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
1428        return true;
1429    }
1430
1431    // we don't cache perspective
1432    if (ctm.hasPerspective()) {
1433        return true;
1434    }
1435
1436    SkMatrix textM;
1437    return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
1438}
1439
1440void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1441                              SkScalar x, SkScalar y,
1442                              const SkPaint& paint) const {
1443    SkDEBUGCODE(this->validate();)
1444
1445    SkTextToPathIter iter(text, byteLength, paint, true);
1446
1447    SkMatrix    matrix;
1448    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1449    matrix.postTranslate(x, y);
1450
1451    const SkPath* iterPath;
1452    SkScalar xpos, prevXPos = 0;
1453
1454    while (iter.next(&iterPath, &xpos)) {
1455        matrix.postTranslate(xpos - prevXPos, 0);
1456        if (iterPath) {
1457            const SkPaint& pnt = iter.getPaint();
1458            if (fDevice) {
1459                fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
1460            } else {
1461                this->drawPath(*iterPath, pnt, &matrix, false);
1462            }
1463        }
1464        prevXPos = xpos;
1465    }
1466}
1467
1468// disable warning : local variable used without having been initialized
1469#if defined _WIN32 && _MSC_VER >= 1300
1470#pragma warning ( push )
1471#pragma warning ( disable : 4701 )
1472#endif
1473
1474//////////////////////////////////////////////////////////////////////////////
1475
1476static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
1477                                   SkFixed fx, SkFixed fy,
1478                                   const SkGlyph& glyph) {
1479    int left = SkFixedFloorToInt(fx);
1480    int top = SkFixedFloorToInt(fy);
1481    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1482    SkASSERT(NULL == state.fBounder);
1483    SkASSERT((NULL == state.fClip && state.fAAClip) ||
1484             (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
1485
1486    left += glyph.fLeft;
1487    top  += glyph.fTop;
1488
1489    int right   = left + glyph.fWidth;
1490    int bottom  = top + glyph.fHeight;
1491
1492    SkMask        mask;
1493    SkIRect        storage;
1494    SkIRect*    bounds = &mask.fBounds;
1495
1496    mask.fBounds.set(left, top, right, bottom);
1497
1498    // this extra test is worth it, assuming that most of the time it succeeds
1499    // since we can avoid writing to storage
1500    if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1501        if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1502            return;
1503        bounds = &storage;
1504    }
1505
1506    uint8_t* aa = (uint8_t*)glyph.fImage;
1507    if (NULL == aa) {
1508        aa = (uint8_t*)state.fCache->findImage(glyph);
1509        if (NULL == aa) {
1510            return; // can't rasterize glyph
1511        }
1512    }
1513
1514    mask.fRowBytes = glyph.rowBytes();
1515    mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1516    mask.fImage = aa;
1517    state.blitMask(mask, *bounds);
1518}
1519
1520static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
1521                                  SkFixed fx, SkFixed fy,
1522                                  const SkGlyph& glyph) {
1523    int left = SkFixedFloorToInt(fx);
1524    int top = SkFixedFloorToInt(fy);
1525    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1526    SkASSERT(!state.fClip->isRect());
1527    SkASSERT(NULL == state.fBounder);
1528
1529    SkMask  mask;
1530
1531    left += glyph.fLeft;
1532    top  += glyph.fTop;
1533
1534    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1535    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1536
1537    if (!clipper.done()) {
1538        const SkIRect&  cr = clipper.rect();
1539        const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1540        if (NULL == aa) {
1541            aa = (uint8_t*)state.fCache->findImage(glyph);
1542            if (NULL == aa) {
1543                return;
1544            }
1545        }
1546
1547        mask.fRowBytes = glyph.rowBytes();
1548        mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1549        mask.fImage = (uint8_t*)aa;
1550        do {
1551            state.blitMask(mask, cr);
1552            clipper.next();
1553        } while (!clipper.done());
1554    }
1555}
1556
1557static void D1G_Bounder(const SkDraw1Glyph& state,
1558                        SkFixed fx, SkFixed fy,
1559                        const SkGlyph& glyph) {
1560    int left = SkFixedFloorToInt(fx);
1561    int top = SkFixedFloorToInt(fy);
1562    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1563
1564    SkMask  mask;
1565
1566    left += glyph.fLeft;
1567    top  += glyph.fTop;
1568
1569    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1570    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1571
1572    if (!clipper.done()) {
1573        const SkIRect&  cr = clipper.rect();
1574        const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1575        if (NULL == aa) {
1576            aa = (uint8_t*)state.fCache->findImage(glyph);
1577            if (NULL == aa) {
1578                return;
1579            }
1580        }
1581
1582        // we need to pass the origin, which we approximate with our
1583        // (unadjusted) left,top coordinates (the caller called fixedfloor)
1584        if (state.fBounder->doIRectGlyph(cr,
1585                                         left - glyph.fLeft,
1586                                         top - glyph.fTop, glyph)) {
1587            mask.fRowBytes = glyph.rowBytes();
1588            mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1589            mask.fImage = (uint8_t*)aa;
1590            do {
1591                state.blitMask(mask, cr);
1592                clipper.next();
1593            } while (!clipper.done());
1594        }
1595    }
1596}
1597
1598static void D1G_Bounder_AAClip(const SkDraw1Glyph& state,
1599                               SkFixed fx, SkFixed fy,
1600                               const SkGlyph& glyph) {
1601    int left = SkFixedFloorToInt(fx);
1602    int top = SkFixedFloorToInt(fy);
1603    SkIRect bounds;
1604    bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1605
1606    if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) {
1607        D1G_NoBounder_RectClip(state, fx, fy, glyph);
1608    }
1609}
1610
1611static bool hasCustomD1GProc(const SkDraw& draw) {
1612    return draw.fProcs && draw.fProcs->fD1GProc;
1613}
1614
1615static bool needsRasterTextBlit(const SkDraw& draw) {
1616    return !hasCustomD1GProc(draw);
1617}
1618
1619SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
1620                                      SkGlyphCache* cache, const SkPaint& pnt) {
1621    fDraw = draw;
1622    fBounder = draw->fBounder;
1623    fBlitter = blitter;
1624    fCache = cache;
1625    fPaint = &pnt;
1626
1627    if (cache->isSubpixel()) {
1628        fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
1629    } else {
1630        fHalfSampleX = fHalfSampleY = SK_FixedHalf;
1631    }
1632
1633    if (hasCustomD1GProc(*draw)) {
1634        // todo: fix this assumption about clips w/ custom
1635        fClip = draw->fClip;
1636        fClipBounds = fClip->getBounds();
1637        return draw->fProcs->fD1GProc;
1638    }
1639
1640    if (draw->fRC->isBW()) {
1641        fAAClip = NULL;
1642        fClip = &draw->fRC->bwRgn();
1643        fClipBounds = fClip->getBounds();
1644        if (NULL == fBounder) {
1645            if (fClip->isRect()) {
1646                return D1G_NoBounder_RectClip;
1647            } else {
1648                return D1G_NoBounder_RgnClip;
1649            }
1650        } else {
1651            return D1G_Bounder;
1652        }
1653    } else {    // aaclip
1654        fAAClip = &draw->fRC->aaRgn();
1655        fClip = NULL;
1656        fClipBounds = fAAClip->getBounds();
1657        if (NULL == fBounder) {
1658            return D1G_NoBounder_RectClip;
1659        } else {
1660            return D1G_Bounder_AAClip;
1661        }
1662    }
1663}
1664
1665void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1666    SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1667
1668    SkBitmap bm;
1669    bm.setConfig(SkBitmap::kARGB_8888_Config,
1670                 mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
1671    bm.setPixels((SkPMColor*)mask.fImage);
1672
1673    fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1674}
1675
1676///////////////////////////////////////////////////////////////////////////////
1677
1678void SkDraw::drawText(const char text[], size_t byteLength,
1679                      SkScalar x, SkScalar y, const SkPaint& paint) const {
1680    SkASSERT(byteLength == 0 || text != NULL);
1681
1682    SkDEBUGCODE(this->validate();)
1683
1684    // nothing to draw
1685    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1686        return;
1687    }
1688
1689    // SkScalarRec doesn't currently have a way of representing hairline stroke and
1690    // will fill if its frame-width is 0.
1691    if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1692        this->drawText_asPaths(text, byteLength, x, y, paint);
1693        return;
1694    }
1695
1696    SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1697
1698    SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
1699    SkGlyphCache*       cache = autoCache.getCache();
1700
1701    // transform our starting point
1702    {
1703        SkPoint loc;
1704        fMatrix->mapXY(x, y, &loc);
1705        x = loc.fX;
1706        y = loc.fY;
1707    }
1708
1709    // need to measure first
1710    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1711        SkVector    stop;
1712
1713        measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1714
1715        SkScalar    stopX = stop.fX;
1716        SkScalar    stopY = stop.fY;
1717
1718        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1719            stopX = SkScalarHalf(stopX);
1720            stopY = SkScalarHalf(stopY);
1721        }
1722        x -= stopX;
1723        y -= stopY;
1724    }
1725
1726    const char* stop = text + byteLength;
1727
1728    SkAAClipBlitter     aaBlitter;
1729    SkAutoBlitterChoose blitterChooser;
1730    SkBlitter*          blitter = NULL;
1731    if (needsRasterTextBlit(*this)) {
1732        blitterChooser.choose(*fBitmap, *fMatrix, paint);
1733        blitter = blitterChooser.get();
1734        if (fRC->isAA()) {
1735            aaBlitter.init(blitter, &fRC->aaRgn());
1736            blitter = &aaBlitter;
1737        }
1738    }
1739
1740    SkAutoKern          autokern;
1741    SkDraw1Glyph        d1g;
1742    SkDraw1Glyph::Proc  proc = d1g.init(this, blitter, cache, paint);
1743
1744    SkFixed fxMask = ~0;
1745    SkFixed fyMask = ~0;
1746    if (cache->isSubpixel()) {
1747        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1748        if (kX_SkAxisAlignment == baseline) {
1749            fyMask = 0;
1750            d1g.fHalfSampleY = SK_FixedHalf;
1751        } else if (kY_SkAxisAlignment == baseline) {
1752            fxMask = 0;
1753            d1g.fHalfSampleX = SK_FixedHalf;
1754        }
1755    }
1756
1757    SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX;
1758    SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY;
1759
1760    while (text < stop) {
1761        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1762
1763        fx += autokern.adjust(glyph);
1764
1765        if (glyph.fWidth) {
1766            proc(d1g, fx, fy, glyph);
1767        }
1768
1769        fx += glyph.fAdvanceX;
1770        fy += glyph.fAdvanceY;
1771    }
1772}
1773
1774// last parameter is interpreted as SkFixed [x, y]
1775// return the fixed position, which may be rounded or not by the caller
1776//   e.g. subpixel doesn't round
1777typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1778
1779static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1780    dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1781}
1782
1783static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1784    dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1785             SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1786}
1787
1788static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
1789    dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1790             SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1791}
1792
1793static AlignProc pick_align_proc(SkPaint::Align align) {
1794    static const AlignProc gProcs[] = {
1795        leftAlignProc, centerAlignProc, rightAlignProc
1796    };
1797
1798    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1799
1800    return gProcs[align];
1801}
1802
1803typedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*);
1804
1805static void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1806    dst->set(loc.fX, loc.fY);
1807}
1808
1809static void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1810    dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
1811             loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
1812}
1813
1814static void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
1815    dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
1816             loc.fY - SkFixedToScalar(glyph.fAdvanceY));
1817}
1818
1819static AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) {
1820    static const AlignProc_scalar gProcs[] = {
1821        leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar
1822    };
1823
1824    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1825
1826    return gProcs[align];
1827}
1828
1829class TextMapState {
1830public:
1831    mutable SkPoint fLoc;
1832
1833    TextMapState(const SkMatrix& matrix, SkScalar y)
1834        : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1835
1836    typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1837
1838    Proc pickProc(int scalarsPerPosition);
1839
1840private:
1841    const SkMatrix&     fMatrix;
1842    SkMatrix::MapXYProc fProc;
1843    SkScalar            fY; // ignored by MapXYProc
1844    // these are only used by Only... procs
1845    SkScalar            fScaleX, fTransX, fTransformedY;
1846
1847    static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1848        state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1849    }
1850
1851    static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1852        state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1853    }
1854
1855    static void MapOnlyScaleXProc(const TextMapState& state,
1856                                  const SkScalar pos[]) {
1857        state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1858                       state.fTransformedY);
1859    }
1860
1861    static void MapOnlyTransXProc(const TextMapState& state,
1862                                  const SkScalar pos[]) {
1863        state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1864    }
1865};
1866
1867TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1868    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1869
1870    if (1 == scalarsPerPosition) {
1871        unsigned mtype = fMatrix.getType();
1872        if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1873            return MapXProc;
1874        } else {
1875            fScaleX = fMatrix.getScaleX();
1876            fTransX = fMatrix.getTranslateX();
1877            fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1878                            fMatrix.getTranslateY();
1879            return (mtype & SkMatrix::kScale_Mask) ?
1880                        MapOnlyScaleXProc : MapOnlyTransXProc;
1881        }
1882    } else {
1883        return MapXYProc;
1884    }
1885}
1886
1887//////////////////////////////////////////////////////////////////////////////
1888
1889void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1890                                 const SkScalar pos[], SkScalar constY,
1891                                 int scalarsPerPosition,
1892                                 const SkPaint& origPaint) const {
1893    // setup our std paint, in hopes of getting hits in the cache
1894    SkPaint paint(origPaint);
1895    SkScalar matrixScale = paint.setupForAsPaths();
1896
1897    SkMatrix matrix;
1898    matrix.setScale(matrixScale, matrixScale);
1899
1900    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1901    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
1902    SkGlyphCache*       cache = autoCache.getCache();
1903
1904    const char*        stop = text + byteLength;
1905    AlignProc_scalar   alignProc = pick_align_proc_scalar(paint.getTextAlign());
1906    TextMapState       tms(SkMatrix::I(), constY);
1907    TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1908
1909    while (text < stop) {
1910        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1911        if (glyph.fWidth) {
1912            const SkPath* path = cache->findPath(glyph);
1913            if (path) {
1914                tmsProc(tms, pos);
1915                SkPoint loc;
1916                alignProc(tms.fLoc, glyph, &loc);
1917
1918                matrix[SkMatrix::kMTransX] = loc.fX;
1919                matrix[SkMatrix::kMTransY] = loc.fY;
1920                if (fDevice) {
1921                    fDevice->drawPath(*this, *path, paint, &matrix, false);
1922                } else {
1923                    this->drawPath(*path, paint, &matrix, false);
1924                }
1925            }
1926        }
1927        pos += scalarsPerPosition;
1928    }
1929}
1930
1931void SkDraw::drawPosText(const char text[], size_t byteLength,
1932                         const SkScalar pos[], SkScalar constY,
1933                         int scalarsPerPosition, const SkPaint& paint) const {
1934    SkASSERT(byteLength == 0 || text != NULL);
1935    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1936
1937    SkDEBUGCODE(this->validate();)
1938
1939    // nothing to draw
1940    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1941        return;
1942    }
1943
1944    if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1945        this->drawPosText_asPaths(text, byteLength, pos, constY,
1946                                  scalarsPerPosition, paint);
1947        return;
1948    }
1949
1950    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1951    SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
1952    SkGlyphCache*       cache = autoCache.getCache();
1953
1954    SkAAClipBlitterWrapper wrapper;
1955    SkAutoBlitterChoose blitterChooser;
1956    SkBlitter* blitter = NULL;
1957    if (needsRasterTextBlit(*this)) {
1958        blitterChooser.choose(*fBitmap, *fMatrix, paint);
1959        blitter = blitterChooser.get();
1960        if (fRC->isAA()) {
1961            wrapper.init(*fRC, blitter);
1962            blitter = wrapper.getBlitter();
1963        }
1964    }
1965
1966    const char*        stop = text + byteLength;
1967    AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
1968    SkDraw1Glyph       d1g;
1969    SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
1970    TextMapState       tms(*fMatrix, constY);
1971    TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1972
1973    if (cache->isSubpixel()) {
1974        // maybe we should skip the rounding if linearText is set
1975        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1976
1977        SkFixed fxMask = ~0;
1978        SkFixed fyMask = ~0;
1979        if (kX_SkAxisAlignment == baseline) {
1980            fyMask = 0;
1981#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
1982            d1g.fHalfSampleY = SK_FixedHalf;
1983#endif
1984        } else if (kY_SkAxisAlignment == baseline) {
1985            fxMask = 0;
1986#ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
1987            d1g.fHalfSampleX = SK_FixedHalf;
1988#endif
1989        }
1990
1991        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1992            while (text < stop) {
1993                tmsProc(tms, pos);
1994                SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX;
1995                SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY;
1996
1997                const SkGlyph& glyph = glyphCacheProc(cache, &text,
1998                                                      fx & fxMask, fy & fyMask);
1999
2000                if (glyph.fWidth) {
2001                    proc(d1g, fx, fy, glyph);
2002                }
2003                pos += scalarsPerPosition;
2004            }
2005        } else {
2006            while (text < stop) {
2007                const char* currentText = text;
2008                const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
2009
2010                if (metricGlyph.fWidth) {
2011                    SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
2012                    SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
2013
2014                    tmsProc(tms, pos);
2015                    SkIPoint fixedLoc;
2016                    alignProc(tms.fLoc, metricGlyph, &fixedLoc);
2017
2018                    SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
2019                    SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
2020
2021                    // have to call again, now that we've been "aligned"
2022                    const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
2023                                                          fx & fxMask, fy & fyMask);
2024                    // the assumption is that the metrics haven't changed
2025                    SkASSERT(prevAdvX == glyph.fAdvanceX);
2026                    SkASSERT(prevAdvY == glyph.fAdvanceY);
2027                    SkASSERT(glyph.fWidth);
2028
2029                    proc(d1g, fx, fy, glyph);
2030                }
2031                pos += scalarsPerPosition;
2032            }
2033        }
2034    } else {    // not subpixel
2035        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
2036            while (text < stop) {
2037                // the last 2 parameters are ignored
2038                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2039
2040                if (glyph.fWidth) {
2041                    tmsProc(tms, pos);
2042
2043                    proc(d1g,
2044                         SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
2045                         SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
2046                         glyph);
2047                }
2048                pos += scalarsPerPosition;
2049            }
2050        } else {
2051            while (text < stop) {
2052                // the last 2 parameters are ignored
2053                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
2054
2055                if (glyph.fWidth) {
2056                    tmsProc(tms, pos);
2057
2058                    SkIPoint fixedLoc;
2059                    alignProc(tms.fLoc, glyph, &fixedLoc);
2060
2061                    proc(d1g,
2062                         fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
2063                         fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY,
2064                         glyph);
2065                }
2066                pos += scalarsPerPosition;
2067            }
2068        }
2069    }
2070}
2071
2072#if defined _WIN32 && _MSC_VER >= 1300
2073#pragma warning ( pop )
2074#endif
2075
2076///////////////////////////////////////////////////////////////////////////////
2077
2078#include "SkPathMeasure.h"
2079
2080static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
2081                        SkPathMeasure& meas, const SkMatrix& matrix) {
2082    SkMatrix::MapXYProc proc = matrix.getMapXYProc();
2083
2084    for (int i = 0; i < count; i++) {
2085        SkPoint pos;
2086        SkVector tangent;
2087
2088        proc(matrix, src[i].fX, src[i].fY, &pos);
2089        SkScalar sx = pos.fX;
2090        SkScalar sy = pos.fY;
2091
2092        if (!meas.getPosTan(sx, &pos, &tangent)) {
2093            // set to 0 if the measure failed, so that we just set dst == pos
2094            tangent.set(0, 0);
2095        }
2096
2097        /*  This is the old way (that explains our approach but is way too slow
2098            SkMatrix    matrix;
2099            SkPoint     pt;
2100
2101            pt.set(sx, sy);
2102            matrix.setSinCos(tangent.fY, tangent.fX);
2103            matrix.preTranslate(-sx, 0);
2104            matrix.postTranslate(pos.fX, pos.fY);
2105            matrix.mapPoints(&dst[i], &pt, 1);
2106        */
2107        dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
2108                   pos.fY + SkScalarMul(tangent.fX, sy));
2109    }
2110}
2111
2112/*  TODO
2113
2114    Need differentially more subdivisions when the follow-path is curvy. Not sure how to
2115    determine that, but we need it. I guess a cheap answer is let the caller tell us,
2116    but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
2117*/
2118static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
2119                      const SkMatrix& matrix) {
2120    SkPath::Iter    iter(src, false);
2121    SkPoint         srcP[4], dstP[3];
2122    SkPath::Verb    verb;
2123
2124    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
2125        switch (verb) {
2126            case SkPath::kMove_Verb:
2127                morphpoints(dstP, srcP, 1, meas, matrix);
2128                dst->moveTo(dstP[0]);
2129                break;
2130            case SkPath::kLine_Verb:
2131                // turn lines into quads to look bendy
2132                srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
2133                srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
2134                morphpoints(dstP, srcP, 2, meas, matrix);
2135                dst->quadTo(dstP[0], dstP[1]);
2136                break;
2137            case SkPath::kQuad_Verb:
2138                morphpoints(dstP, &srcP[1], 2, meas, matrix);
2139                dst->quadTo(dstP[0], dstP[1]);
2140                break;
2141            case SkPath::kCubic_Verb:
2142                morphpoints(dstP, &srcP[1], 3, meas, matrix);
2143                dst->cubicTo(dstP[0], dstP[1], dstP[2]);
2144                break;
2145            case SkPath::kClose_Verb:
2146                dst->close();
2147                break;
2148            default:
2149                SkDEBUGFAIL("unknown verb");
2150                break;
2151        }
2152    }
2153}
2154
2155void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
2156                            const SkPath& follow, const SkMatrix* matrix,
2157                            const SkPaint& paint) const {
2158    SkASSERT(byteLength == 0 || text != NULL);
2159
2160    // nothing to draw
2161    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
2162        return;
2163    }
2164
2165    SkTextToPathIter    iter(text, byteLength, paint, true);
2166    SkPathMeasure       meas(follow, false);
2167    SkScalar            hOffset = 0;
2168
2169    // need to measure first
2170    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
2171        SkScalar pathLen = meas.getLength();
2172        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
2173            pathLen = SkScalarHalf(pathLen);
2174        }
2175        hOffset += pathLen;
2176    }
2177
2178    const SkPath*   iterPath;
2179    SkScalar        xpos;
2180    SkMatrix        scaledMatrix;
2181    SkScalar        scale = iter.getPathScale();
2182
2183    scaledMatrix.setScale(scale, scale);
2184
2185    while (iter.next(&iterPath, &xpos)) {
2186        if (iterPath) {
2187            SkPath      tmp;
2188            SkMatrix    m(scaledMatrix);
2189
2190            m.postTranslate(xpos + hOffset, 0);
2191            if (matrix) {
2192                m.postConcat(*matrix);
2193            }
2194            morphpath(&tmp, *iterPath, meas, m);
2195            if (fDevice) {
2196                fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
2197            } else {
2198                this->drawPath(tmp, iter.getPaint(), NULL, true);
2199            }
2200        }
2201    }
2202}
2203
2204///////////////////////////////////////////////////////////////////////////////
2205
2206struct VertState {
2207    int f0, f1, f2;
2208
2209    VertState(int vCount, const uint16_t indices[], int indexCount)
2210            : fIndices(indices) {
2211        fCurrIndex = 0;
2212        if (indices) {
2213            fCount = indexCount;
2214        } else {
2215            fCount = vCount;
2216        }
2217    }
2218
2219    typedef bool (*Proc)(VertState*);
2220    Proc chooseProc(SkCanvas::VertexMode mode);
2221
2222private:
2223    int             fCount;
2224    int             fCurrIndex;
2225    const uint16_t* fIndices;
2226
2227    static bool Triangles(VertState*);
2228    static bool TrianglesX(VertState*);
2229    static bool TriangleStrip(VertState*);
2230    static bool TriangleStripX(VertState*);
2231    static bool TriangleFan(VertState*);
2232    static bool TriangleFanX(VertState*);
2233};
2234
2235bool VertState::Triangles(VertState* state) {
2236    int index = state->fCurrIndex;
2237    if (index + 3 > state->fCount) {
2238        return false;
2239    }
2240    state->f0 = index + 0;
2241    state->f1 = index + 1;
2242    state->f2 = index + 2;
2243    state->fCurrIndex = index + 3;
2244    return true;
2245}
2246
2247bool VertState::TrianglesX(VertState* state) {
2248    const uint16_t* indices = state->fIndices;
2249    int index = state->fCurrIndex;
2250    if (index + 3 > state->fCount) {
2251        return false;
2252    }
2253    state->f0 = indices[index + 0];
2254    state->f1 = indices[index + 1];
2255    state->f2 = indices[index + 2];
2256    state->fCurrIndex = index + 3;
2257    return true;
2258}
2259
2260bool VertState::TriangleStrip(VertState* state) {
2261    int index = state->fCurrIndex;
2262    if (index + 3 > state->fCount) {
2263        return false;
2264    }
2265    state->f2 = index + 2;
2266    if (index & 1) {
2267        state->f0 = index + 1;
2268        state->f1 = index + 0;
2269    } else {
2270        state->f0 = index + 0;
2271        state->f1 = index + 1;
2272    }
2273    state->fCurrIndex = index + 1;
2274    return true;
2275}
2276
2277bool VertState::TriangleStripX(VertState* state) {
2278    const uint16_t* indices = state->fIndices;
2279    int index = state->fCurrIndex;
2280    if (index + 3 > state->fCount) {
2281        return false;
2282    }
2283    state->f2 = indices[index + 2];
2284    if (index & 1) {
2285        state->f0 = indices[index + 1];
2286        state->f1 = indices[index + 0];
2287    } else {
2288        state->f0 = indices[index + 0];
2289        state->f1 = indices[index + 1];
2290    }
2291    state->fCurrIndex = index + 1;
2292    return true;
2293}
2294
2295bool VertState::TriangleFan(VertState* state) {
2296    int index = state->fCurrIndex;
2297    if (index + 3 > state->fCount) {
2298        return false;
2299    }
2300    state->f0 = 0;
2301    state->f1 = index + 1;
2302    state->f2 = index + 2;
2303    state->fCurrIndex = index + 1;
2304    return true;
2305}
2306
2307bool VertState::TriangleFanX(VertState* state) {
2308    const uint16_t* indices = state->fIndices;
2309    int index = state->fCurrIndex;
2310    if (index + 3 > state->fCount) {
2311        return false;
2312    }
2313    state->f0 = indices[0];
2314    state->f1 = indices[index + 1];
2315    state->f2 = indices[index + 2];
2316    state->fCurrIndex = index + 1;
2317    return true;
2318}
2319
2320VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
2321    switch (mode) {
2322        case SkCanvas::kTriangles_VertexMode:
2323            return fIndices ? TrianglesX : Triangles;
2324        case SkCanvas::kTriangleStrip_VertexMode:
2325            return fIndices ? TriangleStripX : TriangleStrip;
2326        case SkCanvas::kTriangleFan_VertexMode:
2327            return fIndices ? TriangleFanX : TriangleFan;
2328        default:
2329            return NULL;
2330    }
2331}
2332
2333typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
2334                         SkBlitter*);
2335
2336static HairProc ChooseHairProc(bool doAntiAlias) {
2337    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
2338}
2339
2340static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
2341                              const SkPoint texs[], SkMatrix* matrix) {
2342    SkPoint src[3], dst[3];
2343
2344    src[0] = texs[state.f0];
2345    src[1] = texs[state.f1];
2346    src[2] = texs[state.f2];
2347    dst[0] = verts[state.f0];
2348    dst[1] = verts[state.f1];
2349    dst[2] = verts[state.f2];
2350    return matrix->setPolyToPoly(src, dst, 3);
2351}
2352
2353class SkTriColorShader : public SkShader {
2354public:
2355    SkTriColorShader() {}
2356
2357    bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2358
2359    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
2360
2361    SK_TO_STRING_OVERRIDE()
2362    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
2363
2364protected:
2365    SkTriColorShader(SkReadBuffer& buffer) : SkShader(buffer) {}
2366
2367private:
2368    SkMatrix    fDstToUnit;
2369    SkPMColor   fColors[3];
2370
2371    typedef SkShader INHERITED;
2372};
2373
2374bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
2375                             int index0, int index1, int index2) {
2376
2377    fColors[0] = SkPreMultiplyColor(colors[index0]);
2378    fColors[1] = SkPreMultiplyColor(colors[index1]);
2379    fColors[2] = SkPreMultiplyColor(colors[index2]);
2380
2381    SkMatrix m, im;
2382    m.reset();
2383    m.set(0, pts[index1].fX - pts[index0].fX);
2384    m.set(1, pts[index2].fX - pts[index0].fX);
2385    m.set(2, pts[index0].fX);
2386    m.set(3, pts[index1].fY - pts[index0].fY);
2387    m.set(4, pts[index2].fY - pts[index0].fY);
2388    m.set(5, pts[index0].fY);
2389    if (!m.invert(&im)) {
2390        return false;
2391    }
2392    fDstToUnit.setConcat(im, this->getTotalInverse());
2393    return true;
2394}
2395
2396#include "SkColorPriv.h"
2397#include "SkComposeShader.h"
2398
2399static int ScalarTo256(SkScalar v) {
2400    int scale = SkScalarToFixed(v) >> 8;
2401    if (scale < 0) {
2402        scale = 0;
2403    }
2404    if (scale > 255) {
2405        scale = 255;
2406    }
2407    return SkAlpha255To256(scale);
2408}
2409
2410void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2411    SkPoint src;
2412
2413    for (int i = 0; i < count; i++) {
2414        fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2415        x += 1;
2416
2417        int scale1 = ScalarTo256(src.fX);
2418        int scale2 = ScalarTo256(src.fY);
2419        int scale0 = 256 - scale1 - scale2;
2420        if (scale0 < 0) {
2421            if (scale1 > scale2) {
2422                scale2 = 256 - scale1;
2423            } else {
2424                scale1 = 256 - scale2;
2425            }
2426            scale0 = 0;
2427        }
2428
2429        dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2430        SkAlphaMulQ(fColors[1], scale1) +
2431        SkAlphaMulQ(fColors[2], scale2);
2432    }
2433}
2434
2435#ifndef SK_IGNORE_TO_STRING
2436void SkTriColorShader::toString(SkString* str) const {
2437    str->append("SkTriColorShader: (");
2438
2439    this->INHERITED::toString(str);
2440
2441    str->append(")");
2442}
2443#endif
2444
2445void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2446                          const SkPoint vertices[], const SkPoint textures[],
2447                          const SkColor colors[], SkXfermode* xmode,
2448                          const uint16_t indices[], int indexCount,
2449                          const SkPaint& paint) const {
2450    SkASSERT(0 == count || NULL != vertices);
2451
2452    // abort early if there is nothing to draw
2453    if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
2454        return;
2455    }
2456
2457    // transform out vertices into device coordinates
2458    SkAutoSTMalloc<16, SkPoint> storage(count);
2459    SkPoint* devVerts = storage.get();
2460    fMatrix->mapPoints(devVerts, vertices, count);
2461
2462    if (fBounder) {
2463        SkRect bounds;
2464        bounds.set(devVerts, count);
2465        if (!fBounder->doRect(bounds, paint)) {
2466            return;
2467        }
2468    }
2469
2470    /*
2471        We can draw the vertices in 1 of 4 ways:
2472
2473        - solid color (no shader/texture[], no colors[])
2474        - just colors (no shader/texture[], has colors[])
2475        - just texture (has shader/texture[], no colors[])
2476        - colors * texture (has shader/texture[], has colors[])
2477
2478        Thus for texture drawing, we need both texture[] and a shader.
2479    */
2480
2481    SkTriColorShader triShader; // must be above declaration of p
2482    SkPaint p(paint);
2483
2484    SkShader* shader = p.getShader();
2485    if (NULL == shader) {
2486        // if we have no shader, we ignore the texture coordinates
2487        textures = NULL;
2488    } else if (NULL == textures) {
2489        // if we don't have texture coordinates, ignore the shader
2490        p.setShader(NULL);
2491        shader = NULL;
2492    }
2493
2494    // setup the custom shader (if needed)
2495    if (NULL != colors) {
2496        if (NULL == textures) {
2497            // just colors (no texture)
2498            shader = p.setShader(&triShader);
2499        } else {
2500            // colors * texture
2501            SkASSERT(shader);
2502            bool releaseMode = false;
2503            if (NULL == xmode) {
2504                xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
2505                releaseMode = true;
2506            }
2507            SkShader* compose = SkNEW_ARGS(SkComposeShader,
2508                                           (&triShader, shader, xmode));
2509            p.setShader(compose)->unref();
2510            if (releaseMode) {
2511                xmode->unref();
2512            }
2513        }
2514    }
2515
2516    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2517    // important that we abort early, as below we may manipulate the shader
2518    // and that is only valid if the shader returned true from setContext.
2519    // If it returned false, then our blitter will be the NullBlitter.
2520    if (blitter->isNullBlitter()) {
2521        return;
2522    }
2523
2524    // setup our state and function pointer for iterating triangles
2525    VertState       state(count, indices, indexCount);
2526    VertState::Proc vertProc = state.chooseProc(vmode);
2527
2528    if (NULL != textures || NULL != colors) {
2529        SkMatrix  tempM;
2530        SkMatrix  savedLocalM;
2531        if (shader) {
2532            savedLocalM = shader->getLocalMatrix();
2533        }
2534
2535        // setContext has already been called and verified to return true
2536        // by the constructor of SkAutoBlitterChoose
2537        bool prevContextSuccess = true;
2538        while (vertProc(&state)) {
2539            if (NULL != textures) {
2540                if (texture_to_matrix(state, vertices, textures, &tempM)) {
2541                    tempM.postConcat(savedLocalM);
2542                    shader->setLocalMatrix(tempM);
2543                    // Need to recall setContext since we changed the local matrix.
2544                    // However, we also need to balance the calls this with a
2545                    // call to endContext which requires tracking the result of
2546                    // the previous call to setContext.
2547                    if (prevContextSuccess) {
2548                        shader->endContext();
2549                    }
2550                    prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix);
2551                    if (!prevContextSuccess) {
2552                        continue;
2553                    }
2554                }
2555            }
2556            if (NULL != colors) {
2557                if (!triShader.setup(vertices, colors,
2558                                     state.f0, state.f1, state.f2)) {
2559                    continue;
2560                }
2561            }
2562
2563            SkPoint tmp[] = {
2564                devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
2565            };
2566            SkScan::FillTriangle(tmp, *fRC, blitter.get());
2567        }
2568
2569        // now restore the shader's original local matrix
2570        if (NULL != shader) {
2571            shader->setLocalMatrix(savedLocalM);
2572        }
2573
2574        // If the final call to setContext fails we must make it suceed so that the
2575        // call to endContext in the destructor for SkAutoBlitterChoose is balanced.
2576        if (!prevContextSuccess) {
2577            prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I());
2578            SkASSERT(prevContextSuccess);
2579        }
2580    } else {
2581        // no colors[] and no texture
2582        HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2583        const SkRasterClip& clip = *fRC;
2584        while (vertProc(&state)) {
2585            hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
2586            hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
2587            hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
2588        }
2589    }
2590}
2591
2592///////////////////////////////////////////////////////////////////////////////
2593///////////////////////////////////////////////////////////////////////////////
2594
2595#ifdef SK_DEBUG
2596
2597void SkDraw::validate() const {
2598    SkASSERT(fBitmap != NULL);
2599    SkASSERT(fMatrix != NULL);
2600    SkASSERT(fClip != NULL);
2601    SkASSERT(fRC != NULL);
2602
2603    const SkIRect&  cr = fRC->getBounds();
2604    SkIRect         br;
2605
2606    br.set(0, 0, fBitmap->width(), fBitmap->height());
2607    SkASSERT(cr.isEmpty() || br.contains(cr));
2608}
2609
2610#endif
2611
2612///////////////////////////////////////////////////////////////////////////////
2613
2614SkBounder::SkBounder() {
2615    // initialize up front. This gets reset by SkCanvas before each draw call.
2616    fClip = &SkRegion::GetEmptyRegion();
2617}
2618
2619bool SkBounder::doIRect(const SkIRect& r) {
2620    SkIRect    rr;
2621    return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
2622}
2623
2624// TODO: change the prototype to take fixed, and update the callers
2625bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
2626                             const SkGlyph& glyph) {
2627    SkIRect    rr;
2628    if (!rr.intersect(fClip->getBounds(), r)) {
2629        return false;
2630    }
2631    GlyphRec rec;
2632    rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
2633    rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
2634                 rec.fLSB.fY + glyph.fAdvanceY);
2635    rec.fGlyphID = glyph.getGlyphID();
2636    rec.fFlags = 0;
2637    return this->onIRectGlyph(rr, rec);
2638}
2639
2640bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
2641                           const SkPaint& paint) {
2642    SkIRect     r;
2643    SkScalar    v0, v1;
2644
2645    v0 = pt0.fX;
2646    v1 = pt1.fX;
2647    if (v0 > v1) {
2648        SkTSwap<SkScalar>(v0, v1);
2649    }
2650    r.fLeft     = SkScalarFloorToInt(v0);
2651    r.fRight    = SkScalarCeilToInt(v1);
2652
2653    v0 = pt0.fY;
2654    v1 = pt1.fY;
2655    if (v0 > v1) {
2656        SkTSwap<SkScalar>(v0, v1);
2657    }
2658    r.fTop      = SkScalarFloorToInt(v0);
2659    r.fBottom   = SkScalarCeilToInt(v1);
2660
2661    if (paint.isAntiAlias()) {
2662        r.inset(-1, -1);
2663    }
2664    return this->doIRect(r);
2665}
2666
2667bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
2668    SkIRect    r;
2669
2670    if (paint.getStyle() == SkPaint::kFill_Style) {
2671        rect.round(&r);
2672    } else {
2673        int rad = -1;
2674        rect.roundOut(&r);
2675        if (paint.isAntiAlias()) {
2676            rad = -2;
2677        }
2678        r.inset(rad, rad);
2679    }
2680    return this->doIRect(r);
2681}
2682
2683bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
2684    SkIRect       r;
2685    const SkRect& bounds = path.getBounds();
2686
2687    if (doFill) {
2688        bounds.round(&r);
2689    } else {    // hairline
2690        bounds.roundOut(&r);
2691    }
2692
2693    if (paint.isAntiAlias()) {
2694        r.inset(-1, -1);
2695    }
2696    return this->doIRect(r);
2697}
2698
2699void SkBounder::commit() {
2700    // override in subclass
2701}
2702
2703////////////////////////////////////////////////////////////////////////////////////////////////
2704
2705#include "SkPath.h"
2706#include "SkDraw.h"
2707#include "SkRegion.h"
2708#include "SkBlitter.h"
2709
2710static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2711                       const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2712                           SkIRect* bounds) {
2713    if (devPath.isEmpty()) {
2714        return false;
2715    }
2716
2717    //  init our bounds from the path
2718    {
2719        SkRect pathBounds = devPath.getBounds();
2720        pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2721        pathBounds.roundOut(bounds);
2722    }
2723
2724    SkIPoint margin = SkIPoint::Make(0, 0);
2725    if (filter) {
2726        SkASSERT(filterMatrix);
2727
2728        SkMask srcM, dstM;
2729
2730        srcM.fBounds = *bounds;
2731        srcM.fFormat = SkMask::kA8_Format;
2732        srcM.fImage = NULL;
2733        if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2734            return false;
2735        }
2736    }
2737
2738    // (possibly) trim the bounds to reflect the clip
2739    // (plus whatever slop the filter needs)
2740    if (clipBounds) {
2741        SkIRect tmp = *clipBounds;
2742        // Ugh. Guard against gigantic margins from wacky filters. Without this
2743        // check we can request arbitrary amounts of slop beyond our visible
2744        // clip, and bring down the renderer (at least on finite RAM machines
2745        // like handsets, etc.). Need to balance this invented value between
2746        // quality of large filters like blurs, and the corresponding memory
2747        // requests.
2748        static const int MAX_MARGIN = 128;
2749        tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2750                  -SkMin32(margin.fY, MAX_MARGIN));
2751        if (!bounds->intersect(tmp)) {
2752            return false;
2753        }
2754    }
2755
2756    return true;
2757}
2758
2759static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
2760                           SkPaint::Style style) {
2761    SkBitmap        bm;
2762    SkDraw          draw;
2763    SkRasterClip    clip;
2764    SkMatrix        matrix;
2765    SkPaint         paint;
2766
2767    bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
2768    bm.setPixels(mask.fImage);
2769
2770    clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
2771    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2772                        -SkIntToScalar(mask.fBounds.fTop));
2773
2774    draw.fBitmap    = &bm;
2775    draw.fRC        = &clip;
2776    draw.fClip      = &clip.bwRgn();
2777    draw.fMatrix    = &matrix;
2778    draw.fBounder   = NULL;
2779    paint.setAntiAlias(true);
2780    paint.setStyle(style);
2781    draw.drawPath(devPath, paint);
2782}
2783
2784bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2785                        const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2786                        SkMask* mask, SkMask::CreateMode mode,
2787                        SkPaint::Style style) {
2788    if (SkMask::kJustRenderImage_CreateMode != mode) {
2789        if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2790            return false;
2791    }
2792
2793    if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2794        mask->fFormat = SkMask::kA8_Format;
2795        mask->fRowBytes = mask->fBounds.width();
2796        size_t size = mask->computeImageSize();
2797        if (0 == size) {
2798            // we're too big to allocate the mask, abort
2799            return false;
2800        }
2801        mask->fImage = SkMask::AllocImage(size);
2802        memset(mask->fImage, 0, mask->computeImageSize());
2803    }
2804
2805    if (SkMask::kJustComputeBounds_CreateMode != mode) {
2806        draw_into_mask(*mask, devPath, style);
2807    }
2808
2809    return true;
2810}
2811