1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "Canvas.h" 18 19 #include <SkCanvas.h> 20 #include <SkClipStack.h> 21 #include <SkDevice.h> 22 #include <SkDeque.h> 23 #include <SkDrawFilter.h> 24 #include <SkGraphics.h> 25 #include <SkShader.h> 26 #include <SkTArray.h> 27 #include <SkTemplates.h> 28 29 namespace android { 30 31 // Holds an SkCanvas reference plus additional native data. 32 class SkiaCanvas : public Canvas { 33 public: 34 explicit SkiaCanvas(const SkBitmap& bitmap); 35 36 /** 37 * Create a new SkiaCanvas. 38 * 39 * @param canvas SkCanvas to handle calls made to this SkiaCanvas. Must 40 * not be NULL. This constructor will ref() the SkCanvas, and unref() 41 * it in its destructor. 42 */ 43 explicit SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) { 44 SkASSERT(canvas); 45 canvas->ref(); 46 } 47 48 virtual SkCanvas* asSkCanvas() override { 49 return mCanvas.get(); 50 } 51 52 virtual void setBitmap(const SkBitmap& bitmap) override; 53 54 virtual bool isOpaque() override; 55 virtual int width() override; 56 virtual int height() override; 57 58 virtual int getSaveCount() const override; 59 virtual int save(SkCanvas::SaveFlags flags) override; 60 virtual void restore() override; 61 virtual void restoreToCount(int saveCount) override; 62 63 virtual int saveLayer(float left, float top, float right, float bottom, 64 const SkPaint* paint, SkCanvas::SaveFlags flags) override; 65 virtual int saveLayerAlpha(float left, float top, float right, float bottom, 66 int alpha, SkCanvas::SaveFlags flags) override; 67 68 virtual void getMatrix(SkMatrix* outMatrix) const override; 69 virtual void setMatrix(const SkMatrix& matrix) override; 70 virtual void setLocalMatrix(const SkMatrix& matrix) override { this->setMatrix(matrix); } 71 virtual void concat(const SkMatrix& matrix) override; 72 virtual void rotate(float degrees) override; 73 virtual void scale(float sx, float sy) override; 74 virtual void skew(float sx, float sy) override; 75 virtual void translate(float dx, float dy) override; 76 77 virtual bool getClipBounds(SkRect* outRect) const override; 78 virtual bool quickRejectRect(float left, float top, float right, float bottom) const override; 79 virtual bool quickRejectPath(const SkPath& path) const override; 80 virtual bool clipRect(float left, float top, float right, float bottom, 81 SkRegion::Op op) override; 82 virtual bool clipPath(const SkPath* path, SkRegion::Op op) override; 83 virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) override; 84 85 virtual SkDrawFilter* getDrawFilter() override; 86 virtual void setDrawFilter(SkDrawFilter* drawFilter) override; 87 88 virtual void drawColor(int color, SkXfermode::Mode mode) override; 89 virtual void drawPaint(const SkPaint& paint) override; 90 91 virtual void drawPoint(float x, float y, const SkPaint& paint) override; 92 virtual void drawPoints(const float* points, int count, const SkPaint& paint) override; 93 virtual void drawLine(float startX, float startY, float stopX, float stopY, 94 const SkPaint& paint) override; 95 virtual void drawLines(const float* points, int count, const SkPaint& paint) override; 96 virtual void drawRect(float left, float top, float right, float bottom, 97 const SkPaint& paint) override; 98 virtual void drawRoundRect(float left, float top, float right, float bottom, 99 float rx, float ry, const SkPaint& paint) override; 100 virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) override; 101 virtual void drawOval(float left, float top, float right, float bottom, 102 const SkPaint& paint) override; 103 virtual void drawArc(float left, float top, float right, float bottom, 104 float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) override; 105 virtual void drawPath(const SkPath& path, const SkPaint& paint) override; 106 virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount, 107 const float* verts, const float* tex, const int* colors, 108 const uint16_t* indices, int indexCount, const SkPaint& paint) override; 109 110 virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, 111 const SkPaint* paint) override; 112 virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, 113 const SkPaint* paint) override; 114 virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, 115 float srcRight, float srcBottom, float dstLeft, float dstTop, 116 float dstRight, float dstBottom, const SkPaint* paint) override; 117 virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, 118 const float* vertices, const int* colors, const SkPaint* paint) override; 119 120 virtual void drawText(const uint16_t* text, const float* positions, int count, 121 const SkPaint& paint, float x, float y, 122 float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, 123 float totalAdvance) override; 124 virtual void drawPosText(const uint16_t* text, const float* positions, int count, 125 int posCount, const SkPaint& paint) override; 126 virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, 127 float hOffset, float vOffset, const SkPaint& paint) override; 128 129 virtual bool drawTextAbsolutePos() const override { return true; } 130 131 private: 132 struct SaveRec { 133 int saveCount; 134 SkCanvas::SaveFlags saveFlags; 135 }; 136 137 void recordPartialSave(SkCanvas::SaveFlags flags); 138 void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount); 139 void applyClips(const SkTArray<SkClipStack::Element>& clips); 140 141 void drawPoints(const float* points, int count, const SkPaint& paint, 142 SkCanvas::PointMode mode); 143 void drawTextDecorations(float x, float y, float length, const SkPaint& paint); 144 145 SkAutoTUnref<SkCanvas> mCanvas; 146 SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves. 147 }; 148 149 Canvas* Canvas::create_canvas(const SkBitmap& bitmap) { 150 return new SkiaCanvas(bitmap); 151 } 152 153 Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) { 154 return new SkiaCanvas(skiaCanvas); 155 } 156 157 SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) { 158 mCanvas.reset(new SkCanvas(bitmap)); 159 } 160 161 // ---------------------------------------------------------------------------- 162 // Canvas state operations: Replace Bitmap 163 // ---------------------------------------------------------------------------- 164 165 class ClipCopier : public SkCanvas::ClipVisitor { 166 public: 167 ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {} 168 169 virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) { 170 m_dstCanvas->clipRect(rect, op, antialias); 171 } 172 virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) { 173 m_dstCanvas->clipRRect(rrect, op, antialias); 174 } 175 virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) { 176 m_dstCanvas->clipPath(path, op, antialias); 177 } 178 179 private: 180 SkCanvas* m_dstCanvas; 181 }; 182 183 void SkiaCanvas::setBitmap(const SkBitmap& bitmap) { 184 SkCanvas* newCanvas = new SkCanvas(bitmap); 185 SkASSERT(newCanvas); 186 187 if (!bitmap.isNull()) { 188 // Copy the canvas matrix & clip state. 189 newCanvas->setMatrix(mCanvas->getTotalMatrix()); 190 if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) { 191 ClipCopier copier(newCanvas); 192 mCanvas->replayClips(&copier); 193 } 194 } 195 196 // unrefs the existing canvas 197 mCanvas.reset(newCanvas); 198 199 // clean up the old save stack 200 mSaveStack.reset(NULL); 201 } 202 203 // ---------------------------------------------------------------------------- 204 // Canvas state operations 205 // ---------------------------------------------------------------------------- 206 207 bool SkiaCanvas::isOpaque() { 208 return mCanvas->getDevice()->accessBitmap(false).isOpaque(); 209 } 210 211 int SkiaCanvas::width() { 212 return mCanvas->getBaseLayerSize().width(); 213 } 214 215 int SkiaCanvas::height() { 216 return mCanvas->getBaseLayerSize().height(); 217 } 218 219 // ---------------------------------------------------------------------------- 220 // Canvas state operations: Save (layer) 221 // ---------------------------------------------------------------------------- 222 223 int SkiaCanvas::getSaveCount() const { 224 return mCanvas->getSaveCount(); 225 } 226 227 int SkiaCanvas::save(SkCanvas::SaveFlags flags) { 228 int count = mCanvas->save(); 229 recordPartialSave(flags); 230 return count; 231 } 232 233 void SkiaCanvas::restore() { 234 const SaveRec* rec = (NULL == mSaveStack.get()) 235 ? NULL 236 : static_cast<SaveRec*>(mSaveStack->back()); 237 int currentSaveCount = mCanvas->getSaveCount() - 1; 238 SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount); 239 240 if (NULL == rec || rec->saveCount != currentSaveCount) { 241 // Fast path - no record for this frame. 242 mCanvas->restore(); 243 return; 244 } 245 246 bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag); 247 bool preserveClip = !(rec->saveFlags & SkCanvas::kClip_SaveFlag); 248 249 SkMatrix savedMatrix; 250 if (preserveMatrix) { 251 savedMatrix = mCanvas->getTotalMatrix(); 252 } 253 254 SkTArray<SkClipStack::Element> savedClips; 255 if (preserveClip) { 256 saveClipsForFrame(savedClips, currentSaveCount); 257 } 258 259 mCanvas->restore(); 260 261 if (preserveMatrix) { 262 mCanvas->setMatrix(savedMatrix); 263 } 264 265 if (preserveClip && !savedClips.empty()) { 266 applyClips(savedClips); 267 } 268 269 mSaveStack->pop_back(); 270 } 271 272 void SkiaCanvas::restoreToCount(int restoreCount) { 273 while (mCanvas->getSaveCount() > restoreCount) { 274 this->restore(); 275 } 276 } 277 278 int SkiaCanvas::saveLayer(float left, float top, float right, float bottom, 279 const SkPaint* paint, SkCanvas::SaveFlags flags) { 280 SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); 281 int count = mCanvas->saveLayer(&bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag); 282 recordPartialSave(flags); 283 return count; 284 } 285 286 int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom, 287 int alpha, SkCanvas::SaveFlags flags) { 288 SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); 289 int count = mCanvas->saveLayerAlpha(&bounds, alpha, flags | SkCanvas::kMatrixClip_SaveFlag); 290 recordPartialSave(flags); 291 return count; 292 } 293 294 // ---------------------------------------------------------------------------- 295 // functions to emulate legacy SaveFlags (i.e. independent matrix/clip flags) 296 // ---------------------------------------------------------------------------- 297 298 void SkiaCanvas::recordPartialSave(SkCanvas::SaveFlags flags) { 299 // A partial save is a save operation which doesn't capture the full canvas state. 300 // (either kMatrix_SaveFlags or kClip_SaveFlag is missing). 301 302 // Mask-out non canvas state bits. 303 flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag); 304 305 if (SkCanvas::kMatrixClip_SaveFlag == flags) { 306 // not a partial save. 307 return; 308 } 309 310 if (NULL == mSaveStack.get()) { 311 mSaveStack.reset(SkNEW_ARGS(SkDeque, (sizeof(struct SaveRec), 8))); 312 } 313 314 SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back()); 315 // Store the save counter in the SkClipStack domain. 316 // (0-based, equal to the number of save ops on the stack). 317 rec->saveCount = mCanvas->getSaveCount() - 1; 318 rec->saveFlags = flags; 319 } 320 321 void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount) { 322 SkClipStack::Iter clipIterator(*mCanvas->getClipStack(), 323 SkClipStack::Iter::kTop_IterStart); 324 while (const SkClipStack::Element* elem = clipIterator.next()) { 325 if (elem->getSaveCount() < frameSaveCount) { 326 // done with the current frame. 327 break; 328 } 329 SkASSERT(elem->getSaveCount() == frameSaveCount); 330 clips.push_back(*elem); 331 } 332 } 333 334 void SkiaCanvas::applyClips(const SkTArray<SkClipStack::Element>& clips) { 335 ClipCopier clipCopier(mCanvas); 336 337 // The clip stack stores clips in device space. 338 SkMatrix origMatrix = mCanvas->getTotalMatrix(); 339 mCanvas->resetMatrix(); 340 341 // We pushed the clips in reverse order. 342 for (int i = clips.count() - 1; i >= 0; --i) { 343 clips[i].replay(&clipCopier); 344 } 345 346 mCanvas->setMatrix(origMatrix); 347 } 348 349 // ---------------------------------------------------------------------------- 350 // Canvas state operations: Matrix 351 // ---------------------------------------------------------------------------- 352 353 void SkiaCanvas::getMatrix(SkMatrix* outMatrix) const { 354 *outMatrix = mCanvas->getTotalMatrix(); 355 } 356 357 void SkiaCanvas::setMatrix(const SkMatrix& matrix) { 358 mCanvas->setMatrix(matrix); 359 } 360 361 void SkiaCanvas::concat(const SkMatrix& matrix) { 362 mCanvas->concat(matrix); 363 } 364 365 void SkiaCanvas::rotate(float degrees) { 366 mCanvas->rotate(degrees); 367 } 368 369 void SkiaCanvas::scale(float sx, float sy) { 370 mCanvas->scale(sx, sy); 371 } 372 373 void SkiaCanvas::skew(float sx, float sy) { 374 mCanvas->skew(sx, sy); 375 } 376 377 void SkiaCanvas::translate(float dx, float dy) { 378 mCanvas->translate(dx, dy); 379 } 380 381 // ---------------------------------------------------------------------------- 382 // Canvas state operations: Clips 383 // ---------------------------------------------------------------------------- 384 385 // This function is a mirror of SkCanvas::getClipBounds except that it does 386 // not outset the edge of the clip to account for anti-aliasing. There is 387 // a skia bug to investigate pushing this logic into back into skia. 388 // (see https://code.google.com/p/skia/issues/detail?id=1303) 389 bool SkiaCanvas::getClipBounds(SkRect* outRect) const { 390 SkIRect ibounds; 391 if (!mCanvas->getClipDeviceBounds(&ibounds)) { 392 return false; 393 } 394 395 SkMatrix inverse; 396 // if we can't invert the CTM, we can't return local clip bounds 397 if (!mCanvas->getTotalMatrix().invert(&inverse)) { 398 if (outRect) { 399 outRect->setEmpty(); 400 } 401 return false; 402 } 403 404 if (NULL != outRect) { 405 SkRect r = SkRect::Make(ibounds); 406 inverse.mapRect(outRect, r); 407 } 408 return true; 409 } 410 411 bool SkiaCanvas::quickRejectRect(float left, float top, float right, float bottom) const { 412 SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); 413 return mCanvas->quickReject(bounds); 414 } 415 416 bool SkiaCanvas::quickRejectPath(const SkPath& path) const { 417 return mCanvas->quickReject(path); 418 } 419 420 bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 421 SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 422 mCanvas->clipRect(rect, op); 423 return !mCanvas->isClipEmpty(); 424 } 425 426 bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) { 427 mCanvas->clipPath(*path, op); 428 return !mCanvas->isClipEmpty(); 429 } 430 431 bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) { 432 SkPath rgnPath; 433 if (region->getBoundaryPath(&rgnPath)) { 434 // The region is specified in device space. 435 SkMatrix savedMatrix = mCanvas->getTotalMatrix(); 436 mCanvas->resetMatrix(); 437 mCanvas->clipPath(rgnPath, op); 438 mCanvas->setMatrix(savedMatrix); 439 } else { 440 mCanvas->clipRect(SkRect::MakeEmpty(), op); 441 } 442 return !mCanvas->isClipEmpty(); 443 } 444 445 // ---------------------------------------------------------------------------- 446 // Canvas state operations: Filters 447 // ---------------------------------------------------------------------------- 448 449 SkDrawFilter* SkiaCanvas::getDrawFilter() { 450 return mCanvas->getDrawFilter(); 451 } 452 453 void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) { 454 mCanvas->setDrawFilter(drawFilter); 455 } 456 457 // ---------------------------------------------------------------------------- 458 // Canvas draw operations 459 // ---------------------------------------------------------------------------- 460 461 void SkiaCanvas::drawColor(int color, SkXfermode::Mode mode) { 462 mCanvas->drawColor(color, mode); 463 } 464 465 void SkiaCanvas::drawPaint(const SkPaint& paint) { 466 mCanvas->drawPaint(paint); 467 } 468 469 // ---------------------------------------------------------------------------- 470 // Canvas draw operations: Geometry 471 // ---------------------------------------------------------------------------- 472 473 void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint, 474 SkCanvas::PointMode mode) { 475 // convert the floats into SkPoints 476 count >>= 1; // now it is the number of points 477 SkAutoSTMalloc<32, SkPoint> storage(count); 478 SkPoint* pts = storage.get(); 479 for (int i = 0; i < count; i++) { 480 pts[i].set(points[0], points[1]); 481 points += 2; 482 } 483 mCanvas->drawPoints(mode, count, pts, paint); 484 } 485 486 487 void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) { 488 mCanvas->drawPoint(x, y, paint); 489 } 490 491 void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) { 492 this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode); 493 } 494 495 void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, 496 const SkPaint& paint) { 497 mCanvas->drawLine(startX, startY, stopX, stopY, paint); 498 } 499 500 void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) { 501 this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode); 502 } 503 504 void SkiaCanvas::drawRect(float left, float top, float right, float bottom, 505 const SkPaint& paint) { 506 mCanvas->drawRectCoords(left, top, right, bottom, paint); 507 508 } 509 510 void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, 511 float rx, float ry, const SkPaint& paint) { 512 SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 513 mCanvas->drawRoundRect(rect, rx, ry, paint); 514 } 515 516 void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { 517 mCanvas->drawCircle(x, y, radius, paint); 518 } 519 520 void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { 521 SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); 522 mCanvas->drawOval(oval, paint); 523 } 524 525 void SkiaCanvas::drawArc(float left, float top, float right, float bottom, 526 float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) { 527 SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); 528 mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint); 529 } 530 531 void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 532 mCanvas->drawPath(path, paint); 533 } 534 535 void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount, 536 const float* verts, const float* texs, const int* colors, 537 const uint16_t* indices, int indexCount, const SkPaint& paint) { 538 #ifndef SK_SCALAR_IS_FLOAT 539 SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid"); 540 #endif 541 const int ptCount = vertexCount >> 1; 542 mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs, 543 (SkColor*)colors, NULL, indices, indexCount, paint); 544 } 545 546 // ---------------------------------------------------------------------------- 547 // Canvas draw operations: Bitmaps 548 // ---------------------------------------------------------------------------- 549 550 void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) { 551 mCanvas->drawBitmap(bitmap, left, top, paint); 552 } 553 554 void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) { 555 SkAutoCanvasRestore acr(mCanvas, true); 556 mCanvas->concat(matrix); 557 mCanvas->drawBitmap(bitmap, 0, 0, paint); 558 } 559 560 void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, 561 float srcRight, float srcBottom, float dstLeft, float dstTop, 562 float dstRight, float dstBottom, const SkPaint* paint) { 563 SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); 564 SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); 565 mCanvas->drawBitmapRectToRect(bitmap, &srcRect, dstRect, paint); 566 } 567 568 void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, 569 const float* vertices, const int* colors, const SkPaint* paint) { 570 571 const int ptCount = (meshWidth + 1) * (meshHeight + 1); 572 const int indexCount = meshWidth * meshHeight * 6; 573 574 /* Our temp storage holds 2 or 3 arrays. 575 texture points [ptCount * sizeof(SkPoint)] 576 optionally vertex points [ptCount * sizeof(SkPoint)] if we need a 577 copy to convert from float to fixed 578 indices [ptCount * sizeof(uint16_t)] 579 */ 580 ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[] 581 storageSize += indexCount * sizeof(uint16_t); // indices[] 582 583 584 #ifndef SK_SCALAR_IS_FLOAT 585 SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid"); 586 #endif 587 SkAutoMalloc storage(storageSize); 588 SkPoint* texs = (SkPoint*)storage.get(); 589 uint16_t* indices = (uint16_t*)(texs + ptCount); 590 591 // cons up texture coordinates and indices 592 { 593 const SkScalar w = SkIntToScalar(bitmap.width()); 594 const SkScalar h = SkIntToScalar(bitmap.height()); 595 const SkScalar dx = w / meshWidth; 596 const SkScalar dy = h / meshHeight; 597 598 SkPoint* texsPtr = texs; 599 SkScalar y = 0; 600 for (int i = 0; i <= meshHeight; i++) { 601 if (i == meshHeight) { 602 y = h; // to ensure numerically we hit h exactly 603 } 604 SkScalar x = 0; 605 for (int j = 0; j < meshWidth; j++) { 606 texsPtr->set(x, y); 607 texsPtr += 1; 608 x += dx; 609 } 610 texsPtr->set(w, y); 611 texsPtr += 1; 612 y += dy; 613 } 614 SkASSERT(texsPtr - texs == ptCount); 615 } 616 617 // cons up indices 618 { 619 uint16_t* indexPtr = indices; 620 int index = 0; 621 for (int i = 0; i < meshHeight; i++) { 622 for (int j = 0; j < meshWidth; j++) { 623 // lower-left triangle 624 *indexPtr++ = index; 625 *indexPtr++ = index + meshWidth + 1; 626 *indexPtr++ = index + meshWidth + 2; 627 // upper-right triangle 628 *indexPtr++ = index; 629 *indexPtr++ = index + meshWidth + 2; 630 *indexPtr++ = index + 1; 631 // bump to the next cell 632 index += 1; 633 } 634 // bump to the next row 635 index += 1; 636 } 637 SkASSERT(indexPtr - indices == indexCount); 638 SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize); 639 } 640 641 // double-check that we have legal indices 642 #ifdef SK_DEBUG 643 { 644 for (int i = 0; i < indexCount; i++) { 645 SkASSERT((unsigned)indices[i] < (unsigned)ptCount); 646 } 647 } 648 #endif 649 650 // cons-up a shader for the bitmap 651 SkPaint tmpPaint; 652 if (paint) { 653 tmpPaint = *paint; 654 } 655 SkShader* shader = SkShader::CreateBitmapShader(bitmap, 656 SkShader::kClamp_TileMode, 657 SkShader::kClamp_TileMode); 658 SkSafeUnref(tmpPaint.setShader(shader)); 659 660 mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices, 661 texs, (const SkColor*)colors, NULL, indices, 662 indexCount, tmpPaint); 663 } 664 665 // ---------------------------------------------------------------------------- 666 // Canvas draw operations: Text 667 // ---------------------------------------------------------------------------- 668 669 void SkiaCanvas::drawText(const uint16_t* text, const float* positions, int count, 670 const SkPaint& paint, float x, float y, 671 float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, 672 float totalAdvance) { 673 // Set align to left for drawing, as we don't want individual 674 // glyphs centered or right-aligned; the offset above takes 675 // care of all alignment. 676 SkPaint paintCopy(paint); 677 paintCopy.setTextAlign(SkPaint::kLeft_Align); 678 679 SK_COMPILE_ASSERT(sizeof(SkPoint) == sizeof(float)*2, SkPoint_is_no_longer_2_floats); 680 mCanvas->drawPosText(text, count << 1, reinterpret_cast<const SkPoint*>(positions), paintCopy); 681 } 682 683 void SkiaCanvas::drawPosText(const uint16_t* text, const float* positions, int count, int posCount, 684 const SkPaint& paint) { 685 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL; 686 int indx; 687 for (indx = 0; indx < posCount; indx++) { 688 posPtr[indx].fX = positions[indx << 1]; 689 posPtr[indx].fY = positions[(indx << 1) + 1]; 690 } 691 692 SkPaint paintCopy(paint); 693 paintCopy.setTextEncoding(SkPaint::kUTF16_TextEncoding); 694 mCanvas->drawPosText(text, count, posPtr, paintCopy); 695 696 delete[] posPtr; 697 } 698 699 void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path, 700 float hOffset, float vOffset, const SkPaint& paint) { 701 mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint); 702 } 703 704 } // namespace android 705