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 +