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