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