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