gfx/skia/trunk/src/utils/SkCanvasStateUtils.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /*
michael@0 2 * Copyright 2013 Google Inc.
michael@0 3 *
michael@0 4 * Use of this source code is governed by a BSD-style license that can be
michael@0 5 * found in the LICENSE file.
michael@0 6 */
michael@0 7
michael@0 8 #include "SkCanvasStateUtils.h"
michael@0 9
michael@0 10 #include "SkBitmapDevice.h"
michael@0 11 #include "SkCanvas.h"
michael@0 12 #include "SkCanvasStack.h"
michael@0 13 #include "SkErrorInternals.h"
michael@0 14 #include "SkWriter32.h"
michael@0 15
michael@0 16 #define CANVAS_STATE_VERSION 1
michael@0 17 /*
michael@0 18 * WARNING: The structs below are part of a stable ABI and as such we explicitly
michael@0 19 * use unambigious primitives (e.g. int32_t instead of an enum).
michael@0 20 *
michael@0 21 * ANY CHANGES TO THE STRUCTS BELOW THAT IMPACT THE ABI SHOULD RESULT IN AN
michael@0 22 * UPDATE OF THE CANVAS_STATE_VERSION. SUCH CHANGES SHOULD ONLY BE MADE IF
michael@0 23 * ABSOLUTELY NECESSARY!
michael@0 24 */
michael@0 25 enum RasterConfigs {
michael@0 26 kUnknown_RasterConfig = 0,
michael@0 27 kRGB_565_RasterConfig = 1,
michael@0 28 kARGB_8888_RasterConfig = 2
michael@0 29 };
michael@0 30 typedef int32_t RasterConfig;
michael@0 31
michael@0 32 enum CanvasBackends {
michael@0 33 kUnknown_CanvasBackend = 0,
michael@0 34 kRaster_CanvasBackend = 1,
michael@0 35 kGPU_CanvasBackend = 2,
michael@0 36 kPDF_CanvasBackend = 3
michael@0 37 };
michael@0 38 typedef int32_t CanvasBackend;
michael@0 39
michael@0 40 struct ClipRect {
michael@0 41 int32_t left, top, right, bottom;
michael@0 42 };
michael@0 43
michael@0 44 struct SkMCState {
michael@0 45 float matrix[9];
michael@0 46 // NOTE: this only works for non-antialiased clips
michael@0 47 int32_t clipRectCount;
michael@0 48 ClipRect* clipRects;
michael@0 49 };
michael@0 50
michael@0 51 // NOTE: If you add more members, bump CanvasState::version.
michael@0 52 struct SkCanvasLayerState {
michael@0 53 CanvasBackend type;
michael@0 54 int32_t x, y;
michael@0 55 int32_t width;
michael@0 56 int32_t height;
michael@0 57
michael@0 58 SkMCState mcState;
michael@0 59
michael@0 60 union {
michael@0 61 struct {
michael@0 62 RasterConfig config; // pixel format: a value from RasterConfigs.
michael@0 63 size_t rowBytes; // Number of bytes from start of one line to next.
michael@0 64 void* pixels; // The pixels, all (height * rowBytes) of them.
michael@0 65 } raster;
michael@0 66 struct {
michael@0 67 int32_t textureID;
michael@0 68 } gpu;
michael@0 69 };
michael@0 70 };
michael@0 71
michael@0 72 class SkCanvasState {
michael@0 73 public:
michael@0 74 SkCanvasState(SkCanvas* canvas) {
michael@0 75 SkASSERT(canvas);
michael@0 76 version = CANVAS_STATE_VERSION;
michael@0 77 width = canvas->getDeviceSize().width();
michael@0 78 height = canvas->getDeviceSize().height();
michael@0 79 layerCount = 0;
michael@0 80 layers = NULL;
michael@0 81 originalCanvas = SkRef(canvas);
michael@0 82
michael@0 83 mcState.clipRectCount = 0;
michael@0 84 mcState.clipRects = NULL;
michael@0 85 }
michael@0 86
michael@0 87 ~SkCanvasState() {
michael@0 88 // loop through the layers and free the data allocated to the clipRects
michael@0 89 for (int i = 0; i < layerCount; ++i) {
michael@0 90 sk_free(layers[i].mcState.clipRects);
michael@0 91 }
michael@0 92
michael@0 93 sk_free(mcState.clipRects);
michael@0 94 sk_free(layers);
michael@0 95
michael@0 96 // it is now safe to free the canvas since there should be no remaining
michael@0 97 // references to the content that is referenced by this canvas (e.g. pixels)
michael@0 98 originalCanvas->unref();
michael@0 99 }
michael@0 100
michael@0 101 /**
michael@0 102 * The version this struct was built with. This field must always appear
michael@0 103 * first in the struct so that when the versions don't match (and the
michael@0 104 * remaining contents and size are potentially different) we can still
michael@0 105 * compare the version numbers.
michael@0 106 */
michael@0 107 int32_t version;
michael@0 108
michael@0 109 int32_t width;
michael@0 110 int32_t height;
michael@0 111
michael@0 112 SkMCState mcState;
michael@0 113
michael@0 114 int32_t layerCount;
michael@0 115 SkCanvasLayerState* layers;
michael@0 116
michael@0 117 private:
michael@0 118 SkCanvas* originalCanvas;
michael@0 119 };
michael@0 120
michael@0 121 ////////////////////////////////////////////////////////////////////////////////
michael@0 122
michael@0 123 class ClipValidator : public SkCanvas::ClipVisitor {
michael@0 124 public:
michael@0 125 ClipValidator() : fFailed(false) {}
michael@0 126 bool failed() { return fFailed; }
michael@0 127
michael@0 128 // ClipVisitor
michael@0 129 virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) SK_OVERRIDE {
michael@0 130 fFailed |= antialias;
michael@0 131 }
michael@0 132
michael@0 133 virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) SK_OVERRIDE {
michael@0 134 fFailed |= antialias;
michael@0 135 }
michael@0 136
michael@0 137 virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) SK_OVERRIDE {
michael@0 138 fFailed |= antialias;
michael@0 139 }
michael@0 140
michael@0 141 private:
michael@0 142 bool fFailed;
michael@0 143 };
michael@0 144
michael@0 145 static void setup_MC_state(SkMCState* state, const SkMatrix& matrix, const SkRegion& clip) {
michael@0 146 // initialize the struct
michael@0 147 state->clipRectCount = 0;
michael@0 148
michael@0 149 // capture the matrix
michael@0 150 for (int i = 0; i < 9; i++) {
michael@0 151 state->matrix[i] = matrix.get(i);
michael@0 152 }
michael@0 153
michael@0 154 /*
michael@0 155 * capture the clip
michael@0 156 *
michael@0 157 * storage is allocated on the stack for the first 4 rects. This value was
michael@0 158 * chosen somewhat arbitrarily, but does allow us to represent simple clips
michael@0 159 * and some more common complex clips (e.g. a clipRect with a sub-rect
michael@0 160 * clipped out of its interior) without needing to malloc any additional memory.
michael@0 161 */
michael@0 162 SkSWriter32<4*sizeof(ClipRect)> clipWriter;
michael@0 163
michael@0 164 if (!clip.isEmpty()) {
michael@0 165 // only returns the b/w clip so aa clips fail
michael@0 166 SkRegion::Iterator clip_iterator(clip);
michael@0 167 for (; !clip_iterator.done(); clip_iterator.next()) {
michael@0 168 // this assumes the SkIRect is stored in l,t,r,b ordering which
michael@0 169 // matches the ordering of our ClipRect struct
michael@0 170 clipWriter.writeIRect(clip_iterator.rect());
michael@0 171 state->clipRectCount++;
michael@0 172 }
michael@0 173 }
michael@0 174
michael@0 175 // allocate memory for the clip then and copy them to the struct
michael@0 176 state->clipRects = (ClipRect*) sk_malloc_throw(clipWriter.bytesWritten());
michael@0 177 clipWriter.flatten(state->clipRects);
michael@0 178 }
michael@0 179
michael@0 180
michael@0 181
michael@0 182 SkCanvasState* SkCanvasStateUtils::CaptureCanvasState(SkCanvas* canvas) {
michael@0 183 SkASSERT(canvas);
michael@0 184
michael@0 185 // Check the clip can be decomposed into rectangles (i.e. no soft clips).
michael@0 186 ClipValidator validator;
michael@0 187 canvas->replayClips(&validator);
michael@0 188 if (validator.failed()) {
michael@0 189 SkErrorInternals::SetError(kInvalidOperation_SkError,
michael@0 190 "CaptureCanvasState does not support canvases with antialiased clips.\n");
michael@0 191 return NULL;
michael@0 192 }
michael@0 193
michael@0 194 SkAutoTDelete<SkCanvasState> canvasState(SkNEW_ARGS(SkCanvasState, (canvas)));
michael@0 195
michael@0 196 // decompose the total matrix and clip
michael@0 197 setup_MC_state(&canvasState->mcState, canvas->getTotalMatrix(),
michael@0 198 canvas->internal_private_getTotalClip());
michael@0 199
michael@0 200 /*
michael@0 201 * decompose the layers
michael@0 202 *
michael@0 203 * storage is allocated on the stack for the first 3 layers. It is common in
michael@0 204 * some view systems (e.g. Android) that a few non-clipped layers are present
michael@0 205 * and we will not need to malloc any additional memory in those cases.
michael@0 206 */
michael@0 207 SkSWriter32<3*sizeof(SkCanvasLayerState)> layerWriter;
michael@0 208 int layerCount = 0;
michael@0 209 for (SkCanvas::LayerIter layer(canvas, true/*skipEmptyClips*/); !layer.done(); layer.next()) {
michael@0 210
michael@0 211 // we currently only work for bitmap backed devices
michael@0 212 const SkBitmap& bitmap = layer.device()->accessBitmap(true/*changePixels*/);
michael@0 213 if (bitmap.empty() || bitmap.isNull() || !bitmap.lockPixelsAreWritable()) {
michael@0 214 return NULL;
michael@0 215 }
michael@0 216
michael@0 217 SkCanvasLayerState* layerState =
michael@0 218 (SkCanvasLayerState*) layerWriter.reserve(sizeof(SkCanvasLayerState));
michael@0 219 layerState->type = kRaster_CanvasBackend;
michael@0 220 layerState->x = layer.x();
michael@0 221 layerState->y = layer.y();
michael@0 222 layerState->width = bitmap.width();
michael@0 223 layerState->height = bitmap.height();
michael@0 224
michael@0 225 switch (bitmap.colorType()) {
michael@0 226 case kPMColor_SkColorType:
michael@0 227 layerState->raster.config = kARGB_8888_RasterConfig;
michael@0 228 break;
michael@0 229 case kRGB_565_SkColorType:
michael@0 230 layerState->raster.config = kRGB_565_RasterConfig;
michael@0 231 break;
michael@0 232 default:
michael@0 233 return NULL;
michael@0 234 }
michael@0 235 layerState->raster.rowBytes = bitmap.rowBytes();
michael@0 236 layerState->raster.pixels = bitmap.getPixels();
michael@0 237
michael@0 238 setup_MC_state(&layerState->mcState, layer.matrix(), layer.clip());
michael@0 239 layerCount++;
michael@0 240 }
michael@0 241
michael@0 242 // allocate memory for the layers and then and copy them to the struct
michael@0 243 SkASSERT(layerWriter.bytesWritten() == layerCount * sizeof(SkCanvasLayerState));
michael@0 244 canvasState->layerCount = layerCount;
michael@0 245 canvasState->layers = (SkCanvasLayerState*) sk_malloc_throw(layerWriter.bytesWritten());
michael@0 246 layerWriter.flatten(canvasState->layers);
michael@0 247
michael@0 248 // for now, just ignore any client supplied DrawFilter.
michael@0 249 if (canvas->getDrawFilter()) {
michael@0 250 // SkDEBUGF(("CaptureCanvasState will ignore the canvases draw filter.\n"));
michael@0 251 }
michael@0 252
michael@0 253 return canvasState.detach();
michael@0 254 }
michael@0 255
michael@0 256 ////////////////////////////////////////////////////////////////////////////////
michael@0 257
michael@0 258 static void setup_canvas_from_MC_state(const SkMCState& state, SkCanvas* canvas) {
michael@0 259 // reconstruct the matrix
michael@0 260 SkMatrix matrix;
michael@0 261 for (int i = 0; i < 9; i++) {
michael@0 262 matrix.set(i, state.matrix[i]);
michael@0 263 }
michael@0 264
michael@0 265 // reconstruct the clip
michael@0 266 SkRegion clip;
michael@0 267 for (int i = 0; i < state.clipRectCount; ++i) {
michael@0 268 clip.op(SkIRect::MakeLTRB(state.clipRects[i].left,
michael@0 269 state.clipRects[i].top,
michael@0 270 state.clipRects[i].right,
michael@0 271 state.clipRects[i].bottom),
michael@0 272 SkRegion::kUnion_Op);
michael@0 273 }
michael@0 274
michael@0 275 canvas->setMatrix(matrix);
michael@0 276 canvas->setClipRegion(clip);
michael@0 277 }
michael@0 278
michael@0 279 static SkCanvas* create_canvas_from_canvas_layer(const SkCanvasLayerState& layerState) {
michael@0 280 SkASSERT(kRaster_CanvasBackend == layerState.type);
michael@0 281
michael@0 282 SkBitmap bitmap;
michael@0 283 SkColorType colorType =
michael@0 284 layerState.raster.config == kARGB_8888_RasterConfig ? kPMColor_SkColorType :
michael@0 285 layerState.raster.config == kRGB_565_RasterConfig ? kRGB_565_SkColorType :
michael@0 286 kUnknown_SkColorType;
michael@0 287
michael@0 288 if (colorType == kUnknown_SkColorType) {
michael@0 289 return NULL;
michael@0 290 }
michael@0 291
michael@0 292 bitmap.installPixels(SkImageInfo::Make(layerState.width, layerState.height,
michael@0 293 colorType, kPremul_SkAlphaType),
michael@0 294 layerState.raster.pixels, layerState.raster.rowBytes,
michael@0 295 NULL, NULL);
michael@0 296
michael@0 297 SkASSERT(!bitmap.empty());
michael@0 298 SkASSERT(!bitmap.isNull());
michael@0 299
michael@0 300 SkAutoTUnref<SkCanvas> canvas(SkNEW_ARGS(SkCanvas, (bitmap)));
michael@0 301
michael@0 302 // setup the matrix and clip
michael@0 303 setup_canvas_from_MC_state(layerState.mcState, canvas.get());
michael@0 304
michael@0 305 return canvas.detach();
michael@0 306 }
michael@0 307
michael@0 308 SkCanvas* SkCanvasStateUtils::CreateFromCanvasState(const SkCanvasState* state) {
michael@0 309 SkASSERT(state);
michael@0 310
michael@0 311 // check that the versions match
michael@0 312 if (CANVAS_STATE_VERSION != state->version) {
michael@0 313 SkDebugf("CreateFromCanvasState version does not match the one use to create the input");
michael@0 314 return NULL;
michael@0 315 }
michael@0 316
michael@0 317 if (state->layerCount < 1) {
michael@0 318 return NULL;
michael@0 319 }
michael@0 320
michael@0 321 SkAutoTUnref<SkCanvasStack> canvas(SkNEW_ARGS(SkCanvasStack, (state->width, state->height)));
michael@0 322
michael@0 323 // setup the matrix and clip on the n-way canvas
michael@0 324 setup_canvas_from_MC_state(state->mcState, canvas);
michael@0 325
michael@0 326 // Iterate over the layers and add them to the n-way canvas
michael@0 327 for (int i = state->layerCount - 1; i >= 0; --i) {
michael@0 328 SkAutoTUnref<SkCanvas> canvasLayer(create_canvas_from_canvas_layer(state->layers[i]));
michael@0 329 if (!canvasLayer.get()) {
michael@0 330 return NULL;
michael@0 331 }
michael@0 332 canvas->pushCanvas(canvasLayer.get(), SkIPoint::Make(state->layers[i].x,
michael@0 333 state->layers[i].y));
michael@0 334 }
michael@0 335
michael@0 336 return canvas.detach();
michael@0 337 }
michael@0 338
michael@0 339 ////////////////////////////////////////////////////////////////////////////////
michael@0 340
michael@0 341 void SkCanvasStateUtils::ReleaseCanvasState(SkCanvasState* state) {
michael@0 342 SkDELETE(state);
michael@0 343 }

mercurial