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