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