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