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