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