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