RecordingCanvas.cpp revision b87eadda1818034ce03d85f30388384d1ac65916
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 19d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include "DeferredLayerUpdater.h" 20b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RecordedOp.h" 21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include "RenderNode.h" 22b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 25b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikRecordingCanvas::RecordingCanvas(size_t width, size_t height) 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik : mState(*this) 28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik , mResourceCache(ResourceCache::getInstance()) { 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik reset(width, height); 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikRecordingCanvas::~RecordingCanvas() { 33003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik LOG_ALWAYS_FATAL_IF(mDisplayList, 34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "Destroyed a RecordingCanvas during a record!"); 35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::reset(int width, int height) { 38003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik LOG_ALWAYS_FATAL_IF(mDisplayList, 39b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "prepareDirty called a second time during a recording!"); 40003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList = new DisplayList(); 41b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 42e4db79de127cfe961195f52907af8451026eaa20Chris Craik mState.initializeRecordingSaveStack(width, height); 43b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 44161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik mDeferredBarrierType = DeferredBarrierType::InOrder; 45b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.setDirtyClip(false); 46b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 47b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 48003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris CraikDisplayList* RecordingCanvas::finishRecording() { 49b87eadda1818034ce03d85f30388384d1ac65916Chris Craik restoreToCount(1); 50b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mPaintMap.clear(); 51b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mRegionMap.clear(); 52b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mPathMap.clear(); 53003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik DisplayList* displayList = mDisplayList; 54003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList = nullptr; 55b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mSkiaCanvasProxy.reset(nullptr); 56003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik return displayList; 57b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 58b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 59b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris CraikSkCanvas* RecordingCanvas::asSkCanvas() { 60003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik LOG_ALWAYS_FATAL_IF(!mDisplayList, 61b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik "attempting to get an SkCanvas when we are not recording!"); 62b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!mSkiaCanvasProxy) { 63b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mSkiaCanvasProxy.reset(new SkiaCanvasProxy(this)); 64b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 65b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 66b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // SkCanvas instances default to identity transform, but should inherit 67b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // the state of this Canvas; if this code was in the SkiaCanvasProxy 68b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // constructor, we couldn't cache mSkiaCanvasProxy. 69b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkMatrix parentTransform; 70b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik getMatrix(&parentTransform); 71b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mSkiaCanvasProxy.get()->setMatrix(parentTransform); 72b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 73b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return mSkiaCanvasProxy.get(); 74b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 75b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 76b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ---------------------------------------------------------------------------- 776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// CanvasStateClient implementation 786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// ---------------------------------------------------------------------------- 796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikvoid RecordingCanvas::onViewportInitialized() { 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()); 86b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (removed.flags & Snapshot::kFlagIsLayer) { 87b87eadda1818034ce03d85f30388384d1ac65916Chris Craik addOp(new (alloc()) EndUnclippedLayerOp()); 886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 906fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 916fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik// ---------------------------------------------------------------------------- 92b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas state operations 93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ---------------------------------------------------------------------------- 94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Save (layer) 95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikint RecordingCanvas::save(SkCanvas::SaveFlags flags) { 96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return mState.save((int) flags); 97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::RecordingCanvas::restore() { 100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.restore(); 101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::restoreToCount(int saveCount) { 104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.restoreToCount(saveCount); 105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 107b87eadda1818034ce03d85f30388384d1ac65916Chris Craikint RecordingCanvas::saveLayer(float left, float top, float right, float bottom, 108b87eadda1818034ce03d85f30388384d1ac65916Chris Craik const SkPaint* paint, SkCanvas::SaveFlags flags) { 1096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // force matrix/clip isolation for layer 1106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik flags |= SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag; 111b87eadda1818034ce03d85f30388384d1ac65916Chris Craik bool clippedLayer = flags & SkCanvas::kClipToLayer_SaveFlag; 1126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik const Snapshot& previous = *mState.currentSnapshot(); 1146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // initialize the snapshot as though it almost represents an FBO layer so deferred draw 1166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // operations will be able to store and restore the current clip and transform info, and 1176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // quick rejection will be correct (for display lists) 1186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 119b87eadda1818034ce03d85f30388384d1ac65916Chris Craik const Rect unmappedBounds(left, top, right, bottom); 1206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // determine clipped bounds relative to previous viewport. 122b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Rect visibleBounds = unmappedBounds; 1236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik previous.transform->mapRect(visibleBounds); 1246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 125b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (CC_UNLIKELY(!clippedLayer 126b87eadda1818034ce03d85f30388384d1ac65916Chris Craik && previous.transform->rectToRect() 127b87eadda1818034ce03d85f30388384d1ac65916Chris Craik && visibleBounds.contains(previous.getRenderTargetClip()))) { 128b87eadda1818034ce03d85f30388384d1ac65916Chris Craik // unlikely case where an unclipped savelayer is recorded with a clip it can use, 129b87eadda1818034ce03d85f30388384d1ac65916Chris Craik // as none of its unaffected/unclipped area is visible 130b87eadda1818034ce03d85f30388384d1ac65916Chris Craik clippedLayer = true; 131b87eadda1818034ce03d85f30388384d1ac65916Chris Craik flags |= SkCanvas::kClipToLayer_SaveFlag; 132b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik visibleBounds.doIntersect(previous.getRenderTargetClip()); 1356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik visibleBounds.snapToPixelBoundaries(); 136b87eadda1818034ce03d85f30388384d1ac65916Chris Craik visibleBounds.doIntersect(Rect(previous.getViewportWidth(), previous.getViewportHeight())); 1376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // Map visible bounds back to layer space, and intersect with parameter bounds 1396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik Rect layerBounds = visibleBounds; 1406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik Matrix4 inverse; 1416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik inverse.loadInverse(*previous.transform); 1426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik inverse.mapRect(layerBounds); 143b87eadda1818034ce03d85f30388384d1ac65916Chris Craik layerBounds.doIntersect(unmappedBounds); 1446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik int saveValue = mState.save((int) flags); 1466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik Snapshot& snapshot = *mState.writableSnapshot(); 1476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 148b87eadda1818034ce03d85f30388384d1ac65916Chris Craik // layerBounds is in original bounds space, but clipped by current recording clip 149b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (layerBounds.isEmpty() || unmappedBounds.isEmpty()) { 1506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // Don't bother recording layer, since it's been rejected 151b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (CC_LIKELY(clippedLayer)) { 152b87eadda1818034ce03d85f30388384d1ac65916Chris Craik snapshot.resetClip(0, 0, 0, 0); 153b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik return saveValue; 1556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 1566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 157b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (CC_LIKELY(clippedLayer)) { 158b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto previousClip = getRecordedClip(); // note: done before new snapshot's clip has changed 159b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 160b87eadda1818034ce03d85f30388384d1ac65916Chris Craik snapshot.flags |= Snapshot::kFlagIsLayer | Snapshot::kFlagIsFboLayer; 161b87eadda1818034ce03d85f30388384d1ac65916Chris Craik snapshot.initializeViewport(unmappedBounds.getWidth(), unmappedBounds.getHeight()); 162b87eadda1818034ce03d85f30388384d1ac65916Chris Craik snapshot.transform->loadTranslate(-unmappedBounds.left, -unmappedBounds.top, 0.0f); 163b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 164b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Rect clip = layerBounds; 165b87eadda1818034ce03d85f30388384d1ac65916Chris Craik clip.translate(-unmappedBounds.left, -unmappedBounds.top); 166b87eadda1818034ce03d85f30388384d1ac65916Chris Craik snapshot.resetClip(clip.left, clip.top, clip.right, clip.bottom); 167b87eadda1818034ce03d85f30388384d1ac65916Chris Craik snapshot.roundRectClipState = nullptr; 168b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 169b87eadda1818034ce03d85f30388384d1ac65916Chris Craik addOp(new (alloc()) BeginLayerOp( 170b87eadda1818034ce03d85f30388384d1ac65916Chris Craik unmappedBounds, 171b87eadda1818034ce03d85f30388384d1ac65916Chris Craik *previous.transform, // transform to *draw* with 172b87eadda1818034ce03d85f30388384d1ac65916Chris Craik previousClip, // clip to *draw* with 173b87eadda1818034ce03d85f30388384d1ac65916Chris Craik refPaint(paint))); 174b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else { 175b87eadda1818034ce03d85f30388384d1ac65916Chris Craik snapshot.flags |= Snapshot::kFlagIsLayer; 176b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 177b87eadda1818034ce03d85f30388384d1ac65916Chris Craik addOp(new (alloc()) BeginUnclippedLayerOp( 178b87eadda1818034ce03d85f30388384d1ac65916Chris Craik unmappedBounds, 179b87eadda1818034ce03d85f30388384d1ac65916Chris Craik *mState.currentSnapshot()->transform, 180b87eadda1818034ce03d85f30388384d1ac65916Chris Craik getRecordedClip(), 181b87eadda1818034ce03d85f30388384d1ac65916Chris Craik refPaint(paint))); 182b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik return saveValue; 185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 186b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Matrix 188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::rotate(float degrees) { 189b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (degrees == 0) return; 190b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 191b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.rotate(degrees); 192b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 193b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 194b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::scale(float sx, float sy) { 195b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (sx == 1 && sy == 1) return; 196b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 197b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.scale(sx, sy); 198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::skew(float sx, float sy) { 201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.skew(sx, sy); 202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::translate(float dx, float dy) { 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (dx == 0 && dy == 0) return; 206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.translate(dx, dy, 0); 208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Clip 211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::getClipBounds(SkRect* outRect) const { 212e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik *outRect = mState.getLocalClipBounds().toSkRect(); 213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return !(outRect->isEmpty()); 214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectRect(float left, float top, float right, float bottom) const { 216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return mState.quickRejectConservative(left, top, right, bottom); 217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 218b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::quickRejectPath(const SkPath& path) const { 219b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkRect bounds = path.getBounds(); 220b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return mState.quickRejectConservative(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); 221b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 222b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) { 223b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return mState.clipRect(left, top, right, bottom, op); 224b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 225b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipPath(const SkPath* path, SkRegion::Op op) { 226b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return mState.clipPath(path, op); 227b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 228b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikbool RecordingCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) { 229b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return mState.clipRegion(region, op); 230b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 231b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 232b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ---------------------------------------------------------------------------- 233b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// android/graphics/Canvas draw operations 234b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// ---------------------------------------------------------------------------- 235b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawColor(int color, SkXfermode::Mode mode) { 236b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 237b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(color); 238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setXfermodeMode(mode); 239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawPaint(paint); 240b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 242b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPaint(const SkPaint& paint) { 243b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik addOp(new (alloc()) RectOp( 244e4db79de127cfe961195f52907af8451026eaa20Chris Craik mState.getRenderTargetClipBounds(), // OK, since we've not passed transform 245a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik Matrix4::identity(), 246e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 247b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refPaint(&paint))); 248b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 249b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 250386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craikstatic Rect calcBoundsOfPoints(const float* points, int floatCount) { 251386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Rect unmappedBounds(points[0], points[1], points[0], points[1]); 252386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik for (int i = 2; i < floatCount; i += 2) { 253386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik unmappedBounds.expandToCover(points[i], points[i + 1]); 254386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 255386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik return unmappedBounds; 256386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 257386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Geometry 259386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craikvoid RecordingCanvas::drawPoints(const float* points, int floatCount, const SkPaint& paint) { 260386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (floatCount < 2) return; 261386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik floatCount &= ~0x1; // round down to nearest two 262386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 263386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik addOp(new (alloc()) PointsOp( 264386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik calcBoundsOfPoints(points, floatCount), 265386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik *mState.currentSnapshot()->transform, 266e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 267386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik refPaint(&paint), refBuffer<float>(points, floatCount), floatCount)); 268b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 269a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 270a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikvoid RecordingCanvas::drawLines(const float* points, int floatCount, const SkPaint& paint) { 271a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik if (floatCount < 4) return; 272a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik floatCount &= ~0x3; // round down to nearest four 273a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 274a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik addOp(new (alloc()) LinesOp( 275386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik calcBoundsOfPoints(points, floatCount), 276a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik *mState.currentSnapshot()->transform, 277e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 278a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik refPaint(&paint), refBuffer<float>(points, floatCount), floatCount)); 279b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 280a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 281b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) { 282b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik addOp(new (alloc()) RectOp( 283b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Rect(left, top, right, bottom), 284b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *(mState.currentSnapshot()->transform), 285e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 286b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refPaint(&paint))); 287b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 288b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 289b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawSimpleRects(const float* rects, int vertexCount, const SkPaint* paint) { 290b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (rects == nullptr) return; 291b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 292003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik Vertex* rectData = (Vertex*) mDisplayList->allocator.alloc(vertexCount * sizeof(Vertex)); 293b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Vertex* vertex = rectData; 294b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 295b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float left = FLT_MAX; 296b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float top = FLT_MAX; 297b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float right = FLT_MIN; 298b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float bottom = FLT_MIN; 299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik for (int index = 0; index < vertexCount; index += 4) { 300b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float l = rects[index + 0]; 301b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float t = rects[index + 1]; 302b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float r = rects[index + 2]; 303b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float b = rects[index + 3]; 304b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 305b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Vertex::set(vertex++, l, t); 306b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Vertex::set(vertex++, r, t); 307b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Vertex::set(vertex++, l, b); 308b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Vertex::set(vertex++, r, b); 309b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik left = std::min(left, l); 311b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik top = std::min(top, t); 312b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik right = std::max(right, r); 313b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bottom = std::max(bottom, b); 314b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 315b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik addOp(new (alloc()) SimpleRectsOp( 316b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Rect(left, top, right, bottom), 317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *(mState.currentSnapshot()->transform), 318e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 319b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refPaint(paint), rectData, vertexCount)); 320b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 321b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 322b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) { 323b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (paint.getStyle() == SkPaint::kFill_Style 324b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && (!paint.isAntiAlias() || mState.currentTransform()->isSimple())) { 325b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik int count = 0; 326b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Vector<float> rects; 327b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkRegion::Iterator it(region); 328b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik while (!it.done()) { 329b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const SkIRect& r = it.rect(); 330b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik rects.push(r.fLeft); 331b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik rects.push(r.fTop); 332b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik rects.push(r.fRight); 333b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik rects.push(r.fBottom); 334b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik count += 4; 335b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik it.next(); 336b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 337b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawSimpleRects(rects.array(), count, &paint); 338b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else { 339b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkRegion::Iterator it(region); 340b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik while (!it.done()) { 341b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const SkIRect& r = it.rect(); 342b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint); 343b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik it.next(); 344b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 345b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 346b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 347b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRoundRect(float left, float top, float right, float bottom, 348b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float rx, float ry, const SkPaint& paint) { 349386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik addOp(new (alloc()) RoundRectOp( 350386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Rect(left, top, right, bottom), 351386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik *(mState.currentSnapshot()->transform), 352e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 353386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik refPaint(&paint), rx, ry)); 354b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 355386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 356268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craikvoid RecordingCanvas::drawRoundRect( 357268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik CanvasPropertyPrimitive* left, CanvasPropertyPrimitive* top, 358268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom, 359268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry, 360268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik CanvasPropertyPaint* paint) { 361268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(left); 362268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(top); 363268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(right); 364268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(bottom); 365268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(rx); 366268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(ry); 367268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(paint); 368268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik refBitmapsInShader(paint->value.getShader()); 369268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik addOp(new (alloc()) RoundRectPropsOp( 370268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik *(mState.currentSnapshot()->transform), 371e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 372268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik &paint->value, 373268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik &left->value, &top->value, &right->value, &bottom->value, 374268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik &rx->value, &ry->value)); 375268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik} 376268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik 377b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) { 378268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik // TODO: move to Canvas.h 379386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik if (radius <= 0) return; 380386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik drawOval(x - radius, y - radius, x + radius, y + radius, paint); 381b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 382386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 383268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craikvoid RecordingCanvas::drawCircle( 384268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y, 385268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) { 386268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(x); 387268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(y); 388268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(radius); 389268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik mDisplayList->ref(paint); 390268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik refBitmapsInShader(paint->value.getShader()); 391268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik addOp(new (alloc()) CirclePropsOp( 392268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik *(mState.currentSnapshot()->transform), 393e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 394268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik &paint->value, 395268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik &x->value, &y->value, &radius->value)); 396268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik} 397268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik 398268a9c0f29c16a64d5819c7dbe8b0633baedab83Chris Craik 399b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) { 400386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik addOp(new (alloc()) OvalOp( 401386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Rect(left, top, right, bottom), 402386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik *(mState.currentSnapshot()->transform), 403e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 404386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik refPaint(&paint))); 405b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 406386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 407b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawArc(float left, float top, float right, float bottom, 408386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) { 409386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik addOp(new (alloc()) ArcOp( 410386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Rect(left, top, right, bottom), 411386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik *(mState.currentSnapshot()->transform), 412e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 413386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik refPaint(&paint), 414386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik startAngle, sweepAngle, useCenter)); 415b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 416386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 417b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawPath(const SkPath& path, const SkPaint& paint) { 418386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik addOp(new (alloc()) PathOp( 419386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik Rect(path.getBounds()), 420386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik *(mState.currentSnapshot()->transform), 421e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 422386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik refPaint(&paint), refPath(&path))); 423b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 424b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 425b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Bitmap-based 426b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) { 427b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik save(SkCanvas::kMatrix_SaveFlag); 428b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik translate(left, top); 429b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawBitmap(&bitmap, paint); 430b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik restore(); 431b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 432b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 433b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, 434b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const SkPaint* paint) { 435b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (matrix.isIdentity()) { 436b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawBitmap(&bitmap, paint); 437b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else if (!(matrix.getType() & ~(SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)) 438b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && MathUtils::isPositive(matrix.getScaleX()) 439b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && MathUtils::isPositive(matrix.getScaleY())) { 440b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // SkMatrix::isScaleTranslate() not available in L 441b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkRect src; 442b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkRect dst; 443b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik bitmap.getBounds(&src); 444b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik matrix.mapRect(&dst, src); 445b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawBitmap(bitmap, src.fLeft, src.fTop, src.fRight, src.fBottom, 446b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, paint); 447b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else { 448b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik save(SkCanvas::kMatrix_SaveFlag); 449b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik concat(matrix); 450b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawBitmap(&bitmap, paint); 451b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik restore(); 452b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 453b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 454386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop, 456b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float srcRight, float srcBottom, float dstLeft, float dstTop, 457b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float dstRight, float dstBottom, const SkPaint* paint) { 458b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (srcLeft == 0 && srcTop == 0 459b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && srcRight == bitmap.width() 460b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && srcBottom == bitmap.height() 461b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && (srcBottom - srcTop == dstBottom - dstTop) 462b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik && (srcRight - srcLeft == dstRight - dstLeft)) { 463b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // transform simple rect to rect drawing case into position bitmap ops, since they merge 464b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik save(SkCanvas::kMatrix_SaveFlag); 465b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik translate(dstLeft, dstTop); 466b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik drawBitmap(&bitmap, paint); 467b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik restore(); 468b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else { 469f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik addOp(new (alloc()) BitmapRectOp( 470f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik Rect(dstLeft, dstTop, dstRight, dstBottom), 471f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik *(mState.currentSnapshot()->transform), 472e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 473f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik refPaint(paint), refBitmap(bitmap), 474f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik Rect(srcLeft, srcTop, srcRight, srcBottom))); 475b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 476b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 477386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 478b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight, 479b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const float* vertices, const int* colors, const SkPaint* paint) { 480f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik int vertexCount = (meshWidth + 1) * (meshHeight + 1); 481f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik addOp(new (alloc()) BitmapMeshOp( 482f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik calcBoundsOfPoints(vertices, vertexCount * 2), 483f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik *(mState.currentSnapshot()->transform), 484e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 485f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik refPaint(paint), refBitmap(bitmap), meshWidth, meshHeight, 486f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik refBuffer<float>(vertices, vertexCount * 2), // 2 floats per vertex 487f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik refBuffer<int>(colors, vertexCount))); // 1 color per vertex 488b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 489386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 490f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craikvoid RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_png_9patch& patch, 491b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float dstLeft, float dstTop, float dstRight, float dstBottom, 492b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const SkPaint* paint) { 493f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik addOp(new (alloc()) PatchOp( 494f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik Rect(dstLeft, dstTop, dstRight, dstBottom), 495f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik *(mState.currentSnapshot()->transform), 496e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 497f09ff5aa57bff01cb17595fb7ca8e48d238a6acdChris Craik refPaint(paint), refBitmap(bitmap), refPatch(&patch))); 498b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 499b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 500b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik// Text 501a1717271caac5e8ea3808c331d4141ac01a42134Chris Craikvoid RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int glyphCount, 502b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop, 503b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float boundsRight, float boundsBottom, float totalAdvance) { 504a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return; 505a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik glyphs = refBuffer<glyph_t>(glyphs, glyphCount); 506a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik positions = refBuffer<float>(positions, glyphCount * 2); 507a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 50815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // TODO: either must account for text shadow in bounds, or record separate ops for text shadows 509a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik addOp(new (alloc()) TextOp( 510a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik Rect(boundsLeft, boundsTop, boundsRight, boundsBottom), 511a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik *(mState.currentSnapshot()->transform), 512e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 513a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik refPaint(&paint), glyphs, positions, glyphCount, x, y)); 514a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik drawTextDecorations(x, y, totalAdvance, paint); 515b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 516a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 517d7448e65e243754f31890baef29dff187dc2e5e5Chris Craikvoid RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path, 518b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik float hOffset, float vOffset, const SkPaint& paint) { 519d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return; 520d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik glyphs = refBuffer<glyph_t>(glyphs, glyphCount); 521d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik addOp(new (alloc()) TextOnPathOp( 522e4db79de127cfe961195f52907af8451026eaa20Chris Craik mState.getLocalClipBounds(), // TODO: explicitly define bounds 523d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik *(mState.currentSnapshot()->transform), 524e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 525d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik refPaint(&paint), glyphs, glyphCount, refPath(&path), hOffset, vOffset)); 526b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 527b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 528b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { 529b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik addOp(new (alloc()) BitmapOp( 5305430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik Rect(bitmap->width(), bitmap->height()), 531b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *(mState.currentSnapshot()->transform), 532e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 533b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refPaint(paint), refBitmap(*bitmap))); 534b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 535e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik 536b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::drawRenderNode(RenderNode* renderNode) { 53754fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik auto&& stagingProps = renderNode->stagingProperties(); 538b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik RenderNodeOp* op = new (alloc()) RenderNodeOp( 53954fa17f667c285a5c9225e238c8132dfe830ef36Chris Craik Rect(stagingProps.getWidth(), stagingProps.getHeight()), 540b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *(mState.currentSnapshot()->transform), 541e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 542b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik renderNode); 543b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik int opIndex = addOp(op); 544003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik int childIndex = mDisplayList->addChild(op); 545b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 546b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // update the chunk's child indices 547003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik DisplayList::Chunk& chunk = mDisplayList->chunks.back(); 548b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik chunk.endChildIndex = childIndex + 1; 549b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 550b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (renderNode->stagingProperties().isProjectionReceiver()) { 551b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // use staging property, since recording on UI thread 552003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->projectionReceiveIndex = opIndex; 553b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 554b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 555b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 556d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craikvoid RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) { 557d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik // We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics. 558d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik mDisplayList->ref(layerHandle); 559d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 560d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Layer* layer = layerHandle->backingLayer(); 561d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 totalTransform(*(mState.currentSnapshot()->transform)); 562d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik totalTransform.multiply(layer->getTransform()); 563d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 564d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik addOp(new (alloc()) TextureLayerOp( 565d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Rect(layer->getWidth(), layer->getHeight()), 566d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik totalTransform, 567e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 568d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik layer)); 569d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 570d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 571e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craikvoid RecordingCanvas::callDrawGLFunction(Functor* functor) { 572e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik mDisplayList->functors.push_back(functor); 573e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik addOp(new (alloc()) FunctorOp( 574e4db79de127cfe961195f52907af8451026eaa20Chris Craik mState.getLocalClipBounds(), // TODO: explicitly define bounds 575e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik *(mState.currentSnapshot()->transform), 576e4db79de127cfe961195f52907af8451026eaa20Chris Craik getRecordedClip(), 577e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik functor)); 578e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik} 579e29ce6f51d681af7649c0a7cddee97c471e43eb5Chris Craik 580b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiksize_t RecordingCanvas::addOp(RecordedOp* op) { 581b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // TODO: validate if "addDrawOp" quickrejection logic is useful before adding 582003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik int insertIndex = mDisplayList->ops.size(); 583003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->ops.push_back(op); 584161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik if (mDeferredBarrierType != DeferredBarrierType::None) { 585b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // op is first in new chunk 586003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->chunks.emplace_back(); 587003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik DisplayList::Chunk& newChunk = mDisplayList->chunks.back(); 588b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik newChunk.beginOpIndex = insertIndex; 589b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik newChunk.endOpIndex = insertIndex + 1; 590161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik newChunk.reorderChildren = (mDeferredBarrierType == DeferredBarrierType::OutOfOrder); 591b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 592b36af87f8275f4b982906f88193ec27600f2746aChris Craik int nextChildIndex = mDisplayList->children.size(); 593b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex; 594161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik mDeferredBarrierType = DeferredBarrierType::None; 595b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else { 596b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // standard case - append to existing chunk 597003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->chunks.back().endOpIndex = insertIndex + 1; 598b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 599b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return insertIndex; 600b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 601b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 602b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::refBitmapsInShader(const SkShader* shader) { 603b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!shader) return; 604b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 605b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // If this paint has an SkShader that has an SkBitmap add 606b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // it to the bitmap pile 607b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkBitmap bitmap; 608b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkShader::TileMode xy[2]; 609f35b989d26bb98900f6c5fa2e586326b30b6e161Leon Scroggins III if (shader->isABitmap(&bitmap, nullptr, xy)) { 610b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refBitmap(bitmap); 611b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return; 612b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 613b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkShader::ComposeRec rec; 614b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (shader->asACompose(&rec)) { 615b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refBitmapsInShader(rec.fShaderA); 616b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refBitmapsInShader(rec.fShaderB); 617b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return; 618b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 619b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 620b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 621b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace uirenderer 622b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace android 623