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