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