SkiaCanvas.cpp revision fc9999505a36c66892d7ccce85187936105f4f36
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 "SkiaCanvas.h" 18 19#include "CanvasProperty.h" 20#include "VectorDrawable.h" 21#include "hwui/Bitmap.h" 22#include "hwui/MinikinUtils.h" 23 24#include <SkDrawable.h> 25#include <SkDevice.h> 26#include <SkDeque.h> 27#include <SkDrawFilter.h> 28#include <SkGraphics.h> 29#include <SkImage.h> 30#include <SkImagePriv.h> 31#include <SkRSXform.h> 32#include <SkShader.h> 33#include <SkTemplates.h> 34 35#include <memory> 36 37namespace android { 38 39Canvas* Canvas::create_canvas(const SkBitmap& bitmap) { 40 return new SkiaCanvas(bitmap); 41} 42 43Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) { 44 return new SkiaCanvas(skiaCanvas); 45} 46 47SkiaCanvas::SkiaCanvas(const SkBitmap& bitmap) { 48 mCanvas.reset(new SkCanvas(bitmap)); 49} 50 51void SkiaCanvas::reset(SkCanvas* skiaCanvas) { 52 mCanvas.reset(SkRef(skiaCanvas)); 53 mSaveStack.reset(nullptr); 54 mHighContrastText = false; 55} 56 57// ---------------------------------------------------------------------------- 58// Canvas state operations: Replace Bitmap 59// ---------------------------------------------------------------------------- 60 61class ClipCopier : public SkCanvas::ClipVisitor { 62public: 63 explicit ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {} 64 65 virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) { 66 m_dstCanvas->clipRect(rect, op, antialias); 67 } 68 virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) { 69 m_dstCanvas->clipRRect(rrect, op, antialias); 70 } 71 virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) { 72 m_dstCanvas->clipPath(path, op, antialias); 73 } 74 75private: 76 SkCanvas* m_dstCanvas; 77}; 78 79void SkiaCanvas::setBitmap(const SkBitmap& bitmap) { 80 sk_sp<SkCanvas> newCanvas(new SkCanvas(bitmap)); 81 82 if (!bitmap.isNull()) { 83 // Copy the canvas matrix & clip state. 84 newCanvas->setMatrix(mCanvas->getTotalMatrix()); 85 86 ClipCopier copier(newCanvas.get()); 87 mCanvas->replayClips(&copier); 88 } 89 90 // unrefs the existing canvas 91 mCanvas = std::move(newCanvas); 92 93 // clean up the old save stack 94 mSaveStack.reset(NULL); 95} 96 97// ---------------------------------------------------------------------------- 98// Canvas state operations 99// ---------------------------------------------------------------------------- 100 101bool SkiaCanvas::isOpaque() { 102 return mCanvas->imageInfo().isOpaque(); 103} 104 105int SkiaCanvas::width() { 106 return mCanvas->imageInfo().width(); 107} 108 109int SkiaCanvas::height() { 110 return mCanvas->imageInfo().height(); 111} 112 113// ---------------------------------------------------------------------------- 114// Canvas state operations: Save (layer) 115// ---------------------------------------------------------------------------- 116 117int SkiaCanvas::getSaveCount() const { 118 return mCanvas->getSaveCount(); 119} 120 121int SkiaCanvas::save(SaveFlags::Flags flags) { 122 int count = mCanvas->save(); 123 recordPartialSave(flags); 124 return count; 125} 126 127// The SkiaCanvas::restore operation layers on the capability to preserve 128// either (or both) the matrix and/or clip state after a SkCanvas::restore 129// operation. It does this by explicitly saving off the clip & matrix state 130// when requested and playing it back after the SkCanvas::restore. 131void SkiaCanvas::restore() { 132 const SaveRec* rec = (NULL == mSaveStack.get()) 133 ? NULL 134 : static_cast<SaveRec*>(mSaveStack->back()); 135 int currentSaveCount = mCanvas->getSaveCount(); 136 SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount); 137 138 if (NULL == rec || rec->saveCount != currentSaveCount) { 139 // Fast path - no record for this frame. 140 mCanvas->restore(); 141 return; 142 } 143 144 bool preserveMatrix = !(rec->saveFlags & SaveFlags::Matrix); 145 bool preserveClip = !(rec->saveFlags & SaveFlags::Clip); 146 147 SkMatrix savedMatrix; 148 if (preserveMatrix) { 149 savedMatrix = mCanvas->getTotalMatrix(); 150 } 151 152 SkTArray<SkClipStack::Element> savedClips; 153 int topClipStackFrame = mCanvas->getClipStack()->getSaveCount(); 154 if (preserveClip) { 155 saveClipsForFrame(savedClips, topClipStackFrame); 156 } 157 158 mCanvas->restore(); 159 160 if (preserveMatrix) { 161 mCanvas->setMatrix(savedMatrix); 162 } 163 164 if (preserveClip && !savedClips.empty() && 165 topClipStackFrame != mCanvas->getClipStack()->getSaveCount()) { 166 // Only reapply the saved clips if the top clip stack frame was actually 167 // popped by restore(). If it wasn't, it means it doesn't belong to the 168 // restored canvas frame (SkCanvas lazy save/restore kicked in). 169 applyClips(savedClips); 170 } 171 172 mSaveStack->pop_back(); 173} 174 175void SkiaCanvas::restoreToCount(int restoreCount) { 176 while (mCanvas->getSaveCount() > restoreCount) { 177 this->restore(); 178 } 179} 180 181static inline SkCanvas::SaveLayerFlags layerFlags(SaveFlags::Flags flags) { 182 SkCanvas::SaveLayerFlags layerFlags = 0; 183 184 // We intentionally ignore the SaveFlags::HasAlphaLayer and 185 // SkCanvas::kIsOpaque_SaveLayerFlag flags because HWUI ignores it 186 // and our Android client may use it incorrectly. 187 // In Skia, this flag is purely for performance optimization. 188 189 if (!(flags & SaveFlags::ClipToLayer)) { 190 layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag; 191 } 192 193 return layerFlags; 194} 195 196int SkiaCanvas::saveLayer(float left, float top, float right, float bottom, 197 const SkPaint* paint, SaveFlags::Flags flags) { 198 const SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); 199 const SkCanvas::SaveLayerRec rec(&bounds, paint, layerFlags(flags)); 200 201 int count = mCanvas->saveLayer(rec); 202 recordPartialSave(flags); 203 return count; 204} 205 206int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom, 207 int alpha, SaveFlags::Flags flags) { 208 if (static_cast<unsigned>(alpha) < 0xFF) { 209 SkPaint alphaPaint; 210 alphaPaint.setAlpha(alpha); 211 return this->saveLayer(left, top, right, bottom, &alphaPaint, flags); 212 } 213 return this->saveLayer(left, top, right, bottom, nullptr, flags); 214} 215 216// ---------------------------------------------------------------------------- 217// functions to emulate legacy SaveFlags (i.e. independent matrix/clip flags) 218// ---------------------------------------------------------------------------- 219 220void SkiaCanvas::recordPartialSave(SaveFlags::Flags flags) { 221 // A partial save is a save operation which doesn't capture the full canvas state. 222 // (either SaveFlags::Matrix or SaveFlags::Clip is missing). 223 224 // Mask-out non canvas state bits. 225 flags &= SaveFlags::MatrixClip; 226 227 if (flags == SaveFlags::MatrixClip) { 228 // not a partial save. 229 return; 230 } 231 232 if (NULL == mSaveStack.get()) { 233 mSaveStack.reset(new SkDeque(sizeof(struct SaveRec), 8)); 234 } 235 236 SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back()); 237 rec->saveCount = mCanvas->getSaveCount(); 238 rec->saveFlags = flags; 239} 240 241void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, 242 int saveCountToBackup) { 243 // Each SkClipStack::Element stores the index of the canvas save 244 // with which it is associated. Backup only those Elements that 245 // are associated with 'saveCountToBackup' 246 SkClipStack::Iter clipIterator(*mCanvas->getClipStack(), 247 SkClipStack::Iter::kTop_IterStart); 248 while (const SkClipStack::Element* elem = clipIterator.prev()) { 249 if (elem->getSaveCount() < saveCountToBackup) { 250 // done with the target save count. 251 break; 252 } 253 SkASSERT(elem->getSaveCount() == saveCountToBackup); 254 clips.push_back(*elem); 255 } 256} 257 258void SkiaCanvas::applyClips(const SkTArray<SkClipStack::Element>& clips) { 259 ClipCopier clipCopier(mCanvas.get()); 260 261 // The clip stack stores clips in device space. 262 SkMatrix origMatrix = mCanvas->getTotalMatrix(); 263 mCanvas->resetMatrix(); 264 265 // We pushed the clips in reverse order. 266 for (int i = clips.count() - 1; i >= 0; --i) { 267 clips[i].replay(&clipCopier); 268 } 269 270 mCanvas->setMatrix(origMatrix); 271} 272 273// ---------------------------------------------------------------------------- 274// Canvas state operations: Matrix 275// ---------------------------------------------------------------------------- 276 277void SkiaCanvas::getMatrix(SkMatrix* outMatrix) const { 278 *outMatrix = mCanvas->getTotalMatrix(); 279} 280 281void SkiaCanvas::setMatrix(const SkMatrix& matrix) { 282 mCanvas->setMatrix(matrix); 283} 284 285void SkiaCanvas::concat(const SkMatrix& matrix) { 286 mCanvas->concat(matrix); 287} 288 289void SkiaCanvas::rotate(float degrees) { 290 mCanvas->rotate(degrees); 291} 292 293void SkiaCanvas::scale(float sx, float sy) { 294 mCanvas->scale(sx, sy); 295} 296 297void SkiaCanvas::skew(float sx, float sy) { 298 mCanvas->skew(sx, sy); 299} 300 301void SkiaCanvas::translate(float dx, float dy) { 302 mCanvas->translate(dx, dy); 303} 304 305// ---------------------------------------------------------------------------- 306// Canvas state operations: Clips 307// ---------------------------------------------------------------------------- 308 309// This function is a mirror of SkCanvas::getClipBounds except that it does 310// not outset the edge of the clip to account for anti-aliasing. There is 311// a skia bug to investigate pushing this logic into back into skia. 312// (see https://code.google.com/p/skia/issues/detail?id=1303) 313bool SkiaCanvas::getClipBounds(SkRect* outRect) const { 314 SkIRect ibounds; 315 if (!mCanvas->getClipDeviceBounds(&ibounds)) { 316 return false; 317 } 318 319 SkMatrix inverse; 320 // if we can't invert the CTM, we can't return local clip bounds 321 if (!mCanvas->getTotalMatrix().invert(&inverse)) { 322 if (outRect) { 323 outRect->setEmpty(); 324 } 325 return false; 326 } 327 328 if (NULL != outRect) { 329 SkRect r = SkRect::Make(ibounds); 330 inverse.mapRect(outRect, r); 331 } 332 return true; 333} 334 335bool SkiaCanvas::quickRejectRect(float left, float top, float right, float bottom) const { 336 SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom); 337 return mCanvas->quickReject(bounds); 338} 339 340bool SkiaCanvas::quickRejectPath(const SkPath& path) const { 341 return mCanvas->quickReject(path); 342} 343 344bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 345 SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 346 mCanvas->clipRect(rect, op); 347 return !mCanvas->isClipEmpty(); 348} 349 350bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) { 351 SkRRect roundRect; 352 if (path->isRRect(&roundRect)) { 353 mCanvas->clipRRect(roundRect, op); 354 } else { 355 mCanvas->clipPath(*path, op); 356 } 357 return !mCanvas->isClipEmpty(); 358} 359 360bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) { 361 SkPath rgnPath; 362 if (region->getBoundaryPath(&rgnPath)) { 363 // The region is specified in device space. 364 SkMatrix savedMatrix = mCanvas->getTotalMatrix(); 365 mCanvas->resetMatrix(); 366 mCanvas->clipPath(rgnPath, op); 367 mCanvas->setMatrix(savedMatrix); 368 } else { 369 mCanvas->clipRect(SkRect::MakeEmpty(), op); 370 } 371 return !mCanvas->isClipEmpty(); 372} 373 374// ---------------------------------------------------------------------------- 375// Canvas state operations: Filters 376// ---------------------------------------------------------------------------- 377 378SkDrawFilter* SkiaCanvas::getDrawFilter() { 379 return mCanvas->getDrawFilter(); 380} 381 382void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) { 383 mCanvas->setDrawFilter(drawFilter); 384} 385 386// ---------------------------------------------------------------------------- 387// Canvas draw operations 388// ---------------------------------------------------------------------------- 389 390void SkiaCanvas::drawColor(int color, SkBlendMode mode) { 391 mCanvas->drawColor(color, mode); 392} 393 394void SkiaCanvas::drawPaint(const SkPaint& paint) { 395 mCanvas->drawPaint(paint); 396} 397 398// ---------------------------------------------------------------------------- 399// Canvas draw operations: Geometry 400// ---------------------------------------------------------------------------- 401 402void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint, 403 SkCanvas::PointMode mode) { 404 // convert the floats into SkPoints 405 count >>= 1; // now it is the number of points 406 std::unique_ptr<SkPoint[]> pts(new SkPoint[count]); 407 for (int i = 0; i < count; i++) { 408 pts[i].set(points[0], points[1]); 409 points += 2; 410 } 411 mCanvas->drawPoints(mode, count, pts.get(), paint); 412} 413 414 415void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) { 416 mCanvas->drawPoint(x, y, paint); 417} 418 419void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) { 420 this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode); 421} 422 423void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY, 424 const SkPaint& paint) { 425 mCanvas->drawLine(startX, startY, stopX, stopY, paint); 426} 427 428void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) { 429 this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode); 430} 431 432void SkiaCanvas::drawRect(float left, float top, float right, float bottom, 433 const SkPaint& paint) { 434 mCanvas->drawRectCoords(left, top, right, bottom, paint); 435 436} 437 438void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { 439 SkRegion::Iterator it(region); 440 while (!it.done()) { 441 mCanvas->drawRect(SkRect::Make(it.rect()), paint); 442 it.next(); 443 } 444} 445 446void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, 447 float rx, float ry, const SkPaint& paint) { 448 SkRect rect = SkRect::MakeLTRB(left, top, right, bottom); 449 mCanvas->drawRoundRect(rect, rx, ry, paint); 450} 451 452void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { 453 mCanvas->drawCircle(x, y, radius, paint); 454} 455 456void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { 457 SkRect oval = SkRect::MakeLTRB(left, top, right, bottom); 458 mCanvas->drawOval(oval, paint); 459} 460 461void SkiaCanvas::drawArc(float left, float top, float right, float bottom, 462 float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) { 463 SkRect arc = SkRect::MakeLTRB(left, top, right, bottom); 464 mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint); 465} 466 467void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 468 SkRect rect; 469 SkRRect roundRect; 470 if (path.isOval(&rect)) { 471 mCanvas->drawOval(rect, paint); 472 } else if (path.isRRect(&roundRect)) { 473 mCanvas->drawRRect(roundRect, paint); 474 } else { 475 mCanvas->drawPath(path, paint); 476 } 477} 478 479void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount, 480 const float* verts, const float* texs, const int* colors, 481 const uint16_t* indices, int indexCount, const SkPaint& paint) { 482#ifndef SK_SCALAR_IS_FLOAT 483 SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid"); 484#endif 485 const int ptCount = vertexCount >> 1; 486 mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs, 487 (SkColor*)colors, NULL, indices, indexCount, paint); 488} 489 490// ---------------------------------------------------------------------------- 491// Canvas draw operations: Bitmaps 492// ---------------------------------------------------------------------------- 493 494void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) { 495 SkBitmap skBitmap; 496 bitmap.getSkBitmap(&skBitmap); 497 mCanvas->drawBitmap(skBitmap, left, top, paint); 498} 499 500void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, const SkMatrix& matrix, const SkPaint* paint) { 501 SkBitmap bitmap; 502 hwuiBitmap.getSkBitmap(&bitmap); 503 SkAutoCanvasRestore acr(mCanvas.get(), true); 504 mCanvas->concat(matrix); 505 mCanvas->drawBitmap(bitmap, 0, 0, paint); 506} 507 508void SkiaCanvas::drawBitmap(Bitmap& hwuiBitmap, float srcLeft, float srcTop, 509 float srcRight, float srcBottom, float dstLeft, float dstTop, 510 float dstRight, float dstBottom, const SkPaint* paint) { 511 SkBitmap bitmap; 512 hwuiBitmap.getSkBitmap(&bitmap); 513 SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom); 514 SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); 515 mCanvas->drawBitmapRect(bitmap, srcRect, dstRect, paint); 516} 517 518void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, 519 const float* vertices, const int* colors, const SkPaint* paint) { 520 521 const int ptCount = (meshWidth + 1) * (meshHeight + 1); 522 const int indexCount = meshWidth * meshHeight * 6; 523 524 /* Our temp storage holds 2 or 3 arrays. 525 texture points [ptCount * sizeof(SkPoint)] 526 optionally vertex points [ptCount * sizeof(SkPoint)] if we need a 527 copy to convert from float to fixed 528 indices [ptCount * sizeof(uint16_t)] 529 */ 530 ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[] 531 storageSize += indexCount * sizeof(uint16_t); // indices[] 532 533 534#ifndef SK_SCALAR_IS_FLOAT 535 SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid"); 536#endif 537 std::unique_ptr<char[]> storage(new char[storageSize]); 538 SkPoint* texs = (SkPoint*)storage.get(); 539 uint16_t* indices = (uint16_t*)(texs + ptCount); 540 541 // cons up texture coordinates and indices 542 { 543 const SkScalar w = SkIntToScalar(bitmap.width()); 544 const SkScalar h = SkIntToScalar(bitmap.height()); 545 const SkScalar dx = w / meshWidth; 546 const SkScalar dy = h / meshHeight; 547 548 SkPoint* texsPtr = texs; 549 SkScalar y = 0; 550 for (int i = 0; i <= meshHeight; i++) { 551 if (i == meshHeight) { 552 y = h; // to ensure numerically we hit h exactly 553 } 554 SkScalar x = 0; 555 for (int j = 0; j < meshWidth; j++) { 556 texsPtr->set(x, y); 557 texsPtr += 1; 558 x += dx; 559 } 560 texsPtr->set(w, y); 561 texsPtr += 1; 562 y += dy; 563 } 564 SkASSERT(texsPtr - texs == ptCount); 565 } 566 567 // cons up indices 568 { 569 uint16_t* indexPtr = indices; 570 int index = 0; 571 for (int i = 0; i < meshHeight; i++) { 572 for (int j = 0; j < meshWidth; j++) { 573 // lower-left triangle 574 *indexPtr++ = index; 575 *indexPtr++ = index + meshWidth + 1; 576 *indexPtr++ = index + meshWidth + 2; 577 // upper-right triangle 578 *indexPtr++ = index; 579 *indexPtr++ = index + meshWidth + 2; 580 *indexPtr++ = index + 1; 581 // bump to the next cell 582 index += 1; 583 } 584 // bump to the next row 585 index += 1; 586 } 587 SkASSERT(indexPtr - indices == indexCount); 588 SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize); 589 } 590 591 // double-check that we have legal indices 592#ifdef SK_DEBUG 593 { 594 for (int i = 0; i < indexCount; i++) { 595 SkASSERT((unsigned)indices[i] < (unsigned)ptCount); 596 } 597 } 598#endif 599 600 // cons-up a shader for the bitmap 601 SkPaint tmpPaint; 602 if (paint) { 603 tmpPaint = *paint; 604 } 605 sk_sp<SkShader> shader = SkMakeBitmapShader(bitmap, 606 SkShader::kClamp_TileMode, 607 SkShader::kClamp_TileMode, 608 nullptr, 609 kNever_SkCopyPixelsMode, 610 nullptr); 611 tmpPaint.setShader(std::move(shader)); 612 613 mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices, 614 texs, (const SkColor*)colors, NULL, indices, 615 indexCount, tmpPaint); 616} 617 618void SkiaCanvas::drawNinePatch(const SkBitmap& bitmap, const Res_png_9patch& chunk, 619 float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint) { 620 SkRect bounds = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom); 621 NinePatch::Draw(mCanvas.get(), bounds, bitmap, chunk, paint, nullptr); 622} 623 624void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) { 625 vectorDrawable->drawStaging(this); 626} 627 628// ---------------------------------------------------------------------------- 629// Canvas draw operations: Text 630// ---------------------------------------------------------------------------- 631 632void SkiaCanvas::drawGlyphs(const uint16_t* text, const float* positions, int count, 633 const SkPaint& paint, float x, float y, 634 float boundsLeft, float boundsTop, float boundsRight, float boundsBottom, 635 float totalAdvance) { 636 static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats"); 637 mCanvas->drawPosText(text, count << 1, reinterpret_cast<const SkPoint*>(positions), paint); 638 drawTextDecorations(x, y, totalAdvance, paint); 639} 640 641void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset, 642 const SkPaint& paint, const SkPath& path, size_t start, size_t end) { 643 const int N = end - start; 644 SkAutoSMalloc<1024> storage(N * (sizeof(uint16_t) + sizeof(SkRSXform))); 645 SkRSXform* xform = (SkRSXform*)storage.get(); 646 uint16_t* glyphs = (uint16_t*)(xform + N); 647 SkPathMeasure meas(path, false); 648 649 for (size_t i = start; i < end; i++) { 650 glyphs[i - start] = layout.getGlyphId(i); 651 float x = hOffset + layout.getX(i); 652 float y = vOffset + layout.getY(i); 653 654 SkPoint pos; 655 SkVector tan; 656 if (!meas.getPosTan(x, &pos, &tan)) { 657 pos.set(x, y); 658 tan.set(1, 0); 659 } 660 xform[i - start].fSCos = tan.x(); 661 xform[i - start].fSSin = tan.y(); 662 xform[i - start].fTx = pos.x() - tan.y() * y; 663 xform[i - start].fTy = pos.y() + tan.x() * y; 664 } 665 666 this->asSkCanvas()->drawTextRSXform(glyphs, sizeof(uint16_t) * N, xform, nullptr, paint); 667} 668 669// ---------------------------------------------------------------------------- 670// Canvas draw operations: Animations 671// ---------------------------------------------------------------------------- 672 673class AnimatedRoundRect : public SkDrawable { 674 public: 675 AnimatedRoundRect(uirenderer::CanvasPropertyPrimitive* left, 676 uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right, 677 uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx, 678 uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* p) : 679 mLeft(left), mTop(top), mRight(right), mBottom(bottom), mRx(rx), mRy(ry), mPaint(p) {} 680 681 protected: 682 virtual SkRect onGetBounds() override { 683 return SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value); 684 } 685 virtual void onDraw(SkCanvas* canvas) override { 686 SkRect rect = SkRect::MakeLTRB(mLeft->value, mTop->value, mRight->value, mBottom->value); 687 canvas->drawRoundRect(rect, mRx->value, mRy->value, mPaint->value); 688 } 689 690 private: 691 sp<uirenderer::CanvasPropertyPrimitive> mLeft; 692 sp<uirenderer::CanvasPropertyPrimitive> mTop; 693 sp<uirenderer::CanvasPropertyPrimitive> mRight; 694 sp<uirenderer::CanvasPropertyPrimitive> mBottom; 695 sp<uirenderer::CanvasPropertyPrimitive> mRx; 696 sp<uirenderer::CanvasPropertyPrimitive> mRy; 697 sp<uirenderer::CanvasPropertyPaint> mPaint; 698}; 699 700class AnimatedCircle : public SkDrawable { 701 public: 702 AnimatedCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y, 703 uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) : 704 mX(x), mY(y), mRadius(radius), mPaint(paint) {} 705 706 protected: 707 virtual SkRect onGetBounds() override { 708 const float x = mX->value; 709 const float y = mY->value; 710 const float radius = mRadius->value; 711 return SkRect::MakeLTRB(x - radius, y - radius, x + radius, y + radius); 712 } 713 virtual void onDraw(SkCanvas* canvas) override { 714 canvas->drawCircle(mX->value, mY->value, mRadius->value, mPaint->value); 715 } 716 717 private: 718 sp<uirenderer::CanvasPropertyPrimitive> mX; 719 sp<uirenderer::CanvasPropertyPrimitive> mY; 720 sp<uirenderer::CanvasPropertyPrimitive> mRadius; 721 sp<uirenderer::CanvasPropertyPaint> mPaint; 722}; 723 724void SkiaCanvas::drawRoundRect(uirenderer::CanvasPropertyPrimitive* left, 725 uirenderer::CanvasPropertyPrimitive* top, uirenderer::CanvasPropertyPrimitive* right, 726 uirenderer::CanvasPropertyPrimitive* bottom, uirenderer::CanvasPropertyPrimitive* rx, 727 uirenderer::CanvasPropertyPrimitive* ry, uirenderer::CanvasPropertyPaint* paint) { 728 sk_sp<AnimatedRoundRect> drawable( 729 new AnimatedRoundRect(left, top, right, bottom, rx, ry, paint)); 730 mCanvas->drawDrawable(drawable.get()); 731} 732 733void SkiaCanvas::drawCircle(uirenderer::CanvasPropertyPrimitive* x, uirenderer::CanvasPropertyPrimitive* y, 734 uirenderer::CanvasPropertyPrimitive* radius, uirenderer::CanvasPropertyPaint* paint) { 735 sk_sp<AnimatedCircle> drawable(new AnimatedCircle(x, y, radius, paint)); 736 mCanvas->drawDrawable(drawable.get()); 737} 738 739// ---------------------------------------------------------------------------- 740// Canvas draw operations: View System 741// ---------------------------------------------------------------------------- 742 743void SkiaCanvas::drawLayer(uirenderer::DeferredLayerUpdater* layer) { 744 LOG_ALWAYS_FATAL("SkiaCanvas can't directly draw Layers"); 745} 746 747void SkiaCanvas::drawRenderNode(uirenderer::RenderNode* renderNode) { 748 LOG_ALWAYS_FATAL("SkiaCanvas can't directly draw RenderNodes"); 749} 750 751void SkiaCanvas::callDrawGLFunction(Functor* functor, 752 uirenderer::GlFunctorLifecycleListener* listener) { 753 LOG_ALWAYS_FATAL("SkiaCanvas can't directly draw GL Content"); 754} 755 756} // namespace android 757