Index: src/utils/SkCanvasStateUtils.cpp |
diff --git a/src/utils/SkCanvasStateUtils.cpp b/src/utils/SkCanvasStateUtils.cpp |
index eaee61b5e829a6534c87f0180b7f4c1856e7a7b0..e286c9138fd0c07d868d41c9da7fa28dd0db318f 100644 |
--- a/src/utils/SkCanvasStateUtils.cpp |
+++ b/src/utils/SkCanvasStateUtils.cpp |
@@ -13,14 +13,13 @@ |
#include "SkErrorInternals.h" |
#include "SkWriter32.h" |
-#define CANVAS_STATE_VERSION 1 |
/* |
* WARNING: The structs below are part of a stable ABI and as such we explicitly |
* use unambigious primitives (e.g. int32_t instead of an enum). |
* |
- * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN AN |
- * UPDATE OF THE CANVAS_STATE_VERSION. SUCH CHANGES SHOULD ONLY BE MADE IF |
- * ABSOLUTELY NECESSARY! |
+ * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN A NEW |
+ * NEW SUBCLASS OF SkCanvasState. SUCH CHANGES SHOULD ONLY BE MADE IF ABSOLUTELY |
+ * NECESSARY! |
*/ |
enum RasterConfigs { |
kUnknown_RasterConfig = 0, |
@@ -48,7 +47,8 @@ struct SkMCState { |
ClipRect* clipRects; |
}; |
-// NOTE: If you add more members, bump CanvasState::version. |
+// NOTE: If you add more members, create a new subclass of SkCanvasState with a |
+// new CanvasState::version. |
struct SkCanvasLayerState { |
CanvasBackend type; |
int32_t x, y; |
@@ -60,7 +60,7 @@ struct SkCanvasLayerState { |
union { |
struct { |
RasterConfig config; // pixel format: a value from RasterConfigs. |
- size_t rowBytes; // Number of bytes from start of one line to next. |
+ uint64_t rowBytes; // Number of bytes from start of one line to next. |
void* pixels; // The pixels, all (height * rowBytes) of them. |
} raster; |
struct { |
@@ -71,20 +71,41 @@ struct SkCanvasLayerState { |
class SkCanvasState { |
public: |
- SkCanvasState(SkCanvas* canvas) { |
+ SkCanvasState(int32_t version, SkCanvas* canvas) { |
SkASSERT(canvas); |
- version = CANVAS_STATE_VERSION; |
- width = canvas->getDeviceSize().width(); |
- height = canvas->getDeviceSize().height(); |
+ this->version = version; |
+ width = canvas->getBaseLayerSize().width(); |
+ height = canvas->getBaseLayerSize().height(); |
+ |
+ } |
+ |
+ /** |
+ * The version this struct was built with. This field must always appear |
+ * first in the struct so that when the versions don't match (and the |
+ * remaining contents and size are potentially different) we can still |
+ * compare the version numbers. |
+ */ |
+ int32_t version; |
+ int32_t width; |
+ int32_t height; |
+ int32_t alignmentPadding; |
+}; |
+ |
+class SkCanvasState_v1 : public SkCanvasState { |
+public: |
+ static const int32_t kVersion = 1; |
+ |
+ SkCanvasState_v1(SkCanvas* canvas) |
+ : INHERITED(kVersion, canvas) |
+ { |
layerCount = 0; |
layers = NULL; |
- originalCanvas = SkRef(canvas); |
- |
mcState.clipRectCount = 0; |
mcState.clipRects = NULL; |
+ originalCanvas = SkRef(canvas); |
} |
- ~SkCanvasState() { |
+ ~SkCanvasState_v1() { |
// loop through the layers and free the data allocated to the clipRects |
for (int i = 0; i < layerCount; ++i) { |
sk_free(layers[i].mcState.clipRects); |
@@ -98,24 +119,13 @@ public: |
originalCanvas->unref(); |
} |
- /** |
- * The version this struct was built with. This field must always appear |
- * first in the struct so that when the versions don't match (and the |
- * remaining contents and size are potentially different) we can still |
- * compare the version numbers. |
- */ |
- int32_t version; |
- |
- int32_t width; |
- int32_t height; |
- |
SkMCState mcState; |
int32_t layerCount; |
SkCanvasLayerState* layers; |
- |
private: |
SkCanvas* originalCanvas; |
+ typedef SkCanvasState INHERITED; |
}; |
//////////////////////////////////////////////////////////////////////////////// |
@@ -191,7 +201,7 @@ SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) { |
return NULL; |
} |
- SkAutoTDelete<SkCanvasState> canvasState(SkNEW_ARGS(SkCanvasState, (canvas))); |
+ SkAutoTDelete<SkCanvasState_v1> canvasState(SkNEW_ARGS(SkCanvasState_v1, (canvas))); |
// decompose the total matrix and clip |
setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(), |
@@ -247,7 +257,7 @@ SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) { |
// for now, just ignore any client supplied DrawFilter. |
if (canvas->getDrawFilter()) { |
-// SkDEBUGF(("CaptureCanvasState will ignore the canvases draw filter.\n")); |
+// SkDEBUGF(("CaptureCanvasState will ignore the canvas's draw filter.\n")); |
} |
return canvasState.detach(); |
@@ -291,7 +301,7 @@ static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layer |
bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height, |
colorType, kPremul_SkAlphaType), |
- layerState.raster.pixels, layerState.raster.rowBytes); |
+ layerState.raster.pixels, (size_t) layerState.raster.rowBytes); |
SkASSERT(!bitmap.empty()); |
SkASSERT(!bitmap.isNull()); |
@@ -306,30 +316,28 @@ static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layer |
SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state) { |
SkASSERT(state); |
+ // Currently there is only one possible version. |
+ SkASSERT(SkCanvasState_v1::kVersion == state->version); |
- // check that the versions match |
- if (CANVAS_STATE_VERSION != state->version) { |
- SkDebugf("CreateFromCanvasState version does not match the one use to create the input"); |
- return NULL; |
- } |
+ const SkCanvasState_v1* state_v1 = static_cast<const SkCanvasState_v1*>(state); |
- if (state->layerCount < 1) { |
+ if (state_v1->layerCount < 1) { |
return NULL; |
} |
SkAutoTUnref<SkCanvasStack> canvas(SkNEW_ARGS(SkCanvasStack, (state->width, state->height))); |
// setup the matrix and clip on the n-way canvas |
- setup_canvas_from_MC_state(state->mcState, canvas); |
+ setup_canvas_from_MC_state(state_v1->mcState, canvas); |
// Iterate over the layers and add them to the n-way canvas |
- for (int i = state->layerCount - 1; i >= 0; --i) { |
- SkAutoTUnref<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state->layers[i])); |
+ for (int i = state_v1->layerCount - 1; i >= 0; --i) { |
+ SkAutoTUnref<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state_v1->layers[i])); |
if (!canvasLayer.get()) { |
return NULL; |
} |
- canvas->pushCanvas(canvasLayer.get(), SkIPoint::Make(state->layers[i].x, |
- state->layers[i].y)); |
+ canvas->pushCanvas(canvasLayer.get(), SkIPoint::Make(state_v1->layers[i].x, |
+ state_v1->layers[i].y)); |
} |
return canvas.detach(); |
@@ -338,5 +346,9 @@ SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state) |
//////////////////////////////////////////////////////////////////////////////// |
void SkCanvasStateUtils::ReleaseCanvasState(SkCanvasState* state) { |
- SkDELETE(state); |
+ SkASSERT(!state || SkCanvasState_v1::kVersion == state->version); |
+ // Upcast to the correct version of SkCanvasState. This avoids having a virtual destructor on |
+ // SkCanvasState. That would be strange since SkCanvasState has no other virtual functions, and |
+ // instead uses the field "version" to determine how to behave. |
+ SkDELETE(static_cast<SkCanvasState_v1*>(state)); |
} |