RecordingCanvas.cpp revision 54fa17f667c285a5c9225e238c8132dfe830ef36
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
43161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    mDeferredBarrierType = DeferredBarrierType::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 Craikvoid RecordingCanvas::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {
836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    if (removed.flags & Snapshot::kFlagIsFboLayer) {
846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        addOp(new (alloc()) EndLayerOp());
856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// ----------------------------------------------------------------------------
89b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas state operations
90b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
91b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Save (layer)
92b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint RecordingCanvas::save(SkCanvas::SaveFlags flags) {
93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.save((int) flags);
94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::RecordingCanvas::restore() {
97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (mRestoreSaveCount < 0) {
98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restoreToCount(getSaveCount() - 1);
99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount--;
103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.restore();
104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::restoreToCount(int saveCount) {
107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mRestoreSaveCount = saveCount;
108b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.restoreToCount(saveCount);
109b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
110b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
111b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint RecordingCanvas::saveLayer(float left, float top, float right, float bottom, const SkPaint* paint,
112b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkCanvas::SaveFlags flags) {
1136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    if (!(flags & SkCanvas::kClipToLayer_SaveFlag)) {
1146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        LOG_ALWAYS_FATAL("unclipped layers not supported");
1156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // force matrix/clip isolation for layer
1176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag;
1186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1196fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    const Snapshot& previous = *mState.currentSnapshot();
1216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // initialize the snapshot as though it almost represents an FBO layer so deferred draw
1236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // operations will be able to store and restore the current clip and transform info, and
1246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // quick rejection will be correct (for display lists)
1256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    const Rect untransformedBounds(left, top, right, bottom);
1276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // determine clipped bounds relative to previous viewport.
1296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect visibleBounds = untransformedBounds;
1306fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    previous.transform->mapRect(visibleBounds);
1316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    visibleBounds.doIntersect(previous.getRenderTargetClip());
1346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    visibleBounds.snapToPixelBoundaries();
1356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect previousViewport(0, 0, previous.getViewportWidth(), previous.getViewportHeight());
1376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    visibleBounds.doIntersect(previousViewport);
1386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // Map visible bounds back to layer space, and intersect with parameter bounds
1406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect layerBounds = visibleBounds;
1416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Matrix4 inverse;
1426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    inverse.loadInverse(*previous.transform);
1436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    inverse.mapRect(layerBounds);
1446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    layerBounds.doIntersect(untransformedBounds);
1456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    int saveValue = mState.save((int) flags);
1476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Snapshot& snapshot = *mState.writableSnapshot();
1486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // layerBounds is now original bounds, but with clipped to clip
1506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // and viewport to ensure it's minimal size.
1516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    if (layerBounds.isEmpty() || untransformedBounds.isEmpty()) {
1526fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        // Don't bother recording layer, since it's been rejected
1536fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        snapshot.resetClip(0, 0, 0, 0);
1546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        return saveValue;
1556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    }
1566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.flags |= Snapshot::kFlagFboTarget | Snapshot::kFlagIsFboLayer;
1586fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.initializeViewport(untransformedBounds.getWidth(), untransformedBounds.getHeight());
15998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    snapshot.transform->loadTranslate(-untransformedBounds.left, -untransformedBounds.top, 0.0f);
1606fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    Rect clip = layerBounds;
1626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    clip.translate(-untransformedBounds.left, -untransformedBounds.top);
1636fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom);
1646fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    snapshot.roundRectClipState = nullptr;
1656fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1666fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    addOp(new (alloc()) BeginLayerOp(
1676fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            Rect(left, top, right, bottom),
1686fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            *previous.transform, // transform to *draw* with
1696fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            previous.getRenderTargetClip(), // clip to *draw* with
1706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            refPaint(paint)));
1716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
1726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    return saveValue;
173b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
174b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
175b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Matrix
176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::rotate(float degrees) {
177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (degrees == 0) return;
178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
179b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.rotate(degrees);
180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::scale(float sx, float sy) {
183b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (sx == 1 && sy == 1) return;
184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.scale(sx, sy);
186b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::skew(float sx, float sy) {
189b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.skew(sx, sy);
190b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
191b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
192b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::translate(float dx, float dy) {
193b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (dx == 0 && dy == 0) return;
194b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
195b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    mState.translate(dx, dy, 0);
196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
197b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Clip
199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::getClipBounds(SkRect* outRect) const {
200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Rect bounds = mState.getLocalClipBounds();
201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    *outRect = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom);
202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return !(outRect->isEmpty());
203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.quickRejectConservative(left, top, right, bottom);
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectPath(const SkPath& path) const {
208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkRect bounds = path.getBounds();
209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipRect(left, top, right, bottom, op);
213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipPath(path, op);
216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
218b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return mState.clipRegion(region, op);
219b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
220b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
221b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
222b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas draw operations
223b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ----------------------------------------------------------------------------
224b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) {
225b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkPaint paint;
226b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    paint.setColor(color);
227b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    paint.setXfermodeMode(mode);
228b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    drawPaint(paint);
229b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
230b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
231b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPaint(const SkPaint& paint) {
232b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // TODO: more efficient recording?
233b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) RectOp(
234b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
235a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            Matrix4::identity(),
236b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
237b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(&paint)));
238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
240b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Geometry
241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
242b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
243b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
244a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
245a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikvoid RecordingCanvas::drawLines(const float* points, int floatCount, const SkPaint& paint) {
246a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    if (floatCount < 4) return;
247a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    floatCount &= ~0x3; // round down to nearest four
248a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
249a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    Rect unmappedBounds(points[0], points[1], points[0], points[1]);
250a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    for (int i = 2; i < floatCount; i += 2) {
251a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        unmappedBounds.left = std::min(unmappedBounds.left, points[i]);
252a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        unmappedBounds.right = std::max(unmappedBounds.right, points[i]);
253a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        unmappedBounds.top = std::min(unmappedBounds.top, points[i + 1]);
254a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        unmappedBounds.bottom = std::max(unmappedBounds.bottom, points[i + 1]);
255a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    }
256a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
257a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    // since anything AA stroke with less than 1.0 pixel width is drawn with an alpha-reduced
258a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    // 1.0 stroke, treat 1.0 as minimum.
259a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    unmappedBounds.outset(std::max(paint.getStrokeWidth(), 1.0f) * 0.5f);
260a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
261a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    addOp(new (alloc()) LinesOp(
262a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            unmappedBounds,
263a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            *mState.currentSnapshot()->transform,
264a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            mState.getRenderTargetClipBounds(),
265a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            refPaint(&paint), refBuffer<float>(points, floatCount), floatCount));
266b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
267a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
268b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
269b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) RectOp(
270b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(left, top, right, bottom),
271b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
272b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
273b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(&paint)));
274b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
275b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
276b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) {
277b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (rects == nullptr) return;
278b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
279003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc(vertexCount * sizeof(Vertex));
280b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    Vertex* vertex = rectData;
281b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
282b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float left = FLT_MAX;
283b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float top = FLT_MAX;
284b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float right = FLT_MIN;
285b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    float bottom = FLT_MIN;
286b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    for (int index = 0; index < vertexCount; index += 4) {
287b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float l = rects[index + 0];
288b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float t = rects[index + 1];
289b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float r = rects[index + 2];
290b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        float b = rects[index + 3];
291b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
292b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, l, t);
293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, r, t);
294b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, l, b);
295b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vertex::set(vertex++, r, b);
296b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
297b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        left = std::min(left, l);
298b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        top = std::min(top, t);
299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        right = std::max(right, r);
300b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bottom = std::max(bottom, b);
301b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
302b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) SimpleRectsOp(
303b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(left, top, right, bottom),
304b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
305b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
306b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(paint), rectData, vertexCount));
307b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
308b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
309b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (paint.getStyle() == SkPaint::kFill_Style
311b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) {
312b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        int count = 0;
313b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        Vector<float> rects;
314b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRegion::Iterator it(region);
315b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        while (!it.done()) {
316b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkIRect& r = it.rect();
317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fLeft);
318b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fTop);
319b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fRight);
320b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            rects.push(r.fBottom);
321b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            count += 4;
322b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            it.next();
323b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
324b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawSimpleRects(rects.array(), count, &paint);
325b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
326b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRegion::Iterator it(region);
327b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        while (!it.done()) {
328b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkIRect& r = it.rect();
329b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint);
330b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            it.next();
331b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
332b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
333b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
334b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom,
335b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float rx, float ry, const SkPaint& paint) {
336b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
337b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
338b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
339b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
340b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
341b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
344b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawArc(float left, float top, float right, float bottom,
345b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
346b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
347b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
348b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
349b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
350b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
351b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
352b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Bitmap-based
353b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
354b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    save(SkCanvas::kMatrix_SaveFlag);
355b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    translate(left, top);
356b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    drawBitmap(&bitmap, paint);
357b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    restore();
358b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
359b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
360b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
361b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                            const SkPaint* paint) {
362b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (matrix.isIdentity()) {
363b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
364b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask))
365b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && MathUtils::isPositive(matrix.getScaleX())
366b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && MathUtils::isPositive(matrix.getScaleY())) {
367b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // SkMatrix::isScaleTranslate() not available in L
368b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRect src;
369b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkRect dst;
370b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        bitmap.getBounds(&src);
371b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        matrix.mapRect(&dst, src);
372b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom,
373b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                   dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint);
374b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
375b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        save(SkCanvas::kMatrix_SaveFlag);
376b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        concat(matrix);
377b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
378b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restore();
379b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
380b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
381b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
382b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float srcRight, float srcBottom, float dstLeft, float dstTop,
383b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float dstRight, float dstBottom, const SkPaint* paint) {
384b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (srcLeft == 0 && srcTop == 0
385b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && srcRight == bitmap.width()
386b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && srcBottom == bitmap.height()
387b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (srcBottom - srcTop == dstBottom - dstTop)
388b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            && (srcRight - srcLeft == dstRight - dstLeft)) {
389b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // transform simple rect to rect drawing case into position bitmap ops, since they merge
390b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        save(SkCanvas::kMatrix_SaveFlag);
391b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        translate(dstLeft, dstTop);
392b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        drawBitmap(&bitmap, paint);
393b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        restore();
394b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
395b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        LOG_ALWAYS_FATAL("TODO!");
396b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
397b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
398b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
399b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const float* vertices, const int* colors, const SkPaint* paint) {
400b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
401b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
402b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& chunk,
403b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float dstLeft, float dstTop, float dstRight, float dstBottom,
404b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkPaint* paint) {
405b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
406b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
407b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
408b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Text
409a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikvoid RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int glyphCount,
410b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
411b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float boundsRight, float boundsBottom, float totalAdvance) {
412a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
413a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
414a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    positions = refBuffer<float>(positions, glyphCount * 2);
415a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
416a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    addOp(new (alloc()) TextOp(
417a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            Rect(boundsLeft, boundsTop, boundsRight, boundsBottom),
418a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            *(mState.currentSnapshot()->transform),
419a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            mState.getRenderTargetClipBounds(),
420a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            refPaint(&paint), glyphs, positions, glyphCount, x, y));
421a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    drawTextDecorations(x, y, totalAdvance, paint);
422b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
423a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
424b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
425b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            float hOffset, float vOffset, const SkPaint& paint) {
426a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    // NOTE: can't use refPaint() directly, since it forces left alignment
427b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    LOG_ALWAYS_FATAL("TODO!");
428b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
429b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
430b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) {
431b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    addOp(new (alloc()) BitmapOp(
432b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            Rect(0, 0, bitmap->width(), bitmap->height()),
433b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
434b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
435b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            refPaint(paint), refBitmap(*bitmap)));
436b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
437b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRenderNode(RenderNode* renderNode) {
43854fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik    auto&& stagingProps = renderNode->stagingProperties();
439b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    RenderNodeOp* op = new (alloc()) RenderNodeOp(
44054fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik            Rect(stagingProps.getWidth(), stagingProps.getHeight()),
441b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            *(mState.currentSnapshot()->transform),
442b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            mState.getRenderTargetClipBounds(),
443b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            renderNode);
444b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    int opIndex = addOp(op);
445003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    int childIndex = mDisplayList->addChild(op);
446b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
447b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // update the chunk's child indices
448003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    DisplayList::Chunk& chunk = mDisplayList->chunks.back();
449b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    chunk.endChildIndex = childIndex + 1;
450b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
451b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (renderNode->stagingProperties().isProjectionReceiver()) {
452b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // use staging property, since recording on UI thread
453003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->projectionReceiveIndex = opIndex;
454b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
456b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
457b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiksize_t RecordingCanvas::addOp(RecordedOp* op) {
458b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // TODO: validate if "addDrawOp" quickrejection logic is useful before adding
459003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    int insertIndex = mDisplayList->ops.size();
460003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    mDisplayList->ops.push_back(op);
461161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    if (mDeferredBarrierType != DeferredBarrierType::None) {
462b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // op is first in new chunk
463003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->chunks.emplace_back();
464003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        DisplayList::Chunk& newChunk = mDisplayList->chunks.back();
465b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.beginOpIndex = insertIndex;
466b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.endOpIndex = insertIndex + 1;
467161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        newChunk.reorderChildren = (mDeferredBarrierType == DeferredBarrierType::OutOfOrder);
468b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
469b36af87f8275f4b982906f88193ec27600f2746aChris Craik        int nextChildIndex = mDisplayList->children.size();
470b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex;
471161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        mDeferredBarrierType = DeferredBarrierType::None;
472b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    } else {
473b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // standard case - append to existing chunk
474003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        mDisplayList->chunks.back().endOpIndex = insertIndex + 1;
475b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
476b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    return insertIndex;
477b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
478b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
479b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::refBitmapsInShader(const SkShader* shader) {
480b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (!shader) return;
481b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
482b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // If this paint has an SkShader that has an SkBitmap add
483b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    // it to the bitmap pile
484b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkBitmap bitmap;
485b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkShader::TileMode xy[2];
486f35b989d26bb98900f6c5fa2e586326b30b6e161Leon Scroggins III    if (shader->isABitmap(&bitmap, nullptr, xy)) {
487b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmap(bitmap);
488b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
489b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
490b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    SkShader::ComposeRec rec;
491b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    if (shader->asACompose(&rec)) {
492b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmapsInShader(rec.fShaderA);
493b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        refBitmapsInShader(rec.fShaderB);
494b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return;
495b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
496b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
497b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
498b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace uirenderer
499b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace android
500