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