SkDraw.cpp revision 030ffe05175291b1d91ec6808e1a32e862ee90cd
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 40class SkAutoRestoreBounder : SkNoncopyable { 41public: 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 56private: 57 SkDraw* fDraw; 58 SkBounder* fBounder; 59}; 60 61static 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 71class SkAutoBlitterChoose { 72public: 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 83private: 84 SkBlitter* fBlitter; 85 uint32_t fStorage[kBlitterStorageLongCount]; 86}; 87 88SkAutoBlitterChoose::~SkAutoBlitterChoose() { 89 if ((void*)fBlitter == (void*)fStorage) { 90 fBlitter->~SkBlitter(); 91 } else { 92 SkDELETE(fBlitter); 93 } 94} 95 96class SkAutoBitmapShaderInstall { 97public: 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 } 118private: 119 SkPaint* fPaint; 120 SkShader* fPrevShader; 121 uint32_t fStorage[kBlitterStorageLongCount]; 122}; 123 124class SkAutoPaintStyleRestore { 125public: 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 } 134private: 135 SkPaint& fPaint; 136 SkPaint::Style fStyle; 137 138 // illegal 139 SkAutoPaintStyleRestore(const SkAutoPaintStyleRestore&); 140 SkAutoPaintStyleRestore& operator=(const SkAutoPaintStyleRestore&); 141}; 142 143/////////////////////////////////////////////////////////////////////////////// 144 145SkDraw::SkDraw(const SkDraw& src) { 146 memcpy(this, &src, sizeof(*this)); 147} 148 149/////////////////////////////////////////////////////////////////////////////// 150 151typedef void (*BitmapXferProc)(void* pixels, size_t bytes, uint32_t data); 152 153static void D_Clear_BitmapXferProc(void* pixels, size_t bytes, uint32_t) { 154 sk_bzero(pixels, bytes); 155} 156 157static void D_Dst_BitmapXferProc(void*, size_t, uint32_t data) {} 158 159static void D32_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 160 sk_memset32((uint32_t*)pixels, data, bytes >> 2); 161} 162 163static void D16_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 164 sk_memset16((uint16_t*)pixels, data, bytes >> 1); 165} 166 167static void DA8_Src_BitmapXferProc(void* pixels, size_t bytes, uint32_t data) { 168 memset(pixels, data, bytes); 169} 170 171static 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 245static 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 277void 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 317struct 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 333static 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 347static 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 369static 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 380static 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 387static 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 396static 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 403static 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 412static 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 429static 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 447bool 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 479PtProcRec::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 522static 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 541void 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 650static inline SkPoint* as_lefttop(SkRect* r) { 651 return (SkPoint*)(void*)r; 652} 653 654static inline SkPoint* as_rightbottom(SkRect* r) { 655 return ((SkPoint*)(void*)r) + 1; 656} 657 658void 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 if (paint.getStyle() == SkPaint::kFill_Style) { 710 if (paint.isAntiAlias()) { 711 SkScan::AntiFillRect(devRect, clip, blitter); 712 } else { 713 SkScan::FillRect(devRect, clip, blitter); 714 } 715 } else { 716 if (paint.isAntiAlias()) { 717 SkScan::AntiHairRect(devRect, clip, blitter); 718 } else { 719 SkScan::HairRect(devRect, clip, blitter); 720 } 721 } 722} 723 724void SkDraw::drawDevMask(const SkMask& srcM, const SkPaint& paint) const { 725 if (srcM.fBounds.isEmpty()) { 726 return; 727 } 728 729 SkMask dstM; 730 const SkMask* mask = &srcM; 731 732 dstM.fImage = NULL; 733 SkAutoMaskImage ami(&dstM, false); 734 735 if (paint.getMaskFilter() && 736 paint.getMaskFilter()->filterMask(&dstM, srcM, *fMatrix, NULL)) { 737 mask = &dstM; 738 } 739 740 if (fBounder && !fBounder->doIRect(mask->fBounds)) { 741 return; 742 } 743 744 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 745 746 blitter->blitMaskRegion(*mask, *fClip); 747} 748 749class SkAutoPaintRestoreColorStrokeWidth { 750public: 751 SkAutoPaintRestoreColorStrokeWidth(const SkPaint& paint) { 752 fPaint = (SkPaint*)&paint; 753 fColor = paint.getColor(); 754 fWidth = paint.getStrokeWidth(); 755 } 756 ~SkAutoPaintRestoreColorStrokeWidth() { 757 fPaint->setColor(fColor); 758 fPaint->setStrokeWidth(fWidth); 759 } 760 761private: 762 SkPaint* fPaint; 763 SkColor fColor; 764 SkScalar fWidth; 765}; 766 767static SkScalar fast_len(const SkVector& vec) { 768 SkScalar x = SkScalarAbs(vec.fX); 769 SkScalar y = SkScalarAbs(vec.fY); 770 if (x < y) { 771 SkTSwap(x, y); 772 } 773 return x + SkScalarHalf(y); 774} 775 776// our idea is to return true if there is no appreciable skew or non-square scale 777// for that we'll transform (0,1) and (1,0), and check that the resulting dot-prod 778// is nearly one 779static bool map_radius(const SkMatrix& matrix, SkScalar* value) { 780 if (matrix.getType() & SkMatrix::kPerspective_Mask) { 781 return false; 782 } 783 SkVector src[2], dst[2]; 784 src[0].set(*value, 0); 785 src[1].set(0, *value); 786 matrix.mapVectors(dst, src, 2); 787 SkScalar len0 = fast_len(dst[0]); 788 SkScalar len1 = fast_len(dst[1]); 789 if (len0 < SK_Scalar1 && len1 < SK_Scalar1) { 790 *value = SkScalarAve(len0, len1); 791 return true; 792 } 793 return false; 794} 795 796void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& paint, 797 const SkMatrix* prePathMatrix, bool pathIsMutable) const { 798 SkDEBUGCODE(this->validate();) 799 800 // nothing to draw 801 if (fClip->isEmpty() || 802 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 803 return; 804 } 805 806 SkPath* pathPtr = (SkPath*)&origSrcPath; 807 bool doFill = true; 808 SkPath tmpPath; 809 SkMatrix tmpMatrix; 810 const SkMatrix* matrix = fMatrix; 811 812 if (prePathMatrix) { 813 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style || 814 paint.getRasterizer()) { 815 SkPath* result = pathPtr; 816 817 if (!pathIsMutable) { 818 result = &tmpPath; 819 pathIsMutable = true; 820 } 821 pathPtr->transform(*prePathMatrix, result); 822 pathPtr = result; 823 } else { 824 if (!tmpMatrix.setConcat(*matrix, *prePathMatrix)) { 825 // overflow 826 return; 827 } 828 matrix = &tmpMatrix; 829 } 830 } 831 // at this point we're done with prePathMatrix 832 SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;) 833 834 /* 835 If the device thickness < 1.0, then make it a hairline, and 836 modulate alpha if the thickness is even smaller (e.g. thickness == 0.5 837 should modulate the alpha by 1/2) 838 */ 839 840 SkAutoPaintRestoreColorStrokeWidth aprc(paint); 841 842 // can we approximate a thin (but not hairline) stroke with an alpha-modulated 843 // hairline? Only if the matrix scales evenly in X and Y, and the device-width is 844 // less than a pixel 845 if (paint.getStyle() == SkPaint::kStroke_Style && paint.getXfermode() == NULL) { 846 SkScalar width = paint.getStrokeWidth(); 847 if (width > 0 && map_radius(*matrix, &width)) { 848 int scale = (int)SkScalarMul(width, 256); 849 int alpha = paint.getAlpha() * scale >> 8; 850 851 // pretend to be a hairline, with a modulated alpha 852 ((SkPaint*)&paint)->setAlpha(alpha); 853 ((SkPaint*)&paint)->setStrokeWidth(0); 854 } 855 } 856 857 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 858 doFill = paint.getFillPath(*pathPtr, &tmpPath); 859 pathPtr = &tmpPath; 860 } 861 862 if (paint.getRasterizer()) { 863 SkMask mask; 864 if (paint.getRasterizer()->rasterize(*pathPtr, *matrix, 865 &fClip->getBounds(), paint.getMaskFilter(), &mask, 866 SkMask::kComputeBoundsAndRenderImage_CreateMode)) { 867 this->drawDevMask(mask, paint); 868 SkMask::FreeImage(mask.fImage); 869 } 870 return; 871 } 872 873 // avoid possibly allocating a new path in transform if we can 874 SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath; 875 876 // transform the path into device space 877 pathPtr->transform(*matrix, devPathPtr); 878 879 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 880 881 // how does filterPath() know to fill or hairline the path??? <mrr> 882 if (paint.getMaskFilter() && 883 paint.getMaskFilter()->filterPath(*devPathPtr, *fMatrix, *fClip, 884 fBounder, blitter.get())) { 885 return; // filterPath() called the blitter, so we're done 886 } 887 888 if (fBounder && !fBounder->doPath(*devPathPtr, paint, doFill)) { 889 return; 890 } 891 892 if (doFill) { 893 if (paint.isAntiAlias()) { 894 SkScan::AntiFillPath(*devPathPtr, *fClip, blitter.get()); 895 } else { 896 SkScan::FillPath(*devPathPtr, *fClip, blitter.get()); 897 } 898 } else { // hairline 899 if (paint.isAntiAlias()) { 900 SkScan::AntiHairPath(*devPathPtr, fClip, blitter.get()); 901 } else { 902 SkScan::HairPath(*devPathPtr, fClip, blitter.get()); 903 } 904 } 905} 906 907/** For the purposes of drawing bitmaps, if a matrix is "almost" translate 908 go ahead and treat it as if it were, so that subsequent code can go fast. 909 */ 910static bool just_translate(const SkMatrix& matrix, const SkBitmap& bitmap) { 911 SkMatrix::TypeMask mask = matrix.getType(); 912 913 if (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 914 return false; 915 } 916 if (mask & SkMatrix::kScale_Mask) { 917 SkScalar sx = matrix[SkMatrix::kMScaleX]; 918 SkScalar sy = matrix[SkMatrix::kMScaleY]; 919 int w = bitmap.width(); 920 int h = bitmap.height(); 921 int sw = SkScalarRound(SkScalarMul(sx, SkIntToScalar(w))); 922 int sh = SkScalarRound(SkScalarMul(sy, SkIntToScalar(h))); 923 return sw == w && sh == h; 924 } 925 // if we got here, we're either kTranslate_Mask or identity 926 return true; 927} 928 929void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap, 930 const SkPaint& paint) const { 931 SkASSERT(bitmap.getConfig() == SkBitmap::kA8_Config); 932 933 if (just_translate(*fMatrix, bitmap)) { 934 int ix = SkScalarRound(fMatrix->getTranslateX()); 935 int iy = SkScalarRound(fMatrix->getTranslateY()); 936 937 SkMask mask; 938 mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 939 mask.fFormat = SkMask::kA8_Format; 940 mask.fRowBytes = bitmap.rowBytes(); 941 mask.fImage = bitmap.getAddr8(0, 0); 942 943 this->drawDevMask(mask, paint); 944 } else { // need to xform the bitmap first 945 SkRect r; 946 SkMask mask; 947 948 r.set(0, 0, 949 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())); 950 fMatrix->mapRect(&r); 951 r.round(&mask.fBounds); 952 953 // set the mask's bounds to the transformed bitmap-bounds, 954 // clipped to the actual device 955 { 956 SkIRect devBounds; 957 devBounds.set(0, 0, fBitmap->width(), fBitmap->height()); 958 // need intersect(l, t, r, b) on irect 959 if (!mask.fBounds.intersect(devBounds)) { 960 return; 961 } 962 } 963 964 mask.fFormat = SkMask::kA8_Format; 965 mask.fRowBytes = SkAlign4(mask.fBounds.width()); 966 size_t size = mask.computeImageSize(); 967 if (0 == size) { 968 // the mask is too big to allocated, draw nothing 969 return; 970 } 971 972 // allocate (and clear) our temp buffer to hold the transformed bitmap 973 SkAutoMalloc storage(size); 974 mask.fImage = (uint8_t*)storage.get(); 975 memset(mask.fImage, 0, size); 976 977 // now draw our bitmap(src) into mask(dst), transformed by the matrix 978 { 979 SkBitmap device; 980 device.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), 981 mask.fBounds.height(), mask.fRowBytes); 982 device.setPixels(mask.fImage); 983 984 SkCanvas c(device); 985 // need the unclipped top/left for the translate 986 c.translate(-SkIntToScalar(mask.fBounds.fLeft), 987 -SkIntToScalar(mask.fBounds.fTop)); 988 c.concat(*fMatrix); 989 990 // We can't call drawBitmap, or we'll infinitely recurse. Instead 991 // we manually build a shader and draw that into our new mask 992 SkPaint tmpPaint; 993 tmpPaint.setFlags(paint.getFlags()); 994 SkAutoBitmapShaderInstall install(bitmap, &tmpPaint); 995 SkRect rr; 996 rr.set(0, 0, SkIntToScalar(bitmap.width()), 997 SkIntToScalar(bitmap.height())); 998 c.drawRect(rr, tmpPaint); 999 } 1000 this->drawDevMask(mask, paint); 1001 } 1002} 1003 1004static bool clipped_out(const SkMatrix& m, const SkRegion& c, 1005 const SkRect& srcR) { 1006 SkRect dstR; 1007 SkIRect devIR; 1008 1009 m.mapRect(&dstR, srcR); 1010 dstR.roundOut(&devIR); 1011 return c.quickReject(devIR); 1012} 1013 1014static bool clipped_out(const SkMatrix& matrix, const SkRegion& clip, 1015 int width, int height) { 1016 SkRect r; 1017 r.set(0, 0, SkIntToScalar(width), SkIntToScalar(height)); 1018 return clipped_out(matrix, clip, r); 1019} 1020 1021void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix, 1022 const SkPaint& paint) const { 1023 SkDEBUGCODE(this->validate();) 1024 1025 // nothing to draw 1026 if (fClip->isEmpty() || 1027 bitmap.width() == 0 || bitmap.height() == 0 || 1028 bitmap.getConfig() == SkBitmap::kNo_Config || 1029 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 1030 return; 1031 } 1032 1033 // run away on too-big bitmaps for now (exceed 16.16) 1034 if (bitmap.width() > 32767 || bitmap.height() > 32767) { 1035 return; 1036 } 1037 1038 SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); 1039 1040 SkMatrix matrix; 1041 if (!matrix.setConcat(*fMatrix, prematrix)) { 1042 return; 1043 } 1044 1045 // do I need to call the bounder first??? 1046 if (clipped_out(matrix, *fClip, bitmap.width(), bitmap.height())) { 1047 return; 1048 } 1049 1050 // only lock the pixels if we passed the clip test 1051 SkAutoLockPixels alp(bitmap); 1052 // after the lock, check if we are valid 1053 if (!bitmap.readyToDraw()) { 1054 return; 1055 } 1056 1057 if (bitmap.getConfig() != SkBitmap::kA8_Config && 1058 just_translate(matrix, bitmap)) { 1059 int ix = SkScalarRound(matrix.getTranslateX()); 1060 int iy = SkScalarRound(matrix.getTranslateY()); 1061 uint32_t storage[kBlitterStorageLongCount]; 1062 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 1063 ix, iy, storage, sizeof(storage)); 1064 if (blitter) { 1065 SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage); 1066 1067 SkIRect ir; 1068 ir.set(ix, iy, ix + bitmap.width(), iy + bitmap.height()); 1069 1070 if (fBounder && !fBounder->doIRect(ir)) { 1071 return; 1072 } 1073 1074 SkRegion::Cliperator iter(*fClip, ir); 1075 const SkIRect& cr = iter.rect(); 1076 1077 for (; !iter.done(); iter.next()) { 1078 SkASSERT(!cr.isEmpty()); 1079 blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 1080 } 1081 return; 1082 } 1083#if 0 1084 SkDebugf("---- MISSING sprite case: config=%d [%d %d], device=%d, xfer=%p, alpha=0x%X colorFilter=%p\n", 1085 bitmap.config(), bitmap.width(), bitmap.height(), fBitmap->config(), 1086 paint.getXfermode(), paint.getAlpha(), paint.getColorFilter()); 1087#endif 1088 } 1089 1090 // now make a temp draw on the stack, and use it 1091 // 1092 SkDraw draw(*this); 1093 draw.fMatrix = &matrix; 1094 1095 if (bitmap.getConfig() == SkBitmap::kA8_Config) { 1096 draw.drawBitmapAsMask(bitmap, paint); 1097 } else { 1098 SkAutoBitmapShaderInstall install(bitmap, &paint); 1099 1100 SkRect r; 1101 r.set(0, 0, SkIntToScalar(bitmap.width()), 1102 SkIntToScalar(bitmap.height())); 1103 // is this ok if paint has a rasterizer? 1104 draw.drawRect(r, paint); 1105 } 1106} 1107 1108void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y, 1109 const SkPaint& paint) const { 1110 SkDEBUGCODE(this->validate();) 1111 1112 // nothing to draw 1113 if (fClip->isEmpty() || 1114 bitmap.width() == 0 || bitmap.height() == 0 || 1115 bitmap.getConfig() == SkBitmap::kNo_Config || 1116 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 1117 return; 1118 } 1119 1120 SkIRect bounds; 1121 bounds.set(x, y, x + bitmap.width(), y + bitmap.height()); 1122 1123 if (fClip->quickReject(bounds)) { 1124 return; // nothing to draw 1125 } 1126 1127 SkAutoPaintStyleRestore restore(paint, SkPaint::kFill_Style); 1128 1129 if (NULL == paint.getColorFilter()) { 1130 uint32_t storage[kBlitterStorageLongCount]; 1131 SkBlitter* blitter = SkBlitter::ChooseSprite(*fBitmap, paint, bitmap, 1132 x, y, storage, sizeof(storage)); 1133 1134 if (blitter) { 1135 SkAutoTPlacementDelete<SkBlitter> ad(blitter, storage); 1136 1137 if (fBounder && !fBounder->doIRect(bounds)) { 1138 return; 1139 } 1140 1141 SkRegion::Cliperator iter(*fClip, bounds); 1142 const SkIRect& cr = iter.rect(); 1143 1144 for (; !iter.done(); iter.next()) { 1145 SkASSERT(!cr.isEmpty()); 1146 blitter->blitRect(cr.fLeft, cr.fTop, cr.width(), cr.height()); 1147 } 1148 return; 1149 } 1150 } 1151 1152 SkAutoBitmapShaderInstall install(bitmap, &paint); 1153 1154 SkMatrix matrix; 1155 SkRect r; 1156 1157 // get a scalar version of our rect 1158 r.set(bounds); 1159 1160 // tell the shader our offset 1161 matrix.setTranslate(r.fLeft, r.fTop); 1162 paint.getShader()->setLocalMatrix(matrix); 1163 1164 SkDraw draw(*this); 1165 matrix.reset(); 1166 draw.fMatrix = &matrix; 1167 // call ourself with a rect 1168 // is this OK if paint has a rasterizer? 1169 draw.drawRect(r, paint); 1170} 1171 1172/////////////////////////////////////////////////////////////////////////////// 1173 1174#include "SkScalerContext.h" 1175#include "SkGlyphCache.h" 1176#include "SkUtils.h" 1177 1178static void measure_text(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc, 1179 const char text[], size_t byteLength, SkVector* stopVector) { 1180 SkFixed x = 0, y = 0; 1181 const char* stop = text + byteLength; 1182 1183 SkAutoKern autokern; 1184 1185 while (text < stop) { 1186 // don't need x, y here, since all subpixel variants will have the 1187 // same advance 1188 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1189 1190 x += autokern.adjust(glyph) + glyph.fAdvanceX; 1191 y += glyph.fAdvanceY; 1192 } 1193 stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y)); 1194 1195 SkASSERT(text == stop); 1196} 1197 1198void SkDraw::drawText_asPaths(const char text[], size_t byteLength, 1199 SkScalar x, SkScalar y, 1200 const SkPaint& paint) const { 1201 SkDEBUGCODE(this->validate();) 1202 1203 SkTextToPathIter iter(text, byteLength, paint, true, true); 1204 1205 SkMatrix matrix; 1206 matrix.setScale(iter.getPathScale(), iter.getPathScale()); 1207 matrix.postTranslate(x, y); 1208 1209 const SkPath* iterPath; 1210 SkScalar xpos, prevXPos = 0; 1211 1212 while ((iterPath = iter.next(&xpos)) != NULL) { 1213 matrix.postTranslate(xpos - prevXPos, 0); 1214 this->drawPath(*iterPath, iter.getPaint(), &matrix, false); 1215 prevXPos = xpos; 1216 } 1217} 1218 1219#define kStdStrikeThru_Offset (-SK_Scalar1 * 6 / 21) 1220#define kStdUnderline_Offset (SK_Scalar1 / 9) 1221#define kStdUnderline_Thickness (SK_Scalar1 / 18) 1222 1223static void draw_paint_rect(const SkDraw* draw, const SkPaint& paint, 1224 const SkRect& r, SkScalar textSize) { 1225 if (paint.getStyle() == SkPaint::kFill_Style) { 1226 draw->drawRect(r, paint); 1227 } else { 1228 SkPaint p(paint); 1229 p.setStrokeWidth(SkScalarMul(textSize, paint.getStrokeWidth())); 1230 draw->drawRect(r, p); 1231 } 1232} 1233 1234static void handle_aftertext(const SkDraw* draw, const SkPaint& paint, 1235 SkScalar width, const SkPoint& start) { 1236 uint32_t flags = paint.getFlags(); 1237 1238 if (flags & (SkPaint::kUnderlineText_Flag | 1239 SkPaint::kStrikeThruText_Flag)) { 1240 SkScalar textSize = paint.getTextSize(); 1241 SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); 1242 SkRect r; 1243 1244 r.fLeft = start.fX; 1245 r.fRight = start.fX + width; 1246 1247 if (flags & SkPaint::kUnderlineText_Flag) { 1248 SkScalar offset = SkScalarMulAdd(textSize, kStdUnderline_Offset, 1249 start.fY); 1250 r.fTop = offset; 1251 r.fBottom = offset + height; 1252 draw_paint_rect(draw, paint, r, textSize); 1253 } 1254 if (flags & SkPaint::kStrikeThruText_Flag) { 1255 SkScalar offset = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, 1256 start.fY); 1257 r.fTop = offset; 1258 r.fBottom = offset + height; 1259 draw_paint_rect(draw, paint, r, textSize); 1260 } 1261 } 1262} 1263 1264// disable warning : local variable used without having been initialized 1265#if defined _WIN32 && _MSC_VER >= 1300 1266#pragma warning ( push ) 1267#pragma warning ( disable : 4701 ) 1268#endif 1269 1270////////////////////////////////////////////////////////////////////////////// 1271 1272static void D1G_NoBounder_RectClip(const SkDraw1Glyph& state, 1273 const SkGlyph& glyph, int left, int top) { 1274 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1275 SkASSERT(state.fClip->isRect()); 1276 SkASSERT(NULL == state.fBounder); 1277 SkASSERT(state.fClipBounds == state.fClip->getBounds()); 1278 1279 left += glyph.fLeft; 1280 top += glyph.fTop; 1281 1282 int right = left + glyph.fWidth; 1283 int bottom = top + glyph.fHeight; 1284 1285 SkMask mask; 1286 SkIRect storage; 1287 SkIRect* bounds = &mask.fBounds; 1288 1289 mask.fBounds.set(left, top, right, bottom); 1290 1291 // this extra test is worth it, assuming that most of the time it succeeds 1292 // since we can avoid writing to storage 1293 if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) { 1294 if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds)) 1295 return; 1296 bounds = &storage; 1297 } 1298 1299 uint8_t* aa = (uint8_t*)glyph.fImage; 1300 if (NULL == aa) { 1301 aa = (uint8_t*)state.fCache->findImage(glyph); 1302 if (NULL == aa) { 1303 return; // can't rasterize glyph 1304 } 1305 } 1306 1307 mask.fRowBytes = glyph.rowBytes(); 1308 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1309 mask.fImage = aa; 1310 state.fBlitter->blitMask(mask, *bounds); 1311} 1312 1313static void D1G_NoBounder_RgnClip(const SkDraw1Glyph& state, 1314 const SkGlyph& glyph, int left, int top) { 1315 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1316 SkASSERT(!state.fClip->isRect()); 1317 SkASSERT(NULL == state.fBounder); 1318 1319 SkMask mask; 1320 1321 left += glyph.fLeft; 1322 top += glyph.fTop; 1323 1324 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 1325 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 1326 1327 if (!clipper.done()) { 1328 const SkIRect& cr = clipper.rect(); 1329 const uint8_t* aa = (const uint8_t*)glyph.fImage; 1330 if (NULL == aa) { 1331 aa = (uint8_t*)state.fCache->findImage(glyph); 1332 if (NULL == aa) { 1333 return; 1334 } 1335 } 1336 1337 mask.fRowBytes = glyph.rowBytes(); 1338 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1339 mask.fImage = (uint8_t*)aa; 1340 do { 1341 state.fBlitter->blitMask(mask, cr); 1342 clipper.next(); 1343 } while (!clipper.done()); 1344 } 1345} 1346 1347static void D1G_Bounder(const SkDraw1Glyph& state, 1348 const SkGlyph& glyph, int left, int top) { 1349 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); 1350 1351 SkMask mask; 1352 1353 left += glyph.fLeft; 1354 top += glyph.fTop; 1355 1356 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight); 1357 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds); 1358 1359 if (!clipper.done()) { 1360 const SkIRect& cr = clipper.rect(); 1361 const uint8_t* aa = (const uint8_t*)glyph.fImage; 1362 if (NULL == aa) { 1363 aa = (uint8_t*)state.fCache->findImage(glyph); 1364 if (NULL == aa) { 1365 return; 1366 } 1367 } 1368 1369 if (state.fBounder->doIRect(cr)) { 1370 mask.fRowBytes = glyph.rowBytes(); 1371 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); 1372 mask.fImage = (uint8_t*)aa; 1373 do { 1374 state.fBlitter->blitMask(mask, cr); 1375 clipper.next(); 1376 } while (!clipper.done()); 1377 } 1378 } 1379} 1380 1381SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, 1382 SkGlyphCache* cache) { 1383 fDraw = draw; 1384 fBounder = draw->fBounder; 1385 fClip = draw->fClip; 1386 fClipBounds = fClip->getBounds(); 1387 fBlitter = blitter; 1388 fCache = cache; 1389 1390 if (draw->fProcs && draw->fProcs->fD1GProc) { 1391 return draw->fProcs->fD1GProc; 1392 } 1393 1394 if (NULL == fBounder) { 1395 if (fClip->isRect()) { 1396 return D1G_NoBounder_RectClip; 1397 } else { 1398 return D1G_NoBounder_RgnClip; 1399 } 1400 } else { 1401 return D1G_Bounder; 1402 } 1403} 1404 1405enum RoundBaseline { 1406 kDont_Round_Baseline, 1407 kRound_X_Baseline, 1408 kRound_Y_Baseline 1409}; 1410 1411static RoundBaseline computeRoundBaseline(const SkMatrix& mat) { 1412 if (mat[1] == 0 && mat[3] == 0) { 1413 // we're 0 or 180 degrees, round the y coordinate of the baseline 1414 return kRound_Y_Baseline; 1415 } else if (mat[0] == 0 && mat[4] == 0) { 1416 // we're 90 or 270 degrees, round the x coordinate of the baseline 1417 return kRound_X_Baseline; 1418 } else { 1419 return kDont_Round_Baseline; 1420 } 1421} 1422 1423/////////////////////////////////////////////////////////////////////////////// 1424 1425void SkDraw::drawText(const char text[], size_t byteLength, 1426 SkScalar x, SkScalar y, const SkPaint& paint) const { 1427 SkASSERT(byteLength == 0 || text != NULL); 1428 1429 SkDEBUGCODE(this->validate();) 1430 1431 // nothing to draw 1432 if (text == NULL || byteLength == 0 || 1433 fClip->isEmpty() || 1434 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 1435 return; 1436 } 1437 1438 SkScalar underlineWidth = 0; 1439 SkPoint underlineStart; 1440 1441 underlineStart.set(0, 0); // to avoid warning 1442 if (paint.getFlags() & (SkPaint::kUnderlineText_Flag | 1443 SkPaint::kStrikeThruText_Flag)) { 1444 underlineWidth = paint.measureText(text, byteLength); 1445 1446 SkScalar offsetX = 0; 1447 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1448 offsetX = SkScalarHalf(underlineWidth); 1449 } else if (paint.getTextAlign() == SkPaint::kRight_Align) { 1450 offsetX = underlineWidth; 1451 } 1452 underlineStart.set(x - offsetX, y); 1453 } 1454 1455 if (/*paint.isLinearText() ||*/ 1456 (fMatrix->getType() & SkMatrix::kPerspective_Mask)) { 1457 this->drawText_asPaths(text, byteLength, x, y, paint); 1458 handle_aftertext(this, paint, underlineWidth, underlineStart); 1459 return; 1460 } 1461 1462 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1463 1464 SkAutoGlyphCache autoCache(paint, fMatrix); 1465 SkGlyphCache* cache = autoCache.getCache(); 1466 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 1467 1468 // transform our starting point 1469 { 1470 SkPoint loc; 1471 fMatrix->mapXY(x, y, &loc); 1472 x = loc.fX; 1473 y = loc.fY; 1474 } 1475 1476 // need to measure first 1477 if (paint.getTextAlign() != SkPaint::kLeft_Align) { 1478 SkVector stop; 1479 1480 measure_text(cache, glyphCacheProc, text, byteLength, &stop); 1481 1482 SkScalar stopX = stop.fX; 1483 SkScalar stopY = stop.fY; 1484 1485 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1486 stopX = SkScalarHalf(stopX); 1487 stopY = SkScalarHalf(stopY); 1488 } 1489 x -= stopX; 1490 y -= stopY; 1491 } 1492 1493 SkFixed fx = SkScalarToFixed(x); 1494 SkFixed fy = SkScalarToFixed(y); 1495 const char* stop = text + byteLength; 1496 1497 if (paint.isSubpixelText()) { 1498 RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix); 1499 if (kRound_Y_Baseline == roundBaseline) { 1500 fy = (fy + 0x8000) & ~0xFFFF; 1501 } else if (kRound_X_Baseline == roundBaseline) { 1502 fx = (fx + 0x8000) & ~0xFFFF; 1503 } 1504 } else { 1505 // apply the bias here, so we don't have to add 1/2 in the loop 1506 fx += SK_Fixed1/2; 1507 fy += SK_Fixed1/2; 1508 } 1509 1510 SkAutoKern autokern; 1511 SkDraw1Glyph d1g; 1512 SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache); 1513 1514 while (text < stop) { 1515 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); 1516 1517 fx += autokern.adjust(glyph); 1518 1519 if (glyph.fWidth) { 1520 proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy)); 1521 } 1522 fx += glyph.fAdvanceX; 1523 fy += glyph.fAdvanceY; 1524 } 1525 1526 if (underlineWidth) { 1527 autoCache.release(); // release this now to free up the RAM 1528 handle_aftertext(this, paint, underlineWidth, underlineStart); 1529 } 1530} 1531 1532// last parameter is interpreted as SkFixed [x, y] 1533// return the fixed position, which may be rounded or not by the caller 1534// e.g. subpixel doesn't round 1535typedef void (*AlignProc)(const SkPoint&, const SkGlyph&, SkIPoint*); 1536 1537static void leftAlignProc(const SkPoint& loc, const SkGlyph& glyph, 1538 SkIPoint* dst) { 1539 dst->set(SkScalarToFixed(loc.fX), SkScalarToFixed(loc.fY)); 1540} 1541 1542static void centerAlignProc(const SkPoint& loc, const SkGlyph& glyph, 1543 SkIPoint* dst) { 1544 dst->set(SkScalarToFixed(loc.fX) - (glyph.fAdvanceX >> 1), 1545 SkScalarToFixed(loc.fY) - (glyph.fAdvanceY >> 1)); 1546} 1547 1548static void rightAlignProc(const SkPoint& loc, const SkGlyph& glyph, 1549 SkIPoint* dst) { 1550 dst->set(SkScalarToFixed(loc.fX) - glyph.fAdvanceX, 1551 SkScalarToFixed(loc.fY) - glyph.fAdvanceY); 1552} 1553 1554static AlignProc pick_align_proc(SkPaint::Align align) { 1555 static const AlignProc gProcs[] = { 1556 leftAlignProc, centerAlignProc, rightAlignProc 1557 }; 1558 1559 SkASSERT((unsigned)align < SK_ARRAY_COUNT(gProcs)); 1560 1561 return gProcs[align]; 1562} 1563 1564class TextMapState { 1565public: 1566 mutable SkPoint fLoc; 1567 1568 TextMapState(const SkMatrix& matrix, SkScalar y) 1569 : fMatrix(matrix), fProc(matrix.getMapXYProc()), fY(y) {} 1570 1571 typedef void (*Proc)(const TextMapState&, const SkScalar pos[]); 1572 1573 Proc pickProc(int scalarsPerPosition); 1574 1575private: 1576 const SkMatrix& fMatrix; 1577 SkMatrix::MapXYProc fProc; 1578 SkScalar fY; // ignored by MapXYProc 1579 // these are only used by Only... procs 1580 SkScalar fScaleX, fTransX, fTransformedY; 1581 1582 static void MapXProc(const TextMapState& state, const SkScalar pos[]) { 1583 state.fProc(state.fMatrix, *pos, state.fY, &state.fLoc); 1584 } 1585 1586 static void MapXYProc(const TextMapState& state, const SkScalar pos[]) { 1587 state.fProc(state.fMatrix, pos[0], pos[1], &state.fLoc); 1588 } 1589 1590 static void MapOnlyScaleXProc(const TextMapState& state, 1591 const SkScalar pos[]) { 1592 state.fLoc.set(SkScalarMul(state.fScaleX, *pos) + state.fTransX, 1593 state.fTransformedY); 1594 } 1595 1596 static void MapOnlyTransXProc(const TextMapState& state, 1597 const SkScalar pos[]) { 1598 state.fLoc.set(*pos + state.fTransX, state.fTransformedY); 1599 } 1600}; 1601 1602TextMapState::Proc TextMapState::pickProc(int scalarsPerPosition) { 1603 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 1604 1605 if (1 == scalarsPerPosition) { 1606 unsigned mtype = fMatrix.getType(); 1607 if (mtype & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask)) { 1608 return MapXProc; 1609 } else { 1610 fScaleX = fMatrix.getScaleX(); 1611 fTransX = fMatrix.getTranslateX(); 1612 fTransformedY = SkScalarMul(fY, fMatrix.getScaleY()) + 1613 fMatrix.getTranslateY(); 1614 return (mtype & SkMatrix::kScale_Mask) ? 1615 MapOnlyScaleXProc : MapOnlyTransXProc; 1616 } 1617 } else { 1618 return MapXYProc; 1619 } 1620} 1621 1622////////////////////////////////////////////////////////////////////////////// 1623 1624void SkDraw::drawPosText(const char text[], size_t byteLength, 1625 const SkScalar pos[], SkScalar constY, 1626 int scalarsPerPosition, const SkPaint& paint) const { 1627 SkASSERT(byteLength == 0 || text != NULL); 1628 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 1629 1630 SkDEBUGCODE(this->validate();) 1631 1632 // nothing to draw 1633 if (text == NULL || byteLength == 0 || 1634 fClip->isEmpty() || 1635 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 1636 return; 1637 } 1638 1639 if (/*paint.isLinearText() ||*/ 1640 (fMatrix->getType() & SkMatrix::kPerspective_Mask)) { 1641 // TODO !!!! 1642// this->drawText_asPaths(text, byteLength, x, y, paint); 1643 return; 1644 } 1645 1646 SkDrawCacheProc glyphCacheProc = paint.getDrawCacheProc(); 1647 SkAutoGlyphCache autoCache(paint, fMatrix); 1648 SkGlyphCache* cache = autoCache.getCache(); 1649 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, paint); 1650 1651 const char* stop = text + byteLength; 1652 AlignProc alignProc = pick_align_proc(paint.getTextAlign()); 1653 SkDraw1Glyph d1g; 1654 SkDraw1Glyph::Proc proc = d1g.init(this, blitter.get(), cache); 1655 TextMapState tms(*fMatrix, constY); 1656 TextMapState::Proc tmsProc = tms.pickProc(scalarsPerPosition); 1657 1658 if (paint.isSubpixelText()) { 1659 // maybe we should skip the rounding if linearText is set 1660 RoundBaseline roundBaseline = computeRoundBaseline(*fMatrix); 1661 1662 if (SkPaint::kLeft_Align == paint.getTextAlign()) { 1663 while (text < stop) { 1664 tmsProc(tms, pos); 1665 1666 SkFixed fx = SkScalarToFixed(tms.fLoc.fX); 1667 SkFixed fy = SkScalarToFixed(tms.fLoc.fY); 1668 1669 if (kRound_Y_Baseline == roundBaseline) { 1670 fy = (fy + 0x8000) & ~0xFFFF; 1671 } else if (kRound_X_Baseline == roundBaseline) { 1672 fx = (fx + 0x8000) & ~0xFFFF; 1673 } 1674 1675 const SkGlyph& glyph = glyphCacheProc(cache, &text, fx, fy); 1676 1677 if (glyph.fWidth) { 1678 proc(d1g, glyph, SkFixedFloor(fx), SkFixedFloor(fy)); 1679 } 1680 pos += scalarsPerPosition; 1681 } 1682 } else { 1683 while (text < stop) { 1684 const SkGlyph* glyph = &glyphCacheProc(cache, &text, 0, 0); 1685 1686 if (glyph->fWidth) { 1687 SkDEBUGCODE(SkFixed prevAdvX = glyph->fAdvanceX;) 1688 SkDEBUGCODE(SkFixed prevAdvY = glyph->fAdvanceY;) 1689 1690 SkFixed fx, fy; 1691 tmsProc(tms, pos); 1692 1693 { 1694 SkIPoint fixedLoc; 1695 alignProc(tms.fLoc, *glyph, &fixedLoc); 1696 fx = fixedLoc.fX; 1697 fy = fixedLoc.fY; 1698 1699 if (kRound_Y_Baseline == roundBaseline) { 1700 fy = (fy + 0x8000) & ~0xFFFF; 1701 } else if (kRound_X_Baseline == roundBaseline) { 1702 fx = (fx + 0x8000) & ~0xFFFF; 1703 } 1704 } 1705 1706 // have to call again, now that we've been "aligned" 1707 glyph = &glyphCacheProc(cache, &text, fx, fy); 1708 // the assumption is that the advance hasn't changed 1709 SkASSERT(prevAdvX == glyph->fAdvanceX); 1710 SkASSERT(prevAdvY == glyph->fAdvanceY); 1711 1712 proc(d1g, *glyph, SkFixedFloor(fx), SkFixedFloor(fy)); 1713 } 1714 pos += scalarsPerPosition; 1715 } 1716 } 1717 } else { // not subpixel 1718 while (text < stop) { 1719 // the last 2 parameters are ignored 1720 const SkGlyph& glyph = glyphCacheProc(cache, &text, 0, 0); 1721 1722 if (glyph.fWidth) { 1723 tmsProc(tms, pos); 1724 1725 SkIPoint fixedLoc; 1726 alignProc(tms.fLoc, glyph, &fixedLoc); 1727 1728 proc(d1g, glyph, 1729 SkFixedRound(fixedLoc.fX), SkFixedRound(fixedLoc.fY)); 1730 } 1731 pos += scalarsPerPosition; 1732 } 1733 } 1734} 1735 1736#if defined _WIN32 && _MSC_VER >= 1300 1737#pragma warning ( pop ) 1738#endif 1739 1740/////////////////////////////////////////////////////////////////////////////// 1741 1742#include "SkPathMeasure.h" 1743 1744static void morphpoints(SkPoint dst[], const SkPoint src[], int count, 1745 SkPathMeasure& meas, const SkMatrix& matrix) { 1746 SkMatrix::MapXYProc proc = matrix.getMapXYProc(); 1747 1748 for (int i = 0; i < count; i++) { 1749 SkPoint pos; 1750 SkVector tangent; 1751 1752 proc(matrix, src[i].fX, src[i].fY, &pos); 1753 SkScalar sx = pos.fX; 1754 SkScalar sy = pos.fY; 1755 1756 meas.getPosTan(sx, &pos, &tangent); 1757 1758 /* This is the old way (that explains our approach but is way too slow 1759 SkMatrix matrix; 1760 SkPoint pt; 1761 1762 pt.set(sx, sy); 1763 matrix.setSinCos(tangent.fY, tangent.fX); 1764 matrix.preTranslate(-sx, 0); 1765 matrix.postTranslate(pos.fX, pos.fY); 1766 matrix.mapPoints(&dst[i], &pt, 1); 1767 */ 1768 dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy), 1769 pos.fY + SkScalarMul(tangent.fX, sy)); 1770 } 1771} 1772 1773/* TODO 1774 1775 Need differentially more subdivisions when the follow-path is curvy. Not sure how to 1776 determine that, but we need it. I guess a cheap answer is let the caller tell us, 1777 but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out. 1778*/ 1779static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas, 1780 const SkMatrix& matrix) { 1781 SkPath::Iter iter(src, false); 1782 SkPoint srcP[4], dstP[3]; 1783 SkPath::Verb verb; 1784 1785 while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) { 1786 switch (verb) { 1787 case SkPath::kMove_Verb: 1788 morphpoints(dstP, srcP, 1, meas, matrix); 1789 dst->moveTo(dstP[0]); 1790 break; 1791 case SkPath::kLine_Verb: 1792 // turn lines into quads to look bendy 1793 srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX); 1794 srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY); 1795 morphpoints(dstP, srcP, 2, meas, matrix); 1796 dst->quadTo(dstP[0], dstP[1]); 1797 break; 1798 case SkPath::kQuad_Verb: 1799 morphpoints(dstP, &srcP[1], 2, meas, matrix); 1800 dst->quadTo(dstP[0], dstP[1]); 1801 break; 1802 case SkPath::kCubic_Verb: 1803 morphpoints(dstP, &srcP[1], 3, meas, matrix); 1804 dst->cubicTo(dstP[0], dstP[1], dstP[2]); 1805 break; 1806 case SkPath::kClose_Verb: 1807 dst->close(); 1808 break; 1809 default: 1810 SkASSERT(!"unknown verb"); 1811 break; 1812 } 1813 } 1814} 1815 1816void SkDraw::drawTextOnPath(const char text[], size_t byteLength, 1817 const SkPath& follow, const SkMatrix* matrix, 1818 const SkPaint& paint) const { 1819 SkASSERT(byteLength == 0 || text != NULL); 1820 1821 // nothing to draw 1822 if (text == NULL || byteLength == 0 || 1823 fClip->isEmpty() || 1824 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 1825 return; 1826 } 1827 1828 SkTextToPathIter iter(text, byteLength, paint, true, true); 1829 SkPathMeasure meas(follow, false); 1830 SkScalar hOffset = 0; 1831 1832 // need to measure first 1833 if (paint.getTextAlign() != SkPaint::kLeft_Align) { 1834 SkScalar pathLen = meas.getLength(); 1835 if (paint.getTextAlign() == SkPaint::kCenter_Align) { 1836 pathLen = SkScalarHalf(pathLen); 1837 } 1838 hOffset += pathLen; 1839 } 1840 1841 const SkPath* iterPath; 1842 SkScalar xpos; 1843 SkMatrix scaledMatrix; 1844 SkScalar scale = iter.getPathScale(); 1845 1846 scaledMatrix.setScale(scale, scale); 1847 1848 while ((iterPath = iter.next(&xpos)) != NULL) { 1849 SkPath tmp; 1850 SkMatrix m(scaledMatrix); 1851 1852 m.postTranslate(xpos + hOffset, 0); 1853 if (matrix) { 1854 m.postConcat(*matrix); 1855 } 1856 morphpath(&tmp, *iterPath, meas, m); 1857 this->drawPath(tmp, iter.getPaint()); 1858 } 1859} 1860 1861/////////////////////////////////////////////////////////////////////////////// 1862 1863struct VertState { 1864 int f0, f1, f2; 1865 1866 VertState(int vCount, const uint16_t indices[], int indexCount) 1867 : fIndices(indices) { 1868 fCurrIndex = 0; 1869 if (indices) { 1870 fCount = indexCount; 1871 } else { 1872 fCount = vCount; 1873 } 1874 } 1875 1876 typedef bool (*Proc)(VertState*); 1877 Proc chooseProc(SkCanvas::VertexMode mode); 1878 1879private: 1880 int fCount; 1881 int fCurrIndex; 1882 const uint16_t* fIndices; 1883 1884 static bool Triangles(VertState*); 1885 static bool TrianglesX(VertState*); 1886 static bool TriangleStrip(VertState*); 1887 static bool TriangleStripX(VertState*); 1888 static bool TriangleFan(VertState*); 1889 static bool TriangleFanX(VertState*); 1890}; 1891 1892bool VertState::Triangles(VertState* state) { 1893 int index = state->fCurrIndex; 1894 if (index + 3 > state->fCount) { 1895 return false; 1896 } 1897 state->f0 = index + 0; 1898 state->f1 = index + 1; 1899 state->f2 = index + 2; 1900 state->fCurrIndex = index + 3; 1901 return true; 1902} 1903 1904bool VertState::TrianglesX(VertState* state) { 1905 const uint16_t* indices = state->fIndices; 1906 int index = state->fCurrIndex; 1907 if (index + 3 > state->fCount) { 1908 return false; 1909 } 1910 state->f0 = indices[index + 0]; 1911 state->f1 = indices[index + 1]; 1912 state->f2 = indices[index + 2]; 1913 state->fCurrIndex = index + 3; 1914 return true; 1915} 1916 1917bool VertState::TriangleStrip(VertState* state) { 1918 int index = state->fCurrIndex; 1919 if (index + 3 > state->fCount) { 1920 return false; 1921 } 1922 state->f2 = index + 2; 1923 if (index & 1) { 1924 state->f0 = index + 1; 1925 state->f1 = index + 0; 1926 } else { 1927 state->f0 = index + 0; 1928 state->f1 = index + 1; 1929 } 1930 state->fCurrIndex = index + 1; 1931 return true; 1932} 1933 1934bool VertState::TriangleStripX(VertState* state) { 1935 const uint16_t* indices = state->fIndices; 1936 int index = state->fCurrIndex; 1937 if (index + 3 > state->fCount) { 1938 return false; 1939 } 1940 state->f2 = indices[index + 2]; 1941 if (index & 1) { 1942 state->f0 = indices[index + 1]; 1943 state->f1 = indices[index + 0]; 1944 } else { 1945 state->f0 = indices[index + 0]; 1946 state->f1 = indices[index + 1]; 1947 } 1948 state->fCurrIndex = index + 1; 1949 return true; 1950} 1951 1952bool VertState::TriangleFan(VertState* state) { 1953 int index = state->fCurrIndex; 1954 if (index + 3 > state->fCount) { 1955 return false; 1956 } 1957 state->f0 = 0; 1958 state->f1 = index + 1; 1959 state->f2 = index + 2; 1960 state->fCurrIndex = index + 1; 1961 return true; 1962} 1963 1964bool VertState::TriangleFanX(VertState* state) { 1965 const uint16_t* indices = state->fIndices; 1966 int index = state->fCurrIndex; 1967 if (index + 3 > state->fCount) { 1968 return false; 1969 } 1970 state->f0 = indices[0]; 1971 state->f1 = indices[index + 1]; 1972 state->f2 = indices[index + 2]; 1973 state->fCurrIndex = index + 1; 1974 return true; 1975} 1976 1977VertState::Proc VertState::chooseProc(SkCanvas::VertexMode mode) { 1978 switch (mode) { 1979 case SkCanvas::kTriangles_VertexMode: 1980 return fIndices ? TrianglesX : Triangles; 1981 case SkCanvas::kTriangleStrip_VertexMode: 1982 return fIndices ? TriangleStripX : TriangleStrip; 1983 case SkCanvas::kTriangleFan_VertexMode: 1984 return fIndices ? TriangleFanX : TriangleFan; 1985 default: 1986 return NULL; 1987 } 1988} 1989 1990typedef void (*HairProc)(const SkPoint&, const SkPoint&, const SkRegion*, 1991 SkBlitter*); 1992 1993static HairProc ChooseHairProc(bool doAntiAlias) { 1994 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 1995} 1996 1997static bool texture_to_matrix(const VertState& state, const SkPoint verts[], 1998 const SkPoint texs[], SkMatrix* matrix) { 1999 SkPoint src[3], dst[3]; 2000 2001 src[0] = texs[state.f0]; 2002 src[1] = texs[state.f1]; 2003 src[2] = texs[state.f2]; 2004 dst[0] = verts[state.f0]; 2005 dst[1] = verts[state.f1]; 2006 dst[2] = verts[state.f2]; 2007 return matrix->setPolyToPoly(src, dst, 3); 2008} 2009 2010class SkTriColorShader : public SkShader { 2011public: 2012 SkTriColorShader() {} 2013 2014 bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); 2015 2016 virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count); 2017 2018protected: 2019 SkTriColorShader(SkFlattenableReadBuffer& buffer) : SkShader(buffer) {} 2020 2021 virtual Factory getFactory() { return CreateProc; } 2022 2023private: 2024 SkMatrix fDstToUnit; 2025 SkPMColor fColors[3]; 2026 2027 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 2028 return SkNEW_ARGS(SkTriColorShader, (buffer)); 2029 } 2030 typedef SkShader INHERITED; 2031}; 2032 2033bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[], 2034 int index0, int index1, int index2) { 2035 2036 fColors[0] = SkPreMultiplyColor(colors[index0]); 2037 fColors[1] = SkPreMultiplyColor(colors[index1]); 2038 fColors[2] = SkPreMultiplyColor(colors[index2]); 2039 2040 SkMatrix m, im; 2041 m.reset(); 2042 m.set(0, pts[index1].fX - pts[index0].fX); 2043 m.set(1, pts[index2].fX - pts[index0].fX); 2044 m.set(2, pts[index0].fX); 2045 m.set(3, pts[index1].fY - pts[index0].fY); 2046 m.set(4, pts[index2].fY - pts[index0].fY); 2047 m.set(5, pts[index0].fY); 2048 if (!m.invert(&im)) { 2049 return false; 2050 } 2051 return fDstToUnit.setConcat(im, this->getTotalInverse()); 2052} 2053 2054#include "SkColorPriv.h" 2055#include "SkComposeShader.h" 2056 2057static int ScalarTo256(SkScalar v) { 2058 int scale = SkScalarToFixed(v) >> 8; 2059 if (scale < 0) { 2060 scale = 0; 2061 } 2062 if (scale > 255) { 2063 scale = 255; 2064 } 2065 return SkAlpha255To256(scale); 2066} 2067 2068void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { 2069 SkPoint src; 2070 2071 for (int i = 0; i < count; i++) { 2072 fDstToUnit.mapXY(SkIntToScalar(x), SkIntToScalar(y), &src); 2073 x += 1; 2074 2075 int scale1 = ScalarTo256(src.fX); 2076 int scale2 = ScalarTo256(src.fY); 2077 int scale0 = 256 - scale1 - scale2; 2078 if (scale0 < 0) { 2079 if (scale1 > scale2) { 2080 scale2 = 256 - scale1; 2081 } else { 2082 scale1 = 256 - scale2; 2083 } 2084 scale0 = 0; 2085 } 2086 2087 dstC[i] = SkAlphaMulQ(fColors[0], scale0) + 2088 SkAlphaMulQ(fColors[1], scale1) + 2089 SkAlphaMulQ(fColors[2], scale2); 2090 } 2091} 2092 2093void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, 2094 const SkPoint vertices[], const SkPoint textures[], 2095 const SkColor colors[], SkXfermode* xmode, 2096 const uint16_t indices[], int indexCount, 2097 const SkPaint& paint) const { 2098 SkASSERT(0 == count || NULL != vertices); 2099 2100 // abort early if there is nothing to draw 2101 if (count < 3 || (indices && indexCount < 3) || fClip->isEmpty() || 2102 (paint.getAlpha() == 0 && paint.getXfermode() == NULL)) { 2103 return; 2104 } 2105 2106 // transform out vertices into device coordinates 2107 SkAutoSTMalloc<16, SkPoint> storage(count); 2108 SkPoint* devVerts = storage.get(); 2109 fMatrix->mapPoints(devVerts, vertices, count); 2110 2111 if (fBounder) { 2112 SkRect bounds; 2113 bounds.set(devVerts, count); 2114 if (!fBounder->doRect(bounds, paint)) { 2115 return; 2116 } 2117 } 2118 2119 /* 2120 We can draw the vertices in 1 of 4 ways: 2121 2122 - solid color (no shader/texture[], no colors[]) 2123 - just colors (no shader/texture[], has colors[]) 2124 - just texture (has shader/texture[], no colors[]) 2125 - colors * texture (has shader/texture[], has colors[]) 2126 2127 Thus for texture drawing, we need both texture[] and a shader. 2128 */ 2129 2130 SkTriColorShader triShader; // must be above declaration of p 2131 SkPaint p(paint); 2132 2133 SkShader* shader = p.getShader(); 2134 if (NULL == shader) { 2135 // if we have no shader, we ignore the texture coordinates 2136 textures = NULL; 2137 } else if (NULL == textures) { 2138 // if we don't have texture coordinates, ignore the shader 2139 p.setShader(NULL); 2140 shader = NULL; 2141 } 2142 2143 // setup the custom shader (if needed) 2144 if (NULL != colors) { 2145 if (NULL == textures) { 2146 // just colors (no texture) 2147 p.setShader(&triShader); 2148 } else { 2149 // colors * texture 2150 SkASSERT(shader); 2151 bool releaseMode = false; 2152 if (NULL == xmode) { 2153 xmode = SkXfermode::Create(SkXfermode::kMultiply_Mode); 2154 releaseMode = true; 2155 } 2156 SkShader* compose = SkNEW_ARGS(SkComposeShader, 2157 (&triShader, shader, xmode)); 2158 p.setShader(compose)->unref(); 2159 if (releaseMode) { 2160 xmode->unref(); 2161 } 2162 } 2163 } 2164 2165 SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); 2166 // setup our state and function pointer for iterating triangles 2167 VertState state(count, indices, indexCount); 2168 VertState::Proc vertProc = state.chooseProc(vmode); 2169 2170 if (NULL != textures || NULL != colors) { 2171 SkMatrix localM, tempM; 2172 bool hasLocalM = shader && shader->getLocalMatrix(&localM); 2173 2174 if (NULL != colors) { 2175 if (!triShader.setContext(*fBitmap, p, *fMatrix)) { 2176 colors = NULL; 2177 } 2178 } 2179 2180 while (vertProc(&state)) { 2181 if (NULL != textures) { 2182 if (texture_to_matrix(state, vertices, textures, &tempM)) { 2183 if (hasLocalM) { 2184 tempM.postConcat(localM); 2185 } 2186 shader->setLocalMatrix(tempM); 2187 // need to recal setContext since we changed the local matrix 2188 if (!shader->setContext(*fBitmap, p, *fMatrix)) { 2189 continue; 2190 } 2191 } 2192 } 2193 if (NULL != colors) { 2194 if (!triShader.setup(vertices, colors, 2195 state.f0, state.f1, state.f2)) { 2196 continue; 2197 } 2198 } 2199 SkScan::FillTriangle(devVerts[state.f0], devVerts[state.f1], 2200 devVerts[state.f2], fClip, blitter.get()); 2201 } 2202 // now restore the shader's original local matrix 2203 if (NULL != shader) { 2204 if (hasLocalM) { 2205 shader->setLocalMatrix(localM); 2206 } else { 2207 shader->resetLocalMatrix(); 2208 } 2209 } 2210 } else { 2211 // no colors[] and no texture 2212 HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); 2213 while (vertProc(&state)) { 2214 hairProc(devVerts[state.f0], devVerts[state.f1], fClip, blitter.get()); 2215 hairProc(devVerts[state.f1], devVerts[state.f2], fClip, blitter.get()); 2216 hairProc(devVerts[state.f2], devVerts[state.f0], fClip, blitter.get()); 2217 } 2218 } 2219} 2220 2221//////////////////////////////////////////////////////////////////////////////////////// 2222//////////////////////////////////////////////////////////////////////////////////////// 2223 2224#ifdef SK_DEBUG 2225 2226void SkDraw::validate() const { 2227 SkASSERT(fBitmap != NULL); 2228 SkASSERT(fMatrix != NULL); 2229 SkASSERT(fClip != NULL); 2230 2231 const SkIRect& cr = fClip->getBounds(); 2232 SkIRect br; 2233 2234 br.set(0, 0, fBitmap->width(), fBitmap->height()); 2235 SkASSERT(cr.isEmpty() || br.contains(cr)); 2236} 2237 2238#endif 2239 2240////////////////////////////////////////////////////////////////////////////////////////// 2241 2242bool SkBounder::doIRect(const SkIRect& r) { 2243 SkIRect rr; 2244 return rr.intersect(fClip->getBounds(), r) && this->onIRect(rr); 2245} 2246 2247bool SkBounder::doHairline(const SkPoint& pt0, const SkPoint& pt1, 2248 const SkPaint& paint) { 2249 SkIRect r; 2250 SkScalar v0, v1; 2251 2252 v0 = pt0.fX; 2253 v1 = pt1.fX; 2254 if (v0 > v1) { 2255 SkTSwap<SkScalar>(v0, v1); 2256 } 2257 r.fLeft = SkScalarFloor(v0); 2258 r.fRight = SkScalarCeil(v1); 2259 2260 v0 = pt0.fY; 2261 v1 = pt1.fY; 2262 if (v0 > v1) { 2263 SkTSwap<SkScalar>(v0, v1); 2264 } 2265 r.fTop = SkScalarFloor(v0); 2266 r.fBottom = SkScalarCeil(v1); 2267 2268 if (paint.isAntiAlias()) { 2269 r.inset(-1, -1); 2270 } 2271 return this->doIRect(r); 2272} 2273 2274bool SkBounder::doRect(const SkRect& rect, const SkPaint& paint) { 2275 SkIRect r; 2276 2277 if (paint.getStyle() == SkPaint::kFill_Style) { 2278 rect.round(&r); 2279 } else { 2280 int rad = -1; 2281 rect.roundOut(&r); 2282 if (paint.isAntiAlias()) { 2283 rad = -2; 2284 } 2285 r.inset(rad, rad); 2286 } 2287 return this->doIRect(r); 2288} 2289 2290bool SkBounder::doPath(const SkPath& path, const SkPaint& paint, bool doFill) { 2291 SkIRect r; 2292 const SkRect& bounds = path.getBounds(); 2293 2294 if (doFill) { 2295 bounds.round(&r); 2296 } else { // hairline 2297 bounds.roundOut(&r); 2298 } 2299 2300 if (paint.isAntiAlias()) { 2301 r.inset(-1, -1); 2302 } 2303 return this->doIRect(r); 2304} 2305 2306void SkBounder::commit() { 2307 // override in subclass 2308} 2309 2310//////////////////////////////////////////////////////////////////////////////////////////////// 2311 2312#include "SkPath.h" 2313#include "SkDraw.h" 2314#include "SkRegion.h" 2315#include "SkBlitter.h" 2316 2317static bool compute_bounds(const SkPath& devPath, const SkIRect* clipBounds, 2318 SkMaskFilter* filter, const SkMatrix* filterMatrix, 2319 SkIRect* bounds) { 2320 if (devPath.isEmpty()) { 2321 return false; 2322 } 2323 2324 SkIPoint margin; 2325 margin.set(0, 0); 2326 2327 // init our bounds from the path 2328 { 2329 SkRect pathBounds = devPath.getBounds(); 2330 pathBounds.inset(-SK_ScalarHalf, -SK_ScalarHalf); 2331 pathBounds.roundOut(bounds); 2332 } 2333 2334 if (filter) { 2335 SkASSERT(filterMatrix); 2336 2337 SkMask srcM, dstM; 2338 2339 srcM.fBounds = *bounds; 2340 srcM.fFormat = SkMask::kA8_Format; 2341 srcM.fImage = NULL; 2342 if (!filter->filterMask(&dstM, srcM, *filterMatrix, &margin)) { 2343 return false; 2344 } 2345 *bounds = dstM.fBounds; 2346 } 2347 2348 if (clipBounds && !SkIRect::Intersects(*clipBounds, *bounds)) { 2349 return false; 2350 } 2351 2352 // (possibly) trim the srcM bounds to reflect the clip 2353 // (plus whatever slop the filter needs) 2354 if (clipBounds && !clipBounds->contains(*bounds)) { 2355 SkIRect tmp = *bounds; 2356 (void)tmp.intersect(*clipBounds); 2357 // Ugh. Guard against gigantic margins from wacky filters. Without this 2358 // check we can request arbitrary amounts of slop beyond our visible 2359 // clip, and bring down the renderer (at least on finite RAM machines 2360 // like handsets, etc.). Need to balance this invented value between 2361 // quality of large filters like blurs, and the corresponding memory 2362 // requests. 2363 static const int MAX_MARGIN = 128; 2364 tmp.inset(-SkMin32(margin.fX, MAX_MARGIN), 2365 -SkMin32(margin.fY, MAX_MARGIN)); 2366 (void)bounds->intersect(tmp); 2367 } 2368 2369 return true; 2370} 2371 2372static void draw_into_mask(const SkMask& mask, const SkPath& devPath) { 2373 SkBitmap bm; 2374 SkDraw draw; 2375 SkRegion clipRgn; 2376 SkMatrix matrix; 2377 SkPaint paint; 2378 2379 bm.setConfig(SkBitmap::kA8_Config, mask.fBounds.width(), mask.fBounds.height(), mask.fRowBytes); 2380 bm.setPixels(mask.fImage); 2381 2382 clipRgn.setRect(0, 0, mask.fBounds.width(), mask.fBounds.height()); 2383 matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft), 2384 -SkIntToScalar(mask.fBounds.fTop)); 2385 2386 draw.fBitmap = &bm; 2387 draw.fClip = &clipRgn; 2388 draw.fMatrix = &matrix; 2389 draw.fBounder = NULL; 2390 paint.setAntiAlias(true); 2391 draw.drawPath(devPath, paint); 2392} 2393 2394bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds, 2395 SkMaskFilter* filter, const SkMatrix* filterMatrix, 2396 SkMask* mask, SkMask::CreateMode mode) { 2397 if (SkMask::kJustRenderImage_CreateMode != mode) { 2398 if (!compute_bounds(devPath, clipBounds, filter, filterMatrix, &mask->fBounds)) 2399 return false; 2400 } 2401 2402 if (SkMask::kComputeBoundsAndRenderImage_CreateMode == mode) { 2403 mask->fFormat = SkMask::kA8_Format; 2404 mask->fRowBytes = mask->fBounds.width(); 2405 size_t size = mask->computeImageSize(); 2406 if (0 == size) { 2407 // we're too big to allocate the mask, abort 2408 return false; 2409 } 2410 mask->fImage = SkMask::AllocImage(size); 2411 memset(mask->fImage, 0, mask->computeImageSize()); 2412 } 2413 2414 if (SkMask::kJustComputeBounds_CreateMode != mode) { 2415 draw_into_mask(*mask, devPath); 2416 } 2417 2418 return true; 2419} 2420