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