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