From dfd06ab3884d79de3b5bac782d1e8b2a0bd791ab Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 16:48:12 +0100 Subject: [PATCH 01/12] Meson: Require C++11 --- meson.build | 1 + 1 file changed, 1 insertion(+) diff --git a/meson.build b/meson.build index 162b2927c..de89fb235 100644 --- a/meson.build +++ b/meson.build @@ -2,6 +2,7 @@ project('cairo', 'c', meson_version: '>= 1.3.0', version: run_command(find_program('version.py'), check: true).stdout().strip(), default_options: ['c_std=gnu11,c11', + 'cpp_std=gnu++11,c++11', 'warning_level=2'], ) From 613df92660903f5a5fa31199ba568b6d99fee9bd Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 14:12:34 +0100 Subject: [PATCH 02/12] Win32: Remove check for Windows 98 --- src/win32/cairo-win32-device.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/win32/cairo-win32-device.c b/src/win32/cairo-win32-device.c index e000b11f6..42f013392 100644 --- a/src/win32/cairo-win32-device.c +++ b/src/win32/cairo-win32-device.c @@ -90,26 +90,11 @@ D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_T hr = m_pD2DFactory->CreateDCRenderTarget(&props, &device->d2d); #endif -static cairo_bool_t is_win98 (void) -{ - OSVERSIONINFO os; - - os.dwOSVersionInfoSize = sizeof (os); - GetVersionEx (&os); - - return (VER_PLATFORM_WIN32_WINDOWS == os.dwPlatformId && - os.dwMajorVersion == 4 && - os.dwMinorVersion == 10); -} - static void * _cairo_win32_device_get_alpha_blend (cairo_win32_device_t *device) { void *func = NULL; - if (is_win98 ()) - return NULL; - device->msimg32_dll = LoadLibraryW (L"msimg32"); if (device->msimg32_dll) func = GetProcAddress (device->msimg32_dll, "AlphaBlend"); From 361240657c2d668a719cdf4e999867025c8caeb1 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 14:19:55 +0100 Subject: [PATCH 03/12] Win32: Do not load msimg32.dll at runtime This commit drops support for Windows 98 --- src/win32/cairo-win32-device.c | 15 --------------- src/win32/cairo-win32-gdi-compositor.c | 13 ++++--------- src/win32/cairo-win32-private.h | 16 ---------------- 3 files changed, 4 insertions(+), 40 deletions(-) diff --git a/src/win32/cairo-win32-device.c b/src/win32/cairo-win32-device.c index 42f013392..575239352 100644 --- a/src/win32/cairo-win32-device.c +++ b/src/win32/cairo-win32-device.c @@ -90,18 +90,6 @@ D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_T hr = m_pD2DFactory->CreateDCRenderTarget(&props, &device->d2d); #endif -static void * -_cairo_win32_device_get_alpha_blend (cairo_win32_device_t *device) -{ - void *func = NULL; - - device->msimg32_dll = LoadLibraryW (L"msimg32"); - if (device->msimg32_dll) - func = GetProcAddress (device->msimg32_dll, "AlphaBlend"); - - return func; -} - cairo_device_t * _cairo_win32_device_get (void) { @@ -118,9 +106,6 @@ _cairo_win32_device_get (void) device->compositor = _cairo_win32_gdi_compositor_get (); - device->msimg32_dll = NULL; - device->alpha_blend = _cairo_win32_device_get_alpha_blend (device); - if (_cairo_atomic_ptr_cmpxchg ((cairo_atomic_intptr_t *)&__cairo_win32_device, NULL, device)) return cairo_device_reference(&device->base); diff --git a/src/win32/cairo-win32-gdi-compositor.c b/src/win32/cairo-win32-gdi-compositor.c index bc1f69e70..08e5abfb3 100644 --- a/src/win32/cairo-win32-gdi-compositor.c +++ b/src/win32/cairo-win32-gdi-compositor.c @@ -105,7 +105,6 @@ struct copy_box { int tx, ty; HDC dst, src; BLENDFUNCTION bf; - cairo_win32_alpha_blend_func_t alpha_blend; }; static cairo_bool_t copy_box (cairo_box_t *box, void *closure) @@ -131,9 +130,9 @@ static cairo_bool_t alpha_box (cairo_box_t *box, void *closure) int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y); TRACE ((stderr, "%s\n", __FUNCTION__)); - return cb->alpha_blend (cb->dst, x, y, width, height, - cb->src, x + cb->tx, y + cb->ty, width, height, - cb->bf); + return AlphaBlend (cb->dst, x, y, width, height, + cb->src, x + cb->tx, y + cb->ty, width, height, + cb->bf); } struct upload_box { @@ -382,7 +381,6 @@ alpha_blend_boxes (cairo_win32_display_surface_t *dst, cb.bf.BlendFlags = 0; cb.bf.SourceConstantAlpha = alpha; cb.bf.AlphaFormat = (src->win32.format == CAIRO_FORMAT_ARGB32) ? AC_SRC_ALPHA : 0; - cb.alpha_blend = to_win32_device(dst->win32.base.device)->alpha_blend; cb.tx += cb.limit.x; cb.ty += cb.limit.y; @@ -397,10 +395,7 @@ alpha_blend_boxes (cairo_win32_display_surface_t *dst, static cairo_bool_t can_alpha_blend (cairo_win32_display_surface_t *dst) { - if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND) == 0) - return FALSE; - - return to_win32_device(dst->win32.base.device)->alpha_blend != NULL; + return (dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_ALPHABLEND) != 0; } static cairo_status_t diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h index 6af09c0e1..594e2b085 100644 --- a/src/win32/cairo-win32-private.h +++ b/src/win32/cairo-win32-private.h @@ -168,26 +168,10 @@ typedef struct _cairo_win32_printing_surface { } cairo_win32_printing_surface_t; #define to_win32_printing_surface(S) ((cairo_win32_printing_surface_t *)(S)) -typedef BOOL (WINAPI *cairo_win32_alpha_blend_func_t) (HDC hdcDest, - int nXOriginDest, - int nYOriginDest, - int nWidthDest, - int hHeightDest, - HDC hdcSrc, - int nXOriginSrc, - int nYOriginSrc, - int nWidthSrc, - int nHeightSrc, - BLENDFUNCTION blendFunction); - typedef struct _cairo_win32_device { cairo_device_t base; - HMODULE msimg32_dll; - const cairo_compositor_t *compositor; - - cairo_win32_alpha_blend_func_t alpha_blend; } cairo_win32_device_t; #define to_win32_device(D) ((cairo_win32_device_t *)(D)) #define to_win32_device_from_surface(S) to_win32_device(((cairo_surface_t *)(S))->device) From d0ee67a14285788f3b423df5b87ab81c08f50c8f Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 14:26:04 +0100 Subject: [PATCH 04/12] Win32: Remove unused code and defines for old toolchains --- boilerplate/cairo-boilerplate-win32-printing.c | 16 ---------------- src/win32/cairo-win32-device.c | 14 -------------- src/win32/cairo-win32-display-surface.c | 4 ---- src/win32/cairo-win32-font.c | 13 ------------- src/win32/cairo-win32-gdi-compositor.c | 17 ----------------- src/win32/cairo-win32-private.h | 7 ------- src/win32/cairo-win32-surface.c | 4 ---- 7 files changed, 75 deletions(-) diff --git a/boilerplate/cairo-boilerplate-win32-printing.c b/boilerplate/cairo-boilerplate-win32-printing.c index e8fcdcef5..a3802d2e9 100644 --- a/boilerplate/cairo-boilerplate-win32-printing.c +++ b/boilerplate/cairo-boilerplate-win32-printing.c @@ -36,22 +36,6 @@ #include -#if !defined(POSTSCRIPT_IDENTIFY) -# define POSTSCRIPT_IDENTIFY 0x1015 -#endif - -#if !defined(PSIDENT_GDICENTRIC) -# define PSIDENT_GDICENTRIC 0x0000 -#endif - -#if !defined(GET_PS_FEATURESETTING) -# define GET_PS_FEATURESETTING 0x1019 -#endif - -#if !defined(FEATURESETTING_PSLEVEL) -# define FEATURESETTING_PSLEVEL 0x0002 -#endif - static cairo_status_t _cairo_win32_print_gdi_error (const char *context) { diff --git a/src/win32/cairo-win32-device.c b/src/win32/cairo-win32-device.c index 575239352..c55b0789e 100644 --- a/src/win32/cairo-win32-device.c +++ b/src/win32/cairo-win32-device.c @@ -76,20 +76,6 @@ static const cairo_device_backend_t _cairo_win32_device_backend = { _cairo_win32_device_destroy, }; -#if 0 -D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT, - D2D1::PixelFormat( - DXGI_FORMAT_B8G8R8A8_UNORM, - D2D1_ALPHA_MODE_IGNORE), - 0, - 0, - D2D1_RENDER_TARGET_USAGE_NONE, - D2D1_FEATURE_LEVEL_DEFAULT - ); - -hr = m_pD2DFactory->CreateDCRenderTarget(&props, &device->d2d); -#endif - cairo_device_t * _cairo_win32_device_get (void) { diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c index 2800052bc..4f4e8f847 100644 --- a/src/win32/cairo-win32-display-surface.c +++ b/src/win32/cairo-win32-display-surface.c @@ -56,10 +56,6 @@ #include #include -#if defined(__MINGW32__) && !defined(ETO_PDY) -# define ETO_PDY 0x2000 -#endif - #define PELS_72DPI ((LONG)(72. / 0.0254)) /** diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c index 3ad4f7ff4..265f93294 100644 --- a/src/win32/cairo-win32-font.c +++ b/src/win32/cairo-win32-font.c @@ -45,19 +45,6 @@ #include -#ifndef SPI_GETFONTSMOOTHINGTYPE -#define SPI_GETFONTSMOOTHINGTYPE 0x200a -#endif -#ifndef FE_FONTSMOOTHINGCLEARTYPE -#define FE_FONTSMOOTHINGCLEARTYPE 2 -#endif -#ifndef CLEARTYPE_QUALITY -#define CLEARTYPE_QUALITY 5 -#endif -#ifndef TT_PRIM_CSPLINE -#define TT_PRIM_CSPLINE 3 -#endif - #define CMAP_TAG 0x70616d63 /** diff --git a/src/win32/cairo-win32-gdi-compositor.c b/src/win32/cairo-win32-gdi-compositor.c index 08e5abfb3..268ca0100 100644 --- a/src/win32/cairo-win32-gdi-compositor.c +++ b/src/win32/cairo-win32-gdi-compositor.c @@ -55,23 +55,6 @@ #include "cairo-surface-inline.h" #include "cairo-surface-offset-private.h" -#if !defined(AC_SRC_OVER) -#define AC_SRC_OVER 0x00 -#pragma pack(1) -typedef struct { - BYTE BlendOp; - BYTE BlendFlags; - BYTE SourceConstantAlpha; - BYTE AlphaFormat; -}BLENDFUNCTION; -#pragma pack() -#endif - -/* for compatibility with VC++ 6 */ -#ifndef AC_SRC_ALPHA -#define AC_SRC_ALPHA 0x01 -#endif - #define PELS_72DPI ((LONG)(72. / 0.0254)) /* the low-level interface */ diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h index 594e2b085..4e180a81e 100644 --- a/src/win32/cairo-win32-private.h +++ b/src/win32/cairo-win32-private.h @@ -44,13 +44,6 @@ #include "cairo-surface-clipper-private.h" #include "cairo-surface-private.h" -#ifndef SHADEBLENDCAPS -#define SHADEBLENDCAPS 120 -#endif -#ifndef SB_NONE -#define SB_NONE 0 -#endif - #define WIN32_FONT_LOGICAL_SCALE 32 CAIRO_BEGIN_DECLS diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c index ca5c9d823..6e82638ff 100644 --- a/src/win32/cairo-win32-surface.c +++ b/src/win32/cairo-win32-surface.c @@ -53,10 +53,6 @@ #include #include -#if defined(__MINGW32__) && !defined(ETO_PDY) -# define ETO_PDY 0x2000 -#endif - /** * SECTION:cairo-win32 * @Title: Win32 Surfaces From e10adb1c2b81c8b3f1e280b7d32ff63bbfe56c71 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 14:33:58 +0100 Subject: [PATCH 05/12] Win32: Pass FORMAT_MESSAGE_IGNORE_INSERTS This should always be passed when retreving messages from third parties (unless the third party documents format strings) See https://devblogs.microsoft.com/oldnewthing/20071128-00/?p=24353 --- boilerplate/cairo-boilerplate-win32-printing.c | 1 + src/win32/cairo-dwrite-font.cpp | 1 + src/win32/cairo-win32-surface.c | 1 + 3 files changed, 3 insertions(+) diff --git a/boilerplate/cairo-boilerplate-win32-printing.c b/boilerplate/cairo-boilerplate-win32-printing.c index a3802d2e9..a156deb24 100644 --- a/boilerplate/cairo-boilerplate-win32-printing.c +++ b/boilerplate/cairo-boilerplate-win32-printing.c @@ -43,6 +43,7 @@ _cairo_win32_print_gdi_error (const char *context) DWORD last_error = GetLastError (); if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, last_error, diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index f7d1c4767..74d12c6a0 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -110,6 +110,7 @@ _cairo_dwrite_error (HRESULT hr, const char *context) void *lpMsgBuf; if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, hr, diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c index 6e82638ff..6862e2090 100644 --- a/src/win32/cairo-win32-surface.c +++ b/src/win32/cairo-win32-surface.c @@ -95,6 +95,7 @@ _cairo_win32_print_gdi_error (const char *context) DWORD last_error = GetLastError (); if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, last_error, From f289bea1d28718c94e8451a80db607b88d7a3692 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 15:31:23 +0100 Subject: [PATCH 06/12] Readme: Update Windows OS requirements to Windows Vista --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ebe3f99e1..2bd26068b 100644 --- a/README.md +++ b/README.md @@ -126,7 +126,7 @@ system pixman. #### Windows backend -- Microsoft Windows 2000 or newer. +- Microsoft Windows Vista or newer. #### XCB backend From 85f308f690f522e2f69e489c3f54587cf20d2c01 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 14:44:01 +0100 Subject: [PATCH 07/12] Win32: Avoid checking the last error for GDI functions that don't set it Most GDI functions do not set the last error, so GetLastError() returns unrelated error codes. There are some exceptions, however, like BitBlt and CreateDIBSection. Whether a GDI function sets the last error is stated in the reference documentation on MSDN. --- .../cairo-boilerplate-win32-printing.c | 32 +----- src/win32/cairo-win32-display-surface.c | 30 +++--- src/win32/cairo-win32-font.c | 98 ++++++++++++------- src/win32/cairo-win32-gdi-compositor.c | 6 +- src/win32/cairo-win32-printing-surface.c | 59 +++++++---- src/win32/cairo-win32-surface.c | 2 +- 6 files changed, 124 insertions(+), 103 deletions(-) diff --git a/boilerplate/cairo-boilerplate-win32-printing.c b/boilerplate/cairo-boilerplate-win32-printing.c index a156deb24..9177480fc 100644 --- a/boilerplate/cairo-boilerplate-win32-printing.c +++ b/boilerplate/cairo-boilerplate-win32-printing.c @@ -36,36 +36,6 @@ #include -static cairo_status_t -_cairo_win32_print_gdi_error (const char *context) -{ - void *lpMsgBuf; - DWORD last_error = GetLastError (); - - if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - last_error, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR) &lpMsgBuf, - 0, NULL)) { - fprintf (stderr, "%s: Unknown GDI error", context); - } else { - fprintf (stderr, "%s: %S", context, (wchar_t *)lpMsgBuf); - - LocalFree (lpMsgBuf); - } - - fflush (stderr); - - /* We should switch off of last_status, but we'd either return - * CAIRO_STATUS_NO_MEMORY or CAIRO_STATUS_UNKNOWN_ERROR and there - * is no CAIRO_STATUS_UNKNOWN_ERROR. - */ - return CAIRO_STATUS_NO_MEMORY; -} - static cairo_user_data_key_t win32_closure_key; typedef struct _win32_target_closure { @@ -159,7 +129,7 @@ create_printer_dc (win32_target_closure_t *ptc) xform.eDx = 0; xform.eDy = printable_height - ptc->height*y_dpi/72.0; if (!SetWorldTransform (ptc->dc, &xform)) { - _cairo_win32_print_gdi_error ("cairo-boilerplate-win32-printing:SetWorldTransform"); + fprintf (stderr, "%s:%s\n", "cairo-boilerplate-win32-printing", "SetWorldTransform"); return; } diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c index 4f4e8f847..8be03c03c 100644 --- a/src/win32/cairo-win32-display-surface.c +++ b/src/win32/cairo-win32-display-surface.c @@ -95,8 +95,6 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, unsigned char **bits_out, int *rowstride_out) { - cairo_status_t status; - BITMAPINFO *bitmap_info = NULL; struct { BITMAPINFOHEADER bmiHeader; @@ -201,16 +199,20 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, } surface->win32.dc = CreateCompatibleDC (original_dc); - if (!surface->win32.dc) + if (!surface->win32.dc) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateCompatibleDC"); goto FAIL; + } surface->bitmap = CreateDIBSection (surface->win32.dc, bitmap_info, DIB_RGB_COLORS, &bits, NULL, 0); - if (!surface->bitmap) + if (!surface->bitmap) { + _cairo_win32_print_gdi_error ("_create_dc_and_bitmap:CreateDIBSection"); goto FAIL; + } surface->is_dib = TRUE; @@ -218,8 +220,10 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, surface->saved_dc_bitmap = SelectObject (surface->win32.dc, surface->bitmap); - if (!surface->saved_dc_bitmap) + if (!surface->saved_dc_bitmap) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); goto FAIL; + } if (bitmap_info && num_palette > 2) free (bitmap_info); @@ -256,8 +260,6 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, return CAIRO_STATUS_SUCCESS; FAIL: - status = _cairo_win32_print_gdi_error (__FUNCTION__); - if (bitmap_info && num_palette > 2) free (bitmap_info); @@ -276,7 +278,7 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, surface->win32.dc = NULL; } - return status; + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } static cairo_surface_t * @@ -547,7 +549,7 @@ _cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags) fallback->win32.dc, surface->win32.extents.x, surface->win32.extents.y, SRCCOPY)) - status = _cairo_win32_print_gdi_error (__FUNCTION__); + status = _cairo_win32_print_gdi_error ("_cairo_win32_display_surface_flush:BitBlt"); } else if (damage->region) { int n = cairo_region_num_rectangles (damage->region), i; for (i = 0; i < n; i++) { @@ -564,7 +566,7 @@ _cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags) fallback->win32.dc, rect.x, rect.y, SRCCOPY)) { - status = _cairo_win32_print_gdi_error (__FUNCTION__); + status = _cairo_win32_print_gdi_error ("_cairo_win32_display_surface_flush:BitBlt"); break; } } @@ -615,7 +617,7 @@ _cairo_win32_save_initial_clip (HDC hdc, cairo_win32_display_surface_t *surface) clipBoxType = GetClipBox (hdc, &rect); if (clipBoxType == ERROR) { - _cairo_win32_print_gdi_error (__FUNCTION__); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetClipBox"); SetGraphicsMode (hdc, gm); /* XXX: Can we make a more reasonable guess at the error cause here? */ return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); @@ -748,8 +750,10 @@ _cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface, /* AND the new region into our DC */ status = CAIRO_STATUS_SUCCESS; - if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR) - status = _cairo_win32_print_gdi_error (__FUNCTION__); + if (ExtSelectClipRgn (surface->win32.dc, gdi_region, RGN_AND) == ERROR) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ExtSelectClipRgn"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } DeleteObject (gdi_region); diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c index 265f93294..d1ad087f9 100644 --- a/src/win32/cairo-win32-font.c +++ b/src/win32/cairo-win32-font.c @@ -159,12 +159,12 @@ _get_global_font_dc (void) if (!hdc) { hdc = CreateCompatibleDC (NULL); if (!hdc) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateCompatibleDC"); return NULL; } if (!SetGraphicsMode (hdc, GM_ADVANCED)) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetGraphicsMode"); DeleteDC (hdc); return NULL; } @@ -409,8 +409,10 @@ _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font, _cairo_matrix_to_win32_xform (&scaled_font->logical_to_device, &xform); - if (!SetWorldTransform (hdc, &xform)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_world_transform"); + if (!SetWorldTransform (hdc, &xform)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } return CAIRO_STATUS_SUCCESS; } @@ -418,8 +420,10 @@ _win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font, static cairo_status_t _win32_scaled_font_set_identity_transform (HDC hdc) { - if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_set_identity_transform"); + if (!ModifyWorldTransform (hdc, NULL, MWT_IDENTITY)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } return CAIRO_STATUS_SUCCESS; } @@ -437,8 +441,10 @@ _win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font, logfont.lfQuality = scaled_font->quality; scaled_font->scaled_hfont = CreateFontIndirectW (&logfont); - if (!scaled_font->scaled_hfont) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_scaled_hfont"); + if (!scaled_font->scaled_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateFontIndirect"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } } *hfont_out = scaled_font->scaled_hfont; @@ -462,25 +468,30 @@ _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, if (status) return status; - if (! SelectObject (hdc, scaled_hfont)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject"); + if (! SelectObject (hdc, scaled_hfont)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } otm_size = GetOutlineTextMetrics (hdc, 0, NULL); - if (! otm_size) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics"); + if (! otm_size) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetOutlineTextMetrics"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } otm = _cairo_malloc (otm_size); if (otm == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); if (! GetOutlineTextMetrics (hdc, otm_size, otm)) { - status = _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics"); - free (otm); - return status; + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetOutlineTextMetrics"); + free (otm); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } scaled_font->em_square = otm->otmEMSquare; free (otm); + otm = NULL; logfont = scaled_font->logfont; logfont.lfHeight = -scaled_font->em_square; @@ -490,8 +501,10 @@ _win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, logfont.lfQuality = scaled_font->quality; scaled_font->unscaled_hfont = CreateFontIndirectW (&logfont); - if (! scaled_font->unscaled_hfont) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:CreateIndirect"); + if (! scaled_font->unscaled_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateFontIndirect"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } } *hfont_out = scaled_font->unscaled_hfont; @@ -511,8 +524,10 @@ _cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font, return status; old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font"); + if (!old_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } status = _win32_scaled_font_set_identity_transform (hdc); if (status) { @@ -651,7 +666,7 @@ _cairo_win32_scaled_font_ucs4_to_index (void *abstract_font, unicode[0] = ucs4; unicode[1] = 0; if (GetGlyphIndicesW (hdc, unicode, 1, &glyph_index, 0) == GDI_ERROR) { - _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_ucs4_to_index:GetGlyphIndicesW"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphIndices"); glyph_index = 0; } @@ -681,7 +696,8 @@ _cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) return status; if (!GetTextMetrics (hdc, &metrics)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_set_metrics:GetTextMetrics"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetTextMetrics"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } cairo_win32_scaled_font_done_font (&scaled_font->base); @@ -766,7 +782,8 @@ _cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_f return status; if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetCharWidth32"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); width = 0; } cairo_win32_scaled_font_done_font (&scaled_font->base); @@ -965,7 +982,8 @@ _flush_glyphs (cairo_glyph_state_t *state) elements, state->glyphs.num_elements, dx_elements)) { - return _cairo_win32_print_gdi_error ("_flush_glyphs"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } _cairo_array_truncate (&state->glyphs, 0); @@ -1045,8 +1063,10 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface, cairo_status_t status, status2; int i; - if (!SaveDC (surface->dc)) - return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC"); + if (!SaveDC (surface->dc)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SaveDC"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc); if (status) @@ -1167,8 +1187,8 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, res = GetFontUnicodeRanges(hdc, NULL); if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetFontUnicodeRanges"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto exit1; } @@ -1180,8 +1200,8 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, res = GetFontUnicodeRanges(hdc, glyph_set); if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetFontUnicodeRanges"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto exit1; } @@ -1206,8 +1226,8 @@ _cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, utf16[j] = 0; if (GetGlyphIndicesW (hdc, utf16, num_glyphs, glyph_indices, 0) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetGlyphIndicesW"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphIndices"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto exit2; } @@ -1476,7 +1496,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font &metrics, 0, NULL, &matrix); if (bytesGlyph == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphOutline"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_FONT; } @@ -1489,7 +1510,8 @@ _cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), GGO_NATIVE | GGO_GLYPH_INDEX, &metrics, bytesGlyph, buffer, &matrix) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GetGlyphOutline"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_BUFFER; } @@ -1987,14 +2009,16 @@ cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, return status; old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject"); + if (!old_hfont) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } old_mode = SetGraphicsMode (hdc, GM_ADVANCED); if (!old_mode) { - status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetGraphicsMode"); SelectObject (hdc, old_hfont); - return status; + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc); diff --git a/src/win32/cairo-win32-gdi-compositor.c b/src/win32/cairo-win32-gdi-compositor.c index 268ca0100..347cd7ed5 100644 --- a/src/win32/cairo-win32-gdi-compositor.c +++ b/src/win32/cairo-win32-gdi-compositor.c @@ -166,8 +166,10 @@ fill_boxes (cairo_win32_display_surface_t *dst, fb.dc = dst->win32.dc; fb.brush = CreateSolidBrush (color_to_rgb(color)); - if (!fb.brush) - return _cairo_win32_print_gdi_error (__FUNCTION__); + if (!fb.brush) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } if (! _cairo_boxes_for_each_box (boxes, fill_box, &fb)) status = CAIRO_INT_STATUS_UNSUPPORTED; diff --git a/src/win32/cairo-win32-printing-surface.c b/src/win32/cairo-win32-printing-surface.c index 8305ede9c..c5b5f5cab 100644 --- a/src/win32/cairo-win32-printing-surface.c +++ b/src/win32/cairo-win32-printing-surface.c @@ -477,8 +477,10 @@ _cairo_win32_printing_surface_select_solid_brush (cairo_win32_printing_surface_t color = _cairo_win32_printing_surface_flatten_transparency (surface, &pattern->color); surface->brush = CreateSolidBrush (color); - if (!surface->brush) - return _cairo_win32_print_gdi_error ("_cairo_win32_surface_select_solid_brush(CreateSolidBrush)"); + if (!surface->brush) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "CreateSolidBrush"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } surface->old_brush = SelectObject (surface->win32.dc, surface->brush); return CAIRO_STATUS_SUCCESS; @@ -501,13 +503,17 @@ _cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_printing_surface_t * XFORM xform; _cairo_matrix_to_win32_xform (&surface->ctm, &xform); - if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:ModifyWorldTransform"); + if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } GetClipBox (surface->win32.dc, clip); _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform); - if (!SetWorldTransform (surface->win32.dc, &xform)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_get_clip_box:SetWorldTransform"); + if (!SetWorldTransform (surface->win32.dc, &xform)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } return CAIRO_STATUS_SUCCESS; } @@ -887,7 +893,8 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_printing_surface_ _cairo_matrix_to_win32_xform (&m, &xform); if (! SetWorldTransform (surface->win32.dc, &xform)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint_image_pattern"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_OPAQUE_IMAGE; } @@ -922,7 +929,8 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_printing_surface_ DIB_RGB_COLORS, SRCCOPY)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "StretchDIBits"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto CLEANUP_OPAQUE_IMAGE; } } @@ -996,8 +1004,10 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_printing_surface _cairo_matrix_to_win32_xform (&mat, &xform); - if (!SetWorldTransform (surface->win32.dc, &xform)) - return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:SetWorldTransform2"); + if (!SetWorldTransform (surface->win32.dc, &xform)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } GetClipBox (surface->win32.dc, &clip); @@ -1086,7 +1096,10 @@ _cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_printing_surface vert, total_verts, rect, total_rects, GRADIENT_FILL_RECT_H)) - return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:GradientFill"); + { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "GradientFill"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } free (rect); free (vert); @@ -1556,13 +1569,15 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, style->num_dashes, dash_array); if (pen == NULL) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ExtCreatePen"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } obj = SelectObject (surface->win32.dc, pen); if (obj == NULL) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectObject"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } @@ -1582,7 +1597,8 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, xform.eDy = 0.0f; if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } @@ -1590,18 +1606,21 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface, StrokePath (surface->win32.dc); } else { if (!WidenPath (surface->win32.dc)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "WidenPath"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } if (!SelectClipPath (surface->win32.dc, RGN_AND)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SelectClipPath"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } /* Return to device space to paint the pattern */ _cairo_matrix_to_win32_xform (&surface->gdi_ctm, &xform); if (!SetWorldTransform (surface->win32.dc, &xform)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:ModifyWorldTransform"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "SetWorldTransform"); + status = _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); goto cleanup_composite; } status = _cairo_win32_printing_surface_paint_pattern (surface, source, &extents.bounded); @@ -2102,8 +2121,10 @@ _cairo_win32_printing_surface_start_page (void *abstract_surface) surface->ctm.x0 = xform.eDx; surface->ctm.y0 = xform.eDy; cairo_matrix_init_identity (&surface->gdi_ctm); - if (!ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY)) - return _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_start_page:ModifyWorldTransform"); + if (!ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY)) { + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ModifyWorldTransform"); + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); + } } surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c index 6862e2090..8e22996da 100644 --- a/src/win32/cairo-win32-surface.c +++ b/src/win32/cairo-win32-surface.c @@ -319,7 +319,7 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst, num_glyphs, dxy_buf); if (!win_result) { - _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)"); + fprintf (stderr, "%s:%s\n", __FUNCTION__, "ExtTextOut"); } RestoreDC(dst->dc, -1); From 3bc6b616a46655ded95a6f5e016f43ca30be96d7 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 17:33:52 +0100 Subject: [PATCH 08/12] Win32: Rename _cairo_win32_print_gdi_error function ...to _cairo_win32_print_api_error, since it should not be used with most GDI functions. Also move the function definition to cairo-win32-system.c and change argument signature. --- src/win32/cairo-win32-display-surface.c | 6 ++--- src/win32/cairo-win32-font.c | 6 ++--- src/win32/cairo-win32-private.h | 2 +- src/win32/cairo-win32-surface.c | 35 ------------------------ src/win32/cairo-win32-system.c | 36 ++++++++++++++++++++++--- 5 files changed, 40 insertions(+), 45 deletions(-) diff --git a/src/win32/cairo-win32-display-surface.c b/src/win32/cairo-win32-display-surface.c index 8be03c03c..7f0770b4f 100644 --- a/src/win32/cairo-win32-display-surface.c +++ b/src/win32/cairo-win32-display-surface.c @@ -210,7 +210,7 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface, &bits, NULL, 0); if (!surface->bitmap) { - _cairo_win32_print_gdi_error ("_create_dc_and_bitmap:CreateDIBSection"); + _cairo_win32_print_api_error (__FUNCTION__, "CreateDIBSection"); goto FAIL; } @@ -549,7 +549,7 @@ _cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags) fallback->win32.dc, surface->win32.extents.x, surface->win32.extents.y, SRCCOPY)) - status = _cairo_win32_print_gdi_error ("_cairo_win32_display_surface_flush:BitBlt"); + status = _cairo_win32_print_api_error (__FUNCTION__, "BitBlt"); } else if (damage->region) { int n = cairo_region_num_rectangles (damage->region), i; for (i = 0; i < n; i++) { @@ -566,7 +566,7 @@ _cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags) fallback->win32.dc, rect.x, rect.y, SRCCOPY)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_display_surface_flush:BitBlt"); + status = _cairo_win32_print_api_error (__FUNCTION__, "BitBlt"); break; } } diff --git a/src/win32/cairo-win32-font.c b/src/win32/cairo-win32-font.c index d1ad087f9..1412c8bbc 100644 --- a/src/win32/cairo-win32-font.c +++ b/src/win32/cairo-win32-font.c @@ -258,7 +258,7 @@ _have_cleartype_quality (void) version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (!GetVersionEx (&version_info)) { - _cairo_win32_print_gdi_error ("_have_cleartype_quality"); + _cairo_win32_print_api_error (__FUNCTION__, "GetVersionEx"); return FALSE; } @@ -274,7 +274,7 @@ cairo_win32_get_system_text_quality (void) UINT smoothing_type; if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); + _cairo_win32_print_api_error (__FUNCTION__, "SystemParametersInfo"); return DEFAULT_QUALITY; } @@ -282,7 +282,7 @@ cairo_win32_get_system_text_quality (void) if (_have_cleartype_quality ()) { if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); + _cairo_win32_print_api_error (__FUNCTION__, "SystemParametersInfo"); return DEFAULT_QUALITY; } diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h index 4e180a81e..6dd60f1f0 100644 --- a/src/win32/cairo-win32-private.h +++ b/src/win32/cairo-win32-private.h @@ -176,7 +176,7 @@ const cairo_compositor_t * _cairo_win32_gdi_compositor_get (void); cairo_status_t -_cairo_win32_print_gdi_error (const char *context); +_cairo_win32_print_api_error (const char *context, const char *api); cairo_bool_t _cairo_surface_is_win32 (const cairo_surface_t *surface); diff --git a/src/win32/cairo-win32-surface.c b/src/win32/cairo-win32-surface.c index 8e22996da..e1ac51558 100644 --- a/src/win32/cairo-win32-surface.c +++ b/src/win32/cairo-win32-surface.c @@ -79,41 +79,6 @@ * Since: 1.0 **/ -/** - * _cairo_win32_print_gdi_error: - * @context: context string to display along with the error - * - * Helper function to dump out a human readable form of the - * current error code. - * - * Return value: A cairo status code for the error code - **/ -cairo_status_t -_cairo_win32_print_gdi_error (const char *context) -{ - void *lpMsgBuf; - DWORD last_error = GetLastError (); - - if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_IGNORE_INSERTS | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - last_error, - MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPWSTR) &lpMsgBuf, - 0, NULL)) { - fprintf (stderr, "%s: Unknown GDI error", context); - } else { - fprintf (stderr, "%s: %S", context, (wchar_t *)lpMsgBuf); - - LocalFree (lpMsgBuf); - } - - fflush (stderr); - - return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); -} - cairo_bool_t _cairo_win32_surface_get_extents (void *abstract_surface, cairo_rectangle_int_t *rectangle) diff --git a/src/win32/cairo-win32-system.c b/src/win32/cairo-win32-system.c index 01bbe89df..7163d4470 100644 --- a/src/win32/cairo-win32-system.c +++ b/src/win32/cairo-win32-system.c @@ -44,14 +44,44 @@ * And no other function should live here. */ - #include "cairoint.h" +#include + +/** + * _cairo_win32_print_api_error: + * @context: context string to display along with the error + * @api: name of the failing api + * + * Helper function to dump out a human readable form of the + * current error code. + * + * Return value: A cairo status code for the error code + **/ +cairo_status_t +_cairo_win32_print_api_error (const char *context, const char *api) +{ + const DWORD lang_id = MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT); + const DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_IGNORE_INSERTS | + FORMAT_MESSAGE_FROM_SYSTEM; + const DWORD last_error = GetLastError (); + void *lpMsgBuf = NULL; + + if (!FormatMessageW (flags, NULL, last_error, lang_id, (LPWSTR) &lpMsgBuf, 0, NULL)) { + fprintf (stderr, "%s: %s failed with error code %lu\n", context, api, last_error); + } + else { + fprintf (stderr, "%s: %s failed - %S\n", context, api, (wchar_t *)lpMsgBuf); + LocalFree (lpMsgBuf); + } + + return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); +} + #if CAIRO_MUTEX_IMPL_WIN32 #if !CAIRO_WIN32_STATIC_BUILD -#include - /* declare to avoid "no previous prototype for 'DllMain'" warning */ BOOL WINAPI DllMain (HINSTANCE hinstDLL, From 3921eb96be5071405f898ee7cd36f50a96d15a5c Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 18:01:07 +0100 Subject: [PATCH 09/12] Win32: Use TLS callback for module initialization and finalization TLS callbacks are pretty much like DllMain but work also in static builds. --- src/win32/cairo-win32-system.c | 60 ++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/src/win32/cairo-win32-system.c b/src/win32/cairo-win32-system.c index 7163d4470..ae1489ac6 100644 --- a/src/win32/cairo-win32-system.c +++ b/src/win32/cairo-win32-system.c @@ -80,20 +80,11 @@ _cairo_win32_print_api_error (const char *context, const char *api) } #if CAIRO_MUTEX_IMPL_WIN32 -#if !CAIRO_WIN32_STATIC_BUILD -/* declare to avoid "no previous prototype for 'DllMain'" warning */ -BOOL WINAPI -DllMain (HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved); - -BOOL WINAPI -DllMain (HINSTANCE hinstDLL, - DWORD fdwReason, - LPVOID lpvReserved) +static void NTAPI +cairo_win32_tls_callback (PVOID hinstance, DWORD dwReason, PVOID lpvReserved) { - switch (fdwReason) { + switch (dwReason) { case DLL_PROCESS_ATTACH: CAIRO_MUTEX_INITIALIZE (); break; @@ -102,9 +93,50 @@ DllMain (HINSTANCE hinstDLL, CAIRO_MUTEX_FINALIZE (); break; } - - return TRUE; } +#ifdef _MSC_VER + +#ifdef _M_IX86 +# define SYMBOL_PREFIX "_" +#else +# define SYMBOL_PREFIX "" #endif + +#ifdef __cplusplus +# define EXTERN_C_BEGIN extern "C" { +# define EXTERN_C_END } +# define EXTERN_CONST extern const +#else +# define EXTERN_C_BEGIN +# define EXTERN_C_END +# define EXTERN_CONST const #endif + +#define DEFINE_TLS_CALLBACK(func) \ +__pragma (section (".CRT$XLD", long, read)) \ + \ +static void NTAPI func (PVOID, DWORD, PVOID); \ + \ +EXTERN_C_BEGIN \ +__declspec (allocate (".CRT$XLD")) \ +EXTERN_CONST PIMAGE_TLS_CALLBACK _ptr_##func = func; \ +EXTERN_C_END \ + \ +__pragma (comment (linker, "/INCLUDE:" SYMBOL_PREFIX "_tls_used")) \ +__pragma (comment (linker, "/INCLUDE:" SYMBOL_PREFIX "_ptr_" #func)) + +#else /* _MSC_VER */ + +#define DEFINE_TLS_CALLBACK(func) \ +static void NTAPI func (PVOID, DWORD, PVOID); \ + \ +__attribute__ ((used, section (".CRT$XLD"))) \ +static const PIMAGE_TLS_CALLBACK _ptr_##func = func; + + +#endif /* !_MSC_VER */ + +DEFINE_TLS_CALLBACK (cairo_win32_tls_callback); + +#endif /* CAIRO_MUTEX_IMPL_WIN32 */ From 1e5740c75631310adb83992ed61438a08df914bd Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Tue, 21 Jan 2025 11:25:06 +0100 Subject: [PATCH 10/12] Revert "win32: Initialize mutexes for static builds for win32" This reverts commit 5f90f0a706206ea3b940392bf1492fead832d99b. This is not needed anymore now that we have TLS callbacks. --- src/win32/cairo-win32-device.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/win32/cairo-win32-device.c b/src/win32/cairo-win32-device.c index c55b0789e..91ef74588 100644 --- a/src/win32/cairo-win32-device.c +++ b/src/win32/cairo-win32-device.c @@ -81,8 +81,6 @@ _cairo_win32_device_get (void) { cairo_win32_device_t *device; - CAIRO_MUTEX_INITIALIZE (); - if (__cairo_win32_device) return cairo_device_reference (__cairo_win32_device); From 995c09ba67f47e17b883ac0dc4f5a849f100f600 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Tue, 21 Jan 2025 11:29:05 +0100 Subject: [PATCH 11/12] Win32: Avoid library finalization on process termination Library finalization should be done only for explicit library unloads (dlclose / FreeLibrary), not for process termination. --- src/win32/cairo-win32-system.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/win32/cairo-win32-system.c b/src/win32/cairo-win32-system.c index ae1489ac6..6ea14ebed 100644 --- a/src/win32/cairo-win32-system.c +++ b/src/win32/cairo-win32-system.c @@ -90,7 +90,9 @@ cairo_win32_tls_callback (PVOID hinstance, DWORD dwReason, PVOID lpvReserved) break; case DLL_PROCESS_DETACH: - CAIRO_MUTEX_FINALIZE (); + if (lpvReserved == NULL) { + CAIRO_MUTEX_FINALIZE (); + } break; } } From 864ede8e1a8e9205d7c75d3a6ea3360282121ba5 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Thu, 16 Jan 2025 18:08:55 +0100 Subject: [PATCH 12/12] Win32: Load system DLLs from System32 --- src/win32/cairo-dwrite-font.cpp | 3 ++- src/win32/cairo-dwrite-private.hpp | 3 ++- src/win32/cairo-win32-private.h | 3 +++ src/win32/cairo-win32-system.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp index 74d12c6a0..bc8177fd9 100644 --- a/src/win32/cairo-dwrite-font.cpp +++ b/src/win32/cairo-dwrite-font.cpp @@ -137,8 +137,9 @@ public: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif + HMODULE d2d1 = _cairo_win32_load_library_from_system32 (L"d2d1.dll"); D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc) - GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory"); + GetProcAddress(d2d1, "D2D1CreateFactory"); #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/src/win32/cairo-dwrite-private.hpp b/src/win32/cairo-dwrite-private.hpp index c7a24822a..3e0d9a14e 100644 --- a/src/win32/cairo-dwrite-private.hpp +++ b/src/win32/cairo-dwrite-private.hpp @@ -83,8 +83,9 @@ public: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wcast-function-type" #endif + HMODULE dwrite = _cairo_win32_load_library_from_system32 (L"dwrite.dll"); DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc) - GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"); + GetProcAddress(dwrite, "DWriteCreateFactory"); #ifdef __GNUC__ #pragma GCC diagnostic pop #endif diff --git a/src/win32/cairo-win32-private.h b/src/win32/cairo-win32-private.h index 6dd60f1f0..ae8dc52c3 100644 --- a/src/win32/cairo-win32-private.h +++ b/src/win32/cairo-win32-private.h @@ -237,6 +237,9 @@ _cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font); cairo_public BYTE cairo_win32_get_system_text_quality (void); +HMODULE +_cairo_win32_load_library_from_system32 (const wchar_t *name); + #if CAIRO_HAS_DWRITE_FONT cairo_int_status_t diff --git a/src/win32/cairo-win32-system.c b/src/win32/cairo-win32-system.c index 6ea14ebed..c5ef24e8d 100644 --- a/src/win32/cairo-win32-system.c +++ b/src/win32/cairo-win32-system.c @@ -79,6 +79,34 @@ _cairo_win32_print_api_error (const char *context, const char *api) return _cairo_error (CAIRO_STATUS_WIN32_GDI_ERROR); } +/** + * _cairo_win32_load_library_from_system32: + * @name: name of the module to load from System32 + * + * Helper function to load system modules in the System32 + * folder. + * + * Return value: An module HANDLE, NULL on error. + **/ +HMODULE +_cairo_win32_load_library_from_system32 (const wchar_t *name) +{ + HMODULE module_handle; + + module_handle = LoadLibraryExW (name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (module_handle == NULL) { + DWORD code = GetLastError(); + if (code == ERROR_INVALID_PARAMETER) { + /* Support for flag LOAD_LIBRARY_SEARCH_SYSTEM32 was backported + * to Windows Vista / 7 with Update KB2533623. If the flag is + * not supported, simply use LoadLibrary */ + return LoadLibraryW (name); + } + } + + return module_handle; +} + #if CAIRO_MUTEX_IMPL_WIN32 static void NTAPI