1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkCanvasStateUtils.h" 9 10 #include "SkCanvas.h" 11 #include "SkCanvasStack.h" 12 #include "SkDevice.h" 13 #include "SkRasterClip.h" 14 #include "SkWriter32.h" 15 #include "SkClipOpPriv.h" 16 17 /* 18 * 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). 20 * 21 * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN A NEW 22 * NEW SUBCLASS OF SkCanvasState. SUCH CHANGES SHOULD ONLY BE MADE IF ABSOLUTELY 23 * NECESSARY! 24 * 25 * In order to test changes, run the CanvasState tests. gyp/canvas_state_lib.gyp 26 * describes how to create a library to pass to the CanvasState tests. The tests 27 * should succeed when building the library with your changes and passing that to 28 * the tests running in the unchanged Skia. 29 */ 30 enum RasterConfigs { 31 kUnknown_RasterConfig = 0, 32 kRGB_565_RasterConfig = 1, 33 kARGB_8888_RasterConfig = 2 34 }; 35 typedef int32_t RasterConfig; 36 37 enum CanvasBackends { 38 kUnknown_CanvasBackend = 0, 39 kRaster_CanvasBackend = 1, 40 kGPU_CanvasBackend = 2, 41 kPDF_CanvasBackend = 3 42 }; 43 typedef int32_t CanvasBackend; 44 45 struct ClipRect { 46 int32_t left, top, right, bottom; 47 }; 48 49 struct SkMCState { 50 float matrix[9]; 51 // NOTE: this only works for non-antialiased clips 52 int32_t clipRectCount; 53 ClipRect* clipRects; 54 }; 55 56 // NOTE: If you add more members, create a new subclass of SkCanvasState with a 57 // new CanvasState::version. 58 struct SkCanvasLayerState { 59 CanvasBackend type; 60 int32_t x, y; 61 int32_t width; 62 int32_t height; 63 64 SkMCState mcState; 65 66 union { 67 struct { 68 RasterConfig config; // pixel format: a value from RasterConfigs. 69 uint64_t rowBytes; // Number of bytes from start of one line to next. 70 void* pixels; // The pixels, all (height * rowBytes) of them. 71 } raster; 72 struct { 73 int32_t textureID; 74 } gpu; 75 }; 76 }; 77 78 class SkCanvasState { 79 public: 80 SkCanvasState(int32_t version, SkCanvas* canvas) { 81 SkASSERT(canvas); 82 this->version = version; 83 width = canvas->getBaseLayerSize().width(); 84 height = canvas->getBaseLayerSize().height(); 85 86 } 87 88 /** 89 * The version this struct was built with. This field must always appear 90 * first in the struct so that when the versions don't match (and the 91 * remaining contents and size are potentially different) we can still 92 * compare the version numbers. 93 */ 94 int32_t version; 95 int32_t width; 96 int32_t height; 97 int32_t alignmentPadding; 98 }; 99 100 class SkCanvasState_v1 : public SkCanvasState { 101 public: 102 static const int32_t kVersion = 1; 103 104 SkCanvasState_v1(SkCanvas* canvas) : INHERITED(kVersion, canvas) { 105 layerCount = 0; 106 layers = nullptr; 107 mcState.clipRectCount = 0; 108 mcState.clipRects = nullptr; 109 originalCanvas = canvas; 110 } 111 112 ~SkCanvasState_v1() { 113 // loop through the layers and free the data allocated to the clipRects 114 for (int i = 0; i < layerCount; ++i) { 115 sk_free(layers[i].mcState.clipRects); 116 } 117 118 sk_free(mcState.clipRects); 119 sk_free(layers); 120 } 121 122 SkMCState mcState; 123 124 int32_t layerCount; 125 SkCanvasLayerState* layers; 126 private: 127 SkCanvas* originalCanvas; 128 typedef SkCanvasState INHERITED; 129 }; 130 131 //////////////////////////////////////////////////////////////////////////////// 132 133 static void setup_MC_state(SkMCState* state, const SkMatrix& matrix, const SkRegion& clip) { 134 // initialize the struct 135 state->clipRectCount = 0; 136 137 // capture the matrix 138 for (int i = 0; i < 9; i++) { 139 state->matrix[i] = matrix.get(i); 140 } 141 142 /* 143 * capture the clip 144 * 145 * storage is allocated on the stack for the first 4 rects. This value was 146 * chosen somewhat arbitrarily, but does allow us to represent simple clips 147 * and some more common complex clips (e.g. a clipRect with a sub-rect 148 * clipped out of its interior) without needing to malloc any additional memory. 149 */ 150 SkSWriter32<4*sizeof(ClipRect)> clipWriter; 151 152 if (!clip.isEmpty()) { 153 // only returns the b/w clip so aa clips fail 154 SkRegion::Iterator clip_iterator(clip); 155 for (; !clip_iterator.done(); clip_iterator.next()) { 156 // this assumes the SkIRect is stored in l,t,r,b ordering which 157 // matches the ordering of our ClipRect struct 158 clipWriter.writeIRect(clip_iterator.rect()); 159 state->clipRectCount++; 160 } 161 } 162 163 // allocate memory for the clip then and copy them to the struct 164 state->clipRects = (ClipRect*) sk_malloc_throw(clipWriter.bytesWritten()); 165 clipWriter.flatten(state->clipRects); 166 } 167 168 169 170 SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) { 171 SkASSERT(canvas); 172 173 // Check the clip can be decomposed into rectangles (i.e. no soft clips). 174 if (canvas->androidFramework_isClipAA()) { 175 return nullptr; 176 } 177 178 std::unique_ptr<SkCanvasState_v1> canvasState(new SkCanvasState_v1(canvas)); 179 180 // decompose the total matrix and clip 181 { 182 SkRegion rgn; 183 canvas->temporary_internal_getRgnClip(&rgn); 184 setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(), rgn); 185 } 186 187 /* 188 * decompose the layers 189 * 190 * storage is allocated on the stack for the first 3 layers. It is common in 191 * some view systems (e.g. Android) that a few non-clipped layers are present 192 * and we will not need to malloc any additional memory in those cases. 193 */ 194 SkSWriter32<3*sizeof(SkCanvasLayerState)> layerWriter; 195 int layerCount = 0; 196 for (SkCanvas::LayerIter layer(canvas); !layer.done(); layer.next()) { 197 198 // we currently only work for bitmap backed devices 199 SkPixmap pmap; 200 if (!layer.device()->accessPixels(&pmap) || 0 == pmap.width() || 0 == pmap.height()) { 201 return nullptr; 202 } 203 204 SkCanvasLayerState* layerState = 205 (SkCanvasLayerState*) layerWriter.reserve(sizeof(SkCanvasLayerState)); 206 layerState->type = kRaster_CanvasBackend; 207 layerState->x = layer.x(); 208 layerState->y = layer.y(); 209 layerState->width = pmap.width(); 210 layerState->height = pmap.height(); 211 212 switch (pmap.colorType()) { 213 case kN32_SkColorType: 214 layerState->raster.config = kARGB_8888_RasterConfig; 215 break; 216 case kRGB_565_SkColorType: 217 layerState->raster.config = kRGB_565_RasterConfig; 218 break; 219 default: 220 return nullptr; 221 } 222 layerState->raster.rowBytes = pmap.rowBytes(); 223 layerState->raster.pixels = pmap.writable_addr(); 224 225 SkRegion rgn; 226 layer.clip(&rgn); 227 setup_MC_state(&layerState->mcState, layer.matrix(), rgn); 228 layerCount++; 229 } 230 231 // allocate memory for the layers and then and copy them to the struct 232 SkASSERT(layerWriter.bytesWritten() == layerCount * sizeof(SkCanvasLayerState)); 233 canvasState->layerCount = layerCount; 234 canvasState->layers = (SkCanvasLayerState*) sk_malloc_throw(layerWriter.bytesWritten()); 235 layerWriter.flatten(canvasState->layers); 236 237 return canvasState.release(); 238 } 239 240 //////////////////////////////////////////////////////////////////////////////// 241 242 static void setup_canvas_from_MC_state(const SkMCState& state, SkCanvas* canvas) { 243 // reconstruct the matrix 244 SkMatrix matrix; 245 for (int i = 0; i < 9; i++) { 246 matrix.set(i, state.matrix[i]); 247 } 248 249 // reconstruct the clip 250 SkRegion clip; 251 for (int i = 0; i < state.clipRectCount; ++i) { 252 clip.op(SkIRect::MakeLTRB(state.clipRects[i].left, 253 state.clipRects[i].top, 254 state.clipRects[i].right, 255 state.clipRects[i].bottom), 256 SkRegion::kUnion_Op); 257 } 258 259 canvas->setMatrix(matrix); 260 canvas->clipRegion(clip, kReplace_SkClipOp); 261 } 262 263 static std::unique_ptr<SkCanvas> 264 make_canvas_from_canvas_layer(const SkCanvasLayerState& layerState) { 265 SkASSERT(kRaster_CanvasBackend == layerState.type); 266 267 SkBitmap bitmap; 268 SkColorType colorType = 269 layerState.raster.config == kARGB_8888_RasterConfig ? kN32_SkColorType : 270 layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType : 271 kUnknown_SkColorType; 272 273 if (colorType == kUnknown_SkColorType) { 274 return nullptr; 275 } 276 277 bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height, 278 colorType, kPremul_SkAlphaType), 279 layerState.raster.pixels, (size_t) layerState.raster.rowBytes); 280 281 SkASSERT(!bitmap.empty()); 282 SkASSERT(!bitmap.isNull()); 283 284 std::unique_ptr<SkCanvas> canvas(new SkCanvas(bitmap)); 285 286 // setup the matrix and clip 287 setup_canvas_from_MC_state(layerState.mcState, canvas.get()); 288 289 return canvas; 290 } 291 292 std::unique_ptr<SkCanvas> SkCanvasStateUtils::MakeFromCanvasState(const SkCanvasState* state) { 293 SkASSERT(state); 294 // Currently there is only one possible version. 295 SkASSERT(SkCanvasState_v1::kVersion == state->version); 296 297 const SkCanvasState_v1* state_v1 = static_cast<const SkCanvasState_v1*>(state); 298 299 if (state_v1->layerCount < 1) { 300 return nullptr; 301 } 302 303 std::unique_ptr<SkCanvasStack> canvas(new SkCanvasStack(state->width, state->height)); 304 305 // setup the matrix and clip on the n-way canvas 306 setup_canvas_from_MC_state(state_v1->mcState, canvas.get()); 307 308 // Iterate over the layers and add them to the n-way canvas 309 for (int i = state_v1->layerCount - 1; i >= 0; --i) { 310 std::unique_ptr<SkCanvas> canvasLayer = make_canvas_from_canvas_layer(state_v1->layers[i]); 311 if (!canvasLayer.get()) { 312 return nullptr; 313 } 314 canvas->pushCanvas(std::move(canvasLayer), SkIPoint::Make(state_v1->layers[i].x, 315 state_v1->layers[i].y)); 316 } 317 318 return std::move(canvas); 319 } 320 321 //////////////////////////////////////////////////////////////////////////////// 322 323 void SkCanvasStateUtils::ReleaseCanvasState(SkCanvasState* state) { 324 SkASSERT(!state || SkCanvasState_v1::kVersion == state->version); 325 // Upcast to the correct version of SkCanvasState. This avoids having a virtual destructor on 326 // SkCanvasState. That would be strange since SkCanvasState has no other virtual functions, and 327 // instead uses the field "version" to determine how to behave. 328 delete static_cast<SkCanvasState_v1*>(state); 329 } 330