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