RecordingCanvas.cpp revision a1717271caac5e8ea3808c331d4141ac01a42134
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) { 438b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik RenderNodeOp* op = new (alloc()) RenderNodeOp( 439b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik Rect(0, 0, renderNode->getWidth(), renderNode->getHeight()), // are these safe? they're theoretically dynamic 440b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *(mState.currentSnapshot()->transform), 441b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik mState.getRenderTargetClipBounds(), 442b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik renderNode); 443b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik int opIndex = addOp(op); 444003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik int childIndex = mDisplayList->addChild(op); 445b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 446b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // update the chunk's child indices 447003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik DisplayList::Chunk& chunk = mDisplayList->chunks.back(); 448b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik chunk.endChildIndex = childIndex + 1; 449b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 450b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (renderNode->stagingProperties().isProjectionReceiver()) { 451b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // use staging property, since recording on UI thread 452003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->projectionReceiveIndex = opIndex; 453b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 454b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 456b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiksize_t RecordingCanvas::addOp(RecordedOp* op) { 457b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // TODO: validate if "addDrawOp" quickrejection logic is useful before adding 458003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik int insertIndex = mDisplayList->ops.size(); 459003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->ops.push_back(op); 460161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik if (mDeferredBarrierType != DeferredBarrierType::None) { 461b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // op is first in new chunk 462003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->chunks.emplace_back(); 463003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik DisplayList::Chunk& newChunk = mDisplayList->chunks.back(); 464b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik newChunk.beginOpIndex = insertIndex; 465b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik newChunk.endOpIndex = insertIndex + 1; 466161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik newChunk.reorderChildren = (mDeferredBarrierType == DeferredBarrierType::OutOfOrder); 467b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 468b36af87f8275f4b982906f88193ec27600f2746aChris Craik int nextChildIndex = mDisplayList->children.size(); 469b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik newChunk.beginChildIndex = newChunk.endChildIndex = nextChildIndex; 470161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik mDeferredBarrierType = DeferredBarrierType::None; 471b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } else { 472b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // standard case - append to existing chunk 473003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik mDisplayList->chunks.back().endOpIndex = insertIndex + 1; 474b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 475b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return insertIndex; 476b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 477b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 478b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikvoid RecordingCanvas::refBitmapsInShader(const SkShader* shader) { 479b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!shader) return; 480b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 481b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // If this paint has an SkShader that has an SkBitmap add 482b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // it to the bitmap pile 483b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkBitmap bitmap; 484b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkShader::TileMode xy[2]; 485f35b989d26bb98900f6c5fa2e586326b30b6e161Leon Scroggins III if (shader->isABitmap(&bitmap, nullptr, xy)) { 486b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refBitmap(bitmap); 487b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return; 488b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 489b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkShader::ComposeRec rec; 490b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (shader->asACompose(&rec)) { 491b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refBitmapsInShader(rec.fShaderA); 492b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik refBitmapsInShader(rec.fShaderB); 493b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return; 494b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 495b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 496b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 497b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace uirenderer 498b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // namespace android 499