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