SkDraw.cpp revision dcfb7cf336cafffd8d149c908b615e1deaa3a49b
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 "SkCanvas.h"
11#include "SkColorPriv.h"
12#include "SkDevice.h"
13#include "SkDeviceLooper.h"
14#include "SkFixed.h"
15#include "SkMaskFilter.h"
16#include "SkPaint.h"
17#include "SkPathEffect.h"
18#include "SkRasterClip.h"
19#include "SkRasterizer.h"
20#include "SkRRect.h"
21#include "SkScan.h"
22#include "SkShader.h"
23#include "SkSmallAllocator.h"
24#include "SkString.h"
25#include "SkStroke.h"
26#include "SkTextMapStateProc.h"
27#include "SkTLazy.h"
28#include "SkUtils.h"
29#include "SkVertState.h"
30
31#include "SkAutoKern.h"
32#include "SkBitmapProcShader.h"
33#include "SkDrawProcs.h"
34#include "SkMatrixUtils.h"
35
36
37//#define TRACE_BITMAP_DRAWS
38
39
40/** Helper for allocating small blitters on the stack.
41 */
42class SkAutoBlitterChoose : SkNoncopyable {
43public:
44    SkAutoBlitterChoose() {
45        fBlitter = NULL;
46    }
47    SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
48                        const SkPaint& paint, bool drawCoverage = false) {
49        fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
50                                     drawCoverage);
51    }
52
53    SkBlitter*  operator->() { return fBlitter; }
54    SkBlitter*  get() const { return fBlitter; }
55
56    void choose(const SkBitmap& device, const SkMatrix& matrix,
57                const SkPaint& paint, bool drawCoverage = false) {
58        SkASSERT(!fBlitter);
59        fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
60                                     drawCoverage);
61    }
62
63private:
64    // Owned by fAllocator, which will handle the delete.
65    SkBlitter*          fBlitter;
66    SkTBlitterAllocator fAllocator;
67};
68#define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
69
70/**
71 *  Since we are providing the storage for the shader (to avoid the perf cost
72 *  of calling new) we insist that in our destructor we can account for all
73 *  owners of the shader.
74 */
75class SkAutoBitmapShaderInstall : SkNoncopyable {
76public:
77    SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint,
78                              const SkMatrix* localMatrix = NULL)
79            : fPaint(paint) /* makes a copy of the paint */ {
80        fPaint.setShader(SkCreateBitmapShader(src, SkShader::kClamp_TileMode,
81                                              SkShader::kClamp_TileMode,
82                                              localMatrix, &fAllocator));
83        // we deliberately left the shader with an owner-count of 2
84        SkASSERT(2 == fPaint.getShader()->getRefCnt());
85    }
86
87    ~SkAutoBitmapShaderInstall() {
88        // since fAllocator will destroy shader, we insist that owners == 2
89        SkASSERT(2 == fPaint.getShader()->getRefCnt());
90
91        fPaint.setShader(NULL); // unref the shader by 1
92
93    }
94
95    // return the new paint that has the shader applied
96    const SkPaint& paintWithShader() const { return fPaint; }
97
98private:
99    // copy of caller's paint (which we then modify)
100    SkPaint             fPaint;
101    // Stores the shader.
102    SkTBlitterAllocator fAllocator;
103};
104#define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
105
106///////////////////////////////////////////////////////////////////////////////
107
108SkDraw::SkDraw() {
109    sk_bzero(this, sizeof(*this));
110}
111
112SkDraw::SkDraw(const SkDraw& src) {
113    memcpy(this, &src, sizeof(*this));
114}
115
116bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
117    if (fRC->isEmpty()) {
118        return false;
119    }
120
121    SkMatrix inverse;
122    if (!fMatrix->invert(&inverse)) {
123        return false;
124    }
125
126    SkIRect devBounds = fRC->getBounds();
127    // outset to have slop for antialasing and hairlines
128    devBounds.outset(1, 1);
129    inverse.mapRect(localBounds, SkRect::Make(devBounds));
130    return true;
131}
132
133///////////////////////////////////////////////////////////////////////////////
134
135typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
136
137static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
138    sk_bzero(pixels, bytes);
139}
140
141static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
142
143static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
144    sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2));
145}
146
147static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
148    sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1));
149}
150
151static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
152    memset(pixels, data, bytes);
153}
154
155static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
156                                           const SkPaint& paint,
157                                           uint32_t* data) {
158    // todo: we can apply colorfilter up front if no shader, so we wouldn't
159    // need to abort this fastpath
160    if (paint.getShader() || paint.getColorFilter()) {
161        return NULL;
162    }
163
164    SkXfermode::Mode mode;
165    if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
166        return NULL;
167    }
168
169    SkColor color = paint.getColor();
170
171    // collaps modes based on color...
172    if (SkXfermode::kSrcOver_Mode == mode) {
173        unsigned alpha = SkColorGetA(color);
174        if (0 == alpha) {
175            mode = SkXfermode::kDst_Mode;
176        } else if (0xFF == alpha) {
177            mode = SkXfermode::kSrc_Mode;
178        }
179    }
180
181    switch (mode) {
182        case SkXfermode::kClear_Mode:
183//            SkDebugf("--- D_Clear_BitmapXferProc\n");
184            return D_Clear_BitmapXferProc;  // ignore data
185        case SkXfermode::kDst_Mode:
186//            SkDebugf("--- D_Dst_BitmapXferProc\n");
187            return D_Dst_BitmapXferProc;    // ignore data
188        case SkXfermode::kSrc_Mode: {
189            /*
190                should I worry about dithering for the lower depths?
191            */
192            SkPMColor pmc = SkPreMultiplyColor(color);
193            switch (bitmap.colorType()) {
194                case kN32_SkColorType:
195                    if (data) {
196                        *data = pmc;
197                    }
198//                    SkDebugf("--- D32_Src_BitmapXferProc\n");
199                    return D32_Src_BitmapXferProc;
200                case kRGB_565_SkColorType:
201                    if (data) {
202                        *data = SkPixel32ToPixel16(pmc);
203                    }
204//                    SkDebugf("--- D16_Src_BitmapXferProc\n");
205                    return D16_Src_BitmapXferProc;
206                case kAlpha_8_SkColorType:
207                    if (data) {
208                        *data = SkGetPackedA32(pmc);
209                    }
210//                    SkDebugf("--- DA8_Src_BitmapXferProc\n");
211                    return DA8_Src_BitmapXferProc;
212                default:
213                    break;
214            }
215            break;
216        }
217        default:
218            break;
219    }
220    return NULL;
221}
222
223static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
224                               BitmapXferProc proc, uint32_t procData) {
225    int shiftPerPixel;
226    switch (bitmap.colorType()) {
227        case kN32_SkColorType:
228            shiftPerPixel = 2;
229            break;
230        case kRGB_565_SkColorType:
231            shiftPerPixel = 1;
232            break;
233        case kAlpha_8_SkColorType:
234            shiftPerPixel = 0;
235            break;
236        default:
237            SkDEBUGFAIL("Can't use xferproc on this config");
238            return;
239    }
240
241    uint8_t* pixels = (uint8_t*)bitmap.getPixels();
242    SkASSERT(pixels);
243    const size_t rowBytes = bitmap.rowBytes();
244    const int widthBytes = rect.width() << shiftPerPixel;
245
246    // skip down to the first scanline and X position
247    pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel);
248    for (int scans = rect.height() - 1; scans >= 0; --scans) {
249        proc(pixels, widthBytes, procData);
250        pixels += rowBytes;
251    }
252}
253
254void SkDraw::drawPaint(const SkPaint& paint) const {
255    SkDEBUGCODE(this->validate();)
256
257    if (fRC->isEmpty()) {
258        return;
259    }
260
261    SkIRect    devRect;
262    devRect.set(0, 0, fBitmap->width(), fBitmap->height());
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->isScaleTranslate() && 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
536// each of these costs 8-bytes of stack space, so don't make it too large
537// must be even for lines/polygon to work
538#define MAX_DEV_PTS     32
539
540void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
541                        const SkPoint pts[], const SkPaint& paint,
542                        bool forceUseDevice) const {
543    // if we're in lines mode, force count to be even
544    if (SkCanvas::kLines_PointMode == mode) {
545        count &= ~(size_t)1;
546    }
547
548    if ((long)count <= 0) {
549        return;
550    }
551
552    SkASSERT(pts != NULL);
553    SkDEBUGCODE(this->validate();)
554
555     // nothing to draw
556    if (fRC->isEmpty()) {
557        return;
558    }
559
560    PtProcRec rec;
561    if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) {
562        SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
563
564        SkPoint             devPts[MAX_DEV_PTS];
565        const SkMatrix*     matrix = fMatrix;
566        SkBlitter*          bltr = blitter.get();
567        PtProcRec::Proc     proc = rec.chooseProc(&bltr);
568        // we have to back up subsequent passes if we're in polygon mode
569        const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
570
571        do {
572            int n = SkToInt(count);
573            if (n > MAX_DEV_PTS) {
574                n = MAX_DEV_PTS;
575            }
576            matrix->mapPoints(devPts, pts, n);
577            proc(rec, devPts, n, bltr);
578            pts += n - backup;
579            SkASSERT(SkToInt(count) >= n);
580            count -= n;
581            if (count > 0) {
582                count += backup;
583            }
584        } while (count != 0);
585    } else {
586        switch (mode) {
587            case SkCanvas::kPoints_PointMode: {
588                // temporarily mark the paint as filling.
589                SkPaint newPaint(paint);
590                newPaint.setStyle(SkPaint::kFill_Style);
591
592                SkScalar width = newPaint.getStrokeWidth();
593                SkScalar radius = SkScalarHalf(width);
594
595                if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
596                    SkPath      path;
597                    SkMatrix    preMatrix;
598
599                    path.addCircle(0, 0, radius);
600                    for (size_t i = 0; i < count; i++) {
601                        preMatrix.setTranslate(pts[i].fX, pts[i].fY);
602                        // pass true for the last point, since we can modify
603                        // then path then
604                        path.setIsVolatile((count-1) == i);
605                        if (fDevice) {
606                            fDevice->drawPath(*this, path, newPaint, &preMatrix,
607                                              (count-1) == i);
608                        } else {
609                            this->drawPath(path, newPaint, &preMatrix,
610                                           (count-1) == i);
611                        }
612                    }
613                } else {
614                    SkRect  r;
615
616                    for (size_t i = 0; i < count; i++) {
617                        r.fLeft = pts[i].fX - radius;
618                        r.fTop = pts[i].fY - radius;
619                        r.fRight = r.fLeft + width;
620                        r.fBottom = r.fTop + width;
621                        if (fDevice) {
622                            fDevice->drawRect(*this, r, newPaint);
623                        } else {
624                            this->drawRect(r, newPaint);
625                        }
626                    }
627                }
628                break;
629            }
630            case SkCanvas::kLines_PointMode:
631                if (2 == count && paint.getPathEffect()) {
632                    // most likely a dashed line - see if it is one of the ones
633                    // we can accelerate
634                    SkStrokeRec rec(paint);
635                    SkPathEffect::PointData pointData;
636
637                    SkPath path;
638                    path.moveTo(pts[0]);
639                    path.lineTo(pts[1]);
640
641                    SkRect cullRect = SkRect::Make(fRC->getBounds());
642
643                    if (paint.getPathEffect()->asPoints(&pointData, path, rec,
644                                                        *fMatrix, &cullRect)) {
645                        // 'asPoints' managed to find some fast path
646
647                        SkPaint newP(paint);
648                        newP.setPathEffect(NULL);
649                        newP.setStyle(SkPaint::kFill_Style);
650
651                        if (!pointData.fFirst.isEmpty()) {
652                            if (fDevice) {
653                                fDevice->drawPath(*this, pointData.fFirst, newP);
654                            } else {
655                                this->drawPath(pointData.fFirst, newP);
656                            }
657                        }
658
659                        if (!pointData.fLast.isEmpty()) {
660                            if (fDevice) {
661                                fDevice->drawPath(*this, pointData.fLast, newP);
662                            } else {
663                                this->drawPath(pointData.fLast, newP);
664                            }
665                        }
666
667                        if (pointData.fSize.fX == pointData.fSize.fY) {
668                            // The rest of the dashed line can just be drawn as points
669                            SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth()));
670
671                            if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) {
672                                newP.setStrokeCap(SkPaint::kRound_Cap);
673                            } else {
674                                newP.setStrokeCap(SkPaint::kButt_Cap);
675                            }
676
677                            if (fDevice) {
678                                fDevice->drawPoints(*this,
679                                                    SkCanvas::kPoints_PointMode,
680                                                    pointData.fNumPoints,
681                                                    pointData.fPoints,
682                                                    newP);
683                            } else {
684                                this->drawPoints(SkCanvas::kPoints_PointMode,
685                                                 pointData.fNumPoints,
686                                                 pointData.fPoints,
687                                                 newP,
688                                                 forceUseDevice);
689                            }
690                            break;
691                        } else {
692                            // The rest of the dashed line must be drawn as rects
693                            SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag &
694                                      pointData.fFlags));
695
696                            SkRect r;
697
698                            for (int i = 0; i < pointData.fNumPoints; ++i) {
699                                r.set(pointData.fPoints[i].fX - pointData.fSize.fX,
700                                      pointData.fPoints[i].fY - pointData.fSize.fY,
701                                      pointData.fPoints[i].fX + pointData.fSize.fX,
702                                      pointData.fPoints[i].fY + pointData.fSize.fY);
703                                if (fDevice) {
704                                    fDevice->drawRect(*this, r, newP);
705                                } else {
706                                    this->drawRect(r, newP);
707                                }
708                            }
709                        }
710
711                        break;
712                    }
713                }
714                // couldn't take fast path so fall through!
715            case SkCanvas::kPolygon_PointMode: {
716                count -= 1;
717                SkPath path;
718                SkPaint p(paint);
719                p.setStyle(SkPaint::kStroke_Style);
720                size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
721                path.setIsVolatile(true);
722                for (size_t i = 0; i < count; i += inc) {
723                    path.moveTo(pts[i]);
724                    path.lineTo(pts[i+1]);
725                    if (fDevice) {
726                        fDevice->drawPath(*this, path, p, NULL, true);
727                    } else {
728                        this->drawPath(path, p, NULL, true);
729                    }
730                    path.rewind();
731                }
732                break;
733            }
734        }
735    }
736}
737
738static inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) {
739    SkASSERT(matrix.rectStaysRect());
740    SkASSERT(SkPaint::kFill_Style != paint.getStyle());
741
742    SkVector size;
743    SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
744    matrix.mapVectors(&size, &pt, 1);
745    return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY));
746}
747
748static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix,
749                           SkPoint* strokeSize) {
750    if (SkPaint::kMiter_Join != paint.getStrokeJoin() ||
751        paint.getStrokeMiter() < SK_ScalarSqrt2) {
752        return false;
753    }
754
755    *strokeSize = compute_stroke_size(paint, matrix);
756    return true;
757}
758
759SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
760                                         const SkMatrix& matrix,
761                                         SkPoint* strokeSize) {
762    RectType rtype;
763    const SkScalar width = paint.getStrokeWidth();
764    const bool zeroWidth = (0 == width);
765    SkPaint::Style style = paint.getStyle();
766
767    if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
768        style = SkPaint::kFill_Style;
769    }
770
771    if (paint.getPathEffect() || paint.getMaskFilter() ||
772        paint.getRasterizer() || !matrix.rectStaysRect() ||
773        SkPaint::kStrokeAndFill_Style == style) {
774        rtype = kPath_RectType;
775    } else if (SkPaint::kFill_Style == style) {
776        rtype = kFill_RectType;
777    } else if (zeroWidth) {
778        rtype = kHair_RectType;
779    } else if (easy_rect_join(paint, matrix, strokeSize)) {
780        rtype = kStroke_RectType;
781    } else {
782        rtype = kPath_RectType;
783    }
784    return rtype;
785}
786
787static const SkPoint* rect_points(const SkRect& r) {
788    return SkTCast<const SkPoint*>(&r);
789}
790
791static SkPoint* rect_points(SkRect& r) {
792    return SkTCast<SkPoint*>(&r);
793}
794
795void SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint,
796                      const SkMatrix* paintMatrix, const SkRect* postPaintRect) const {
797    SkDEBUGCODE(this->validate();)
798
799    // nothing to draw
800    if (fRC->isEmpty()) {
801        return;
802    }
803
804    const SkMatrix* matrix;
805    SkMatrix combinedMatrixStorage;
806    if (paintMatrix) {
807        SkASSERT(postPaintRect);
808        combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix);
809        matrix = &combinedMatrixStorage;
810    } else {
811        SkASSERT(!postPaintRect);
812        matrix = fMatrix;
813    }
814
815    SkPoint strokeSize;
816    RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize);
817
818    if (kPath_RectType == rtype) {
819        SkDraw draw(*this);
820        if (paintMatrix) {
821            draw.fMatrix = matrix;
822        }
823        SkPath  tmp;
824        tmp.addRect(prePaintRect);
825        tmp.setFillType(SkPath::kWinding_FillType);
826        draw.drawPath(tmp, paint, NULL, true);
827        return;
828    }
829
830    SkRect devRect;
831    const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect;
832    // skip the paintMatrix when transforming the rect by the CTM
833    fMatrix->mapPoints(rect_points(devRect), rect_points(paintRect), 2);
834    devRect.sort();
835
836    // look for the quick exit, before we build a blitter
837    SkRect bbox = devRect;
838    if (paint.getStyle() != SkPaint::kFill_Style) {
839        // extra space for hairlines
840        if (paint.getStrokeWidth() == 0) {
841            bbox.outset(1, 1);
842        } else {
843            // For kStroke_RectType, strokeSize is already computed.
844            const SkPoint& ssize = (kStroke_RectType == rtype)
845                ? strokeSize
846                : compute_stroke_size(paint, *fMatrix);
847            bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y()));
848        }
849    }
850
851    SkIRect ir = bbox.roundOut();
852    if (fRC->quickReject(ir)) {
853        return;
854    }
855
856    SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
857    while (looper.next()) {
858        SkRect localDevRect;
859        looper.mapRect(&localDevRect, devRect);
860        SkMatrix localMatrix;
861        looper.mapMatrix(&localMatrix, *matrix);
862
863        SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, paint);
864        const SkRasterClip& clip = looper.getRC();
865        SkBlitter*          blitter = blitterStorage.get();
866
867        // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
868        // case we are also hairline (if we've gotten to here), which devolves to
869        // effectively just kFill
870        switch (rtype) {
871            case kFill_RectType:
872                if (paint.isAntiAlias()) {
873                    SkScan::AntiFillRect(localDevRect, clip, blitter);
874                } else {
875                    SkScan::FillRect(localDevRect, clip, blitter);
876                }
877                break;
878            case kStroke_RectType:
879                if (paint.isAntiAlias()) {
880                    SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
881                } else {
882                    SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
883                }
884                break;
885            case kHair_RectType:
886                if (paint.isAntiAlias()) {
887                    SkScan::AntiHairRect(localDevRect, clip, blitter);
888                } else {
889                    SkScan::HairRect(localDevRect, clip, blitter);
890                }
891                break;
892            default:
893                SkDEBUGFAIL("bad rtype");
894        }
895    }
896}
897
898void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
899    if (srcM.fBounds.isEmpty()) {
900        return;
901    }
902
903    const SkMask* mask = &srcM;
904
905    SkMask dstM;
906    if (paint.getMaskFilter() &&
907            paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
908        mask = &dstM;
909    } else {
910        dstM.fImage = NULL;
911    }
912    SkAutoMaskFreeImage ami(dstM.fImage);
913
914    SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
915    SkBlitter* blitter = blitterChooser.get();
916
917    SkAAClipBlitterWrapper wrapper;
918    const SkRegion* clipRgn;
919
920    if (fRC->isBW()) {
921        clipRgn = &fRC->bwRgn();
922    } else {
923        wrapper.init(*fRC, blitter);
924        clipRgn = &wrapper.getRgn();
925        blitter = wrapper.getBlitter();
926    }
927    blitter->blitMaskRegion(*mask, *clipRgn);
928}
929
930static SkScalar fast_len(const SkVector& vec) {
931    SkScalar x = SkScalarAbs(vec.fX);
932    SkScalar y = SkScalarAbs(vec.fY);
933    if (x < y) {
934        SkTSwap(x, y);
935    }
936    return x + SkScalarHalf(y);
937}
938
939bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
940                                   SkScalar* coverage) {
941    SkASSERT(strokeWidth > 0);
942    // We need to try to fake a thick-stroke with a modulated hairline.
943
944    if (matrix.hasPerspective()) {
945        return false;
946    }
947
948    SkVector src[2], dst[2];
949    src[0].set(strokeWidth, 0);
950    src[1].set(0, strokeWidth);
951    matrix.mapVectors(dst, src, 2);
952    SkScalar len0 = fast_len(dst[0]);
953    SkScalar len1 = fast_len(dst[1]);
954    if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
955        if (coverage) {
956            *coverage = SkScalarAve(len0, len1);
957        }
958        return true;
959    }
960    return false;
961}
962
963void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
964    SkDEBUGCODE(this->validate());
965
966    if (fRC->isEmpty()) {
967        return;
968    }
969
970    {
971        // TODO: Investigate optimizing these options. They are in the same
972        // order as SkDraw::drawPath, which handles each case. It may be
973        // that there is no way to optimize for these using the SkRRect path.
974        SkScalar coverage;
975        if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) {
976            goto DRAW_PATH;
977        }
978
979        if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
980            goto DRAW_PATH;
981        }
982
983        if (paint.getRasterizer()) {
984            goto DRAW_PATH;
985        }
986    }
987
988    if (paint.getMaskFilter()) {
989        // Transform the rrect into device space.
990        SkRRect devRRect;
991        if (rrect.transform(*fMatrix, &devRRect)) {
992            SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
993            if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get(),
994                                                   SkPaint::kFill_Style)) {
995                return; // filterRRect() called the blitter, so we're done
996            }
997        }
998    }
999
1000DRAW_PATH:
1001    // Now fall back to the default case of using a path.
1002    SkPath path;
1003    path.addRRect(rrect);
1004    this->drawPath(path, paint, NULL, true);
1005}
1006
1007void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
1008                      const SkMatrix* prePathMatrix, bool pathIsMutable,
1009                      bool drawCoverage, SkBlitter* customBlitter) const {
1010    SkDEBUGCODE(this->validate();)
1011
1012    // nothing to draw
1013    if (fRC->isEmpty()) {
1014        return;
1015    }
1016
1017    SkPath*         pathPtr = (SkPath*)&origSrcPath;
1018    bool            doFill = true;
1019    SkPath          tmpPath;
1020    SkMatrix        tmpMatrix;
1021    const SkMatrix* matrix = fMatrix;
1022    tmpPath.setIsVolatile(true);
1023
1024    if (prePathMatrix) {
1025        if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
1026                origPaint.getRasterizer()) {
1027            SkPath* result = pathPtr;
1028
1029            if (!pathIsMutable) {
1030                result = &tmpPath;
1031                pathIsMutable = true;
1032            }
1033            pathPtr->transform(*prePathMatrix, result);
1034            pathPtr = result;
1035        } else {
1036            tmpMatrix.setConcat(*matrix, *prePathMatrix);
1037            matrix = &tmpMatrix;
1038        }
1039    }
1040    // at this point we're done with prePathMatrix
1041    SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
1042
1043    SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
1044
1045    {
1046        SkScalar coverage;
1047        if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
1048            if (SK_Scalar1 == coverage) {
1049                paint.writable()->setStrokeWidth(0);
1050            } else if (SkXfermode::SupportsCoverageAsAlpha(origPaint.getXfermode())) {
1051                U8CPU newAlpha;
1052#if 0
1053                newAlpha = SkToU8(SkScalarRoundToInt(coverage *
1054                                                     origPaint.getAlpha()));
1055#else
1056                // this is the old technique, which we preserve for now so
1057                // we don't change previous results (testing)
1058                // the new way seems fine, its just (a tiny bit) different
1059                int scale = (int)SkScalarMul(coverage, 256);
1060                newAlpha = origPaint.getAlpha() * scale >> 8;
1061#endif
1062                SkPaint* writablePaint = paint.writable();
1063                writablePaint->setStrokeWidth(0);
1064                writablePaint->setAlpha(newAlpha);
1065            }
1066        }
1067    }
1068
1069    if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
1070        SkRect cullRect;
1071        const SkRect* cullRectPtr = NULL;
1072        if (this->computeConservativeLocalClipBounds(&cullRect)) {
1073            cullRectPtr = &cullRect;
1074        }
1075        doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr);
1076        pathPtr = &tmpPath;
1077    }
1078
1079    if (paint->getRasterizer()) {
1080        SkMask  mask;
1081        if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
1082                            &fRC->getBounds(), paint->getMaskFilter(), &mask,
1083                            SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
1084            this->drawDevMask(mask, *paint);
1085            SkMask::FreeImage(mask.fImage);
1086        }
1087        return;
1088    }
1089
1090    // avoid possibly allocating a new path in transform if we can
1091    SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
1092
1093    // transform the path into device space
1094    pathPtr->transform(*matrix, devPathPtr);
1095
1096    SkBlitter* blitter = NULL;
1097    SkAutoBlitterChoose blitterStorage;
1098    if (NULL == customBlitter) {
1099        blitterStorage.choose(*fBitmap, *fMatrix, *paint, drawCoverage);
1100        blitter = blitterStorage.get();
1101    } else {
1102        blitter = customBlitter;
1103    }
1104
1105    if (paint->getMaskFilter()) {
1106        SkPaint::Style style = doFill ? SkPaint::kFill_Style :
1107            SkPaint::kStroke_Style;
1108        if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, blitter, style)) {
1109            return; // filterPath() called the blitter, so we're done
1110        }
1111    }
1112
1113    void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
1114    if (doFill) {
1115        if (paint->isAntiAlias()) {
1116            proc = SkScan::AntiFillPath;
1117        } else {
1118            proc = SkScan::FillPath;
1119        }
1120    } else {    // hairline
1121        if (paint->isAntiAlias()) {
1122            proc = SkScan::AntiHairPath;
1123        } else {
1124            proc = SkScan::HairPath;
1125        }
1126    }
1127    proc(*devPathPtr, *fRC, blitter);
1128}
1129
1130/** For the purposes of drawing bitmaps, if a matrix is "almost" translate
1131    go ahead and treat it as if it were, so that subsequent code can go fast.
1132 */
1133static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
1134    unsigned bits = 0;  // TODO: find a way to allow the caller to tell us to
1135                        // respect filtering.
1136    return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
1137}
1138
1139void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
1140                              const SkPaint& paint) const {
1141    SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType);
1142
1143    if (just_translate(*fMatrix, bitmap)) {
1144        int ix = SkScalarRoundToInt(fMatrix->getTranslateX());
1145        int iy = SkScalarRoundToInt(fMatrix->getTranslateY());
1146
1147        SkAutoLockPixels alp(bitmap);
1148        if (!bitmap.readyToDraw()) {
1149            return;
1150        }
1151
1152        SkMask  mask;
1153        mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1154        mask.fFormat = SkMask::kA8_Format;
1155        mask.fRowBytes = SkToU32(bitmap.rowBytes());
1156        mask.fImage = bitmap.getAddr8(0, 0);
1157
1158        this->drawDevMask(mask, paint);
1159    } else {    // need to xform the bitmap first
1160        SkRect  r;
1161        SkMask  mask;
1162
1163        r.set(0, 0,
1164              SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
1165        fMatrix->mapRect(&r);
1166        r.round(&mask.fBounds);
1167
1168        // set the mask's bounds to the transformed bitmap-bounds,
1169        // clipped to the actual device
1170        {
1171            SkIRect    devBounds;
1172            devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
1173            // need intersect(l, t, r, b) on irect
1174            if (!mask.fBounds.intersect(devBounds)) {
1175                return;
1176            }
1177        }
1178
1179        mask.fFormat = SkMask::kA8_Format;
1180        mask.fRowBytes = SkAlign4(mask.fBounds.width());
1181        size_t size = mask.computeImageSize();
1182        if (0 == size) {
1183            // the mask is too big to allocated, draw nothing
1184            return;
1185        }
1186
1187        // allocate (and clear) our temp buffer to hold the transformed bitmap
1188        SkAutoMalloc    storage(size);
1189        mask.fImage = (uint8_t*)storage.get();
1190        memset(mask.fImage, 0, size);
1191
1192        // now draw our bitmap(src) into mask(dst), transformed by the matrix
1193        {
1194            SkBitmap    device;
1195            device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
1196                                 mask.fImage, mask.fRowBytes);
1197
1198            SkCanvas c(device);
1199            // need the unclipped top/left for the translate
1200            c.translate(-SkIntToScalar(mask.fBounds.fLeft),
1201                        -SkIntToScalar(mask.fBounds.fTop));
1202            c.concat(*fMatrix);
1203
1204            // We can't call drawBitmap, or we'll infinitely recurse. Instead
1205            // we manually build a shader and draw that into our new mask
1206            SkPaint tmpPaint;
1207            tmpPaint.setFlags(paint.getFlags());
1208            SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
1209            SkRect rr;
1210            rr.set(0, 0, SkIntToScalar(bitmap.width()),
1211                   SkIntToScalar(bitmap.height()));
1212            c.drawRect(rr, install.paintWithShader());
1213        }
1214        this->drawDevMask(mask, paint);
1215    }
1216}
1217
1218static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
1219                        const SkRect& srcR) {
1220    SkRect  dstR;
1221    m.mapRect(&dstR, srcR);
1222    return c.quickReject(dstR.roundOut());
1223}
1224
1225static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
1226                        int width, int height) {
1227    SkRect  r;
1228    r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1229    return clipped_out(matrix, clip, r);
1230}
1231
1232static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
1233                              const SkBitmap& bitmap) {
1234    return clip.isBW() ||
1235           clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
1236}
1237
1238void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1239                        const SkRect* dstBounds, const SkPaint& origPaint) const {
1240    SkDEBUGCODE(this->validate();)
1241
1242    // nothing to draw
1243    if (fRC->isEmpty() ||
1244            bitmap.width() == 0 || bitmap.height() == 0 ||
1245            bitmap.colorType() == kUnknown_SkColorType) {
1246        return;
1247    }
1248
1249    SkPaint paint(origPaint);
1250    paint.setStyle(SkPaint::kFill_Style);
1251
1252    SkMatrix matrix;
1253    matrix.setConcat(*fMatrix, prematrix);
1254
1255    if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
1256        return;
1257    }
1258
1259    if (bitmap.colorType() != kAlpha_8_SkColorType && just_translate(matrix, bitmap)) {
1260        //
1261        // It is safe to call lock pixels now, since we know the matrix is
1262        // (more or less) identity.
1263        //
1264        SkAutoLockPixels alp(bitmap);
1265        if (!bitmap.readyToDraw()) {
1266            return;
1267        }
1268        int ix = SkScalarRoundToInt(matrix.getTranslateX());
1269        int iy = SkScalarRoundToInt(matrix.getTranslateY());
1270        if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
1271            SkTBlitterAllocator allocator;
1272            // blitter will be owned by the allocator.
1273            SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1274                                                         ix, iy, &allocator);
1275            if (blitter) {
1276                SkIRect    ir;
1277                ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1278
1279                SkScan::FillIRect(ir, *fRC, blitter);
1280                return;
1281            }
1282        }
1283    }
1284
1285    // now make a temp draw on the stack, and use it
1286    //
1287    SkDraw draw(*this);
1288    draw.fMatrix = &matrix;
1289
1290    if (bitmap.colorType() == kAlpha_8_SkColorType) {
1291        draw.drawBitmapAsMask(bitmap, paint);
1292    } else {
1293        SkAutoBitmapShaderInstall install(bitmap, paint);
1294        const SkPaint& paintWithShader = install.paintWithShader();
1295        const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height());
1296        if (dstBounds) {
1297            this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds);
1298        } else {
1299            draw.drawRect(srcBounds, paintWithShader);
1300        }
1301    }
1302}
1303
1304void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1305                        const SkPaint& origPaint) const {
1306    SkDEBUGCODE(this->validate();)
1307
1308    // nothing to draw
1309    if (fRC->isEmpty() ||
1310            bitmap.width() == 0 || bitmap.height() == 0 ||
1311            bitmap.colorType() == kUnknown_SkColorType) {
1312        return;
1313    }
1314
1315    SkIRect    bounds;
1316    bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1317
1318    if (fRC->quickReject(bounds)) {
1319        return; // nothing to draw
1320    }
1321
1322    SkPaint paint(origPaint);
1323    paint.setStyle(SkPaint::kFill_Style);
1324
1325    if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
1326        SkTBlitterAllocator allocator;
1327        // blitter will be owned by the allocator.
1328        SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1329                                                     x, y, &allocator);
1330
1331        if (blitter) {
1332            SkScan::FillIRect(bounds, *fRC, blitter);
1333            return;
1334        }
1335    }
1336
1337    SkMatrix        matrix;
1338    SkRect          r;
1339
1340    // get a scalar version of our rect
1341    r.set(bounds);
1342
1343    // create shader with offset
1344    matrix.setTranslate(r.fLeft, r.fTop);
1345    SkAutoBitmapShaderInstall install(bitmap, paint, &matrix);
1346    const SkPaint& shaderPaint = install.paintWithShader();
1347
1348    SkDraw draw(*this);
1349    matrix.reset();
1350    draw.fMatrix = &matrix;
1351    // call ourself with a rect
1352    // is this OK if paint has a rasterizer?
1353    draw.drawRect(r, shaderPaint);
1354}
1355
1356///////////////////////////////////////////////////////////////////////////////
1357
1358#include "SkScalerContext.h"
1359#include "SkGlyphCache.h"
1360#include "SkTextToPathIter.h"
1361#include "SkUtils.h"
1362
1363static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1364                const char text[], size_t byteLength, SkVector* stopVector) {
1365    SkFixed     x = 0, y = 0;
1366    const char* stop = text + byteLength;
1367
1368    SkAutoKern  autokern;
1369
1370    while (text < stop) {
1371        // don't need x, y here, since all subpixel variants will have the
1372        // same advance
1373        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1374
1375        x += autokern.adjust(glyph) + glyph.fAdvanceX;
1376        y += glyph.fAdvanceY;
1377    }
1378    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1379
1380    SkASSERT(text == stop);
1381}
1382
1383bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
1384    // hairline glyphs are fast enough so we don't need to cache them
1385    if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
1386        return true;
1387    }
1388
1389    // we don't cache perspective
1390    if (ctm.hasPerspective()) {
1391        return true;
1392    }
1393
1394    SkMatrix textM;
1395    return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
1396}
1397
1398void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1399                              SkScalar x, SkScalar y,
1400                              const SkPaint& paint) const {
1401    SkDEBUGCODE(this->validate();)
1402
1403    SkTextToPathIter iter(text, byteLength, paint, true);
1404
1405    SkMatrix    matrix;
1406    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1407    matrix.postTranslate(x, y);
1408
1409    const SkPath* iterPath;
1410    SkScalar xpos, prevXPos = 0;
1411
1412    while (iter.next(&iterPath, &xpos)) {
1413        matrix.postTranslate(xpos - prevXPos, 0);
1414        if (iterPath) {
1415            const SkPaint& pnt = iter.getPaint();
1416            if (fDevice) {
1417                fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
1418            } else {
1419                this->drawPath(*iterPath, pnt, &matrix, false);
1420            }
1421        }
1422        prevXPos = xpos;
1423    }
1424}
1425
1426// disable warning : local variable used without having been initialized
1427#if defined _WIN32 && _MSC_VER >= 1300
1428#pragma warning ( push )
1429#pragma warning ( disable : 4701 )
1430#endif
1431
1432//////////////////////////////////////////////////////////////////////////////
1433
1434static void D1G_RectClip(const SkDraw1Glyph& state, SkFixed fx, SkFixed fy, const SkGlyph& glyph) {
1435    int left = SkFixedFloorToInt(fx);
1436    int top = SkFixedFloorToInt(fy);
1437    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1438    SkASSERT((NULL == state.fClip && state.fAAClip) ||
1439             (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
1440
1441    left += glyph.fLeft;
1442    top  += glyph.fTop;
1443
1444    int right   = left + glyph.fWidth;
1445    int bottom  = top + glyph.fHeight;
1446
1447    SkMask        mask;
1448    SkIRect        storage;
1449    SkIRect*    bounds = &mask.fBounds;
1450
1451    mask.fBounds.set(left, top, right, bottom);
1452
1453    // this extra test is worth it, assuming that most of the time it succeeds
1454    // since we can avoid writing to storage
1455    if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1456        if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1457            return;
1458        bounds = &storage;
1459    }
1460
1461    uint8_t* aa = (uint8_t*)glyph.fImage;
1462    if (NULL == aa) {
1463        aa = (uint8_t*)state.fCache->findImage(glyph);
1464        if (NULL == aa) {
1465            return; // can't rasterize glyph
1466        }
1467    }
1468
1469    mask.fRowBytes = glyph.rowBytes();
1470    mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1471    mask.fImage = aa;
1472    state.blitMask(mask, *bounds);
1473}
1474
1475static void D1G_RgnClip(const SkDraw1Glyph& state, SkFixed fx, SkFixed fy, const SkGlyph& glyph) {
1476    int left = SkFixedFloorToInt(fx);
1477    int top = SkFixedFloorToInt(fy);
1478    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1479    SkASSERT(!state.fClip->isRect());
1480
1481    SkMask  mask;
1482
1483    left += glyph.fLeft;
1484    top  += glyph.fTop;
1485
1486    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1487    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1488
1489    if (!clipper.done()) {
1490        const SkIRect&  cr = clipper.rect();
1491        const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1492        if (NULL == aa) {
1493            aa = (uint8_t*)state.fCache->findImage(glyph);
1494            if (NULL == aa) {
1495                return;
1496            }
1497        }
1498
1499        mask.fRowBytes = glyph.rowBytes();
1500        mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1501        mask.fImage = (uint8_t*)aa;
1502        do {
1503            state.blitMask(mask, cr);
1504            clipper.next();
1505        } while (!clipper.done());
1506    }
1507}
1508
1509static bool hasCustomD1GProc(const SkDraw& draw) {
1510    return draw.fProcs && draw.fProcs->fD1GProc;
1511}
1512
1513static bool needsRasterTextBlit(const SkDraw& draw) {
1514    return !hasCustomD1GProc(draw);
1515}
1516
1517SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
1518                                      const SkPaint& pnt) {
1519    fDraw = draw;
1520    fBlitter = blitter;
1521    fCache = cache;
1522    fPaint = &pnt;
1523
1524    if (cache->isSubpixel()) {
1525        fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
1526    } else {
1527        fHalfSampleX = fHalfSampleY = SK_FixedHalf;
1528    }
1529
1530    if (hasCustomD1GProc(*draw)) {
1531        // todo: fix this assumption about clips w/ custom
1532        fClip = draw->fClip;
1533        fClipBounds = fClip->getBounds();
1534        return draw->fProcs->fD1GProc;
1535    }
1536
1537    if (draw->fRC->isBW()) {
1538        fAAClip = NULL;
1539        fClip = &draw->fRC->bwRgn();
1540        fClipBounds = fClip->getBounds();
1541        if (fClip->isRect()) {
1542            return D1G_RectClip;
1543        } else {
1544            return D1G_RgnClip;
1545        }
1546    } else {    // aaclip
1547        fAAClip = &draw->fRC->aaRgn();
1548        fClip = NULL;
1549        fClipBounds = fAAClip->getBounds();
1550        return D1G_RectClip;
1551    }
1552}
1553
1554void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1555    SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1556
1557    SkBitmap bm;
1558    bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()),
1559                     (SkPMColor*)mask.fImage, mask.fRowBytes);
1560
1561    fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1562}
1563
1564///////////////////////////////////////////////////////////////////////////////
1565
1566void SkDraw::drawText(const char text[], size_t byteLength,
1567                      SkScalar x, SkScalar y, const SkPaint& paint) const {
1568    SkASSERT(byteLength == 0 || text != NULL);
1569
1570    SkDEBUGCODE(this->validate();)
1571
1572    // nothing to draw
1573    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1574        return;
1575    }
1576
1577    // SkScalarRec doesn't currently have a way of representing hairline stroke and
1578    // will fill if its frame-width is 0.
1579    if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1580        this->drawText_asPaths(text, byteLength, x, y, paint);
1581        return;
1582    }
1583
1584    SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1585
1586    SkAutoGlyphCache    autoCache(paint, &fDevice->getLeakyProperties(), fMatrix);
1587    SkGlyphCache*       cache = autoCache.getCache();
1588
1589    // transform our starting point
1590    {
1591        SkPoint loc;
1592        fMatrix->mapXY(x, y, &loc);
1593        x = loc.fX;
1594        y = loc.fY;
1595    }
1596
1597    // need to measure first
1598    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1599        SkVector    stop;
1600
1601        measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1602
1603        SkScalar    stopX = stop.fX;
1604        SkScalar    stopY = stop.fY;
1605
1606        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1607            stopX = SkScalarHalf(stopX);
1608            stopY = SkScalarHalf(stopY);
1609        }
1610        x -= stopX;
1611        y -= stopY;
1612    }
1613
1614    const char* stop = text + byteLength;
1615
1616    SkAAClipBlitter     aaBlitter;
1617    SkAutoBlitterChoose blitterChooser;
1618    SkBlitter*          blitter = NULL;
1619    if (needsRasterTextBlit(*this)) {
1620        blitterChooser.choose(*fBitmap, *fMatrix, paint);
1621        blitter = blitterChooser.get();
1622        if (fRC->isAA()) {
1623            aaBlitter.init(blitter, &fRC->aaRgn());
1624            blitter = &aaBlitter;
1625        }
1626    }
1627
1628    SkAutoKern          autokern;
1629    SkDraw1Glyph        d1g;
1630    SkDraw1Glyph::Proc  proc = d1g.init(this, blitter, cache, paint);
1631
1632    SkFixed fxMask = ~0;
1633    SkFixed fyMask = ~0;
1634    if (cache->isSubpixel()) {
1635        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1636        if (kX_SkAxisAlignment == baseline) {
1637            fyMask = 0;
1638            d1g.fHalfSampleY = SK_FixedHalf;
1639        } else if (kY_SkAxisAlignment == baseline) {
1640            fxMask = 0;
1641            d1g.fHalfSampleX = SK_FixedHalf;
1642        }
1643    }
1644
1645    SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX;
1646    SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY;
1647
1648    while (text < stop) {
1649        const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
1650
1651        fx += autokern.adjust(glyph);
1652
1653        if (glyph.fWidth) {
1654            proc(d1g, fx, fy, glyph);
1655        }
1656
1657        fx += glyph.fAdvanceX;
1658        fy += glyph.fAdvanceY;
1659    }
1660}
1661
1662//////////////////////////////////////////////////////////////////////////////
1663
1664void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1665                                 const SkScalar pos[], int scalarsPerPosition,
1666                                 const SkPoint& offset, const SkPaint& origPaint) const {
1667    // setup our std paint, in hopes of getting hits in the cache
1668    SkPaint paint(origPaint);
1669    SkScalar matrixScale = paint.setupForAsPaths();
1670
1671    SkMatrix matrix;
1672    matrix.setScale(matrixScale, matrixScale);
1673
1674    // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
1675    paint.setStyle(SkPaint::kFill_Style);
1676    paint.setPathEffect(NULL);
1677
1678    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1679    SkAutoGlyphCache    autoCache(paint, NULL, NULL);
1680    SkGlyphCache*       cache = autoCache.getCache();
1681
1682    const char*        stop = text + byteLength;
1683    SkTextAlignProcScalar alignProc(paint.getTextAlign());
1684    SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
1685
1686    // Now restore the original settings, so we "draw" with whatever style/stroking.
1687    paint.setStyle(origPaint.getStyle());
1688    paint.setPathEffect(origPaint.getPathEffect());
1689
1690    while (text < stop) {
1691        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1692        if (glyph.fWidth) {
1693            const SkPath* path = cache->findPath(glyph);
1694            if (path) {
1695                SkPoint tmsLoc;
1696                tmsProc(pos, &tmsLoc);
1697                SkPoint loc;
1698                alignProc(tmsLoc, glyph, &loc);
1699
1700                matrix[SkMatrix::kMTransX] = loc.fX;
1701                matrix[SkMatrix::kMTransY] = loc.fY;
1702                if (fDevice) {
1703                    fDevice->drawPath(*this, *path, paint, &matrix, false);
1704                } else {
1705                    this->drawPath(*path, paint, &matrix, false);
1706                }
1707            }
1708        }
1709        pos += scalarsPerPosition;
1710    }
1711}
1712
1713void SkDraw::drawPosText(const char text[], size_t byteLength,
1714                         const SkScalar pos[], int scalarsPerPosition,
1715                         const SkPoint& offset, const SkPaint& paint) const {
1716    SkASSERT(byteLength == 0 || text != NULL);
1717    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1718
1719    SkDEBUGCODE(this->validate();)
1720
1721    // nothing to draw
1722    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1723        return;
1724    }
1725
1726    if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1727        this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, offset, paint);
1728        return;
1729    }
1730
1731    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1732    SkAutoGlyphCache    autoCache(paint, &fDevice->getLeakyProperties(), fMatrix);
1733    SkGlyphCache*       cache = autoCache.getCache();
1734
1735    SkAAClipBlitterWrapper wrapper;
1736    SkAutoBlitterChoose blitterChooser;
1737    SkBlitter* blitter = NULL;
1738    if (needsRasterTextBlit(*this)) {
1739        blitterChooser.choose(*fBitmap, *fMatrix, paint);
1740        blitter = blitterChooser.get();
1741        if (fRC->isAA()) {
1742            wrapper.init(*fRC, blitter);
1743            blitter = wrapper.getBlitter();
1744        }
1745    }
1746
1747    const char*        stop = text + byteLength;
1748    SkTextAlignProc    alignProc(paint.getTextAlign());
1749    SkDraw1Glyph       d1g;
1750    SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
1751    SkTextMapStateProc tmsProc(*fMatrix, offset, scalarsPerPosition);
1752
1753    if (cache->isSubpixel()) {
1754        // maybe we should skip the rounding if linearText is set
1755        SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
1756
1757        SkFixed fxMask = ~0;
1758        SkFixed fyMask = ~0;
1759        if (kX_SkAxisAlignment == baseline) {
1760            fyMask = 0;
1761            d1g.fHalfSampleY = SK_FixedHalf;
1762        } else if (kY_SkAxisAlignment == baseline) {
1763            fxMask = 0;
1764            d1g.fHalfSampleX = SK_FixedHalf;
1765        }
1766
1767        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1768            while (text < stop) {
1769                SkPoint tmsLoc;
1770                tmsProc(pos, &tmsLoc);
1771                SkFixed fx = SkScalarToFixed(tmsLoc.fX) + d1g.fHalfSampleX;
1772                SkFixed fy = SkScalarToFixed(tmsLoc.fY) + d1g.fHalfSampleY;
1773
1774                const SkGlyph& glyph = glyphCacheProc(cache, &text,
1775                                                      fx & fxMask, fy & fyMask);
1776
1777                if (glyph.fWidth) {
1778                    proc(d1g, fx, fy, glyph);
1779                }
1780                pos += scalarsPerPosition;
1781            }
1782        } else {
1783            while (text < stop) {
1784                const char* currentText = text;
1785                const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
1786
1787                if (metricGlyph.fWidth) {
1788                    SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
1789                    SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
1790                    SkPoint tmsLoc;
1791                    tmsProc(pos, &tmsLoc);
1792                    SkIPoint fixedLoc;
1793                    alignProc(tmsLoc, metricGlyph, &fixedLoc);
1794
1795                    SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
1796                    SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
1797
1798                    // have to call again, now that we've been "aligned"
1799                    const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
1800                                                          fx & fxMask, fy & fyMask);
1801                    // the assumption is that the metrics haven't changed
1802                    SkASSERT(prevAdvX == glyph.fAdvanceX);
1803                    SkASSERT(prevAdvY == glyph.fAdvanceY);
1804                    SkASSERT(glyph.fWidth);
1805
1806                    proc(d1g, fx, fy, glyph);
1807                }
1808                pos += scalarsPerPosition;
1809            }
1810        }
1811    } else {    // not subpixel
1812        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1813            while (text < stop) {
1814                // the last 2 parameters are ignored
1815                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1816
1817                if (glyph.fWidth) {
1818                    SkPoint tmsLoc;
1819                    tmsProc(pos, &tmsLoc);
1820
1821                    proc(d1g,
1822                         SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
1823                         SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
1824                         glyph);
1825                }
1826                pos += scalarsPerPosition;
1827            }
1828        } else {
1829            while (text < stop) {
1830                // the last 2 parameters are ignored
1831                const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1832
1833                if (glyph.fWidth) {
1834                    SkPoint tmsLoc;
1835                    tmsProc(pos, &tmsLoc);
1836
1837                    SkIPoint fixedLoc;
1838                    alignProc(tmsLoc, glyph, &fixedLoc);
1839
1840                    proc(d1g,
1841                         fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
1842                         fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY,
1843                         glyph);
1844                }
1845                pos += scalarsPerPosition;
1846            }
1847        }
1848    }
1849}
1850
1851#if defined _WIN32 && _MSC_VER >= 1300
1852#pragma warning ( pop )
1853#endif
1854
1855///////////////////////////////////////////////////////////////////////////////
1856
1857#include "SkPathMeasure.h"
1858
1859static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
1860                        SkPathMeasure& meas, const SkMatrix& matrix) {
1861    SkMatrix::MapXYProc proc = matrix.getMapXYProc();
1862
1863    for (int i = 0; i < count; i++) {
1864        SkPoint pos;
1865        SkVector tangent;
1866
1867        proc(matrix, src[i].fX, src[i].fY, &pos);
1868        SkScalar sx = pos.fX;
1869        SkScalar sy = pos.fY;
1870
1871        if (!meas.getPosTan(sx, &pos, &tangent)) {
1872            // set to 0 if the measure failed, so that we just set dst == pos
1873            tangent.set(0, 0);
1874        }
1875
1876        /*  This is the old way (that explains our approach but is way too slow
1877            SkMatrix    matrix;
1878            SkPoint     pt;
1879
1880            pt.set(sx, sy);
1881            matrix.setSinCos(tangent.fY, tangent.fX);
1882            matrix.preTranslate(-sx, 0);
1883            matrix.postTranslate(pos.fX, pos.fY);
1884            matrix.mapPoints(&dst[i], &pt, 1);
1885        */
1886        dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
1887                   pos.fY + SkScalarMul(tangent.fX, sy));
1888    }
1889}
1890
1891/*  TODO
1892
1893    Need differentially more subdivisions when the follow-path is curvy. Not sure how to
1894    determine that, but we need it. I guess a cheap answer is let the caller tell us,
1895    but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
1896*/
1897static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
1898                      const SkMatrix& matrix) {
1899    SkPath::Iter    iter(src, false);
1900    SkPoint         srcP[4], dstP[3];
1901    SkPath::Verb    verb;
1902
1903    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
1904        switch (verb) {
1905            case SkPath::kMove_Verb:
1906                morphpoints(dstP, srcP, 1, meas, matrix);
1907                dst->moveTo(dstP[0]);
1908                break;
1909            case SkPath::kLine_Verb:
1910                // turn lines into quads to look bendy
1911                srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
1912                srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
1913                morphpoints(dstP, srcP, 2, meas, matrix);
1914                dst->quadTo(dstP[0], dstP[1]);
1915                break;
1916            case SkPath::kQuad_Verb:
1917                morphpoints(dstP, &srcP[1], 2, meas, matrix);
1918                dst->quadTo(dstP[0], dstP[1]);
1919                break;
1920            case SkPath::kCubic_Verb:
1921                morphpoints(dstP, &srcP[1], 3, meas, matrix);
1922                dst->cubicTo(dstP[0], dstP[1], dstP[2]);
1923                break;
1924            case SkPath::kClose_Verb:
1925                dst->close();
1926                break;
1927            default:
1928                SkDEBUGFAIL("unknown verb");
1929                break;
1930        }
1931    }
1932}
1933
1934void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
1935                            const SkPath& follow, const SkMatrix* matrix,
1936                            const SkPaint& paint) const {
1937    SkASSERT(byteLength == 0 || text != NULL);
1938
1939    // nothing to draw
1940    if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
1941        return;
1942    }
1943
1944    SkTextToPathIter    iter(text, byteLength, paint, true);
1945    SkPathMeasure       meas(follow, false);
1946    SkScalar            hOffset = 0;
1947
1948    // need to measure first
1949    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1950        SkScalar pathLen = meas.getLength();
1951        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1952            pathLen = SkScalarHalf(pathLen);
1953        }
1954        hOffset += pathLen;
1955    }
1956
1957    const SkPath*   iterPath;
1958    SkScalar        xpos;
1959    SkMatrix        scaledMatrix;
1960    SkScalar        scale = iter.getPathScale();
1961
1962    scaledMatrix.setScale(scale, scale);
1963
1964    while (iter.next(&iterPath, &xpos)) {
1965        if (iterPath) {
1966            SkPath      tmp;
1967            SkMatrix    m(scaledMatrix);
1968
1969            tmp.setIsVolatile(true);
1970            m.postTranslate(xpos + hOffset, 0);
1971            if (matrix) {
1972                m.postConcat(*matrix);
1973            }
1974            morphpath(&tmp, *iterPath, meas, m);
1975            if (fDevice) {
1976                fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
1977            } else {
1978                this->drawPath(tmp, iter.getPaint(), NULL, true);
1979            }
1980        }
1981    }
1982}
1983
1984///////////////////////////////////////////////////////////////////////////////
1985
1986typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
1987                         SkBlitter*);
1988
1989static HairProc ChooseHairProc(bool doAntiAlias) {
1990    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
1991}
1992
1993static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
1994                              const SkPoint texs[], SkMatrix* matrix) {
1995    SkPoint src[3], dst[3];
1996
1997    src[0] = texs[state.f0];
1998    src[1] = texs[state.f1];
1999    src[2] = texs[state.f2];
2000    dst[0] = verts[state.f0];
2001    dst[1] = verts[state.f1];
2002    dst[2] = verts[state.f2];
2003    return matrix->setPolyToPoly(src, dst, 3);
2004}
2005
2006class SkTriColorShader : public SkShader {
2007public:
2008    SkTriColorShader() {}
2009
2010    size_t contextSize() const SK_OVERRIDE;
2011
2012    class TriColorShaderContext : public SkShader::Context {
2013    public:
2014        TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&);
2015        virtual ~TriColorShaderContext();
2016
2017        bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2018
2019        void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
2020
2021    private:
2022        SkMatrix    fDstToUnit;
2023        SkPMColor   fColors[3];
2024
2025        typedef SkShader::Context INHERITED;
2026    };
2027
2028    SK_TO_STRING_OVERRIDE()
2029
2030    // For serialization.  This will never be called.
2031    Factory getFactory() const SK_OVERRIDE { sk_throw(); return NULL; }
2032
2033protected:
2034    Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE {
2035        return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec));
2036    }
2037
2038private:
2039    typedef SkShader INHERITED;
2040};
2041
2042bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[],
2043                                                    int index0, int index1, int index2) {
2044
2045    fColors[0] = SkPreMultiplyColor(colors[index0]);
2046    fColors[1] = SkPreMultiplyColor(colors[index1]);
2047    fColors[2] = SkPreMultiplyColor(colors[index2]);
2048
2049    SkMatrix m, im;
2050    m.reset();
2051    m.set(0, pts[index1].fX - pts[index0].fX);
2052    m.set(1, pts[index2].fX - pts[index0].fX);
2053    m.set(2, pts[index0].fX);
2054    m.set(3, pts[index1].fY - pts[index0].fY);
2055    m.set(4, pts[index2].fY - pts[index0].fY);
2056    m.set(5, pts[index0].fY);
2057    if (!m.invert(&im)) {
2058        return false;
2059    }
2060    // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix
2061    // as our interators are intrinsically tied to the vertices, and nothing else.
2062    SkMatrix ctmInv;
2063    if (!this->getCTM().invert(&ctmInv)) {
2064        return false;
2065    }
2066    fDstToUnit.setConcat(im, ctmInv);
2067    return true;
2068}
2069
2070#include "SkColorPriv.h"
2071#include "SkComposeShader.h"
2072
2073static int ScalarTo256(SkScalar v) {
2074    int scale = SkScalarToFixed(v) >> 8;
2075    if (scale < 0) {
2076        scale = 0;
2077    }
2078    if (scale > 255) {
2079        scale = 255;
2080    }
2081    return SkAlpha255To256(scale);
2082}
2083
2084
2085SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader,
2086                                                               const ContextRec& rec)
2087    : INHERITED(shader, rec) {}
2088
2089SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {}
2090
2091size_t SkTriColorShader::contextSize() const {
2092    return sizeof(TriColorShaderContext);
2093}
2094void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2095    const int alphaScale = Sk255To256(this->getPaintAlpha());
2096
2097    SkPoint src;
2098
2099    for (int i = 0; i < count; i++) {
2100        fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2101        x += 1;
2102
2103        int scale1 = ScalarTo256(src.fX);
2104        int scale2 = ScalarTo256(src.fY);
2105        int scale0 = 256 - scale1 - scale2;
2106        if (scale0 < 0) {
2107            if (scale1 > scale2) {
2108                scale2 = 256 - scale1;
2109            } else {
2110                scale1 = 256 - scale2;
2111            }
2112            scale0 = 0;
2113        }
2114
2115        if (256 != alphaScale) {
2116            scale0 = SkAlphaMul(scale0, alphaScale);
2117            scale1 = SkAlphaMul(scale1, alphaScale);
2118            scale2 = SkAlphaMul(scale2, alphaScale);
2119        }
2120
2121        dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2122                  SkAlphaMulQ(fColors[1], scale1) +
2123                  SkAlphaMulQ(fColors[2], scale2);
2124    }
2125}
2126
2127#ifndef SK_IGNORE_TO_STRING
2128void SkTriColorShader::toString(SkString* str) const {
2129    str->append("SkTriColorShader: (");
2130
2131    this->INHERITED::toString(str);
2132
2133    str->append(")");
2134}
2135#endif
2136
2137void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2138                          const SkPoint vertices[], const SkPoint textures[],
2139                          const SkColor colors[], SkXfermode* xmode,
2140                          const uint16_t indices[], int indexCount,
2141                          const SkPaint& paint) const {
2142    SkASSERT(0 == count || vertices);
2143
2144    // abort early if there is nothing to draw
2145    if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
2146        return;
2147    }
2148
2149    // transform out vertices into device coordinates
2150    SkAutoSTMalloc<16, SkPoint> storage(count);
2151    SkPoint* devVerts = storage.get();
2152    fMatrix->mapPoints(devVerts, vertices, count);
2153
2154    /*
2155        We can draw the vertices in 1 of 4 ways:
2156
2157        - solid color (no shader/texture[], no colors[])
2158        - just colors (no shader/texture[], has colors[])
2159        - just texture (has shader/texture[], no colors[])
2160        - colors * texture (has shader/texture[], has colors[])
2161
2162        Thus for texture drawing, we need both texture[] and a shader.
2163    */
2164
2165    SkTriColorShader triShader; // must be above declaration of p
2166    SkPaint p(paint);
2167
2168    SkShader* shader = p.getShader();
2169    if (NULL == shader) {
2170        // if we have no shader, we ignore the texture coordinates
2171        textures = NULL;
2172    } else if (NULL == textures) {
2173        // if we don't have texture coordinates, ignore the shader
2174        p.setShader(NULL);
2175        shader = NULL;
2176    }
2177
2178    // setup the custom shader (if needed)
2179    SkAutoTUnref<SkComposeShader> composeShader;
2180    if (colors) {
2181        if (NULL == textures) {
2182            // just colors (no texture)
2183            shader = p.setShader(&triShader);
2184        } else {
2185            // colors * texture
2186            SkASSERT(shader);
2187            bool releaseMode = false;
2188            if (NULL == xmode) {
2189                xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
2190                releaseMode = true;
2191            }
2192            composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode)));
2193            p.setShader(composeShader);
2194            if (releaseMode) {
2195                xmode->unref();
2196            }
2197        }
2198    }
2199
2200    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2201    // Abort early if we failed to create a shader context.
2202    if (blitter->isNullBlitter()) {
2203        return;
2204    }
2205
2206    // setup our state and function pointer for iterating triangles
2207    VertState       state(count, indices, indexCount);
2208    VertState::Proc vertProc = state.chooseProc(vmode);
2209
2210    if (textures || colors) {
2211        while (vertProc(&state)) {
2212            if (textures) {
2213                SkMatrix tempM;
2214                if (texture_to_matrix(state, vertices, textures, &tempM)) {
2215                    SkShader::ContextRec rec(*fBitmap, p, *fMatrix);
2216                    rec.fLocalMatrix = &tempM;
2217                    if (!blitter->resetShaderContext(rec)) {
2218                        continue;
2219                    }
2220                }
2221            }
2222            if (colors) {
2223                // Find the context for triShader.
2224                SkTriColorShader::TriColorShaderContext* triColorShaderContext;
2225
2226                SkShader::Context* shaderContext = blitter->getShaderContext();
2227                SkASSERT(shaderContext);
2228                if (p.getShader() == &triShader) {
2229                    triColorShaderContext =
2230                            static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext);
2231                } else {
2232                    // The shader is a compose shader and triShader is its first shader.
2233                    SkASSERT(p.getShader() == composeShader);
2234                    SkASSERT(composeShader->getShaderA() == &triShader);
2235                    SkComposeShader::ComposeShaderContext* composeShaderContext =
2236                            static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext);
2237                    SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA();
2238                    triColorShaderContext =
2239                            static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA);
2240                }
2241
2242                if (!triColorShaderContext->setup(vertices, colors,
2243                                                  state.f0, state.f1, state.f2)) {
2244                    continue;
2245                }
2246            }
2247
2248            SkPoint tmp[] = {
2249                devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
2250            };
2251            SkScan::FillTriangle(tmp, *fRC, blitter.get());
2252        }
2253    } else {
2254        // no colors[] and no texture, stroke hairlines with paint's color.
2255        HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2256        const SkRasterClip& clip = *fRC;
2257        while (vertProc(&state)) {
2258            hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
2259            hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
2260            hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
2261        }
2262    }
2263}
2264
2265///////////////////////////////////////////////////////////////////////////////
2266///////////////////////////////////////////////////////////////////////////////
2267
2268#ifdef SK_DEBUG
2269
2270void SkDraw::validate() const {
2271    SkASSERT(fBitmap != NULL);
2272    SkASSERT(fMatrix != NULL);
2273    SkASSERT(fClip != NULL);
2274    SkASSERT(fRC != NULL);
2275
2276    const SkIRect&  cr = fRC->getBounds();
2277    SkIRect         br;
2278
2279    br.set(0, 0, fBitmap->width(), fBitmap->height());
2280    SkASSERT(cr.isEmpty() || br.contains(cr));
2281}
2282
2283#endif
2284
2285////////////////////////////////////////////////////////////////////////////////////////////////
2286
2287#include "SkPath.h"
2288#include "SkDraw.h"
2289#include "SkRegion.h"
2290#include "SkBlitter.h"
2291
2292static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2293                           const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2294                           SkIRect* bounds) {
2295    if (devPath.isEmpty()) {
2296        return false;
2297    }
2298
2299    //  init our bounds from the path
2300    {
2301        SkRect pathBounds = devPath.getBounds();
2302        pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2303        pathBounds.roundOut(bounds);
2304    }
2305
2306    SkIPoint margin = SkIPoint::Make(0, 0);
2307    if (filter) {
2308        SkASSERT(filterMatrix);
2309
2310        SkMask srcM, dstM;
2311
2312        srcM.fBounds = *bounds;
2313        srcM.fFormat = SkMask::kA8_Format;
2314        srcM.fImage = NULL;
2315        if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2316            return false;
2317        }
2318    }
2319
2320    // (possibly) trim the bounds to reflect the clip
2321    // (plus whatever slop the filter needs)
2322    if (clipBounds) {
2323        SkIRect tmp = *clipBounds;
2324        // Ugh. Guard against gigantic margins from wacky filters. Without this
2325        // check we can request arbitrary amounts of slop beyond our visible
2326        // clip, and bring down the renderer (at least on finite RAM machines
2327        // like handsets, etc.). Need to balance this invented value between
2328        // quality of large filters like blurs, and the corresponding memory
2329        // requests.
2330        static const int MAX_MARGIN = 128;
2331        tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2332                  -SkMin32(margin.fY, MAX_MARGIN));
2333        if (!bounds->intersect(tmp)) {
2334            return false;
2335        }
2336    }
2337
2338    return true;
2339}
2340
2341static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
2342                           SkPaint::Style style) {
2343    SkBitmap        bm;
2344    SkDraw          draw;
2345    SkRasterClip    clip;
2346    SkMatrix        matrix;
2347    SkPaint         paint;
2348
2349    bm.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
2350                     mask.fImage, mask.fRowBytes);
2351
2352    clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
2353    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2354                        -SkIntToScalar(mask.fBounds.fTop));
2355
2356    draw.fBitmap    = &bm;
2357    draw.fRC        = &clip;
2358    draw.fClip      = &clip.bwRgn();
2359    draw.fMatrix    = &matrix;
2360    paint.setAntiAlias(true);
2361    paint.setStyle(style);
2362    draw.drawPath(devPath, paint);
2363}
2364
2365bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2366                        const SkMaskFilter* filter, const SkMatrix* filterMatrix,
2367                        SkMask* mask, SkMask::CreateMode mode,
2368                        SkPaint::Style style) {
2369    if (SkMask::kJustRenderImage_CreateMode != mode) {
2370        if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2371            return false;
2372    }
2373
2374    if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2375        mask->fFormat = SkMask::kA8_Format;
2376        mask->fRowBytes = mask->fBounds.width();
2377        size_t size = mask->computeImageSize();
2378        if (0 == size) {
2379            // we're too big to allocate the mask, abort
2380            return false;
2381        }
2382        mask->fImage = SkMask::AllocImage(size);
2383        memset(mask->fImage, 0, mask->computeImageSize());
2384    }
2385
2386    if (SkMask::kJustComputeBounds_CreateMode != mode) {
2387        draw_into_mask(*mask, devPath, style);
2388    }
2389
2390    return true;
2391}
2392