From 269cfa82082b51ad7f1fa8240df6524943967410 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Sat, 22 Aug 2015 23:59:24 +0200 Subject: [PATCH] Backport upstream patches to add API required by gtk3 --- ...API-to-set-up-a-Win32-surface-for-an.patch | 143 ++++++++ ...2-boilerplate-that-uses-a-real-windo.patch | 308 ++++++++++++++++++ mingw-cairo.spec | 11 +- 3 files changed, 461 insertions(+), 1 deletion(-) create mode 100644 0001-win32-Add-cairo-API-to-set-up-a-Win32-surface-for-an.patch create mode 100644 0002-win32-Add-a-win32-boilerplate-that-uses-a-real-windo.patch diff --git a/0001-win32-Add-cairo-API-to-set-up-a-Win32-surface-for-an.patch b/0001-win32-Add-cairo-API-to-set-up-a-Win32-surface-for-an.patch new file mode 100644 index 0000000..cdd2ca1 --- /dev/null +++ b/0001-win32-Add-cairo-API-to-set-up-a-Win32-surface-for-an.patch @@ -0,0 +1,143 @@ +From 16898ba11b4d6e9e2e64bb2d02d0fb5adbe266e2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1?= + =?UTF-8?q?=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= +Date: Thu, 26 Mar 2015 19:33:43 +0000 +Subject: [PATCH 1/2] win32: Add cairo API to set up a Win32 surface for an HDC + with an alpha channel. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: Руслан Ижбулатов +Reviewed-by: Bryce Harrington +--- + src/cairo-win32.h | 4 ++ + src/win32/cairo-win32-display-surface.c | 68 +++++++++++++++++++++++++-------- + 2 files changed, 56 insertions(+), 16 deletions(-) + +diff --git a/src/cairo-win32.h b/src/cairo-win32.h +index 3d2e1c6..db4cac6 100644 +--- a/src/cairo-win32.h ++++ b/src/cairo-win32.h +@@ -49,6 +49,10 @@ cairo_public cairo_surface_t * + cairo_win32_surface_create (HDC hdc); + + cairo_public cairo_surface_t * ++cairo_win32_surface_create_with_format (HDC hdc, ++ cairo_format_t format); ++ ++cairo_public cairo_surface_t * + cairo_win32_printing_surface_create (HDC hdc); + + cairo_public cairo_surface_t * +diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c +index 965f2c4..1571480 100644 +--- a/src/win32/cairo-win32-display-surface.c ++++ b/src/win32/cairo-win32-display-surface.c +@@ -917,31 +917,41 @@ static const cairo_surface_backend_t cairo_win32_display_surface_backend = { + */ + + /** +- * cairo_win32_surface_create: ++ * cairo_win32_surface_create_with_format: + * @hdc: the DC to create a surface for ++ * @format: format of pixels in the surface to create + * + * Creates a cairo surface that targets the given DC. The DC will be + * queried for its initial clip extents, and this will be used as the +- * size of the cairo surface. The resulting surface will always be of +- * format %CAIRO_FORMAT_RGB24; should you need another surface format, +- * you will need to create one through +- * cairo_win32_surface_create_with_dib(). ++ * size of the cairo surface. + * +- * Return value: the newly created surface ++ * Supported formats are: ++ * %CAIRO_FORMAT_ARGB32 ++ * %CAIRO_FORMAT_RGB24 + * +- * Since: 1.0 ++ * Note: @format only tells cairo how to draw on the surface, not what ++ * the format of the surface is. Namely, cairo does not (and cannot) ++ * check that @hdc actually supports alpha-transparency. ++ * ++ * Return value: the newly created surface, NULL on failure ++ * ++ * Since: 1.14.3 + **/ + cairo_surface_t * +-cairo_win32_surface_create (HDC hdc) ++cairo_win32_surface_create_with_format (HDC hdc, cairo_format_t format) + { + cairo_win32_display_surface_t *surface; + +- cairo_format_t format; + cairo_status_t status; + cairo_device_t *device; + +- /* Assume that everything coming in as a HDC is RGB24 */ +- format = CAIRO_FORMAT_RGB24; ++ switch (format) { ++ default: ++ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); ++ case CAIRO_FORMAT_ARGB32: ++ case CAIRO_FORMAT_RGB24: ++ break; ++ } + + surface = malloc (sizeof (*surface)); + if (surface == NULL) +@@ -977,6 +987,28 @@ cairo_win32_surface_create (HDC hdc) + } + + /** ++ * cairo_win32_surface_create: ++ * @hdc: the DC to create a surface for ++ * ++ * Creates a cairo surface that targets the given DC. The DC will be ++ * queried for its initial clip extents, and this will be used as the ++ * size of the cairo surface. The resulting surface will always be of ++ * format %CAIRO_FORMAT_RGB24; should you need another surface format, ++ * you will need to create one through ++ * cairo_win32_surface_create_with_format() or ++ * cairo_win32_surface_create_with_dib(). ++ * ++ * Return value: the newly created surface, NULL on failure ++ * ++ * Since: 1.0 ++ **/ ++cairo_surface_t * ++cairo_win32_surface_create (HDC hdc) ++{ ++ return cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_RGB24); ++} ++ ++/** + * cairo_win32_surface_create_with_dib: + * @format: format of pixels in the surface to create + * @width: width of the surface, in pixels +@@ -1027,12 +1059,16 @@ cairo_win32_surface_create_with_ddb (HDC hdc, + HDC screen_dc, ddb_dc; + HBITMAP saved_dc_bitmap; + +- if (format != CAIRO_FORMAT_RGB24) ++ switch (format) { ++ default: ++/* XXX handle these eventually */ ++ case CAIRO_FORMAT_A8: ++ case CAIRO_FORMAT_A1: + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); +-/* XXX handle these eventually +- format != CAIRO_FORMAT_A8 || +- format != CAIRO_FORMAT_A1) +-*/ ++ case CAIRO_FORMAT_ARGB32: ++ case CAIRO_FORMAT_RGB24: ++ break; ++ } + + if (!hdc) { + screen_dc = GetDC (NULL); +-- +2.4.3 + diff --git a/0002-win32-Add-a-win32-boilerplate-that-uses-a-real-windo.patch b/0002-win32-Add-a-win32-boilerplate-that-uses-a-real-windo.patch new file mode 100644 index 0000000..078f831 --- /dev/null +++ b/0002-win32-Add-a-win32-boilerplate-that-uses-a-real-windo.patch @@ -0,0 +1,308 @@ +From e38e942ac0ef6f5366cabdb22df9858fa4c05ea1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=20=D0=98=D0=B6=D0=B1?= + =?UTF-8?q?=D1=83=D0=BB=D0=B0=D1=82=D0=BE=D0=B2?= +Date: Sat, 4 Apr 2015 15:58:53 +0000 +Subject: [PATCH 2/2] win32: Add a win32 boilerplate that uses a real window + +This way it uses the codepath for cairo_win32_surface_create_with_format(), +instead of the cairo_win32_surface_create_with_dib(). + +Without the recording tests (which terminate the testsuite) +the testsuite results for win32 are: + +284 Passed, 167 Failed [1 crashed, 9 expected], 23 Skipped +win32 (rgb24): 1 crashed! +win32 (rgb24): 17 error +win32 (rgb24): 155 failed +win32 (argb32): 1 crashed! +win32 (argb32): 17 error +win32 (argb32): 68 failed +win32-window-color (rgb24): 1 crashed! +win32-window-color (rgb24): 17 error +win32-window-color (rgb24): 148 failed +win32-window-coloralpha (argb32): 1 crashed! +win32-window-coloralpha (argb32): 17 error +win32-window-coloralpha (argb32): 66 failed + +Reviewed-by: Bryce Harrington +--- + boilerplate/cairo-boilerplate-win32.c | 242 ++++++++++++++++++++++++++++++++-- + 1 file changed, 228 insertions(+), 14 deletions(-) + +diff --git a/boilerplate/cairo-boilerplate-win32.c b/boilerplate/cairo-boilerplate-win32.c +index 7469cc7..4fd0a10 100644 +--- a/boilerplate/cairo-boilerplate-win32.c ++++ b/boilerplate/cairo-boilerplate-win32.c +@@ -28,15 +28,191 @@ + + #include + ++static const cairo_user_data_key_t win32_closure_key; ++ ++typedef struct _win32_target_closure { ++ HWND wnd; ++ HDC dc; ++ ATOM bpl_atom; ++ cairo_surface_t *surface; ++} win32_target_closure_t; ++ ++static void ++_cairo_boilerplate_win32_cleanup_window_surface (void *closure) ++{ ++ win32_target_closure_t *win32tc = closure; ++ ++ if (win32tc != NULL) ++ { ++ if (win32tc->wnd != NULL && ++ ReleaseDC (win32tc->wnd, win32tc->dc) != 1) ++ fprintf (stderr, ++ "Failed to release DC of a test window when cleaning up.\n"); ++ if (win32tc->wnd != NULL && ++ DestroyWindow (win32tc->wnd) == 0) ++ fprintf (stderr, ++ "Failed to destroy a test window when cleaning up, GLE is %lu.\n", ++ GetLastError ()); ++ if (win32tc->bpl_atom != 0 && ++ UnregisterClassA ((LPCSTR) MAKELPARAM (win32tc->bpl_atom, 0), GetModuleHandle (NULL)) == 0 && ++ GetLastError () != ERROR_CLASS_DOES_NOT_EXIST) ++ fprintf (stderr, ++ "Failed to unregister boilerplate window class, GLE is %lu.\n", ++ GetLastError ()); ++ ++ free (win32tc); ++ } ++} ++ ++static win32_target_closure_t * ++_cairo_boilerplate_win32_create_window (int width, ++ int height) ++{ ++ WNDCLASSEXA wincl; ++ win32_target_closure_t *win32tc; ++ LPCSTR window_class_name; ++ ++ ZeroMemory (&wincl, sizeof (WNDCLASSEXA)); ++ wincl.cbSize = sizeof (WNDCLASSEXA); ++ wincl.hInstance = GetModuleHandle (0); ++ wincl.lpszClassName = "cairo_boilerplate_win32_dummy"; ++ wincl.lpfnWndProc = DefWindowProcA; ++ wincl.style = CS_OWNDC; ++ ++ win32tc = calloc (1, sizeof (win32_target_closure_t)); ++ ++ if (win32tc == NULL) ++ { ++ int error = errno; ++ fprintf (stderr, "Ran out of memory: %d.\n", error); ++ return NULL; ++ } ++ ++ ZeroMemory (win32tc, sizeof (win32_target_closure_t)); ++ ++ win32tc->bpl_atom = RegisterClassExA (&wincl); ++ ++ if (win32tc->bpl_atom == 0 && GetLastError () != ERROR_CLASS_ALREADY_EXISTS) ++ { ++ fprintf (stderr, ++ "Failed to register a boilerplate window class, GLE is %lu.\n", ++ GetLastError ()); ++ _cairo_boilerplate_win32_cleanup_window_surface (win32tc); ++ return NULL; ++ } ++ ++ if (win32tc->bpl_atom == 0) ++ window_class_name = wincl.lpszClassName; ++ else ++ window_class_name = (LPCSTR) MAKELPARAM (win32tc->bpl_atom, 0); ++ ++ win32tc->wnd = CreateWindowExA (WS_EX_TOOLWINDOW, ++ window_class_name, ++ 0, ++ WS_POPUP, ++ 0, ++ 0, ++ width, ++ height, ++ 0, ++ 0, ++ 0, ++ 0); ++ ++ if (win32tc->wnd == NULL) ++ { ++ fprintf (stderr, ++ "Failed to create a test window, GLE is %lu.\n", ++ GetLastError ()); ++ _cairo_boilerplate_win32_cleanup_window_surface (win32tc); ++ return NULL; ++ } ++ ++ win32tc->dc = GetDC (win32tc->wnd); ++ ++ if (win32tc->dc == NULL) ++ { ++ fprintf (stderr, "Failed to get test window DC.\n"); ++ _cairo_boilerplate_win32_cleanup_window_surface (win32tc); ++ return NULL; ++ } ++ ++ SetWindowPos (win32tc->wnd, ++ HWND_BOTTOM, ++ INT_MIN, ++ INT_MIN, ++ width, ++ height, ++ SWP_NOACTIVATE | SWP_SHOWWINDOW); ++ ++ return win32tc; ++} ++ + static cairo_surface_t * +-_cairo_boilerplate_win32_create_surface (const char *name, +- cairo_content_t content, +- double width, +- double height, +- double max_width, +- double max_height, +- cairo_boilerplate_mode_t mode, +- void **closure) ++_cairo_boilerplate_win32_create_window_surface (const char *name, ++ cairo_content_t content, ++ double width, ++ double height, ++ double max_width, ++ double max_height, ++ cairo_boilerplate_mode_t mode, ++ void **closure) ++{ ++ win32_target_closure_t *win32tc; ++ cairo_surface_t *surface; ++ cairo_format_t format; ++ cairo_status_t status; ++ ++ win32tc = _cairo_boilerplate_win32_create_window (width, height); ++ ++ if (win32tc == NULL) ++ return NULL; ++ ++ format = cairo_boilerplate_format_from_content (content); ++ ++ surface = cairo_win32_surface_create_with_format (win32tc->dc, format); ++ ++ win32tc->surface = surface; ++ ++ status = cairo_surface_status (surface); ++ ++ if (status != CAIRO_STATUS_SUCCESS) ++ { ++ fprintf (stderr, ++ "Failed to create the test surface: %s [%d].\n", ++ cairo_status_to_string (status), status); ++ _cairo_boilerplate_win32_cleanup_window_surface (win32tc); ++ return NULL; ++ } ++ ++ status = cairo_surface_set_user_data (surface, &win32_closure_key, win32tc, NULL); ++ ++ if (status != CAIRO_STATUS_SUCCESS) ++ { ++ fprintf (stderr, ++ "Failed to set surface userdata: %s [%d].\n", ++ cairo_status_to_string (status), status); ++ ++ cairo_surface_destroy (surface); ++ _cairo_boilerplate_win32_cleanup_window_surface (win32tc); ++ ++ return NULL; ++ } ++ ++ *closure = win32tc; ++ ++ return surface; ++} ++ ++static cairo_surface_t * ++_cairo_boilerplate_win32_create_dib_surface (const char *name, ++ cairo_content_t content, ++ double width, ++ double height, ++ double max_width, ++ double max_height, ++ cairo_boilerplate_mode_t mode, ++ void **closure) + { + cairo_format_t format; + +@@ -52,12 +228,16 @@ static const cairo_boilerplate_target_t targets[] = { + "win32", "win32", NULL, NULL, + CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR, 0, + "cairo_win32_surface_create_with_dib", +- _cairo_boilerplate_win32_create_surface, ++ _cairo_boilerplate_win32_create_dib_surface, + cairo_surface_create_similar, +- NULL, NULL, ++ NULL, ++ NULL, + _cairo_boilerplate_get_image_surface, + cairo_surface_write_to_png, +- NULL, NULL, NULL, TRUE, FALSE, FALSE ++ NULL, ++ NULL, ++ NULL, ++ TRUE, FALSE, FALSE + }, + /* Testing the win32 surface isn't interesting, since for + * ARGB images it just chains to the image backend +@@ -66,12 +246,46 @@ static const cairo_boilerplate_target_t targets[] = { + "win32", "win32", NULL, NULL, + CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR_ALPHA, 0, + "cairo_win32_surface_create_with_dib", +- _cairo_boilerplate_win32_create_surface, ++ _cairo_boilerplate_win32_create_dib_surface, + cairo_surface_create_similar, +- NULL, NULL, ++ NULL, ++ NULL, + _cairo_boilerplate_get_image_surface, + cairo_surface_write_to_png, +- NULL, NULL, NULL, FALSE, FALSE, FALSE ++ NULL, ++ NULL, ++ NULL, ++ FALSE, FALSE, FALSE ++ }, ++ { ++ "win32-window-color", "win32", NULL, NULL, ++ CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR, 1, ++ "cairo_win32_surface_create", ++ _cairo_boilerplate_win32_create_window_surface, ++ cairo_surface_create_similar, ++ NULL, ++ NULL, ++ _cairo_boilerplate_get_image_surface, ++ cairo_surface_write_to_png, ++ _cairo_boilerplate_win32_cleanup_window_surface, ++ NULL, ++ NULL, ++ FALSE, FALSE, FALSE ++ }, ++ { ++ "win32-window-coloralpha", "win32", NULL, NULL, ++ CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR_ALPHA, 1, ++ "cairo_win32_surface_create_with_format", ++ _cairo_boilerplate_win32_create_window_surface, ++ cairo_surface_create_similar, ++ NULL, ++ NULL, ++ _cairo_boilerplate_get_image_surface, ++ cairo_surface_write_to_png, ++ _cairo_boilerplate_win32_cleanup_window_surface, ++ NULL, ++ NULL, ++ FALSE, FALSE, FALSE + }, + }; + CAIRO_BOILERPLATE (win32, targets) +-- +2.4.3 + diff --git a/mingw-cairo.spec b/mingw-cairo.spec index 11b70b8..c00f492 100644 --- a/mingw-cairo.spec +++ b/mingw-cairo.spec @@ -2,7 +2,7 @@ Name: mingw-cairo Version: 1.14.2 -Release: 2%{?dist} +Release: 3%{?dist} Summary: MinGW Windows Cairo library License: LGPLv2 or MPLv1.1 @@ -10,6 +10,10 @@ URL: http://cairographics.org Source0: http://cairographics.org/releases/cairo-%{version}.tar.xz Group: Development/Libraries +# Backported upstream patches to add API required by gtk3 +Patch0: 0001-win32-Add-cairo-API-to-set-up-a-Win32-surface-for-an.patch +Patch1: 0002-win32-Add-a-win32-boilerplate-that-uses-a-real-windo.patch + BuildArch: noarch BuildRequires: mingw32-filesystem >= 95 @@ -86,6 +90,8 @@ Static version of the MinGW Windows Cairo library. %prep %setup -q -n cairo-%{version} +%patch0 -p1 +%patch1 -p1 %build @@ -210,6 +216,9 @@ find $RPM_BUILD_ROOT -name "*.la" -delete %changelog +* Sat Aug 22 2015 Kalev Lember - 1.14.2-3 +- Backport upstream patches to add API required by gtk3 + * Wed Jun 17 2015 Fedora Release Engineering - 1.14.2-2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild