Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Side by Side Diff: src/utils/SkCanvasStateUtils.cpp

Issue 396763002: Change SkCanvasState to use inheritance. (Closed) Base URL: https://skia.googlesource.com/skia.git@m37_2062
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « include/utils/SkCanvasStateUtils.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2013 Google Inc. 2 * Copyright 2013 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCanvasStateUtils.h" 8 #include "SkCanvasStateUtils.h"
9 9
10 #include "SkBitmapDevice.h" 10 #include "SkBitmapDevice.h"
11 #include "SkCanvas.h" 11 #include "SkCanvas.h"
12 #include "SkCanvasStack.h" 12 #include "SkCanvasStack.h"
13 #include "SkErrorInternals.h" 13 #include "SkErrorInternals.h"
14 #include "SkWriter32.h" 14 #include "SkWriter32.h"
15 15
16 #define CANVAS_STATE_VERSION 1
17 /* 16 /*
18 * WARNING: The structs below are part of a stable ABI and as such we explicitly 17 * WARNING: The structs below are part of a stable ABI and as such we explicitly
19 * use unambigious primitives (e.g. int32_t instead of an enum). 18 * use unambigious primitives (e.g. int32_t instead of an enum).
20 * 19 *
21 * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN AN 20 * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN A NEW
22 * UPDATE OF THE CANVAS_STATE_VERSION. SUCH CHANGES SHOULD ONLY BE MADE IF 21 * NEW SUBCLASS OF SkCanvasState. SUCH CHANGES SHOULD ONLY BE MADE IF ABSOLUTELY
23 * ABSOLUTELY NECESSARY! 22 * NECESSARY!
24 */ 23 */
25 enum RasterConfigs { 24 enum RasterConfigs {
26 kUnknown_RasterConfig = 0, 25 kUnknown_RasterConfig = 0,
27 kRGB_565_RasterConfig = 1, 26 kRGB_565_RasterConfig = 1,
28 kARGB_8888_RasterConfig = 2 27 kARGB_8888_RasterConfig = 2
29 }; 28 };
30 typedef int32_t RasterConfig; 29 typedef int32_t RasterConfig;
31 30
32 enum CanvasBackends { 31 enum CanvasBackends {
33 kUnknown_CanvasBackend = 0, 32 kUnknown_CanvasBackend = 0,
34 kRaster_CanvasBackend = 1, 33 kRaster_CanvasBackend = 1,
35 kGPU_CanvasBackend = 2, 34 kGPU_CanvasBackend = 2,
36 kPDF_CanvasBackend = 3 35 kPDF_CanvasBackend = 3
37 }; 36 };
38 typedef int32_t CanvasBackend; 37 typedef int32_t CanvasBackend;
39 38
40 struct ClipRect { 39 struct ClipRect {
41 int32_t left, top, right, bottom; 40 int32_t left, top, right, bottom;
42 }; 41 };
43 42
44 struct SkMCState { 43 struct SkMCState {
45 float matrix[9]; 44 float matrix[9];
46 // NOTE: this only works for non-antialiased clips 45 // NOTE: this only works for non-antialiased clips
47 int32_t clipRectCount; 46 int32_t clipRectCount;
48 ClipRect* clipRects; 47 ClipRect* clipRects;
49 }; 48 };
50 49
51 // NOTE: If you add more members, bump CanvasState::version. 50 // NOTE: If you add more members, create a new subclass of SkCanvasState with a
51 // new CanvasState::version.
52 struct SkCanvasLayerState { 52 struct SkCanvasLayerState {
53 CanvasBackend type; 53 CanvasBackend type;
54 int32_t x, y; 54 int32_t x, y;
55 int32_t width; 55 int32_t width;
56 int32_t height; 56 int32_t height;
57 57
58 SkMCState mcState; 58 SkMCState mcState;
59 59
60 union { 60 union {
61 struct { 61 struct {
62 RasterConfig config; // pixel format: a value from RasterConfigs. 62 RasterConfig config; // pixel format: a value from RasterConfigs.
63 size_t rowBytes; // Number of bytes from start of one line to ne xt. 63 uint64_t rowBytes; // Number of bytes from start of one line to ne xt.
64 void* pixels; // The pixels, all (height * rowBytes) of them. 64 void* pixels; // The pixels, all (height * rowBytes) of them.
65 } raster; 65 } raster;
66 struct { 66 struct {
67 int32_t textureID; 67 int32_t textureID;
68 } gpu; 68 } gpu;
69 }; 69 };
70 }; 70 };
71 71
72 class SkCanvasState { 72 class SkCanvasState {
73 public: 73 public:
74 SkCanvasState(SkCanvas* canvas) { 74 SkCanvasState(int32_t version, SkCanvas* canvas) {
75 SkASSERT(canvas); 75 SkASSERT(canvas);
76 version = CANVAS_STATE_VERSION; 76 this->version = version;
77 width = canvas->getDeviceSize().width(); 77 width = canvas->getBaseLayerSize().width();
78 height = canvas->getDeviceSize().height(); 78 height = canvas->getBaseLayerSize().height();
79
80 }
81
82 /**
83 * The version this struct was built with. This field must always appear
84 * first in the struct so that when the versions don't match (and the
85 * remaining contents and size are potentially different) we can still
86 * compare the version numbers.
87 */
88 int32_t version;
89 int32_t width;
90 int32_t height;
91 int32_t alignmentPadding;
92 };
93
94 class SkCanvasState_v1 : public SkCanvasState {
95 public:
96 static const int32_t kVersion = 1;
97
98 SkCanvasState_v1(SkCanvas* canvas)
99 : INHERITED(kVersion, canvas)
100 {
79 layerCount = 0; 101 layerCount = 0;
80 layers = NULL; 102 layers = NULL;
81 originalCanvas = SkRef(canvas);
82
83 mcState.clipRectCount = 0; 103 mcState.clipRectCount = 0;
84 mcState.clipRects = NULL; 104 mcState.clipRects = NULL;
105 originalCanvas = SkRef(canvas);
85 } 106 }
86 107
87 ~SkCanvasState() { 108 ~SkCanvasState_v1() {
88 // loop through the layers and free the data allocated to the clipRects 109 // loop through the layers and free the data allocated to the clipRects
89 for (int i = 0; i < layerCount; ++i) { 110 for (int i = 0; i < layerCount; ++i) {
90 sk_free(layers[i].mcState.clipRects); 111 sk_free(layers[i].mcState.clipRects);
91 } 112 }
92 113
93 sk_free(mcState.clipRects); 114 sk_free(mcState.clipRects);
94 sk_free(layers); 115 sk_free(layers);
95 116
96 // it is now safe to free the canvas since there should be no remaining 117 // it is now safe to free the canvas since there should be no remaining
97 // references to the content that is referenced by this canvas (e.g. pix els) 118 // references to the content that is referenced by this canvas (e.g. pix els)
98 originalCanvas->unref(); 119 originalCanvas->unref();
99 } 120 }
100 121
101 /**
102 * The version this struct was built with. This field must always appear
103 * first in the struct so that when the versions don't match (and the
104 * remaining contents and size are potentially different) we can still
105 * compare the version numbers.
106 */
107 int32_t version;
108
109 int32_t width;
110 int32_t height;
111
112 SkMCState mcState; 122 SkMCState mcState;
113 123
114 int32_t layerCount; 124 int32_t layerCount;
115 SkCanvasLayerState* layers; 125 SkCanvasLayerState* layers;
116
117 private: 126 private:
118 SkCanvas* originalCanvas; 127 SkCanvas* originalCanvas;
128 typedef SkCanvasState INHERITED;
119 }; 129 };
120 130
121 //////////////////////////////////////////////////////////////////////////////// 131 ////////////////////////////////////////////////////////////////////////////////
122 132
123 class ClipValidator : public SkCanvas::ClipVisitor { 133 class ClipValidator : public SkCanvas::ClipVisitor {
124 public: 134 public:
125 ClipValidator() : fFailed(false) {} 135 ClipValidator() : fFailed(false) {}
126 bool failed() { return fFailed; } 136 bool failed() { return fFailed; }
127 137
128 // ClipVisitor 138 // ClipVisitor
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 194
185 // Check the clip can be decomposed into rectangles (i.e. no soft clips). 195 // Check the clip can be decomposed into rectangles (i.e. no soft clips).
186 ClipValidator validator; 196 ClipValidator validator;
187 canvas->replayClips(&validator); 197 canvas->replayClips(&validator);
188 if (validator.failed()) { 198 if (validator.failed()) {
189 SkErrorInternals::SetError(kInvalidOperation_SkError, 199 SkErrorInternals::SetError(kInvalidOperation_SkError,
190 "CaptureCanvasState does not support canvases with antialiased c lips.\n"); 200 "CaptureCanvasState does not support canvases with antialiased c lips.\n");
191 return NULL; 201 return NULL;
192 } 202 }
193 203
194 SkAutoTDelete<SkCanvasState> canvasState(SkNEW_ARGS(SkCanvasState, (canvas)) ); 204 SkAutoTDelete<SkCanvasState_v1> canvasState(SkNEW_ARGS(SkCanvasState_v1, (ca nvas)));
195 205
196 // decompose the total matrix and clip 206 // decompose the total matrix and clip
197 setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(), 207 setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(),
198 canvas->internal_private_getTotalClip()); 208 canvas->internal_private_getTotalClip());
199 209
200 /* 210 /*
201 * decompose the layers 211 * decompose the layers
202 * 212 *
203 * storage is allocated on the stack for the first 3 layers. It is common in 213 * storage is allocated on the stack for the first 3 layers. It is common in
204 * some view systems (e.g. Android) that a few non-clipped layers are presen t 214 * some view systems (e.g. Android) that a few non-clipped layers are presen t
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
240 } 250 }
241 251
242 // allocate memory for the layers and then and copy them to the struct 252 // allocate memory for the layers and then and copy them to the struct
243 SkASSERT(layerWriter.bytesWritten() == layerCount * sizeof(SkCanvasLayerStat e)); 253 SkASSERT(layerWriter.bytesWritten() == layerCount * sizeof(SkCanvasLayerStat e));
244 canvasState->layerCount = layerCount; 254 canvasState->layerCount = layerCount;
245 canvasState->layers = (SkCanvasLayerState*) sk_malloc_throw(layerWriter.byte sWritten()); 255 canvasState->layers = (SkCanvasLayerState*) sk_malloc_throw(layerWriter.byte sWritten());
246 layerWriter.flatten(canvasState->layers); 256 layerWriter.flatten(canvasState->layers);
247 257
248 // for now, just ignore any client supplied DrawFilter. 258 // for now, just ignore any client supplied DrawFilter.
249 if (canvas->getDrawFilter()) { 259 if (canvas->getDrawFilter()) {
250 // SkDEBUGF(("CaptureCanvasState will ignore the canvases draw filter.\n" )); 260 // SkDEBUGF(("CaptureCanvasState will ignore the canvas's draw filter.\n" ));
251 } 261 }
252 262
253 return canvasState.detach(); 263 return canvasState.detach();
254 } 264 }
255 265
256 //////////////////////////////////////////////////////////////////////////////// 266 ////////////////////////////////////////////////////////////////////////////////
257 267
258 static void setup_canvas_from_MC_state(const SkMCState& state, SkCanvas* canvas) { 268 static void setup_canvas_from_MC_state(const SkMCState& state, SkCanvas* canvas) {
259 // reconstruct the matrix 269 // reconstruct the matrix
260 SkMatrix matrix; 270 SkMatrix matrix;
(...skipping 23 matching lines...) Expand all
284 layerState.raster.config == kARGB_8888_RasterConfig ? kN32_SkColorType : 294 layerState.raster.config == kARGB_8888_RasterConfig ? kN32_SkColorType :
285 layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType : 295 layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType :
286 kUnknown_SkColorType; 296 kUnknown_SkColorType;
287 297
288 if (colorType == kUnknown_SkColorType) { 298 if (colorType == kUnknown_SkColorType) {
289 return NULL; 299 return NULL;
290 } 300 }
291 301
292 bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height, 302 bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height,
293 colorType, kPremul_SkAlphaType), 303 colorType, kPremul_SkAlphaType),
294 layerState.raster.pixels, layerState.raster.rowBytes); 304 layerState.raster.pixels, (size_t) layerState.raster.ro wBytes);
295 305
296 SkASSERT(!bitmap.empty()); 306 SkASSERT(!bitmap.empty());
297 SkASSERT(!bitmap.isNull()); 307 SkASSERT(!bitmap.isNull());
298 308
299 SkAutoTUnref<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (bitmap))); 309 SkAutoTUnref<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (bitmap)));
300 310
301 // setup the matrix and clip 311 // setup the matrix and clip
302 setup_canvas_from_MC_state(layerState.mcState, canvas.get()); 312 setup_canvas_from_MC_state(layerState.mcState, canvas.get());
303 313
304 return canvas.detach(); 314 return canvas.detach();
305 } 315 }
306 316
307 SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state) { 317 SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state) {
308 SkASSERT(state); 318 SkASSERT(state);
319 // Currently there is only one possible version.
320 SkASSERT(SkCanvasState_v1::kVersion == state->version);
309 321
310 // check that the versions match 322 const SkCanvasState_v1* state_v1 = static_cast<const SkCanvasState_v1*>(stat e);
311 if (CANVAS_STATE_VERSION != state->version) {
312 SkDebugf("CreateFromCanvasState version does not match the one use to cr eate the input");
313 return NULL;
314 }
315 323
316 if (state->layerCount < 1) { 324 if (state_v1->layerCount < 1) {
317 return NULL; 325 return NULL;
318 } 326 }
319 327
320 SkAutoTUnref<SkCanvasStack> canvas(SkNEW_ARGS(SkCanvasStack, (state->width, state->height))); 328 SkAutoTUnref<SkCanvasStack> canvas(SkNEW_ARGS(SkCanvasStack, (state->width, state->height)));
321 329
322 // setup the matrix and clip on the n-way canvas 330 // setup the matrix and clip on the n-way canvas
323 setup_canvas_from_MC_state(state->mcState, canvas); 331 setup_canvas_from_MC_state(state_v1->mcState, canvas);
324 332
325 // Iterate over the layers and add them to the n-way canvas 333 // Iterate over the layers and add them to the n-way canvas
326 for (int i = state->layerCount - 1; i >= 0; --i) { 334 for (int i = state_v1->layerCount - 1; i >= 0; --i) {
327 SkAutoTUnref<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state ->layers[i])); 335 SkAutoTUnref<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state _v1->layers[i]));
328 if (!canvasLayer.get()) { 336 if (!canvasLayer.get()) {
329 return NULL; 337 return NULL;
330 } 338 }
331 canvas->pushCanvas(canvasLayer.get(), SkIPoint::Make(state->layers[i].x, 339 canvas->pushCanvas(canvasLayer.get(), SkIPoint::Make(state_v1->layers[i] .x,
332 state->layers[i].y) ); 340 state_v1->layers[i] .y));
333 } 341 }
334 342
335 return canvas.detach(); 343 return canvas.detach();
336 } 344 }
337 345
338 //////////////////////////////////////////////////////////////////////////////// 346 ////////////////////////////////////////////////////////////////////////////////
339 347
340 void SkCanvasStateUtils::ReleaseCanvasState(SkCanvasState* state) { 348 void SkCanvasStateUtils::ReleaseCanvasState(SkCanvasState* state) {
341 SkDELETE(state); 349 SkASSERT(!state || SkCanvasState_v1::kVersion == state->version);
350 // Upcast to the correct version of SkCanvasState. This avoids having a virt ual destructor on
351 // SkCanvasState. That would be strange since SkCanvasState has no other vir tual functions, and
352 // instead uses the field "version" to determine how to behave.
353 SkDELETE(static_cast<SkCanvasState_v1*>(state));
342 } 354 }
OLDNEW
« no previous file with comments | « include/utils/SkCanvasStateUtils.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698