RecordingCanvas.cpp revision 6fe991e5e76f9af9dab960100d5768d96d5f4daa
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/*
2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2015 The Android Open Source Project
3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License.
6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at
7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *
10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software
11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and
14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License.
15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */
16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RecordingCanvas.h"
18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RecordedOp.h"
20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RenderNode.h"
21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
22b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android {
23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer {
24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
25b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikRecordingCanvas::RecordingCanvas(size_t width, size_t height)
26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        : mState(*this)
27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        , mResourceCache(ResourceCache::getInstance()) {
28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    reset(width, height);
29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikRecordingCanvas::~RecordingCanvas() {
32003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    LOG_ALWAYS_FATAL_IF(mDisplayList,
33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            "Destroyed a RecordingCanvas during a record!");
34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::reset(int width, int height) {
37003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    LOG_ALWAYS_FATAL_IF(mDisplayList,
38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            "prepareDirty called a second time during a recording!");
39003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mDisplayList = new DisplayList();
40b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
41b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.initializeSaveStack(width, height, 0, 0, width, height, Vector3());
42b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
43b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mDeferredBarrierType = kBarrier_InOrder;
44b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.setDirtyClip(false);
45b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount = -1;
46b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
47b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
48003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris CraikDisplayList* RecordingCanvas::finishRecording() {
49b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mPaintMap.clear();
50b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRegionMap.clear();
51b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mPathMap.clear();
52003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    DisplayList* displayList = mDisplayList;
53003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mDisplayList = nullptr;
54b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mSkiaCanvasProxy.reset(nullptr);
55003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    return displayList;
56b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
57b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
58b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikSkCanvas* RecordingCanvas::asSkCanvas() {
59003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    LOG_ALWAYS_FATAL_IF(!mDisplayList,
60b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            "attempting to get an SkCanvas when we are not recording!");
61b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!mSkiaCanvasProxy) {
62b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this));
63b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
64b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
65b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // SkCanvas instances default to identity transform, but should inherit
66b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // the state of this Canvas; if this code was in the SkiaCanvasProxy
67b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // constructor, we couldn't cache mSkiaCanvasProxy.
68b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkMatrix parentTransform;
69b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    getMatrix(&parentTransform);
70b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mSkiaCanvasProxy.get()->setMatrix(parentTransform);
71b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
72b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mSkiaCanvasProxy.get();
73b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
74b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
75b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
766fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// CanvasStateClient implementation
776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// ----------------------------------------------------------------------------
786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid RecordingCanvas::onViewportInitialized() {
806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
816fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    if (removed.flags & Snapshot::kFlagIsFboLayer) {
856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        addOp(new (alloc()) EndLayerOp());
866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// ----------------------------------------------------------------------------
90b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas state operations
91b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
92b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Save (layer)
93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint RecordingCanvas::save(SkCanvas::SaveFlags flags) {
94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.save((int) flags);
95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::RecordingCanvas::restore() {
98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (mRestoreSaveCount < 0) {
99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restoreToCount(getSaveCount() - 1);
100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount--;
104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.restore();
105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::restoreToCount(int saveCount) {
108b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount = saveCount;
109b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.restoreToCount(saveCount);
110b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
111b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
112b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint RecordingCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
113b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkCanvas::SaveFlags flags) {
1146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    if (!(flags & SkCanvas::kClipToLayer_SaveFlag)) {
1156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        LOG_ALWAYS_FATAL("unclipped layers not supported");
1166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // force matrix/clip isolation for layer
1186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
1196fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    const Snapshot& previous = *mState.currentSnapshot();
1226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // initialize the snapshot as though it almost represents an FBO layer so deferred draw
1246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // operations will be able to store and restore the current clip and transform info, and
1256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // quick rejection will be correct (for display lists)
1266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    const Rect untransformedBounds(left, top, right, bottom);
1286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // determine clipped bounds relative to previous viewport.
1306fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect visibleBounds = untransformedBounds;
1316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    previous.transform->mapRect(visibleBounds);
1326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    visibleBounds.doIntersect(previous.getRenderTargetClip());
1356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    visibleBounds.snapToPixelBoundaries();
1366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect previousViewport(0, 0, previous.getViewportWidth(), previous.getViewportHeight());
1386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    visibleBounds.doIntersect(previousViewport);
1396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // Map visible bounds back to layer space, and intersect with parameter bounds
1416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect layerBounds = visibleBounds;
1426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Matrix4 inverse;
1436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    inverse.loadInverse(*previous.transform);
1446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    inverse.mapRect(layerBounds);
1456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    layerBounds.doIntersect(untransformedBounds);
1466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    int saveValue = mState.save((int) flags);
1486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Snapshot& snapshot = *mState.writableSnapshot();
1496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // layerBounds is now original bounds, but with clipped to clip
1516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // and viewport to ensure it's minimal size.
1526fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    if (layerBounds.isEmpty() || untransformedBounds.isEmpty()) {
1536fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        // Don't bother recording layer, since it's been rejected
1546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        snapshot.resetClip(0, 0, 0, 0);
1556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return saveValue;
1566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1586fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
1596fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.initializeViewport(untransformedBounds.getWidth(), untransformedBounds.getHeight());
1606fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.resetTransform(-untransformedBounds.left, -untransformedBounds.top, 0.0f);
1616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect clip = layerBounds;
1636fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    clip.translate(-untransformedBounds.left, -untransformedBounds.top);
1646fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
1656fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.roundRectClipState = nullptr;
1666fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1676fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    addOp(new (alloc()) BeginLayerOp(
1686fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            Rect(left, top, right, bottom),
1696fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            *previous.transform, // transform to *draw* with
1706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            previous.getRenderTargetClip(), // clip to *draw* with
1716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            refPaint(paint)));
1726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    return saveValue;
174b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
175b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Matrix
177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::rotate(float degrees) {
178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (degrees == 0) return;
179b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.rotate(degrees);
181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
183b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::scale(float sx, float sy) {
184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (sx == 1 && sy == 1) return;
185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
186b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.scale(sx, sy);
187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
189b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::skew(float sx, float sy) {
190b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.skew(sx, sy);
191b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
192b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
193b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::translate(float dx, float dy) {
194b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (dx == 0 && dy == 0) return;
195b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.translate(dx, dy, 0);
197b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Clip
200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::getClipBounds(SkRect* outRect) const {
201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Rect bounds = mState.getLocalClipBounds();
202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return !(outRect->isEmpty());
204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.quickRejectConservative(left, top, right, bottom);
207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectPath(const SkPath& path) const {
209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkRect bounds = path.getBounds();
210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipRect(left, top, right, bottom, op);
214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipPath(path, op);
217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
218b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
219b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipRegion(region, op);
220b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
221b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
222b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
223b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas draw operations
224b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
225b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
226b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkPaint paint;
227b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    paint.setColor(color);
228b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    paint.setXfermodeMode(mode);
229b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    drawPaint(paint);
230b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
231b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
232b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPaint(const SkPaint& paint) {
233b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // TODO: more efficient recording?
234b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Matrix4 identity;
235b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    identity.loadIdentity();
236b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
237b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) RectOp(
238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            identity,
240b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(&paint)));
242b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
243b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
244b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Geometry
245b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
246b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
247b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
248b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
249b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
250b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
251b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
252b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) RectOp(
253b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(left, top, right, bottom),
254b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
255b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
256b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(&paint)));
257b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
259b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
260b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (rects == nullptr) return;
261b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
262003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc(vertexCount * sizeof(Vertex));
263b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Vertex* vertex = rectData;
264b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
265b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float left = FLT_MAX;
266b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float top = FLT_MAX;
267b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float right = FLT_MIN;
268b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float bottom = FLT_MIN;
269b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    for (int index = 0; index < vertexCount; index += 4) {
270b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float l = rects[index + 0];
271b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float t = rects[index + 1];
272b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float r = rects[index + 2];
273b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float b = rects[index + 3];
274b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
275b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, l, t);
276b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, r, t);
277b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, l, b);
278b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, r, b);
279b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
280b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        left = std::min(left, l);
281b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        top = std::min(top, t);
282b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        right = std::max(right, r);
283b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bottom = std::max(bottom, b);
284b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
285b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) SimpleRectsOp(
286b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(left, top, right, bottom),
287b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
288b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
289b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(paint), rectData, vertexCount));
290b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
291b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
292b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (paint.getStyle() == SkPaint::kFill_Style
294b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
295b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        int count = 0;
296b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vector<float> rects;
297b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRegion::Iterator it(region);
298b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        while (!it.done()) {
299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkIRect& r = it.rect();
300b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fLeft);
301b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fTop);
302b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fRight);
303b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fBottom);
304b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            count += 4;
305b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            it.next();
306b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
307b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawSimpleRects(rects.array(), count, &paint);
308b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
309b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRegion::Iterator it(region);
310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        while (!it.done()) {
311b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkIRect& r = it.rect();
312b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
313b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            it.next();
314b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
315b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
316b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
318b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float rx, float ry, const SkPaint& paint) {
319b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
320b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
321b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
322b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
323b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
324b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
325b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
326b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
327b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawArc(float left, float top, float right, float bottom,
328b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
329b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
330b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
331b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
332b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
333b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
334b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
335b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Bitmap-based
336b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
337b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    save(SkCanvas::kMatrix_SaveFlag);
338b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    translate(left, top);
339b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    drawBitmap(&bitmap, paint);
340b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    restore();
341b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
344b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                            const SkPaint* paint) {
345b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (matrix.isIdentity()) {
346b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
347b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
348b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && MathUtils::isPositive(matrix.getScaleX())
349b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && MathUtils::isPositive(matrix.getScaleY())) {
350b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // SkMatrix::isScaleTranslate() not available in L
351b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRect src;
352b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRect dst;
353b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bitmap.getBounds(&src);
354b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        matrix.mapRect(&dst, src);
355b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
356b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                   dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
357b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
358b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        save(SkCanvas::kMatrix_SaveFlag);
359b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        concat(matrix);
360b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
361b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restore();
362b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
363b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
364b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
365b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float srcRight, float srcBottom, float dstLeft, float dstTop,
366b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float dstRight, float dstBottom, const SkPaint* paint) {
367b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (srcLeft == 0 && srcTop == 0
368b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && srcRight == bitmap.width()
369b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && srcBottom == bitmap.height()
370b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (srcBottom - srcTop == dstBottom - dstTop)
371b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (srcRight - srcLeft == dstRight - dstLeft)) {
372b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // transform simple rect to rect drawing case into position bitmap ops, since they merge
373b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        save(SkCanvas::kMatrix_SaveFlag);
374b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        translate(dstLeft, dstTop);
375b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
376b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restore();
377b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
378b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        LOG_ALWAYS_FATAL("TODO!");
379b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
380b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
381b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
382b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const float* vertices, const int* colors, const SkPaint* paint) {
383b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
384b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
385b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
386b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float dstLeft, float dstTop, float dstRight, float dstBottom,
387b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkPaint* paint) {
388b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
389b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
390b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
391b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Text
392b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int count,
393b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
394b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float boundsRight, float boundsBottom, float totalAdvance) {
395b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
396b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
397b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPosText(const uint16_t* text, const float* positions, int count,
398b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            int posCount, const SkPaint& paint) {
399b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
400b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
401b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
402b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float hOffset, float vOffset, const SkPaint& paint) {
403b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
404b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
405b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
406b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
407b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) BitmapOp(
408b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(0, 0, bitmap->width(), bitmap->height()),
409b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
410b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
411b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(paint), refBitmap(*bitmap)));
412b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
413b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
414b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    RenderNodeOp* op = new (alloc()) RenderNodeOp(
415b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(0, 0, renderNode->getWidth(), renderNode->getHeight()), // are these safe? they're theoretically dynamic
416b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
417b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
418b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            renderNode);
419b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    int opIndex = addOp(op);
420003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    int childIndex = mDisplayList->addChild(op);
421b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
422b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // update the chunk's child indices
423003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    DisplayList::Chunk& chunk = mDisplayList->chunks.back();
424b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    chunk.endChildIndex = childIndex + 1;
425b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
426b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (renderNode->stagingProperties().isProjectionReceiver()) {
427b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // use staging property, since recording on UI thread
428003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->projectionReceiveIndex = opIndex;
429b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
430b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
431b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
432b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiksize_t RecordingCanvas::addOp(RecordedOp* op) {
433b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
434003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    int insertIndex = mDisplayList->ops.size();
435003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mDisplayList->ops.push_back(op);
436b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (mDeferredBarrierType != kBarrier_None) {
437b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // op is first in new chunk
438003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->chunks.emplace_back();
439003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        DisplayList::Chunk& newChunk = mDisplayList->chunks.back();
440b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.beginOpIndex = insertIndex;
441b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.endOpIndex = insertIndex + 1;
442b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder);
443b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
444b36af87f8275f4b982906f88193ec27600f2746aChris Craik        int nextChildIndex = mDisplayList->children.size();
445b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
446b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        mDeferredBarrierType = kBarrier_None;
447b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
448b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // standard case - append to existing chunk
449003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->chunks.back().endOpIndex = insertIndex + 1;
450b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
451b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return insertIndex;
452b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
453b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
454b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!shader) return;
456b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
457b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // If this paint has an SkShader that has an SkBitmap add
458b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // it to the bitmap pile
459b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkBitmap bitmap;
460b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkShader::TileMode xy[2];
461b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (shader->asABitmap(&bitmap, nullptr, xy) == SkShader::kDefault_BitmapType) {
462b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmap(bitmap);
463b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
464b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
465b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkShader::ComposeRec rec;
466b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (shader->asACompose(&rec)) {
467b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmapsInShader(rec.fShaderA);
468b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmapsInShader(rec.fShaderB);
469b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
470b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
471b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
472b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
473b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace uirenderer
474b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace android
475