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, bool drawCoverage = false) {
     64         fBlitter = SkBlitter::Choose(device, matrix, paint,
     65                                      fStorage, sizeof(fStorage), drawCoverage);
     66     }
     67 
     68     ~SkAutoBlitterChoose() {
     69         if ((void*)fBlitter == (void*)fStorage) {
     70             fBlitter->~SkBlitter();
     71         } else {
     72             SkDELETE(fBlitter);
     73         }
     74     }
     75 
     76     SkBlitter*  operator->() { return fBlitter; }
     77     SkBlitter*  get() const { return fBlitter; }
     78 
     79     void choose(const SkBitmap& device, const SkMatrix& matrix,
     80                 const SkPaint& paint) {
     81         SkASSERT(!fBlitter);
     82         fBlitter = SkBlitter::Choose(device, matrix, paint,
     83                                      fStorage, sizeof(fStorage));
     84     }
     85 
     86 private:
     87     SkBlitter*  fBlitter;
     88     uint32_t    fStorage[kBlitterStorageLongCount];
     89 };
     90 #define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
     91 
     92 /**
     93  *  Since we are providing the storage for the shader (to avoid the perf cost
     94  *  of calling new) we insist that in our destructor we can account for all
     95  *  owners of the shader.
     96  */
     97 class SkAutoBitmapShaderInstall : SkNoncopyable {
     98 public:
     99     SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
    100             : fPaint(paint) /* makes a copy of the paint */ {
    101         fPaint.setShader(SkShader::CreateBitmapShader(src,
    102                            SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
    103                            fStorage, sizeof(fStorage)));
    104         // we deliberately left the shader with an owner-count of 2
    105         SkASSERT(2 == fPaint.getShader()->getRefCnt());
    106     }
    107 
    108     ~SkAutoBitmapShaderInstall() {
    109         SkShader* shader = fPaint.getShader();
    110         // since we manually destroy shader, we insist that owners == 2
    111         SkASSERT(2 == shader->getRefCnt());
    112 
    113         fPaint.setShader(NULL); // unref the shader by 1
    114 
    115         // now destroy to take care of the 2nd owner-count
    116         if ((void*)shader == (void*)fStorage) {
    117             shader->~SkShader();
    118         } else {
    119             SkDELETE(shader);
    120         }
    121     }
    122 
    123     // return the new paint that has the shader applied
    124     const SkPaint& paintWithShader() const { return fPaint; }
    125 
    126 private:
    127     SkPaint     fPaint; // copy of caller's paint (which we then modify)
    128     uint32_t    fStorage[kBlitterStorageLongCount];
    129 };
    130 #define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
    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 SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
    992                                    SkScalar* coverage) {
    993     SkASSERT(strokeWidth > 0);
    994     // We need to try to fake a thick-stroke with a modulated hairline.
    995 
    996     if (matrix.hasPerspective()) {
    997         return false;
    998     }
    999 
   1000     SkVector src[2], dst[2];
   1001     src[0].set(strokeWidth, 0);
   1002     src[1].set(0, strokeWidth);
   1003     matrix.mapVectors(dst, src, 2);
   1004     SkScalar len0 = fast_len(dst[0]);
   1005     SkScalar len1 = fast_len(dst[1]);
   1006     if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
   1007         if (NULL != coverage) {
   1008             *coverage = SkScalarAve(len0, len1);
   1009         }
   1010         return true;
   1011     }
   1012     return false;
   1013 }
   1014 
   1015 void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
   1016     SkDEBUGCODE(this->validate());
   1017 
   1018     if (fRC->isEmpty()) {
   1019         return;
   1020     }
   1021 
   1022     {
   1023         // TODO: Investigate optimizing these options. They are in the same
   1024         // order as SkDraw::drawPath, which handles each case. It may be
   1025         // that there is no way to optimize for these using the SkRRect path.
   1026         SkScalar coverage;
   1027         if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) {
   1028             goto DRAW_PATH;
   1029         }
   1030 
   1031         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
   1032             goto DRAW_PATH;
   1033         }
   1034 
   1035         if (paint.getRasterizer()) {
   1036             goto DRAW_PATH;
   1037         }
   1038     }
   1039 
   1040     if (paint.getMaskFilter()) {
   1041         // Transform the rrect into device space.
   1042         SkRRect devRRect;
   1043         if (rrect.transform(*fMatrix, &devRRect)) {
   1044             SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
   1045             if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC,
   1046                                                    fBounder, blitter.get(),
   1047                                                    SkPaint::kFill_Style)) {
   1048                 return; // filterRRect() called the blitter, so we're done
   1049             }
   1050         }
   1051     }
   1052 
   1053 DRAW_PATH:
   1054     // Now fall back to the default case of using a path.
   1055     SkPath path;
   1056     path.addRRect(rrect);
   1057     this->drawPath(path, paint, NULL, true);
   1058 }
   1059 
   1060 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
   1061                       const SkMatrix* prePathMatrix, bool pathIsMutable,
   1062                       bool drawCoverage) const {
   1063     SkDEBUGCODE(this->validate();)
   1064 
   1065     // nothing to draw
   1066     if (fRC->isEmpty()) {
   1067         return;
   1068     }
   1069 
   1070     SkPath*         pathPtr = (SkPath*)&origSrcPath;
   1071     bool            doFill = true;
   1072     SkPath          tmpPath;
   1073     SkMatrix        tmpMatrix;
   1074     const SkMatrix* matrix = fMatrix;
   1075 
   1076     if (prePathMatrix) {
   1077         if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
   1078                 origPaint.getRasterizer()) {
   1079             SkPath* result = pathPtr;
   1080 
   1081             if (!pathIsMutable) {
   1082                 result = &tmpPath;
   1083                 pathIsMutable = true;
   1084             }
   1085             pathPtr->transform(*prePathMatrix, result);
   1086             pathPtr = result;
   1087         } else {
   1088             if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) {
   1089                 // overflow
   1090                 return;
   1091             }
   1092             matrix = &tmpMatrix;
   1093         }
   1094     }
   1095     // at this point we're done with prePathMatrix
   1096     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
   1097 
   1098     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
   1099 
   1100     {
   1101         SkScalar coverage;
   1102         if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
   1103             if (SK_Scalar1 == coverage) {
   1104                 paint.writable()->setStrokeWidth(0);
   1105             } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
   1106                 U8CPU newAlpha;
   1107 #if 0
   1108                 newAlpha = SkToU8(SkScalarRoundToInt(coverage *
   1109                                                      origPaint.getAlpha()));
   1110 #else
   1111                 // this is the old technique, which we preserve for now so
   1112                 // we don't change previous results (testing)
   1113                 // the new way seems fine, its just (a tiny bit) different
   1114                 int scale = (int)SkScalarMul(coverage, 256);
   1115                 newAlpha = origPaint.getAlpha() * scale >> 8;
   1116 #endif
   1117                 SkPaint* writablePaint = paint.writable();
   1118                 writablePaint->setStrokeWidth(0);
   1119                 writablePaint->setAlpha(newAlpha);
   1120             }
   1121         }
   1122     }
   1123 
   1124     if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
   1125         SkRect cullRect;
   1126         const SkRect* cullRectPtr = NULL;
   1127         if (this->computeConservativeLocalClipBounds(&cullRect)) {
   1128             cullRectPtr = &cullRect;
   1129         }
   1130         doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr);
   1131         pathPtr = &tmpPath;
   1132     }
   1133 
   1134     if (paint->getRasterizer()) {
   1135         SkMask  mask;
   1136         if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
   1137                             &fRC->getBounds(), paint->getMaskFilter(), &mask,
   1138                             SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
   1139             this->drawDevMask(mask, *paint);
   1140             SkMask::FreeImage(mask.fImage);
   1141         }
   1142         return;
   1143     }
   1144 
   1145     // avoid possibly allocating a new path in transform if we can
   1146     SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
   1147 
   1148     // transform the path into device space
   1149     pathPtr->transform(*matrix, devPathPtr);
   1150 
   1151     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, *paint, drawCoverage);
   1152 
   1153     if (paint->getMaskFilter()) {
   1154         SkPaint::Style style = doFill ? SkPaint::kFill_Style :
   1155             SkPaint::kStroke_Style;
   1156         if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC,
   1157                                                fBounder, blitter.get(),
   1158                                                style)) {
   1159             return; // filterPath() called the blitter, so we're done
   1160         }
   1161     }
   1162 
   1163     if (fBounder && !fBounder->doPath(*devPathPtr, *paint, doFill)) {
   1164         return;
   1165     }
   1166 
   1167     void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
   1168     if (doFill) {
   1169         if (paint->isAntiAlias()) {
   1170             proc = SkScan::AntiFillPath;
   1171         } else {
   1172             proc = SkScan::FillPath;
   1173         }
   1174     } else {    // hairline
   1175         if (paint->isAntiAlias()) {
   1176             proc = SkScan::AntiHairPath;
   1177         } else {
   1178             proc = SkScan::HairPath;
   1179         }
   1180     }
   1181     proc(*devPathPtr, *fRC, blitter.get());
   1182 }
   1183 
   1184 /** For the purposes of drawing bitmaps, if a matrix is "almost" translate
   1185     go ahead and treat it as if it were, so that subsequent code can go fast.
   1186  */
   1187 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
   1188     unsigned bits = 0;  // TODO: find a way to allow the caller to tell us to
   1189                         // respect filtering.
   1190     return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
   1191 }
   1192 
   1193 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
   1194                               const SkPaint& paint) const {
   1195     SkASSERT(bitmap.config() == SkBitmap::kA8_Config);
   1196 
   1197     if (just_translate(*fMatrix, bitmap)) {
   1198         int ix = SkScalarRound(fMatrix->getTranslateX());
   1199         int iy = SkScalarRound(fMatrix->getTranslateY());
   1200 
   1201         SkAutoLockPixels alp(bitmap);
   1202         if (!bitmap.readyToDraw()) {
   1203             return;
   1204         }
   1205 
   1206         SkMask  mask;
   1207         mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
   1208         mask.fFormat = SkMask::kA8_Format;
   1209         mask.fRowBytes = SkToU32(bitmap.rowBytes());
   1210         mask.fImage = bitmap.getAddr8(0, 0);
   1211 
   1212         this->drawDevMask(mask, paint);
   1213     } else {    // need to xform the bitmap first
   1214         SkRect  r;
   1215         SkMask  mask;
   1216 
   1217         r.set(0, 0,
   1218               SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
   1219         fMatrix->mapRect(&r);
   1220         r.round(&mask.fBounds);
   1221 
   1222         // set the mask's bounds to the transformed bitmap-bounds,
   1223         // clipped to the actual device
   1224         {
   1225             SkIRect    devBounds;
   1226             devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
   1227             // need intersect(l, t, r, b) on irect
   1228             if (!mask.fBounds.intersect(devBounds)) {
   1229                 return;
   1230             }
   1231         }
   1232 
   1233         mask.fFormat = SkMask::kA8_Format;
   1234         mask.fRowBytes = SkAlign4(mask.fBounds.width());
   1235         size_t size = mask.computeImageSize();
   1236         if (0 == size) {
   1237             // the mask is too big to allocated, draw nothing
   1238             return;
   1239         }
   1240 
   1241         // allocate (and clear) our temp buffer to hold the transformed bitmap
   1242         SkAutoMalloc    storage(size);
   1243         mask.fImage = (uint8_t*)storage.get();
   1244         memset(mask.fImage, 0, size);
   1245 
   1246         // now draw our bitmap(src) into mask(dst), transformed by the matrix
   1247         {
   1248             SkBitmap    device;
   1249             device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(),
   1250                              mask.fBounds.height(), mask.fRowBytes);
   1251             device.setPixels(mask.fImage);
   1252 
   1253             SkCanvas c(device);
   1254             // need the unclipped top/left for the translate
   1255             c.translate(-SkIntToScalar(mask.fBounds.fLeft),
   1256                         -SkIntToScalar(mask.fBounds.fTop));
   1257             c.concat(*fMatrix);
   1258 
   1259             // We can't call drawBitmap, or we'll infinitely recurse. Instead
   1260             // we manually build a shader and draw that into our new mask
   1261             SkPaint tmpPaint;
   1262             tmpPaint.setFlags(paint.getFlags());
   1263             SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
   1264             SkRect rr;
   1265             rr.set(0, 0, SkIntToScalar(bitmap.width()),
   1266                    SkIntToScalar(bitmap.height()));
   1267             c.drawRect(rr, install.paintWithShader());
   1268         }
   1269         this->drawDevMask(mask, paint);
   1270     }
   1271 }
   1272 
   1273 static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
   1274                         const SkRect& srcR) {
   1275     SkRect  dstR;
   1276     SkIRect devIR;
   1277 
   1278     m.mapRect(&dstR, srcR);
   1279     dstR.roundOut(&devIR);
   1280     return c.quickReject(devIR);
   1281 }
   1282 
   1283 static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
   1284                         int width, int height) {
   1285     SkRect  r;
   1286     r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
   1287     return clipped_out(matrix, clip, r);
   1288 }
   1289 
   1290 static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
   1291                               const SkBitmap& bitmap) {
   1292     return clip.isBW() ||
   1293            clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
   1294 }
   1295 
   1296 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
   1297                         const SkPaint& origPaint) const {
   1298     SkDEBUGCODE(this->validate();)
   1299 
   1300     // nothing to draw
   1301     if (fRC->isEmpty() ||
   1302             bitmap.width() == 0 || bitmap.height() == 0 ||
   1303             bitmap.config() == SkBitmap::kNo_Config) {
   1304         return;
   1305     }
   1306 
   1307     SkPaint paint(origPaint);
   1308     paint.setStyle(SkPaint::kFill_Style);
   1309 
   1310     SkMatrix matrix;
   1311     if (!matrix.setConcat(*fMatrix, prematrix)) {
   1312         return;
   1313     }
   1314 
   1315     if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
   1316         return;
   1317     }
   1318 
   1319     if (fBounder && just_translate(matrix, bitmap)) {
   1320         SkIRect ir;
   1321         int32_t ix = SkScalarRound(matrix.getTranslateX());
   1322         int32_t iy = SkScalarRound(matrix.getTranslateY());
   1323         ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
   1324         if (!fBounder->doIRect(ir)) {
   1325             return;
   1326         }
   1327     }
   1328 
   1329     if (bitmap.config() != SkBitmap::kA8_Config &&
   1330             just_translate(matrix, bitmap)) {
   1331         //
   1332         // It is safe to call lock pixels now, since we know the matrix is
   1333         // (more or less) identity.
   1334         //
   1335         SkAutoLockPixels alp(bitmap);
   1336         if (!bitmap.readyToDraw()) {
   1337             return;
   1338         }
   1339         int ix = SkScalarRound(matrix.getTranslateX());
   1340         int iy = SkScalarRound(matrix.getTranslateY());
   1341         if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
   1342             uint32_t    storage[kBlitterStorageLongCount];
   1343             SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
   1344                                                 ix, iy, storage, sizeof(storage));
   1345             if (blitter) {
   1346                 SkAutoTPlacementDelete<SkBlitter>   ad(blitter, storage);
   1347 
   1348                 SkIRect    ir;
   1349                 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
   1350 
   1351                 SkScan::FillIRect(ir, *fRC, blitter);
   1352                 return;
   1353             }
   1354         }
   1355     }
   1356 
   1357     // now make a temp draw on the stack, and use it
   1358     //
   1359     SkDraw draw(*this);
   1360     draw.fMatrix = &matrix;
   1361 
   1362     if (bitmap.config() == SkBitmap::kA8_Config) {
   1363         draw.drawBitmapAsMask(bitmap, paint);
   1364     } else {
   1365         SkAutoBitmapShaderInstall install(bitmap, paint);
   1366 
   1367         SkRect  r;
   1368         r.set(0, 0, SkIntToScalar(bitmap.width()),
   1369               SkIntToScalar(bitmap.height()));
   1370         // is this ok if paint has a rasterizer?
   1371         draw.drawRect(r, install.paintWithShader());
   1372     }
   1373 }
   1374 
   1375 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
   1376                         const SkPaint& origPaint) const {
   1377     SkDEBUGCODE(this->validate();)
   1378 
   1379     // nothing to draw
   1380     if (fRC->isEmpty() ||
   1381             bitmap.width() == 0 || bitmap.height() == 0 ||
   1382             bitmap.config() == SkBitmap::kNo_Config) {
   1383         return;
   1384     }
   1385 
   1386     SkIRect    bounds;
   1387     bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
   1388 
   1389     if (fRC->quickReject(bounds)) {
   1390         return; // nothing to draw
   1391     }
   1392 
   1393     SkPaint paint(origPaint);
   1394     paint.setStyle(SkPaint::kFill_Style);
   1395 
   1396     if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
   1397         uint32_t    storage[kBlitterStorageLongCount];
   1398         SkBlitter*  blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
   1399                                                 x, y, storage, sizeof(storage));
   1400 
   1401         if (blitter) {
   1402             SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage);
   1403 
   1404             if (fBounder && !fBounder->doIRect(bounds)) {
   1405                 return;
   1406             }
   1407 
   1408             SkScan::FillIRect(bounds, *fRC, blitter);
   1409             return;
   1410         }
   1411     }
   1412 
   1413     SkAutoBitmapShaderInstall install(bitmap, paint);
   1414     const SkPaint& shaderPaint = install.paintWithShader();
   1415 
   1416     SkMatrix        matrix;
   1417     SkRect          r;
   1418 
   1419     // get a scalar version of our rect
   1420     r.set(bounds);
   1421 
   1422     // tell the shader our offset
   1423     matrix.setTranslate(r.fLeft, r.fTop);
   1424     shaderPaint.getShader()->setLocalMatrix(matrix);
   1425 
   1426     SkDraw draw(*this);
   1427     matrix.reset();
   1428     draw.fMatrix = &matrix;
   1429     // call ourself with a rect
   1430     // is this OK if paint has a rasterizer?
   1431     draw.drawRect(r, shaderPaint);
   1432 }
   1433 
   1434 ///////////////////////////////////////////////////////////////////////////////
   1435 
   1436 #include "SkScalerContext.h"
   1437 #include "SkGlyphCache.h"
   1438 #include "SkTextToPathIter.h"
   1439 #include "SkUtils.h"
   1440 
   1441 static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
   1442                 const char text[], size_t byteLength, SkVector* stopVector) {
   1443     SkFixed     x = 0, y = 0;
   1444     const char* stop = text + byteLength;
   1445 
   1446     SkAutoKern  autokern;
   1447 
   1448     while (text < stop) {
   1449         // don't need x, y here, since all subpixel variants will have the
   1450         // same advance
   1451         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   1452 
   1453         x += autokern.adjust(glyph) + glyph.fAdvanceX;
   1454         y += glyph.fAdvanceY;
   1455     }
   1456     stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
   1457 
   1458     SkASSERT(text == stop);
   1459 }
   1460 
   1461 void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
   1462                               SkScalar x, SkScalar y,
   1463                               const SkPaint& paint) const {
   1464     SkDEBUGCODE(this->validate();)
   1465 
   1466     SkTextToPathIter iter(text, byteLength, paint, true);
   1467 
   1468     SkMatrix    matrix;
   1469     matrix.setScale(iter.getPathScale(), iter.getPathScale());
   1470     matrix.postTranslate(x, y);
   1471 
   1472     const SkPath* iterPath;
   1473     SkScalar xpos, prevXPos = 0;
   1474 
   1475     while (iter.next(&iterPath, &xpos)) {
   1476         matrix.postTranslate(xpos - prevXPos, 0);
   1477         if (iterPath) {
   1478             const SkPaint& pnt = iter.getPaint();
   1479             if (fDevice) {
   1480                 fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
   1481             } else {
   1482                 this->drawPath(*iterPath, pnt, &matrix, false);
   1483             }
   1484         }
   1485         prevXPos = xpos;
   1486     }
   1487 }
   1488 
   1489 // disable warning : local variable used without having been initialized
   1490 #if defined _WIN32 && _MSC_VER >= 1300
   1491 #pragma warning ( push )
   1492 #pragma warning ( disable : 4701 )
   1493 #endif
   1494 
   1495 //////////////////////////////////////////////////////////////////////////////
   1496 
   1497 static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state,
   1498                                    SkFixed fx, SkFixed fy,
   1499                                    const SkGlyph& glyph) {
   1500     int left = SkFixedFloor(fx);
   1501     int top = SkFixedFloor(fy);
   1502     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
   1503     SkASSERT(NULL == state.fBounder);
   1504     SkASSERT((NULL == state.fClip && state.fAAClip) ||
   1505              (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
   1506 
   1507     left += glyph.fLeft;
   1508     top  += glyph.fTop;
   1509 
   1510     int right   = left + glyph.fWidth;
   1511     int bottom  = top + glyph.fHeight;
   1512 
   1513     SkMask        mask;
   1514     SkIRect        storage;
   1515     SkIRect*    bounds = &mask.fBounds;
   1516 
   1517     mask.fBounds.set(left, top, right, bottom);
   1518 
   1519     // this extra test is worth it, assuming that most of the time it succeeds
   1520     // since we can avoid writing to storage
   1521     if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
   1522         if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
   1523             return;
   1524         bounds = &storage;
   1525     }
   1526 
   1527     uint8_t* aa = (uint8_t*)glyph.fImage;
   1528     if (NULL == aa) {
   1529         aa = (uint8_t*)state.fCache->findImage(glyph);
   1530         if (NULL == aa) {
   1531             return; // can't rasterize glyph
   1532         }
   1533     }
   1534 
   1535     mask.fRowBytes = glyph.rowBytes();
   1536     mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
   1537     mask.fImage = aa;
   1538     state.blitMask(mask, *bounds);
   1539 }
   1540 
   1541 static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state,
   1542                                   SkFixed fx, SkFixed fy,
   1543                                   const SkGlyph& glyph) {
   1544     int left = SkFixedFloor(fx);
   1545     int top = SkFixedFloor(fy);
   1546     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
   1547     SkASSERT(!state.fClip->isRect());
   1548     SkASSERT(NULL == state.fBounder);
   1549 
   1550     SkMask  mask;
   1551 
   1552     left += glyph.fLeft;
   1553     top  += glyph.fTop;
   1554 
   1555     mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
   1556     SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
   1557 
   1558     if (!clipper.done()) {
   1559         const SkIRect&  cr = clipper.rect();
   1560         const uint8_t*  aa = (const uint8_t*)glyph.fImage;
   1561         if (NULL == aa) {
   1562             aa = (uint8_t*)state.fCache->findImage(glyph);
   1563             if (NULL == aa) {
   1564                 return;
   1565             }
   1566         }
   1567 
   1568         mask.fRowBytes = glyph.rowBytes();
   1569         mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
   1570         mask.fImage = (uint8_t*)aa;
   1571         do {
   1572             state.blitMask(mask, cr);
   1573             clipper.next();
   1574         } while (!clipper.done());
   1575     }
   1576 }
   1577 
   1578 static void D1G_Bounder(const SkDraw1Glyph& state,
   1579                         SkFixed fx, SkFixed fy,
   1580                         const SkGlyph& glyph) {
   1581     int left = SkFixedFloor(fx);
   1582     int top = SkFixedFloor(fy);
   1583     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
   1584 
   1585     SkMask  mask;
   1586 
   1587     left += glyph.fLeft;
   1588     top  += glyph.fTop;
   1589 
   1590     mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
   1591     SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
   1592 
   1593     if (!clipper.done()) {
   1594         const SkIRect&  cr = clipper.rect();
   1595         const uint8_t*  aa = (const uint8_t*)glyph.fImage;
   1596         if (NULL == aa) {
   1597             aa = (uint8_t*)state.fCache->findImage(glyph);
   1598             if (NULL == aa) {
   1599                 return;
   1600             }
   1601         }
   1602 
   1603         // we need to pass the origin, which we approximate with our
   1604         // (unadjusted) left,top coordinates (the caller called fixedfloor)
   1605         if (state.fBounder->doIRectGlyph(cr,
   1606                                          left - glyph.fLeft,
   1607                                          top - glyph.fTop, glyph)) {
   1608             mask.fRowBytes = glyph.rowBytes();
   1609             mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
   1610             mask.fImage = (uint8_t*)aa;
   1611             do {
   1612                 state.blitMask(mask, cr);
   1613                 clipper.next();
   1614             } while (!clipper.done());
   1615         }
   1616     }
   1617 }
   1618 
   1619 static void D1G_Bounder_AAClip(const SkDraw1Glyph& state,
   1620                                SkFixed fx, SkFixed fy,
   1621                                const SkGlyph& glyph) {
   1622     int left = SkFixedFloor(fx);
   1623     int top = SkFixedFloor(fy);
   1624     SkIRect bounds;
   1625     bounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
   1626 
   1627     if (state.fBounder->doIRectGlyph(bounds, left, top, glyph)) {
   1628         D1G_NoBounder_RectClip(state, fx, fy, glyph);
   1629     }
   1630 }
   1631 
   1632 static bool hasCustomD1GProc(const SkDraw& draw) {
   1633     return draw.fProcs && draw.fProcs->fD1GProc;
   1634 }
   1635 
   1636 static bool needsRasterTextBlit(const SkDraw& draw) {
   1637     return !hasCustomD1GProc(draw);
   1638 }
   1639 
   1640 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter,
   1641                                       SkGlyphCache* cache, const SkPaint& pnt) {
   1642     fDraw = draw;
   1643     fBounder = draw->fBounder;
   1644     fBlitter = blitter;
   1645     fCache = cache;
   1646     fPaint = &pnt;
   1647 
   1648     if (cache->isSubpixel()) {
   1649         fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
   1650     } else {
   1651         fHalfSampleX = fHalfSampleY = SK_FixedHalf;
   1652     }
   1653 
   1654     if (hasCustomD1GProc(*draw)) {
   1655         // todo: fix this assumption about clips w/ custom
   1656         fClip = draw->fClip;
   1657         fClipBounds = fClip->getBounds();
   1658         return draw->fProcs->fD1GProc;
   1659     }
   1660 
   1661     if (draw->fRC->isBW()) {
   1662         fAAClip = NULL;
   1663         fClip = &draw->fRC->bwRgn();
   1664         fClipBounds = fClip->getBounds();
   1665         if (NULL == fBounder) {
   1666             if (fClip->isRect()) {
   1667                 return D1G_NoBounder_RectClip;
   1668             } else {
   1669                 return D1G_NoBounder_RgnClip;
   1670             }
   1671         } else {
   1672             return D1G_Bounder;
   1673         }
   1674     } else {    // aaclip
   1675         fAAClip = &draw->fRC->aaRgn();
   1676         fClip = NULL;
   1677         fClipBounds = fAAClip->getBounds();
   1678         if (NULL == fBounder) {
   1679             return D1G_NoBounder_RectClip;
   1680         } else {
   1681             return D1G_Bounder_AAClip;
   1682         }
   1683     }
   1684 }
   1685 
   1686 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
   1687     SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
   1688 
   1689     SkBitmap bm;
   1690     bm.setConfig(SkBitmap::kARGB_8888_Config,
   1691                  mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
   1692     bm.setPixels((SkPMColor*)mask.fImage);
   1693 
   1694     fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
   1695 }
   1696 
   1697 ///////////////////////////////////////////////////////////////////////////////
   1698 
   1699 void SkDraw::drawText(const char text[], size_t byteLength,
   1700                       SkScalar x, SkScalar y, const SkPaint& paint) const {
   1701     SkASSERT(byteLength == 0 || text != NULL);
   1702 
   1703     SkDEBUGCODE(this->validate();)
   1704 
   1705     // nothing to draw
   1706     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
   1707         return;
   1708     }
   1709 
   1710     // SkScalarRec doesn't currently have a way of representing hairline stroke and
   1711     // will fill if its frame-width is 0.
   1712     if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
   1713         this->drawText_asPaths(text, byteLength, x, y, paint);
   1714         return;
   1715     }
   1716 
   1717     SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
   1718 
   1719 #if SK_DISTANCEFIELD_FONTS
   1720     const SkMatrix* ctm = fMatrix;
   1721     const SkPaint* paintRef = &paint;
   1722     SkPaint paintCopy;
   1723     uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
   1724     if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
   1725         paintCopy = paint;
   1726         paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
   1727         paintCopy.setLCDRenderText(false);
   1728         paintRef = &paintCopy;
   1729     }
   1730     if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
   1731         ctm = NULL;
   1732     }
   1733     SkAutoGlyphCache    autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
   1734 #else
   1735     SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
   1736 #endif
   1737     SkGlyphCache*       cache = autoCache.getCache();
   1738 
   1739     // transform our starting point
   1740 #if SK_DISTANCEFIELD_FONTS
   1741     if (!(procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag))
   1742 #endif
   1743     {
   1744         SkPoint loc;
   1745         fMatrix->mapXY(x, y, &loc);
   1746         x = loc.fX;
   1747         y = loc.fY;
   1748     }
   1749 
   1750     // need to measure first
   1751     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
   1752         SkVector    stop;
   1753 
   1754         measure_text(cache, glyphCacheProc, text, byteLength, &stop);
   1755 
   1756         SkScalar    stopX = stop.fX;
   1757         SkScalar    stopY = stop.fY;
   1758 
   1759         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
   1760             stopX = SkScalarHalf(stopX);
   1761             stopY = SkScalarHalf(stopY);
   1762         }
   1763         x -= stopX;
   1764         y -= stopY;
   1765     }
   1766 
   1767     const char* stop = text + byteLength;
   1768 
   1769     SkAAClipBlitter     aaBlitter;
   1770     SkAutoBlitterChoose blitterChooser;
   1771     SkBlitter*          blitter = NULL;
   1772     if (needsRasterTextBlit(*this)) {
   1773         blitterChooser.choose(*fBitmap, *fMatrix, paint);
   1774         blitter = blitterChooser.get();
   1775         if (fRC->isAA()) {
   1776             aaBlitter.init(blitter, &fRC->aaRgn());
   1777             blitter = &aaBlitter;
   1778         }
   1779     }
   1780 
   1781     SkAutoKern          autokern;
   1782     SkDraw1Glyph        d1g;
   1783     SkDraw1Glyph::Proc  proc = d1g.init(this, blitter, cache, paint);
   1784 
   1785     SkFixed fxMask = ~0;
   1786     SkFixed fyMask = ~0;
   1787     if (cache->isSubpixel()) {
   1788         SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
   1789         if (kX_SkAxisAlignment == baseline) {
   1790             fyMask = 0;
   1791             d1g.fHalfSampleY = SK_FixedHalf;
   1792         } else if (kY_SkAxisAlignment == baseline) {
   1793             fxMask = 0;
   1794             d1g.fHalfSampleX = SK_FixedHalf;
   1795         }
   1796     }
   1797 
   1798     SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX;
   1799     SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY;
   1800 
   1801 #if SK_DISTANCEFIELD_FONTS
   1802     SkFixed fixedScale;
   1803     if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
   1804         fixedScale = SkScalarToFixed(paint.getTextSize()/(float)SkDrawProcs::kBaseDFFontSize);
   1805     }
   1806 #endif
   1807     while (text < stop) {
   1808         const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
   1809 
   1810 #if SK_DISTANCEFIELD_FONTS
   1811         if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
   1812             fx += SkFixedMul_portable(autokern.adjust(glyph), fixedScale);
   1813         } else {
   1814             fx += autokern.adjust(glyph);
   1815         }
   1816 #else
   1817         fx += autokern.adjust(glyph);
   1818 #endif
   1819 
   1820         if (glyph.fWidth) {
   1821             proc(d1g, fx, fy, glyph);
   1822         }
   1823 
   1824 #if SK_DISTANCEFIELD_FONTS
   1825         if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
   1826             fx += SkFixedMul_portable(glyph.fAdvanceX, fixedScale);
   1827             fy += SkFixedMul_portable(glyph.fAdvanceY, fixedScale);
   1828         } else {
   1829             fx += glyph.fAdvanceX;
   1830             fy += glyph.fAdvanceY;
   1831         }
   1832 #else
   1833         fx += glyph.fAdvanceX;
   1834         fy += glyph.fAdvanceY;
   1835 #endif
   1836     }
   1837 }
   1838 
   1839 // last parameter is interpreted as SkFixed [x, y]
   1840 // return the fixed position, which may be rounded or not by the caller
   1841 //   e.g. subpixel doesn't round
   1842 typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*);
   1843 
   1844 static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
   1845     dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY));
   1846 }
   1847 
   1848 static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
   1849     dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1),
   1850              SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1));
   1851 }
   1852 
   1853 static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, SkIPoint* dst) {
   1854     dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX,
   1855              SkScalarToFixed(loc.fY) - glyph.fAdvanceY);
   1856 }
   1857 
   1858 static AlignProc pick_align_proc(SkPaint::Align align) {
   1859     static const AlignProc gProcs[] = {
   1860         leftAlignProc, centerAlignProc, rightAlignProc
   1861     };
   1862 
   1863     SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
   1864 
   1865     return gProcs[align];
   1866 }
   1867 
   1868 typedef void (*AlignProc_scalar)(const SkPoint&, const SkGlyph&, SkPoint*);
   1869 
   1870 static void leftAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
   1871     dst->set(loc.fX, loc.fY);
   1872 }
   1873 
   1874 static void centerAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
   1875     dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX >> 1),
   1876              loc.fY - SkFixedToScalar(glyph.fAdvanceY >> 1));
   1877 }
   1878 
   1879 static void rightAlignProc_scalar(const SkPoint& loc, const SkGlyph& glyph, SkPoint* dst) {
   1880     dst->set(loc.fX - SkFixedToScalar(glyph.fAdvanceX),
   1881              loc.fY - SkFixedToScalar(glyph.fAdvanceY));
   1882 }
   1883 
   1884 static AlignProc_scalar pick_align_proc_scalar(SkPaint::Align align) {
   1885     static const AlignProc_scalar gProcs[] = {
   1886         leftAlignProc_scalar, centerAlignProc_scalar, rightAlignProc_scalar
   1887     };
   1888 
   1889     SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs));
   1890 
   1891     return gProcs[align];
   1892 }
   1893 
   1894 class TextMapState {
   1895 public:
   1896     mutable SkPoint fLoc;
   1897 
   1898     TextMapState(const SkMatrix& matrix, SkScalar y)
   1899         : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {}
   1900 
   1901     typedef void (*Proc)(const TextMapState&, const SkScalar pos[]);
   1902 
   1903     Proc pickProc(int scalarsPerPosition);
   1904 
   1905 private:
   1906     const SkMatrix&     fMatrix;
   1907     SkMatrix::MapXYProc fProc;
   1908     SkScalar            fY; // ignored by MapXYProc
   1909     // these are only used by Only... procs
   1910     SkScalar            fScaleX, fTransX, fTransformedY;
   1911 
   1912     static void MapXProc(const TextMapState& state, const SkScalar pos[]) {
   1913         state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc);
   1914     }
   1915 
   1916     static void MapXYProc(const TextMapState& state, const SkScalar pos[]) {
   1917         state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc);
   1918     }
   1919 
   1920     static void MapOnlyScaleXProc(const TextMapState& state,
   1921                                   const SkScalar pos[]) {
   1922         state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX,
   1923                        state.fTransformedY);
   1924     }
   1925 
   1926     static void MapOnlyTransXProc(const TextMapState& state,
   1927                                   const SkScalar pos[]) {
   1928         state.fLoc.set(*pos + state.fTransX, state.fTransformedY);
   1929     }
   1930 };
   1931 
   1932 TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) {
   1933     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
   1934 
   1935     if (1 == scalarsPerPosition) {
   1936         unsigned mtype = fMatrix.getType();
   1937         if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) {
   1938             return MapXProc;
   1939         } else {
   1940             fScaleX = fMatrix.getScaleX();
   1941             fTransX = fMatrix.getTranslateX();
   1942             fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) +
   1943                             fMatrix.getTranslateY();
   1944             return (mtype & SkMatrix::kScale_Mask) ?
   1945                         MapOnlyScaleXProc : MapOnlyTransXProc;
   1946         }
   1947     } else {
   1948         return MapXYProc;
   1949     }
   1950 }
   1951 
   1952 //////////////////////////////////////////////////////////////////////////////
   1953 
   1954 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
   1955                                  const SkScalar pos[], SkScalar constY,
   1956                                  int scalarsPerPosition,
   1957                                  const SkPaint& origPaint) const {
   1958     // setup our std paint, in hopes of getting hits in the cache
   1959     SkPaint paint(origPaint);
   1960     SkScalar matrixScale = paint.setupForAsPaths();
   1961 
   1962     SkMatrix matrix;
   1963     matrix.setScale(matrixScale, matrixScale);
   1964 
   1965     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
   1966     SkAutoGlyphCache    autoCache(paint, NULL, NULL);
   1967     SkGlyphCache*       cache = autoCache.getCache();
   1968 
   1969     const char*        stop = text + byteLength;
   1970     AlignProc_scalar   alignProc = pick_align_proc_scalar(paint.getTextAlign());
   1971     TextMapState       tms(SkMatrix::I(), constY);
   1972     TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
   1973 
   1974     while (text < stop) {
   1975         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   1976         if (glyph.fWidth) {
   1977             const SkPath* path = cache->findPath(glyph);
   1978             if (path) {
   1979                 tmsProc(tms, pos);
   1980                 SkPoint loc;
   1981                 alignProc(tms.fLoc, glyph, &loc);
   1982 
   1983                 matrix[SkMatrix::kMTransX] = loc.fX;
   1984                 matrix[SkMatrix::kMTransY] = loc.fY;
   1985                 if (fDevice) {
   1986                     fDevice->drawPath(*this, *path, paint, &matrix, false);
   1987                 } else {
   1988                     this->drawPath(*path, paint, &matrix, false);
   1989                 }
   1990             }
   1991         }
   1992         pos += scalarsPerPosition;
   1993     }
   1994 }
   1995 
   1996 void SkDraw::drawPosText(const char text[], size_t byteLength,
   1997                          const SkScalar pos[], SkScalar constY,
   1998                          int scalarsPerPosition, const SkPaint& paint) const {
   1999     SkASSERT(byteLength == 0 || text != NULL);
   2000     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
   2001 
   2002     SkDEBUGCODE(this->validate();)
   2003 
   2004     // nothing to draw
   2005     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
   2006         return;
   2007     }
   2008 
   2009     if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
   2010         this->drawPosText_asPaths(text, byteLength, pos, constY,
   2011                                   scalarsPerPosition, paint);
   2012         return;
   2013     }
   2014 
   2015     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
   2016 #if SK_DISTANCEFIELD_FONTS
   2017     const SkMatrix* ctm = fMatrix;
   2018     const SkPaint* paintRef = &paint;
   2019     SkPaint paintCopy;
   2020     uint32_t procFlags = fProcs ? fProcs->fFlags : 0;
   2021     if (procFlags & SkDrawProcs::kUseScaledGlyphs_Flag) {
   2022         paintCopy = paint;
   2023         paintCopy.setTextSize(SkDrawProcs::kBaseDFFontSize);
   2024         paintRef = &paintCopy;
   2025     }
   2026     if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
   2027         ctm = &SkMatrix::I();
   2028     }
   2029     SkAutoGlyphCache    autoCache(*paintRef, &fDevice->fLeakyProperties, ctm);
   2030 #else
   2031     SkAutoGlyphCache    autoCache(paint, &fDevice->fLeakyProperties, fMatrix);
   2032 #endif
   2033     SkGlyphCache*       cache = autoCache.getCache();
   2034 
   2035     SkAAClipBlitterWrapper wrapper;
   2036     SkAutoBlitterChoose blitterChooser;
   2037     SkBlitter* blitter = NULL;
   2038     if (needsRasterTextBlit(*this)) {
   2039         blitterChooser.choose(*fBitmap, *fMatrix, paint);
   2040         blitter = blitterChooser.get();
   2041         if (fRC->isAA()) {
   2042             wrapper.init(*fRC, blitter);
   2043             blitter = wrapper.getBlitter();
   2044         }
   2045     }
   2046 
   2047     const char*        stop = text + byteLength;
   2048     AlignProc          alignProc = pick_align_proc(paint.getTextAlign());
   2049     SkDraw1Glyph       d1g;
   2050     SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
   2051 #if SK_DISTANCEFIELD_FONTS
   2052     TextMapState       tms(*ctm, constY);
   2053 #else
   2054     TextMapState       tms(*fMatrix, constY);
   2055 #endif
   2056     TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition);
   2057 
   2058     if (cache->isSubpixel()) {
   2059         // maybe we should skip the rounding if linearText is set
   2060         SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
   2061 
   2062         SkFixed fxMask = ~0;
   2063         SkFixed fyMask = ~0;
   2064         if (kX_SkAxisAlignment == baseline) {
   2065             fyMask = 0;
   2066 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
   2067             d1g.fHalfSampleY = SK_FixedHalf;
   2068 #endif
   2069         } else if (kY_SkAxisAlignment == baseline) {
   2070             fxMask = 0;
   2071 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX
   2072             d1g.fHalfSampleX = SK_FixedHalf;
   2073 #endif
   2074         }
   2075 
   2076         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
   2077             while (text < stop) {
   2078 #if SK_DISTANCEFIELD_FONTS
   2079                 if (procFlags & SkDrawProcs::kSkipBakedGlyphTransform_Flag) {
   2080                     tms.fLoc.fX = *pos;
   2081                     tms.fLoc.fY = *(pos+1);
   2082                 } else {
   2083                     tmsProc(tms, pos);
   2084                 }
   2085 #else
   2086                 tmsProc(tms, pos);
   2087 #endif
   2088                 SkFixed fx = SkScalarToFixed(tms.fLoc.fX) + d1g.fHalfSampleX;
   2089                 SkFixed fy = SkScalarToFixed(tms.fLoc.fY) + d1g.fHalfSampleY;
   2090 
   2091                 const SkGlyph& glyph = glyphCacheProc(cache, &text,
   2092                                                       fx & fxMask, fy & fyMask);
   2093 
   2094                 if (glyph.fWidth) {
   2095                     proc(d1g, fx, fy, glyph);
   2096                 }
   2097                 pos += scalarsPerPosition;
   2098             }
   2099         } else {
   2100             while (text < stop) {
   2101                 const char* currentText = text;
   2102                 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
   2103 
   2104                 if (metricGlyph.fWidth) {
   2105                     SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
   2106                     SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
   2107 
   2108                     tmsProc(tms, pos);
   2109                     SkIPoint fixedLoc;
   2110                     alignProc(tms.fLoc, metricGlyph, &fixedLoc);
   2111 
   2112                     SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX;
   2113                     SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY;
   2114 
   2115                     // have to call again, now that we've been "aligned"
   2116                     const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
   2117                                                           fx & fxMask, fy & fyMask);
   2118                     // the assumption is that the metrics haven't changed
   2119                     SkASSERT(prevAdvX == glyph.fAdvanceX);
   2120                     SkASSERT(prevAdvY == glyph.fAdvanceY);
   2121                     SkASSERT(glyph.fWidth);
   2122 
   2123                     proc(d1g, fx, fy, glyph);
   2124                 }
   2125                 pos += scalarsPerPosition;
   2126             }
   2127         }
   2128     } else {    // not subpixel
   2129         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
   2130             while (text < stop) {
   2131                 // the last 2 parameters are ignored
   2132                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   2133 
   2134                 if (glyph.fWidth) {
   2135                     tmsProc(tms, pos);
   2136 
   2137                     proc(d1g,
   2138                          SkScalarToFixed(tms.fLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX,
   2139                          SkScalarToFixed(tms.fLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY,
   2140                          glyph);
   2141                 }
   2142                 pos += scalarsPerPosition;
   2143             }
   2144         } else {
   2145             while (text < stop) {
   2146                 // the last 2 parameters are ignored
   2147                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   2148 
   2149                 if (glyph.fWidth) {
   2150                     tmsProc(tms, pos);
   2151 
   2152                     SkIPoint fixedLoc;
   2153                     alignProc(tms.fLoc, glyph, &fixedLoc);
   2154 
   2155                     proc(d1g,
   2156                          fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX,
   2157                          fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY,
   2158                          glyph);
   2159                 }
   2160                 pos += scalarsPerPosition;
   2161             }
   2162         }
   2163     }
   2164 }
   2165 
   2166 #if defined _WIN32 && _MSC_VER >= 1300
   2167 #pragma warning ( pop )
   2168 #endif
   2169 
   2170 ///////////////////////////////////////////////////////////////////////////////
   2171 
   2172 #include "SkPathMeasure.h"
   2173 
   2174 static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
   2175                         SkPathMeasure& meas, const SkMatrix& matrix) {
   2176     SkMatrix::MapXYProc proc = matrix.getMapXYProc();
   2177 
   2178     for (int i = 0; i < count; i++) {
   2179         SkPoint pos;
   2180         SkVector tangent;
   2181 
   2182         proc(matrix, src[i].fX, src[i].fY, &pos);
   2183         SkScalar sx = pos.fX;
   2184         SkScalar sy = pos.fY;
   2185 
   2186         if (!meas.getPosTan(sx, &pos, &tangent)) {
   2187             // set to 0 if the measure failed, so that we just set dst == pos
   2188             tangent.set(0, 0);
   2189         }
   2190 
   2191         /*  This is the old way (that explains our approach but is way too slow
   2192             SkMatrix    matrix;
   2193             SkPoint     pt;
   2194 
   2195             pt.set(sx, sy);
   2196             matrix.setSinCos(tangent.fY, tangent.fX);
   2197             matrix.preTranslate(-sx, 0);
   2198             matrix.postTranslate(pos.fX, pos.fY);
   2199             matrix.mapPoints(&dst[i], &pt, 1);
   2200         */
   2201         dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
   2202                    pos.fY + SkScalarMul(tangent.fX, sy));
   2203     }
   2204 }
   2205 
   2206 /*  TODO
   2207 
   2208     Need differentially more subdivisions when the follow-path is curvy. Not sure how to
   2209     determine that, but we need it. I guess a cheap answer is let the caller tell us,
   2210     but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
   2211 */
   2212 static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
   2213                       const SkMatrix& matrix) {
   2214     SkPath::Iter    iter(src, false);
   2215     SkPoint         srcP[4], dstP[3];
   2216     SkPath::Verb    verb;
   2217 
   2218     while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
   2219         switch (verb) {
   2220             case SkPath::kMove_Verb:
   2221                 morphpoints(dstP, srcP, 1, meas, matrix);
   2222                 dst->moveTo(dstP[0]);
   2223                 break;
   2224             case SkPath::kLine_Verb:
   2225                 // turn lines into quads to look bendy
   2226                 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
   2227                 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
   2228                 morphpoints(dstP, srcP, 2, meas, matrix);
   2229                 dst->quadTo(dstP[0], dstP[1]);
   2230                 break;
   2231             case SkPath::kQuad_Verb:
   2232                 morphpoints(dstP, &srcP[1], 2, meas, matrix);
   2233                 dst->quadTo(dstP[0], dstP[1]);
   2234                 break;
   2235             case SkPath::kCubic_Verb:
   2236                 morphpoints(dstP, &srcP[1], 3, meas, matrix);
   2237                 dst->cubicTo(dstP[0], dstP[1], dstP[2]);
   2238                 break;
   2239             case SkPath::kClose_Verb:
   2240                 dst->close();
   2241                 break;
   2242             default:
   2243                 SkDEBUGFAIL("unknown verb");
   2244                 break;
   2245         }
   2246     }
   2247 }
   2248 
   2249 void SkDraw::drawTextOnPath(const char text[], size_t byteLength,
   2250                             const SkPath& follow, const SkMatrix* matrix,
   2251                             const SkPaint& paint) const {
   2252     SkASSERT(byteLength == 0 || text != NULL);
   2253 
   2254     // nothing to draw
   2255     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
   2256         return;
   2257     }
   2258 
   2259     SkTextToPathIter    iter(text, byteLength, paint, true);
   2260     SkPathMeasure       meas(follow, false);
   2261     SkScalar            hOffset = 0;
   2262 
   2263     // need to measure first
   2264     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
   2265         SkScalar pathLen = meas.getLength();
   2266         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
   2267             pathLen = SkScalarHalf(pathLen);
   2268         }
   2269         hOffset += pathLen;
   2270     }
   2271 
   2272     const SkPath*   iterPath;
   2273     SkScalar        xpos;
   2274     SkMatrix        scaledMatrix;
   2275     SkScalar        scale = iter.getPathScale();
   2276 
   2277     scaledMatrix.setScale(scale, scale);
   2278 
   2279     while (iter.next(&iterPath, &xpos)) {
   2280         if (iterPath) {
   2281             SkPath      tmp;
   2282             SkMatrix    m(scaledMatrix);
   2283 
   2284             m.postTranslate(xpos + hOffset, 0);
   2285             if (matrix) {
   2286                 m.postConcat(*matrix);
   2287             }
   2288             morphpath(&tmp, *iterPath, meas, m);
   2289             if (fDevice) {
   2290                 fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true);
   2291             } else {
   2292                 this->drawPath(tmp, iter.getPaint(), NULL, true);
   2293             }
   2294         }
   2295     }
   2296 }
   2297 
   2298 ///////////////////////////////////////////////////////////////////////////////
   2299 
   2300 struct VertState {
   2301     int f0, f1, f2;
   2302 
   2303     VertState(int vCount, const uint16_t indices[], int indexCount)
   2304             : fIndices(indices) {
   2305         fCurrIndex = 0;
   2306         if (indices) {
   2307             fCount = indexCount;
   2308         } else {
   2309             fCount = vCount;
   2310         }
   2311     }
   2312 
   2313     typedef bool (*Proc)(VertState*);
   2314     Proc chooseProc(SkCanvas::VertexMode mode);
   2315 
   2316 private:
   2317     int             fCount;
   2318     int             fCurrIndex;
   2319     const uint16_t* fIndices;
   2320 
   2321     static bool Triangles(VertState*);
   2322     static bool TrianglesX(VertState*);
   2323     static bool TriangleStrip(VertState*);
   2324     static bool TriangleStripX(VertState*);
   2325     static bool TriangleFan(VertState*);
   2326     static bool TriangleFanX(VertState*);
   2327 };
   2328 
   2329 bool VertState::Triangles(VertState* state) {
   2330     int index = state->fCurrIndex;
   2331     if (index + 3 > state->fCount) {
   2332         return false;
   2333     }
   2334     state->f0 = index + 0;
   2335     state->f1 = index + 1;
   2336     state->f2 = index + 2;
   2337     state->fCurrIndex = index + 3;
   2338     return true;
   2339 }
   2340 
   2341 bool VertState::TrianglesX(VertState* state) {
   2342     const uint16_t* indices = state->fIndices;
   2343     int index = state->fCurrIndex;
   2344     if (index + 3 > state->fCount) {
   2345         return false;
   2346     }
   2347     state->f0 = indices[index + 0];
   2348     state->f1 = indices[index + 1];
   2349     state->f2 = indices[index + 2];
   2350     state->fCurrIndex = index + 3;
   2351     return true;
   2352 }
   2353 
   2354 bool VertState::TriangleStrip(VertState* state) {
   2355     int index = state->fCurrIndex;
   2356     if (index + 3 > state->fCount) {
   2357         return false;
   2358     }
   2359     state->f2 = index + 2;
   2360     if (index & 1) {
   2361         state->f0 = index + 1;
   2362         state->f1 = index + 0;
   2363     } else {
   2364         state->f0 = index + 0;
   2365         state->f1 = index + 1;
   2366     }
   2367     state->fCurrIndex = index + 1;
   2368     return true;
   2369 }
   2370 
   2371 bool VertState::TriangleStripX(VertState* state) {
   2372     const uint16_t* indices = state->fIndices;
   2373     int index = state->fCurrIndex;
   2374     if (index + 3 > state->fCount) {
   2375         return false;
   2376     }
   2377     state->f2 = indices[index + 2];
   2378     if (index & 1) {
   2379         state->f0 = indices[index + 1];
   2380         state->f1 = indices[index + 0];
   2381     } else {
   2382         state->f0 = indices[index + 0];
   2383         state->f1 = indices[index + 1];
   2384     }
   2385     state->fCurrIndex = index + 1;
   2386     return true;
   2387 }
   2388 
   2389 bool VertState::TriangleFan(VertState* state) {
   2390     int index = state->fCurrIndex;
   2391     if (index + 3 > state->fCount) {
   2392         return false;
   2393     }
   2394     state->f0 = 0;
   2395     state->f1 = index + 1;
   2396     state->f2 = index + 2;
   2397     state->fCurrIndex = index + 1;
   2398     return true;
   2399 }
   2400 
   2401 bool VertState::TriangleFanX(VertState* state) {
   2402     const uint16_t* indices = state->fIndices;
   2403     int index = state->fCurrIndex;
   2404     if (index + 3 > state->fCount) {
   2405         return false;
   2406     }
   2407     state->f0 = indices[0];
   2408     state->f1 = indices[index + 1];
   2409     state->f2 = indices[index + 2];
   2410     state->fCurrIndex = index + 1;
   2411     return true;
   2412 }
   2413 
   2414 VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) {
   2415     switch (mode) {
   2416         case SkCanvas::kTriangles_VertexMode:
   2417             return fIndices ? TrianglesX : Triangles;
   2418         case SkCanvas::kTriangleStrip_VertexMode:
   2419             return fIndices ? TriangleStripX : TriangleStrip;
   2420         case SkCanvas::kTriangleFan_VertexMode:
   2421             return fIndices ? TriangleFanX : TriangleFan;
   2422         default:
   2423             return NULL;
   2424     }
   2425 }
   2426 
   2427 typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&,
   2428                          SkBlitter*);
   2429 
   2430 static HairProc ChooseHairProc(bool doAntiAlias) {
   2431     return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
   2432 }
   2433 
   2434 static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
   2435                               const SkPoint texs[], SkMatrix* matrix) {
   2436     SkPoint src[3], dst[3];
   2437 
   2438     src[0] = texs[state.f0];
   2439     src[1] = texs[state.f1];
   2440     src[2] = texs[state.f2];
   2441     dst[0] = verts[state.f0];
   2442     dst[1] = verts[state.f1];
   2443     dst[2] = verts[state.f2];
   2444     return matrix->setPolyToPoly(src, dst, 3);
   2445 }
   2446 
   2447 class SkTriColorShader : public SkShader {
   2448 public:
   2449     SkTriColorShader() {}
   2450 
   2451     bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
   2452 
   2453     virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
   2454 
   2455     SK_DEVELOPER_TO_STRING()
   2456     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
   2457 
   2458 protected:
   2459     SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {}
   2460 
   2461 private:
   2462     SkMatrix    fDstToUnit;
   2463     SkPMColor   fColors[3];
   2464 
   2465     typedef SkShader INHERITED;
   2466 };
   2467 
   2468 bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[],
   2469                              int index0, int index1, int index2) {
   2470 
   2471     fColors[0] = SkPreMultiplyColor(colors[index0]);
   2472     fColors[1] = SkPreMultiplyColor(colors[index1]);
   2473     fColors[2] = SkPreMultiplyColor(colors[index2]);
   2474 
   2475     SkMatrix m, im;
   2476     m.reset();
   2477     m.set(0, pts[index1].fX - pts[index0].fX);
   2478     m.set(1, pts[index2].fX - pts[index0].fX);
   2479     m.set(2, pts[index0].fX);
   2480     m.set(3, pts[index1].fY - pts[index0].fY);
   2481     m.set(4, pts[index2].fY - pts[index0].fY);
   2482     m.set(5, pts[index0].fY);
   2483     if (!m.invert(&im)) {
   2484         return false;
   2485     }
   2486     return fDstToUnit.setConcat(im, this->getTotalInverse());
   2487 }
   2488 
   2489 #include "SkColorPriv.h"
   2490 #include "SkComposeShader.h"
   2491 
   2492 static int ScalarTo256(SkScalar v) {
   2493     int scale = SkScalarToFixed(v) >> 8;
   2494     if (scale < 0) {
   2495         scale = 0;
   2496     }
   2497     if (scale > 255) {
   2498         scale = 255;
   2499     }
   2500     return SkAlpha255To256(scale);
   2501 }
   2502 
   2503 void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
   2504     SkPoint src;
   2505 
   2506     for (int i = 0; i < count; i++) {
   2507         fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
   2508         x += 1;
   2509 
   2510         int scale1 = ScalarTo256(src.fX);
   2511         int scale2 = ScalarTo256(src.fY);
   2512         int scale0 = 256 - scale1 - scale2;
   2513         if (scale0 < 0) {
   2514             if (scale1 > scale2) {
   2515                 scale2 = 256 - scale1;
   2516             } else {
   2517                 scale1 = 256 - scale2;
   2518             }
   2519             scale0 = 0;
   2520         }
   2521 
   2522         dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
   2523         SkAlphaMulQ(fColors[1], scale1) +
   2524         SkAlphaMulQ(fColors[2], scale2);
   2525     }
   2526 }
   2527 
   2528 #ifdef SK_DEVELOPER
   2529 void SkTriColorShader::toString(SkString* str) const {
   2530     str->append("SkTriColorShader: (");
   2531 
   2532     this->INHERITED::toString(str);
   2533 
   2534     str->append(")");
   2535 }
   2536 #endif
   2537 
   2538 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
   2539                           const SkPoint vertices[], const SkPoint textures[],
   2540                           const SkColor colors[], SkXfermode* xmode,
   2541                           const uint16_t indices[], int indexCount,
   2542                           const SkPaint& paint) const {
   2543     SkASSERT(0 == count || NULL != vertices);
   2544 
   2545     // abort early if there is nothing to draw
   2546     if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
   2547         return;
   2548     }
   2549 
   2550     // transform out vertices into device coordinates
   2551     SkAutoSTMalloc<16, SkPoint> storage(count);
   2552     SkPoint* devVerts = storage.get();
   2553     fMatrix->mapPoints(devVerts, vertices, count);
   2554 
   2555     if (fBounder) {
   2556         SkRect bounds;
   2557         bounds.set(devVerts, count);
   2558         if (!fBounder->doRect(bounds, paint)) {
   2559             return;
   2560         }
   2561     }
   2562 
   2563     /*
   2564         We can draw the vertices in 1 of 4 ways:
   2565 
   2566         - solid color (no shader/texture[], no colors[])
   2567         - just colors (no shader/texture[], has colors[])
   2568         - just texture (has shader/texture[], no colors[])
   2569         - colors * texture (has shader/texture[], has colors[])
   2570 
   2571         Thus for texture drawing, we need both texture[] and a shader.
   2572     */
   2573 
   2574     SkTriColorShader triShader; // must be above declaration of p
   2575     SkPaint p(paint);
   2576 
   2577     SkShader* shader = p.getShader();
   2578     if (NULL == shader) {
   2579         // if we have no shader, we ignore the texture coordinates
   2580         textures = NULL;
   2581     } else if (NULL == textures) {
   2582         // if we don't have texture coordinates, ignore the shader
   2583         p.setShader(NULL);
   2584         shader = NULL;
   2585     }
   2586 
   2587     // setup the custom shader (if needed)
   2588     if (NULL != colors) {
   2589         if (NULL == textures) {
   2590             // just colors (no texture)
   2591             shader = p.setShader(&triShader);
   2592         } else {
   2593             // colors * texture
   2594             SkASSERT(shader);
   2595             bool releaseMode = false;
   2596             if (NULL == xmode) {
   2597                 xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
   2598                 releaseMode = true;
   2599             }
   2600             SkShader* compose = SkNEW_ARGS(SkComposeShader,
   2601                                            (&triShader, shader, xmode));
   2602             p.setShader(compose)->unref();
   2603             if (releaseMode) {
   2604                 xmode->unref();
   2605             }
   2606             shader = compose;
   2607         }
   2608     }
   2609 
   2610     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
   2611     // important that we abort early, as below we may manipulate the shader
   2612     // and that is only valid if the shader returned true from setContext.
   2613     // If it returned false, then our blitter will be the NullBlitter.
   2614     if (blitter->isNullBlitter()) {
   2615         return;
   2616     }
   2617 
   2618     // setup our state and function pointer for iterating triangles
   2619     VertState       state(count, indices, indexCount);
   2620     VertState::Proc vertProc = state.chooseProc(vmode);
   2621 
   2622     if (NULL != textures || NULL != colors) {
   2623         SkMatrix  tempM;
   2624         SkMatrix  savedLocalM;
   2625         if (shader) {
   2626             savedLocalM = shader->getLocalMatrix();
   2627         }
   2628 
   2629         // setContext has already been called and verified to return true
   2630         // by the constructor of SkAutoBlitterChoose
   2631         bool prevContextSuccess = true;
   2632         while (vertProc(&state)) {
   2633             if (NULL != textures) {
   2634                 if (texture_to_matrix(state, vertices, textures, &tempM)) {
   2635                     tempM.postConcat(savedLocalM);
   2636                     shader->setLocalMatrix(tempM);
   2637                     // Need to recall setContext since we changed the local matrix.
   2638                     // However, we also need to balance the calls this with a
   2639                     // call to endContext which requires tracking the result of
   2640                     // the previous call to setContext.
   2641                     if (prevContextSuccess) {
   2642                         shader->endContext();
   2643                     }
   2644                     prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix);
   2645                     if (!prevContextSuccess) {
   2646                         continue;
   2647                     }
   2648                 }
   2649             }
   2650             if (NULL != colors) {
   2651                 if (!triShader.setup(vertices, colors,
   2652                                      state.f0, state.f1, state.f2)) {
   2653                     continue;
   2654                 }
   2655             }
   2656 
   2657             SkPoint tmp[] = {
   2658                 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
   2659             };
   2660             SkScan::FillTriangle(tmp, *fRC, blitter.get());
   2661         }
   2662 
   2663         // now restore the shader's original local matrix
   2664         if (NULL != shader) {
   2665             shader->setLocalMatrix(savedLocalM);
   2666         }
   2667 
   2668         // If the final call to setContext fails we must make it suceed so that the
   2669         // call to endContext in the destructor for SkAutoBlitterChoose is balanced.
   2670         if (!prevContextSuccess) {
   2671             prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I());
   2672             SkASSERT(prevContextSuccess);
   2673         }
   2674     } else {
   2675         // no colors[] and no texture
   2676         HairProc hairProc = ChooseHairProc(paint.isAntiAlias());
   2677         const SkRasterClip& clip = *fRC;
   2678         while (vertProc(&state)) {
   2679             hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get());
   2680             hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get());
   2681             hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get());
   2682         }
   2683     }
   2684 }
   2685 
   2686 ///////////////////////////////////////////////////////////////////////////////
   2687 ///////////////////////////////////////////////////////////////////////////////
   2688 
   2689 #ifdef SK_DEBUG
   2690 
   2691 void SkDraw::validate() const {
   2692     SkASSERT(fBitmap != NULL);
   2693     SkASSERT(fMatrix != NULL);
   2694     SkASSERT(fClip != NULL);
   2695     SkASSERT(fRC != NULL);
   2696 
   2697     const SkIRect&  cr = fRC->getBounds();
   2698     SkIRect         br;
   2699 
   2700     br.set(0, 0, fBitmap->width(), fBitmap->height());
   2701     SkASSERT(cr.isEmpty() || br.contains(cr));
   2702 }
   2703 
   2704 #endif
   2705 
   2706 ///////////////////////////////////////////////////////////////////////////////
   2707 
   2708 SkBounder::SkBounder() {
   2709     // initialize up front. This gets reset by SkCanvas before each draw call.
   2710     fClip = &SkRegion::GetEmptyRegion();
   2711 }
   2712 
   2713 bool SkBounder::doIRect(const SkIRect& r) {
   2714     SkIRect    rr;
   2715     return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr);
   2716 }
   2717 
   2718 // TODO: change the prototype to take fixed, and update the callers
   2719 bool SkBounder::doIRectGlyph(const SkIRect& r, int x, int y,
   2720                              const SkGlyph& glyph) {
   2721     SkIRect    rr;
   2722     if (!rr.intersect(fClip->getBounds(), r)) {
   2723         return false;
   2724     }
   2725     GlyphRec rec;
   2726     rec.fLSB.set(SkIntToFixed(x), SkIntToFixed(y));
   2727     rec.fRSB.set(rec.fLSB.fX + glyph.fAdvanceX,
   2728                  rec.fLSB.fY + glyph.fAdvanceY);
   2729     rec.fGlyphID = glyph.getGlyphID();
   2730     rec.fFlags = 0;
   2731     return this->onIRectGlyph(rr, rec);
   2732 }
   2733 
   2734 bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1,
   2735                            const SkPaint& paint) {
   2736     SkIRect     r;
   2737     SkScalar    v0, v1;
   2738 
   2739     v0 = pt0.fX;
   2740     v1 = pt1.fX;
   2741     if (v0 > v1) {
   2742         SkTSwap<SkScalar>(v0, v1);
   2743     }
   2744     r.fLeft     = SkScalarFloor(v0);
   2745     r.fRight    = SkScalarCeil(v1);
   2746 
   2747     v0 = pt0.fY;
   2748     v1 = pt1.fY;
   2749     if (v0 > v1) {
   2750         SkTSwap<SkScalar>(v0, v1);
   2751     }
   2752     r.fTop      = SkScalarFloor(v0);
   2753     r.fBottom   = SkScalarCeil(v1);
   2754 
   2755     if (paint.isAntiAlias()) {
   2756         r.inset(-1, -1);
   2757     }
   2758     return this->doIRect(r);
   2759 }
   2760 
   2761 bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) {
   2762     SkIRect    r;
   2763 
   2764     if (paint.getStyle() == SkPaint::kFill_Style) {
   2765         rect.round(&r);
   2766     } else {
   2767         int rad = -1;
   2768         rect.roundOut(&r);
   2769         if (paint.isAntiAlias()) {
   2770             rad = -2;
   2771         }
   2772         r.inset(rad, rad);
   2773     }
   2774     return this->doIRect(r);
   2775 }
   2776 
   2777 bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) {
   2778     SkIRect       r;
   2779     const SkRect& bounds = path.getBounds();
   2780 
   2781     if (doFill) {
   2782         bounds.round(&r);
   2783     } else {    // hairline
   2784         bounds.roundOut(&r);
   2785     }
   2786 
   2787     if (paint.isAntiAlias()) {
   2788         r.inset(-1, -1);
   2789     }
   2790     return this->doIRect(r);
   2791 }
   2792 
   2793 void SkBounder::commit() {
   2794     // override in subclass
   2795 }
   2796 
   2797 ////////////////////////////////////////////////////////////////////////////////////////////////
   2798 
   2799 #include "SkPath.h"
   2800 #include "SkDraw.h"
   2801 #include "SkRegion.h"
   2802 #include "SkBlitter.h"
   2803 
   2804 static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
   2805                        const SkMaskFilter* filter, const SkMatrix* filterMatrix,
   2806                            SkIRect* bounds) {
   2807     if (devPath.isEmpty()) {
   2808         return false;
   2809     }
   2810 
   2811     //  init our bounds from the path
   2812     {
   2813         SkRect pathBounds = devPath.getBounds();
   2814         pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf);
   2815         pathBounds.roundOut(bounds);
   2816     }
   2817 
   2818     SkIPoint margin = SkIPoint::Make(0, 0);
   2819     if (filter) {
   2820         SkASSERT(filterMatrix);
   2821 
   2822         SkMask srcM, dstM;
   2823 
   2824         srcM.fBounds = *bounds;
   2825         srcM.fFormat = SkMask::kA8_Format;
   2826         srcM.fImage = NULL;
   2827         if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
   2828             return false;
   2829         }
   2830     }
   2831 
   2832     // (possibly) trim the bounds to reflect the clip
   2833     // (plus whatever slop the filter needs)
   2834     if (clipBounds) {
   2835         SkIRect tmp = *clipBounds;
   2836         // Ugh. Guard against gigantic margins from wacky filters. Without this
   2837         // check we can request arbitrary amounts of slop beyond our visible
   2838         // clip, and bring down the renderer (at least on finite RAM machines
   2839         // like handsets, etc.). Need to balance this invented value between
   2840         // quality of large filters like blurs, and the corresponding memory
   2841         // requests.
   2842         static const int MAX_MARGIN = 128;
   2843         tmp.inset(-SkMin32(margin.fX, MAX_MARGIN),
   2844                   -SkMin32(margin.fY, MAX_MARGIN));
   2845         if (!bounds->intersect(tmp)) {
   2846             return false;
   2847         }
   2848     }
   2849 
   2850     return true;
   2851 }
   2852 
   2853 static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
   2854                            SkPaint::Style style) {
   2855     SkBitmap        bm;
   2856     SkDraw          draw;
   2857     SkRasterClip    clip;
   2858     SkMatrix        matrix;
   2859     SkPaint         paint;
   2860 
   2861     bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes);
   2862     bm.setPixels(mask.fImage);
   2863 
   2864     clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
   2865     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
   2866                         -SkIntToScalar(mask.fBounds.fTop));
   2867 
   2868     draw.fBitmap    = &bm;
   2869     draw.fRC        = &clip;
   2870     draw.fClip      = &clip.bwRgn();
   2871     draw.fMatrix    = &matrix;
   2872     draw.fBounder   = NULL;
   2873     paint.setAntiAlias(true);
   2874     paint.setStyle(style);
   2875     draw.drawPath(devPath, paint);
   2876 }
   2877 
   2878 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
   2879                         const SkMaskFilter* filter, const SkMatrix* filterMatrix,
   2880                         SkMask* mask, SkMask::CreateMode mode,
   2881                         SkPaint::Style style) {
   2882     if (SkMask::kJustRenderImage_CreateMode != mode) {
   2883         if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
   2884             return false;
   2885     }
   2886 
   2887     if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
   2888         mask->fFormat = SkMask::kA8_Format;
   2889         mask->fRowBytes = mask->fBounds.width();
   2890         size_t size = mask->computeImageSize();
   2891         if (0 == size) {
   2892             // we're too big to allocate the mask, abort
   2893             return false;
   2894         }
   2895         mask->fImage = SkMask::AllocImage(size);
   2896         memset(mask->fImage, 0, mask->computeImageSize());
   2897     }
   2898 
   2899     if (SkMask::kJustComputeBounds_CreateMode != mode) {
   2900         draw_into_mask(*mask, devPath, style);
   2901     }
   2902 
   2903     return true;
   2904 }
   2905 
   2906