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