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