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