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