SkDraw.cpp revision 99a45d3b5a2f492b3ee3d5d8c8baa52745c4b2fa
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(fBitmap->width(), fBitmap->height());)
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(fBitmap->width(), fBitmap->height());)
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(fBitmap->width(), fBitmap->height());)
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    // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
710    // case we are also hairline (if we've gotten to here), which devolves to
711    // effectively just kFill
712    if (paint.getStyle() != SkPaint::kStroke_Style) {
713        if (paint.isAntiAlias()) {
714            SkScan::AntiFillRect(devRect, clip, blitter);
715        } else {
716            SkScan::FillRect(devRect, clip, blitter);
717        }
718    } else {
719        if (paint.isAntiAlias()) {
720            SkScan::AntiHairRect(devRect, clip, blitter);
721        } else {
722            SkScan::HairRect(devRect, clip, blitter);
723        }
724    }
725}
726
727void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
728    if (srcM.fBounds.isEmpty()) {
729        return;
730    }
731
732    SkMask          dstM;
733    const SkMask*   mask = &srcM;
734
735    dstM.fImage = NULL;
736    SkAutoMaskImage ami(&dstM, false);
737
738    if (paint.getMaskFilter() &&
739            paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
740        mask = &dstM;
741    }
742
743    if (fBounder && !fBounder->doIRect(mask->fBounds)) {
744        return;
745    }
746
747    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
748
749    blitter->blitMaskRegion(*mask, *fClip);
750}
751
752class SkAutoPaintRestoreColorStrokeWidth {
753public:
754    SkAutoPaintRestoreColorStrokeWidth(const SkPaint& paint) {
755        fPaint = (SkPaint*)&paint;
756        fColor = paint.getColor();
757        fWidth = paint.getStrokeWidth();
758    }
759    ~SkAutoPaintRestoreColorStrokeWidth() {
760        fPaint->setColor(fColor);
761        fPaint->setStrokeWidth(fWidth);
762    }
763
764private:
765    SkPaint*    fPaint;
766    SkColor     fColor;
767    SkScalar    fWidth;
768};
769
770static SkScalar fast_len(const SkVector& vec) {
771    SkScalar x = SkScalarAbs(vec.fX);
772    SkScalar y = SkScalarAbs(vec.fY);
773    if (x < y) {
774        SkTSwap(x, y);
775    }
776    return x + SkScalarHalf(y);
777}
778
779// our idea is to return true if there is no appreciable skew or non-square scale
780// for that we'll transform (0,1) and (1,0), and check that the resulting dot-prod
781// is nearly one
782static bool map_radius(const SkMatrix& matrix, SkScalar* value) {
783    if (matrix.getType() & SkMatrix::kPerspective_Mask) {
784        return false;
785    }
786    SkVector src[2], dst[2];
787    src[0].set(*value, 0);
788    src[1].set(0, *value);
789    matrix.mapVectors(dst, src, 2);
790    SkScalar len0 = fast_len(dst[0]);
791    SkScalar len1 = fast_len(dst[1]);
792    if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
793        *value = SkScalarAve(len0, len1);
794        return true;
795    }
796    return false;
797}
798
799void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint,
800                      const SkMatrix* prePathMatrix, bool pathIsMutable) const {
801    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
802
803    // nothing to draw
804    if (fClip->isEmpty() ||
805        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
806        return;
807    }
808
809    SkPath*         pathPtr = (SkPath*)&origSrcPath;
810    bool            doFill = true;
811    SkPath          tmpPath;
812    SkMatrix        tmpMatrix;
813    const SkMatrix* matrix = fMatrix;
814
815    if (prePathMatrix) {
816        if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style ||
817                paint.getRasterizer()) {
818            SkPath* result = pathPtr;
819
820            if (!pathIsMutable) {
821                result = &tmpPath;
822                pathIsMutable = true;
823            }
824            pathPtr->transform(*prePathMatrix, result);
825            pathPtr = result;
826        } else {
827            if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
828                // overflow
829                return;
830            }
831            matrix = &tmpMatrix;
832        }
833    }
834    // at this point we're done with prePathMatrix
835    SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
836
837    /*
838        If the device thickness < 1.0, then make it a hairline, and
839        modulate alpha if the thickness is even smaller (e.g. thickness == 0.5
840        should modulate the alpha by 1/2)
841    */
842
843    SkAutoPaintRestoreColorStrokeWidth aprc(paint);
844
845    // can we approximate a thin (but not hairline) stroke with an alpha-modulated
846    // hairline? Only if the matrix scales evenly in X and Y, and the device-width is
847    // less than a pixel
848    if (paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) {
849        SkScalar width = paint.getStrokeWidth();
850        if (width > 0 && map_radius(*matrix, &width)) {
851            int scale = (int)SkScalarMul(width, 256);
852            int alpha = paint.getAlpha() * scale >> 8;
853
854            // pretend to be a hairline, with a modulated alpha
855            ((SkPaint*)&paint)->setAlpha(alpha);
856            ((SkPaint*)&paint)->setStrokeWidth(0);
857        }
858    }
859
860    if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
861        doFill = paint.getFillPath(*pathPtr, &tmpPath);
862        pathPtr = &tmpPath;
863    }
864
865    if (paint.getRasterizer()) {
866        SkMask  mask;
867        if (paint.getRasterizer()->rasterize(*pathPtr, *matrix,
868                            &fClip->getBounds(), paint.getMaskFilter(), &mask,
869                            SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
870            this->drawDevMask(mask, paint);
871            SkMask::FreeImage(mask.fImage);
872        }
873        return;
874    }
875
876    // avoid possibly allocating a new path in transform if we can
877    SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
878
879    // transform the path into device space
880    pathPtr->transform(*matrix, devPathPtr);
881
882    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
883
884    // how does filterPath() know to fill or hairline the path??? <mrr>
885    if (paint.getMaskFilter() &&
886            paint.getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fClip,
887                                              fBounder, blitter.get())) {
888        return; // filterPath() called the blitter, so we're done
889    }
890
891    if (fBounder && !fBounder->doPath(*devPathPtr, paint, doFill)) {
892        return;
893    }
894
895    if (doFill) {
896        if (paint.isAntiAlias()) {
897            SkScan::AntiFillPath(*devPathPtr, *fClip, blitter.get());
898        } else {
899            SkScan::FillPath(*devPathPtr, *fClip, blitter.get());
900        }
901    } else {    // hairline
902        if (paint.isAntiAlias()) {
903            SkScan::AntiHairPath(*devPathPtr, fClip, blitter.get());
904        } else {
905            SkScan::HairPath(*devPathPtr, fClip, blitter.get());
906        }
907    }
908}
909
910/** For the purposes of drawing bitmaps, if a matrix is "almost" translate
911    go ahead and treat it as if it were, so that subsequent code can go fast.
912 */
913static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
914    SkMatrix::TypeMask mask = matrix.getType();
915
916    if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
917        return false;
918    }
919    if (mask & SkMatrix::kScale_Mask) {
920        SkScalar sx = matrix[SkMatrix::kMScaleX];
921        SkScalar sy = matrix[SkMatrix::kMScaleY];
922        int w = bitmap.width();
923        int h = bitmap.height();
924        int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w)));
925        int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h)));
926        return sw == w && sh == h;
927    }
928    // if we got here, we're either kTranslate_Mask or identity
929    return true;
930}
931
932void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
933                              const SkPaint& paint) const {
934    SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config);
935
936    if (just_translate(*fMatrix, bitmap)) {
937        int ix = SkScalarRound(fMatrix->getTranslateX());
938        int iy = SkScalarRound(fMatrix->getTranslateY());
939
940        SkMask  mask;
941        mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
942        mask.fFormat = SkMask::kA8_Format;
943        mask.fRowBytes = bitmap.rowBytes();
944        mask.fImage = bitmap.getAddr8(0, 0);
945
946        this->drawDevMask(mask, paint);
947    } else {    // need to xform the bitmap first
948        SkRect  r;
949        SkMask  mask;
950
951        r.set(0, 0,
952              SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
953        fMatrix->mapRect(&r);
954        r.round(&mask.fBounds);
955
956        // set the mask's bounds to the transformed bitmap-bounds,
957        // clipped to the actual device
958        {
959            SkIRect    devBounds;
960            devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
961            // need intersect(l, t, r, b) on irect
962            if (!mask.fBounds.intersect(devBounds)) {
963                return;
964            }
965        }
966
967        mask.fFormat = SkMask::kA8_Format;
968        mask.fRowBytes = SkAlign4(mask.fBounds.width());
969        size_t size = mask.computeImageSize();
970        if (0 == size) {
971            // the mask is too big to allocated, draw nothing
972            return;
973        }
974
975        // allocate (and clear) our temp buffer to hold the transformed bitmap
976        SkAutoMalloc    storage(size);
977        mask.fImage = (uint8_t*)storage.get();
978        memset(mask.fImage, 0, size);
979
980        // now draw our bitmap(src) into mask(dst), transformed by the matrix
981        {
982            SkBitmap    device;
983            device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
984                             mask.fBounds.height(), mask.fRowBytes);
985            device.setPixels(mask.fImage);
986
987            SkCanvas c(device);
988            // need the unclipped top/left for the translate
989            c.translate(-SkIntToScalar(mask.fBounds.fLeft),
990                        -SkIntToScalar(mask.fBounds.fTop));
991            c.concat(*fMatrix);
992
993            // We can't call drawBitmap, or we'll infinitely recurse. Instead
994            // we manually build a shader and draw that into our new mask
995            SkPaint tmpPaint;
996            tmpPaint.setFlags(paint.getFlags());
997            SkAutoBitmapShaderInstall   install(bitmap, &tmpPaint);
998            SkRect rr;
999            rr.set(0, 0, SkIntToScalar(bitmap.width()),
1000                   SkIntToScalar(bitmap.height()));
1001            c.drawRect(rr, tmpPaint);
1002        }
1003        this->drawDevMask(mask, paint);
1004    }
1005}
1006
1007static bool clipped_out(const SkMatrix& m, const SkRegion& c,
1008                        const SkRect& srcR) {
1009    SkRect  dstR;
1010    SkIRect devIR;
1011
1012    m.mapRect(&dstR, srcR);
1013    dstR.roundOut(&devIR);
1014    return c.quickReject(devIR);
1015}
1016
1017static bool clipped_out(const SkMatrix& matrix, const SkRegion& clip,
1018                        int width, int height) {
1019    SkRect  r;
1020    r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
1021    return clipped_out(matrix, clip, r);
1022}
1023
1024void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
1025                        const SkPaint& paint) const {
1026    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
1027
1028    // nothing to draw
1029    if (fClip->isEmpty() ||
1030            bitmap.width() == 0 || bitmap.height() == 0 ||
1031            bitmap.getConfig() == SkBitmap::kNo_Config ||
1032            (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1033        return;
1034    }
1035
1036    // run away on too-big bitmaps for now (exceed 16.16)
1037    if (bitmap.width() > 32767 || bitmap.height() > 32767) {
1038        return;
1039    }
1040
1041    SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style);
1042
1043    SkMatrix matrix;
1044    if (!matrix.setConcat(*fMatrix, prematrix)) {
1045        return;
1046    }
1047
1048    if (clipped_out(matrix, *fClip, bitmap.width(), bitmap.height())) {
1049        return;
1050    }
1051
1052    if (fBounder && just_translate(matrix, bitmap)) {
1053        SkIRect ir;
1054        int32_t ix = SkScalarRound(matrix.getTranslateX());
1055        int32_t iy = SkScalarRound(matrix.getTranslateY());
1056        ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1057        if (!fBounder->doIRect(ir)) {
1058            return;
1059        }
1060    }
1061
1062    // only lock the pixels if we passed the clip and bounder tests
1063    SkAutoLockPixels alp(bitmap);
1064    // after the lock, check if we are valid
1065    if (!bitmap.readyToDraw()) {
1066        return;
1067    }
1068
1069    if (bitmap.getConfig() != SkBitmap::kA8_Config &&
1070            just_translate(matrix, bitmap)) {
1071        int         ix = SkScalarRound(matrix.getTranslateX());
1072        int         iy = SkScalarRound(matrix.getTranslateY());
1073        uint32_t    storage[kBlitterStorageLongCount];
1074        SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1075                                            ix, iy, storage, sizeof(storage));
1076        if (blitter) {
1077            SkAutoTPlacementDelete<SkBlitter>   ad(blitter, storage);
1078
1079            SkIRect    ir;
1080            ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
1081
1082            SkRegion::Cliperator iter(*fClip, ir);
1083            const SkIRect&       cr = iter.rect();
1084
1085            for (; !iter.done(); iter.next()) {
1086                SkASSERT(!cr.isEmpty());
1087                blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
1088            }
1089            return;
1090        }
1091#if 0
1092        SkDebugf("---- MISSING sprite case: config=%d [%d %d], device=%d, xfer=%p, alpha=0x%X colorFilter=%p\n",
1093                bitmap.config(), bitmap.width(), bitmap.height(), fBitmap->config(),
1094                paint.getXfermode(), paint.getAlpha(), paint.getColorFilter());
1095#endif
1096    }
1097
1098    // now make a temp draw on the stack, and use it
1099    //
1100    SkDraw draw(*this);
1101    draw.fMatrix = &matrix;
1102
1103    if (bitmap.getConfig() == SkBitmap::kA8_Config) {
1104        draw.drawBitmapAsMask(bitmap, paint);
1105    } else {
1106        SkAutoBitmapShaderInstall   install(bitmap, &paint);
1107
1108        SkRect  r;
1109        r.set(0, 0, SkIntToScalar(bitmap.width()),
1110              SkIntToScalar(bitmap.height()));
1111        // is this ok if paint has a rasterizer?
1112        draw.drawRect(r, paint);
1113    }
1114}
1115
1116void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
1117                        const SkPaint& paint) const {
1118    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
1119
1120    // nothing to draw
1121    if (fClip->isEmpty() ||
1122            bitmap.width() == 0 || bitmap.height() == 0 ||
1123            bitmap.getConfig() == SkBitmap::kNo_Config ||
1124            (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1125        return;
1126    }
1127
1128    SkIRect    bounds;
1129    bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
1130
1131    if (fClip->quickReject(bounds)) {
1132        return; // nothing to draw
1133    }
1134
1135    SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style);
1136
1137    if (NULL == paint.getColorFilter()) {
1138        uint32_t    storage[kBlitterStorageLongCount];
1139        SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
1140                                                x, y, storage, sizeof(storage));
1141
1142        if (blitter) {
1143            SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
1144
1145            if (fBounder && !fBounder->doIRect(bounds)) {
1146                return;
1147            }
1148
1149            SkRegion::Cliperator iter(*fClip, bounds);
1150            const SkIRect&       cr = iter.rect();
1151
1152            for (; !iter.done(); iter.next()) {
1153                SkASSERT(!cr.isEmpty());
1154                blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height());
1155            }
1156            return;
1157        }
1158    }
1159
1160    SkAutoBitmapShaderInstall   install(bitmap, &paint);
1161
1162    SkMatrix        matrix;
1163    SkRect          r;
1164
1165    // get a scalar version of our rect
1166    r.set(bounds);
1167
1168    // tell the shader our offset
1169    matrix.setTranslate(r.fLeft, r.fTop);
1170    paint.getShader()->setLocalMatrix(matrix);
1171
1172    SkDraw draw(*this);
1173    matrix.reset();
1174    draw.fMatrix = &matrix;
1175    // call ourself with a rect
1176    // is this OK if paint has a rasterizer?
1177    draw.drawRect(r, paint);
1178}
1179
1180///////////////////////////////////////////////////////////////////////////////
1181
1182#include "SkScalerContext.h"
1183#include "SkGlyphCache.h"
1184#include "SkUtils.h"
1185
1186static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
1187                const char text[], size_t byteLength, SkVector* stopVector) {
1188    SkFixed     x = 0, y = 0;
1189    const char* stop = text + byteLength;
1190
1191    SkAutoKern  autokern;
1192
1193    while (text < stop) {
1194        // don't need x, y here, since all subpixel variants will have the
1195        // same advance
1196        const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1197
1198        x += autokern.adjust(glyph) + glyph.fAdvanceX;
1199        y += glyph.fAdvanceY;
1200    }
1201    stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
1202
1203    SkASSERT(text == stop);
1204}
1205
1206void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
1207                              SkScalar x, SkScalar y,
1208                              const SkPaint& paint) const {
1209    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
1210
1211    SkTextToPathIter iter(text, byteLength, paint, true, true);
1212
1213    SkMatrix    matrix;
1214    matrix.setScale(iter.getPathScale(), iter.getPathScale());
1215    matrix.postTranslate(x, y);
1216
1217    const SkPath* iterPath;
1218    SkScalar xpos, prevXPos = 0;
1219
1220    while ((iterPath = iter.next(&xpos)) != NULL) {
1221        matrix.postTranslate(xpos - prevXPos, 0);
1222        this->drawPath(*iterPath, iter.getPaint(), &matrix, false);
1223        prevXPos = xpos;
1224    }
1225}
1226
1227#define kStdStrikeThru_Offset       (-SK_Scalar1 * 6 / 21)
1228#define kStdUnderline_Offset        (SK_Scalar1 / 9)
1229#define kStdUnderline_Thickness     (SK_Scalar1 / 18)
1230
1231static void draw_paint_rect(const SkDraw* draw, const SkPaint& paint,
1232                            const SkRect& r, SkScalar textSize) {
1233    if (paint.getStyle() == SkPaint::kFill_Style) {
1234        draw->drawRect(r, paint);
1235    } else {
1236        SkPaint p(paint);
1237        p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth()));
1238        draw->drawRect(r, p);
1239    }
1240}
1241
1242static void handle_aftertext(const SkDraw* draw, const SkPaint& paint,
1243                             SkScalar width, const SkPoint& start) {
1244    uint32_t flags = paint.getFlags();
1245
1246    if (flags & (SkPaint::kUnderlineText_Flag |
1247                 SkPaint::kStrikeThruText_Flag)) {
1248        SkScalar textSize = paint.getTextSize();
1249        SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness);
1250        SkRect   r;
1251
1252        r.fLeft = start.fX;
1253        r.fRight = start.fX + width;
1254
1255        if (flags & SkPaint::kUnderlineText_Flag) {
1256            SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset,
1257                                             start.fY);
1258            r.fTop = offset;
1259            r.fBottom = offset + height;
1260            draw_paint_rect(draw, paint, r, textSize);
1261        }
1262        if (flags & SkPaint::kStrikeThruText_Flag) {
1263            SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset,
1264                                             start.fY);
1265            r.fTop = offset;
1266            r.fBottom = offset + height;
1267            draw_paint_rect(draw, paint, r, textSize);
1268        }
1269    }
1270}
1271
1272// disable warning : local variable used without having been initialized
1273#if defined _WIN32 && _MSC_VER >= 1300
1274#pragma warning ( push )
1275#pragma warning ( disable : 4701 )
1276#endif
1277
1278//////////////////////////////////////////////////////////////////////////////
1279
1280static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
1281								   const SkGlyph& glyph, int left, int top) {
1282    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1283	SkASSERT(state.fClip->isRect());
1284	SkASSERT(NULL == state.fBounder);
1285	SkASSERT(state.fClipBounds == state.fClip->getBounds());
1286
1287    left += glyph.fLeft;
1288    top  += glyph.fTop;
1289
1290    int right   = left + glyph.fWidth;
1291    int bottom  = top + glyph.fHeight;
1292
1293	SkMask		mask;
1294	SkIRect		storage;
1295	SkIRect*	bounds = &mask.fBounds;
1296
1297	mask.fBounds.set(left, top, right, bottom);
1298
1299	// this extra test is worth it, assuming that most of the time it succeeds
1300	// since we can avoid writing to storage
1301	if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1302		if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1303			return;
1304		bounds = &storage;
1305	}
1306
1307	uint8_t* aa = (uint8_t*)glyph.fImage;
1308	if (NULL == aa) {
1309		aa = (uint8_t*)state.fCache->findImage(glyph);
1310		if (NULL == aa) {
1311			return; // can't rasterize glyph
1312        }
1313	}
1314
1315	mask.fRowBytes = glyph.rowBytes();
1316	mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1317	mask.fImage = aa;
1318	state.fBlitter->blitMask(mask, *bounds);
1319}
1320
1321static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
1322								  const SkGlyph& glyph, int left, int top) {
1323    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1324	SkASSERT(!state.fClip->isRect());
1325	SkASSERT(NULL == state.fBounder);
1326
1327    SkMask  mask;
1328
1329    left += glyph.fLeft;
1330    top  += glyph.fTop;
1331
1332    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1333	SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1334
1335	if (!clipper.done()) {
1336		const SkIRect&  cr = clipper.rect();
1337		const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1338		if (NULL == aa) {
1339			aa = (uint8_t*)state.fCache->findImage(glyph);
1340			if (NULL == aa) {
1341				return;
1342            }
1343		}
1344
1345		mask.fRowBytes = glyph.rowBytes();
1346		mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1347		mask.fImage = (uint8_t*)aa;
1348		do {
1349			state.fBlitter->blitMask(mask, cr);
1350			clipper.next();
1351		} while (!clipper.done());
1352	}
1353}
1354
1355static void D1G_Bounder(const SkDraw1Glyph& state,
1356						const SkGlyph& glyph, int left, int top) {
1357    SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1358
1359    SkMask  mask;
1360
1361    left += glyph.fLeft;
1362    top  += glyph.fTop;
1363
1364    mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1365    SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1366
1367	if (!clipper.done()) {
1368		const SkIRect&  cr = clipper.rect();
1369		const uint8_t*  aa = (const uint8_t*)glyph.fImage;
1370		if (NULL == aa) {
1371			aa = (uint8_t*)state.fCache->findImage(glyph);
1372			if (NULL == aa) {
1373				return;
1374            }
1375		}
1376
1377        // we need to pass the origin, which we approximate with our
1378        // (unadjusted) left,top coordinates (the caller called fixedfloor)
1379		if (state.fBounder->doIRectGlyph(cr,
1380                                         left - glyph.fLeft,
1381                                         top - glyph.fTop, glyph)) {
1382			mask.fRowBytes = glyph.rowBytes();
1383			mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1384			mask.fImage = (uint8_t*)aa;
1385			do {
1386				state.fBlitter->blitMask(mask, cr);
1387				clipper.next();
1388			} while (!clipper.done());
1389		}
1390	}
1391}
1392
1393SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
1394                                      SkGlyphCache* cache) {
1395    fDraw = draw;
1396	fBounder = draw->fBounder;
1397	fClip = draw->fClip;
1398    fClipBounds = fClip->getBounds();
1399	fBlitter = blitter;
1400	fCache = cache;
1401
1402    if (draw->fProcs && draw->fProcs->fD1GProc) {
1403        return draw->fProcs->fD1GProc;
1404    }
1405
1406    if (NULL == fBounder) {
1407        if (fClip->isRect()) {
1408            return D1G_NoBounder_RectClip;
1409        } else {
1410            return D1G_NoBounder_RgnClip;
1411        }
1412    } else {
1413        return D1G_Bounder;
1414    }
1415}
1416
1417enum RoundBaseline {
1418    kDont_Round_Baseline,
1419    kRound_X_Baseline,
1420    kRound_Y_Baseline
1421};
1422
1423static RoundBaseline computeRoundBaseline(const SkMatrix& mat) {
1424    if (mat[1] == 0 && mat[3] == 0) {
1425        // we're 0 or 180 degrees, round the y coordinate of the baseline
1426        return kRound_Y_Baseline;
1427    } else if (mat[0] == 0 && mat[4] == 0) {
1428        // we're 90 or 270 degrees, round the x coordinate of the baseline
1429        return kRound_X_Baseline;
1430    } else {
1431        return kDont_Round_Baseline;
1432    }
1433}
1434
1435///////////////////////////////////////////////////////////////////////////////
1436
1437void SkDraw::drawText(const char text[], size_t byteLength,
1438                      SkScalar x, SkScalar y, const SkPaint& paint) const {
1439    SkASSERT(byteLength == 0 || text != NULL);
1440
1441    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
1442
1443    // nothing to draw
1444    if (text == NULL || byteLength == 0 ||
1445        fClip->isEmpty() ||
1446        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1447        return;
1448    }
1449
1450    SkScalar    underlineWidth = 0;
1451    SkPoint     underlineStart;
1452
1453    underlineStart.set(0, 0);    // to avoid warning
1454    if (paint.getFlags() & (SkPaint::kUnderlineText_Flag |
1455                            SkPaint::kStrikeThruText_Flag)) {
1456        underlineWidth = paint.measureText(text, byteLength);
1457
1458        SkScalar offsetX = 0;
1459        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1460            offsetX = SkScalarHalf(underlineWidth);
1461        } else if (paint.getTextAlign() == SkPaint::kRight_Align) {
1462            offsetX = underlineWidth;
1463        }
1464        underlineStart.set(x - offsetX, y);
1465    }
1466
1467    if (/*paint.isLinearText() ||*/
1468        (fMatrix->getType() & SkMatrix::kPerspective_Mask)) {
1469        this->drawText_asPaths(text, byteLength, x, y, paint);
1470        handle_aftertext(this, paint, underlineWidth, underlineStart);
1471        return;
1472    }
1473
1474    SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
1475
1476    SkAutoGlyphCache    autoCache(paint, fMatrix);
1477    SkGlyphCache*       cache = autoCache.getCache();
1478    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
1479
1480    // transform our starting point
1481    {
1482        SkPoint loc;
1483        fMatrix->mapXY(x, y, &loc);
1484        x = loc.fX;
1485        y = loc.fY;
1486    }
1487
1488    // need to measure first
1489    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1490        SkVector    stop;
1491
1492        measure_text(cache, glyphCacheProc, text, byteLength, &stop);
1493
1494        SkScalar    stopX = stop.fX;
1495        SkScalar    stopY = stop.fY;
1496
1497        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1498            stopX = SkScalarHalf(stopX);
1499            stopY = SkScalarHalf(stopY);
1500        }
1501        x -= stopX;
1502        y -= stopY;
1503    }
1504
1505    SkFixed fx = SkScalarToFixed(x);
1506    SkFixed fy = SkScalarToFixed(y);
1507    const char* stop = text + byteLength;
1508
1509    if (paint.isSubpixelText()) {
1510        RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
1511        if (kRound_Y_Baseline == roundBaseline) {
1512            fy = (fy + 0x8000) & ~0xFFFF;
1513        } else if (kRound_X_Baseline == roundBaseline) {
1514            fx = (fx + 0x8000) & ~0xFFFF;
1515        }
1516    } else {
1517        // apply the bias here, so we don't have to add 1/2 in the loop
1518        fx += SK_Fixed1/2;
1519        fy += SK_Fixed1/2;
1520    }
1521
1522    SkAutoKern          autokern;
1523	SkDraw1Glyph        d1g;
1524	SkDraw1Glyph::Proc  proc = d1g.init(this, blitter.get(), cache);
1525
1526    while (text < stop) {
1527        const SkGlyph& glyph  = glyphCacheProc(cache, &text, fx, fy);
1528
1529        fx += autokern.adjust(glyph);
1530
1531        if (glyph.fWidth) {
1532			proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
1533        }
1534        fx += glyph.fAdvanceX;
1535        fy += glyph.fAdvanceY;
1536    }
1537
1538    if (underlineWidth) {
1539        autoCache.release();    // release this now to free up the RAM
1540        handle_aftertext(this, paint, underlineWidth, underlineStart);
1541    }
1542}
1543
1544// last parameter is interpreted as SkFixed [x, y]
1545// return the fixed position, which may be rounded or not by the caller
1546//   e.g. subpixel doesn't round
1547typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
1548
1549static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1550                          SkIPoint* dst) {
1551    dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
1552}
1553
1554static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1555                            SkIPoint* dst) {
1556    dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
1557             SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
1558}
1559
1560static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph,
1561                           SkIPoint* dst) {
1562    dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
1563             SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
1564}
1565
1566static AlignProc pick_align_proc(SkPaint::Align align) {
1567    static const AlignProc gProcs[] = {
1568        leftAlignProc, centerAlignProc, rightAlignProc
1569    };
1570
1571    SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
1572
1573    return gProcs[align];
1574}
1575
1576class TextMapState {
1577public:
1578    mutable SkPoint fLoc;
1579
1580    TextMapState(const SkMatrix& matrix, SkScalar y)
1581        : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
1582
1583    typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
1584
1585    Proc pickProc(int scalarsPerPosition);
1586
1587private:
1588    const SkMatrix&     fMatrix;
1589    SkMatrix::MapXYProc fProc;
1590    SkScalar            fY; // ignored by MapXYProc
1591    // these are only used by Only... procs
1592    SkScalar            fScaleX, fTransX, fTransformedY;
1593
1594    static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
1595        state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
1596    }
1597
1598    static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
1599        state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
1600    }
1601
1602    static void MapOnlyScaleXProc(const TextMapState& state,
1603                                  const SkScalar pos[]) {
1604        state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
1605                       state.fTransformedY);
1606    }
1607
1608    static void MapOnlyTransXProc(const TextMapState& state,
1609                                  const SkScalar pos[]) {
1610        state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
1611    }
1612};
1613
1614TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
1615    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1616
1617    if (1 == scalarsPerPosition) {
1618        unsigned mtype = fMatrix.getType();
1619        if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
1620            return MapXProc;
1621        } else {
1622            fScaleX = fMatrix.getScaleX();
1623            fTransX = fMatrix.getTranslateX();
1624            fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
1625                            fMatrix.getTranslateY();
1626            return (mtype & SkMatrix::kScale_Mask) ?
1627                        MapOnlyScaleXProc : MapOnlyTransXProc;
1628        }
1629    } else {
1630        return MapXYProc;
1631    }
1632}
1633
1634//////////////////////////////////////////////////////////////////////////////
1635
1636void SkDraw::drawPosText(const char text[], size_t byteLength,
1637                         const SkScalar pos[], SkScalar constY,
1638                         int scalarsPerPosition, const SkPaint& paint) const {
1639    SkASSERT(byteLength == 0 || text != NULL);
1640    SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
1641
1642    SkDEBUGCODE(this->validate(fBitmap->width(), fBitmap->height());)
1643
1644    // nothing to draw
1645    if (text == NULL || byteLength == 0 ||
1646        fClip->isEmpty() ||
1647        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1648        return;
1649    }
1650
1651    if (/*paint.isLinearText() ||*/
1652        (fMatrix->getType() & SkMatrix::kPerspective_Mask)) {
1653        // TODO !!!!
1654//      this->drawText_asPaths(text, byteLength, x, y, paint);
1655        return;
1656    }
1657
1658    SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
1659    SkAutoGlyphCache    autoCache(paint, fMatrix);
1660    SkGlyphCache*       cache = autoCache.getCache();
1661    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
1662
1663    const char*        stop = text + byteLength;
1664    AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
1665	SkDraw1Glyph	   d1g;
1666	SkDraw1Glyph::Proc  proc = d1g.init(this, blitter.get(), cache);
1667    TextMapState       tms(*fMatrix, constY);
1668    TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
1669
1670    if (paint.isSubpixelText()) {
1671        // maybe we should skip the rounding if linearText is set
1672        RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix);
1673
1674        if (SkPaint::kLeft_Align == paint.getTextAlign()) {
1675            while (text < stop) {
1676                tmsProc(tms, pos);
1677
1678                SkFixed fx = SkScalarToFixed(tms.fLoc.fX);
1679                SkFixed fy = SkScalarToFixed(tms.fLoc.fY);
1680
1681                if (kRound_Y_Baseline == roundBaseline) {
1682                    fy = (fy + 0x8000) & ~0xFFFF;
1683                } else if (kRound_X_Baseline == roundBaseline) {
1684                    fx = (fx + 0x8000) & ~0xFFFF;
1685                }
1686
1687                const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy);
1688
1689                if (glyph.fWidth) {
1690                    proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy));
1691                }
1692                pos += scalarsPerPosition;
1693            }
1694        } else {
1695            while (text < stop) {
1696                const SkGlyph* glyph = &glyphCacheProc(cache, &text, 0, 0);
1697
1698                if (glyph->fWidth) {
1699                    SkDEBUGCODE(SkFixed prevAdvX = glyph->fAdvanceX;)
1700                    SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;)
1701
1702                    SkFixed fx, fy;
1703                    tmsProc(tms, pos);
1704
1705                    {
1706                        SkIPoint fixedLoc;
1707                        alignProc(tms.fLoc, *glyph, &fixedLoc);
1708                        fx = fixedLoc.fX;
1709                        fy = fixedLoc.fY;
1710
1711                        if (kRound_Y_Baseline == roundBaseline) {
1712                            fy = (fy + 0x8000) & ~0xFFFF;
1713                        } else if (kRound_X_Baseline == roundBaseline) {
1714                            fx = (fx + 0x8000) & ~0xFFFF;
1715                        }
1716                    }
1717
1718                    // have to call again, now that we've been "aligned"
1719                    glyph = &glyphCacheProc(cache, &text, fx, fy);
1720                    // the assumption is that the advance hasn't changed
1721                    SkASSERT(prevAdvX == glyph->fAdvanceX);
1722                    SkASSERT(prevAdvY == glyph->fAdvanceY);
1723
1724                    proc(d1g, *glyph, SkFixedFloor(fx), SkFixedFloor(fy));
1725                }
1726                pos += scalarsPerPosition;
1727            }
1728        }
1729    } else {    // not subpixel
1730        while (text < stop) {
1731            // the last 2 parameters are ignored
1732            const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
1733
1734            if (glyph.fWidth) {
1735                tmsProc(tms, pos);
1736
1737                SkIPoint fixedLoc;
1738                alignProc(tms.fLoc, glyph, &fixedLoc);
1739
1740                proc(d1g, glyph,
1741                     SkFixedRound(fixedLoc.fX), SkFixedRound(fixedLoc.fY));
1742            }
1743            pos += scalarsPerPosition;
1744        }
1745    }
1746}
1747
1748#if defined _WIN32 && _MSC_VER >= 1300
1749#pragma warning ( pop )
1750#endif
1751
1752///////////////////////////////////////////////////////////////////////////////
1753
1754#include "SkPathMeasure.h"
1755
1756static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
1757                        SkPathMeasure& meas, const SkMatrix& matrix) {
1758    SkMatrix::MapXYProc proc = matrix.getMapXYProc();
1759
1760    for (int i = 0; i < count; i++) {
1761        SkPoint pos;
1762        SkVector tangent;
1763
1764        proc(matrix, src[i].fX, src[i].fY, &pos);
1765        SkScalar sx = pos.fX;
1766        SkScalar sy = pos.fY;
1767
1768        meas.getPosTan(sx, &pos, &tangent);
1769
1770        /*  This is the old way (that explains our approach but is way too slow
1771            SkMatrix    matrix;
1772            SkPoint     pt;
1773
1774            pt.set(sx, sy);
1775            matrix.setSinCos(tangent.fY, tangent.fX);
1776            matrix.preTranslate(-sx, 0);
1777            matrix.postTranslate(pos.fX, pos.fY);
1778            matrix.mapPoints(&dst[i], &pt, 1);
1779        */
1780        dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
1781                   pos.fY + SkScalarMul(tangent.fX, sy));
1782    }
1783}
1784
1785/*  TODO
1786
1787    Need differentially more subdivisions when the follow-path is curvy. Not sure how to
1788    determine that, but we need it. I guess a cheap answer is let the caller tell us,
1789    but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
1790*/
1791static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
1792                      const SkMatrix& matrix) {
1793    SkPath::Iter    iter(src, false);
1794    SkPoint         srcP[4], dstP[3];
1795    SkPath::Verb    verb;
1796
1797    while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
1798        switch (verb) {
1799            case SkPath::kMove_Verb:
1800                morphpoints(dstP, srcP, 1, meas, matrix);
1801                dst->moveTo(dstP[0]);
1802                break;
1803            case SkPath::kLine_Verb:
1804                // turn lines into quads to look bendy
1805                srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
1806                srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
1807                morphpoints(dstP, srcP, 2, meas, matrix);
1808                dst->quadTo(dstP[0], dstP[1]);
1809                break;
1810            case SkPath::kQuad_Verb:
1811                morphpoints(dstP, &srcP[1], 2, meas, matrix);
1812                dst->quadTo(dstP[0], dstP[1]);
1813                break;
1814            case SkPath::kCubic_Verb:
1815                morphpoints(dstP, &srcP[1], 3, meas, matrix);
1816                dst->cubicTo(dstP[0], dstP[1], dstP[2]);
1817                break;
1818            case SkPath::kClose_Verb:
1819                dst->close();
1820                break;
1821            default:
1822                SkASSERT(!"unknown verb");
1823                break;
1824        }
1825    }
1826}
1827
1828void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
1829                            const SkPath& follow, const SkMatrix* matrix,
1830                            const SkPaint& paint) const {
1831    SkASSERT(byteLength == 0 || text != NULL);
1832
1833    // nothing to draw
1834    if (text == NULL || byteLength == 0 ||
1835        fClip->isEmpty() ||
1836        (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
1837        return;
1838    }
1839
1840    SkTextToPathIter    iter(text, byteLength, paint, true, true);
1841    SkPathMeasure       meas(follow, false);
1842    SkScalar            hOffset = 0;
1843
1844    // need to measure first
1845    if (paint.getTextAlign() != SkPaint::kLeft_Align) {
1846        SkScalar pathLen = meas.getLength();
1847        if (paint.getTextAlign() == SkPaint::kCenter_Align) {
1848            pathLen = SkScalarHalf(pathLen);
1849        }
1850        hOffset += pathLen;
1851    }
1852
1853    const SkPath*   iterPath;
1854    SkScalar        xpos;
1855    SkMatrix        scaledMatrix;
1856    SkScalar        scale = iter.getPathScale();
1857
1858    scaledMatrix.setScale(scale, scale);
1859
1860    while ((iterPath = iter.next(&xpos)) != NULL) {
1861        SkPath      tmp;
1862        SkMatrix    m(scaledMatrix);
1863
1864        m.postTranslate(xpos + hOffset, 0);
1865        if (matrix) {
1866            m.postConcat(*matrix);
1867        }
1868        morphpath(&tmp, *iterPath, meas, m);
1869        this->drawPath(tmp, iter.getPaint());
1870    }
1871}
1872
1873///////////////////////////////////////////////////////////////////////////////
1874
1875struct VertState {
1876    int f0, f1, f2;
1877
1878    VertState(int vCount, const uint16_t indices[], int indexCount)
1879            : fIndices(indices) {
1880        fCurrIndex = 0;
1881        if (indices) {
1882            fCount = indexCount;
1883        } else {
1884            fCount = vCount;
1885        }
1886    }
1887
1888    typedef bool (*Proc)(VertState*);
1889    Proc chooseProc(SkCanvas::VertexMode mode);
1890
1891private:
1892    int             fCount;
1893    int             fCurrIndex;
1894    const uint16_t* fIndices;
1895
1896    static bool Triangles(VertState*);
1897    static bool TrianglesX(VertState*);
1898    static bool TriangleStrip(VertState*);
1899    static bool TriangleStripX(VertState*);
1900    static bool TriangleFan(VertState*);
1901    static bool TriangleFanX(VertState*);
1902};
1903
1904bool VertState::Triangles(VertState* state) {
1905    int index = state->fCurrIndex;
1906    if (index + 3 > state->fCount) {
1907        return false;
1908    }
1909    state->f0 = index + 0;
1910    state->f1 = index + 1;
1911    state->f2 = index + 2;
1912    state->fCurrIndex = index + 3;
1913    return true;
1914}
1915
1916bool VertState::TrianglesX(VertState* state) {
1917    const uint16_t* indices = state->fIndices;
1918    int index = state->fCurrIndex;
1919    if (index + 3 > state->fCount) {
1920        return false;
1921    }
1922    state->f0 = indices[index + 0];
1923    state->f1 = indices[index + 1];
1924    state->f2 = indices[index + 2];
1925    state->fCurrIndex = index + 3;
1926    return true;
1927}
1928
1929bool VertState::TriangleStrip(VertState* state) {
1930    int index = state->fCurrIndex;
1931    if (index + 3 > state->fCount) {
1932        return false;
1933    }
1934    state->f2 = index + 2;
1935    if (index & 1) {
1936        state->f0 = index + 1;
1937        state->f1 = index + 0;
1938    } else {
1939        state->f0 = index + 0;
1940        state->f1 = index + 1;
1941    }
1942    state->fCurrIndex = index + 1;
1943    return true;
1944}
1945
1946bool VertState::TriangleStripX(VertState* state) {
1947    const uint16_t* indices = state->fIndices;
1948    int index = state->fCurrIndex;
1949    if (index + 3 > state->fCount) {
1950        return false;
1951    }
1952    state->f2 = indices[index + 2];
1953    if (index & 1) {
1954        state->f0 = indices[index + 1];
1955        state->f1 = indices[index + 0];
1956    } else {
1957        state->f0 = indices[index + 0];
1958        state->f1 = indices[index + 1];
1959    }
1960    state->fCurrIndex = index + 1;
1961    return true;
1962}
1963
1964bool VertState::TriangleFan(VertState* state) {
1965    int index = state->fCurrIndex;
1966    if (index + 3 > state->fCount) {
1967        return false;
1968    }
1969    state->f0 = 0;
1970    state->f1 = index + 1;
1971    state->f2 = index + 2;
1972    state->fCurrIndex = index + 1;
1973    return true;
1974}
1975
1976bool VertState::TriangleFanX(VertState* state) {
1977    const uint16_t* indices = state->fIndices;
1978    int index = state->fCurrIndex;
1979    if (index + 3 > state->fCount) {
1980        return false;
1981    }
1982    state->f0 = indices[0];
1983    state->f1 = indices[index + 1];
1984    state->f2 = indices[index + 2];
1985    state->fCurrIndex = index + 1;
1986    return true;
1987}
1988
1989VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
1990    switch (mode) {
1991        case SkCanvas::kTriangles_VertexMode:
1992            return fIndices ? TrianglesX : Triangles;
1993        case SkCanvas::kTriangleStrip_VertexMode:
1994            return fIndices ? TriangleStripX : TriangleStrip;
1995        case SkCanvas::kTriangleFan_VertexMode:
1996            return fIndices ? TriangleFanX : TriangleFan;
1997        default:
1998            return NULL;
1999    }
2000}
2001
2002typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRegion*,
2003                         SkBlitter*);
2004
2005static HairProc ChooseHairProc(bool doAntiAlias) {
2006    return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
2007}
2008
2009static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
2010                              const SkPoint texs[], SkMatrix* matrix) {
2011    SkPoint src[3], dst[3];
2012
2013    src[0] = texs[state.f0];
2014    src[1] = texs[state.f1];
2015    src[2] = texs[state.f2];
2016    dst[0] = verts[state.f0];
2017    dst[1] = verts[state.f1];
2018    dst[2] = verts[state.f2];
2019    return matrix->setPolyToPoly(src, dst, 3);
2020}
2021
2022class SkTriColorShader : public SkShader {
2023public:
2024    SkTriColorShader() {}
2025
2026    bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
2027
2028    virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
2029
2030protected:
2031    SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
2032
2033    virtual Factory getFactory() { return CreateProc; }
2034
2035private:
2036    SkMatrix    fDstToUnit;
2037    SkPMColor   fColors[3];
2038
2039    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
2040        return SkNEW_ARGS(SkTriColorShader, (buffer));
2041    }
2042    typedef SkShader INHERITED;
2043};
2044
2045bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
2046                             int index0, int index1, int index2) {
2047
2048    fColors[0] = SkPreMultiplyColor(colors[index0]);
2049    fColors[1] = SkPreMultiplyColor(colors[index1]);
2050    fColors[2] = SkPreMultiplyColor(colors[index2]);
2051
2052    SkMatrix m, im;
2053    m.reset();
2054    m.set(0, pts[index1].fX - pts[index0].fX);
2055    m.set(1, pts[index2].fX - pts[index0].fX);
2056    m.set(2, pts[index0].fX);
2057    m.set(3, pts[index1].fY - pts[index0].fY);
2058    m.set(4, pts[index2].fY - pts[index0].fY);
2059    m.set(5, pts[index0].fY);
2060    if (!m.invert(&im)) {
2061        return false;
2062    }
2063    return fDstToUnit.setConcat(im, this->getTotalInverse());
2064}
2065
2066#include "SkColorPriv.h"
2067#include "SkComposeShader.h"
2068
2069static int ScalarTo256(SkScalar v) {
2070    int scale = SkScalarToFixed(v) >> 8;
2071    if (scale < 0) {
2072        scale = 0;
2073    }
2074    if (scale > 255) {
2075        scale = 255;
2076    }
2077    return SkAlpha255To256(scale);
2078}
2079
2080void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
2081    SkPoint src;
2082
2083    for (int i = 0; i < count; i++) {
2084        fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
2085        x += 1;
2086
2087        int scale1 = ScalarTo256(src.fX);
2088        int scale2 = ScalarTo256(src.fY);
2089        int scale0 = 256 - scale1 - scale2;
2090        if (scale0 < 0) {
2091            if (scale1 > scale2) {
2092                scale2 = 256 - scale1;
2093            } else {
2094                scale1 = 256 - scale2;
2095            }
2096            scale0 = 0;
2097        }
2098
2099        dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
2100        SkAlphaMulQ(fColors[1], scale1) +
2101        SkAlphaMulQ(fColors[2], scale2);
2102    }
2103}
2104
2105void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
2106                          const SkPoint vertices[], const SkPoint textures[],
2107                          const SkColor colors[], SkXfermode* xmode,
2108                          const uint16_t indices[], int indexCount,
2109                          const SkPaint& paint) const {
2110    SkASSERT(0 == count || NULL != vertices);
2111
2112    // abort early if there is nothing to draw
2113    if (count < 3 || (indices && indexCount < 3) || fClip->isEmpty() ||
2114            (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) {
2115        return;
2116    }
2117
2118    // transform out vertices into device coordinates
2119    SkAutoSTMalloc<16, SkPoint> storage(count);
2120    SkPoint* devVerts = storage.get();
2121    fMatrix->mapPoints(devVerts, vertices, count);
2122
2123    if (fBounder) {
2124        SkRect bounds;
2125        bounds.set(devVerts, count);
2126        if (!fBounder->doRect(bounds, paint)) {
2127            return;
2128        }
2129    }
2130
2131    /*
2132        We can draw the vertices in 1 of 4 ways:
2133
2134        - solid color (no shader/texture[], no colors[])
2135        - just colors (no shader/texture[], has colors[])
2136        - just texture (has shader/texture[], no colors[])
2137        - colors * texture (has shader/texture[], has colors[])
2138
2139        Thus for texture drawing, we need both texture[] and a shader.
2140    */
2141
2142    SkTriColorShader triShader; // must be above declaration of p
2143    SkPaint p(paint);
2144
2145    SkShader* shader = p.getShader();
2146    if (NULL == shader) {
2147        // if we have no shader, we ignore the texture coordinates
2148        textures = NULL;
2149    } else if (NULL == textures) {
2150        // if we don't have texture coordinates, ignore the shader
2151        p.setShader(NULL);
2152        shader = NULL;
2153    }
2154
2155    // setup the custom shader (if needed)
2156    if (NULL != colors) {
2157        if (NULL == textures) {
2158            // just colors (no texture)
2159            p.setShader(&triShader);
2160        } else {
2161            // colors * texture
2162            SkASSERT(shader);
2163            bool releaseMode = false;
2164            if (NULL == xmode) {
2165                xmode = SkXfermode::Create(SkXfermode::kMultiply_Mode);
2166                releaseMode = true;
2167            }
2168            SkShader* compose = SkNEW_ARGS(SkComposeShader,
2169                                           (&triShader, shader, xmode));
2170            p.setShader(compose)->unref();
2171            if (releaseMode) {
2172                xmode->unref();
2173            }
2174        }
2175    }
2176
2177    SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
2178    // setup our state and function pointer for iterating triangles
2179    VertState       state(count, indices, indexCount);
2180    VertState::Proc vertProc = state.chooseProc(vmode);
2181
2182    if (NULL != textures || NULL != colors) {
2183        SkMatrix  localM, tempM;
2184        bool      hasLocalM = shader && shader->getLocalMatrix(&localM);
2185
2186        if (NULL != colors) {
2187            if (!triShader.setContext(*fBitmap, p, *fMatrix)) {
2188                colors = NULL;
2189            }
2190        }
2191
2192        while (vertProc(&state)) {
2193            if (NULL != textures) {
2194                if (texture_to_matrix(state, vertices, textures, &tempM)) {
2195                    if (hasLocalM) {
2196                        tempM.postConcat(localM);
2197                    }
2198                    shader->setLocalMatrix(tempM);
2199                    // need to recal setContext since we changed the local matrix
2200                    if (!shader->setContext(*fBitmap, p, *fMatrix)) {
2201                        continue;
2202                    }
2203                }
2204            }
2205            if (NULL != colors) {
2206                if (!triShader.setup(vertices, colors,
2207                                     state.f0, state.f1, state.f2)) {
2208                    continue;
2209                }
2210            }
2211            SkScan::FillTriangle(devVerts[state.f0], devVerts[state.f1],
2212                                 devVerts[state.f2], fClip, blitter.get());
2213        }
2214        // now restore the shader's original local matrix
2215        if (NULL != shader) {
2216            if (hasLocalM) {
2217                shader->setLocalMatrix(localM);
2218            } else {
2219                shader->resetLocalMatrix();
2220            }
2221        }
2222    } else {
2223        // no colors[] and no texture
2224        HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
2225        while (vertProc(&state)) {
2226            hairProc(devVerts[state.f0], devVerts[state.f1], fClip, blitter.get());
2227            hairProc(devVerts[state.f1], devVerts[state.f2], fClip, blitter.get());
2228            hairProc(devVerts[state.f2], devVerts[state.f0], fClip, blitter.get());
2229        }
2230    }
2231}
2232
2233////////////////////////////////////////////////////////////////////////////////////////
2234////////////////////////////////////////////////////////////////////////////////////////
2235
2236#ifdef SK_DEBUG
2237
2238void SkDraw::validate(int width, int height) const {
2239    SkASSERT(fBitmap != NULL);
2240    SkASSERT(fMatrix != NULL);
2241    SkASSERT(fClip != NULL);
2242
2243    const SkIRect&  cr = fClip->getBounds();
2244    SkIRect         br;
2245
2246    br.set(0, 0, width, height);
2247    SkASSERT(cr.isEmpty() || br.contains(cr));
2248}
2249
2250#endif
2251
2252//////////////////////////////////////////////////////////////////////////////////////////
2253
2254bool SkBounder::doIRect(const SkIRect& r) {
2255    SkIRect    rr;
2256    return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
2257}
2258
2259// TODO: change the prototype to take fixed, and update the callers
2260bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
2261                             const SkGlyph& glyph) {
2262    SkIRect    rr;
2263    if (!rr.intersect(fClip->getBounds(), r)) {
2264        return false;
2265    }
2266    GlyphRec rec;
2267    rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
2268    rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
2269                 rec.fLSB.fY + glyph.fAdvanceY);
2270    rec.fGlyphID = glyph.getGlyphID();
2271    rec.fFlags = 0;
2272    return this->onIRectGlyph(rr, rec);
2273}
2274
2275bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
2276                           const SkPaint& paint) {
2277    SkIRect     r;
2278    SkScalar    v0, v1;
2279
2280    v0 = pt0.fX;
2281    v1 = pt1.fX;
2282    if (v0 > v1) {
2283        SkTSwap<SkScalar>(v0, v1);
2284    }
2285    r.fLeft     = SkScalarFloor(v0);
2286    r.fRight    = SkScalarCeil(v1);
2287
2288    v0 = pt0.fY;
2289    v1 = pt1.fY;
2290    if (v0 > v1) {
2291        SkTSwap<SkScalar>(v0, v1);
2292    }
2293    r.fTop      = SkScalarFloor(v0);
2294    r.fBottom   = SkScalarCeil(v1);
2295
2296    if (paint.isAntiAlias()) {
2297        r.inset(-1, -1);
2298    }
2299    return this->doIRect(r);
2300}
2301
2302bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
2303    SkIRect    r;
2304
2305    if (paint.getStyle() == SkPaint::kFill_Style) {
2306        rect.round(&r);
2307    } else {
2308        int rad = -1;
2309        rect.roundOut(&r);
2310        if (paint.isAntiAlias()) {
2311            rad = -2;
2312        }
2313        r.inset(rad, rad);
2314    }
2315    return this->doIRect(r);
2316}
2317
2318bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
2319    SkIRect       r;
2320    const SkRect& bounds = path.getBounds();
2321
2322    if (doFill) {
2323        bounds.round(&r);
2324    } else {    // hairline
2325        bounds.roundOut(&r);
2326    }
2327
2328    if (paint.isAntiAlias()) {
2329        r.inset(-1, -1);
2330    }
2331    return this->doIRect(r);
2332}
2333
2334void SkBounder::commit() {
2335    // override in subclass
2336}
2337
2338////////////////////////////////////////////////////////////////////////////////////////////////
2339
2340#include "SkPath.h"
2341#include "SkDraw.h"
2342#include "SkRegion.h"
2343#include "SkBlitter.h"
2344
2345static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
2346                           SkMaskFilter* filter, const SkMatrix* filterMatrix,
2347                           SkIRect* bounds) {
2348    if (devPath.isEmpty()) {
2349        return false;
2350    }
2351
2352    SkIPoint   margin;
2353    margin.set(0, 0);
2354
2355    //  init our bounds from the path
2356    {
2357        SkRect pathBounds = devPath.getBounds();
2358        pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
2359        pathBounds.roundOut(bounds);
2360    }
2361
2362    if (filter) {
2363        SkASSERT(filterMatrix);
2364
2365        SkMask  srcM, dstM;
2366
2367        srcM.fBounds = *bounds;
2368        srcM.fFormat = SkMask::kA8_Format;
2369        srcM.fImage = NULL;
2370        if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
2371            return false;
2372        }
2373        *bounds = dstM.fBounds;
2374    }
2375
2376    if (clipBounds && !SkIRect::Intersects(*clipBounds, *bounds)) {
2377        return false;
2378    }
2379
2380    // (possibly) trim the srcM bounds to reflect the clip
2381    // (plus whatever slop the filter needs)
2382    if (clipBounds && !clipBounds->contains(*bounds)) {
2383        SkIRect tmp = *bounds;
2384        (void)tmp.intersect(*clipBounds);
2385        // Ugh. Guard against gigantic margins from wacky filters. Without this
2386        // check we can request arbitrary amounts of slop beyond our visible
2387        // clip, and bring down the renderer (at least on finite RAM machines
2388        // like handsets, etc.). Need to balance this invented value between
2389        // quality of large filters like blurs, and the corresponding memory
2390        // requests.
2391        static const int MAX_MARGIN = 128;
2392        tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
2393                  -SkMin32(margin.fY, MAX_MARGIN));
2394        (void)bounds->intersect(tmp);
2395    }
2396
2397    return true;
2398}
2399
2400static void draw_into_mask(const SkMask& mask, const SkPath& devPath) {
2401    SkBitmap    bm;
2402    SkDraw      draw;
2403    SkRegion    clipRgn;
2404    SkMatrix    matrix;
2405    SkPaint     paint;
2406
2407    bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
2408    bm.setPixels(mask.fImage);
2409
2410    clipRgn.setRect(0, 0, mask.fBounds.width(), mask.fBounds.height());
2411    matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
2412                        -SkIntToScalar(mask.fBounds.fTop));
2413
2414    draw.fBitmap    = &bm;
2415    draw.fClip      = &clipRgn;
2416    draw.fMatrix    = &matrix;
2417    draw.fBounder   = NULL;
2418    paint.setAntiAlias(true);
2419    draw.drawPath(devPath, paint);
2420}
2421
2422bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
2423                        SkMaskFilter* filter, const SkMatrix* filterMatrix,
2424                        SkMask* mask, SkMask::CreateMode mode) {
2425    if (SkMask::kJustRenderImage_CreateMode != mode) {
2426        if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
2427            return false;
2428    }
2429
2430    if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
2431        mask->fFormat = SkMask::kA8_Format;
2432        mask->fRowBytes = mask->fBounds.width();
2433        size_t size = mask->computeImageSize();
2434        if (0 == size) {
2435            // we're too big to allocate the mask, abort
2436            return false;
2437        }
2438        mask->fImage = SkMask::AllocImage(size);
2439        memset(mask->fImage, 0, mask->computeImageSize());
2440    }
2441
2442    if (SkMask::kJustComputeBounds_CreateMode != mode) {
2443        draw_into_mask(*mask, devPath);
2444    }
2445
2446    return true;
2447}
2448