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