gfx/cairo/win32-ddb-dib.patch

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/win32-ddb-dib.patch	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,181 @@
     1.4 +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
     1.5 +
     1.6 +If a DDB is used as a source for an operation that can't be handled
     1.7 +natively by GDI, we end up needing to take a really slow path (creating a
     1.8 +temporary surface for acquire_source) for each operation.  If we convert
     1.9 +the DDB to a DIB, we then end up having a real image buffer and can hand
    1.10 +things off to pixman directly.
    1.11 +
    1.12 +This isn't the default mode because I'm not sure if there are cases where a
    1.13 +DDB is explicitly needed (e.g. for printing), and it would change
    1.14 +current cairo behaviour.  It might become the default at some point in the
    1.15 +future.
    1.16 +
    1.17 +diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h
    1.18 +--- a/gfx/cairo/cairo/src/cairo-win32-private.h
    1.19 ++++ b/gfx/cairo/cairo/src/cairo-win32-private.h
    1.20 +@@ -117,6 +117,9 @@
    1.21 + 
    1.22 +     /* Whether we can use the CHECKJPEGFORMAT escape function */
    1.23 +     CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
    1.24 ++
    1.25 ++    /* if this DDB surface can be converted to a DIB if necessary */
    1.26 ++    CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB = (1<<9),
    1.27 + };
    1.28 + 
    1.29 + cairo_status_t
    1.30 +diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
    1.31 +--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
    1.32 ++++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
    1.33 +@@ -560,6 +560,56 @@
    1.34 +     return CAIRO_STATUS_SUCCESS;
    1.35 + }
    1.36 + 
    1.37 ++static void
    1.38 ++_cairo_win32_convert_ddb_to_dib (cairo_win32_surface_t *surface)
    1.39 ++{
    1.40 ++    cairo_win32_surface_t *new_surface;
    1.41 ++    int width = surface->extents.width;
    1.42 ++    int height = surface->extents.height;
    1.43 ++
    1.44 ++    BOOL ok;
    1.45 ++    HBITMAP oldbitmap;
    1.46 ++
    1.47 ++    new_surface = (cairo_win32_surface_t*)
    1.48 ++	_cairo_win32_surface_create_for_dc (surface->dc,
    1.49 ++					    surface->format,
    1.50 ++					    width,
    1.51 ++					    height);
    1.52 ++
    1.53 ++    if (new_surface->base.status)
    1.54 ++	return;
    1.55 ++
    1.56 ++    /* DDB can't be 32bpp, so BitBlt is safe */
    1.57 ++    ok = BitBlt (new_surface->dc,
    1.58 ++		 0, 0, width, height,
    1.59 ++		 surface->dc,
    1.60 ++		 0, 0, SRCCOPY);
    1.61 ++
    1.62 ++    if (!ok)
    1.63 ++	goto out;
    1.64 ++
    1.65 ++    /* Now swap around new_surface and surface's internal bitmap
    1.66 ++     * pointers. */
    1.67 ++    DeleteDC (new_surface->dc);
    1.68 ++    new_surface->dc = NULL;
    1.69 ++
    1.70 ++    oldbitmap = SelectObject (surface->dc, new_surface->bitmap);
    1.71 ++    DeleteObject (oldbitmap);
    1.72 ++
    1.73 ++    surface->image = new_surface->image;
    1.74 ++    surface->is_dib = new_surface->is_dib;
    1.75 ++    surface->bitmap = new_surface->bitmap;
    1.76 ++
    1.77 ++    new_surface->bitmap = NULL;
    1.78 ++    new_surface->image = NULL;
    1.79 ++
    1.80 ++    /* Finally update flags */
    1.81 ++    surface->flags = _cairo_win32_flags_for_dc (surface->dc);
    1.82 ++
    1.83 ++  out:
    1.84 ++    cairo_surface_destroy ((cairo_surface_t*)new_surface);
    1.85 ++}
    1.86 ++
    1.87 + static cairo_status_t
    1.88 + _cairo_win32_surface_acquire_source_image (void                    *abstract_surface,
    1.89 + 					   cairo_image_surface_t  **image_out,
    1.90 +@@ -568,6 +618,17 @@
    1.91 +     cairo_win32_surface_t *surface = abstract_surface;
    1.92 +     cairo_win32_surface_t *local = NULL;
    1.93 +     cairo_status_t status;
    1.94 ++
    1.95 ++    if (!surface->image && !surface->is_dib && surface->bitmap &&
    1.96 ++	(surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0)
    1.97 ++    {
    1.98 ++	/* This is a DDB, and we're being asked to use it as a source for
    1.99 ++	 * something that we couldn't support natively.  So turn it into
   1.100 ++	 * a DIB, so that we have an equivalent image surface, as long
   1.101 ++	 * as we're allowed to via flags.
   1.102 ++	 */
   1.103 ++	_cairo_win32_convert_ddb_to_dib (surface);
   1.104 ++    }
   1.105 + 
   1.106 +     if (surface->image) {
   1.107 + 	*image_out = (cairo_image_surface_t *)surface->image;
   1.108 +@@ -2133,3 +2194,61 @@
   1.109 +     free(rd);
   1.110 +     fflush (stderr);
   1.111 + }
   1.112 ++
   1.113 ++/**
   1.114 ++ * cairo_win32_surface_set_can_convert_to_dib
   1.115 ++ * @surface: a #cairo_surface_t
   1.116 ++ * @can_convert: a #cairo_bool_t indicating whether this surface can
   1.117 ++ *               be coverted to a DIB if necessary
   1.118 ++ *
   1.119 ++ * A DDB surface with this flag set can be converted to a DIB if it's
   1.120 ++ * used as a source in a way that GDI can't natively handle; for
   1.121 ++ * example, drawing a RGB24 DDB onto an ARGB32 DIB.  Doing this
   1.122 ++ * conversion results in a significant speed optimization, because we
   1.123 ++ * can call on pixman to perform the operation natively, instead of
   1.124 ++ * reading the data from the DC each time.
   1.125 ++ *
   1.126 ++ * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
   1.127 ++ * changed, or an error otherwise.
   1.128 ++ * 
   1.129 ++ */
   1.130 ++cairo_status_t
   1.131 ++cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t can_convert)
   1.132 ++{
   1.133 ++    cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
   1.134 ++    if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
   1.135 ++	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
   1.136 ++
   1.137 ++    if (surface->bitmap) {
   1.138 ++	if (can_convert)
   1.139 ++	    surface->flags |= CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
   1.140 ++	else
   1.141 ++	    surface->flags &= ~CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
   1.142 ++    }
   1.143 ++
   1.144 ++    return CAIRO_STATUS_SUCCESS;
   1.145 ++}
   1.146 ++
   1.147 ++/**
   1.148 ++ * cairo_win32_surface_get_can_convert_to_dib
   1.149 ++ * @surface: a #cairo_surface_t
   1.150 ++ * @can_convert: a #cairo_bool_t* that receives the return value
   1.151 ++ *
   1.152 ++ * Returns the value of the flag indicating whether the surface can be
   1.153 ++ * converted to a DIB if necessary, as set by
   1.154 ++ * cairo_win32_surface_set_can_convert_to_dib.
   1.155 ++ *
   1.156 ++ * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
   1.157 ++ * retreived, or an error otherwise.
   1.158 ++ * 
   1.159 ++ */
   1.160 ++cairo_status_t
   1.161 ++cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t *can_convert)
   1.162 ++{
   1.163 ++    cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
   1.164 ++    if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
   1.165 ++	return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
   1.166 ++
   1.167 ++    *can_convert = ((surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0);
   1.168 ++    return CAIRO_STATUS_SUCCESS;
   1.169 ++}
   1.170 +diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h
   1.171 +--- a/gfx/cairo/cairo/src/cairo-win32.h
   1.172 ++++ b/gfx/cairo/cairo/src/cairo-win32.h
   1.173 +@@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
   1.174 + cairo_public cairo_surface_t *
   1.175 + cairo_win32_surface_get_image (cairo_surface_t *surface);
   1.176 + 
   1.177 ++cairo_public cairo_status_t
   1.178 ++cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t can_convert);
   1.179 ++
   1.180 ++cairo_public cairo_status_t
   1.181 ++cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t *can_convert);
   1.182 ++
   1.183 + #if CAIRO_HAS_WIN32_FONT
   1.184 + 

mercurial