Flutter Engine
The Flutter Engine
Static Public Member Functions | List of all members
SkCanvasStateUtils Class Reference

#include <SkCanvasStateUtils.h>

Static Public Member Functions

static SkCanvasStateCaptureCanvasState (SkCanvas *canvas)
 
static std::unique_ptr< SkCanvasMakeFromCanvasState (const SkCanvasState *state)
 
static void ReleaseCanvasState (SkCanvasState *state)
 

Detailed Description

A set of functions that are useful for copying the state of an SkCanvas across a library boundary where the Skia library on the other side of the boundary may be newer. The expected usage is outline below...

                     Lib Boundary

CaptureCanvasState(...) ||| SkCanvas --> SkCanvasState ||| ||| CreateFromCanvasState(...) ||| SkCanvasState --> SkCanvas ||| Draw into SkCanvas ||| Unref SkCanvas` ReleaseCanvasState(...) |||

Definition at line 33 of file SkCanvasStateUtils.h.

Member Function Documentation

◆ CaptureCanvasState()

SkCanvasState * SkCanvasStateUtils::CaptureCanvasState ( SkCanvas canvas)
static

Captures the current state of the canvas into an opaque ptr that is safe to pass to a different instance of Skia (which may be the same version, or may be newer). The function will return NULL in the event that one of the following conditions are true. 1) the canvas device type is not supported (currently only raster is supported) 2) the canvas clip type is not supported (currently only non-AA clips are supported)

It is recommended that the original canvas also not be used until all canvases that have been created using its captured state have been dereferenced.

Finally, it is important to note that any draw filters attached to the canvas are NOT currently captured.

Parameters
canvasThe canvas you wish to capture the current state of.
Returns
NULL or an opaque ptr that can be passed to CreateFromCanvasState to reconstruct the canvas. The caller is responsible for calling ReleaseCanvasState to free the memory associated with this state.

Definition at line 178 of file SkCanvasStateUtils.cpp.

178 {
179 SkASSERT(canvas);
180
181 // Check the clip can be decomposed into rectangles (i.e. no soft clips).
182 if (canvas->androidFramework_isClipAA()) {
183 return nullptr;
184 }
185
186 std::unique_ptr<SkCanvasState_v1> canvasState(new SkCanvasState_v1(canvas));
187
188 setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(), canvas->getDeviceClipBounds());
189
190 // Historically, the canvas state could report multiple top-level layers because SkCanvas
191 // supported unclipped layers. With that feature removed, all required information is contained
192 // by the canvas' top-most device.
193 SkDevice* device = canvas->topDevice();
195
196 SkSWriter32<sizeof(SkCanvasLayerState)> layerWriter;
197 // we currently only work for bitmap backed devices
198 SkPixmap pmap;
199 if (!device->accessPixels(&pmap) || 0 == pmap.width() || 0 == pmap.height()) {
200 return nullptr;
201 }
202 // and for axis-aligned devices (so not transformed for an image filter)
203 if (!device->isPixelAlignedToGlobal()) {
204 return nullptr;
205 }
206
207 SkIPoint origin = device->getOrigin(); // safe since it's pixel aligned
208
209 SkCanvasLayerState* layerState =
210 (SkCanvasLayerState*) layerWriter.reserve(sizeof(SkCanvasLayerState));
211 layerState->type = kRaster_CanvasBackend;
212 layerState->x = origin.x();
213 layerState->y = origin.y();
214 layerState->width = pmap.width();
215 layerState->height = pmap.height();
216
217 switch (pmap.colorType()) {
218 case kN32_SkColorType:
220 break;
222 layerState->raster.config = kRGB_565_RasterConfig;
223 break;
224 default:
225 return nullptr;
226 }
227 layerState->raster.rowBytes = pmap.rowBytes();
228 layerState->raster.pixels = pmap.writable_addr();
229
230 setup_MC_state(&layerState->mcState, device->localToDevice(), device->devClipBounds());
231
232 // allocate memory for the layers and then and copy them to the struct
233 SkASSERT(layerWriter.bytesWritten() == sizeof(SkCanvasLayerState));
234 canvasState->layerCount = 1;
235 canvasState->layers = (SkCanvasLayerState*) sk_malloc_throw(layerWriter.bytesWritten());
236 layerWriter.flatten(canvasState->layers);
237
238 return canvasState.release();
239}
#define SkASSERT(cond)
Definition: SkAssert.h:116
@ kRaster_CanvasBackend
@ kARGB_8888_RasterConfig
@ kRGB_565_RasterConfig
static void setup_MC_state(SkMCState *state, const SkMatrix &matrix, const SkIRect &clip)
@ kRGB_565_SkColorType
pixel with 5 bits red, 6 bits green, 5 bits blue, in 16-bit word
Definition: SkColorType.h:22
static void * sk_malloc_throw(size_t size)
Definition: SkMalloc.h:67
SkMatrix getTotalMatrix() const
Definition: SkCanvas.cpp:1629
SkIRect getDeviceClipBounds() const
Definition: SkCanvas.cpp:1607
VkDevice device
Definition: main.cc:53
struct SkCanvasLayerState::@423::@425 raster
constexpr int32_t y() const
Definition: SkPoint_impl.h:52
constexpr int32_t x() const
Definition: SkPoint_impl.h:46

◆ MakeFromCanvasState()

std::unique_ptr< SkCanvas > SkCanvasStateUtils::MakeFromCanvasState ( const SkCanvasState state)
static

Create a new SkCanvas from the captured state of another SkCanvas. The function will return NULL in the event that one of the following conditions are true. 1) the captured state is in an unrecognized format 2) the captured canvas device type is not supported

Parameters
stateOpaque object created by CaptureCanvasState.
Returns
NULL or an SkCanvas* whose devices and matrix/clip state are identical to the captured canvas. The caller is responsible for calling unref on the SkCanvas.

Definition at line 299 of file SkCanvasStateUtils.cpp.

299 {
301 // Currently there is only one possible version.
303
304 const SkCanvasState_v1* state_v1 = static_cast<const SkCanvasState_v1*>(state);
305
306 if (state_v1->layerCount < 1) {
307 return nullptr;
308 }
309
310 std::unique_ptr<SkCanvasStack> canvas(new SkCanvasStack(state->width, state->height));
311
312 // setup the matrix and clip on the n-way canvas
313 setup_canvas_from_MC_state(state_v1->mcState, canvas.get());
314
315 // Iterate over the layers and add them to the n-way canvas. New clients will only send one
316 // layer since unclipped layers are no longer supported, but old canvas clients may still
317 // create them.
318 for (int i = state_v1->layerCount - 1; i >= 0; --i) {
319 std::unique_ptr<SkCanvas> canvasLayer = make_canvas_from_canvas_layer(state_v1->layers[i]);
320 if (!canvasLayer) {
321 return nullptr;
322 }
323 canvas->pushCanvas(std::move(canvasLayer), SkIPoint::Make(state_v1->layers[i].x,
324 state_v1->layers[i].y));
325 }
326
327 return canvas;
328}
static std::unique_ptr< SkCanvas > make_canvas_from_canvas_layer(const SkCanvasLayerState &layerState)
static void setup_canvas_from_MC_state(const SkMCState &state, SkCanvas *canvas)
static const int32_t kVersion
SkCanvasLayerState * layers
AtkStateType state
static constexpr SkIPoint Make(int32_t x, int32_t y)
Definition: SkPoint_impl.h:38

◆ ReleaseCanvasState()

void SkCanvasStateUtils::ReleaseCanvasState ( SkCanvasState state)
static

Free the memory associated with the captured canvas state. The state should not be released until all SkCanvas objects created using that state have been dereferenced. Must be called from the same library instance that created the state via CaptureCanvasState.

Parameters
stateThe captured state you wish to dispose of.

Definition at line 332 of file SkCanvasStateUtils.cpp.

332 {
334 // Upcast to the correct version of SkCanvasState. This avoids having a virtual destructor on
335 // SkCanvasState. That would be strange since SkCanvasState has no other virtual functions, and
336 // instead uses the field "version" to determine how to behave.
337 delete static_cast<SkCanvasState_v1*>(state);
338}

The documentation for this class was generated from the following files: