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