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.

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

mercurial