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