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