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