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