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 8 #include "SkDraw.h" 9 #include "SkBlitter.h" 10 #include "SkCanvas.h" 11 #include "SkColorPriv.h" 12 #include "SkDevice.h" 13 #include "SkDeviceLooper.h" 14 #include "SkFixed.h" 15 #include "SkMaskFilter.h" 16 #include "SkPaint.h" 17 #include "SkPathEffect.h" 18 #include "SkRasterClip.h" 19 #include "SkRasterizer.h" 20 #include "SkRRect.h" 21 #include "SkScan.h" 22 #include "SkShader.h" 23 #include "SkSmallAllocator.h" 24 #include "SkString.h" 25 #include "SkStroke.h" 26 #include "SkTextMapStateProc.h" 27 #include "SkTLazy.h" 28 #include "SkUtils.h" 29 #include "SkVertState.h" 30 31 #include "SkAutoKern.h" 32 #include "SkBitmapProcShader.h" 33 #include "SkDrawProcs.h" 34 #include "SkMatrixUtils.h" 35 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(CreateBitmapShader(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], devPts[i+1], *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 for (int i = 0; i < count - 1; i++) { 391 SkScan::HairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 392 } 393 } 394 395 // aa versions 396 397 static void aa_line_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 398 int count, SkBlitter* blitter) { 399 for (int i = 0; i < count; i += 2) { 400 SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 401 } 402 } 403 404 static void aa_poly_hair_proc(const PtProcRec& rec, const SkPoint devPts[], 405 int count, SkBlitter* blitter) { 406 for (int i = 0; i < count - 1; i++) { 407 SkScan::AntiHairLine(devPts[i], devPts[i+1], *rec.fRC, blitter); 408 } 409 } 410 411 // square procs (strokeWidth > 0 but matrix is square-scale (sx == sy) 412 413 static void bw_square_proc(const PtProcRec& rec, const SkPoint devPts[], 414 int count, SkBlitter* blitter) { 415 const SkFixed radius = rec.fRadius; 416 for (int i = 0; i < count; i++) { 417 SkFixed x = SkScalarToFixed(devPts[i].fX); 418 SkFixed y = SkScalarToFixed(devPts[i].fY); 419 420 SkXRect r; 421 r.fLeft = x - radius; 422 r.fTop = y - radius; 423 r.fRight = x + radius; 424 r.fBottom = y + radius; 425 426 SkScan::FillXRect(r, *rec.fRC, blitter); 427 } 428 } 429 430 static void aa_square_proc(const PtProcRec& rec, const SkPoint devPts[], 431 int count, SkBlitter* blitter) { 432 const SkFixed radius = rec.fRadius; 433 for (int i = 0; i < count; i++) { 434 SkFixed x = SkScalarToFixed(devPts[i].fX); 435 SkFixed y = SkScalarToFixed(devPts[i].fY); 436 437 SkXRect r; 438 r.fLeft = x - radius; 439 r.fTop = y - radius; 440 r.fRight = x + radius; 441 r.fBottom = y + radius; 442 443 SkScan::AntiFillXRect(r, *rec.fRC, blitter); 444 } 445 } 446 447 // If this guy returns true, then chooseProc() must return a valid proc 448 bool PtProcRec::init(SkCanvas::PointMode mode, const SkPaint& paint, 449 const SkMatrix* matrix, const SkRasterClip* rc) { 450 if (paint.getPathEffect()) { 451 return false; 452 } 453 SkScalar width = paint.getStrokeWidth(); 454 if (0 == width) { 455 fMode = mode; 456 fPaint = &paint; 457 fClip = NULL; 458 fRC = rc; 459 fRadius = SK_FixedHalf; 460 return true; 461 } 462 if (paint.getStrokeCap() != SkPaint::kRound_Cap && 463 matrix->isScaleTranslate() && SkCanvas::kPoints_PointMode == mode) { 464 SkScalar sx = matrix->get(SkMatrix::kMScaleX); 465 SkScalar sy = matrix->get(SkMatrix::kMScaleY); 466 if (SkScalarNearlyZero(sx - sy)) { 467 if (sx < 0) { 468 sx = -sx; 469 } 470 471 fMode = mode; 472 fPaint = &paint; 473 fClip = NULL; 474 fRC = rc; 475 fRadius = SkScalarToFixed(SkScalarMul(width, sx)) >> 1; 476 return true; 477 } 478 } 479 return false; 480 } 481 482 PtProcRec::Proc PtProcRec::chooseProc(SkBlitter** blitterPtr) { 483 Proc proc = NULL; 484 485 SkBlitter* blitter = *blitterPtr; 486 if (fRC->isBW()) { 487 fClip = &fRC->bwRgn(); 488 } else { 489 fWrapper.init(*fRC, blitter); 490 fClip = &fWrapper.getRgn(); 491 blitter = fWrapper.getBlitter(); 492 *blitterPtr = blitter; 493 } 494 495 // for our arrays 496 SkASSERT(0 == SkCanvas::kPoints_PointMode); 497 SkASSERT(1 == SkCanvas::kLines_PointMode); 498 SkASSERT(2 == SkCanvas::kPolygon_PointMode); 499 SkASSERT((unsigned)fMode <= (unsigned)SkCanvas::kPolygon_PointMode); 500 501 if (fPaint->isAntiAlias()) { 502 if (0 == fPaint->getStrokeWidth()) { 503 static const Proc gAAProcs[] = { 504 aa_square_proc, aa_line_hair_proc, aa_poly_hair_proc 505 }; 506 proc = gAAProcs[fMode]; 507 } else if (fPaint->getStrokeCap() != SkPaint::kRound_Cap) { 508 SkASSERT(SkCanvas::kPoints_PointMode == fMode); 509 proc = aa_square_proc; 510 } 511 } else { // BW 512 if (fRadius <= SK_FixedHalf) { // small radii and hairline 513 if (SkCanvas::kPoints_PointMode == fMode && fClip->isRect()) { 514 uint32_t value; 515 const SkBitmap* bm = blitter->justAnOpaqueColor(&value); 516 if (bm && kRGB_565_SkColorType == bm->colorType()) { 517 proc = bw_pt_rect_16_hair_proc; 518 } else if (bm && kN32_SkColorType == bm->colorType()) { 519 proc = bw_pt_rect_32_hair_proc; 520 } else { 521 proc = bw_pt_rect_hair_proc; 522 } 523 } else { 524 static Proc gBWProcs[] = { 525 bw_pt_hair_proc, bw_line_hair_proc, bw_poly_hair_proc 526 }; 527 proc = gBWProcs[fMode]; 528 } 529 } else { 530 proc = bw_square_proc; 531 } 532 } 533 return proc; 534 } 535 536 // each of these costs 8-bytes of stack space, so don't make it too large 537 // must be even for lines/polygon to work 538 #define MAX_DEV_PTS 32 539 540 void SkDraw::drawPoints(SkCanvas::PointMode mode, size_t count, 541 const SkPoint pts[], const SkPaint& paint, 542 bool forceUseDevice) const { 543 // if we're in lines mode, force count to be even 544 if (SkCanvas::kLines_PointMode == mode) { 545 count &= ~(size_t)1; 546 } 547 548 if ((long)count <= 0) { 549 return; 550 } 551 552 SkASSERT(pts != NULL); 553 SkDEBUGCODE(this->validate();) 554 555 // nothing to draw 556 if (fRC->isEmpty()) { 557 return; 558 } 559 560 PtProcRec rec; 561 if (!forceUseDevice && rec.init(mode, paint, fMatrix, fRC)) { 562 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 563 564 SkPoint devPts[MAX_DEV_PTS]; 565 const SkMatrix* matrix = fMatrix; 566 SkBlitter* bltr = blitter.get(); 567 PtProcRec::Proc proc = rec.chooseProc(&bltr); 568 // we have to back up subsequent passes if we're in polygon mode 569 const size_t backup = (SkCanvas::kPolygon_PointMode == mode); 570 571 do { 572 int n = SkToInt(count); 573 if (n > MAX_DEV_PTS) { 574 n = MAX_DEV_PTS; 575 } 576 matrix->mapPoints(devPts, pts, n); 577 proc(rec, devPts, n, bltr); 578 pts += n - backup; 579 SkASSERT(SkToInt(count) >= n); 580 count -= n; 581 if (count > 0) { 582 count += backup; 583 } 584 } while (count != 0); 585 } else { 586 switch (mode) { 587 case SkCanvas::kPoints_PointMode: { 588 // temporarily mark the paint as filling. 589 SkPaint newPaint(paint); 590 newPaint.setStyle(SkPaint::kFill_Style); 591 592 SkScalar width = newPaint.getStrokeWidth(); 593 SkScalar radius = SkScalarHalf(width); 594 595 if (newPaint.getStrokeCap() == SkPaint::kRound_Cap) { 596 SkPath path; 597 SkMatrix preMatrix; 598 599 path.addCircle(0, 0, radius); 600 for (size_t i = 0; i < count; i++) { 601 preMatrix.setTranslate(pts[i].fX, pts[i].fY); 602 // pass true for the last point, since we can modify 603 // then path then 604 if (fDevice) { 605 fDevice->drawPath(*this, path, newPaint, &preMatrix, 606 (count-1) == i); 607 } else { 608 this->drawPath(path, newPaint, &preMatrix, 609 (count-1) == i); 610 } 611 } 612 } else { 613 SkRect r; 614 615 for (size_t i = 0; i < count; i++) { 616 r.fLeft = pts[i].fX - radius; 617 r.fTop = pts[i].fY - radius; 618 r.fRight = r.fLeft + width; 619 r.fBottom = r.fTop + width; 620 if (fDevice) { 621 fDevice->drawRect(*this, r, newPaint); 622 } else { 623 this->drawRect(r, newPaint); 624 } 625 } 626 } 627 break; 628 } 629 case SkCanvas::kLines_PointMode: 630 #ifndef SK_DISABLE_DASHING_OPTIMIZATION 631 if (2 == count && paint.getPathEffect()) { 632 // most likely a dashed line - see if it is one of the ones 633 // we can accelerate 634 SkStrokeRec rec(paint); 635 SkPathEffect::PointData pointData; 636 637 SkPath path; 638 path.moveTo(pts[0]); 639 path.lineTo(pts[1]); 640 641 SkRect cullRect = SkRect::Make(fRC->getBounds()); 642 643 if (paint.getPathEffect()->asPoints(&pointData, path, rec, 644 *fMatrix, &cullRect)) { 645 // 'asPoints' managed to find some fast path 646 647 SkPaint newP(paint); 648 newP.setPathEffect(NULL); 649 newP.setStyle(SkPaint::kFill_Style); 650 651 if (!pointData.fFirst.isEmpty()) { 652 if (fDevice) { 653 fDevice->drawPath(*this, pointData.fFirst, newP); 654 } else { 655 this->drawPath(pointData.fFirst, newP); 656 } 657 } 658 659 if (!pointData.fLast.isEmpty()) { 660 if (fDevice) { 661 fDevice->drawPath(*this, pointData.fLast, newP); 662 } else { 663 this->drawPath(pointData.fLast, newP); 664 } 665 } 666 667 if (pointData.fSize.fX == pointData.fSize.fY) { 668 // The rest of the dashed line can just be drawn as points 669 SkASSERT(pointData.fSize.fX == SkScalarHalf(newP.getStrokeWidth())); 670 671 if (SkPathEffect::PointData::kCircles_PointFlag & pointData.fFlags) { 672 newP.setStrokeCap(SkPaint::kRound_Cap); 673 } else { 674 newP.setStrokeCap(SkPaint::kButt_Cap); 675 } 676 677 if (fDevice) { 678 fDevice->drawPoints(*this, 679 SkCanvas::kPoints_PointMode, 680 pointData.fNumPoints, 681 pointData.fPoints, 682 newP); 683 } else { 684 this->drawPoints(SkCanvas::kPoints_PointMode, 685 pointData.fNumPoints, 686 pointData.fPoints, 687 newP, 688 forceUseDevice); 689 } 690 break; 691 } else { 692 // The rest of the dashed line must be drawn as rects 693 SkASSERT(!(SkPathEffect::PointData::kCircles_PointFlag & 694 pointData.fFlags)); 695 696 SkRect r; 697 698 for (int i = 0; i < pointData.fNumPoints; ++i) { 699 r.set(pointData.fPoints[i].fX - pointData.fSize.fX, 700 pointData.fPoints[i].fY - pointData.fSize.fY, 701 pointData.fPoints[i].fX + pointData.fSize.fX, 702 pointData.fPoints[i].fY + pointData.fSize.fY); 703 if (fDevice) { 704 fDevice->drawRect(*this, r, newP); 705 } else { 706 this->drawRect(r, newP); 707 } 708 } 709 } 710 711 break; 712 } 713 } 714 #endif // DISABLE_DASHING_OPTIMIZATION 715 // couldn't take fast path so fall through! 716 case SkCanvas::kPolygon_PointMode: { 717 count -= 1; 718 SkPath path; 719 SkPaint p(paint); 720 p.setStyle(SkPaint::kStroke_Style); 721 size_t inc = (SkCanvas::kLines_PointMode == mode) ? 2 : 1; 722 for (size_t i = 0; i < count; i += inc) { 723 path.moveTo(pts[i]); 724 path.lineTo(pts[i+1]); 725 if (fDevice) { 726 fDevice->drawPath(*this, path, p, NULL, true); 727 } else { 728 this->drawPath(path, p, NULL, true); 729 } 730 path.rewind(); 731 } 732 break; 733 } 734 } 735 } 736 } 737 738 static bool easy_rect_join(const SkPaint& paint, const SkMatrix& matrix, 739 SkPoint* strokeSize) { 740 if (SkPaint::kMiter_Join != paint.getStrokeJoin() || 741 paint.getStrokeMiter() < SK_ScalarSqrt2) { 742 return false; 743 } 744 745 SkASSERT(matrix.rectStaysRect()); 746 SkPoint pt = { paint.getStrokeWidth(), paint.getStrokeWidth() }; 747 matrix.mapVectors(strokeSize, &pt, 1); 748 strokeSize->fX = SkScalarAbs(strokeSize->fX); 749 strokeSize->fY = SkScalarAbs(strokeSize->fY); 750 return true; 751 } 752 753 SkDraw::RectType SkDraw::ComputeRectType(const SkPaint& paint, 754 const SkMatrix& matrix, 755 SkPoint* strokeSize) { 756 RectType rtype; 757 const SkScalar width = paint.getStrokeWidth(); 758 const bool zeroWidth = (0 == width); 759 SkPaint::Style style = paint.getStyle(); 760 761 if ((SkPaint::kStrokeAndFill_Style == style) && zeroWidth) { 762 style = SkPaint::kFill_Style; 763 } 764 765 if (paint.getPathEffect() || paint.getMaskFilter() || 766 paint.getRasterizer() || !matrix.rectStaysRect() || 767 SkPaint::kStrokeAndFill_Style == style) { 768 rtype = kPath_RectType; 769 } else if (SkPaint::kFill_Style == style) { 770 rtype = kFill_RectType; 771 } else if (zeroWidth) { 772 rtype = kHair_RectType; 773 } else if (easy_rect_join(paint, matrix, strokeSize)) { 774 rtype = kStroke_RectType; 775 } else { 776 rtype = kPath_RectType; 777 } 778 return rtype; 779 } 780 781 static const SkPoint* rect_points(const SkRect& r) { 782 return SkTCast<const SkPoint*>(&r); 783 } 784 785 static SkPoint* rect_points(SkRect& r) { 786 return SkTCast<SkPoint*>(&r); 787 } 788 789 void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const { 790 SkDEBUGCODE(this->validate();) 791 792 // nothing to draw 793 if (fRC->isEmpty()) { 794 return; 795 } 796 797 SkPoint strokeSize; 798 RectType rtype = ComputeRectType(paint, *fMatrix, &strokeSize); 799 800 if (kPath_RectType == rtype) { 801 SkPath tmp; 802 tmp.addRect(rect); 803 tmp.setFillType(SkPath::kWinding_FillType); 804 this->drawPath(tmp, paint, NULL, true); 805 return; 806 } 807 808 const SkMatrix& matrix = *fMatrix; 809 SkRect devRect; 810 811 // transform rect into devRect 812 matrix.mapPoints(rect_points(devRect), rect_points(rect), 2); 813 devRect.sort(); 814 815 // look for the quick exit, before we build a blitter 816 SkIRect ir; 817 devRect.roundOut(&ir); 818 if (paint.getStyle() != SkPaint::kFill_Style) { 819 // extra space for hairlines 820 if (paint.getStrokeWidth() == 0) { 821 ir.outset(1, 1); 822 } else { 823 SkScalar radius = SkScalarHalf(paint.getStrokeWidth()); 824 ir.outset(radius, radius); 825 } 826 } 827 if (fRC->quickReject(ir)) { 828 return; 829 } 830 831 SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias()); 832 while (looper.next()) { 833 SkRect localDevRect; 834 looper.mapRect(&localDevRect, devRect); 835 SkMatrix localMatrix; 836 looper.mapMatrix(&localMatrix, matrix); 837 838 SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix, 839 paint); 840 const SkRasterClip& clip = looper.getRC(); 841 SkBlitter* blitter = blitterStorage.get(); 842 843 // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter 844 // case we are also hairline (if we've gotten to here), which devolves to 845 // effectively just kFill 846 switch (rtype) { 847 case kFill_RectType: 848 if (paint.isAntiAlias()) { 849 SkScan::AntiFillRect(localDevRect, clip, blitter); 850 } else { 851 SkScan::FillRect(localDevRect, clip, blitter); 852 } 853 break; 854 case kStroke_RectType: 855 if (paint.isAntiAlias()) { 856 SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter); 857 } else { 858 SkScan::FrameRect(localDevRect, strokeSize, clip, blitter); 859 } 860 break; 861 case kHair_RectType: 862 if (paint.isAntiAlias()) { 863 SkScan::AntiHairRect(localDevRect, clip, blitter); 864 } else { 865 SkScan::HairRect(localDevRect, clip, blitter); 866 } 867 break; 868 default: 869 SkDEBUGFAIL("bad rtype"); 870 } 871 } 872 } 873 874 void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 875 if (srcM.fBounds.isEmpty()) { 876 return; 877 } 878 879 const SkMask* mask = &srcM; 880 881 SkMask dstM; 882 if (paint.getMaskFilter() && 883 paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) { 884 mask = &dstM; 885 } else { 886 dstM.fImage = NULL; 887 } 888 SkAutoMaskFreeImage ami(dstM.fImage); 889 890 SkAutoBlitterChoose blitterChooser(*fBitmap, *fMatrix, paint); 891 SkBlitter* blitter = blitterChooser.get(); 892 893 SkAAClipBlitterWrapper wrapper; 894 const SkRegion* clipRgn; 895 896 if (fRC->isBW()) { 897 clipRgn = &fRC->bwRgn(); 898 } else { 899 wrapper.init(*fRC, blitter); 900 clipRgn = &wrapper.getRgn(); 901 blitter = wrapper.getBlitter(); 902 } 903 blitter->blitMaskRegion(*mask, *clipRgn); 904 } 905 906 static SkScalar fast_len(const SkVector& vec) { 907 SkScalar x = SkScalarAbs(vec.fX); 908 SkScalar y = SkScalarAbs(vec.fY); 909 if (x < y) { 910 SkTSwap(x, y); 911 } 912 return x + SkScalarHalf(y); 913 } 914 915 static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) { 916 SkXfermode::Coeff dc; 917 if (!SkXfermode::AsCoeff(xfer, NULL, &dc)) { 918 return false; 919 } 920 921 switch (dc) { 922 case SkXfermode::kOne_Coeff: 923 case SkXfermode::kISA_Coeff: 924 case SkXfermode::kISC_Coeff: 925 return true; 926 default: 927 return false; 928 } 929 } 930 931 bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix, 932 SkScalar* coverage) { 933 SkASSERT(strokeWidth > 0); 934 // We need to try to fake a thick-stroke with a modulated hairline. 935 936 if (matrix.hasPerspective()) { 937 return false; 938 } 939 940 SkVector src[2], dst[2]; 941 src[0].set(strokeWidth, 0); 942 src[1].set(0, strokeWidth); 943 matrix.mapVectors(dst, src, 2); 944 SkScalar len0 = fast_len(dst[0]); 945 SkScalar len1 = fast_len(dst[1]); 946 if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) { 947 if (coverage) { 948 *coverage = SkScalarAve(len0, len1); 949 } 950 return true; 951 } 952 return false; 953 } 954 955 void SkDraw::drawRRect(const SkRRect& rrect, const SkPaint& paint) const { 956 SkDEBUGCODE(this->validate()); 957 958 if (fRC->isEmpty()) { 959 return; 960 } 961 962 { 963 // TODO: Investigate optimizing these options. They are in the same 964 // order as SkDraw::drawPath, which handles each case. It may be 965 // that there is no way to optimize for these using the SkRRect path. 966 SkScalar coverage; 967 if (SkDrawTreatAsHairline(paint, *fMatrix, &coverage)) { 968 goto DRAW_PATH; 969 } 970 971 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 972 goto DRAW_PATH; 973 } 974 975 if (paint.getRasterizer()) { 976 goto DRAW_PATH; 977 } 978 } 979 980 if (paint.getMaskFilter()) { 981 // Transform the rrect into device space. 982 SkRRect devRRect; 983 if (rrect.transform(*fMatrix, &devRRect)) { 984 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 985 if (paint.getMaskFilter()->filterRRect(devRRect, *fMatrix, *fRC, blitter.get(), 986 SkPaint::kFill_Style)) { 987 return; // filterRRect() called the blitter, so we're done 988 } 989 } 990 } 991 992 DRAW_PATH: 993 // Now fall back to the default case of using a path. 994 SkPath path; 995 path.addRRect(rrect); 996 this->drawPath(path, paint, NULL, true); 997 } 998 999 void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, 1000 const SkMatrix* prePathMatrix, bool pathIsMutable, 1001 bool drawCoverage, SkBlitter* customBlitter) const { 1002 SkDEBUGCODE(this->validate();) 1003 1004 // nothing to draw 1005 if (fRC->isEmpty()) { 1006 return; 1007 } 1008 1009 SkPath* pathPtr = (SkPath*)&origSrcPath; 1010 bool doFill = true; 1011 SkPath tmpPath; 1012 SkMatrix tmpMatrix; 1013 const SkMatrix* matrix = fMatrix; 1014 1015 if (prePathMatrix) { 1016 if (origPaint.getPathEffect() || origPaint.getStyle() != SkPaint::kFill_Style || 1017 origPaint.getRasterizer()) { 1018 SkPath* result = pathPtr; 1019 1020 if (!pathIsMutable) { 1021 result = &tmpPath; 1022 pathIsMutable = true; 1023 } 1024 pathPtr->transform(*prePathMatrix, result); 1025 pathPtr = result; 1026 } else { 1027 tmpMatrix.setConcat(*matrix, *prePathMatrix); 1028 matrix = &tmpMatrix; 1029 } 1030 } 1031 // at this point we're done with prePathMatrix 1032 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 1033 1034 SkTCopyOnFirstWrite<SkPaint> paint(origPaint); 1035 1036 { 1037 SkScalar coverage; 1038 if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { 1039 if (SK_Scalar1 == coverage) { 1040 paint.writable()->setStrokeWidth(0); 1041 } else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) { 1042 U8CPU newAlpha; 1043 #if 0 1044 newAlpha = SkToU8(SkScalarRoundToInt(coverage * 1045 origPaint.getAlpha())); 1046 #else 1047 // this is the old technique, which we preserve for now so 1048 // we don't change previous results (testing) 1049 // the new way seems fine, its just (a tiny bit) different 1050 int scale = (int)SkScalarMul(coverage, 256); 1051 newAlpha = origPaint.getAlpha() * scale >> 8; 1052 #endif 1053 SkPaint* writablePaint = paint.writable(); 1054 writablePaint->setStrokeWidth(0); 1055 writablePaint->setAlpha(newAlpha); 1056 } 1057 } 1058 } 1059 1060 if (paint->getPathEffect() || paint->getStyle() != SkPaint::kFill_Style) { 1061 SkRect cullRect; 1062 const SkRect* cullRectPtr = NULL; 1063 if (this->computeConservativeLocalClipBounds(&cullRect)) { 1064 cullRectPtr = &cullRect; 1065 } 1066 doFill = paint->getFillPath(*pathPtr, &tmpPath, cullRectPtr); 1067 pathPtr = &tmpPath; 1068 } 1069 1070 if (paint->getRasterizer()) { 1071 SkMask mask; 1072 if (paint->getRasterizer()->rasterize(*pathPtr, *matrix, 1073 &fRC->getBounds(), paint->getMaskFilter(), &mask, 1074 SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 1075 this->drawDevMask(mask, *paint); 1076 SkMask::FreeImage(mask.fImage); 1077 } 1078 return; 1079 } 1080 1081 // avoid possibly allocating a new path in transform if we can 1082 SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 1083 1084 // transform the path into device space 1085 pathPtr->transform(*matrix, devPathPtr); 1086 1087 SkBlitter* blitter = NULL; 1088 SkAutoBlitterChoose blitterStorage; 1089 if (NULL == customBlitter) { 1090 blitterStorage.choose(*fBitmap, *fMatrix, *paint, drawCoverage); 1091 blitter = blitterStorage.get(); 1092 } else { 1093 blitter = customBlitter; 1094 } 1095 1096 if (paint->getMaskFilter()) { 1097 SkPaint::Style style = doFill ? SkPaint::kFill_Style : 1098 SkPaint::kStroke_Style; 1099 if (paint->getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fRC, blitter, style)) { 1100 return; // filterPath() called the blitter, so we're done 1101 } 1102 } 1103 1104 void (*proc)(const SkPath&, const SkRasterClip&, SkBlitter*); 1105 if (doFill) { 1106 if (paint->isAntiAlias()) { 1107 proc = SkScan::AntiFillPath; 1108 } else { 1109 proc = SkScan::FillPath; 1110 } 1111 } else { // hairline 1112 if (paint->isAntiAlias()) { 1113 proc = SkScan::AntiHairPath; 1114 } else { 1115 proc = SkScan::HairPath; 1116 } 1117 } 1118 proc(*devPathPtr, *fRC, blitter); 1119 } 1120 1121 /** For the purposes of drawing bitmaps, if a matrix is "almost" translate 1122 go ahead and treat it as if it were, so that subsequent code can go fast. 1123 */ 1124 static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) { 1125 unsigned bits = 0; // TODO: find a way to allow the caller to tell us to 1126 // respect filtering. 1127 return SkTreatAsSprite(matrix, bitmap.width(), bitmap.height(), bits); 1128 } 1129 1130 void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, 1131 const SkPaint& paint) const { 1132 SkASSERT(bitmap.colorType() == kAlpha_8_SkColorType); 1133 1134 if (just_translate(*fMatrix, bitmap)) { 1135 int ix = SkScalarRoundToInt(fMatrix->getTranslateX()); 1136 int iy = SkScalarRoundToInt(fMatrix->getTranslateY()); 1137 1138 SkAutoLockPixels alp(bitmap); 1139 if (!bitmap.readyToDraw()) { 1140 return; 1141 } 1142 1143 SkMask mask; 1144 mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 1145 mask.fFormat = SkMask::kA8_Format; 1146 mask.fRowBytes = SkToU32(bitmap.rowBytes()); 1147 mask.fImage = bitmap.getAddr8(0, 0); 1148 1149 this->drawDevMask(mask, paint); 1150 } else { // need to xform the bitmap first 1151 SkRect r; 1152 SkMask mask; 1153 1154 r.set(0, 0, 1155 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 1156 fMatrix->mapRect(&r); 1157 r.round(&mask.fBounds); 1158 1159 // set the mask's bounds to the transformed bitmap-bounds, 1160 // clipped to the actual device 1161 { 1162 SkIRect devBounds; 1163 devBounds.set(0, 0, fBitmap->width(), fBitmap->height()); 1164 // need intersect(l, t, r, b) on irect 1165 if (!mask.fBounds.intersect(devBounds)) { 1166 return; 1167 } 1168 } 1169 1170 mask.fFormat = SkMask::kA8_Format; 1171 mask.fRowBytes = SkAlign4(mask.fBounds.width()); 1172 size_t size = mask.computeImageSize(); 1173 if (0 == size) { 1174 // the mask is too big to allocated, draw nothing 1175 return; 1176 } 1177 1178 // allocate (and clear) our temp buffer to hold the transformed bitmap 1179 SkAutoMalloc storage(size); 1180 mask.fImage = (uint8_t*)storage.get(); 1181 memset(mask.fImage, 0, size); 1182 1183 // now draw our bitmap(src) into mask(dst), transformed by the matrix 1184 { 1185 SkBitmap device; 1186 device.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()), 1187 mask.fImage, mask.fRowBytes); 1188 1189 SkCanvas c(device); 1190 // need the unclipped top/left for the translate 1191 c.translate(-SkIntToScalar(mask.fBounds.fLeft), 1192 -SkIntToScalar(mask.fBounds.fTop)); 1193 c.concat(*fMatrix); 1194 1195 // We can't call drawBitmap, or we'll infinitely recurse. Instead 1196 // we manually build a shader and draw that into our new mask 1197 SkPaint tmpPaint; 1198 tmpPaint.setFlags(paint.getFlags()); 1199 SkAutoBitmapShaderInstall install(bitmap, tmpPaint); 1200 SkRect rr; 1201 rr.set(0, 0, SkIntToScalar(bitmap.width()), 1202 SkIntToScalar(bitmap.height())); 1203 c.drawRect(rr, install.paintWithShader()); 1204 } 1205 this->drawDevMask(mask, paint); 1206 } 1207 } 1208 1209 static bool clipped_out(const SkMatrix& m, const SkRasterClip& c, 1210 const SkRect& srcR) { 1211 SkRect dstR; 1212 SkIRect devIR; 1213 1214 m.mapRect(&dstR, srcR); 1215 dstR.roundOut(&devIR); 1216 return c.quickReject(devIR); 1217 } 1218 1219 static bool clipped_out(const SkMatrix& matrix, const SkRasterClip& clip, 1220 int width, int height) { 1221 SkRect r; 1222 r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 1223 return clipped_out(matrix, clip, r); 1224 } 1225 1226 static bool clipHandlesSprite(const SkRasterClip& clip, int x, int y, 1227 const SkBitmap& bitmap) { 1228 return clip.isBW() || 1229 clip.quickContains(x, y, x + bitmap.width(), y + bitmap.height()); 1230 } 1231 1232 void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 1233 const SkPaint& origPaint) const { 1234 SkDEBUGCODE(this->validate();) 1235 1236 // nothing to draw 1237 if (fRC->isEmpty() || 1238 bitmap.width() == 0 || bitmap.height() == 0 || 1239 bitmap.colorType() == kUnknown_SkColorType) { 1240 return; 1241 } 1242 1243 SkPaint paint(origPaint); 1244 paint.setStyle(SkPaint::kFill_Style); 1245 1246 SkMatrix matrix; 1247 matrix.setConcat(*fMatrix, prematrix); 1248 1249 if (clipped_out(matrix, *fRC, bitmap.width(), bitmap.height())) { 1250 return; 1251 } 1252 1253 if (bitmap.colorType() != kAlpha_8_SkColorType && just_translate(matrix, bitmap)) { 1254 // 1255 // It is safe to call lock pixels now, since we know the matrix is 1256 // (more or less) identity. 1257 // 1258 SkAutoLockPixels alp(bitmap); 1259 if (!bitmap.readyToDraw()) { 1260 return; 1261 } 1262 int ix = SkScalarRoundToInt(matrix.getTranslateX()); 1263 int iy = SkScalarRoundToInt(matrix.getTranslateY()); 1264 if (clipHandlesSprite(*fRC, ix, iy, bitmap)) { 1265 SkTBlitterAllocator allocator; 1266 // blitter will be owned by the allocator. 1267 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 1268 ix, iy, &allocator); 1269 if (blitter) { 1270 SkIRect ir; 1271 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 1272 1273 SkScan::FillIRect(ir, *fRC, blitter); 1274 return; 1275 } 1276 } 1277 } 1278 1279 // now make a temp draw on the stack, and use it 1280 // 1281 SkDraw draw(*this); 1282 draw.fMatrix = &matrix; 1283 1284 if (bitmap.colorType() == kAlpha_8_SkColorType) { 1285 draw.drawBitmapAsMask(bitmap, paint); 1286 } else { 1287 SkAutoBitmapShaderInstall install(bitmap, paint); 1288 1289 SkRect r; 1290 r.set(0, 0, SkIntToScalar(bitmap.width()), 1291 SkIntToScalar(bitmap.height())); 1292 // is this ok if paint has a rasterizer? 1293 draw.drawRect(r, install.paintWithShader()); 1294 } 1295 } 1296 1297 void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, 1298 const SkPaint& origPaint) const { 1299 SkDEBUGCODE(this->validate();) 1300 1301 // nothing to draw 1302 if (fRC->isEmpty() || 1303 bitmap.width() == 0 || bitmap.height() == 0 || 1304 bitmap.colorType() == kUnknown_SkColorType) { 1305 return; 1306 } 1307 1308 SkIRect bounds; 1309 bounds.set(x, y, x + bitmap.width(), y + bitmap.height()); 1310 1311 if (fRC->quickReject(bounds)) { 1312 return; // nothing to draw 1313 } 1314 1315 SkPaint paint(origPaint); 1316 paint.setStyle(SkPaint::kFill_Style); 1317 1318 if (NULL == paint.getColorFilter() && clipHandlesSprite(*fRC, x, y, bitmap)) { 1319 SkTBlitterAllocator allocator; 1320 // blitter will be owned by the allocator. 1321 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 1322 x, y, &allocator); 1323 1324 if (blitter) { 1325 SkScan::FillIRect(bounds, *fRC, blitter); 1326 return; 1327 } 1328 } 1329 1330 SkMatrix matrix; 1331 SkRect r; 1332 1333 // get a scalar version of our rect 1334 r.set(bounds); 1335 1336 // create shader with offset 1337 matrix.setTranslate(r.fLeft, r.fTop); 1338 SkAutoBitmapShaderInstall install(bitmap, paint, &matrix); 1339 const SkPaint& shaderPaint = install.paintWithShader(); 1340 1341 SkDraw draw(*this); 1342 matrix.reset(); 1343 draw.fMatrix = &matrix; 1344 // call ourself with a rect 1345 // is this OK if paint has a rasterizer? 1346 draw.drawRect(r, shaderPaint); 1347 } 1348 1349 /////////////////////////////////////////////////////////////////////////////// 1350 1351 #include "SkScalerContext.h" 1352 #include "SkGlyphCache.h" 1353 #include "SkTextToPathIter.h" 1354 #include "SkUtils.h" 1355 1356 static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, 1357 const char text[], size_t byteLength, SkVector* stopVector) { 1358 SkFixed x = 0, y = 0; 1359 const char* stop = text + byteLength; 1360 1361 SkAutoKern autokern; 1362 1363 while (text < stop) { 1364 // don't need x, y here, since all subpixel variants will have the 1365 // same advance 1366 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1367 1368 x += autokern.adjust(glyph) + glyph.fAdvanceX; 1369 y += glyph.fAdvanceY; 1370 } 1371 stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); 1372 1373 SkASSERT(text == stop); 1374 } 1375 1376 bool SkDraw::ShouldDrawTextAsPaths(const SkPaint& paint, const SkMatrix& ctm) { 1377 // hairline glyphs are fast enough so we don't need to cache them 1378 if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 1379 return true; 1380 } 1381 1382 // we don't cache perspective 1383 if (ctm.hasPerspective()) { 1384 return true; 1385 } 1386 1387 SkMatrix textM; 1388 return SkPaint::TooBigToUseCache(ctm, *paint.setTextMatrix(&textM)); 1389 } 1390 1391 void SkDraw::drawText_asPaths(const char text[], size_t byteLength, 1392 SkScalar x, SkScalar y, 1393 const SkPaint& paint) const { 1394 SkDEBUGCODE(this->validate();) 1395 1396 SkTextToPathIter iter(text, byteLength, paint, true); 1397 1398 SkMatrix matrix; 1399 matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1400 matrix.postTranslate(x, y); 1401 1402 const SkPath* iterPath; 1403 SkScalar xpos, prevXPos = 0; 1404 1405 while (iter.next(&iterPath, &xpos)) { 1406 matrix.postTranslate(xpos - prevXPos, 0); 1407 if (iterPath) { 1408 const SkPaint& pnt = iter.getPaint(); 1409 if (fDevice) { 1410 fDevice->drawPath(*this, *iterPath, pnt, &matrix, false); 1411 } else { 1412 this->drawPath(*iterPath, pnt, &matrix, false); 1413 } 1414 } 1415 prevXPos = xpos; 1416 } 1417 } 1418 1419 // disable warning : local variable used without having been initialized 1420 #if defined _WIN32 && _MSC_VER >= 1300 1421 #pragma warning ( push ) 1422 #pragma warning ( disable : 4701 ) 1423 #endif 1424 1425 ////////////////////////////////////////////////////////////////////////////// 1426 1427 static void D1G_RectClip(const SkDraw1Glyph& state, SkFixed fx, SkFixed fy, const SkGlyph& glyph) { 1428 int left = SkFixedFloorToInt(fx); 1429 int top = SkFixedFloorToInt(fy); 1430 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1431 SkASSERT((NULL == state.fClip && state.fAAClip) || 1432 (state.fClip && NULL == state.fAAClip && state.fClip->isRect())); 1433 1434 left += glyph.fLeft; 1435 top += glyph.fTop; 1436 1437 int right = left + glyph.fWidth; 1438 int bottom = top + glyph.fHeight; 1439 1440 SkMask mask; 1441 SkIRect storage; 1442 SkIRect* bounds = &mask.fBounds; 1443 1444 mask.fBounds.set(left, top, right, bottom); 1445 1446 // this extra test is worth it, assuming that most of the time it succeeds 1447 // since we can avoid writing to storage 1448 if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) { 1449 if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds)) 1450 return; 1451 bounds = &storage; 1452 } 1453 1454 uint8_t* aa = (uint8_t*)glyph.fImage; 1455 if (NULL == aa) { 1456 aa = (uint8_t*)state.fCache->findImage(glyph); 1457 if (NULL == aa) { 1458 return; // can't rasterize glyph 1459 } 1460 } 1461 1462 mask.fRowBytes = glyph.rowBytes(); 1463 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1464 mask.fImage = aa; 1465 state.blitMask(mask, *bounds); 1466 } 1467 1468 static void D1G_RgnClip(const SkDraw1Glyph& state, SkFixed fx, SkFixed fy, const SkGlyph& glyph) { 1469 int left = SkFixedFloorToInt(fx); 1470 int top = SkFixedFloorToInt(fy); 1471 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1472 SkASSERT(!state.fClip->isRect()); 1473 1474 SkMask mask; 1475 1476 left += glyph.fLeft; 1477 top += glyph.fTop; 1478 1479 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 1480 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 1481 1482 if (!clipper.done()) { 1483 const SkIRect& cr = clipper.rect(); 1484 const uint8_t* aa = (const uint8_t*)glyph.fImage; 1485 if (NULL == aa) { 1486 aa = (uint8_t*)state.fCache->findImage(glyph); 1487 if (NULL == aa) { 1488 return; 1489 } 1490 } 1491 1492 mask.fRowBytes = glyph.rowBytes(); 1493 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1494 mask.fImage = (uint8_t*)aa; 1495 do { 1496 state.blitMask(mask, cr); 1497 clipper.next(); 1498 } while (!clipper.done()); 1499 } 1500 } 1501 1502 static bool hasCustomD1GProc(const SkDraw& draw) { 1503 return draw.fProcs && draw.fProcs->fD1GProc; 1504 } 1505 1506 static bool needsRasterTextBlit(const SkDraw& draw) { 1507 return !hasCustomD1GProc(draw); 1508 } 1509 1510 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, 1511 const SkPaint& pnt) { 1512 fDraw = draw; 1513 fBlitter = blitter; 1514 fCache = cache; 1515 fPaint = &pnt; 1516 1517 if (cache->isSubpixel()) { 1518 fHalfSampleX = fHalfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); 1519 } else { 1520 fHalfSampleX = fHalfSampleY = SK_FixedHalf; 1521 } 1522 1523 if (hasCustomD1GProc(*draw)) { 1524 // todo: fix this assumption about clips w/ custom 1525 fClip = draw->fClip; 1526 fClipBounds = fClip->getBounds(); 1527 return draw->fProcs->fD1GProc; 1528 } 1529 1530 if (draw->fRC->isBW()) { 1531 fAAClip = NULL; 1532 fClip = &draw->fRC->bwRgn(); 1533 fClipBounds = fClip->getBounds(); 1534 if (fClip->isRect()) { 1535 return D1G_RectClip; 1536 } else { 1537 return D1G_RgnClip; 1538 } 1539 } else { // aaclip 1540 fAAClip = &draw->fRC->aaRgn(); 1541 fClip = NULL; 1542 fClipBounds = fAAClip->getBounds(); 1543 return D1G_RectClip; 1544 } 1545 } 1546 1547 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const { 1548 SkASSERT(SkMask::kARGB32_Format == mask.fFormat); 1549 1550 SkBitmap bm; 1551 bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()), 1552 (SkPMColor*)mask.fImage, mask.fRowBytes); 1553 1554 fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint); 1555 } 1556 1557 /////////////////////////////////////////////////////////////////////////////// 1558 1559 void SkDraw::drawText(const char text[], size_t byteLength, 1560 SkScalar x, SkScalar y, const SkPaint& paint) const { 1561 SkASSERT(byteLength == 0 || text != NULL); 1562 1563 SkDEBUGCODE(this->validate();) 1564 1565 // nothing to draw 1566 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 1567 return; 1568 } 1569 1570 // SkScalarRec doesn't currently have a way of representing hairline stroke and 1571 // will fill if its frame-width is 0. 1572 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1573 this->drawText_asPaths(text, byteLength, x, y, paint); 1574 return; 1575 } 1576 1577 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1578 1579 SkAutoGlyphCache autoCache(paint, &fDevice->getLeakyProperties(), fMatrix); 1580 SkGlyphCache* cache = autoCache.getCache(); 1581 1582 // transform our starting point 1583 { 1584 SkPoint loc; 1585 fMatrix->mapXY(x, y, &loc); 1586 x = loc.fX; 1587 y = loc.fY; 1588 } 1589 1590 // need to measure first 1591 if (paint.getTextAlign() != SkPaint::kLeft_Align) { 1592 SkVector stop; 1593 1594 measure_text(cache, glyphCacheProc, text, byteLength, &stop); 1595 1596 SkScalar stopX = stop.fX; 1597 SkScalar stopY = stop.fY; 1598 1599 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1600 stopX = SkScalarHalf(stopX); 1601 stopY = SkScalarHalf(stopY); 1602 } 1603 x -= stopX; 1604 y -= stopY; 1605 } 1606 1607 const char* stop = text + byteLength; 1608 1609 SkAAClipBlitter aaBlitter; 1610 SkAutoBlitterChoose blitterChooser; 1611 SkBlitter* blitter = NULL; 1612 if (needsRasterTextBlit(*this)) { 1613 blitterChooser.choose(*fBitmap, *fMatrix, paint); 1614 blitter = blitterChooser.get(); 1615 if (fRC->isAA()) { 1616 aaBlitter.init(blitter, &fRC->aaRgn()); 1617 blitter = &aaBlitter; 1618 } 1619 } 1620 1621 SkAutoKern autokern; 1622 SkDraw1Glyph d1g; 1623 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 1624 1625 SkFixed fxMask = ~0; 1626 SkFixed fyMask = ~0; 1627 if (cache->isSubpixel()) { 1628 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); 1629 if (kX_SkAxisAlignment == baseline) { 1630 fyMask = 0; 1631 d1g.fHalfSampleY = SK_FixedHalf; 1632 } else if (kY_SkAxisAlignment == baseline) { 1633 fxMask = 0; 1634 d1g.fHalfSampleX = SK_FixedHalf; 1635 } 1636 } 1637 1638 SkFixed fx = SkScalarToFixed(x) + d1g.fHalfSampleX; 1639 SkFixed fy = SkScalarToFixed(y) + d1g.fHalfSampleY; 1640 1641 while (text < stop) { 1642 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx & fxMask, fy & fyMask); 1643 1644 fx += autokern.adjust(glyph); 1645 1646 if (glyph.fWidth) { 1647 proc(d1g, fx, fy, glyph); 1648 } 1649 1650 fx += glyph.fAdvanceX; 1651 fy += glyph.fAdvanceY; 1652 } 1653 } 1654 1655 ////////////////////////////////////////////////////////////////////////////// 1656 1657 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 1658 const SkScalar pos[], SkScalar constY, 1659 int scalarsPerPosition, 1660 const SkPaint& origPaint) const { 1661 // setup our std paint, in hopes of getting hits in the cache 1662 SkPaint paint(origPaint); 1663 SkScalar matrixScale = paint.setupForAsPaths(); 1664 1665 SkMatrix matrix; 1666 matrix.setScale(matrixScale, matrixScale); 1667 1668 // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. 1669 paint.setStyle(SkPaint::kFill_Style); 1670 paint.setPathEffect(NULL); 1671 1672 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1673 SkAutoGlyphCache autoCache(paint, NULL, NULL); 1674 SkGlyphCache* cache = autoCache.getCache(); 1675 1676 const char* stop = text + byteLength; 1677 SkTextAlignProcScalar alignProc(paint.getTextAlign()); 1678 SkTextMapStateProc tmsProc(SkMatrix::I(), constY, scalarsPerPosition); 1679 1680 // Now restore the original settings, so we "draw" with whatever style/stroking. 1681 paint.setStyle(origPaint.getStyle()); 1682 paint.setPathEffect(origPaint.getPathEffect()); 1683 1684 while (text < stop) { 1685 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1686 if (glyph.fWidth) { 1687 const SkPath* path = cache->findPath(glyph); 1688 if (path) { 1689 SkPoint tmsLoc; 1690 tmsProc(pos, &tmsLoc); 1691 SkPoint loc; 1692 alignProc(tmsLoc, glyph, &loc); 1693 1694 matrix[SkMatrix::kMTransX] = loc.fX; 1695 matrix[SkMatrix::kMTransY] = loc.fY; 1696 if (fDevice) { 1697 fDevice->drawPath(*this, *path, paint, &matrix, false); 1698 } else { 1699 this->drawPath(*path, paint, &matrix, false); 1700 } 1701 } 1702 } 1703 pos += scalarsPerPosition; 1704 } 1705 } 1706 1707 void SkDraw::drawPosText(const char text[], size_t byteLength, 1708 const SkScalar pos[], SkScalar constY, 1709 int scalarsPerPosition, const SkPaint& paint) const { 1710 SkASSERT(byteLength == 0 || text != NULL); 1711 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 1712 1713 SkDEBUGCODE(this->validate();) 1714 1715 // nothing to draw 1716 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 1717 return; 1718 } 1719 1720 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1721 this->drawPosText_asPaths(text, byteLength, pos, constY, 1722 scalarsPerPosition, paint); 1723 return; 1724 } 1725 1726 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1727 SkAutoGlyphCache autoCache(paint, &fDevice->getLeakyProperties(), fMatrix); 1728 SkGlyphCache* cache = autoCache.getCache(); 1729 1730 SkAAClipBlitterWrapper wrapper; 1731 SkAutoBlitterChoose blitterChooser; 1732 SkBlitter* blitter = NULL; 1733 if (needsRasterTextBlit(*this)) { 1734 blitterChooser.choose(*fBitmap, *fMatrix, paint); 1735 blitter = blitterChooser.get(); 1736 if (fRC->isAA()) { 1737 wrapper.init(*fRC, blitter); 1738 blitter = wrapper.getBlitter(); 1739 } 1740 } 1741 1742 const char* stop = text + byteLength; 1743 SkTextAlignProc alignProc(paint.getTextAlign()); 1744 SkDraw1Glyph d1g; 1745 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); 1746 SkTextMapStateProc tmsProc(*fMatrix, constY, scalarsPerPosition); 1747 1748 if (cache->isSubpixel()) { 1749 // maybe we should skip the rounding if linearText is set 1750 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(*fMatrix); 1751 1752 SkFixed fxMask = ~0; 1753 SkFixed fyMask = ~0; 1754 if (kX_SkAxisAlignment == baseline) { 1755 fyMask = 0; 1756 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX 1757 d1g.fHalfSampleY = SK_FixedHalf; 1758 #endif 1759 } else if (kY_SkAxisAlignment == baseline) { 1760 fxMask = 0; 1761 #ifndef SK_IGNORE_SUBPIXEL_AXIS_ALIGN_FIX 1762 d1g.fHalfSampleX = SK_FixedHalf; 1763 #endif 1764 } 1765 1766 if (SkPaint::kLeft_Align == paint.getTextAlign()) { 1767 while (text < stop) { 1768 SkPoint tmsLoc; 1769 tmsProc(pos, &tmsLoc); 1770 SkFixed fx = SkScalarToFixed(tmsLoc.fX) + d1g.fHalfSampleX; 1771 SkFixed fy = SkScalarToFixed(tmsLoc.fY) + d1g.fHalfSampleY; 1772 1773 const SkGlyph& glyph = glyphCacheProc(cache, &text, 1774 fx & fxMask, fy & fyMask); 1775 1776 if (glyph.fWidth) { 1777 proc(d1g, fx, fy, glyph); 1778 } 1779 pos += scalarsPerPosition; 1780 } 1781 } else { 1782 while (text < stop) { 1783 const char* currentText = text; 1784 const SkGlyph& metricGlyph = glyphCacheProc(cache, &text, 0, 0); 1785 1786 if (metricGlyph.fWidth) { 1787 SkDEBUGCODE(SkFixed prevAdvX = metricGlyph.fAdvanceX;) 1788 SkDEBUGCODE(SkFixed prevAdvY = metricGlyph.fAdvanceY;) 1789 SkPoint tmsLoc; 1790 tmsProc(pos, &tmsLoc); 1791 SkIPoint fixedLoc; 1792 alignProc(tmsLoc, metricGlyph, &fixedLoc); 1793 1794 SkFixed fx = fixedLoc.fX + d1g.fHalfSampleX; 1795 SkFixed fy = fixedLoc.fY + d1g.fHalfSampleY; 1796 1797 // have to call again, now that we've been "aligned" 1798 const SkGlyph& glyph = glyphCacheProc(cache, ¤tText, 1799 fx & fxMask, fy & fyMask); 1800 // the assumption is that the metrics haven't changed 1801 SkASSERT(prevAdvX == glyph.fAdvanceX); 1802 SkASSERT(prevAdvY == glyph.fAdvanceY); 1803 SkASSERT(glyph.fWidth); 1804 1805 proc(d1g, fx, fy, glyph); 1806 } 1807 pos += scalarsPerPosition; 1808 } 1809 } 1810 } else { // not subpixel 1811 if (SkPaint::kLeft_Align == paint.getTextAlign()) { 1812 while (text < stop) { 1813 // the last 2 parameters are ignored 1814 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1815 1816 if (glyph.fWidth) { 1817 SkPoint tmsLoc; 1818 tmsProc(pos, &tmsLoc); 1819 1820 proc(d1g, 1821 SkScalarToFixed(tmsLoc.fX) + SK_FixedHalf, //d1g.fHalfSampleX, 1822 SkScalarToFixed(tmsLoc.fY) + SK_FixedHalf, //d1g.fHalfSampleY, 1823 glyph); 1824 } 1825 pos += scalarsPerPosition; 1826 } 1827 } else { 1828 while (text < stop) { 1829 // the last 2 parameters are ignored 1830 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1831 1832 if (glyph.fWidth) { 1833 SkPoint tmsLoc; 1834 tmsProc(pos, &tmsLoc); 1835 1836 SkIPoint fixedLoc; 1837 alignProc(tmsLoc, glyph, &fixedLoc); 1838 1839 proc(d1g, 1840 fixedLoc.fX + SK_FixedHalf, //d1g.fHalfSampleX, 1841 fixedLoc.fY + SK_FixedHalf, //d1g.fHalfSampleY, 1842 glyph); 1843 } 1844 pos += scalarsPerPosition; 1845 } 1846 } 1847 } 1848 } 1849 1850 #if defined _WIN32 && _MSC_VER >= 1300 1851 #pragma warning ( pop ) 1852 #endif 1853 1854 /////////////////////////////////////////////////////////////////////////////// 1855 1856 #include "SkPathMeasure.h" 1857 1858 static void morphpoints(SkPoint dst[], const SkPoint src[], int count, 1859 SkPathMeasure& meas, const SkMatrix& matrix) { 1860 SkMatrix::MapXYProc proc = matrix.getMapXYProc(); 1861 1862 for (int i = 0; i < count; i++) { 1863 SkPoint pos; 1864 SkVector tangent; 1865 1866 proc(matrix, src[i].fX, src[i].fY, &pos); 1867 SkScalar sx = pos.fX; 1868 SkScalar sy = pos.fY; 1869 1870 if (!meas.getPosTan(sx, &pos, &tangent)) { 1871 // set to 0 if the measure failed, so that we just set dst == pos 1872 tangent.set(0, 0); 1873 } 1874 1875 /* This is the old way (that explains our approach but is way too slow 1876 SkMatrix matrix; 1877 SkPoint pt; 1878 1879 pt.set(sx, sy); 1880 matrix.setSinCos(tangent.fY, tangent.fX); 1881 matrix.preTranslate(-sx, 0); 1882 matrix.postTranslate(pos.fX, pos.fY); 1883 matrix.mapPoints(&dst[i], &pt, 1); 1884 */ 1885 dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy), 1886 pos.fY + SkScalarMul(tangent.fX, sy)); 1887 } 1888 } 1889 1890 /* TODO 1891 1892 Need differentially more subdivisions when the follow-path is curvy. Not sure how to 1893 determine that, but we need it. I guess a cheap answer is let the caller tell us, 1894 but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out. 1895 */ 1896 static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas, 1897 const SkMatrix& matrix) { 1898 SkPath::Iter iter(src, false); 1899 SkPoint srcP[4], dstP[3]; 1900 SkPath::Verb verb; 1901 1902 while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) { 1903 switch (verb) { 1904 case SkPath::kMove_Verb: 1905 morphpoints(dstP, srcP, 1, meas, matrix); 1906 dst->moveTo(dstP[0]); 1907 break; 1908 case SkPath::kLine_Verb: 1909 // turn lines into quads to look bendy 1910 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX); 1911 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY); 1912 morphpoints(dstP, srcP, 2, meas, matrix); 1913 dst->quadTo(dstP[0], dstP[1]); 1914 break; 1915 case SkPath::kQuad_Verb: 1916 morphpoints(dstP, &srcP[1], 2, meas, matrix); 1917 dst->quadTo(dstP[0], dstP[1]); 1918 break; 1919 case SkPath::kCubic_Verb: 1920 morphpoints(dstP, &srcP[1], 3, meas, matrix); 1921 dst->cubicTo(dstP[0], dstP[1], dstP[2]); 1922 break; 1923 case SkPath::kClose_Verb: 1924 dst->close(); 1925 break; 1926 default: 1927 SkDEBUGFAIL("unknown verb"); 1928 break; 1929 } 1930 } 1931 } 1932 1933 void SkDraw::drawTextOnPath(const char text[], size_t byteLength, 1934 const SkPath& follow, const SkMatrix* matrix, 1935 const SkPaint& paint) const { 1936 SkASSERT(byteLength == 0 || text != NULL); 1937 1938 // nothing to draw 1939 if (text == NULL || byteLength == 0 || fRC->isEmpty()) { 1940 return; 1941 } 1942 1943 SkTextToPathIter iter(text, byteLength, paint, true); 1944 SkPathMeasure meas(follow, false); 1945 SkScalar hOffset = 0; 1946 1947 // need to measure first 1948 if (paint.getTextAlign() != SkPaint::kLeft_Align) { 1949 SkScalar pathLen = meas.getLength(); 1950 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1951 pathLen = SkScalarHalf(pathLen); 1952 } 1953 hOffset += pathLen; 1954 } 1955 1956 const SkPath* iterPath; 1957 SkScalar xpos; 1958 SkMatrix scaledMatrix; 1959 SkScalar scale = iter.getPathScale(); 1960 1961 scaledMatrix.setScale(scale, scale); 1962 1963 while (iter.next(&iterPath, &xpos)) { 1964 if (iterPath) { 1965 SkPath tmp; 1966 SkMatrix m(scaledMatrix); 1967 1968 m.postTranslate(xpos + hOffset, 0); 1969 if (matrix) { 1970 m.postConcat(*matrix); 1971 } 1972 morphpath(&tmp, *iterPath, meas, m); 1973 if (fDevice) { 1974 fDevice->drawPath(*this, tmp, iter.getPaint(), NULL, true); 1975 } else { 1976 this->drawPath(tmp, iter.getPaint(), NULL, true); 1977 } 1978 } 1979 } 1980 } 1981 1982 /////////////////////////////////////////////////////////////////////////////// 1983 1984 typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRasterClip&, 1985 SkBlitter*); 1986 1987 static HairProc ChooseHairProc(bool doAntiAlias) { 1988 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 1989 } 1990 1991 static bool texture_to_matrix(const VertState& state, const SkPoint verts[], 1992 const SkPoint texs[], SkMatrix* matrix) { 1993 SkPoint src[3], dst[3]; 1994 1995 src[0] = texs[state.f0]; 1996 src[1] = texs[state.f1]; 1997 src[2] = texs[state.f2]; 1998 dst[0] = verts[state.f0]; 1999 dst[1] = verts[state.f1]; 2000 dst[2] = verts[state.f2]; 2001 return matrix->setPolyToPoly(src, dst, 3); 2002 } 2003 2004 class SkTriColorShader : public SkShader { 2005 public: 2006 SkTriColorShader() {} 2007 2008 virtual size_t contextSize() const SK_OVERRIDE; 2009 2010 class TriColorShaderContext : public SkShader::Context { 2011 public: 2012 TriColorShaderContext(const SkTriColorShader& shader, const ContextRec&); 2013 virtual ~TriColorShaderContext(); 2014 2015 bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 2016 2017 virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; 2018 2019 private: 2020 SkMatrix fDstToUnit; 2021 SkPMColor fColors[3]; 2022 2023 typedef SkShader::Context INHERITED; 2024 }; 2025 2026 SK_TO_STRING_OVERRIDE() 2027 SK_DECLARE_NOT_FLATTENABLE_PROCS(SkTriColorShader) 2028 2029 protected: 2030 virtual Context* onCreateContext(const ContextRec& rec, void* storage) const SK_OVERRIDE { 2031 return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, rec)); 2032 } 2033 2034 private: 2035 typedef SkShader INHERITED; 2036 }; 2037 2038 bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], 2039 int index0, int index1, int index2) { 2040 2041 fColors[0] = SkPreMultiplyColor(colors[index0]); 2042 fColors[1] = SkPreMultiplyColor(colors[index1]); 2043 fColors[2] = SkPreMultiplyColor(colors[index2]); 2044 2045 SkMatrix m, im; 2046 m.reset(); 2047 m.set(0, pts[index1].fX - pts[index0].fX); 2048 m.set(1, pts[index2].fX - pts[index0].fX); 2049 m.set(2, pts[index0].fX); 2050 m.set(3, pts[index1].fY - pts[index0].fY); 2051 m.set(4, pts[index2].fY - pts[index0].fY); 2052 m.set(5, pts[index0].fY); 2053 if (!m.invert(&im)) { 2054 return false; 2055 } 2056 // We can't call getTotalInverse(), because we explicitly don't want to look at the localmatrix 2057 // as our interators are intrinsically tied to the vertices, and nothing else. 2058 SkMatrix ctmInv; 2059 if (!this->getCTM().invert(&ctmInv)) { 2060 return false; 2061 } 2062 fDstToUnit.setConcat(im, ctmInv); 2063 return true; 2064 } 2065 2066 #include "SkColorPriv.h" 2067 #include "SkComposeShader.h" 2068 2069 static int ScalarTo256(SkScalar v) { 2070 int scale = SkScalarToFixed(v) >> 8; 2071 if (scale < 0) { 2072 scale = 0; 2073 } 2074 if (scale > 255) { 2075 scale = 255; 2076 } 2077 return SkAlpha255To256(scale); 2078 } 2079 2080 2081 SkTriColorShader::TriColorShaderContext::TriColorShaderContext(const SkTriColorShader& shader, 2082 const ContextRec& rec) 2083 : INHERITED(shader, rec) {} 2084 2085 SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} 2086 2087 size_t SkTriColorShader::contextSize() const { 2088 return sizeof(TriColorShaderContext); 2089 } 2090 void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 2091 const int alphaScale = Sk255To256(this->getPaintAlpha()); 2092 2093 SkPoint src; 2094 2095 for (int i = 0; i < count; i++) { 2096 fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); 2097 x += 1; 2098 2099 int scale1 = ScalarTo256(src.fX); 2100 int scale2 = ScalarTo256(src.fY); 2101 int scale0 = 256 - scale1 - scale2; 2102 if (scale0 < 0) { 2103 if (scale1 > scale2) { 2104 scale2 = 256 - scale1; 2105 } else { 2106 scale1 = 256 - scale2; 2107 } 2108 scale0 = 0; 2109 } 2110 2111 if (256 != alphaScale) { 2112 scale0 = SkAlphaMul(scale0, alphaScale); 2113 scale1 = SkAlphaMul(scale1, alphaScale); 2114 scale2 = SkAlphaMul(scale2, alphaScale); 2115 } 2116 2117 dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 2118 SkAlphaMulQ(fColors[1], scale1) + 2119 SkAlphaMulQ(fColors[2], scale2); 2120 } 2121 } 2122 2123 #ifndef SK_IGNORE_TO_STRING 2124 void SkTriColorShader::toString(SkString* str) const { 2125 str->append("SkTriColorShader: ("); 2126 2127 this->INHERITED::toString(str); 2128 2129 str->append(")"); 2130 } 2131 #endif 2132 2133 void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, 2134 const SkPoint vertices[], const SkPoint textures[], 2135 const SkColor colors[], SkXfermode* xmode, 2136 const uint16_t indices[], int indexCount, 2137 const SkPaint& paint) const { 2138 SkASSERT(0 == count || vertices); 2139 2140 // abort early if there is nothing to draw 2141 if (count < 3 || (indices && indexCount < 3) || fRC->isEmpty()) { 2142 return; 2143 } 2144 2145 // transform out vertices into device coordinates 2146 SkAutoSTMalloc<16, SkPoint> storage(count); 2147 SkPoint* devVerts = storage.get(); 2148 fMatrix->mapPoints(devVerts, vertices, count); 2149 2150 /* 2151 We can draw the vertices in 1 of 4 ways: 2152 2153 - solid color (no shader/texture[], no colors[]) 2154 - just colors (no shader/texture[], has colors[]) 2155 - just texture (has shader/texture[], no colors[]) 2156 - colors * texture (has shader/texture[], has colors[]) 2157 2158 Thus for texture drawing, we need both texture[] and a shader. 2159 */ 2160 2161 SkTriColorShader triShader; // must be above declaration of p 2162 SkPaint p(paint); 2163 2164 SkShader* shader = p.getShader(); 2165 if (NULL == shader) { 2166 // if we have no shader, we ignore the texture coordinates 2167 textures = NULL; 2168 } else if (NULL == textures) { 2169 // if we don't have texture coordinates, ignore the shader 2170 p.setShader(NULL); 2171 shader = NULL; 2172 } 2173 2174 // setup the custom shader (if needed) 2175 SkAutoTUnref<SkComposeShader> composeShader; 2176 if (colors) { 2177 if (NULL == textures) { 2178 // just colors (no texture) 2179 shader = p.setShader(&triShader); 2180 } else { 2181 // colors * texture 2182 SkASSERT(shader); 2183 bool releaseMode = false; 2184 if (NULL == xmode) { 2185 xmode = SkXfermode::Create(SkXfermode::kModulate_Mode); 2186 releaseMode = true; 2187 } 2188 composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode))); 2189 p.setShader(composeShader); 2190 if (releaseMode) { 2191 xmode->unref(); 2192 } 2193 } 2194 } 2195 2196 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); 2197 // Abort early if we failed to create a shader context. 2198 if (blitter->isNullBlitter()) { 2199 return; 2200 } 2201 2202 // setup our state and function pointer for iterating triangles 2203 VertState state(count, indices, indexCount); 2204 VertState::Proc vertProc = state.chooseProc(vmode); 2205 2206 if (textures || colors) { 2207 while (vertProc(&state)) { 2208 if (textures) { 2209 SkMatrix tempM; 2210 if (texture_to_matrix(state, vertices, textures, &tempM)) { 2211 SkShader::ContextRec rec(*fBitmap, p, *fMatrix); 2212 rec.fLocalMatrix = &tempM; 2213 if (!blitter->resetShaderContext(rec)) { 2214 continue; 2215 } 2216 } 2217 } 2218 if (colors) { 2219 // Find the context for triShader. 2220 SkTriColorShader::TriColorShaderContext* triColorShaderContext; 2221 2222 SkShader::Context* shaderContext = blitter->getShaderContext(); 2223 SkASSERT(shaderContext); 2224 if (p.getShader() == &triShader) { 2225 triColorShaderContext = 2226 static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext); 2227 } else { 2228 // The shader is a compose shader and triShader is its first shader. 2229 SkASSERT(p.getShader() == composeShader); 2230 SkASSERT(composeShader->getShaderA() == &triShader); 2231 SkComposeShader::ComposeShaderContext* composeShaderContext = 2232 static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext); 2233 SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA(); 2234 triColorShaderContext = 2235 static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA); 2236 } 2237 2238 if (!triColorShaderContext->setup(vertices, colors, 2239 state.f0, state.f1, state.f2)) { 2240 continue; 2241 } 2242 } 2243 2244 SkPoint tmp[] = { 2245 devVerts[state.f0], devVerts[state.f1], devVerts[state.f2] 2246 }; 2247 SkScan::FillTriangle(tmp, *fRC, blitter.get()); 2248 } 2249 } else { 2250 // no colors[] and no texture, stroke hairlines with paint's color. 2251 HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); 2252 const SkRasterClip& clip = *fRC; 2253 while (vertProc(&state)) { 2254 hairProc(devVerts[state.f0], devVerts[state.f1], clip, blitter.get()); 2255 hairProc(devVerts[state.f1], devVerts[state.f2], clip, blitter.get()); 2256 hairProc(devVerts[state.f2], devVerts[state.f0], clip, blitter.get()); 2257 } 2258 } 2259 } 2260 2261 /////////////////////////////////////////////////////////////////////////////// 2262 /////////////////////////////////////////////////////////////////////////////// 2263 2264 #ifdef SK_DEBUG 2265 2266 void SkDraw::validate() const { 2267 SkASSERT(fBitmap != NULL); 2268 SkASSERT(fMatrix != NULL); 2269 SkASSERT(fClip != NULL); 2270 SkASSERT(fRC != NULL); 2271 2272 const SkIRect& cr = fRC->getBounds(); 2273 SkIRect br; 2274 2275 br.set(0, 0, fBitmap->width(), fBitmap->height()); 2276 SkASSERT(cr.isEmpty() || br.contains(cr)); 2277 } 2278 2279 #endif 2280 2281 //////////////////////////////////////////////////////////////////////////////////////////////// 2282 2283 #include "SkPath.h" 2284 #include "SkDraw.h" 2285 #include "SkRegion.h" 2286 #include "SkBlitter.h" 2287 2288 static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 2289 const SkMaskFilter* filter, const SkMatrix* filterMatrix, 2290 SkIRect* bounds) { 2291 if (devPath.isEmpty()) { 2292 return false; 2293 } 2294 2295 // init our bounds from the path 2296 { 2297 SkRect pathBounds = devPath.getBounds(); 2298 pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf); 2299 pathBounds.roundOut(bounds); 2300 } 2301 2302 SkIPoint margin = SkIPoint::Make(0, 0); 2303 if (filter) { 2304 SkASSERT(filterMatrix); 2305 2306 SkMask srcM, dstM; 2307 2308 srcM.fBounds = *bounds; 2309 srcM.fFormat = SkMask::kA8_Format; 2310 srcM.fImage = NULL; 2311 if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 2312 return false; 2313 } 2314 } 2315 2316 // (possibly) trim the bounds to reflect the clip 2317 // (plus whatever slop the filter needs) 2318 if (clipBounds) { 2319 SkIRect tmp = *clipBounds; 2320 // Ugh. Guard against gigantic margins from wacky filters. Without this 2321 // check we can request arbitrary amounts of slop beyond our visible 2322 // clip, and bring down the renderer (at least on finite RAM machines 2323 // like handsets, etc.). Need to balance this invented value between 2324 // quality of large filters like blurs, and the corresponding memory 2325 // requests. 2326 static const int MAX_MARGIN = 128; 2327 tmp.inset(-SkMin32(margin.fX, MAX_MARGIN), 2328 -SkMin32(margin.fY, MAX_MARGIN)); 2329 if (!bounds->intersect(tmp)) { 2330 return false; 2331 } 2332 } 2333 2334 return true; 2335 } 2336 2337 static void draw_into_mask(const SkMask& mask, const SkPath& devPath, 2338 SkPaint::Style style) { 2339 SkBitmap bm; 2340 SkDraw draw; 2341 SkRasterClip clip; 2342 SkMatrix matrix; 2343 SkPaint paint; 2344 2345 bm.installPixels(SkImageInfo::MakeA8(mask.fBounds.width(), mask.fBounds.height()), 2346 mask.fImage, mask.fRowBytes); 2347 2348 clip.setRect(SkIRect::MakeWH(mask.fBounds.width(), mask.fBounds.height())); 2349 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 2350 -SkIntToScalar(mask.fBounds.fTop)); 2351 2352 draw.fBitmap = &bm; 2353 draw.fRC = &clip; 2354 draw.fClip = &clip.bwRgn(); 2355 draw.fMatrix = &matrix; 2356 paint.setAntiAlias(true); 2357 paint.setStyle(style); 2358 draw.drawPath(devPath, paint); 2359 } 2360 2361 bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 2362 const SkMaskFilter* filter, const SkMatrix* filterMatrix, 2363 SkMask* mask, SkMask::CreateMode mode, 2364 SkPaint::Style style) { 2365 if (SkMask::kJustRenderImage_CreateMode != mode) { 2366 if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 2367 return false; 2368 } 2369 2370 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 2371 mask->fFormat = SkMask::kA8_Format; 2372 mask->fRowBytes = mask->fBounds.width(); 2373 size_t size = mask->computeImageSize(); 2374 if (0 == size) { 2375 // we're too big to allocate the mask, abort 2376 return false; 2377 } 2378 mask->fImage = SkMask::AllocImage(size); 2379 memset(mask->fImage, 0, mask->computeImageSize()); 2380 } 2381 2382 if (SkMask::kJustComputeBounds_CreateMode != mode) { 2383 draw_into_mask(*mask, devPath, style); 2384 } 2385 2386 return true; 2387 } 2388