From e811c0640a48f44614e3abb7c30c2e9dbdf4769a Mon Sep 17 00:00:00 2001 From: Artur Wieczorek Date: Tue, 10 Jan 2017 21:34:51 +0100 Subject: [PATCH] Optimize creating wxCairoContext from wxMemoryDC associated with ARGB wxBitmap (MSW) Legacy API cairo_win32_surface_create() can create only 24 bpp RGB surfaces but new API cairo_win32_surface_create_with_format() introduced in 1.15.4 supports creating also 32 bpp ARGB surfaces. So, this new API can be used to create ARGB surface directly from ARGB bitmap (HDC), superseding current implementation based on the access to the bitmap data with cairo_image_surface_create_for_data(). Unfortunately, 0RGB bitmaps are not supported by cairo_win32_surface_create_with_format() and for such bitmaps surface has to be still created from bitmap data. --- docs/changes.txt | 2 ++ src/common/cairo.cpp | 2 ++ src/generic/graphicc.cpp | 28 +++++++++++++++++++++++----- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 6feb607043..1deb5a0b14 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -156,6 +156,8 @@ wxMSW: - Return null BSTR from wxIAccessible if string returned from wxAccesible method is empty. - Handle Ctrl-A in non-rich multiline text controls (Jens Göpfert). +- Use cairo_win32_surface_create_with_format() to create ARGB surface from + wxMemoryDC (Cairo >= 1.15.4). wxOSX: diff --git a/src/common/cairo.cpp b/src/common/cairo.cpp index 8baa0da911..31d38d4f09 100644 --- a/src/common/cairo.cpp +++ b/src/common/cairo.cpp @@ -185,6 +185,8 @@ #define wxCAIRO_PLATFORM_METHODS(m) \ m( cairo_surface_t*, cairo_win32_surface_create, \ (HDC hdc), (hdc), NULL ) \ + m( cairo_surface_t*, cairo_win32_surface_create_with_format, \ + (HDC hdc, cairo_format_t format), (hdc, format), NULL ) \ m( cairo_surface_t*, cairo_win32_printing_surface_create, \ (HDC hdc), (hdc), NULL ) \ m( HDC, cairo_win32_surface_get_dc, \ diff --git a/src/generic/graphicc.cpp b/src/generic/graphicc.cpp index d7026db8e5..e5583801ce 100644 --- a/src/generic/graphicc.cpp +++ b/src/generic/graphicc.cpp @@ -1881,9 +1881,17 @@ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& // transformation settings from source // wxDC to Cairo context on our own. - // cairo_win32_surface_create creates a 24-bit bitmap, - // so if we 32bpp bitmap, we need to create a 32-bit surface instead. - if ( bmp.GetDepth() == 32 ) + // Prior to 1.15.4 creating surface from HDC could be done only with + // cairo_win32_surface_create() supporting only 24 bpp RGB surface. + // So, in case of a 32 bpp ARGB bitmap, it was necessary to create + // a 32 bpp surface directly from bitmap data with cairo_image_surface_create_for_data(). + // New API cairo_win32_surface_create_with_format() introduced in 1.15.4 + // supports creating also 32 bpp ARGB surface so this function + // can be used to create a surface from both RGB and ARGB bitmaps. + // For 0RGB bitmaps, surface still has to be created in the old way, from + // bitmap data. + if ( bmp.GetDepth() == 32 && + (cairo_version() < CAIRO_VERSION_ENCODE(1, 15, 4) || !bmp.HasAlpha()) ) { #if wxUSE_WXDIB // We need to convert the currently selected bitmap to a DIB @@ -1972,7 +1980,7 @@ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& } } - // Fallback if Cairo surface hasn't been created from 32bpp bitmap. + // Fallback if Cairo surface hasn't been created from bitmap data. if( !hasBitmap ) { // When x- or y-coordinate of DC origin > 0 then surface @@ -1998,7 +2006,17 @@ wxCairoContext::wxCairoContext( wxGraphicsRenderer* renderer, const wxMemoryDC& } #endif // Cairo <= 1.15.2 - m_mswSurface = cairo_win32_surface_create(hdc); +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 15, 4) + if ( cairo_version() >= CAIRO_VERSION_ENCODE(1, 15, 4) ) + { + m_mswSurface = cairo_win32_surface_create_with_format(hdc, + bmp.HasAlpha() ? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24); + } + else +#endif // Cairo >= 1.15.4 + { + m_mswSurface = cairo_win32_surface_create(hdc); + } wxASSERT_MSG( cairo_surface_status(m_mswSurface) == CAIRO_STATUS_SUCCESS, wxS("wxCairoContext ctor - Error creating Cairo surface") ); }