gfx/cairo/win32-ddb-dib.patch

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     1 b=455513; add optional flag to allow converting a DDB to a DIB internally, if the surface is every used as a source; r=jmuizelaar
     3 If a DDB is used as a source for an operation that can't be handled
     4 natively by GDI, we end up needing to take a really slow path (creating a
     5 temporary surface for acquire_source) for each operation.  If we convert
     6 the DDB to a DIB, we then end up having a real image buffer and can hand
     7 things off to pixman directly.
     9 This isn't the default mode because I'm not sure if there are cases where a
    10 DDB is explicitly needed (e.g. for printing), and it would change
    11 current cairo behaviour.  It might become the default at some point in the
    12 future.
    14 diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h
    15 --- a/gfx/cairo/cairo/src/cairo-win32-private.h
    16 +++ b/gfx/cairo/cairo/src/cairo-win32-private.h
    17 @@ -117,6 +117,9 @@
    19      /* Whether we can use the CHECKJPEGFORMAT escape function */
    20      CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
    21 +
    22 +    /* if this DDB surface can be converted to a DIB if necessary */
    23 +    CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB = (1<<9),
    24  };
    26  cairo_status_t
    27 diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
    28 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c
    29 +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
    30 @@ -560,6 +560,56 @@
    31      return CAIRO_STATUS_SUCCESS;
    32  }
    34 +static void
    35 +_cairo_win32_convert_ddb_to_dib (cairo_win32_surface_t *surface)
    36 +{
    37 +    cairo_win32_surface_t *new_surface;
    38 +    int width = surface->extents.width;
    39 +    int height = surface->extents.height;
    40 +
    41 +    BOOL ok;
    42 +    HBITMAP oldbitmap;
    43 +
    44 +    new_surface = (cairo_win32_surface_t*)
    45 +	_cairo_win32_surface_create_for_dc (surface->dc,
    46 +					    surface->format,
    47 +					    width,
    48 +					    height);
    49 +
    50 +    if (new_surface->base.status)
    51 +	return;
    52 +
    53 +    /* DDB can't be 32bpp, so BitBlt is safe */
    54 +    ok = BitBlt (new_surface->dc,
    55 +		 0, 0, width, height,
    56 +		 surface->dc,
    57 +		 0, 0, SRCCOPY);
    58 +
    59 +    if (!ok)
    60 +	goto out;
    61 +
    62 +    /* Now swap around new_surface and surface's internal bitmap
    63 +     * pointers. */
    64 +    DeleteDC (new_surface->dc);
    65 +    new_surface->dc = NULL;
    66 +
    67 +    oldbitmap = SelectObject (surface->dc, new_surface->bitmap);
    68 +    DeleteObject (oldbitmap);
    69 +
    70 +    surface->image = new_surface->image;
    71 +    surface->is_dib = new_surface->is_dib;
    72 +    surface->bitmap = new_surface->bitmap;
    73 +
    74 +    new_surface->bitmap = NULL;
    75 +    new_surface->image = NULL;
    76 +
    77 +    /* Finally update flags */
    78 +    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
    79 +
    80 +  out:
    81 +    cairo_surface_destroy ((cairo_surface_t*)new_surface);
    82 +}
    83 +
    84  static cairo_status_t
    85  _cairo_win32_surface_acquire_source_image (void                    *abstract_surface,
    86  					   cairo_image_surface_t  **image_out,
    87 @@ -568,6 +618,17 @@
    88      cairo_win32_surface_t *surface = abstract_surface;
    89      cairo_win32_surface_t *local = NULL;
    90      cairo_status_t status;
    91 +
    92 +    if (!surface->image && !surface->is_dib && surface->bitmap &&
    93 +	(surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0)
    94 +    {
    95 +	/* This is a DDB, and we're being asked to use it as a source for
    96 +	 * something that we couldn't support natively.  So turn it into
    97 +	 * a DIB, so that we have an equivalent image surface, as long
    98 +	 * as we're allowed to via flags.
    99 +	 */
   100 +	_cairo_win32_convert_ddb_to_dib (surface);
   101 +    }
   103      if (surface->image) {
   104  	*image_out = (cairo_image_surface_t *)surface->image;
   105 @@ -2133,3 +2194,61 @@
   106      free(rd);
   107      fflush (stderr);
   108  }
   109 +
   110 +/**
   111 + * cairo_win32_surface_set_can_convert_to_dib
   112 + * @surface: a #cairo_surface_t
   113 + * @can_convert: a #cairo_bool_t indicating whether this surface can
   114 + *               be coverted to a DIB if necessary
   115 + *
   116 + * A DDB surface with this flag set can be converted to a DIB if it's
   117 + * used as a source in a way that GDI can't natively handle; for
   118 + * example, drawing a RGB24 DDB onto an ARGB32 DIB.  Doing this
   119 + * conversion results in a significant speed optimization, because we
   120 + * can call on pixman to perform the operation natively, instead of
   121 + * reading the data from the DC each time.
   122 + *
   123 + * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
   124 + * changed, or an error otherwise.
   125 + * 
   126 + */
   127 +cairo_status_t
   128 +cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t can_convert)
   129 +{
   130 +    cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
   131 +    if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
   132 +	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
   133 +
   134 +    if (surface->bitmap) {
   135 +	if (can_convert)
   136 +	    surface->flags |= CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
   137 +	else
   138 +	    surface->flags &= ~CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
   139 +    }
   140 +
   141 +    return CAIRO_STATUS_SUCCESS;
   142 +}
   143 +
   144 +/**
   145 + * cairo_win32_surface_get_can_convert_to_dib
   146 + * @surface: a #cairo_surface_t
   147 + * @can_convert: a #cairo_bool_t* that receives the return value
   148 + *
   149 + * Returns the value of the flag indicating whether the surface can be
   150 + * converted to a DIB if necessary, as set by
   151 + * cairo_win32_surface_set_can_convert_to_dib.
   152 + *
   153 + * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
   154 + * retreived, or an error otherwise.
   155 + * 
   156 + */
   157 +cairo_status_t
   158 +cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t *can_convert)
   159 +{
   160 +    cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
   161 +    if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
   162 +	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
   163 +
   164 +    *can_convert = ((surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0);
   165 +    return CAIRO_STATUS_SUCCESS;
   166 +}
   167 diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h
   168 --- a/gfx/cairo/cairo/src/cairo-win32.h
   169 +++ b/gfx/cairo/cairo/src/cairo-win32.h
   170 @@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
   171  cairo_public cairo_surface_t *
   172  cairo_win32_surface_get_image (cairo_surface_t *surface);
   174 +cairo_public cairo_status_t
   175 +cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t can_convert);
   176 +
   177 +cairo_public cairo_status_t
   178 +cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t *can_convert);
   179 +
   180  #if CAIRO_HAS_WIN32_FONT

mercurial