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