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 #define __STDC_LIMIT_MACROS
      8 
      9 #include "SkDraw.h"
     10 #include "SkBlitter.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 "SkSmallAllocator.h"
     25 #include "SkString.h"
     26 #include "SkStroke.h"
     27 #include "SkTextMapStateProc.h"
     28 #include "SkTLazy.h"
     29 #include "SkUtils.h"
     30 #include "SkVertState.h"
     31 
     32 #include "SkAutoKern.h"
     33 #include "SkBitmapProcShader.h"
     34 #include "SkDrawProcs.h"
     35 #include "SkMatrixUtils.h"
     36 
     37 //#define TRACE_BITMAP_DRAWS
     38 
     39 
     40 /** Helper for allocating small blitters on the stack.
     41  */
     42 class SkAutoBlitterChoose : SkNoncopyable {
     43 public:
     44     SkAutoBlitterChoose() {
     45         fBlitter = NULL;
     46     }
     47     SkAutoBlitterChoose(const SkBitmap& device, const SkMatrix& matrix,
     48                         const SkPaint& paint, bool drawCoverage = false) {
     49         fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
     50                                      drawCoverage);
     51     }
     52 
     53     SkBlitter*  operator->() { return fBlitter; }
     54     SkBlitter*  get() const { return fBlitter; }
     55 
     56     void choose(const SkBitmap& device, const SkMatrix& matrix,
     57                 const SkPaint& paint, bool drawCoverage = false) {
     58         SkASSERT(!fBlitter);
     59         fBlitter = SkBlitter::Choose(device, matrix, paint, &fAllocator,
     60                                      drawCoverage);
     61     }
     62 
     63 private:
     64     // Owned by fAllocator, which will handle the delete.
     65     SkBlitter*          fBlitter;
     66     SkTBlitterAllocator fAllocator;
     67 };
     68 #define SkAutoBlitterChoose(...) SK_REQUIRE_LOCAL_VAR(SkAutoBlitterChoose)
     69 
     70 /**
     71  *  Since we are providing the storage for the shader (to avoid the perf cost
     72  *  of calling new) we insist that in our destructor we can account for all
     73  *  owners of the shader.
     74  */
     75 class SkAutoBitmapShaderInstall : SkNoncopyable {
     76 public:
     77     SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint,
     78                               const SkMatrix* localMatrix = NULL)
     79             : fPaint(paint) /* makes a copy of the paint */ {
     80         fPaint.setShader(SkCreateBitmapShader(src, SkShader::kClamp_TileMode,
     81                                               SkShader::kClamp_TileMode,
     82                                               localMatrix, &fAllocator));
     83         // we deliberately left the shader with an owner-count of 2
     84         SkASSERT(2 == fPaint.getShader()->getRefCnt());
     85     }
     86 
     87     ~SkAutoBitmapShaderInstall() {
     88         // since fAllocator will destroy shader, we insist that owners == 2
     89         SkASSERT(2 == fPaint.getShader()->getRefCnt());
     90 
     91         fPaint.setShader(NULL); // unref the shader by 1
     92 
     93     }
     94 
     95     // return the new paint that has the shader applied
     96     const SkPaint& paintWithShader() const { return fPaint; }
     97 
     98 private:
     99     // copy of caller's paint (which we then modify)
    100     SkPaint             fPaint;
    101     // Stores the shader.
    102     SkTBlitterAllocator fAllocator;
    103 };
    104 #define SkAutoBitmapShaderInstall(...) SK_REQUIRE_LOCAL_VAR(SkAutoBitmapShaderInstall)
    105 
    106 ///////////////////////////////////////////////////////////////////////////////
    107 
    108 SkDraw::SkDraw() {
    109     sk_bzero(this, sizeof(*this));
    110 }
    111 
    112 SkDraw::SkDraw(const SkDraw& src) {
    113     memcpy(this, &src, sizeof(*this));
    114 }
    115 
    116 bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
    117     if (fRC->isEmpty()) {
    118         return false;
    119     }
    120 
    121     SkMatrix inverse;
    122     if (!fMatrix->invert(&inverse)) {
    123         return false;
    124     }
    125 
    126     SkIRect devBounds = fRC->getBounds();
    127     // outset to have slop for antialasing and hairlines
    128     devBounds.outset(1, 1);
    129     inverse.mapRect(localBounds, SkRect::Make(devBounds));
    130     return true;
    131 }
    132 
    133 ///////////////////////////////////////////////////////////////////////////////
    134 
    135 typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data);
    136 
    137 static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) {
    138     sk_bzero(pixels, bytes);
    139 }
    140 
    141 static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {}
    142 
    143 static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
    144     sk_memset32((uint32_t*)pixels, data, SkToInt(bytes >> 2));
    145 }
    146 
    147 static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
    148     sk_memset16((uint16_t*)pixels, data, SkToInt(bytes >> 1));
    149 }
    150 
    151 static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) {
    152     memset(pixels, data, bytes);
    153 }
    154 
    155 static BitmapXferProc ChooseBitmapXferProc(const SkBitmap& bitmap,
    156                                            const SkPaint& paint,
    157                                            uint32_t* data) {
    158     // todo: we can apply colorfilter up front if no shader, so we wouldn't
    159     // need to abort this fastpath
    160     if (paint.getShader() || paint.getColorFilter()) {
    161         return NULL;
    162     }
    163 
    164     SkXfermode::Mode mode;
    165     if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) {
    166         return NULL;
    167     }
    168 
    169     SkColor color = paint.getColor();
    170 
    171     // collaps modes based on color...
    172     if (SkXfermode::kSrcOver_Mode == mode) {
    173         unsigned alpha = SkColorGetA(color);
    174         if (0 == alpha) {
    175             mode = SkXfermode::kDst_Mode;
    176         } else if (0xFF == alpha) {
    177             mode = SkXfermode::kSrc_Mode;
    178         }
    179     }
    180 
    181     switch (mode) {
    182         case SkXfermode::kClear_Mode:
    183 //            SkDebugf("--- D_Clear_BitmapXferProc\n");
    184             return D_Clear_BitmapXferProc;  // ignore data
    185         case SkXfermode::kDst_Mode:
    186 //            SkDebugf("--- D_Dst_BitmapXferProc\n");
    187             return D_Dst_BitmapXferProc;    // ignore data
    188         case SkXfermode::kSrc_Mode: {
    189             /*
    190                 should I worry about dithering for the lower depths?
    191             */
    192             SkPMColor pmc = SkPreMultiplyColor(color);
    193             switch (bitmap.colorType()) {
    194                 case kN32_SkColorType:
    195                     if (data) {
    196                         *data = pmc;
    197                     }
    198 //                    SkDebugf("--- D32_Src_BitmapXferProc\n");
    199                     return D32_Src_BitmapXferProc;
    200                 case kRGB_565_SkColorType:
    201                     if (data) {
    202                         *data = SkPixel32ToPixel16(pmc);
    203                     }
    204 //                    SkDebugf("--- D16_Src_BitmapXferProc\n");
    205                     return D16_Src_BitmapXferProc;
    206                 case kAlpha_8_SkColorType:
    207                     if (data) {
    208                         *data = SkGetPackedA32(pmc);
    209                     }
    210 //                    SkDebugf("--- DA8_Src_BitmapXferProc\n");
    211                     return DA8_Src_BitmapXferProc;
    212                 default:
    213                     break;
    214             }
    215             break;
    216         }
    217         default:
    218             break;
    219     }
    220     return NULL;
    221 }
    222 
    223 static void CallBitmapXferProc(const SkBitmap& bitmap, const SkIRect& rect,
    224                                BitmapXferProc proc, uint32_t procData) {
    225     int shiftPerPixel;
    226     switch (bitmap.colorType()) {
    227         case kN32_SkColorType:
    228             shiftPerPixel = 2;
    229             break;
    230         case kRGB_565_SkColorType:
    231             shiftPerPixel = 1;
    232             break;
    233         case kAlpha_8_SkColorType:
    234             shiftPerPixel = 0;
    235             break;
    236         default:
    237             SkDEBUGFAIL("Can't use xferproc on this config");
    238             return;
    239     }
    240 
    241     uint8_t* pixels = (uint8_t*)bitmap.getPixels();
    242     SkASSERT(pixels);
    243     const size_t rowBytes = bitmap.rowBytes();
    244     const int widthBytes = rect.width() << shiftPerPixel;
    245 
    246     // skip down to the first scanline and X position
    247     pixels += rect.fTop * rowBytes + (rect.fLeft << shiftPerPixel);
    248     for (int scans = rect.height() - 1; scans >= 0; --scans) {
    249         proc(pixels, widthBytes, procData);
    250         pixels += rowBytes;
    251     }
    252 }
    253 
    254 void SkDraw::drawPaint(const SkPaint& paint) const {
    255     SkDEBUGCODE(this->validate();)
    256 
    257     if (fRC->isEmpty()) {
    258         return;
    259     }
    260 
    261     SkIRect    devRect;
    262     devRect.set(0, 0, fBitmap->width(), fBitmap->height());
    263 
    264     if (fRC->isBW()) {
    265         /*  If we don't have a shader (i.e. we're just a solid color) we may
    266             be faster to operate directly on the device bitmap, rather than invoking
    267             a blitter. Esp. true for xfermodes, which require a colorshader to be
    268             present, which is just redundant work. Since we're drawing everywhere
    269             in the clip, we don't have to worry about antialiasing.
    270         */
    271         uint32_t procData = 0;  // to avoid the warning
    272         BitmapXferProc proc = ChooseBitmapXferProc(*fBitmap, paint, &procData);
    273         if (proc) {
    274             if (D_Dst_BitmapXferProc == proc) { // nothing to do
    275                 return;
    276             }
    277 
    278             SkRegion::Iterator iter(fRC->bwRgn());
    279             while (!iter.done()) {
    280                 CallBitmapXferProc(*fBitmap, iter.rect(), proc, procData);
    281                 iter.next();
    282             }
    283             return;
    284         }
    285     }
    286 
    287     // normal case: use a blitter
    288     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
    289     SkScan::FillIRect(devRect, *fRC, blitter.get());
    290 }
    291 
    292 ///////////////////////////////////////////////////////////////////////////////
    293 
    294 struct PtProcRec {
    295     SkCanvas::PointMode fMode;
    296     const SkPaint*  fPaint;
    297     const SkRegion* fClip;
    298     const SkRasterClip* fRC;
    299 
    300     // computed values
    301     SkFixed fRadius;
    302 
    303     typedef void (*Proc)(const PtProcRec&, const SkPoint devPts[], int count,
    304                          SkBlitter*);
    305 
    306     bool init(SkCanvas::PointMode, const SkPaint&, const SkMatrix* matrix,
    307               const SkRasterClip*);
    308     Proc chooseProc(SkBlitter** blitter);
    309 
    310 private:
    311     SkAAClipBlitterWrapper fWrapper;
    312 };
    313 
    314 static void bw_pt_rect_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
    315                                  int count, SkBlitter* blitter) {
    316     SkASSERT(rec.fClip->isRect());
    317     const SkIRect& r = rec.fClip->getBounds();
    318 
    319     for (int i = 0; i < count; i++) {
    320         int x = SkScalarFloorToInt(devPts[i].fX);
    321         int y = SkScalarFloorToInt(devPts[i].fY);
    322         if (r.contains(x, y)) {
    323             blitter->blitH(x, y, 1);
    324         }
    325     }
    326 }
    327 
    328 static void bw_pt_rect_16_hair_proc(const PtProcRec& rec,
    329                                     const SkPoint devPts[], int count,
    330                                     SkBlitter* blitter) {
    331     SkASSERT(rec.fRC->isRect());
    332     const SkIRect& r = rec.fRC->getBounds();
    333     uint32_t value;
    334     const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
    335     SkASSERT(bitmap);
    336 
    337     uint16_t* addr = bitmap->getAddr16(0, 0);
    338     size_t    rb = bitmap->rowBytes();
    339 
    340     for (int i = 0; i < count; i++) {
    341         int x = SkScalarFloorToInt(devPts[i].fX);
    342         int y = SkScalarFloorToInt(devPts[i].fY);
    343         if (r.contains(x, y)) {
    344             ((uint16_t*)((char*)addr + y * rb))[x] = SkToU16(value);
    345         }
    346     }
    347 }
    348 
    349 static void bw_pt_rect_32_hair_proc(const PtProcRec& rec,
    350                                     const SkPoint devPts[], int count,
    351                                     SkBlitter* blitter) {
    352     SkASSERT(rec.fRC->isRect());
    353     const SkIRect& r = rec.fRC->getBounds();
    354     uint32_t value;
    355     const SkBitmap* bitmap = blitter->justAnOpaqueColor(&value);
    356     SkASSERT(bitmap);
    357 
    358     SkPMColor* addr = bitmap->getAddr32(0, 0);
    359     size_t     rb = bitmap->rowBytes();
    360 
    361     for (int i = 0; i < count; i++) {
    362         int x = SkScalarFloorToInt(devPts[i].fX);
    363         int y = SkScalarFloorToInt(devPts[i].fY);
    364         if (r.contains(x, y)) {
    365             ((SkPMColor*)((char*)addr + y * rb))[x] = value;
    366         }
    367     }
    368 }
    369 
    370 static void bw_pt_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
    371                             int count, SkBlitter* blitter) {
    372     for (int i = 0; i < count; i++) {
    373         int x = SkScalarFloorToInt(devPts[i].fX);
    374         int y = SkScalarFloorToInt(devPts[i].fY);
    375         if (rec.fClip->contains(x, y)) {
    376             blitter->blitH(x, y, 1);
    377         }
    378     }
    379 }
    380 
    381 static void bw_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
    382                               int count, SkBlitter* blitter) {
    383     for (int i = 0; i < count; i += 2) {
    384         SkScan::HairLine(&devPts[i], 2, *rec.fRC, blitter);
    385     }
    386 }
    387 
    388 static void bw_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
    389                               int count, SkBlitter* blitter) {
    390     SkScan::HairLine(devPts, count, *rec.fRC, blitter);
    391 }
    392 
    393 // aa versions
    394 
    395 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
    396                               int count, SkBlitter* blitter) {
    397     for (int i = 0; i < count; i += 2) {
    398         SkScan::AntiHairLine(&devPts[i], 2, *rec.fRC, blitter);
    399     }
    400 }
    401 
    402 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[],
    403                               int count, SkBlitter* blitter) {
    404     SkScan::AntiHairLine(devPts, count, *rec.fRC, blitter);
    405 }
    406 
    407 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy)
    408 
    409 static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[],
    410                            int count, SkBlitter* blitter) {
    411     const SkFixed radius = rec.fRadius;
    412     for (int i = 0; i < count; i++) {
    413         SkFixed x = SkScalarToFixed(devPts[i].fX);
    414         SkFixed y = SkScalarToFixed(devPts[i].fY);
    415 
    416         SkXRect r;
    417         r.fLeft = x - radius;
    418         r.fTop = y - radius;
    419         r.fRight = x + radius;
    420         r.fBottom = y + radius;
    421 
    422         SkScan::FillXRect(r, *rec.fRC, blitter);
    423     }
    424 }
    425 
    426 static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[],
    427                            int count, SkBlitter* blitter) {
    428     const SkFixed radius = rec.fRadius;
    429     for (int i = 0; i < count; i++) {
    430         SkFixed x = SkScalarToFixed(devPts[i].fX);
    431         SkFixed y = SkScalarToFixed(devPts[i].fY);
    432 
    433         SkXRect r;
    434         r.fLeft = x - radius;
    435         r.fTop = y - radius;
    436         r.fRight = x + radius;
    437         r.fBottom = y + radius;
    438 
    439         SkScan::AntiFillXRect(r, *rec.fRC, blitter);
    440     }
    441 }
    442 
    443 // If this guy returns true, then chooseProc() must return a valid proc
    444 bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint,
    445                      const SkMatrix* matrix, const SkRasterClip* rc) {
    446     if (paint.getPathEffect()) {
    447         return false;
    448     }
    449     SkScalar width = paint.getStrokeWidth();
    450     if (0 == width) {
    451         fMode = mode;
    452         fPaint = &paint;
    453         fClip = NULL;
    454         fRC = rc;
    455         fRadius = SK_FixedHalf;
    456         return true;
    457     }
    458     if (paint.getStrokeCap() != SkPaint::kRound_Cap &&
    459         matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) {
    460         SkScalar sx = matrix->get(SkMatrix::kMScaleX);
    461         SkScalar sy = matrix->get(SkMatrix::kMScaleY);
    462         if (SkScalarNearlyZero(sx - sy)) {
    463             if (sx < 0) {
    464                 sx = -sx;
    465             }
    466 
    467             fMode = mode;
    468             fPaint = &paint;
    469             fClip = NULL;
    470             fRC = rc;
    471             fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1;
    472             return true;
    473         }
    474     }
    475     return false;
    476 }
    477 
    478 PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) {
    479     Proc proc = NULL;
    480 
    481     SkBlitter* blitter = *blitterPtr;
    482     if (fRC->isBW()) {
    483         fClip = &fRC->bwRgn();
    484     } else {
    485         fWrapper.init(*fRC, blitter);
    486         fClip = &fWrapper.getRgn();
    487         blitter = fWrapper.getBlitter();
    488         *blitterPtr = blitter;
    489     }
    490 
    491     // for our arrays
    492     SkASSERT(0 == SkCanvas::kPoints_PointMode);
    493     SkASSERT(1 == SkCanvas::kLines_PointMode);
    494     SkASSERT(2 == SkCanvas::kPolygon_PointMode);
    495     SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode);
    496 
    497     if (fPaint->isAntiAlias()) {
    498         if (0 == fPaint->getStrokeWidth()) {
    499             static const Proc gAAProcs[] = {
    500                 aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc
    501             };
    502             proc = gAAProcs[fMode];
    503         } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) {
    504             SkASSERT(SkCanvas::kPoints_PointMode == fMode);
    505             proc = aa_square_proc;
    506         }
    507     } else {    // BW
    508         if (fRadius <= SK_FixedHalf) {    // small radii and hairline
    509             if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) {
    510                 uint32_t value;
    511                 const SkBitmap* bm = blitter->justAnOpaqueColor(&value);
    512                 if (bm && kRGB_565_SkColorType == bm->colorType()) {
    513                     proc = bw_pt_rect_16_hair_proc;
    514                 } else if (bm && kN32_SkColorType == bm->colorType()) {
    515                     proc = bw_pt_rect_32_hair_proc;
    516                 } else {
    517                     proc = bw_pt_rect_hair_proc;
    518                 }
    519             } else {
    520                 static Proc gBWProcs[] = {
    521                     bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc
    522                 };
    523                 proc = gBWProcs[fMode];
    524             }
    525         } else {
    526             proc = bw_square_proc;
    527         }
    528     }
    529     return proc;
    530 }
    531 
    532 // each of these costs 8-bytes of stack space, so don't make it too large
    533 // must be even for lines/polygon to work
    534 #define MAX_DEV_PTS     32
    535 
    536 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count,
    537                         const SkPoint pts[], const SkPaint& paint,
    538                         bool forceUseDevice) const {
    539     // if we're in lines mode, force count to be even
    540     if (SkCanvas::kLines_PointMode == mode) {
    541         count &= ~(size_t)1;
    542     }
    543 
    544     if ((long)count <= 0) {
    545         return;
    546     }
    547 
    548     SkASSERT(pts != NULL);
    549     SkDEBUGCODE(this->validate();)
    550 
    551      // nothing to draw
    552     if (fRC->isEmpty()) {
    553         return;
    554     }
    555 
    556     PtProcRec rec;
    557     if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) {
    558         SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
    559 
    560         SkPoint             devPts[MAX_DEV_PTS];
    561         const SkMatrix*     matrix = fMatrix;
    562         SkBlitter*          bltr = blitter.get();
    563         PtProcRec::Proc     proc = rec.chooseProc(&bltr);
    564         // we have to back up subsequent passes if we're in polygon mode
    565         const size_t backup = (SkCanvas::kPolygon_PointMode == mode);
    566 
    567         do {
    568             int n = SkToInt(count);
    569             if (n > MAX_DEV_PTS) {
    570                 n = MAX_DEV_PTS;
    571             }
    572             matrix->mapPoints(devPts, pts, n);
    573             proc(rec, devPts, n, bltr);
    574             pts += n - backup;
    575             SkASSERT(SkToInt(count) >= n);
    576             count -= n;
    577             if (count > 0) {
    578                 count += backup;
    579             }
    580         } while (count != 0);
    581     } else {
    582         switch (mode) {
    583             case SkCanvas::kPoints_PointMode: {
    584                 // temporarily mark the paint as filling.
    585                 SkPaint newPaint(paint);
    586                 newPaint.setStyle(SkPaint::kFill_Style);
    587 
    588                 SkScalar width = newPaint.getStrokeWidth();
    589                 SkScalar radius = SkScalarHalf(width);
    590 
    591                 if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) {
    592                     SkPath      path;
    593                     SkMatrix    preMatrix;
    594 
    595                     path.addCircle(0, 0, radius);
    596                     for (size_t i = 0; i < count; i++) {
    597                         preMatrix.setTranslate(pts[i].fX, pts[i].fY);
    598                         // pass true for the last point, since we can modify
    599                         // then path then
    600                         path.setIsVolatile((count-1) == i);
    601                         if (fDevice) {
    602                             fDevice->drawPath(*this, path, newPaint, &preMatrix,
    603                                               (count-1) == i);
    604                         } else {
    605                             this->drawPath(path, newPaint, &preMatrix,
    606                                            (count-1) == i);
    607                         }
    608                     }
    609                 } else {
    610                     SkRect  r;
    611 
    612                     for (size_t i = 0; i < count; i++) {
    613                         r.fLeft = pts[i].fX - radius;
    614                         r.fTop = pts[i].fY - radius;
    615                         r.fRight = r.fLeft + width;
    616                         r.fBottom = r.fTop + width;
    617                         if (fDevice) {
    618                             fDevice->drawRect(*this, r, newPaint);
    619                         } else {
    620                             this->drawRect(r, newPaint);
    621                         }
    622                     }
    623                 }
    624                 break;
    625             }
    626             case SkCanvas::kLines_PointMode:
    627                 if (2 == count && paint.getPathEffect()) {
    628                     // most likely a dashed line - see if it is one of the ones
    629                     // we can accelerate
    630                     SkStrokeRec rec(paint);
    631                     SkPathEffect::PointData pointData;
    632 
    633                     SkPath path;
    634                     path.moveTo(pts[0]);
    635                     path.lineTo(pts[1]);
    636 
    637                     SkRect cullRect = SkRect::Make(fRC->getBounds());
    638 
    639                     if (paint.getPathEffect()->asPoints(&pointData, path, rec,
    640                                                         *fMatrix, &cullRect)) {
    641                         // 'asPoints' managed to find some fast path
    642 
    643                         SkPaint newP(paint);
    644                         newP.setPathEffect(NULL);
    645                         newP.setStyle(SkPaint::kFill_Style);
    646 
    647                         if (!pointData.fFirst.isEmpty()) {
    648                             if (fDevice) {
    649                                 fDevice->drawPath(*this, pointData.fFirst, newP);
    650                             } else {
    651                                 this->drawPath(pointData.fFirst, newP);
    652                             }
    653                         }
    654 
    655                         if (!pointData.fLast.isEmpty()) {
    656                             if (fDevice) {
    657                                 fDevice->drawPath(*this, pointData.fLast, newP);
    658                             } else {
    659                                 this->drawPath(pointData.fLast, newP);
    660                             }
    661                         }
    662 
    663                         if (pointData.fSize.fX == pointData.fSize.fY) {
    664                             // The rest of the dashed line can just be drawn as points
    665                             SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth()));
    666 
    667                             if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) {
    668                                 newP.setStrokeCap(SkPaint::kRound_Cap);
    669                             } else {
    670                                 newP.setStrokeCap(SkPaint::kButt_Cap);
    671                             }
    672 
    673                             if (fDevice) {
    674                                 fDevice->drawPoints(*this,
    675                                                     SkCanvas::kPoints_PointMode,
    676                                                     pointData.fNumPoints,
    677                                                     pointData.fPoints,
    678                                                     newP);
    679                             } else {
    680                                 this->drawPoints(SkCanvas::kPoints_PointMode,
    681                                                  pointData.fNumPoints,
    682                                                  pointData.fPoints,
    683                                                  newP,
    684                                                  forceUseDevice);
    685                             }
    686                             break;
    687                         } else {
    688                             // The rest of the dashed line must be drawn as rects
    689                             SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag &
    690                                       pointData.fFlags));
    691 
    692                             SkRect r;
    693 
    694                             for (int i = 0; i < pointData.fNumPoints; ++i) {
    695                                 r.set(pointData.fPoints[i].fX - pointData.fSize.fX,
    696                                       pointData.fPoints[i].fY - pointData.fSize.fY,
    697                                       pointData.fPoints[i].fX + pointData.fSize.fX,
    698                                       pointData.fPoints[i].fY + pointData.fSize.fY);
    699                                 if (fDevice) {
    700                                     fDevice->drawRect(*this, r, newP);
    701                                 } else {
    702                                     this->drawRect(r, newP);
    703                                 }
    704                             }
    705                         }
    706 
    707                         break;
    708                     }
    709                 }
    710                 // couldn't take fast path so fall through!
    711             case SkCanvas::kPolygon_PointMode: {
    712                 count -= 1;
    713                 SkPath path;
    714                 SkPaint p(paint);
    715                 p.setStyle(SkPaint::kStroke_Style);
    716                 size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1;
    717                 path.setIsVolatile(true);
    718                 for (size_t i = 0; i < count; i += inc) {
    719                     path.moveTo(pts[i]);
    720                     path.lineTo(pts[i+1]);
    721                     if (fDevice) {
    722                         fDevice->drawPath(*this, path, p, NULL, true);
    723                     } else {
    724                         this->drawPath(path, p, NULL, true);
    725                     }
    726                     path.rewind();
    727                 }
    728                 break;
    729             }
    730         }
    731     }
    732 }
    733 
    734 static inline SkPoint compute_stroke_size(const SkPaint& paint, const SkMatrix& matrix) {
    735     SkASSERT(matrix.rectStaysRect());
    736     SkASSERT(SkPaint::kFill_Style != paint.getStyle());
    737 
    738     SkVector size;
    739     SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() };
    740     matrix.mapVectors(&size, &pt, 1);
    741     return SkPoint::Make(SkScalarAbs(size.fX), SkScalarAbs(size.fY));
    742 }
    743 
    744 static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix,
    745                            SkPoint* strokeSize) {
    746     if (SkPaint::kMiter_Join != paint.getStrokeJoin() ||
    747         paint.getStrokeMiter() < SK_ScalarSqrt2) {
    748         return false;
    749     }
    750 
    751     *strokeSize = compute_stroke_size(paint, matrix);
    752     return true;
    753 }
    754 
    755 SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint,
    756                                          const SkMatrix& matrix,
    757                                          SkPoint* strokeSize) {
    758     RectType rtype;
    759     const SkScalar width = paint.getStrokeWidth();
    760     const bool zeroWidth = (0 == width);
    761     SkPaint::Style style = paint.getStyle();
    762 
    763     if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) {
    764         style = SkPaint::kFill_Style;
    765     }
    766 
    767     if (paint.getPathEffect() || paint.getMaskFilter() ||
    768         paint.getRasterizer() || !matrix.rectStaysRect() ||
    769         SkPaint::kStrokeAndFill_Style == style) {
    770         rtype = kPath_RectType;
    771     } else if (SkPaint::kFill_Style == style) {
    772         rtype = kFill_RectType;
    773     } else if (zeroWidth) {
    774         rtype = kHair_RectType;
    775     } else if (easy_rect_join(paint, matrix, strokeSize)) {
    776         rtype = kStroke_RectType;
    777     } else {
    778         rtype = kPath_RectType;
    779     }
    780     return rtype;
    781 }
    782 
    783 static const SkPoint* rect_points(const SkRect& r) {
    784     return SkTCast<const SkPoint*>(&r);
    785 }
    786 
    787 static SkPoint* rect_points(SkRect& r) {
    788     return SkTCast<SkPoint*>(&r);
    789 }
    790 
    791 void SkDraw::drawRect(const SkRect& prePaintRect, const SkPaint& paint,
    792                       const SkMatrix* paintMatrix, const SkRect* postPaintRect) const {
    793     SkDEBUGCODE(this->validate();)
    794 
    795     // nothing to draw
    796     if (fRC->isEmpty()) {
    797         return;
    798     }
    799 
    800     const SkMatrix* matrix;
    801     SkMatrix combinedMatrixStorage;
    802     if (paintMatrix) {
    803         SkASSERT(postPaintRect);
    804         combinedMatrixStorage.setConcat(*fMatrix, *paintMatrix);
    805         matrix = &combinedMatrixStorage;
    806     } else {
    807         SkASSERT(!postPaintRect);
    808         matrix = fMatrix;
    809     }
    810 
    811     SkPoint strokeSize;
    812     RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize);
    813 
    814     if (kPath_RectType == rtype) {
    815         SkDraw draw(*this);
    816         if (paintMatrix) {
    817             draw.fMatrix = matrix;
    818         }
    819         SkPath  tmp;
    820         tmp.addRect(prePaintRect);
    821         tmp.setFillType(SkPath::kWinding_FillType);
    822         draw.drawPath(tmp, paint, NULL, true);
    823         return;
    824     }
    825 
    826     SkRect devRect;
    827     const SkRect& paintRect = paintMatrix ? *postPaintRect : prePaintRect;
    828     // skip the paintMatrix when transforming the rect by the CTM
    829     fMatrix->mapPoints(rect_points(devRect), rect_points(paintRect), 2);
    830     devRect.sort();
    831 
    832     // look for the quick exit, before we build a blitter
    833     SkRect bbox = devRect;
    834     if (paint.getStyle() != SkPaint::kFill_Style) {
    835         // extra space for hairlines
    836         if (paint.getStrokeWidth() == 0) {
    837             bbox.outset(1, 1);
    838         } else {
    839             // For kStroke_RectType, strokeSize is already computed.
    840             const SkPoint& ssize = (kStroke_RectType == rtype)
    841                 ? strokeSize
    842                 : compute_stroke_size(paint, *fMatrix);
    843             bbox.outset(SkScalarHalf(ssize.x()), SkScalarHalf(ssize.y()));
    844         }
    845     }
    846 
    847     SkIRect ir = bbox.roundOut();
    848     if (fRC->quickReject(ir)) {
    849         return;
    850     }
    851 
    852     SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
    853     while (looper.next()) {
    854         SkRect localDevRect;
    855         looper.mapRect(&localDevRect, devRect);
    856         SkMatrix localMatrix;
    857         looper.mapMatrix(&localMatrix, *matrix);
    858 
    859         SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, paint);
    860         const SkRasterClip& clip = looper.getRC();
    861         SkBlitter*          blitter = blitterStorage.get();
    862 
    863         // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
    864         // case we are also hairline (if we've gotten to here), which devolves to
    865         // effectively just kFill
    866         switch (rtype) {
    867             case kFill_RectType:
    868                 if (paint.isAntiAlias()) {
    869                     SkScan::AntiFillRect(localDevRect, clip, blitter);
    870                 } else {
    871                     SkScan::FillRect(localDevRect, clip, blitter);
    872                 }
    873                 break;
    874             case kStroke_RectType:
    875                 if (paint.isAntiAlias()) {
    876                     SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
    877                 } else {
    878                     SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
    879                 }
    880                 break;
    881             case kHair_RectType:
    882                 if (paint.isAntiAlias()) {
    883                     SkScan::AntiHairRect(localDevRect, clip, blitter);
    884                 } else {
    885                     SkScan::HairRect(localDevRect, clip, blitter);
    886                 }
    887                 break;
    888             default:
    889                 SkDEBUGFAIL("bad rtype");
    890         }
    891     }
    892 }
    893 
    894 void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const {
    895     if (srcM.fBounds.isEmpty()) {
    896         return;
    897     }
    898 
    899     const SkMask* mask = &srcM;
    900 
    901     SkMask dstM;
    902     if (paint.getMaskFilter() &&
    903             paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) {
    904         mask = &dstM;
    905     } else {
    906         dstM.fImage = NULL;
    907     }
    908     SkAutoMaskFreeImage ami(dstM.fImage);
    909 
    910     SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint);
    911     SkBlitter* blitter = blitterChooser.get();
    912 
    913     SkAAClipBlitterWrapper wrapper;
    914     const SkRegion* clipRgn;
    915 
    916     if (fRC->isBW()) {
    917         clipRgn = &fRC->bwRgn();
    918     } else {
    919         wrapper.init(*fRC, blitter);
    920         clipRgn = &wrapper.getRgn();
    921         blitter = wrapper.getBlitter();
    922     }
    923     blitter->blitMaskRegion(*mask, *clipRgn);
    924 }
    925 
    926 static SkScalar fast_len(const SkVector& vec) {
    927     SkScalar x = SkScalarAbs(vec.fX);
    928     SkScalar y = SkScalarAbs(vec.fY);
    929     if (x < y) {
    930         SkTSwap(x, y);
    931     }
    932     return x + SkScalarHalf(y);
    933 }
    934 
    935 bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
    936                                    SkScalar* coverage) {
    937     SkASSERT(strokeWidth > 0);
    938     // We need to try to fake a thick-stroke with a modulated hairline.
    939 
    940     if (matrix.hasPerspective()) {
    941         return false;
    942     }
    943 
    944     SkVector src[2], dst[2];
    945     src[0].set(strokeWidth, 0);
    946     src[1].set(0, strokeWidth);
    947     matrix.mapVectors(dst, src, 2);
    948     SkScalar len0 = fast_len(dst[0]);
    949     SkScalar len1 = fast_len(dst[1]);
    950     if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
    951         if (coverage) {
    952             *coverage = SkScalarAve(len0, len1);
    953         }
    954         return true;
    955     }
    956     return false;
    957 }
    958 
    959 void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const {
    960     SkDEBUGCODE(this->validate());
    961 
    962     if (fRC->isEmpty()) {
    963         return;
    964     }
    965 
    966     {
    967         // TODO: Investigate optimizing these options. They are in the same
    968         // order as SkDraw::drawPath, which handles each case. It may be
    969         // that there is no way to optimize for these using the SkRRect path.
    970         SkScalar coverage;
    971         if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) {
    972             goto DRAW_PATH;
    973         }
    974 
    975         if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
    976             goto DRAW_PATH;
    977         }
    978 
    979         if (paint.getRasterizer()) {
    980             goto DRAW_PATH;
    981         }
    982     }
    983 
    984     if (paint.getMaskFilter()) {
    985         // Transform the rrect into device space.
    986         SkRRect devRRect;
    987         if (rrect.transform(*fMatrix, &devRRect)) {
    988             SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint);
    989             if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get(),
    990                                                    SkPaint::kFill_Style)) {
    991                 return; // filterRRect() called the blitter, so we're done
    992             }
    993         }
    994     }
    995 
    996 DRAW_PATH:
    997     // Now fall back to the default case of using a path.
    998     SkPath path;
    999     path.addRRect(rrect);
   1000     this->drawPath(path, paint, NULL, true);
   1001 }
   1002 
   1003 static SkScalar compute_res_scale_for_stroking(const SkMatrix& matrix) {
   1004     if (!matrix.hasPerspective()) {
   1005         SkScalar sx = SkPoint::Length(matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewY]);
   1006         SkScalar sy = SkPoint::Length(matrix[SkMatrix::kMSkewX],  matrix[SkMatrix::kMScaleY]);
   1007         if (SkScalarsAreFinite(sx, sy)) {
   1008             return SkTMax(sx, sy);
   1009         }
   1010     }
   1011     return 1;
   1012 }
   1013 
   1014 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
   1015                       const SkMatrix* prePathMatrix, bool pathIsMutable,
   1016                       bool drawCoverage, SkBlitter* customBlitter) const {
   1017     SkDEBUGCODE(this->validate();)
   1018 
   1019     // nothing to draw
   1020     if (fRC->isEmpty()) {
   1021         return;
   1022     }
   1023 
   1024     SkPath*         pathPtr = (SkPath*)&origSrcPath;
   1025     bool            doFill = true;
   1026     SkPath          tmpPath;
   1027     SkMatrix        tmpMatrix;
   1028     const SkMatrix* matrix = fMatrix;
   1029     tmpPath.setIsVolatile(true);
   1030 
   1031     if (prePathMatrix) {
   1032         if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style ||
   1033                 origPaint.getRasterizer()) {
   1034             SkPath* result = pathPtr;
   1035 
   1036             if (!pathIsMutable) {
   1037                 result = &tmpPath;
   1038                 pathIsMutable = true;
   1039             }
   1040             pathPtr->transform(*prePathMatrix, result);
   1041             pathPtr = result;
   1042         } else {
   1043             tmpMatrix.setConcat(*matrix, *prePathMatrix);
   1044             matrix = &tmpMatrix;
   1045         }
   1046     }
   1047     // at this point we're done with prePathMatrix
   1048     SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
   1049 
   1050     SkTCopyOnFirstWrite<SkPaint> paint(origPaint);
   1051 
   1052     {
   1053         SkScalar coverage;
   1054         if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
   1055             if (SK_Scalar1 == coverage) {
   1056                 paint.writable()->setStrokeWidth(0);
   1057             } else if (SkXfermode::SupportsCoverageAsAlpha(origPaint.getXfermode())) {
   1058                 U8CPU newAlpha;
   1059 #if 0
   1060                 newAlpha = SkToU8(SkScalarRoundToInt(coverage *
   1061                                                      origPaint.getAlpha()));
   1062 #else
   1063                 // this is the old technique, which we preserve for now so
   1064                 // we don't change previous results (testing)
   1065                 // the new way seems fine, its just (a tiny bit) different
   1066                 int scale = (int)SkScalarMul(coverage, 256);
   1067                 newAlpha = origPaint.getAlpha() * scale >> 8;
   1068 #endif
   1069                 SkPaint* writablePaint = paint.writable();
   1070                 writablePaint->setStrokeWidth(0);
   1071                 writablePaint->setAlpha(newAlpha);
   1072             }
   1073         }
   1074     }
   1075 
   1076     if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) {
   1077         SkRect cullRect;
   1078         const SkRect* cullRectPtr = NULL;
   1079         if (this->computeConservativeLocalClipBounds(&cullRect)) {
   1080             cullRectPtr = &cullRect;
   1081         }
   1082         doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr,
   1083                                     compute_res_scale_for_stroking(*fMatrix));
   1084         pathPtr = &tmpPath;
   1085     }
   1086 
   1087     if (paint->getRasterizer()) {
   1088         SkMask  mask;
   1089         if (paint->getRasterizer()->rasterize(*pathPtr, *matrix,
   1090                             &fRC->getBounds(), paint->getMaskFilter(), &mask,
   1091                             SkMask::kComputeBoundsAndRenderImage_CreateMode)) {
   1092             this->drawDevMask(mask, *paint);
   1093             SkMask::FreeImage(mask.fImage);
   1094         }
   1095         return;
   1096     }
   1097 
   1098     // avoid possibly allocating a new path in transform if we can
   1099     SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
   1100 
   1101     // transform the path into device space
   1102     pathPtr->transform(*matrix, devPathPtr);
   1103 
   1104     SkBlitter* blitter = NULL;
   1105     SkAutoBlitterChoose blitterStorage;
   1106     if (NULL == customBlitter) {
   1107         blitterStorage.choose(*fBitmap, *fMatrix, *paint, drawCoverage);
   1108         blitter = blitterStorage.get();
   1109     } else {
   1110         blitter = customBlitter;
   1111     }
   1112 
   1113     if (paint->getMaskFilter()) {
   1114         SkPaint::Style style = doFill ? SkPaint::kFill_Style :
   1115             SkPaint::kStroke_Style;
   1116         if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, blitter, style)) {
   1117             return; // filterPath() called the blitter, so we're done
   1118         }
   1119     }
   1120 
   1121     void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*);
   1122     if (doFill) {
   1123         if (paint->isAntiAlias()) {
   1124             proc = SkScan::AntiFillPath;
   1125         } else {
   1126             proc = SkScan::FillPath;
   1127         }
   1128     } else {    // hairline
   1129         if (paint->isAntiAlias()) {
   1130             proc = SkScan::AntiHairPath;
   1131         } else {
   1132             proc = SkScan::HairPath;
   1133         }
   1134     }
   1135     proc(*devPathPtr, *fRC, blitter);
   1136 }
   1137 
   1138 /** For the purposes of drawing bitmaps, if a matrix is "almost" translate
   1139     go ahead and treat it as if it were, so that subsequent code can go fast.
   1140  */
   1141 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) {
   1142     unsigned bits = 0;  // TODO: find a way to allow the caller to tell us to
   1143                         // respect filtering.
   1144     return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits);
   1145 }
   1146 
   1147 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
   1148                               const SkPaint& paint) const {
   1149     SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType);
   1150 
   1151     if (just_translate(*fMatrix, bitmap)) {
   1152         int ix = SkScalarRoundToInt(fMatrix->getTranslateX());
   1153         int iy = SkScalarRoundToInt(fMatrix->getTranslateY());
   1154 
   1155         SkAutoLockPixels alp(bitmap);
   1156         if (!bitmap.readyToDraw()) {
   1157             return;
   1158         }
   1159 
   1160         SkMask  mask;
   1161         mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
   1162         mask.fFormat = SkMask::kA8_Format;
   1163         mask.fRowBytes = SkToU32(bitmap.rowBytes());
   1164         mask.fImage = bitmap.getAddr8(0, 0);
   1165 
   1166         this->drawDevMask(mask, paint);
   1167     } else {    // need to xform the bitmap first
   1168         SkRect  r;
   1169         SkMask  mask;
   1170 
   1171         r.set(0, 0,
   1172               SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height()));
   1173         fMatrix->mapRect(&r);
   1174         r.round(&mask.fBounds);
   1175 
   1176         // set the mask's bounds to the transformed bitmap-bounds,
   1177         // clipped to the actual device
   1178         {
   1179             SkIRect    devBounds;
   1180             devBounds.set(0, 0, fBitmap->width(), fBitmap->height());
   1181             // need intersect(l, t, r, b) on irect
   1182             if (!mask.fBounds.intersect(devBounds)) {
   1183                 return;
   1184             }
   1185         }
   1186 
   1187         mask.fFormat = SkMask::kA8_Format;
   1188         mask.fRowBytes = SkAlign4(mask.fBounds.width());
   1189         size_t size = mask.computeImageSize();
   1190         if (0 == size) {
   1191             // the mask is too big to allocated, draw nothing
   1192             return;
   1193         }
   1194 
   1195         // allocate (and clear) our temp buffer to hold the transformed bitmap
   1196         SkAutoMalloc    storage(size);
   1197         mask.fImage = (uint8_t*)storage.get();
   1198         memset(mask.fImage, 0, size);
   1199 
   1200         // now draw our bitmap(src) into mask(dst), transformed by the matrix
   1201         {
   1202             SkBitmap    device;
   1203             device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
   1204                                  mask.fImage, mask.fRowBytes);
   1205 
   1206             SkCanvas c(device);
   1207             // need the unclipped top/left for the translate
   1208             c.translate(-SkIntToScalar(mask.fBounds.fLeft),
   1209                         -SkIntToScalar(mask.fBounds.fTop));
   1210             c.concat(*fMatrix);
   1211 
   1212             // We can't call drawBitmap, or we'll infinitely recurse. Instead
   1213             // we manually build a shader and draw that into our new mask
   1214             SkPaint tmpPaint;
   1215             tmpPaint.setFlags(paint.getFlags());
   1216             SkAutoBitmapShaderInstall install(bitmap, tmpPaint);
   1217             SkRect rr;
   1218             rr.set(0, 0, SkIntToScalar(bitmap.width()),
   1219                    SkIntToScalar(bitmap.height()));
   1220             c.drawRect(rr, install.paintWithShader());
   1221         }
   1222         this->drawDevMask(mask, paint);
   1223     }
   1224 }
   1225 
   1226 static bool clipped_out(const SkMatrix& m, const SkRasterClip& c,
   1227                         const SkRect& srcR) {
   1228     SkRect  dstR;
   1229     m.mapRect(&dstR, srcR);
   1230     return c.quickReject(dstR.roundOut());
   1231 }
   1232 
   1233 static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip,
   1234                         int width, int height) {
   1235     SkRect  r;
   1236     r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height));
   1237     return clipped_out(matrix, clip, r);
   1238 }
   1239 
   1240 static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y,
   1241                               const SkBitmap& bitmap) {
   1242     return clip.isBW() ||
   1243            clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height());
   1244 }
   1245 
   1246 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
   1247                         const SkRect* dstBounds, const SkPaint& origPaint) const {
   1248     SkDEBUGCODE(this->validate();)
   1249 
   1250     // nothing to draw
   1251     if (fRC->isEmpty() ||
   1252             bitmap.width() == 0 || bitmap.height() == 0 ||
   1253             bitmap.colorType() == kUnknown_SkColorType) {
   1254         return;
   1255     }
   1256 
   1257     SkPaint paint(origPaint);
   1258     paint.setStyle(SkPaint::kFill_Style);
   1259 
   1260     SkMatrix matrix;
   1261     matrix.setConcat(*fMatrix, prematrix);
   1262 
   1263     if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) {
   1264         return;
   1265     }
   1266 
   1267     if (bitmap.colorType() != kAlpha_8_SkColorType && just_translate(matrix, bitmap)) {
   1268         //
   1269         // It is safe to call lock pixels now, since we know the matrix is
   1270         // (more or less) identity.
   1271         //
   1272         SkAutoLockPixels alp(bitmap);
   1273         if (!bitmap.readyToDraw()) {
   1274             return;
   1275         }
   1276         int ix = SkScalarRoundToInt(matrix.getTranslateX());
   1277         int iy = SkScalarRoundToInt(matrix.getTranslateY());
   1278         if (clipHandlesSprite(*fRC, ix, iy, bitmap)) {
   1279             SkTBlitterAllocator allocator;
   1280             // blitter will be owned by the allocator.
   1281             SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
   1282                                                          ix, iy, &allocator);
   1283             if (blitter) {
   1284                 SkIRect    ir;
   1285                 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
   1286 
   1287                 SkScan::FillIRect(ir, *fRC, blitter);
   1288                 return;
   1289             }
   1290         }
   1291     }
   1292 
   1293     // now make a temp draw on the stack, and use it
   1294     //
   1295     SkDraw draw(*this);
   1296     draw.fMatrix = &matrix;
   1297 
   1298     if (bitmap.colorType() == kAlpha_8_SkColorType) {
   1299         draw.drawBitmapAsMask(bitmap, paint);
   1300     } else {
   1301         SkAutoBitmapShaderInstall install(bitmap, paint);
   1302         const SkPaint& paintWithShader = install.paintWithShader();
   1303         const SkRect srcBounds = SkRect::MakeIWH(bitmap.width(), bitmap.height());
   1304         if (dstBounds) {
   1305             this->drawRect(srcBounds, paintWithShader, &prematrix, dstBounds);
   1306         } else {
   1307             draw.drawRect(srcBounds, paintWithShader);
   1308         }
   1309     }
   1310 }
   1311 
   1312 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
   1313                         const SkPaint& origPaint) const {
   1314     SkDEBUGCODE(this->validate();)
   1315 
   1316     // nothing to draw
   1317     if (fRC->isEmpty() ||
   1318             bitmap.width() == 0 || bitmap.height() == 0 ||
   1319             bitmap.colorType() == kUnknown_SkColorType) {
   1320         return;
   1321     }
   1322 
   1323     SkIRect    bounds;
   1324     bounds.set(x, y, x + bitmap.width(), y + bitmap.height());
   1325 
   1326     if (fRC->quickReject(bounds)) {
   1327         return; // nothing to draw
   1328     }
   1329 
   1330     SkPaint paint(origPaint);
   1331     paint.setStyle(SkPaint::kFill_Style);
   1332 
   1333     if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) {
   1334         SkTBlitterAllocator allocator;
   1335         // blitter will be owned by the allocator.
   1336         SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap,
   1337                                                      x, y, &allocator);
   1338 
   1339         if (blitter) {
   1340             SkScan::FillIRect(bounds, *fRC, blitter);
   1341             return;
   1342         }
   1343     }
   1344 
   1345     SkMatrix        matrix;
   1346     SkRect          r;
   1347 
   1348     // get a scalar version of our rect
   1349     r.set(bounds);
   1350 
   1351     // create shader with offset
   1352     matrix.setTranslate(r.fLeft, r.fTop);
   1353     SkAutoBitmapShaderInstall install(bitmap, paint, &matrix);
   1354     const SkPaint& shaderPaint = install.paintWithShader();
   1355 
   1356     SkDraw draw(*this);
   1357     matrix.reset();
   1358     draw.fMatrix = &matrix;
   1359     // call ourself with a rect
   1360     // is this OK if paint has a rasterizer?
   1361     draw.drawRect(r, shaderPaint);
   1362 }
   1363 
   1364 ///////////////////////////////////////////////////////////////////////////////
   1365 
   1366 #include "SkScalerContext.h"
   1367 #include "SkGlyphCache.h"
   1368 #include "SkTextToPathIter.h"
   1369 #include "SkUtils.h"
   1370 
   1371 static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
   1372                 const char text[], size_t byteLength, SkVector* stopVector) {
   1373     SkFixed     x = 0, y = 0;
   1374     const char* stop = text + byteLength;
   1375 
   1376     SkAutoKern  autokern;
   1377 
   1378     while (text < stop) {
   1379         // don't need x, y here, since all subpixel variants will have the
   1380         // same advance
   1381         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   1382 
   1383         x += autokern.adjust(glyph) + glyph.fAdvanceX;
   1384         y += glyph.fAdvanceY;
   1385     }
   1386     stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
   1387 
   1388     SkASSERT(text == stop);
   1389 }
   1390 
   1391 bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) {
   1392     // hairline glyphs are fast enough so we don't need to cache them
   1393     if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) {
   1394         return true;
   1395     }
   1396 
   1397     // we don't cache perspective
   1398     if (ctm.hasPerspective()) {
   1399         return true;
   1400     }
   1401 
   1402     SkMatrix textM;
   1403     return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM));
   1404 }
   1405 
   1406 void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
   1407                               SkScalar x, SkScalar y,
   1408                               const SkPaint& paint) const {
   1409     SkDEBUGCODE(this->validate();)
   1410 
   1411     SkTextToPathIter iter(text, byteLength, paint, true);
   1412 
   1413     SkMatrix    matrix;
   1414     matrix.setScale(iter.getPathScale(), iter.getPathScale());
   1415     matrix.postTranslate(x, y);
   1416 
   1417     const SkPath* iterPath;
   1418     SkScalar xpos, prevXPos = 0;
   1419 
   1420     while (iter.next(&iterPath, &xpos)) {
   1421         matrix.postTranslate(xpos - prevXPos, 0);
   1422         if (iterPath) {
   1423             const SkPaint& pnt = iter.getPaint();
   1424             if (fDevice) {
   1425                 fDevice->drawPath(*this, *iterPath, pnt, &matrix, false);
   1426             } else {
   1427                 this->drawPath(*iterPath, pnt, &matrix, false);
   1428             }
   1429         }
   1430         prevXPos = xpos;
   1431     }
   1432 }
   1433 
   1434 // disable warning : local variable used without having been initialized
   1435 #if defined _WIN32 && _MSC_VER >= 1300
   1436 #pragma warning ( push )
   1437 #pragma warning ( disable : 4701 )
   1438 #endif
   1439 
   1440 //////////////////////////////////////////////////////////////////////////////
   1441 
   1442 static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, const SkGlyph& glyph) {
   1443     // Prevent glyphs from being drawn outside of or straddling the edge of device space.
   1444     if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
   1445         (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
   1446         (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
   1447         (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))
   1448     {
   1449         return;
   1450     }
   1451 
   1452     int left = Sk48Dot16FloorToInt(fx);
   1453     int top = Sk48Dot16FloorToInt(fy);
   1454     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
   1455     SkASSERT((NULL == state.fClip && state.fAAClip) ||
   1456              (state.fClip && NULL == state.fAAClip && state.fClip->isRect()));
   1457 
   1458     left += glyph.fLeft;
   1459     top  += glyph.fTop;
   1460 
   1461     int right   = left + glyph.fWidth;
   1462     int bottom  = top + glyph.fHeight;
   1463 
   1464     SkMask        mask;
   1465     SkIRect        storage;
   1466     SkIRect*    bounds = &mask.fBounds;
   1467 
   1468     mask.fBounds.set(left, top, right, bottom);
   1469 
   1470     // this extra test is worth it, assuming that most of the time it succeeds
   1471     // since we can avoid writing to storage
   1472     if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
   1473         if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
   1474             return;
   1475         bounds = &storage;
   1476     }
   1477 
   1478     uint8_t* aa = (uint8_t*)glyph.fImage;
   1479     if (NULL == aa) {
   1480         aa = (uint8_t*)state.fCache->findImage(glyph);
   1481         if (NULL == aa) {
   1482             return; // can't rasterize glyph
   1483         }
   1484     }
   1485 
   1486     mask.fRowBytes = glyph.rowBytes();
   1487     mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
   1488     mask.fImage = aa;
   1489     state.blitMask(mask, *bounds);
   1490 }
   1491 
   1492 static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, const SkGlyph& glyph) {
   1493     int left = Sk48Dot16FloorToInt(fx);
   1494     int top = Sk48Dot16FloorToInt(fy);
   1495     SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
   1496     SkASSERT(!state.fClip->isRect());
   1497 
   1498     SkMask  mask;
   1499 
   1500     left += glyph.fLeft;
   1501     top  += glyph.fTop;
   1502 
   1503     mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
   1504     SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
   1505 
   1506     if (!clipper.done()) {
   1507         const SkIRect&  cr = clipper.rect();
   1508         const uint8_t*  aa = (const uint8_t*)glyph.fImage;
   1509         if (NULL == aa) {
   1510             aa = (uint8_t*)state.fCache->findImage(glyph);
   1511             if (NULL == aa) {
   1512                 return;
   1513             }
   1514         }
   1515 
   1516         mask.fRowBytes = glyph.rowBytes();
   1517         mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
   1518         mask.fImage = (uint8_t*)aa;
   1519         do {
   1520             state.blitMask(mask, cr);
   1521             clipper.next();
   1522         } while (!clipper.done());
   1523     }
   1524 }
   1525 
   1526 static bool hasCustomD1GProc(const SkDraw& draw) {
   1527     return draw.fProcs && draw.fProcs->fD1GProc;
   1528 }
   1529 
   1530 static bool needsRasterTextBlit(const SkDraw& draw) {
   1531     return !hasCustomD1GProc(draw);
   1532 }
   1533 
   1534 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
   1535                                       const SkPaint& pnt) {
   1536     fDraw = draw;
   1537     fBlitter = blitter;
   1538     fCache = cache;
   1539     fPaint = &pnt;
   1540 
   1541     if (cache->isSubpixel()) {
   1542         fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
   1543     } else {
   1544         fHalfSampleX = fHalfSampleY = SK_ScalarHalf;
   1545     }
   1546 
   1547     if (hasCustomD1GProc(*draw)) {
   1548         // todo: fix this assumption about clips w/ custom
   1549         fClip = draw->fClip;
   1550         fClipBounds = fClip->getBounds();
   1551         return draw->fProcs->fD1GProc;
   1552     }
   1553 
   1554     if (draw->fRC->isBW()) {
   1555         fAAClip = NULL;
   1556         fClip = &draw->fRC->bwRgn();
   1557         fClipBounds = fClip->getBounds();
   1558         if (fClip->isRect()) {
   1559             return D1G_RectClip;
   1560         } else {
   1561             return D1G_RgnClip;
   1562         }
   1563     } else {    // aaclip
   1564         fAAClip = &draw->fRC->aaRgn();
   1565         fClip = NULL;
   1566         fClipBounds = fAAClip->getBounds();
   1567         return D1G_RectClip;
   1568     }
   1569 }
   1570 
   1571 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
   1572     SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
   1573 
   1574     SkBitmap bm;
   1575     bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()),
   1576                      (SkPMColor*)mask.fImage, mask.fRowBytes);
   1577 
   1578     fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
   1579 }
   1580 
   1581 ///////////////////////////////////////////////////////////////////////////////
   1582 
   1583 void SkDraw::drawText(const char text[], size_t byteLength,
   1584                       SkScalar x, SkScalar y, const SkPaint& paint) const {
   1585     SkASSERT(byteLength == 0 || text != NULL);
   1586 
   1587     SkDEBUGCODE(this->validate();)
   1588 
   1589     // nothing to draw
   1590     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
   1591         return;
   1592     }
   1593 
   1594     // SkScalarRec doesn't currently have a way of representing hairline stroke and
   1595     // will fill if its frame-width is 0.
   1596     if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
   1597         this->drawText_asPaths(text, byteLength, x, y, paint);
   1598         return;
   1599     }
   1600 
   1601     SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc();
   1602 
   1603     SkAutoGlyphCache    autoCache(paint, &fDevice->getLeakyProperties(), fMatrix);
   1604     SkGlyphCache*       cache = autoCache.getCache();
   1605 
   1606     // transform our starting point
   1607     {
   1608         SkPoint loc;
   1609         fMatrix->mapXY(x, y, &loc);
   1610         x = loc.fX;
   1611         y = loc.fY;
   1612     }
   1613 
   1614     // need to measure first
   1615     if (paint.getTextAlign() != SkPaint::kLeft_Align) {
   1616         SkVector    stop;
   1617 
   1618         measure_text(cache, glyphCacheProc, text, byteLength, &stop);
   1619 
   1620         SkScalar    stopX = stop.fX;
   1621         SkScalar    stopY = stop.fY;
   1622 
   1623         if (paint.getTextAlign() == SkPaint::kCenter_Align) {
   1624             stopX = SkScalarHalf(stopX);
   1625             stopY = SkScalarHalf(stopY);
   1626         }
   1627         x -= stopX;
   1628         y -= stopY;
   1629     }
   1630 
   1631     const char* stop = text + byteLength;
   1632 
   1633     SkAAClipBlitter     aaBlitter;
   1634     SkAutoBlitterChoose blitterChooser;
   1635     SkBlitter*          blitter = NULL;
   1636     if (needsRasterTextBlit(*this)) {
   1637         blitterChooser.choose(*fBitmap, *fMatrix, paint);
   1638         blitter = blitterChooser.get();
   1639         if (fRC->isAA()) {
   1640             aaBlitter.init(blitter, &fRC->aaRgn());
   1641             blitter = &aaBlitter;
   1642         }
   1643     }
   1644 
   1645     SkAutoKern          autokern;
   1646     SkDraw1Glyph        d1g;
   1647     SkDraw1Glyph::Proc  proc = d1g.init(this, blitter, cache, paint);
   1648 
   1649     SkFixed fxMask = ~0;
   1650     SkFixed fyMask = ~0;
   1651     if (cache->isSubpixel()) {
   1652         SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
   1653         if (kX_SkAxisAlignment == baseline) {
   1654             fyMask = 0;
   1655             d1g.fHalfSampleY = SK_ScalarHalf;
   1656         } else if (kY_SkAxisAlignment == baseline) {
   1657             fxMask = 0;
   1658             d1g.fHalfSampleX = SK_ScalarHalf;
   1659         }
   1660     }
   1661 
   1662     Sk48Dot16 fx = SkScalarTo48Dot16(x + d1g.fHalfSampleX);
   1663     Sk48Dot16 fy = SkScalarTo48Dot16(y + d1g.fHalfSampleY);
   1664 
   1665     while (text < stop) {
   1666         const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
   1667 
   1668         fx += autokern.adjust(glyph);
   1669 
   1670         if (glyph.fWidth) {
   1671             proc(d1g, fx, fy, glyph);
   1672         }
   1673 
   1674         fx += glyph.fAdvanceX;
   1675         fy += glyph.fAdvanceY;
   1676     }
   1677 }
   1678 
   1679 //////////////////////////////////////////////////////////////////////////////
   1680 
   1681 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
   1682                                  const SkScalar pos[], int scalarsPerPosition,
   1683                                  const SkPoint& offset, const SkPaint& origPaint) const {
   1684     // setup our std paint, in hopes of getting hits in the cache
   1685     SkPaint paint(origPaint);
   1686     SkScalar matrixScale = paint.setupForAsPaths();
   1687 
   1688     SkMatrix matrix;
   1689     matrix.setScale(matrixScale, matrixScale);
   1690 
   1691     // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
   1692     paint.setStyle(SkPaint::kFill_Style);
   1693     paint.setPathEffect(NULL);
   1694 
   1695     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
   1696     SkAutoGlyphCache    autoCache(paint, NULL, NULL);
   1697     SkGlyphCache*       cache = autoCache.getCache();
   1698 
   1699     const char*        stop = text + byteLength;
   1700     SkTextAlignProc    alignProc(paint.getTextAlign());
   1701     SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
   1702 
   1703     // Now restore the original settings, so we "draw" with whatever style/stroking.
   1704     paint.setStyle(origPaint.getStyle());
   1705     paint.setPathEffect(origPaint.getPathEffect());
   1706 
   1707     while (text < stop) {
   1708         const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   1709         if (glyph.fWidth) {
   1710             const SkPath* path = cache->findPath(glyph);
   1711             if (path) {
   1712                 SkPoint tmsLoc;
   1713                 tmsProc(pos, &tmsLoc);
   1714                 SkPoint loc;
   1715                 alignProc(tmsLoc, glyph, &loc);
   1716 
   1717                 matrix[SkMatrix::kMTransX] = loc.fX;
   1718                 matrix[SkMatrix::kMTransY] = loc.fY;
   1719                 if (fDevice) {
   1720                     fDevice->drawPath(*this, *path, paint, &matrix, false);
   1721                 } else {
   1722                     this->drawPath(*path, paint, &matrix, false);
   1723                 }
   1724             }
   1725         }
   1726         pos += scalarsPerPosition;
   1727     }
   1728 }
   1729 
   1730 void SkDraw::drawPosText(const char text[], size_t byteLength,
   1731                          const SkScalar pos[], int scalarsPerPosition,
   1732                          const SkPoint& offset, const SkPaint& paint) const {
   1733     SkASSERT(byteLength == 0 || text != NULL);
   1734     SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
   1735 
   1736     SkDEBUGCODE(this->validate();)
   1737 
   1738     // nothing to draw
   1739     if (text == NULL || byteLength == 0 || fRC->isEmpty()) {
   1740         return;
   1741     }
   1742 
   1743     if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
   1744         this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, offset, paint);
   1745         return;
   1746     }
   1747 
   1748     SkDrawCacheProc     glyphCacheProc = paint.getDrawCacheProc();
   1749     SkAutoGlyphCache    autoCache(paint, &fDevice->getLeakyProperties(), fMatrix);
   1750     SkGlyphCache*       cache = autoCache.getCache();
   1751 
   1752     SkAAClipBlitterWrapper wrapper;
   1753     SkAutoBlitterChoose blitterChooser;
   1754     SkBlitter* blitter = NULL;
   1755     if (needsRasterTextBlit(*this)) {
   1756         blitterChooser.choose(*fBitmap, *fMatrix, paint);
   1757         blitter = blitterChooser.get();
   1758         if (fRC->isAA()) {
   1759             wrapper.init(*fRC, blitter);
   1760             blitter = wrapper.getBlitter();
   1761         }
   1762     }
   1763 
   1764     const char*        stop = text + byteLength;
   1765     SkTextAlignProc    alignProc(paint.getTextAlign());
   1766     SkDraw1Glyph       d1g;
   1767     SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint);
   1768     SkTextMapStateProc tmsProc(*fMatrix, offset, scalarsPerPosition);
   1769 
   1770     if (cache->isSubpixel()) {
   1771         // maybe we should skip the rounding if linearText is set
   1772         SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix);
   1773 
   1774         SkFixed fxMask = ~0;
   1775         SkFixed fyMask = ~0;
   1776         if (kX_SkAxisAlignment == baseline) {
   1777             fyMask = 0;
   1778             d1g.fHalfSampleY = SK_ScalarHalf;
   1779         } else if (kY_SkAxisAlignment == baseline) {
   1780             fxMask = 0;
   1781             d1g.fHalfSampleX = SK_ScalarHalf;
   1782         }
   1783 
   1784         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
   1785             while (text < stop) {
   1786                 SkPoint tmsLoc;
   1787                 tmsProc(pos, &tmsLoc);
   1788 
   1789                 Sk48Dot16 fx = SkScalarTo48Dot16(tmsLoc.fX + d1g.fHalfSampleX);
   1790                 Sk48Dot16 fy = SkScalarTo48Dot16(tmsLoc.fY + d1g.fHalfSampleY);
   1791 
   1792                 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask);
   1793 
   1794                 if (glyph.fWidth) {
   1795                     proc(d1g, fx, fy, glyph);
   1796                 }
   1797                 pos += scalarsPerPosition;
   1798             }
   1799         } else {
   1800             while (text < stop) {
   1801                 const char* currentText = text;
   1802                 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0);
   1803 
   1804                 if (metricGlyph.fWidth) {
   1805                     SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;)
   1806                     SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;)
   1807                     SkPoint tmsLoc;
   1808                     tmsProc(pos, &tmsLoc);
   1809 
   1810                     SkPoint alignLoc;
   1811                     alignProc(tmsLoc, metricGlyph, &alignLoc);
   1812 
   1813                     Sk48Dot16 fx = SkScalarTo48Dot16(alignLoc.fX + d1g.fHalfSampleX);
   1814                     Sk48Dot16 fy = SkScalarTo48Dot16(alignLoc.fY + d1g.fHalfSampleY);
   1815 
   1816                     // have to call again, now that we've been "aligned"
   1817                     const SkGlyph& glyph = glyphCacheProc(cache, &currentText,
   1818                                                           fx & fxMask, fy & fyMask);
   1819                     // the assumption is that the metrics haven't changed
   1820                     SkASSERT(prevAdvX == glyph.fAdvanceX);
   1821                     SkASSERT(prevAdvY == glyph.fAdvanceY);
   1822                     SkASSERT(glyph.fWidth);
   1823 
   1824                     proc(d1g, fx, fy, glyph);
   1825                 }
   1826                 pos += scalarsPerPosition;
   1827             }
   1828         }
   1829     } else {    // not subpixel
   1830         if (SkPaint::kLeft_Align == paint.getTextAlign()) {
   1831             while (text < stop) {
   1832                 // the last 2 parameters are ignored
   1833                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   1834 
   1835                 if (glyph.fWidth) {
   1836                     SkPoint tmsLoc;
   1837                     tmsProc(pos, &tmsLoc);
   1838 
   1839                     proc(d1g,
   1840                          SkScalarTo48Dot16(tmsLoc.fX + SK_ScalarHalf), //d1g.fHalfSampleX,
   1841                          SkScalarTo48Dot16(tmsLoc.fY + SK_ScalarHalf), //d1g.fHalfSampleY,
   1842                          glyph);
   1843                 }
   1844                 pos += scalarsPerPosition;
   1845             }
   1846         } else {
   1847             while (text < stop) {
   1848                 // the last 2 parameters are ignored
   1849                 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0);
   1850 
   1851                 if (glyph.fWidth) {
   1852                     SkPoint tmsLoc;
   1853                     tmsProc(pos, &tmsLoc);
   1854 
   1855                     SkPoint alignLoc;
   1856                     alignProc(tmsLoc, glyph, &alignLoc);
   1857 
   1858                     proc(d1g,
   1859                          SkScalarTo48Dot16(alignLoc.fX + SK_ScalarHalf), //d1g.fHalfSampleX,
   1860                          SkScalarTo48Dot16(alignLoc.fY + SK_ScalarHalf), //d1g.fHalfSampleY,
   1861                          glyph);
   1862                 }
   1863                 pos += scalarsPerPosition;
   1864             }
   1865         }
   1866     }
   1867 }
   1868 
   1869 #if defined _WIN32 && _MSC_VER >= 1300
   1870 #pragma warning ( pop )
   1871 #endif
   1872 
   1873 ///////////////////////////////////////////////////////////////////////////////
   1874 
   1875 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
   1876     return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
   1877 }
   1878 
   1879 static bool texture_to_matrix(const VertState& state, const SkPoint verts[],
   1880                               const SkPoint texs[], SkMatrix* matrix) {
   1881     SkPoint src[3], dst[3];
   1882 
   1883     src[0] = texs[state.f0];
   1884     src[1] = texs[state.f1];
   1885     src[2] = texs[state.f2];
   1886     dst[0] = verts[state.f0];
   1887     dst[1] = verts[state.f1];
   1888     dst[2] = verts[state.f2];
   1889     return matrix->setPolyToPoly(src, dst, 3);
   1890 }
   1891 
   1892 class SkTriColorShader : public SkShader {
   1893 public:
   1894     SkTriColorShader() {}
   1895 
   1896     size_t contextSize() const override;
   1897 
   1898     class TriColorShaderContext : public SkShader::Context {
   1899     public:
   1900         TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&);
   1901         virtual ~TriColorShaderContext();
   1902 
   1903         bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
   1904 
   1905         void shadeSpan(int x, int y, SkPMColor dstC[], int count) override;
   1906 
   1907     private:
   1908         SkMatrix    fDstToUnit;
   1909         SkPMColor   fColors[3];
   1910 
   1911         typedef SkShader::Context INHERITED;
   1912     };
   1913 
   1914     SK_TO_STRING_OVERRIDE()
   1915 
   1916     // For serialization.  This will never be called.
   1917     Factory getFactory() const override { sk_throw(); return NULL; }
   1918 
   1919 protected:
   1920     Context* onCreateContext(const ContextRec& rec, void* storage) const override {
   1921         return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec));
   1922     }
   1923 
   1924 private:
   1925     typedef SkShader INHERITED;
   1926 };
   1927 
   1928 bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[],
   1929                                                     int index0, int index1, int index2) {
   1930 
   1931     fColors[0] = SkPreMultiplyColor(colors[index0]);
   1932     fColors[1] = SkPreMultiplyColor(colors[index1]);
   1933     fColors[2] = SkPreMultiplyColor(colors[index2]);
   1934 
   1935     SkMatrix m, im;
   1936     m.reset();
   1937     m.set(0, pts[index1].fX - pts[index0].fX);
   1938     m.set(1, pts[index2].fX - pts[index0].fX);
   1939     m.set(2, pts[index0].fX);
   1940     m.set(3, pts[index1].fY - pts[index0].fY);
   1941     m.set(4, pts[index2].fY - pts[index0].fY);
   1942     m.set(5, pts[index0].fY);
   1943     if (!m.invert(&im)) {
   1944         return false;
   1945     }
   1946     // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix
   1947     // as our interators are intrinsically tied to the vertices, and nothing else.
   1948     SkMatrix ctmInv;
   1949     if (!this->getCTM().invert(&ctmInv)) {
   1950         return false;
   1951     }
   1952     fDstToUnit.setConcat(im, ctmInv);
   1953     return true;
   1954 }
   1955 
   1956 #include "SkColorPriv.h"
   1957 #include "SkComposeShader.h"
   1958 
   1959 static int ScalarTo256(SkScalar v) {
   1960     int scale = SkScalarToFixed(v) >> 8;
   1961     if (scale < 0) {
   1962         scale = 0;
   1963     }
   1964     if (scale > 255) {
   1965         scale = 255;
   1966     }
   1967     return SkAlpha255To256(scale);
   1968 }
   1969 
   1970 
   1971 SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader,
   1972                                                                const ContextRec& rec)
   1973     : INHERITED(shader, rec) {}
   1974 
   1975 SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {}
   1976 
   1977 size_t SkTriColorShader::contextSize() const {
   1978     return sizeof(TriColorShaderContext);
   1979 }
   1980 void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) {
   1981     const int alphaScale = Sk255To256(this->getPaintAlpha());
   1982 
   1983     SkPoint src;
   1984 
   1985     for (int i = 0; i < count; i++) {
   1986         fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src);
   1987         x += 1;
   1988 
   1989         int scale1 = ScalarTo256(src.fX);
   1990         int scale2 = ScalarTo256(src.fY);
   1991         int scale0 = 256 - scale1 - scale2;
   1992         if (scale0 < 0) {
   1993             if (scale1 > scale2) {
   1994                 scale2 = 256 - scale1;
   1995             } else {
   1996                 scale1 = 256 - scale2;
   1997             }
   1998             scale0 = 0;
   1999         }
   2000 
   2001         if (256 != alphaScale) {
   2002             scale0 = SkAlphaMul(scale0, alphaScale);
   2003             scale1 = SkAlphaMul(scale1, alphaScale);
   2004             scale2 = SkAlphaMul(scale2, alphaScale);
   2005         }
   2006 
   2007         dstC[i] = SkAlphaMulQ(fColors[0], scale0) +
   2008                   SkAlphaMulQ(fColors[1], scale1) +
   2009                   SkAlphaMulQ(fColors[2], scale2);
   2010     }
   2011 }
   2012 
   2013 #ifndef SK_IGNORE_TO_STRING
   2014 void SkTriColorShader::toString(SkString* str) const {
   2015     str->append("SkTriColorShader: (");
   2016 
   2017     this->INHERITED::toString(str);
   2018 
   2019     str->append(")");
   2020 }
   2021 #endif
   2022 
   2023 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
   2024                           const SkPoint vertices[], const SkPoint textures[],
   2025                           const SkColor colors[], SkXfermode* xmode,
   2026                           const uint16_t indices[], int indexCount,
   2027                           const SkPaint& paint) const {
   2028     SkASSERT(0 == count || vertices);
   2029 
   2030     // abort early if there is nothing to draw
   2031     if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) {
   2032         return;
   2033     }
   2034 
   2035     // transform out vertices into device coordinates
   2036     SkAutoSTMalloc<16, SkPoint> storage(count);
   2037     SkPoint* devVerts = storage.get();
   2038     fMatrix->mapPoints(devVerts, vertices, count);
   2039 
   2040     /*
   2041         We can draw the vertices in 1 of 4 ways:
   2042 
   2043         - solid color (no shader/texture[], no colors[])
   2044         - just colors (no shader/texture[], has colors[])
   2045         - just texture (has shader/texture[], no colors[])
   2046         - colors * texture (has shader/texture[], has colors[])
   2047 
   2048         Thus for texture drawing, we need both texture[] and a shader.
   2049     */
   2050 
   2051     SkTriColorShader triShader; // must be above declaration of p
   2052     SkPaint p(paint);
   2053 
   2054     SkShader* shader = p.getShader();
   2055     if (NULL == shader) {
   2056         // if we have no shader, we ignore the texture coordinates
   2057         textures = NULL;
   2058     } else if (NULL == textures) {
   2059         // if we don't have texture coordinates, ignore the shader
   2060         p.setShader(NULL);
   2061         shader = NULL;
   2062     }
   2063 
   2064     // setup the custom shader (if needed)
   2065     SkAutoTUnref<SkComposeShader> composeShader;
   2066     if (colors) {
   2067         if (NULL == textures) {
   2068             // just colors (no texture)
   2069             shader = p.setShader(&triShader);
   2070         } else {
   2071             // colors * texture
   2072             SkASSERT(shader);
   2073             bool releaseMode = false;
   2074             if (NULL == xmode) {
   2075                 xmode = SkXfermode::Create(SkXfermode::kModulate_Mode);
   2076                 releaseMode = true;
   2077             }
   2078             composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode)));
   2079             p.setShader(composeShader);
   2080             if (releaseMode) {
   2081                 xmode->unref();
   2082             }
   2083         }
   2084     }
   2085 
   2086     SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p);
   2087     // Abort early if we failed to create a shader context.
   2088     if (blitter->isNullBlitter()) {
   2089         return;
   2090     }
   2091 
   2092     // setup our state and function pointer for iterating triangles
   2093     VertState       state(count, indices, indexCount);
   2094     VertState::Proc vertProc = state.chooseProc(vmode);
   2095 
   2096     if (textures || colors) {
   2097         while (vertProc(&state)) {
   2098             if (textures) {
   2099                 SkMatrix tempM;
   2100                 if (texture_to_matrix(state, vertices, textures, &tempM)) {
   2101                     SkShader::ContextRec rec(*fBitmap, p, *fMatrix);
   2102                     rec.fLocalMatrix = &tempM;
   2103                     if (!blitter->resetShaderContext(rec)) {
   2104                         continue;
   2105                     }
   2106                 }
   2107             }
   2108             if (colors) {
   2109                 // Find the context for triShader.
   2110                 SkTriColorShader::TriColorShaderContext* triColorShaderContext;
   2111 
   2112                 SkShader::Context* shaderContext = blitter->getShaderContext();
   2113                 SkASSERT(shaderContext);
   2114                 if (p.getShader() == &triShader) {
   2115                     triColorShaderContext =
   2116                             static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext);
   2117                 } else {
   2118                     // The shader is a compose shader and triShader is its first shader.
   2119                     SkASSERT(p.getShader() == composeShader);
   2120                     SkASSERT(composeShader->getShaderA() == &triShader);
   2121                     SkComposeShader::ComposeShaderContext* composeShaderContext =
   2122                             static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext);
   2123                     SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA();
   2124                     triColorShaderContext =
   2125                             static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA);
   2126                 }
   2127 
   2128                 if (!triColorShaderContext->setup(vertices, colors,
   2129                                                   state.f0, state.f1, state.f2)) {
   2130                     continue;
   2131                 }
   2132             }
   2133 
   2134             SkPoint tmp[] = {
   2135                 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2]
   2136             };
   2137             SkScan::FillTriangle(tmp, *fRC, blitter.get());
   2138         }
   2139     } else {
   2140         // no colors[] and no texture, stroke hairlines with paint's color.
   2141         SkScan::HairRCProc hairProc = ChooseHairProc(paint.isAntiAlias());
   2142         const SkRasterClip& clip = *fRC;
   2143         while (vertProc(&state)) {
   2144             SkPoint array[] = {
   2145                 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2], devVerts[state.f0]
   2146             };
   2147             hairProc(array, 4, clip, blitter.get());
   2148         }
   2149     }
   2150 }
   2151 
   2152 ///////////////////////////////////////////////////////////////////////////////
   2153 ///////////////////////////////////////////////////////////////////////////////
   2154 
   2155 #ifdef SK_DEBUG
   2156 
   2157 void SkDraw::validate() const {
   2158     SkASSERT(fBitmap != NULL);
   2159     SkASSERT(fMatrix != NULL);
   2160     SkASSERT(fClip != NULL);
   2161     SkASSERT(fRC != NULL);
   2162 
   2163     const SkIRect&  cr = fRC->getBounds();
   2164     SkIRect         br;
   2165 
   2166     br.set(0, 0, fBitmap->width(), fBitmap->height());
   2167     SkASSERT(cr.isEmpty() || br.contains(cr));
   2168 }
   2169 
   2170 #endif
   2171 
   2172 ////////////////////////////////////////////////////////////////////////////////////////////////
   2173 
   2174 #include "SkPath.h"
   2175 #include "SkDraw.h"
   2176 #include "SkRegion.h"
   2177 #include "SkBlitter.h"
   2178 
   2179 static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds,
   2180                            const SkMaskFilter* filter, const SkMatrix* filterMatrix,
   2181                            SkIRect* bounds) {
   2182     if (devPath.isEmpty()) {
   2183         return false;
   2184     }
   2185 
   2186     //  init our bounds from the path
   2187     *bounds = devPath.getBounds().makeOutset(SK_ScalarHalf, SK_ScalarHalf).roundOut();
   2188 
   2189     SkIPoint margin = SkIPoint::Make(0, 0);
   2190     if (filter) {
   2191         SkASSERT(filterMatrix);
   2192 
   2193         SkMask srcM, dstM;
   2194 
   2195         srcM.fBounds = *bounds;
   2196         srcM.fFormat = SkMask::kA8_Format;
   2197         srcM.fImage = NULL;
   2198         if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) {
   2199             return false;
   2200         }
   2201     }
   2202 
   2203     // (possibly) trim the bounds to reflect the clip
   2204     // (plus whatever slop the filter needs)
   2205     if (clipBounds) {
   2206         // Ugh. Guard against gigantic margins from wacky filters. Without this
   2207         // check we can request arbitrary amounts of slop beyond our visible
   2208         // clip, and bring down the renderer (at least on finite RAM machines
   2209         // like handsets, etc.). Need to balance this invented value between
   2210         // quality of large filters like blurs, and the corresponding memory
   2211         // requests.
   2212         static const int MAX_MARGIN = 128;
   2213         if (!bounds->intersect(clipBounds->makeOutset(SkMin32(margin.fX, MAX_MARGIN),
   2214                                                       SkMin32(margin.fY, MAX_MARGIN)))) {
   2215             return false;
   2216         }
   2217     }
   2218 
   2219     return true;
   2220 }
   2221 
   2222 static void draw_into_mask(const SkMask& mask, const SkPath& devPath,
   2223                            SkPaint::Style style) {
   2224     SkBitmap        bm;
   2225     SkDraw          draw;
   2226     SkRasterClip    clip;
   2227     SkMatrix        matrix;
   2228     SkPaint         paint;
   2229 
   2230     bm.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()),
   2231                      mask.fImage, mask.fRowBytes);
   2232 
   2233     clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height()));
   2234     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
   2235                         -SkIntToScalar(mask.fBounds.fTop));
   2236 
   2237     draw.fBitmap    = &bm;
   2238     draw.fRC        = &clip;
   2239     draw.fClip      = &clip.bwRgn();
   2240     draw.fMatrix    = &matrix;
   2241     paint.setAntiAlias(true);
   2242     paint.setStyle(style);
   2243     draw.drawPath(devPath, paint);
   2244 }
   2245 
   2246 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
   2247                         const SkMaskFilter* filter, const SkMatrix* filterMatrix,
   2248                         SkMask* mask, SkMask::CreateMode mode,
   2249                         SkPaint::Style style) {
   2250     if (SkMask::kJustRenderImage_CreateMode != mode) {
   2251         if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds))
   2252             return false;
   2253     }
   2254 
   2255     if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) {
   2256         mask->fFormat = SkMask::kA8_Format;
   2257         mask->fRowBytes = mask->fBounds.width();
   2258         size_t size = mask->computeImageSize();
   2259         if (0 == size) {
   2260             // we're too big to allocate the mask, abort
   2261             return false;
   2262         }
   2263         mask->fImage = SkMask::AllocImage(size);
   2264         memset(mask->fImage, 0, mask->computeImageSize());
   2265     }
   2266 
   2267     if (SkMask::kJustComputeBounds_CreateMode != mode) {
   2268         draw_into_mask(*mask, devPath, style);
   2269     }
   2270 
   2271     return true;
   2272 }
   2273