summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/win32-ddb-dib.patch
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/win32-ddb-dib.patch')
-rw-r--r--gfx/cairo/win32-ddb-dib.patch181
1 files changed, 181 insertions, 0 deletions
diff --git a/gfx/cairo/win32-ddb-dib.patch b/gfx/cairo/win32-ddb-dib.patch
new file mode 100644
index 0000000000..a520d6e10a
--- /dev/null
+++ b/gfx/cairo/win32-ddb-dib.patch
@@ -0,0 +1,181 @@
+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
+
+If a DDB is used as a source for an operation that can't be handled
+natively by GDI, we end up needing to take a really slow path (creating a
+temporary surface for acquire_source) for each operation. If we convert
+the DDB to a DIB, we then end up having a real image buffer and can hand
+things off to pixman directly.
+
+This isn't the default mode because I'm not sure if there are cases where a
+DDB is explicitly needed (e.g. for printing), and it would change
+current cairo behaviour. It might become the default at some point in the
+future.
+
+diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h
+--- a/gfx/cairo/cairo/src/cairo-win32-private.h
++++ b/gfx/cairo/cairo/src/cairo-win32-private.h
+@@ -117,6 +117,9 @@
+
+ /* Whether we can use the CHECKJPEGFORMAT escape function */
+ CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
++
++ /* if this DDB surface can be converted to a DIB if necessary */
++ CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB = (1<<9),
+ };
+
+ cairo_status_t
+diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
+--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
++++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
+@@ -560,6 +560,56 @@
+ return CAIRO_STATUS_SUCCESS;
+ }
+
++static void
++_cairo_win32_convert_ddb_to_dib (cairo_win32_surface_t *surface)
++{
++ cairo_win32_surface_t *new_surface;
++ int width = surface->extents.width;
++ int height = surface->extents.height;
++
++ BOOL ok;
++ HBITMAP oldbitmap;
++
++ new_surface = (cairo_win32_surface_t*)
++ _cairo_win32_surface_create_for_dc (surface->dc,
++ surface->format,
++ width,
++ height);
++
++ if (new_surface->base.status)
++ return;
++
++ /* DDB can't be 32bpp, so BitBlt is safe */
++ ok = BitBlt (new_surface->dc,
++ 0, 0, width, height,
++ surface->dc,
++ 0, 0, SRCCOPY);
++
++ if (!ok)
++ goto out;
++
++ /* Now swap around new_surface and surface's internal bitmap
++ * pointers. */
++ DeleteDC (new_surface->dc);
++ new_surface->dc = NULL;
++
++ oldbitmap = SelectObject (surface->dc, new_surface->bitmap);
++ DeleteObject (oldbitmap);
++
++ surface->image = new_surface->image;
++ surface->is_dib = new_surface->is_dib;
++ surface->bitmap = new_surface->bitmap;
++
++ new_surface->bitmap = NULL;
++ new_surface->image = NULL;
++
++ /* Finally update flags */
++ surface->flags = _cairo_win32_flags_for_dc (surface->dc);
++
++ out:
++ cairo_surface_destroy ((cairo_surface_t*)new_surface);
++}
++
+ static cairo_status_t
+ _cairo_win32_surface_acquire_source_image (void *abstract_surface,
+ cairo_image_surface_t **image_out,
+@@ -568,6 +618,17 @@
+ cairo_win32_surface_t *surface = abstract_surface;
+ cairo_win32_surface_t *local = NULL;
+ cairo_status_t status;
++
++ if (!surface->image && !surface->is_dib && surface->bitmap &&
++ (surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0)
++ {
++ /* This is a DDB, and we're being asked to use it as a source for
++ * something that we couldn't support natively. So turn it into
++ * a DIB, so that we have an equivalent image surface, as long
++ * as we're allowed to via flags.
++ */
++ _cairo_win32_convert_ddb_to_dib (surface);
++ }
+
+ if (surface->image) {
+ *image_out = (cairo_image_surface_t *)surface->image;
+@@ -2133,3 +2194,61 @@
+ free(rd);
+ fflush (stderr);
+ }
++
++/**
++ * cairo_win32_surface_set_can_convert_to_dib
++ * @surface: a #cairo_surface_t
++ * @can_convert: a #cairo_bool_t indicating whether this surface can
++ * be coverted to a DIB if necessary
++ *
++ * A DDB surface with this flag set can be converted to a DIB if it's
++ * used as a source in a way that GDI can't natively handle; for
++ * example, drawing a RGB24 DDB onto an ARGB32 DIB. Doing this
++ * conversion results in a significant speed optimization, because we
++ * can call on pixman to perform the operation natively, instead of
++ * reading the data from the DC each time.
++ *
++ * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
++ * changed, or an error otherwise.
++ *
++ */
++cairo_status_t
++cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t can_convert)
++{
++ cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
++ if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
++ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
++
++ if (surface->bitmap) {
++ if (can_convert)
++ surface->flags |= CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
++ else
++ surface->flags &= ~CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
++ }
++
++ return CAIRO_STATUS_SUCCESS;
++}
++
++/**
++ * cairo_win32_surface_get_can_convert_to_dib
++ * @surface: a #cairo_surface_t
++ * @can_convert: a #cairo_bool_t* that receives the return value
++ *
++ * Returns the value of the flag indicating whether the surface can be
++ * converted to a DIB if necessary, as set by
++ * cairo_win32_surface_set_can_convert_to_dib.
++ *
++ * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
++ * retreived, or an error otherwise.
++ *
++ */
++cairo_status_t
++cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t *can_convert)
++{
++ cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
++ if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
++ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
++
++ *can_convert = ((surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0);
++ return CAIRO_STATUS_SUCCESS;
++}
+diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h
+--- a/gfx/cairo/cairo/src/cairo-win32.h
++++ b/gfx/cairo/cairo/src/cairo-win32.h
+@@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
+ cairo_public cairo_surface_t *
+ cairo_win32_surface_get_image (cairo_surface_t *surface);
+
++cairo_public cairo_status_t
++cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t can_convert);
++
++cairo_public cairo_status_t
++cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t *can_convert);
++
+ #if CAIRO_HAS_WIN32_FONT
+