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