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