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