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