From f1fe73d1909a2448a004a88362a1a532d0d4f7c3 Mon Sep 17 00:00:00 2001 From: sanine Date: Sun, 12 Feb 2023 23:53:22 -0600 Subject: switch to tinyobj and nanovg from assimp and cairo --- libs/cairo-1.16.0/src/win32/cairo-win32-debug.c | 87 - libs/cairo-1.16.0/src/win32/cairo-win32-device.c | 202 -- .../src/win32/cairo-win32-display-surface.c | 1147 ---------- libs/cairo-1.16.0/src/win32/cairo-win32-font.c | 2318 -------------------- .../src/win32/cairo-win32-gdi-compositor.c | 671 ------ .../src/win32/cairo-win32-printing-surface.c | 2226 ------------------- libs/cairo-1.16.0/src/win32/cairo-win32-private.h | 248 --- libs/cairo-1.16.0/src/win32/cairo-win32-surface.c | 334 --- libs/cairo-1.16.0/src/win32/cairo-win32-system.c | 89 - 9 files changed, 7322 deletions(-) delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-debug.c delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-device.c delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-display-surface.c delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-font.c delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-gdi-compositor.c delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-printing-surface.c delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-private.h delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-surface.c delete mode 100644 libs/cairo-1.16.0/src/win32/cairo-win32-system.c (limited to 'libs/cairo-1.16.0/src/win32') diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-debug.c b/libs/cairo-1.16.0/src/win32/cairo-win32-debug.c deleted file mode 100644 index 5a971bd..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-debug.c +++ /dev/null @@ -1,87 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2012 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Stuart Parmenter - * Vladimir Vukicevic - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" -#include "cairo-win32-private.h" - -#include -#include - -void -_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header) -{ - RGNDATA *rd; - unsigned int z; - - if (header) - fprintf (stderr, "%s\n", header); - - if (rgn == NULL) { - fprintf (stderr, " NULL\n"); - } - - z = GetRegionData(rgn, 0, NULL); - rd = (RGNDATA*) _cairo_malloc (z); - z = GetRegionData(rgn, z, rd); - - fprintf (stderr, " %ld rects, bounds: %ld %ld %ld %ld\n", - rd->rdh.nCount, - rd->rdh.rcBound.left, - rd->rdh.rcBound.top, - rd->rdh.rcBound.right - rd->rdh.rcBound.left, - rd->rdh.rcBound.bottom - rd->rdh.rcBound.top); - - for (z = 0; z < rd->rdh.nCount; z++) { - RECT r = ((RECT*)rd->Buffer)[z]; - fprintf (stderr, " [%d]: [%ld %ld %ld %ld]\n", - z, r.left, r.top, r.right - r.left, r.bottom - r.top); - } - - free(rd); - fflush (stderr); -} diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-device.c b/libs/cairo-1.16.0/src/win32/cairo-win32-device.c deleted file mode 100644 index 6fce722..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-device.c +++ /dev/null @@ -1,202 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2012 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Stuart Parmenter - * Vladimir Vukicevic - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-atomic-private.h" -#include "cairo-device-private.h" -#include "cairo-win32-private.h" - -#include -#include - -static cairo_device_t *__cairo_win32_device; - -static cairo_status_t -_cairo_win32_device_flush (void *device) -{ - GdiFlush (); - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_device_finish (void *device) -{ -} - -static void -_cairo_win32_device_destroy (void *device) -{ - free (device); -} - -static const cairo_device_backend_t _cairo_win32_device_backend = { - CAIRO_DEVICE_TYPE_WIN32, - - NULL, NULL, /* lock, unlock */ - - _cairo_win32_device_flush, - _cairo_win32_device_finish, - _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 - -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"); - - return func; -} - -cairo_device_t * -_cairo_win32_device_get (void) -{ - cairo_win32_device_t *device; - - CAIRO_MUTEX_INITIALIZE (); - - if (__cairo_win32_device) - return cairo_device_reference (__cairo_win32_device); - - device = _cairo_malloc (sizeof (*device)); - - _cairo_device_init (&device->base, &_cairo_win32_device_backend); - - 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 ((void **)&__cairo_win32_device, NULL, device)) - return cairo_device_reference(&device->base); - - _cairo_win32_device_destroy (device); - return cairo_device_reference (__cairo_win32_device); -} - -unsigned -_cairo_win32_flags_for_dc (HDC dc, cairo_format_t format) -{ - uint32_t flags = 0; - cairo_bool_t is_display = GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY; - - if (format == CAIRO_FORMAT_RGB24 || format == CAIRO_FORMAT_ARGB32) - { - int cap = GetDeviceCaps(dc, RASTERCAPS); - if (cap & RC_BITBLT) - flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT; - if (!is_display && GetDeviceCaps(dc, SHADEBLENDCAPS) != SB_NONE) - flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND; - - /* ARGB32 available operations are a strict subset of RGB24 - * available operations. This is because the same GDI functions - * can be used but most of them always reset alpha channel to 0 - * which is bad for ARGB32. - */ - if (format == CAIRO_FORMAT_RGB24) - { - flags |= CAIRO_WIN32_SURFACE_CAN_RGB_BRUSH; - if (cap & RC_STRETCHBLT) - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT; - if (cap & RC_STRETCHDIB) - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB; - } - } - - if (is_display) { - flags |= CAIRO_WIN32_SURFACE_IS_DISPLAY; - - /* These will always be possible, but the actual GetDeviceCaps - * calls will return whether they're accelerated or not. - * We may want to use our own (pixman) routines sometimes - * if they're eventually faster, but for now have GDI do - * everything. - */ -#if 0 - flags |= CAIRO_WIN32_SURFACE_CAN_BITBLT; - flags |= CAIRO_WIN32_SURFACE_CAN_ALPHABLEND; - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHBLT; - flags |= CAIRO_WIN32_SURFACE_CAN_STRETCHDIB; -#endif - } - - return flags; -} diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-display-surface.c b/libs/cairo-1.16.0/src/win32/cairo-win32-display-surface.c deleted file mode 100644 index 304d34a..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-display-surface.c +++ /dev/null @@ -1,1147 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2012 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Stuart Parmenter - * Vladimir Vukicevic - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-clip-private.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-compositor-private.h" -#include "cairo-damage-private.h" -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-inline.h" -#include "cairo-paginated-private.h" -#include "cairo-pattern-private.h" -#include "cairo-win32-private.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-surface-fallback-private.h" -#include "cairo-surface-backend-private.h" - -#include -#include - -#if defined(__MINGW32__) && !defined(ETO_PDY) -# define ETO_PDY 0x2000 -#endif - -#define PELS_72DPI ((LONG)(72. / 0.0254)) - -/** - * SECTION:cairo-win32 - * @Title: Win32 Surfaces - * @Short_Description: Microsoft Windows surface support - * @See_Also: #cairo_surface_t - * - * The Microsoft Windows surface is used to render cairo graphics to - * Microsoft Windows windows, bitmaps, and printing device contexts. - * - * The surface returned by cairo_win32_printing_surface_create() is of surface - * type %CAIRO_SURFACE_TYPE_WIN32_PRINTING and is a multi-page vector surface - * type. - * - * The surface returned by the other win32 constructors is of surface type - * %CAIRO_SURFACE_TYPE_WIN32 and is a raster surface type. - **/ - -/** - * CAIRO_HAS_WIN32_SURFACE: - * - * Defined if the Microsoft Windows surface backend is available. - * This macro can be used to conditionally compile backend-specific code. - * - * Since: 1.0 - **/ - -static const cairo_surface_backend_t cairo_win32_display_surface_backend; - -static cairo_status_t -_create_dc_and_bitmap (cairo_win32_display_surface_t *surface, - HDC original_dc, - cairo_format_t format, - int width, - int height, - unsigned char **bits_out, - int *rowstride_out) -{ - cairo_status_t status; - - BITMAPINFO *bitmap_info = NULL; - struct { - BITMAPINFOHEADER bmiHeader; - RGBQUAD bmiColors[2]; - } bmi_stack; - void *bits; - - int num_palette = 0; /* Quiet GCC */ - int i; - - surface->win32.dc = NULL; - surface->bitmap = NULL; - surface->is_dib = FALSE; - - switch (format) { - default: - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB30: - return _cairo_error (CAIRO_STATUS_INVALID_FORMAT); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - num_palette = 0; - break; - - case CAIRO_FORMAT_A8: - num_palette = 256; - break; - - case CAIRO_FORMAT_A1: - num_palette = 2; - break; - } - - if (num_palette > 2) { - bitmap_info = _cairo_malloc_ab_plus_c (num_palette, sizeof(RGBQUAD), sizeof(BITMAPINFOHEADER)); - if (!bitmap_info) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } else { - bitmap_info = (BITMAPINFO *)&bmi_stack; - } - - bitmap_info->bmiHeader.biSize = sizeof (BITMAPINFOHEADER); - bitmap_info->bmiHeader.biWidth = width == 0 ? 1 : width; - bitmap_info->bmiHeader.biHeight = height == 0 ? -1 : - height; /* top-down */ - bitmap_info->bmiHeader.biSizeImage = 0; - bitmap_info->bmiHeader.biXPelsPerMeter = PELS_72DPI; /* unused here */ - bitmap_info->bmiHeader.biYPelsPerMeter = PELS_72DPI; /* unused here */ - bitmap_info->bmiHeader.biPlanes = 1; - - switch (format) { - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB30: - ASSERT_NOT_REACHED; - /* We can't create real RGB24 bitmaps because something seems to - * break if we do, especially if we don't set up an image - * fallback. It could be a bug with using a 24bpp pixman image - * (and creating one with masks). So treat them like 32bpp. - * Note: This causes problems when using BitBlt/AlphaBlend/etc! - * see end of file. - */ - case CAIRO_FORMAT_RGB24: - case CAIRO_FORMAT_ARGB32: - bitmap_info->bmiHeader.biBitCount = 32; - bitmap_info->bmiHeader.biCompression = BI_RGB; - bitmap_info->bmiHeader.biClrUsed = 0; /* unused */ - bitmap_info->bmiHeader.biClrImportant = 0; - break; - - case CAIRO_FORMAT_A8: - bitmap_info->bmiHeader.biBitCount = 8; - bitmap_info->bmiHeader.biCompression = BI_RGB; - bitmap_info->bmiHeader.biClrUsed = 256; - bitmap_info->bmiHeader.biClrImportant = 0; - - for (i = 0; i < 256; i++) { - bitmap_info->bmiColors[i].rgbBlue = i; - bitmap_info->bmiColors[i].rgbGreen = i; - bitmap_info->bmiColors[i].rgbRed = i; - bitmap_info->bmiColors[i].rgbReserved = 0; - } - break; - - case CAIRO_FORMAT_A1: - bitmap_info->bmiHeader.biBitCount = 1; - bitmap_info->bmiHeader.biCompression = BI_RGB; - bitmap_info->bmiHeader.biClrUsed = 2; - bitmap_info->bmiHeader.biClrImportant = 0; - - for (i = 0; i < 2; i++) { - bitmap_info->bmiColors[i].rgbBlue = i * 255; - bitmap_info->bmiColors[i].rgbGreen = i * 255; - bitmap_info->bmiColors[i].rgbRed = i * 255; - bitmap_info->bmiColors[i].rgbReserved = 0; - } - break; - } - - surface->win32.dc = CreateCompatibleDC (original_dc); - if (!surface->win32.dc) - goto FAIL; - - surface->bitmap = CreateDIBSection (surface->win32.dc, - bitmap_info, - DIB_RGB_COLORS, - &bits, - NULL, 0); - if (!surface->bitmap) - goto FAIL; - - surface->is_dib = TRUE; - - GdiFlush(); - - surface->saved_dc_bitmap = SelectObject (surface->win32.dc, - surface->bitmap); - if (!surface->saved_dc_bitmap) - goto FAIL; - - if (bitmap_info && num_palette > 2) - free (bitmap_info); - - if (bits_out) - *bits_out = bits; - - if (rowstride_out) { - /* Windows bitmaps are padded to 32-bit (dword) boundaries */ - switch (format) { - case CAIRO_FORMAT_INVALID: - case CAIRO_FORMAT_RGB16_565: - case CAIRO_FORMAT_RGB30: - ASSERT_NOT_REACHED; - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - *rowstride_out = 4 * width; - break; - - case CAIRO_FORMAT_A8: - *rowstride_out = (width + 3) & ~3; - break; - - case CAIRO_FORMAT_A1: - *rowstride_out = ((width + 31) & ~31) / 8; - break; - } - } - - surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc, format); - - return CAIRO_STATUS_SUCCESS; - - FAIL: - status = _cairo_win32_print_gdi_error (__FUNCTION__); - - if (bitmap_info && num_palette > 2) - free (bitmap_info); - - if (surface->saved_dc_bitmap) { - SelectObject (surface->win32.dc, surface->saved_dc_bitmap); - surface->saved_dc_bitmap = NULL; - } - - if (surface->bitmap) { - DeleteObject (surface->bitmap); - surface->bitmap = NULL; - } - - if (surface->win32.dc) { - DeleteDC (surface->win32.dc); - surface->win32.dc = NULL; - } - - return status; -} - -static cairo_surface_t * -_cairo_win32_display_surface_create_for_dc (HDC original_dc, - cairo_format_t format, - int width, - int height) -{ - cairo_status_t status; - cairo_device_t *device; - cairo_win32_display_surface_t *surface; - unsigned char *bits; - int rowstride; - - surface = _cairo_malloc (sizeof (*surface)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - surface->fallback = NULL; - - status = _create_dc_and_bitmap (surface, original_dc, format, - width, height, - &bits, &rowstride); - if (status) - goto FAIL; - - surface->image = cairo_image_surface_create_for_data (bits, format, - width, height, rowstride); - status = surface->image->status; - if (status) - goto FAIL; - - _cairo_image_surface_set_parent (to_image_surface(surface->image), - &surface->win32.base); - - surface->win32.format = format; - - surface->win32.extents.x = 0; - surface->win32.extents.y = 0; - surface->win32.extents.width = width; - surface->win32.extents.height = height; - surface->win32.x_ofs = 0; - surface->win32.y_ofs = 0; - - surface->initial_clip_rgn = NULL; - surface->had_simple_clip = FALSE; - - device = _cairo_win32_device_get (); - - _cairo_surface_init (&surface->win32.base, - &cairo_win32_display_surface_backend, - device, - _cairo_content_from_format (format), - FALSE); /* is_vector */ - - cairo_device_destroy (device); - - return &surface->win32.base; - - FAIL: - if (surface->bitmap) { - SelectObject (surface->win32.dc, surface->saved_dc_bitmap); - DeleteObject (surface->bitmap); - DeleteDC (surface->win32.dc); - } - free (surface); - - return _cairo_surface_create_in_error (status); -} - -static cairo_surface_t * -_cairo_win32_display_surface_create_similar (void *abstract_src, - cairo_content_t content, - int width, - int height) -{ - cairo_win32_display_surface_t *src = abstract_src; - cairo_format_t format = _cairo_format_from_content (content); - cairo_surface_t *new_surf = NULL; - - /* We force a DIB always if: - * - we need alpha; or - * - the parent is a DIB; or - * - the parent is for printing (because we don't care about the - * bit depth at that point) - * - * We also might end up with a DIB even if a DDB is requested if - * DDB creation failed due to out of memory. - */ - if (!(src->is_dib || content & CAIRO_CONTENT_ALPHA)) { - /* try to create a ddb */ - new_surf = cairo_win32_surface_create_with_ddb (src->win32.dc, CAIRO_FORMAT_RGB24, width, height); - - if (new_surf->status) - new_surf = NULL; - } - - if (new_surf == NULL) { - new_surf = _cairo_win32_display_surface_create_for_dc (src->win32.dc, format, width, height); - } - - return new_surf; -} - -static cairo_surface_t * -_cairo_win32_display_surface_create_similar_image (void *abstract_other, - cairo_format_t format, - int width, - int height) -{ - cairo_win32_display_surface_t *surface = abstract_other; - cairo_image_surface_t *image; - - surface = (cairo_win32_display_surface_t *) - _cairo_win32_display_surface_create_for_dc (surface->win32.dc, - format, width, height); - if (surface->win32.base.status) - return &surface->win32.base; - - /* And clear in order to comply with our user API semantics */ - image = (cairo_image_surface_t *) surface->image; - if (! image->base.is_clear) { - memset (image->data, 0, image->stride * height); - image->base.is_clear = TRUE; - } - - return &image->base; -} - -static cairo_status_t -_cairo_win32_display_surface_finish (void *abstract_surface) -{ - cairo_win32_display_surface_t *surface = abstract_surface; - - if (surface->image && to_image_surface(surface->image)->parent) { - assert (to_image_surface(surface->image)->parent == &surface->win32.base); - /* Unhook ourselves first to avoid the double-unref from the image */ - to_image_surface(surface->image)->parent = NULL; - cairo_surface_finish (surface->image); - cairo_surface_destroy (surface->image); - } - - /* If we created the Bitmap and DC, destroy them */ - if (surface->bitmap) { - SelectObject (surface->win32.dc, surface->saved_dc_bitmap); - DeleteObject (surface->bitmap); - DeleteDC (surface->win32.dc); - } - - _cairo_win32_display_surface_discard_fallback (surface); - - if (surface->initial_clip_rgn) - DeleteObject (surface->initial_clip_rgn); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_image_surface_t * -_cairo_win32_display_surface_map_to_image (void *abstract_surface, - const cairo_rectangle_int_t *extents) -{ - cairo_win32_display_surface_t *surface = abstract_surface; - cairo_status_t status; - - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, surface->win32.base.unique_id)); - - if (surface->image) - goto done; - - if (surface->fallback == NULL) { - surface->fallback = - _cairo_win32_display_surface_create_for_dc (surface->win32.dc, - surface->win32.format, - surface->win32.extents.x + surface->win32.extents.width, - surface->win32.extents.y + surface->win32.extents.height); - if (unlikely (status = surface->fallback->status)) - goto err; - - if (!BitBlt (to_win32_surface(surface->fallback)->dc, - surface->win32.extents.x, surface->win32.extents.y, - surface->win32.extents.width, - surface->win32.extents.height, - surface->win32.dc, - surface->win32.extents.x + surface->win32.x_ofs, /* Handling multi-monitor... */ - surface->win32.extents.y + surface->win32.y_ofs, /* ... setup on Win32 */ - SRCCOPY)) { - status = _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - goto err; - } - } - - surface = to_win32_display_surface (surface->fallback); -done: - GdiFlush(); - return _cairo_surface_map_to_image (surface->image, extents); - -err: - cairo_surface_destroy (surface->fallback); - surface->fallback = NULL; - - return _cairo_image_surface_create_in_error (status); -} - -static cairo_int_status_t -_cairo_win32_display_surface_unmap_image (void *abstract_surface, - cairo_image_surface_t *image) -{ - cairo_win32_display_surface_t *surface = abstract_surface; - - /* Delay the download until the next flush, which means we also need - * to make sure our sources rare flushed. - */ - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, to_win32_surface(surface)->base.unique_id)); - - if (surface->fallback) { - cairo_rectangle_int_t r; - - r.x = image->base.device_transform_inverse.x0; - r.y = image->base.device_transform_inverse.y0; - r.width = image->width; - r.height = image->height; - - TRACE ((stderr, "%s: adding damage (%d,%d)x(%d,%d)\n", - __FUNCTION__, r.x, r.y, r.width, r.height)); - surface->fallback->damage = - _cairo_damage_add_rectangle (surface->fallback->damage, &r); - surface = to_win32_display_surface (surface->fallback); - } - - return _cairo_surface_unmap_image (surface->image, image); -} - -static cairo_status_t -_cairo_win32_display_surface_flush (void *abstract_surface, unsigned flags) -{ - cairo_win32_display_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - if (flags) - return CAIRO_STATUS_SUCCESS; - - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, surface->win32.base.unique_id)); - if (surface->fallback == NULL) - return CAIRO_STATUS_SUCCESS; - - if (surface->fallback->damage) { - cairo_win32_display_surface_t *fallback; - cairo_damage_t *damage; - - damage = _cairo_damage_reduce (surface->fallback->damage); - surface->fallback->damage = NULL; - - fallback = to_win32_display_surface (surface->fallback); - assert (fallback->image); - - TRACE ((stderr, "%s: flushing damage x %d\n", __FUNCTION__, - damage->region ? cairo_region_num_rectangles (damage->region) : 0)); - - if (damage->status) { - if (!BitBlt (surface->win32.dc, - surface->win32.extents.x + surface->win32.x_ofs, /* Handling multi-monitor... */ - surface->win32.extents.y + surface->win32.y_ofs, /* ... setup on Win32 */ - surface->win32.extents.width, - surface->win32.extents.height, - fallback->win32.dc, - surface->win32.extents.x, surface->win32.extents.y, - SRCCOPY)) - status = _cairo_win32_print_gdi_error (__FUNCTION__); - } else if (damage->region) { - int n = cairo_region_num_rectangles (damage->region), i; - for (i = 0; i < n; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (damage->region, i, &rect); - TRACE ((stderr, "%s: damage (%d,%d)x(%d,%d)\n", __FUNCTION__, - rect.x, rect.y, - rect.width, rect.height)); - if (!BitBlt (surface->win32.dc, - rect.x + surface->win32.x_ofs, /* Handling multi-monitor... */ - rect.y + surface->win32.y_ofs, /* ... setup on Win32 */ - rect.width, rect.height, - fallback->win32.dc, - rect.x, rect.y, - SRCCOPY)) { - status = _cairo_win32_print_gdi_error (__FUNCTION__); - break; - } - } - } - _cairo_damage_destroy (damage); - } else { - cairo_surface_destroy (surface->fallback); - surface->fallback = NULL; - } - - return status; -} - -static cairo_status_t -_cairo_win32_display_surface_mark_dirty (void *abstract_surface, - int x, int y, int width, int height) -{ - _cairo_win32_display_surface_discard_fallback (abstract_surface); - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_save_initial_clip (HDC hdc, cairo_win32_display_surface_t *surface) -{ - RECT rect; - int clipBoxType; - int gm; - XFORM saved_xform; - - /* GetClipBox/GetClipRgn and friends interact badly with a world transform - * set. GetClipBox returns values in logical (transformed) coordinates; - * it's unclear what GetClipRgn returns, because the region is empty in the - * case of a SIMPLEREGION clip, but I assume device (untransformed) coordinates. - * Similarly, IntersectClipRect works in logical units, whereas SelectClipRgn - * works in device units. - * - * So, avoid the whole mess and get rid of the world transform - * while we store our initial data and when we restore initial coordinates. - * - * XXX we may need to modify x/y by the ViewportOrg or WindowOrg - * here in GM_COMPATIBLE; unclear. - */ - gm = GetGraphicsMode (hdc); - if (gm == GM_ADVANCED) { - GetWorldTransform (hdc, &saved_xform); - ModifyWorldTransform (hdc, NULL, MWT_IDENTITY); - } - - clipBoxType = GetClipBox (hdc, &rect); - if (clipBoxType == ERROR) { - _cairo_win32_print_gdi_error (__FUNCTION__); - SetGraphicsMode (hdc, gm); - /* XXX: Can we make a more reasonable guess at the error cause here? */ - return _cairo_error (CAIRO_STATUS_DEVICE_ERROR); - } - - surface->win32.extents.x = rect.left; - surface->win32.extents.y = rect.top; - surface->win32.extents.width = rect.right - rect.left; - surface->win32.extents.height = rect.bottom - rect.top; - - /* On multi-monitor setup, under Windows, the primary monitor always - * have origin (0,0). Any monitors that extends to the left or above - * will have coordinates in the negative range. Take this into - * account, by forcing our Win32 surface to start at extent (0,0) and - * using a device offset. Cairo does not handle extents with negative - * offsets. - */ - surface->win32.x_ofs = 0; - surface->win32.y_ofs = 0; - if ((surface->win32.extents.x < 0) || - (surface->win32.extents.y < 0)) { - /* Negative offsets occurs for (and ONLY for) the desktop DC (virtual - * desktop), when a monitor extend to the left or above the primary - * monitor. - * - * More info @ https://www.microsoft.com/msj/0697/monitor/monitor.aspx - * - * Note that any other DC, including memory DC created with - * CreateCompatibleDC() will have extents in the - * positive range. This will be taken into account later when we perform - * raster operations between the DC (may have to perform offset - * translation). - */ - surface->win32.x_ofs = surface->win32.extents.x; - surface->win32.y_ofs = surface->win32.extents.y; - surface->win32.extents.x = 0; - surface->win32.extents.y = 0; - } - - surface->initial_clip_rgn = NULL; - surface->had_simple_clip = FALSE; - - if (clipBoxType == COMPLEXREGION) { - surface->initial_clip_rgn = CreateRectRgn (0, 0, 0, 0); - if (GetClipRgn (hdc, surface->initial_clip_rgn) <= 0) { - DeleteObject(surface->initial_clip_rgn); - surface->initial_clip_rgn = NULL; - } - } else if (clipBoxType == SIMPLEREGION) { - surface->had_simple_clip = TRUE; - } - - if (gm == GM_ADVANCED) - SetWorldTransform (hdc, &saved_xform); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_status_t -_cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface, - cairo_clip_t *clip) -{ - char stack[512]; - cairo_rectangle_int_t extents; - int num_rects; - RGNDATA *data; - size_t data_size; - RECT *rects; - int i; - HRGN gdi_region; - cairo_status_t status; - cairo_region_t *region; - - /* The semantics we want is that any clip set by cairo combines - * is intersected with the clip on device context that the - * surface was created for. To implement this, we need to - * save the original clip when first setting a clip on surface. - */ - - assert (_cairo_clip_is_region (clip)); - region = _cairo_clip_get_region (clip); - if (region == NULL) - return CAIRO_STATUS_SUCCESS; - - cairo_region_get_extents (region, &extents); - num_rects = cairo_region_num_rectangles (region); - - /* XXX see notes in _cairo_win32_save_initial_clip -- - * this code will interact badly with a HDC which had an initial - * world transform -- we should probably manually transform the - * region rects, because SelectClipRgn takes device units, not - * logical units (unlike IntersectClipRect). - */ - - data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT); - if (data_size > sizeof (stack)) { - data = _cairo_malloc (data_size); - if (!data) - return _cairo_error(CAIRO_STATUS_NO_MEMORY); - } else - data = (RGNDATA *)stack; - - data->rdh.dwSize = sizeof (RGNDATAHEADER); - data->rdh.iType = RDH_RECTANGLES; - data->rdh.nCount = num_rects; - data->rdh.nRgnSize = num_rects * sizeof (RECT); - data->rdh.rcBound.left = extents.x; - data->rdh.rcBound.top = extents.y; - data->rdh.rcBound.right = extents.x + extents.width; - data->rdh.rcBound.bottom = extents.y + extents.height; - - rects = (RECT *)data->Buffer; - for (i = 0; i < num_rects; i++) { - cairo_rectangle_int_t rect; - - cairo_region_get_rectangle (region, i, &rect); - - rects[i].left = rect.x; - rects[i].top = rect.y; - rects[i].right = rect.x + rect.width; - rects[i].bottom = rect.y + rect.height; - } - - gdi_region = ExtCreateRegion (NULL, data_size, data); - if ((char *)data != stack) - free (data); - - if (!gdi_region) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - /* 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__); - - DeleteObject (gdi_region); - - return status; -} - -void -_cairo_win32_display_surface_unset_clip (cairo_win32_display_surface_t *surface) -{ - XFORM saved_xform; - int gm = GetGraphicsMode (surface->win32.dc); - if (gm == GM_ADVANCED) { - GetWorldTransform (surface->win32.dc, &saved_xform); - ModifyWorldTransform (surface->win32.dc, NULL, MWT_IDENTITY); - } - - /* initial_clip_rgn will either be a real region or NULL (which means reset to no clip region) */ - SelectClipRgn (surface->win32.dc, surface->initial_clip_rgn); - - if (surface->had_simple_clip) { - /* then if we had a simple clip, intersect */ - IntersectClipRect (surface->win32.dc, - surface->win32.extents.x, - surface->win32.extents.y, - surface->win32.extents.x + surface->win32.extents.width, - surface->win32.extents.y + surface->win32.extents.height); - } - - if (gm == GM_ADVANCED) - SetWorldTransform (surface->win32.dc, &saved_xform); -} - -void -_cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface) -{ - if (surface->fallback) { - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, surface->win32.base.unique_id)); - - cairo_surface_finish (surface->fallback); - cairo_surface_destroy (surface->fallback); - surface->fallback = NULL; - } -} - -static cairo_int_status_t -_cairo_win32_display_surface_paint (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - cairo_win32_device_t *device = to_win32_device_from_surface (surface); - - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, to_win32_surface(surface)->base.unique_id)); - - if (clip == NULL && - (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR)) - _cairo_win32_display_surface_discard_fallback (surface); - - return _cairo_compositor_paint (device->compositor, - surface, op, source, clip); -} - -static cairo_int_status_t -_cairo_win32_display_surface_mask (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_pattern_t *mask, - const cairo_clip_t *clip) -{ - cairo_win32_device_t *device = to_win32_device_from_surface (surface); - - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, to_win32_surface(surface)->base.unique_id)); - - if (clip == NULL && op == CAIRO_OPERATOR_SOURCE) - _cairo_win32_display_surface_discard_fallback (surface); - - return _cairo_compositor_mask (device->compositor, - surface, op, source, mask, clip); -} - -static cairo_int_status_t -_cairo_win32_display_surface_stroke (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_win32_device_t *device = to_win32_device_from_surface (surface); - - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, to_win32_surface(surface)->base.unique_id)); - - return _cairo_compositor_stroke (device->compositor, surface, - op, source, path, - style, ctm, ctm_inverse, - tolerance, antialias, clip); -} - -static cairo_int_status_t -_cairo_win32_display_surface_fill (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_win32_device_t *device = to_win32_device_from_surface (surface); - - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, to_win32_surface(surface)->base.unique_id)); - - return _cairo_compositor_fill (device->compositor, surface, - op, source, path, - fill_rule, tolerance, antialias, - clip); -} - -static cairo_int_status_t -_cairo_win32_display_surface_glyphs (void *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) -{ - cairo_win32_device_t *device = to_win32_device_from_surface (surface); - - TRACE ((stderr, "%s (surface=%d)\n", - __FUNCTION__, to_win32_surface(surface)->base.unique_id)); - - return _cairo_compositor_glyphs (device->compositor, surface, - op, source, - glyphs, num_glyphs, scaled_font, - clip); -} - -static const cairo_surface_backend_t cairo_win32_display_surface_backend = { - CAIRO_SURFACE_TYPE_WIN32, - _cairo_win32_display_surface_finish, - - _cairo_default_context_create, - - _cairo_win32_display_surface_create_similar, - _cairo_win32_display_surface_create_similar_image, - _cairo_win32_display_surface_map_to_image, - _cairo_win32_display_surface_unmap_image, - - _cairo_surface_default_source, - _cairo_surface_default_acquire_source_image, - _cairo_surface_default_release_source_image, - NULL, /* snapshot */ - - NULL, /* copy_page */ - NULL, /* show_page */ - - _cairo_win32_surface_get_extents, - NULL, /* get_font_options */ - - _cairo_win32_display_surface_flush, - _cairo_win32_display_surface_mark_dirty, - - _cairo_win32_display_surface_paint, - _cairo_win32_display_surface_mask, - _cairo_win32_display_surface_stroke, - _cairo_win32_display_surface_fill, - NULL, /* fill/stroke */ - _cairo_win32_display_surface_glyphs, -}; - -/* Notes: - * - * Win32 alpha-understanding functions - * - * BitBlt - will copy full 32 bits from a 32bpp DIB to result - * (so it's safe to use for ARGB32->ARGB32 SOURCE blits) - * (but not safe going RGB24->ARGB32, if RGB24 is also represented - * as a 32bpp DIB, since the alpha isn't discarded!) - * - * AlphaBlend - if both the source and dest have alpha, even if AC_SRC_ALPHA isn't set, - * it will still copy over the src alpha, because the SCA value (255) will be - * multiplied by all the src components. - */ - -/** - * 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. - * - * Supported formats are: - * %CAIRO_FORMAT_ARGB32 - * %CAIRO_FORMAT_RGB24 - * - * 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 - **/ -cairo_surface_t * -cairo_win32_surface_create_with_format (HDC hdc, cairo_format_t format) -{ - cairo_win32_display_surface_t *surface; - - cairo_status_t status; - cairo_device_t *device; - - 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 = _cairo_malloc (sizeof (*surface)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - - status = _cairo_win32_save_initial_clip (hdc, surface); - if (status) { - free (surface); - return _cairo_surface_create_in_error (status); - } - - surface->image = NULL; - surface->fallback = NULL; - surface->win32.format = format; - - surface->win32.dc = hdc; - surface->bitmap = NULL; - surface->is_dib = FALSE; - surface->saved_dc_bitmap = NULL; - - surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc, format); - - device = _cairo_win32_device_get (); - - _cairo_surface_init (&surface->win32.base, - &cairo_win32_display_surface_backend, - device, - _cairo_content_from_format (format), - FALSE); /* is_vector */ - - cairo_device_destroy (device); - - return &surface->win32.base; -} - -/** - * 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 - * @height: height of the surface, in pixels - * - * Creates a device-independent-bitmap surface not associated with - * any particular existing surface or device context. The created - * bitmap will be uninitialized. - * - * Return value: the newly created surface - * - * Since: 1.2 - **/ -cairo_surface_t * -cairo_win32_surface_create_with_dib (cairo_format_t format, - int width, - int height) -{ - if (! CAIRO_FORMAT_VALID (format)) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT)); - - return _cairo_win32_display_surface_create_for_dc (NULL, format, width, height); -} - -/** - * cairo_win32_surface_create_with_ddb: - * @hdc: a DC compatible with the surface to create - * @format: format of pixels in the surface to create - * @width: width of the surface, in pixels - * @height: height of the surface, in pixels - * - * Creates a device-dependent-bitmap surface not associated with - * any particular existing surface or device context. The created - * bitmap will be uninitialized. - * - * Return value: the newly created surface - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_win32_surface_create_with_ddb (HDC hdc, - cairo_format_t format, - int width, - int height) -{ - cairo_win32_display_surface_t *new_surf; - HBITMAP ddb; - HDC screen_dc, ddb_dc; - HBITMAP saved_dc_bitmap; - - 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)); - case CAIRO_FORMAT_ARGB32: - case CAIRO_FORMAT_RGB24: - break; - } - - if (!hdc) { - screen_dc = GetDC (NULL); - hdc = screen_dc; - } else { - screen_dc = NULL; - } - - ddb_dc = CreateCompatibleDC (hdc); - if (ddb_dc == NULL) { - new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto FINISH; - } - - ddb = CreateCompatibleBitmap (hdc, width, height); - if (ddb == NULL) { - DeleteDC (ddb_dc); - - /* Note that if an app actually does hit this out of memory - * condition, it's going to have lots of other issues, as - * video memory is probably exhausted. However, it can often - * continue using DIBs instead of DDBs. - */ - new_surf = (cairo_win32_display_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - goto FINISH; - } - - saved_dc_bitmap = SelectObject (ddb_dc, ddb); - - new_surf = (cairo_win32_display_surface_t*) cairo_win32_surface_create (ddb_dc); - new_surf->bitmap = ddb; - new_surf->saved_dc_bitmap = saved_dc_bitmap; - new_surf->is_dib = FALSE; - -FINISH: - if (screen_dc) - ReleaseDC (NULL, screen_dc); - - return &new_surf->win32.base; -} diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-font.c b/libs/cairo-1.16.0/src/win32/cairo-win32-font.c deleted file mode 100644 index 1f21757..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-font.c +++ /dev/null @@ -1,2318 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as GetGlyphIndices */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-win32-private.h" - -#include "cairo-array-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-pattern-private.h" -#include "cairo-scaled-font-subsets-private.h" - -#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 - -/** - * SECTION:cairo-win32-fonts - * @Title: Win32 Fonts - * @Short_Description: Font support for Microsoft Windows - * @See_Also: #cairo_font_face_t - * - * The Microsoft Windows font backend is primarily used to render text on - * Microsoft Windows systems. - **/ - -/** - * CAIRO_HAS_WIN32_FONT: - * - * Defined if the Microsoft Windows font backend is available. - * This macro can be used to conditionally compile backend-specific code. - * - * Since: 1.8 - **/ - -const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend; - -typedef struct { - cairo_scaled_font_t base; - - LOGFONTW logfont; - - BYTE quality; - - /* We do drawing and metrics computation in a "logical space" which - * is similar to font space, except that it is scaled by a factor - * of the (desired font size) * (WIN32_FONT_LOGICAL_SCALE). The multiplication - * by WIN32_FONT_LOGICAL_SCALE allows for sub-pixel precision. - */ - double logical_scale; - - /* The size we should actually request the font at from Windows; differs - * from the logical_scale because it is quantized for orthogonal - * transformations - */ - double logical_size; - - /* Transformations from device <=> logical space - */ - cairo_matrix_t logical_to_device; - cairo_matrix_t device_to_logical; - - /* We special case combinations of 90-degree-rotations, scales and - * flips ... that is transformations that take the axes to the - * axes. If preserve_axes is true, then swap_axes/swap_x/swap_y - * encode the 8 possibilities for orientation (4 rotation angles with - * and without a flip), and scale_x, scale_y the scale components. - */ - cairo_bool_t preserve_axes; - cairo_bool_t swap_axes; - cairo_bool_t swap_x; - cairo_bool_t swap_y; - double x_scale; - double y_scale; - - /* The size of the design unit of the font - */ - int em_square; - - HFONT scaled_hfont; - HFONT unscaled_hfont; - - cairo_bool_t is_bitmap; - cairo_bool_t is_type1; - cairo_bool_t delete_scaled_hfont; - cairo_bool_t has_type1_notdef_index; - unsigned long type1_notdef_index; -} cairo_win32_scaled_font_t; - -static cairo_status_t -_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font); - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph); - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph); - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph); - -#define NEARLY_ZERO(d) (fabs(d) < (1. / 65536.)) - -static HDC -_get_global_font_dc (void) -{ - static HDC hdc; - - if (!hdc) { - hdc = CreateCompatibleDC (NULL); - if (!hdc) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); - return NULL; - } - - if (!SetGraphicsMode (hdc, GM_ADVANCED)) { - _cairo_win32_print_gdi_error ("_get_global_font_dc"); - DeleteDC (hdc); - return NULL; - } - } - - return hdc; -} - -static cairo_status_t -_compute_transform (cairo_win32_scaled_font_t *scaled_font, - cairo_matrix_t *sc) -{ - cairo_status_t status; - - if (NEARLY_ZERO (sc->yx) && NEARLY_ZERO (sc->xy) && - !NEARLY_ZERO(sc->xx) && !NEARLY_ZERO(sc->yy)) { - scaled_font->preserve_axes = TRUE; - scaled_font->x_scale = sc->xx; - scaled_font->swap_x = (sc->xx < 0); - scaled_font->y_scale = sc->yy; - scaled_font->swap_y = (sc->yy < 0); - scaled_font->swap_axes = FALSE; - - } else if (NEARLY_ZERO (sc->xx) && NEARLY_ZERO (sc->yy) && - !NEARLY_ZERO(sc->yx) && !NEARLY_ZERO(sc->xy)) { - scaled_font->preserve_axes = TRUE; - scaled_font->x_scale = sc->yx; - scaled_font->swap_x = (sc->yx < 0); - scaled_font->y_scale = sc->xy; - scaled_font->swap_y = (sc->xy < 0); - scaled_font->swap_axes = TRUE; - - } else { - scaled_font->preserve_axes = FALSE; - scaled_font->swap_x = scaled_font->swap_y = scaled_font->swap_axes = FALSE; - } - - if (scaled_font->preserve_axes) { - if (scaled_font->swap_x) - scaled_font->x_scale = - scaled_font->x_scale; - if (scaled_font->swap_y) - scaled_font->y_scale = - scaled_font->y_scale; - - scaled_font->logical_scale = WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale; - scaled_font->logical_size = WIN32_FONT_LOGICAL_SCALE * - _cairo_lround (scaled_font->y_scale); - } - - /* The font matrix has x and y "scale" components which we extract and - * use as character scale values. - */ - cairo_matrix_init (&scaled_font->logical_to_device, - sc->xx, sc->yx, sc->xy, sc->yy, 0, 0); - - if (!scaled_font->preserve_axes) { - status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->logical_to_device, - &scaled_font->x_scale, &scaled_font->y_scale, - TRUE); /* XXX: Handle vertical text */ - if (status) - return status; - - scaled_font->logical_size = - _cairo_lround (WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale); - scaled_font->logical_scale = - WIN32_FONT_LOGICAL_SCALE * scaled_font->y_scale; - } - - cairo_matrix_scale (&scaled_font->logical_to_device, - 1.0 / scaled_font->logical_scale, - 1.0 / scaled_font->logical_scale); - - scaled_font->device_to_logical = scaled_font->logical_to_device; - - status = cairo_matrix_invert (&scaled_font->device_to_logical); - if (status) - cairo_matrix_init_identity (&scaled_font->device_to_logical); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_have_cleartype_quality (void) -{ - OSVERSIONINFO version_info; - - version_info.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - - if (!GetVersionEx (&version_info)) { - _cairo_win32_print_gdi_error ("_have_cleartype_quality"); - return FALSE; - } - - return (version_info.dwMajorVersion > 5 || - (version_info.dwMajorVersion == 5 && - version_info.dwMinorVersion >= 1)); /* XP or newer */ -} - -static BYTE -_get_system_quality (void) -{ - BOOL font_smoothing; - UINT smoothing_type; - - if (!SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); - return DEFAULT_QUALITY; - } - - if (font_smoothing) { - if (_have_cleartype_quality ()) { - if (!SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, - 0, &smoothing_type, 0)) { - _cairo_win32_print_gdi_error ("_get_system_quality"); - return DEFAULT_QUALITY; - } - - if (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE) - return CLEARTYPE_QUALITY; - } - - return ANTIALIASED_QUALITY; - } else { - return DEFAULT_QUALITY; - } -} - -/* If face_hfont is non-%NULL then font_matrix must be a simple scale by some - * factor S, ctm must be the identity, logfont->lfHeight must be -S, - * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must - * all be 0, and face_hfont is the result of calling CreateFontIndirectW on - * logfont. - */ -static cairo_status_t -_win32_scaled_font_create (LOGFONTW *logfont, - HFONT face_hfont, - cairo_font_face_t *font_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **font_out) -{ - HDC hdc; - cairo_win32_scaled_font_t *f; - cairo_matrix_t scale; - cairo_status_t status; - - hdc = _get_global_font_dc (); - if (hdc == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - f = _cairo_malloc (sizeof(cairo_win32_scaled_font_t)); - if (f == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - f->logfont = *logfont; - - /* We don't have any control over the hinting style or subpixel - * order in the Win32 font API, so we ignore those parts of - * cairo_font_options_t. We use the 'antialias' field to set - * the 'quality'. - * - * XXX: The other option we could pay attention to, but don't - * here is the hint_metrics options. - */ - if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) - f->quality = _get_system_quality (); - else { - switch (options->antialias) { - case CAIRO_ANTIALIAS_NONE: - f->quality = NONANTIALIASED_QUALITY; - break; - case CAIRO_ANTIALIAS_GRAY: - case CAIRO_ANTIALIAS_FAST: - case CAIRO_ANTIALIAS_GOOD: - f->quality = ANTIALIASED_QUALITY; - break; - case CAIRO_ANTIALIAS_SUBPIXEL: - case CAIRO_ANTIALIAS_BEST: - if (_have_cleartype_quality ()) - f->quality = CLEARTYPE_QUALITY; - else - f->quality = ANTIALIASED_QUALITY; - break; - case CAIRO_ANTIALIAS_DEFAULT: - ASSERT_NOT_REACHED; - } - } - - f->em_square = 0; - f->scaled_hfont = NULL; - f->unscaled_hfont = NULL; - f->has_type1_notdef_index = FALSE; - - if (f->quality == logfont->lfQuality || - (logfont->lfQuality == DEFAULT_QUALITY && - options->antialias == CAIRO_ANTIALIAS_DEFAULT)) { - /* If face_hfont is non-NULL, then we can use it to avoid creating our - * own --- because the constraints on face_hfont mentioned above - * guarantee it was created in exactly the same way that - * _win32_scaled_font_get_scaled_hfont would create it. - */ - f->scaled_hfont = face_hfont; - } - /* don't delete the hfont if we're using the one passed in to us */ - f->delete_scaled_hfont = !f->scaled_hfont; - - cairo_matrix_multiply (&scale, font_matrix, ctm); - status = _compute_transform (f, &scale); - if (status) - goto FAIL; - - status = _cairo_scaled_font_init (&f->base, font_face, - font_matrix, ctm, options, - &_cairo_win32_scaled_font_backend); - if (status) - goto FAIL; - - status = _cairo_win32_scaled_font_set_metrics (f); - if (status) { - _cairo_scaled_font_fini (&f->base); - goto FAIL; - } - - *font_out = &f->base; - return CAIRO_STATUS_SUCCESS; - - FAIL: - free (f); - return status; -} - -static cairo_status_t -_win32_scaled_font_set_world_transform (cairo_win32_scaled_font_t *scaled_font, - HDC hdc) -{ - XFORM xform; - - _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"); - - return CAIRO_STATUS_SUCCESS; -} - -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"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_win32_scaled_font_get_scaled_hfont (cairo_win32_scaled_font_t *scaled_font, - HFONT *hfont_out) -{ - if (!scaled_font->scaled_hfont) { - LOGFONTW logfont = scaled_font->logfont; - logfont.lfHeight = -scaled_font->logical_size; - logfont.lfWidth = 0; - logfont.lfEscapement = 0; - logfont.lfOrientation = 0; - 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"); - } - - *hfont_out = scaled_font->scaled_hfont; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_win32_scaled_font_get_unscaled_hfont (cairo_win32_scaled_font_t *scaled_font, - HDC hdc, - HFONT *hfont_out) -{ - if (scaled_font->unscaled_hfont == NULL) { - OUTLINETEXTMETRIC *otm; - unsigned int otm_size; - HFONT scaled_hfont; - LOGFONTW logfont; - cairo_status_t status; - - status = _win32_scaled_font_get_scaled_hfont (scaled_font, - &scaled_hfont); - if (status) - return status; - - if (! SelectObject (hdc, scaled_hfont)) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:SelectObject"); - - otm_size = GetOutlineTextMetrics (hdc, 0, NULL); - if (! otm_size) - return _cairo_win32_print_gdi_error ("_win32_scaled_font_get_unscaled_hfont:GetOutlineTextMetrics"); - - 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; - } - - scaled_font->em_square = otm->otmEMSquare; - free (otm); - - logfont = scaled_font->logfont; - logfont.lfHeight = -scaled_font->em_square; - logfont.lfWidth = 0; - logfont.lfEscapement = 0; - logfont.lfOrientation = 0; - 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"); - } - - *hfont_out = scaled_font->unscaled_hfont; - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_scaled_font_select_unscaled_font (cairo_scaled_font_t *scaled_font, - HDC hdc) -{ - cairo_status_t status; - HFONT hfont; - HFONT old_hfont = NULL; - - status = _win32_scaled_font_get_unscaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, hdc, &hfont); - if (status) - return status; - - old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_select_unscaled_font"); - - status = _win32_scaled_font_set_identity_transform (hdc); - if (status) { - SelectObject (hdc, old_hfont); - return status; - } - - SetMapMode (hdc, MM_TEXT); - - return CAIRO_STATUS_SUCCESS; -} - -cairo_bool_t -_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font) -{ - cairo_win32_scaled_font_t *win32_scaled_font; - - win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font; - - return win32_scaled_font->is_type1; -} - -cairo_bool_t -_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font) -{ - cairo_win32_scaled_font_t *win32_scaled_font; - - win32_scaled_font = (cairo_win32_scaled_font_t *) scaled_font; - - return win32_scaled_font->is_bitmap; -} - -static void -_cairo_win32_scaled_font_done_unscaled_font (cairo_scaled_font_t *scaled_font) -{ -} - -/* implement the font backend interface */ - -static cairo_status_t -_cairo_win32_font_face_create_for_toy (cairo_toy_font_face_t *toy_face, - cairo_font_face_t **font_face) -{ - LOGFONTW logfont; - uint16_t *face_name; - int face_name_len; - cairo_status_t status; - - status = _cairo_utf8_to_utf16 (toy_face->family, -1, - &face_name, &face_name_len); - if (status) - return status; - - if (face_name_len > LF_FACESIZE - 1) - face_name_len = LF_FACESIZE - 1; - - memcpy (logfont.lfFaceName, face_name, sizeof (uint16_t) * face_name_len); - logfont.lfFaceName[face_name_len] = 0; - free (face_name); - - logfont.lfHeight = 0; /* filled in later */ - logfont.lfWidth = 0; /* filled in later */ - logfont.lfEscapement = 0; /* filled in later */ - logfont.lfOrientation = 0; /* filled in later */ - - switch (toy_face->weight) { - case CAIRO_FONT_WEIGHT_NORMAL: - default: - logfont.lfWeight = FW_NORMAL; - break; - case CAIRO_FONT_WEIGHT_BOLD: - logfont.lfWeight = FW_BOLD; - break; - } - - switch (toy_face->slant) { - case CAIRO_FONT_SLANT_NORMAL: - default: - logfont.lfItalic = FALSE; - break; - case CAIRO_FONT_SLANT_ITALIC: - case CAIRO_FONT_SLANT_OBLIQUE: - logfont.lfItalic = TRUE; - break; - } - - logfont.lfUnderline = FALSE; - logfont.lfStrikeOut = FALSE; - /* The docs for LOGFONT discourage using this, since the - * interpretation is locale-specific, but it's not clear what - * would be a better alternative. - */ - logfont.lfCharSet = DEFAULT_CHARSET; - logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; - logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; - logfont.lfQuality = DEFAULT_QUALITY; /* filled in later */ - logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; - - *font_face = cairo_win32_font_face_create_for_logfontw (&logfont); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_scaled_font_fini (void *abstract_font) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - - if (scaled_font == NULL) - return; - - if (scaled_font->scaled_hfont && scaled_font->delete_scaled_hfont) - DeleteObject (scaled_font->scaled_hfont); - - if (scaled_font->unscaled_hfont) - DeleteObject (scaled_font->unscaled_hfont); -} - -static cairo_int_status_t -_cairo_win32_scaled_font_type1_text_to_glyphs (cairo_win32_scaled_font_t *scaled_font, - double x, - double y, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - uint16_t *utf16; - int n16; - int i; - WORD *glyph_indices = NULL; - cairo_status_t status; - double x_pos, y_pos; - HDC hdc = NULL; - cairo_matrix_t mat; - - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); - if (status) - return status; - - glyph_indices = _cairo_malloc_ab (n16 + 1, sizeof (WORD)); - if (!glyph_indices) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL1; - } - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - goto FAIL2; - - if (GetGlyphIndicesW (hdc, utf16, n16, glyph_indices, 0) == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_type1_text_to_glyphs:GetGlyphIndicesW"); - goto FAIL3; - } - - *num_glyphs = n16; - *glyphs = _cairo_malloc_ab (n16, sizeof (cairo_glyph_t)); - if (!*glyphs) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL3; - } - - x_pos = x; - y_pos = y; - - mat = scaled_font->base.ctm; - status = cairo_matrix_invert (&mat); - assert (status == CAIRO_STATUS_SUCCESS); - - _cairo_scaled_font_freeze_cache (&scaled_font->base); - - for (i = 0; i < n16; i++) { - cairo_scaled_glyph_t *scaled_glyph; - - (*glyphs)[i].index = glyph_indices[i]; - (*glyphs)[i].x = x_pos; - (*glyphs)[i].y = y_pos; - - status = _cairo_scaled_glyph_lookup (&scaled_font->base, - glyph_indices[i], - CAIRO_SCALED_GLYPH_INFO_METRICS, - &scaled_glyph); - if (status) { - free (*glyphs); - *glyphs = NULL; - break; - } - - x = scaled_glyph->x_advance; - y = scaled_glyph->y_advance; - cairo_matrix_transform_distance (&mat, &x, &y); - x_pos += x; - y_pos += y; - } - - _cairo_scaled_font_thaw_cache (&scaled_font->base); - -FAIL3: - cairo_win32_scaled_font_done_font (&scaled_font->base); -FAIL2: - free (glyph_indices); -FAIL1: - free (utf16); - - return status; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_text_to_glyphs (void *abstract_font, - double x, - double y, - const char *utf8, - cairo_glyph_t **glyphs, - int *num_glyphs) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - uint16_t *utf16; - int n16; - GCP_RESULTSW gcp_results; - unsigned int buffer_size, i; - WCHAR *glyph_indices = NULL; - int *dx = NULL; - cairo_status_t status; - double x_pos, y_pos; - double x_incr, y_incr; - HDC hdc = NULL; - - /* GetCharacterPlacement() returns utf16 instead of glyph indices - * for Type 1 fonts. Use GetGlyphIndices for Type 1 fonts. */ - if (scaled_font->is_type1) - return _cairo_win32_scaled_font_type1_text_to_glyphs (scaled_font, - x, - y, - utf8, - glyphs, - num_glyphs); - - /* Compute a vector in user space along the baseline of length one logical space unit */ - x_incr = 1; - y_incr = 0; - cairo_matrix_transform_distance (&scaled_font->base.font_matrix, &x_incr, &y_incr); - x_incr /= scaled_font->logical_scale; - y_incr /= scaled_font->logical_scale; - - status = _cairo_utf8_to_utf16 (utf8, -1, &utf16, &n16); - if (status) - return status; - - gcp_results.lStructSize = sizeof (GCP_RESULTS); - gcp_results.lpOutString = NULL; - gcp_results.lpOrder = NULL; - gcp_results.lpCaretPos = NULL; - gcp_results.lpClass = NULL; - - buffer_size = MAX (n16 * 1.2, 16); /* Initially guess number of chars plus a few */ - if (buffer_size > INT_MAX) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL1; - } - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - goto FAIL1; - - while (TRUE) { - free (glyph_indices); - glyph_indices = NULL; - - free (dx); - dx = NULL; - - glyph_indices = _cairo_malloc_ab (buffer_size, sizeof (WCHAR)); - dx = _cairo_malloc_ab (buffer_size, sizeof (int)); - if (!glyph_indices || !dx) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - - gcp_results.nGlyphs = buffer_size; - gcp_results.lpDx = dx; - gcp_results.lpGlyphs = glyph_indices; - - if (!GetCharacterPlacementW (hdc, utf16, n16, - 0, - &gcp_results, - GCP_DIACRITIC | GCP_LIGATE | GCP_GLYPHSHAPE | GCP_REORDER)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_text_to_glyphs"); - goto FAIL2; - } - - if (gcp_results.lpDx && gcp_results.lpGlyphs) - break; - - /* Too small a buffer, try again */ - - buffer_size += buffer_size / 2; - if (buffer_size > INT_MAX) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - } - - *num_glyphs = gcp_results.nGlyphs; - *glyphs = _cairo_malloc_ab (gcp_results.nGlyphs, sizeof (cairo_glyph_t)); - if (!*glyphs) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto FAIL2; - } - - x_pos = x; - y_pos = y; - - for (i = 0; i < gcp_results.nGlyphs; i++) { - (*glyphs)[i].index = glyph_indices[i]; - (*glyphs)[i].x = x_pos ; - (*glyphs)[i].y = y_pos; - - x_pos += x_incr * dx[i]; - y_pos += y_incr * dx[i]; - } - - FAIL2: - free (glyph_indices); - free (dx); - - cairo_win32_scaled_font_done_font (&scaled_font->base); - - FAIL1: - free (utf16); - - return status; -} - -static unsigned long -_cairo_win32_scaled_font_ucs4_to_index (void *abstract_font, - uint32_t ucs4) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - wchar_t unicode[2]; - WORD glyph_index; - HDC hdc = NULL; - cairo_status_t status; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return 0; - - 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"); - glyph_index = 0; - } - - cairo_win32_scaled_font_done_font (&scaled_font->base); - - return glyph_index; -} - -static cairo_status_t -_cairo_win32_scaled_font_set_metrics (cairo_win32_scaled_font_t *scaled_font) -{ - cairo_status_t status; - cairo_font_extents_t extents; - - TEXTMETRIC metrics = {0}; - HDC hdc; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - if (scaled_font->preserve_axes || scaled_font->base.options.hint_metrics == CAIRO_HINT_METRICS_OFF) { - /* For 90-degree rotations (including 0), we get the metrics - * from the GDI in logical space, then convert back to font space - */ - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - if (!GetTextMetrics (hdc, &metrics)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_set_metrics:GetTextMetrics"); - } - - cairo_win32_scaled_font_done_font (&scaled_font->base); - if (status) - return status; - - extents.ascent = metrics.tmAscent / scaled_font->logical_scale; - extents.descent = metrics.tmDescent / scaled_font->logical_scale; - - extents.height = (metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->logical_scale; - extents.max_x_advance = metrics.tmMaxCharWidth / scaled_font->logical_scale; - extents.max_y_advance = 0; - - } else { - /* For all other transformations, we use the design metrics - * of the font. The GDI results from GetTextMetrics() on a - * transformed font are inexplicably large and we want to - * avoid them. - */ - status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); - if (status) - return status; - GetTextMetrics (hdc, &metrics); - _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); - - extents.ascent = (double)metrics.tmAscent / scaled_font->em_square; - extents.descent = (double)metrics.tmDescent / scaled_font->em_square; - extents.height = (double)(metrics.tmHeight + metrics.tmExternalLeading) / scaled_font->em_square; - extents.max_x_advance = (double)(metrics.tmMaxCharWidth) / scaled_font->em_square; - extents.max_y_advance = 0; - - } - - scaled_font->is_bitmap = !(metrics.tmPitchAndFamily & TMPF_VECTOR); - - /* Need to determine if this is a Type 1 font for the special - * handling in _text_to_glyphs. Unlike TrueType or OpenType, - * Type1 fonts do not have a "cmap" table (or any other table). - * However GetFontData() will retrieve a Type1 font when - * requesting that GetFontData() retrieve data from the start of - * the file. This is to distinguish Type1 from stroke fonts such - * as "Script" and "Modern". The TMPF_TRUETYPE test is redundant - * but improves performance for the most common fonts. - */ - scaled_font->is_type1 = FALSE; - if (!(metrics.tmPitchAndFamily & TMPF_TRUETYPE) && - (metrics.tmPitchAndFamily & TMPF_VECTOR)) - { - if ((GetFontData (hdc, CMAP_TAG, 0, NULL, 0) == GDI_ERROR) && - (GetFontData (hdc, 0, 0, NULL, 0) != GDI_ERROR)) - { - scaled_font->is_type1 = TRUE; - } - } - - return _cairo_scaled_font_set_metrics (&scaled_font->base, &extents); -} - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_metrics (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; - GLYPHMETRICS metrics; - cairo_status_t status; - cairo_text_extents_t extents; - HDC hdc; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - if (scaled_font->is_bitmap) { - /* GetGlyphOutline will not work. Assume that the glyph does not extend outside the font box. */ - cairo_font_extents_t font_extents; - INT width = 0; - UINT charIndex = _cairo_scaled_glyph_index (scaled_glyph); - - cairo_scaled_font_extents (&scaled_font->base, &font_extents); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - if (!GetCharWidth32(hdc, charIndex, charIndex, &width)) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_init_glyph_metrics:GetCharWidth32"); - width = 0; - } - cairo_win32_scaled_font_done_font (&scaled_font->base); - if (status) - return status; - - extents.x_bearing = 0; - extents.y_bearing = scaled_font->base.ctm.yy * (-font_extents.ascent / scaled_font->y_scale); - extents.width = width / (WIN32_FONT_LOGICAL_SCALE * scaled_font->x_scale); - extents.height = scaled_font->base.ctm.yy * (font_extents.ascent + font_extents.descent) / scaled_font->y_scale; - extents.x_advance = extents.width; - extents.y_advance = 0; - } else if (scaled_font->preserve_axes && scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) { - /* If we aren't rotating / skewing the axes, then we get the metrics - * from the GDI in device space and convert to font space. - */ - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix) == GDI_ERROR) { - memset (&metrics, 0, sizeof (GLYPHMETRICS)); - } else { - if (metrics.gmBlackBoxX > 0 && scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE) { - /* The bounding box reported by Windows supposedly contains the glyph's "black" area; - * however, antialiasing (especially with ClearType) means that the actual image that - * needs to be rendered may "bleed" into the adjacent pixels, mainly on the right side. - * To avoid clipping the glyphs when drawn by _cairo_surface_fallback_show_glyphs, - * for example, or other code that uses glyph extents to determine the area to update, - * we add a pixel of "slop" to left side of the nominal "black" area returned by GDI, - * and two pixels to the right (as tests show some glyphs bleed into this column). - */ - metrics.gmptGlyphOrigin.x -= 1; - metrics.gmBlackBoxX += 3; - } - } - cairo_win32_scaled_font_done_font (&scaled_font->base); - - if (scaled_font->swap_axes) { - extents.x_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; - extents.y_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; - extents.width = metrics.gmBlackBoxY / scaled_font->y_scale; - extents.height = metrics.gmBlackBoxX / scaled_font->x_scale; - extents.x_advance = metrics.gmCellIncY / scaled_font->x_scale; - extents.y_advance = metrics.gmCellIncX / scaled_font->y_scale; - } else { - extents.x_bearing = metrics.gmptGlyphOrigin.x / scaled_font->x_scale; - extents.y_bearing = - metrics.gmptGlyphOrigin.y / scaled_font->y_scale; - extents.width = metrics.gmBlackBoxX / scaled_font->x_scale; - extents.height = metrics.gmBlackBoxY / scaled_font->y_scale; - extents.x_advance = metrics.gmCellIncX / scaled_font->x_scale; - extents.y_advance = metrics.gmCellIncY / scaled_font->y_scale; - } - - if (scaled_font->swap_x) { - extents.x_bearing = (- extents.x_bearing - extents.width); - extents.x_advance = - extents.x_advance; - } - - if (scaled_font->swap_y) { - extents.y_bearing = (- extents.y_bearing - extents.height); - extents.y_advance = - extents.y_advance; - } - } else { - /* For all other transformations, we use the design metrics - * of the font. - */ - status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); - if (status) - return status; - - if (GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix) == GDI_ERROR) { - memset (&metrics, 0, sizeof (GLYPHMETRICS)); - } - _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); - - extents.x_bearing = (double)metrics.gmptGlyphOrigin.x / scaled_font->em_square; - extents.y_bearing = - (double)metrics.gmptGlyphOrigin.y / scaled_font->em_square; - extents.width = (double)metrics.gmBlackBoxX / scaled_font->em_square; - extents.height = (double)metrics.gmBlackBoxY / scaled_font->em_square; - extents.x_advance = (double)metrics.gmCellIncX / scaled_font->em_square; - extents.y_advance = (double)metrics.gmCellIncY / scaled_font->em_square; - } - - _cairo_scaled_glyph_set_metrics (scaled_glyph, - &scaled_font->base, - &extents); - - return CAIRO_STATUS_SUCCESS; -} - -/* Not currently used code, but may be useful in the future if we add - * back the capability to the scaled font backend interface to get the - * actual device space bbox rather than computing it from the - * font-space metrics. - */ -#if 0 -static cairo_status_t -_cairo_win32_scaled_font_glyph_bbox (void *abstract_font, - const cairo_glyph_t *glyphs, - int num_glyphs, - cairo_box_t *bbox) -{ - static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } }; - cairo_win32_scaled_font_t *scaled_font = abstract_font; - int x1 = 0, x2 = 0, y1 = 0, y2 = 0; - - if (num_glyphs > 0) { - HDC hdc; - GLYPHMETRICS metrics; - cairo_status_t status; - int i; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - for (i = 0; i < num_glyphs; i++) { - int x = _cairo_lround (glyphs[i].x); - int y = _cairo_lround (glyphs[i].y); - - GetGlyphOutlineW (hdc, glyphs[i].index, GGO_METRICS | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix); - - if (i == 0 || x1 > x + metrics.gmptGlyphOrigin.x) - x1 = x + metrics.gmptGlyphOrigin.x; - if (i == 0 || y1 > y - metrics.gmptGlyphOrigin.y) - y1 = y - metrics.gmptGlyphOrigin.y; - if (i == 0 || x2 < x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX) - x2 = x + metrics.gmptGlyphOrigin.x + (int)metrics.gmBlackBoxX; - if (i == 0 || y2 < y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY) - y2 = y - metrics.gmptGlyphOrigin.y + (int)metrics.gmBlackBoxY; - } - - cairo_win32_scaled_font_done_font (&scaled_font->base); - } - - bbox->p1.x = _cairo_fixed_from_int (x1); - bbox->p1.y = _cairo_fixed_from_int (y1); - bbox->p2.x = _cairo_fixed_from_int (x2); - bbox->p2.y = _cairo_fixed_from_int (y2); - - return CAIRO_STATUS_SUCCESS; -} -#endif - -typedef struct { - cairo_win32_scaled_font_t *scaled_font; - HDC hdc; - - cairo_array_t glyphs; - cairo_array_t dx; - - int start_x; - int last_x; - int last_y; -} cairo_glyph_state_t; - -static void -_start_glyphs (cairo_glyph_state_t *state, - cairo_win32_scaled_font_t *scaled_font, - HDC hdc) -{ - state->hdc = hdc; - state->scaled_font = scaled_font; - - _cairo_array_init (&state->glyphs, sizeof (WCHAR)); - _cairo_array_init (&state->dx, sizeof (int)); -} - -static cairo_status_t -_flush_glyphs (cairo_glyph_state_t *state) -{ - cairo_status_t status; - int dx = 0; - WCHAR * elements; - int * dx_elements; - - status = _cairo_array_append (&state->dx, &dx); - if (status) - return status; - - elements = _cairo_array_index (&state->glyphs, 0); - dx_elements = _cairo_array_index (&state->dx, 0); - if (!ExtTextOutW (state->hdc, - state->start_x, state->last_y, - ETO_GLYPH_INDEX, - NULL, - elements, - state->glyphs.num_elements, - dx_elements)) { - return _cairo_win32_print_gdi_error ("_flush_glyphs"); - } - - _cairo_array_truncate (&state->glyphs, 0); - _cairo_array_truncate (&state->dx, 0); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_add_glyph (cairo_glyph_state_t *state, - unsigned long index, - double device_x, - double device_y) -{ - cairo_status_t status; - double user_x = device_x; - double user_y = device_y; - WCHAR glyph_index = index; - int logical_x, logical_y; - - cairo_matrix_transform_point (&state->scaled_font->device_to_logical, &user_x, &user_y); - - logical_x = _cairo_lround (user_x); - logical_y = _cairo_lround (user_y); - - if (state->glyphs.num_elements > 0) { - int dx; - - if (logical_y != state->last_y) { - status = _flush_glyphs (state); - if (status) - return status; - state->start_x = logical_x; - } else { - dx = logical_x - state->last_x; - status = _cairo_array_append (&state->dx, &dx); - if (status) - return status; - } - } else { - state->start_x = logical_x; - } - - state->last_x = logical_x; - state->last_y = logical_y; - - status = _cairo_array_append (&state->glyphs, &glyph_index); - if (status) - return status; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_finish_glyphs (cairo_glyph_state_t *state) -{ - cairo_status_t status; - - status = _flush_glyphs (state); - - _cairo_array_fini (&state->glyphs); - _cairo_array_fini (&state->dx); - - return status; -} - -static cairo_status_t -_draw_glyphs_on_surface (cairo_win32_surface_t *surface, - cairo_win32_scaled_font_t *scaled_font, - COLORREF color, - int x_offset, - int y_offset, - const cairo_glyph_t *glyphs, - int num_glyphs) -{ - cairo_glyph_state_t state; - cairo_status_t status, status2; - int i; - - if (!SaveDC (surface->dc)) - return _cairo_win32_print_gdi_error ("_draw_glyphs_on_surface:SaveDC"); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, surface->dc); - if (status) - goto FAIL1; - - SetTextColor (surface->dc, color); - SetTextAlign (surface->dc, TA_BASELINE | TA_LEFT); - SetBkMode (surface->dc, TRANSPARENT); - - _start_glyphs (&state, scaled_font, surface->dc); - - for (i = 0; i < num_glyphs; i++) { - status = _add_glyph (&state, glyphs[i].index, - glyphs[i].x - x_offset, glyphs[i].y - y_offset); - if (status) - goto FAIL2; - } - - FAIL2: - status2 = _finish_glyphs (&state); - if (status == CAIRO_STATUS_SUCCESS) - status = status2; - - cairo_win32_scaled_font_done_font (&scaled_font->base); - FAIL1: - RestoreDC (surface->dc, -1); - - return status; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_glyph_init (void *abstract_font, - cairo_scaled_glyph_t *scaled_glyph, - cairo_scaled_glyph_info_t info) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - cairo_status_t status; - - if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) { - status = _cairo_win32_scaled_font_init_glyph_metrics (scaled_font, scaled_glyph); - if (status) - return status; - } - - if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) { - status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph); - if (status) - return status; - } - - if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) { - status = _cairo_win32_scaled_font_init_glyph_path (scaled_font, scaled_glyph); - if (status) - return status; - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_load_truetype_table (void *abstract_font, - unsigned long tag, - long offset, - unsigned char *buffer, - unsigned long *length) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - HDC hdc; - cairo_status_t status; - DWORD ret; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - tag = (tag&0x000000ff)<<24 | (tag&0x0000ff00)<<8 | (tag&0x00ff0000)>>8 | (tag&0xff000000)>>24; - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - ret = GetFontData (hdc, tag, offset, buffer, *length); - if (ret == GDI_ERROR || (buffer && ret != *length)) - status = CAIRO_INT_STATUS_UNSUPPORTED; - else - *length = ret; - - cairo_win32_scaled_font_done_font (&scaled_font->base); - - return status; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_index_to_ucs4 (void *abstract_font, - unsigned long index, - uint32_t *ucs4) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - GLYPHSET *glyph_set; - uint16_t *utf16 = NULL; - WORD *glyph_indices = NULL; - HDC hdc = NULL; - int res; - unsigned int i, j, num_glyphs; - cairo_status_t status; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - if (status) - return status; - - res = GetFontUnicodeRanges(hdc, NULL); - if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); - goto exit1; - } - - glyph_set = _cairo_malloc (res); - if (glyph_set == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto exit1; - } - - res = GetFontUnicodeRanges(hdc, glyph_set); - if (res == 0) { - status = _cairo_win32_print_gdi_error ( - "_cairo_win32_scaled_font_index_to_ucs4:GetFontUnicodeRanges"); - goto exit1; - } - - *ucs4 = (uint32_t) -1; - for (i = 0; i < glyph_set->cRanges; i++) { - num_glyphs = glyph_set->ranges[i].cGlyphs; - - utf16 = _cairo_malloc_ab (num_glyphs + 1, sizeof (uint16_t)); - if (utf16 == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto exit1; - } - - glyph_indices = _cairo_malloc_ab (num_glyphs + 1, sizeof (WORD)); - if (glyph_indices == NULL) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto exit2; - } - - for (j = 0; j < num_glyphs; j++) - utf16[j] = glyph_set->ranges[i].wcLow + j; - 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"); - goto exit2; - } - - for (j = 0; j < num_glyphs; j++) { - if (glyph_indices[j] == index) { - *ucs4 = utf16[j]; - goto exit2; - } - } - - free (glyph_indices); - glyph_indices = NULL; - free (utf16); - utf16 = NULL; - } - -exit2: - free (glyph_indices); - free (utf16); - free (glyph_set); -exit1: - cairo_win32_scaled_font_done_font (&scaled_font->base); - - return status; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_is_synthetic (void *abstract_font, - cairo_bool_t *is_synthetic) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - cairo_status_t status; - int weight; - cairo_bool_t bold; - cairo_bool_t italic; - - *is_synthetic = FALSE; - status = _cairo_truetype_get_style (&scaled_font->base, - &weight, - &bold, - &italic); - /* If this doesn't work assume it is not synthetic to avoid - * unnecessary subsetting fallbacks. */ - if (status != CAIRO_STATUS_SUCCESS) - return CAIRO_STATUS_SUCCESS; - - if (scaled_font->logfont.lfWeight != weight || - scaled_font->logfont.lfItalic != italic) - *is_synthetic = TRUE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_index_to_glyph_name (void *abstract_font, - char **glyph_names, - int num_glyph_names, - unsigned long glyph_index, - unsigned long *glyph_array_index) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - int i; - - /* Windows puts .notdef at index 0 then numbers the remaining - * glyphs starting from 1 in the order they appear in the font. */ - - /* Find the position of .notdef in the list of glyph names. We - * only need to do this once per scaled font. */ - if (! scaled_font->has_type1_notdef_index) { - for (i = 0; i < num_glyph_names; i++) { - if (strcmp (glyph_names[i], ".notdef") == 0) { - scaled_font->type1_notdef_index = i; - scaled_font->has_type1_notdef_index = TRUE; - break; - } - } - if (! scaled_font->has_type1_notdef_index) - return CAIRO_INT_STATUS_UNSUPPORTED; - } - - /* Once we know the position of .notdef the position of any glyph - * in the font can easily be obtained. */ - if (glyph_index == 0) - *glyph_array_index = scaled_font->type1_notdef_index; - else if (glyph_index <= scaled_font->type1_notdef_index) - *glyph_array_index = glyph_index - 1; - else if (glyph_index < (unsigned long)num_glyph_names) - *glyph_array_index = glyph_index; - else - return CAIRO_INT_STATUS_UNSUPPORTED; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_scaled_font_load_type1_data (void *abstract_font, - long offset, - unsigned char *buffer, - unsigned long *length) -{ - cairo_win32_scaled_font_t *scaled_font = abstract_font; - - if (! scaled_font->is_type1) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Using the tag 0 retrieves the entire font file. This works with - * Type 1 fonts as well as TTF/OTF fonts. */ - return _cairo_win32_scaled_font_load_truetype_table (scaled_font, - 0, - offset, - buffer, - length); -} - -static cairo_surface_t * -_compute_mask (cairo_surface_t *surface, - int quality) -{ - cairo_image_surface_t *glyph; - cairo_image_surface_t *mask; - int i, j; - - glyph = (cairo_image_surface_t *)cairo_surface_map_to_image (surface, NULL); - if (unlikely (glyph->base.status)) - return &glyph->base; - - if (quality == CLEARTYPE_QUALITY) { - /* Duplicate the green channel of a 4-channel mask into the - * alpha channel, then invert the whole mask. - */ - mask = (cairo_image_surface_t *) - cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - glyph->width, glyph->height); - if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) { - for (i = 0; i < glyph->height; i++) { - uint32_t *p = (uint32_t *) (glyph->data + i * glyph->stride); - uint32_t *q = (uint32_t *) (mask->data + i * mask->stride); - - for (j = 0; j < glyph->width; j++) { - *q++ = 0xffffffff ^ (*p | ((*p & 0x0000ff00) << 16)); - p++; - } - } - } - } else { - /* Compute an alpha-mask from a using the green channel of a - * (presumed monochrome) RGB24 image. - */ - mask = (cairo_image_surface_t *) - cairo_image_surface_create (CAIRO_FORMAT_A8, - glyph->width, glyph->height); - if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) { - for (i = 0; i < glyph->height; i++) { - uint32_t *p = (uint32_t *) (glyph->data + i * glyph->stride); - uint8_t *q = (uint8_t *) (mask->data + i * mask->stride); - - for (j = 0; j < glyph->width; j++) - *q++ = 255 - ((*p++ & 0x0000ff00) >> 8); - } - } - } - - cairo_surface_unmap_image (surface, &glyph->base); - return &mask->base; -} - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - cairo_status_t status; - cairo_glyph_t glyph; - cairo_surface_t *surface; - cairo_surface_t *image; - int width, height; - int x1, y1, x2, y2; - - x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x); - y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y); - x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); - y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); - width = x2 - x1; - height = y2 - y1; - - surface = cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, - width, height); - status = _cairo_surface_paint (surface, CAIRO_OPERATOR_SOURCE, - &_cairo_pattern_white.base, NULL); - if (status) - goto FAIL; - - glyph.index = _cairo_scaled_glyph_index (scaled_glyph); - glyph.x = -x1; - glyph.y = -y1; - status = _draw_glyphs_on_surface (to_win32_surface (surface), - scaled_font, RGB(0,0,0), - 0, 0, &glyph, 1); - if (status) - goto FAIL; - - image = _compute_mask (surface, scaled_font->quality); - status = image->status; - if (status) - goto FAIL; - - cairo_surface_set_device_offset (image, -x1, -y1); - _cairo_scaled_glyph_set_surface (scaled_glyph, - &scaled_font->base, - (cairo_image_surface_t *) image); - - FAIL: - cairo_surface_destroy (surface); - - return status; -} - -static void -_cairo_win32_transform_FIXED_to_fixed (cairo_matrix_t *matrix, - FIXED Fx, FIXED Fy, - cairo_fixed_t *fx, cairo_fixed_t *fy) -{ - double x = Fx.value + Fx.fract / 65536.0; - double y = Fy.value + Fy.fract / 65536.0; - cairo_matrix_transform_point (matrix, &x, &y); - *fx = _cairo_fixed_from_double (x); - *fy = _cairo_fixed_from_double (y); -} - -static cairo_status_t -_cairo_win32_scaled_font_init_glyph_path (cairo_win32_scaled_font_t *scaled_font, - cairo_scaled_glyph_t *scaled_glyph) -{ - static const MAT2 matrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, -1 } }; - cairo_status_t status; - GLYPHMETRICS metrics; - HDC hdc; - DWORD bytesGlyph; - unsigned char *buffer, *ptr; - cairo_path_fixed_t *path; - cairo_matrix_t transform; - cairo_fixed_t x, y; - - if (scaled_font->is_bitmap) - return CAIRO_INT_STATUS_UNSUPPORTED; - - hdc = _get_global_font_dc (); - assert (hdc != NULL); - - path = _cairo_path_fixed_create (); - if (!path) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) { - status = _cairo_win32_scaled_font_select_unscaled_font (&scaled_font->base, hdc); - transform = scaled_font->base.scale; - cairo_matrix_scale (&transform, 1.0/scaled_font->em_square, 1.0/scaled_font->em_square); - } else { - status = cairo_win32_scaled_font_select_font (&scaled_font->base, hdc); - cairo_matrix_init_identity(&transform); - } - if (status) - goto CLEANUP_PATH; - - bytesGlyph = GetGlyphOutlineW (hdc, _cairo_scaled_glyph_index (scaled_glyph), - GGO_NATIVE | GGO_GLYPH_INDEX, - &metrics, 0, NULL, &matrix); - - if (bytesGlyph == GDI_ERROR) { - status = _cairo_win32_print_gdi_error ("_cairo_win32_scaled_font_glyph_path"); - goto CLEANUP_FONT; - } - - ptr = buffer = _cairo_malloc (bytesGlyph); - if (!buffer && bytesGlyph != 0) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto CLEANUP_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"); - goto CLEANUP_BUFFER; - } - - while (ptr < buffer + bytesGlyph) { - TTPOLYGONHEADER *header = (TTPOLYGONHEADER *)ptr; - unsigned char *endPoly = ptr + header->cb; - - ptr += sizeof (TTPOLYGONHEADER); - - _cairo_win32_transform_FIXED_to_fixed (&transform, - header->pfxStart.x, - header->pfxStart.y, - &x, &y); - status = _cairo_path_fixed_move_to (path, x, y); - if (status) - goto CLEANUP_BUFFER; - - while (ptr < endPoly) { - TTPOLYCURVE *curve = (TTPOLYCURVE *)ptr; - POINTFX *points = curve->apfx; - int i; - switch (curve->wType) { - case TT_PRIM_LINE: - for (i = 0; i < curve->cpfx; i++) { - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i].x, - points[i].y, - &x, &y); - status = _cairo_path_fixed_line_to (path, x, y); - if (status) - goto CLEANUP_BUFFER; - } - break; - case TT_PRIM_QSPLINE: - for (i = 0; i < curve->cpfx - 1; i++) { - cairo_fixed_t p1x, p1y, p2x, p2y, cx, cy, c1x, c1y, c2x, c2y; - if (! _cairo_path_fixed_get_current_point (path, &p1x, &p1y)) - goto CLEANUP_BUFFER; - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i].x, - points[i].y, - &cx, &cy); - - if (i + 1 == curve->cpfx - 1) { - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 1].x, - points[i + 1].y, - &p2x, &p2y); - } else { - /* records with more than one curve use interpolation for - control points, per http://support.microsoft.com/kb/q87115/ */ - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 1].x, - points[i + 1].y, - &x, &y); - p2x = (cx + x) / 2; - p2y = (cy + y) / 2; - } - - c1x = 2 * cx / 3 + p1x / 3; - c1y = 2 * cy / 3 + p1y / 3; - c2x = 2 * cx / 3 + p2x / 3; - c2y = 2 * cy / 3 + p2y / 3; - - status = _cairo_path_fixed_curve_to (path, c1x, c1y, c2x, c2y, p2x, p2y); - if (status) - goto CLEANUP_BUFFER; - } - break; - case TT_PRIM_CSPLINE: - for (i = 0; i < curve->cpfx - 2; i += 2) { - cairo_fixed_t x1, y1, x2, y2; - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i].x, - points[i].y, - &x, &y); - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 1].x, - points[i + 1].y, - &x1, &y1); - _cairo_win32_transform_FIXED_to_fixed (&transform, - points[i + 2].x, - points[i + 2].y, - &x2, &y2); - status = _cairo_path_fixed_curve_to (path, x, y, x1, y1, x2, y2); - if (status) - goto CLEANUP_BUFFER; - } - break; - } - ptr += sizeof(TTPOLYCURVE) + sizeof (POINTFX) * (curve->cpfx - 1); - } - status = _cairo_path_fixed_close_path (path); - if (status) - goto CLEANUP_BUFFER; - } - - _cairo_scaled_glyph_set_path (scaled_glyph, - &scaled_font->base, - path); - - CLEANUP_BUFFER: - free (buffer); - - CLEANUP_FONT: - if (scaled_font->base.options.hint_style == CAIRO_HINT_STYLE_NONE) - _cairo_win32_scaled_font_done_unscaled_font (&scaled_font->base); - else - cairo_win32_scaled_font_done_font (&scaled_font->base); - - CLEANUP_PATH: - if (status != CAIRO_STATUS_SUCCESS) - _cairo_path_fixed_destroy (path); - - return status; -} - -const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = { - CAIRO_FONT_TYPE_WIN32, - _cairo_win32_scaled_font_fini, - _cairo_win32_scaled_font_glyph_init, - NULL, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */ - _cairo_win32_scaled_font_ucs4_to_index, - _cairo_win32_scaled_font_load_truetype_table, - _cairo_win32_scaled_font_index_to_ucs4, - _cairo_win32_scaled_font_is_synthetic, - _cairo_win32_scaled_font_index_to_glyph_name, - _cairo_win32_scaled_font_load_type1_data -}; - -/* #cairo_win32_font_face_t */ - -typedef struct _cairo_win32_font_face cairo_win32_font_face_t; - -/* If hfont is non-%NULL then logfont->lfHeight must be -S for some S, - * logfont->lfWidth, logfont->lfEscapement, logfont->lfOrientation must - * all be 0, and hfont is the result of calling CreateFontIndirectW on - * logfont. - */ -struct _cairo_win32_font_face { - cairo_font_face_t base; - LOGFONTW logfont; - HFONT hfont; -}; - -/* We maintain a hash table from LOGFONT,HFONT => #cairo_font_face_t. - * The primary purpose of this mapping is to provide unique - * #cairo_font_face_t values so that our cache and mapping from - * #cairo_font_face_t => #cairo_scaled_font_t works. Once the - * corresponding #cairo_font_face_t objects fall out of downstream - * caches, we don't need them in this hash table anymore. - * - * Modifications to this hash table are protected by - * _cairo_win32_font_face_mutex. - */ - -static cairo_hash_table_t *cairo_win32_font_face_hash_table = NULL; - -static int -_cairo_win32_font_face_keys_equal (const void *key_a, - const void *key_b); - -static void -_cairo_win32_font_face_hash_table_destroy (void) -{ - cairo_hash_table_t *hash_table; - - /* We manually acquire the lock rather than calling - * _cairo_win32_font_face_hash_table_lock simply to avoid creating - * the table only to destroy it again. */ - CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex); - hash_table = cairo_win32_font_face_hash_table; - cairo_win32_font_face_hash_table = NULL; - CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex); - - if (hash_table != NULL) - _cairo_hash_table_destroy (hash_table); -} - -static cairo_hash_table_t * -_cairo_win32_font_face_hash_table_lock (void) -{ - CAIRO_MUTEX_LOCK (_cairo_win32_font_face_mutex); - - if (unlikely (cairo_win32_font_face_hash_table == NULL)) - { - cairo_win32_font_face_hash_table = - _cairo_hash_table_create (_cairo_win32_font_face_keys_equal); - - if (unlikely (cairo_win32_font_face_hash_table == NULL)) { - CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex); - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return NULL; - } - } - - return cairo_win32_font_face_hash_table; -} - -static void -_cairo_win32_font_face_hash_table_unlock (void) -{ - CAIRO_MUTEX_UNLOCK (_cairo_win32_font_face_mutex); -} - -static cairo_bool_t -_cairo_win32_font_face_destroy (void *abstract_face) -{ - cairo_win32_font_face_t *font_face = abstract_face; - cairo_hash_table_t *hash_table; - - hash_table = _cairo_win32_font_face_hash_table_lock (); - /* All created objects must have been mapped in the hash table. */ - assert (hash_table != NULL); - - if (! _cairo_reference_count_dec_and_test (&font_face->base.ref_count)) { - /* somebody recreated the font whilst we waited for the lock */ - _cairo_win32_font_face_hash_table_unlock (); - return FALSE; - } - - /* Font faces in SUCCESS status are guaranteed to be in the - * hashtable. Font faces in an error status are removed from the - * hashtable if they are found during a lookup, thus they should - * only be removed if they are in the hashtable. */ - if (likely (font_face->base.status == CAIRO_STATUS_SUCCESS) || - _cairo_hash_table_lookup (hash_table, &font_face->base.hash_entry) == font_face) - _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry); - - _cairo_win32_font_face_hash_table_unlock (); - return TRUE; -} - -static void -_cairo_win32_font_face_init_key (cairo_win32_font_face_t *key, - LOGFONTW *logfont, - HFONT font) -{ - unsigned long hash = _CAIRO_HASH_INIT_VALUE; - - key->logfont = *logfont; - key->hfont = font; - - hash = _cairo_hash_bytes (0, logfont->lfFaceName, 2*wcslen(logfont->lfFaceName)); - hash = _cairo_hash_bytes (hash, &logfont->lfWeight, sizeof(logfont->lfWeight)); - hash = _cairo_hash_bytes (hash, &logfont->lfItalic, sizeof(logfont->lfItalic)); - - key->base.hash_entry.hash = hash; -} - -static int -_cairo_win32_font_face_keys_equal (const void *key_a, - const void *key_b) -{ - const cairo_win32_font_face_t *face_a = key_a; - const cairo_win32_font_face_t *face_b = key_b; - - if (face_a->logfont.lfWeight == face_b->logfont.lfWeight && - face_a->logfont.lfItalic == face_b->logfont.lfItalic && - face_a->logfont.lfUnderline == face_b->logfont.lfUnderline && - face_a->logfont.lfStrikeOut == face_b->logfont.lfStrikeOut && - face_a->logfont.lfCharSet == face_b->logfont.lfCharSet && - face_a->logfont.lfOutPrecision == face_b->logfont.lfOutPrecision && - face_a->logfont.lfClipPrecision == face_b->logfont.lfClipPrecision && - face_a->logfont.lfPitchAndFamily == face_b->logfont.lfPitchAndFamily && - (wcscmp (face_a->logfont.lfFaceName, face_b->logfont.lfFaceName) == 0)) - return TRUE; - else - return FALSE; -} - -/* implement the platform-specific interface */ - -static cairo_bool_t -_is_scale (const cairo_matrix_t *matrix, double scale) -{ - return matrix->xx == scale && matrix->yy == scale && - matrix->xy == 0. && matrix->yx == 0. && - matrix->x0 == 0. && matrix->y0 == 0.; -} - -static cairo_status_t -_cairo_win32_font_face_scaled_font_create (void *abstract_face, - const cairo_matrix_t *font_matrix, - const cairo_matrix_t *ctm, - const cairo_font_options_t *options, - cairo_scaled_font_t **font) -{ - HFONT hfont = NULL; - - cairo_win32_font_face_t *font_face = abstract_face; - - if (font_face->hfont) { - /* Check whether it's OK to go ahead and use the font-face's HFONT. */ - if (_is_scale (ctm, 1.) && - _is_scale (font_matrix, -font_face->logfont.lfHeight)) { - hfont = font_face->hfont; - } - } - - return _win32_scaled_font_create (&font_face->logfont, - hfont, - &font_face->base, - font_matrix, ctm, options, - font); -} - -const cairo_font_face_backend_t _cairo_win32_font_face_backend = { - CAIRO_FONT_TYPE_WIN32, - _cairo_win32_font_face_create_for_toy, - _cairo_win32_font_face_destroy, - _cairo_win32_font_face_scaled_font_create -}; - -/** - * cairo_win32_font_face_create_for_logfontw_hfont: - * @logfont: A #LOGFONTW structure specifying the font to use. - * If @font is %NULL then the lfHeight, lfWidth, lfOrientation and lfEscapement - * fields of this structure are ignored. Otherwise lfWidth, lfOrientation and - * lfEscapement must be zero. - * @font: An #HFONT that can be used when the font matrix is a scale by - * -lfHeight and the CTM is identity. - * - * Creates a new font for the Win32 font backend based on a - * #LOGFONT. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * The #cairo_scaled_font_t - * returned from cairo_scaled_font_create() is also for the Win32 backend - * and can be used with functions such as cairo_win32_scaled_font_select_font(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - * - * Since: 1.6 - **/ -cairo_font_face_t * -cairo_win32_font_face_create_for_logfontw_hfont (LOGFONTW *logfont, HFONT font) -{ - cairo_win32_font_face_t *font_face, key; - cairo_hash_table_t *hash_table; - cairo_status_t status; - - hash_table = _cairo_win32_font_face_hash_table_lock (); - if (unlikely (hash_table == NULL)) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - return (cairo_font_face_t *)&_cairo_font_face_nil; - } - - _cairo_win32_font_face_init_key (&key, logfont, font); - - /* Return existing unscaled font if it exists in the hash table. */ - font_face = _cairo_hash_table_lookup (hash_table, - &key.base.hash_entry); - if (font_face != NULL) { - if (font_face->base.status == CAIRO_STATUS_SUCCESS) { - cairo_font_face_reference (&font_face->base); - _cairo_win32_font_face_hash_table_unlock (); - return &font_face->base; - } - - /* remove the bad font from the hash table */ - _cairo_hash_table_remove (hash_table, &font_face->base.hash_entry); - } - - /* Otherwise create it and insert into hash table. */ - font_face = _cairo_malloc (sizeof (cairo_win32_font_face_t)); - if (!font_face) { - _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); - goto FAIL; - } - - _cairo_win32_font_face_init_key (font_face, logfont, font); - _cairo_font_face_init (&font_face->base, &_cairo_win32_font_face_backend); - - assert (font_face->base.hash_entry.hash == key.base.hash_entry.hash); - status = _cairo_hash_table_insert (hash_table, - &font_face->base.hash_entry); - if (unlikely (status)) - goto FAIL; - - _cairo_win32_font_face_hash_table_unlock (); - return &font_face->base; - -FAIL: - _cairo_win32_font_face_hash_table_unlock (); - return (cairo_font_face_t *)&_cairo_font_face_nil; -} - -/** - * cairo_win32_font_face_create_for_logfontw: - * @logfont: A #LOGFONTW structure specifying the font to use. - * The lfHeight, lfWidth, lfOrientation and lfEscapement - * fields of this structure are ignored. - * - * Creates a new font for the Win32 font backend based on a - * #LOGFONT. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * The #cairo_scaled_font_t - * returned from cairo_scaled_font_create() is also for the Win32 backend - * and can be used with functions such as cairo_win32_scaled_font_select_font(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - * - * Since: 1.0 - **/ -cairo_font_face_t * -cairo_win32_font_face_create_for_logfontw (LOGFONTW *logfont) -{ - return cairo_win32_font_face_create_for_logfontw_hfont (logfont, NULL); -} - -/** - * cairo_win32_font_face_create_for_hfont: - * @font: An #HFONT structure specifying the font to use. - * - * Creates a new font for the Win32 font backend based on a - * #HFONT. This font can then be used with - * cairo_set_font_face() or cairo_scaled_font_create(). - * The #cairo_scaled_font_t - * returned from cairo_scaled_font_create() is also for the Win32 backend - * and can be used with functions such as cairo_win32_scaled_font_select_font(). - * - * Return value: a newly created #cairo_font_face_t. Free with - * cairo_font_face_destroy() when you are done using it. - * - * Since: 1.2 - **/ -cairo_font_face_t * -cairo_win32_font_face_create_for_hfont (HFONT font) -{ - LOGFONTW logfont; - GetObjectW (font, sizeof(logfont), &logfont); - - if (logfont.lfEscapement != 0 || logfont.lfOrientation != 0 || - logfont.lfWidth != 0) { - /* We can't use this font because that optimization requires that - * lfEscapement, lfOrientation and lfWidth be zero. */ - font = NULL; - } - - return cairo_win32_font_face_create_for_logfontw_hfont (&logfont, font); -} - -static cairo_bool_t -_cairo_scaled_font_is_win32 (cairo_scaled_font_t *scaled_font) -{ - return scaled_font->backend == &_cairo_win32_scaled_font_backend; -} - -/** - * cairo_win32_scaled_font_select_font: - * @scaled_font: A #cairo_scaled_font_t from the Win32 font backend. Such an - * object can be created with cairo_win32_font_face_create_for_logfontw(). - * @hdc: a device context - * - * Selects the font into the given device context and changes the - * map mode and world transformation of the device context to match - * that of the font. This function is intended for use when using - * layout APIs such as Uniscribe to do text layout with the - * cairo font. After finishing using the device context, you must call - * cairo_win32_scaled_font_done_font() to release any resources allocated - * by this function. - * - * See cairo_win32_scaled_font_get_metrics_factor() for converting logical - * coordinates from the device context to font space. - * - * Normally, calls to SaveDC() and RestoreDC() would be made around - * the use of this function to preserve the original graphics state. - * - * Return value: %CAIRO_STATUS_SUCCESS if the operation succeeded. - * otherwise an error such as %CAIRO_STATUS_NO_MEMORY and - * the device context is unchanged. - * - * Since: 1.0 - **/ -cairo_status_t -cairo_win32_scaled_font_select_font (cairo_scaled_font_t *scaled_font, - HDC hdc) -{ - cairo_status_t status; - HFONT hfont; - HFONT old_hfont = NULL; - int old_mode; - - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - return _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH); - } - - if (scaled_font->status) - return scaled_font->status; - - status = _win32_scaled_font_get_scaled_hfont ((cairo_win32_scaled_font_t *)scaled_font, &hfont); - if (status) - return status; - - old_hfont = SelectObject (hdc, hfont); - if (!old_hfont) - return _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SelectObject"); - - old_mode = SetGraphicsMode (hdc, GM_ADVANCED); - if (!old_mode) { - status = _cairo_win32_print_gdi_error ("cairo_win32_scaled_font_select_font:SetGraphicsMode"); - SelectObject (hdc, old_hfont); - return status; - } - - status = _win32_scaled_font_set_world_transform ((cairo_win32_scaled_font_t *)scaled_font, hdc); - if (status) { - SetGraphicsMode (hdc, old_mode); - SelectObject (hdc, old_hfont); - return status; - } - - SetMapMode (hdc, MM_TEXT); - - return CAIRO_STATUS_SUCCESS; -} - -/** - * cairo_win32_scaled_font_done_font: - * @scaled_font: A scaled font from the Win32 font backend. - * - * Releases any resources allocated by cairo_win32_scaled_font_select_font() - * - * Since: 1.0 - **/ -void -cairo_win32_scaled_font_done_font (cairo_scaled_font_t *scaled_font) -{ - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - } -} - -/** - * cairo_win32_scaled_font_get_metrics_factor: - * @scaled_font: a scaled font from the Win32 font backend - * - * Gets a scale factor between logical coordinates in the coordinate - * space used by cairo_win32_scaled_font_select_font() (that is, the - * coordinate system used by the Windows functions to return metrics) and - * font space coordinates. - * - * Return value: factor to multiply logical units by to get font space - * coordinates. - * - * Since: 1.0 - **/ -double -cairo_win32_scaled_font_get_metrics_factor (cairo_scaled_font_t *scaled_font) -{ - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - return 1.; - } - return 1. / ((cairo_win32_scaled_font_t *)scaled_font)->logical_scale; -} - -/** - * cairo_win32_scaled_font_get_logical_to_device: - * @scaled_font: a scaled font from the Win32 font backend - * @logical_to_device: matrix to return - * - * Gets the transformation mapping the logical space used by @scaled_font - * to device space. - * - * Since: 1.4 - **/ -void -cairo_win32_scaled_font_get_logical_to_device (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *logical_to_device) -{ - cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font; - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - cairo_matrix_init_identity (logical_to_device); - return; - } - *logical_to_device = win_font->logical_to_device; -} - -/** - * cairo_win32_scaled_font_get_device_to_logical: - * @scaled_font: a scaled font from the Win32 font backend - * @device_to_logical: matrix to return - * - * Gets the transformation mapping device space to the logical space - * used by @scaled_font. - * - * Since: 1.4 - **/ -void -cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font, - cairo_matrix_t *device_to_logical) -{ - cairo_win32_scaled_font_t *win_font = (cairo_win32_scaled_font_t *)scaled_font; - if (! _cairo_scaled_font_is_win32 (scaled_font)) { - _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH); - cairo_matrix_init_identity (device_to_logical); - return; - } - *device_to_logical = win_font->device_to_logical; -} - -void -_cairo_win32_font_reset_static_data (void) -{ - _cairo_win32_font_face_hash_table_destroy (); -} diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-gdi-compositor.c b/libs/cairo-1.16.0/src/win32/cairo-win32-gdi-compositor.c deleted file mode 100644 index 1d1d7f8..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-gdi-compositor.c +++ /dev/null @@ -1,671 +0,0 @@ -/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2012 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is University of Southern - * California. - * - * Contributor(s): - * Carl D. Worth - * Behdad Esfahbod - * Chris Wilson - * Karl Tomlinson , Mozilla Corporation - */ - -/* The original X drawing API was very restrictive in what it could handle, - * pixel-aligned fill/blits are all that map into Cairo's drawing model. - */ - -#include "cairoint.h" - -#include "cairo-win32-private.h" - -#include "cairo-boxes-private.h" -#include "cairo-clip-inline.h" -#include "cairo-compositor-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-pattern-private.h" -#include "cairo-region-private.h" -#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 */ - -struct fill_box { - HDC dc; - HBRUSH brush; -}; - -static cairo_bool_t fill_box (cairo_box_t *box, void *closure) -{ - struct fill_box *fb = closure; - RECT rect; - - rect.left = _cairo_fixed_integer_part (box->p1.x); - rect.top = _cairo_fixed_integer_part (box->p1.y); - rect.right = _cairo_fixed_integer_part (box->p2.x); - rect.bottom = _cairo_fixed_integer_part (box->p2.y); - - TRACE ((stderr, "%s\n", __FUNCTION__)); - return FillRect (fb->dc, &rect, fb->brush); -} - -struct check_box { - cairo_rectangle_int_t limit; - int tx, ty; -}; - -struct copy_box { - cairo_rectangle_int_t limit; - 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) -{ - const struct copy_box *cb = closure; - int x = _cairo_fixed_integer_part (box->p1.x); - int y = _cairo_fixed_integer_part (box->p1.y); - int width = _cairo_fixed_integer_part (box->p2.x - box->p1.x); - int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y); - - TRACE ((stderr, "%s\n", __FUNCTION__)); - return BitBlt (cb->dst, x, y, width, height, - cb->src, x + cb->tx, y + cb->ty, - SRCCOPY); -} - -static cairo_bool_t alpha_box (cairo_box_t *box, void *closure) -{ - const struct copy_box *cb = closure; - int x = _cairo_fixed_integer_part (box->p1.x); - int y = _cairo_fixed_integer_part (box->p1.y); - int width = _cairo_fixed_integer_part (box->p2.x - box->p1.x); - 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); -} - -struct upload_box { - cairo_rectangle_int_t limit; - int tx, ty; - HDC dst; - BITMAPINFO bi; - void *data; -}; - -static cairo_bool_t upload_box (cairo_box_t *box, void *closure) -{ - const struct upload_box *cb = closure; - int x = _cairo_fixed_integer_part (box->p1.x); - int y = _cairo_fixed_integer_part (box->p1.y); - int width = _cairo_fixed_integer_part (box->p2.x - box->p1.x); - int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y); - int src_height = -cb->bi.bmiHeader.biHeight; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - return StretchDIBits (cb->dst, x, y + height - 1, width, -height, - x + cb->tx, src_height - (y + cb->ty - 1), - width, -height, - cb->data, &cb->bi, - DIB_RGB_COLORS, SRCCOPY); -} - -/* the mid-level: converts boxes into drawing operations */ - -static COLORREF color_to_rgb(const cairo_color_t *c) -{ - return RGB (c->red_short >> 8, c->green_short >> 8, c->blue_short >> 8); -} - -static cairo_int_status_t -fill_boxes (cairo_win32_display_surface_t *dst, - const cairo_pattern_t *src, - cairo_boxes_t *boxes) -{ - const cairo_color_t *color = &((cairo_solid_pattern_t *) src)->color; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - struct fill_box fb; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_RGB_BRUSH) == 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - fb.dc = dst->win32.dc; - fb.brush = CreateSolidBrush (color_to_rgb(color)); - if (!fb.brush) - return _cairo_win32_print_gdi_error (__FUNCTION__); - - if (! _cairo_boxes_for_each_box (boxes, fill_box, &fb)) - status = CAIRO_INT_STATUS_UNSUPPORTED; - - DeleteObject (fb.brush); - - return status; -} - -static cairo_bool_t source_contains_box (cairo_box_t *box, void *closure) -{ - struct check_box *data = closure; - - /* The box is pixel-aligned so the truncation is safe. */ - return - _cairo_fixed_integer_part (box->p1.x) + data->tx >= data->limit.x && - _cairo_fixed_integer_part (box->p1.y) + data->ty >= data->limit.y && - _cairo_fixed_integer_part (box->p2.x) + data->tx <= data->limit.x + data->limit.width && - _cairo_fixed_integer_part (box->p2.y) + data->ty <= data->limit.y + data->limit.height; -} - -static cairo_status_t -copy_boxes (cairo_win32_display_surface_t *dst, - const cairo_pattern_t *source, - cairo_boxes_t *boxes) -{ - const cairo_surface_pattern_t *pattern; - struct copy_box cb; - cairo_surface_t *surface; - cairo_status_t status; - cairo_win32_surface_t *src; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - pattern = (const cairo_surface_pattern_t *) source; - surface = _cairo_surface_get_source (pattern->surface, &cb.limit); - if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) { - surface = to_image_surface(surface)->parent; - if (surface == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - } - if (surface->type != CAIRO_SURFACE_TYPE_WIN32) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_matrix_is_integer_translation (&source->matrix, - &cb.tx, &cb.ty)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - src = to_win32_surface(surface); - - if (src->format != dst->win32.format && - !(src->format == CAIRO_FORMAT_ARGB32 && dst->win32.format == CAIRO_FORMAT_RGB24)) - { - /* forbid copy different surfaces unless it is from argb32 to - * rgb (dropping alpha) */ - return CAIRO_INT_STATUS_UNSUPPORTED; - } - cb.dst = dst->win32.dc; - cb.src = src->dc; - - /* First check that the data is entirely within the image */ - if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = __cairo_surface_flush (surface, 0); - if (status) - return status; - - cb.tx += cb.limit.x; - cb.ty += cb.limit.y; - status = CAIRO_STATUS_SUCCESS; - if (! _cairo_boxes_for_each_box (boxes, copy_box, &cb)) - status = CAIRO_INT_STATUS_UNSUPPORTED; - - _cairo_win32_display_surface_discard_fallback (dst); - return status; -} - -static cairo_status_t -upload_boxes (cairo_win32_display_surface_t *dst, - const cairo_pattern_t *source, - cairo_boxes_t *boxes) -{ - const cairo_surface_pattern_t *pattern; - struct upload_box cb; - cairo_surface_t *surface; - cairo_image_surface_t *image; - void *image_extra; - cairo_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB) == 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_matrix_is_integer_translation (&source->matrix, - &cb.tx, &cb.ty)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - pattern = (const cairo_surface_pattern_t *) source; - surface = _cairo_surface_get_source (pattern->surface, &cb.limit); - - /* First check that the data is entirely within the image */ - if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->type != CAIRO_SURFACE_TYPE_IMAGE) { - status = _cairo_surface_acquire_source_image (surface, - &image, &image_extra); - if (status) - return status; - } else - image = to_image_surface(surface); - - status = CAIRO_INT_STATUS_UNSUPPORTED; - if (!(image->format == CAIRO_FORMAT_ARGB32 || - image->format == CAIRO_FORMAT_RGB24)) - goto err; - if (image->stride != 4*image->width) - goto err; - - cb.dst = dst->win32.dc; - cb.data = image->data; - - cb.bi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER); - cb.bi.bmiHeader.biWidth = image->width; - cb.bi.bmiHeader.biHeight = -image->height; - cb.bi.bmiHeader.biSizeImage = 0; - cb.bi.bmiHeader.biXPelsPerMeter = PELS_72DPI; - cb.bi.bmiHeader.biYPelsPerMeter = PELS_72DPI; - cb.bi.bmiHeader.biPlanes = 1; - cb.bi.bmiHeader.biBitCount = 32; - cb.bi.bmiHeader.biCompression = BI_RGB; - cb.bi.bmiHeader.biClrUsed = 0; - cb.bi.bmiHeader.biClrImportant = 0; - - cb.tx += cb.limit.x; - cb.ty += cb.limit.y; - status = CAIRO_STATUS_SUCCESS; - if (! _cairo_boxes_for_each_box (boxes, upload_box, &cb)) - status = CAIRO_INT_STATUS_UNSUPPORTED; - - _cairo_win32_display_surface_discard_fallback (dst); -err: - if (&image->base != surface) - _cairo_surface_release_source_image (surface, image, image_extra); - - return status; -} - -static cairo_status_t -alpha_blend_boxes (cairo_win32_display_surface_t *dst, - const cairo_pattern_t *source, - cairo_boxes_t *boxes, - uint8_t alpha) -{ - const cairo_surface_pattern_t *pattern; - struct copy_box cb; - cairo_surface_t *surface; - cairo_win32_display_surface_t *src; - cairo_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - if (source->type != CAIRO_PATTERN_TYPE_SURFACE) - return CAIRO_INT_STATUS_UNSUPPORTED; - - pattern = (const cairo_surface_pattern_t *) source; - surface = _cairo_surface_get_source (pattern->surface, &cb.limit); - if (surface->type == CAIRO_SURFACE_TYPE_IMAGE) { - surface = to_image_surface(surface)->parent; - if (surface == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - } - if (surface->type != CAIRO_SURFACE_TYPE_WIN32) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (! _cairo_matrix_is_integer_translation (&source->matrix, - &cb.tx, &cb.ty)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - src = to_win32_display_surface (surface); - cb.dst = dst->win32.dc; - cb.src = src->win32.dc; - - /* First check that the data is entirely within the image */ - if (! _cairo_boxes_for_each_box (boxes, source_contains_box, &cb)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = __cairo_surface_flush (&src->win32.base, 0); - if (status) - return status; - - cb.bf.BlendOp = AC_SRC_OVER; - 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; - status = CAIRO_STATUS_SUCCESS; - if (! _cairo_boxes_for_each_box (boxes, alpha_box, &cb)) - status = CAIRO_INT_STATUS_UNSUPPORTED; - - _cairo_win32_display_surface_discard_fallback (dst); - return status; -} - -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; -} - -static cairo_status_t -draw_boxes (cairo_composite_rectangles_t *composite, - cairo_boxes_t *boxes) -{ - cairo_win32_display_surface_t *dst = to_win32_display_surface(composite->surface); - cairo_operator_t op = composite->op; - const cairo_pattern_t *src = &composite->source_pattern.base; - cairo_int_status_t status; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - if (boxes->num_boxes == 0 && composite->is_bounded) - return CAIRO_STATUS_SUCCESS; - - if (!boxes->is_pixel_aligned) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (op == CAIRO_OPERATOR_CLEAR) - op = CAIRO_OPERATOR_SOURCE; - - if (op == CAIRO_OPERATOR_OVER && - _cairo_pattern_is_opaque (src, &composite->bounded)) - op = CAIRO_OPERATOR_SOURCE; - - if (dst->win32.base.is_clear && - (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)) - op = CAIRO_OPERATOR_SOURCE; - - if (op == CAIRO_OPERATOR_SOURCE) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - if (src->type == CAIRO_PATTERN_TYPE_SURFACE) { - status = copy_boxes (dst, src, boxes); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) - status = upload_boxes (dst, src, boxes); - } else if (src->type == CAIRO_PATTERN_TYPE_SOLID) { - status = fill_boxes (dst, src, boxes); - } - return status; - } - - if (op == CAIRO_OPERATOR_OVER && can_alpha_blend (dst)) - return alpha_blend_boxes (dst, src, boxes, 255); - - return CAIRO_INT_STATUS_UNSUPPORTED; -} - -static cairo_status_t -opacity_boxes (cairo_composite_rectangles_t *composite, - cairo_boxes_t *boxes) -{ - cairo_win32_display_surface_t *dst = to_win32_display_surface(composite->surface); - cairo_operator_t op = composite->op; - const cairo_pattern_t *src = &composite->source_pattern.base; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - if (composite->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (boxes->num_boxes == 0 && composite->is_bounded) - return CAIRO_STATUS_SUCCESS; - - if (!boxes->is_pixel_aligned) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (op != CAIRO_OPERATOR_OVER) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (!can_alpha_blend (dst)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - return alpha_blend_boxes (dst, src, boxes, - composite->mask_pattern.solid.color.alpha_short >> 8); -} - -/* high-level compositor interface */ - -static cairo_bool_t check_blit (cairo_composite_rectangles_t *composite) -{ - cairo_win32_display_surface_t *dst; - - if (composite->clip->path) - return FALSE; - - dst = to_win32_display_surface (composite->surface); - if (dst->fallback) - return FALSE; - - if (dst->win32.format != CAIRO_FORMAT_RGB24 - && dst->win32.format != CAIRO_FORMAT_ARGB32) - return FALSE; - - if (dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_BITBLT) - return TRUE; - - return dst->image == NULL; -} - -static cairo_int_status_t -_cairo_win32_gdi_compositor_paint (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (check_blit (composite)) { - cairo_boxes_t boxes; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - _cairo_clip_steal_boxes (composite->clip, &boxes); - status = draw_boxes (composite, &boxes); - _cairo_clip_unsteal_boxes (composite->clip, &boxes); - } - - return status; -} - -static cairo_int_status_t -_cairo_win32_gdi_compositor_mask (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite) -{ - cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; - - if (check_blit (composite)) { - cairo_boxes_t boxes; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - _cairo_clip_steal_boxes (composite->clip, &boxes); - status = opacity_boxes (composite, &boxes); - _cairo_clip_unsteal_boxes (composite->clip, &boxes); - } - - return status; -} - -static cairo_int_status_t -_cairo_win32_gdi_compositor_stroke (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *ctm, - const cairo_matrix_t *ctm_inverse, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_int_status_t status; - - status = CAIRO_INT_STATUS_UNSUPPORTED; - if (check_blit (composite) && - _cairo_path_fixed_stroke_is_rectilinear (path)) { - cairo_boxes_t boxes; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - _cairo_boxes_init_with_clip (&boxes, composite->clip); - status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path, - style, - ctm, - antialias, - &boxes); - if (likely (status == CAIRO_INT_STATUS_SUCCESS)) - status = draw_boxes (composite, &boxes); - _cairo_boxes_fini (&boxes); - } - - return status; -} - -static cairo_int_status_t -_cairo_win32_gdi_compositor_fill (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t *composite, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_int_status_t status; - - status = CAIRO_INT_STATUS_UNSUPPORTED; - if (check_blit (composite) && - _cairo_path_fixed_fill_is_rectilinear (path)) { - cairo_boxes_t boxes; - - TRACE ((stderr, "%s\n", __FUNCTION__)); - _cairo_boxes_init_with_clip (&boxes, composite->clip); - status = _cairo_path_fixed_fill_rectilinear_to_boxes (path, - fill_rule, - antialias, - &boxes); - if (likely (status == CAIRO_INT_STATUS_SUCCESS)) - status = draw_boxes (composite, &boxes); - _cairo_boxes_fini (&boxes); - } - - return status; -} - -static cairo_bool_t check_glyphs (cairo_composite_rectangles_t *composite, - cairo_scaled_font_t *scaled_font) -{ - if (! _cairo_clip_is_region (composite->clip)) - return FALSE; - - if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32) - return FALSE; - - if (! _cairo_pattern_is_opaque_solid (&composite->source_pattern.base)) - return FALSE; - - return (composite->op == CAIRO_OPERATOR_CLEAR || - composite->op == CAIRO_OPERATOR_SOURCE || - composite->op == CAIRO_OPERATOR_OVER); -} - -static cairo_int_status_t -_cairo_win32_gdi_compositor_glyphs (const cairo_compositor_t *compositor, - cairo_composite_rectangles_t*composite, - cairo_scaled_font_t *scaled_font, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_bool_t overlap) -{ - cairo_int_status_t status; - - status = CAIRO_INT_STATUS_UNSUPPORTED; - if (check_blit (composite) && check_glyphs (composite, scaled_font)) { - cairo_win32_display_surface_t *dst = to_win32_display_surface (composite->surface); - - TRACE ((stderr, "%s\n", __FUNCTION__)); - - if ((dst->win32.flags & CAIRO_WIN32_SURFACE_CAN_RGB_BRUSH) == 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_win32_display_surface_set_clip(dst, composite->clip); - if (status) - return status; - - status = _cairo_win32_surface_emit_glyphs (&dst->win32, - &composite->source_pattern.base, - glyphs, - num_glyphs, - scaled_font, - TRUE); - - _cairo_win32_display_surface_unset_clip (dst); - } - - return status; -} - -const cairo_compositor_t * -_cairo_win32_gdi_compositor_get (void) -{ - static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT; - static cairo_compositor_t compositor; - - if (_cairo_atomic_init_once_enter(&once)) { - compositor.delegate = &_cairo_fallback_compositor; - - compositor.paint = _cairo_win32_gdi_compositor_paint; - compositor.mask = _cairo_win32_gdi_compositor_mask; - compositor.fill = _cairo_win32_gdi_compositor_fill; - compositor.stroke = _cairo_win32_gdi_compositor_stroke; - compositor.glyphs = _cairo_win32_gdi_compositor_glyphs; - - _cairo_atomic_init_once_leave(&once); - } - - return &compositor; -} diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-printing-surface.c b/libs/cairo-1.16.0/src/win32/cairo-win32-printing-surface.c deleted file mode 100644 index da7357c..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-printing-surface.c +++ /dev/null @@ -1,2226 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2007, 2008 Adrian Johnson - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Adrian Johnson. - * - * Contributor(s): - * Adrian Johnson - * Vladimir Vukicevic - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-paginated-private.h" - -#include "cairo-clip-private.h" -#include "cairo-composite-rectangles-private.h" -#include "cairo-win32-private.h" -#include "cairo-recording-surface-inline.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-image-info-private.h" -#include "cairo-image-surface-inline.h" -#include "cairo-image-surface-private.h" -#include "cairo-surface-backend-private.h" -#include "cairo-surface-clipper-private.h" -#include "cairo-surface-snapshot-inline.h" -#include "cairo-surface-subsurface-private.h" - -#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 - -#if !defined(GRADIENT_FILL_RECT_H) -# define GRADIENT_FILL_RECT_H 0x00 -#endif - -#if !defined(CHECKJPEGFORMAT) -# define CHECKJPEGFORMAT 0x1017 -#endif - -#if !defined(CHECKPNGFORMAT) -# define CHECKPNGFORMAT 0x1018 -#endif - -#define PELS_72DPI ((LONG)(72. / 0.0254)) - -static const char *_cairo_win32_printing_supported_mime_types[] = -{ - CAIRO_MIME_TYPE_JPEG, - CAIRO_MIME_TYPE_PNG, - NULL -}; - -static const cairo_surface_backend_t cairo_win32_printing_surface_backend; -static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend; - -static void -_cairo_win32_printing_surface_init_ps_mode (cairo_win32_printing_surface_t *surface) -{ - DWORD word; - INT ps_feature, ps_level; - - word = PSIDENT_GDICENTRIC; - if (ExtEscape (surface->win32.dc, POSTSCRIPT_IDENTIFY, sizeof(DWORD), (char *)&word, 0, (char *)NULL) <= 0) - return; - - ps_feature = FEATURESETTING_PSLEVEL; - if (ExtEscape (surface->win32.dc, GET_PS_FEATURESETTING, sizeof(INT), - (char *)&ps_feature, sizeof(INT), (char *)&ps_level) <= 0) - return; - - if (ps_level >= 3) - surface->win32.flags |= CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT; -} - -static void -_cairo_win32_printing_surface_init_image_support (cairo_win32_printing_surface_t *surface) -{ - DWORD word; - - word = CHECKJPEGFORMAT; - if (ExtEscape(surface->win32.dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0) - surface->win32.flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG; - - word = CHECKPNGFORMAT; - if (ExtEscape(surface->win32.dc, QUERYESCSUPPORT, sizeof(word), (char *)&word, 0, (char *)NULL) > 0) - surface->win32.flags |= CAIRO_WIN32_SURFACE_CAN_CHECK_PNG; -} - -/* When creating an EMF file, ExtTextOut with ETO_GLYPH_INDEX does not - * work unless the GDI function GdiInitializeLanguagePack() has been - * called. - * - * http://m-a-tech.blogspot.com/2009/04/emf-buffer-idiocracy.html - * - * The only information I could find on the how to use this - * undocumented function is the use in: - * - * http://src.chromium.org/viewvc/chrome/trunk/src/chrome/renderer/render_process.cc?view=markup - * - * to solve the same problem. The above code first checks if LPK.DLL - * is already loaded. If it is not it calls - * GdiInitializeLanguagePack() using the prototype - * BOOL GdiInitializeLanguagePack (int) - * and argument 0. - */ -static void -_cairo_win32_printing_surface_init_language_pack (cairo_win32_printing_surface_t *surface) -{ - typedef BOOL (WINAPI *gdi_init_lang_pack_func_t)(int); - gdi_init_lang_pack_func_t gdi_init_lang_pack; - HMODULE module; - - if (GetModuleHandleW (L"LPK.DLL")) - return; - - module = GetModuleHandleW (L"GDI32.DLL"); - if (module) { - gdi_init_lang_pack = (gdi_init_lang_pack_func_t) - GetProcAddress (module, "GdiInitializeLanguagePack"); - if (gdi_init_lang_pack) - gdi_init_lang_pack (0); - } -} - -/** - * _cairo_win32_printing_surface_acquire_image_pattern: - * @surface: the win32 printing surface - * @pattern: A #cairo_pattern_t of type SURFACE or RASTER_SOURCE to use as the source - * @extents: extents of the operation that is using this source - * @image_pattern: returns pattern containing acquired image. The matrix (adjusted for - * the device offset of raster source) is copied from the pattern. - * @width: returns width of the pattern - * @height: returns height of pattern - * @image_extra: returns image extra for image type surface - * - * Acquire source surface or raster source pattern. - **/ -static cairo_status_t -_cairo_win32_printing_surface_acquire_image_pattern ( - cairo_win32_printing_surface_t *surface, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents, - cairo_surface_pattern_t *image_pattern, - int *width, - int *height, - void **image_extra) -{ - cairo_status_t status; - cairo_image_surface_t *image; - cairo_matrix_t tm; - double x = 0; - double y = 0; - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_t *surf = ((cairo_surface_pattern_t *) pattern)->surface; - - status = _cairo_surface_acquire_source_image (surf, &image, image_extra); - if (unlikely (status)) - return status; - - *width = image->width; - *height = image->height; - } break; - - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: { - cairo_surface_t *surf; - cairo_box_t box; - cairo_rectangle_int_t rect; - cairo_raster_source_pattern_t *raster; - - /* get the operation extents in pattern space */ - _cairo_box_from_rectangle (&box, extents); - _cairo_matrix_transform_bounding_box_fixed (&pattern->matrix, &box, NULL); - _cairo_box_round_to_rectangle (&box, &rect); - surf = _cairo_raster_source_pattern_acquire (pattern, &surface->win32.base, &rect); - if (!surf) - return CAIRO_INT_STATUS_UNSUPPORTED; - - assert (_cairo_surface_is_image (surf)); - image = (cairo_image_surface_t *) surf; - cairo_surface_get_device_offset (surf, &x, &y); - - raster = (cairo_raster_source_pattern_t *) pattern; - *width = raster->extents.width; - *height = raster->extents.height; - } break; - - case CAIRO_PATTERN_TYPE_SOLID: - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: - default: - ASSERT_NOT_REACHED; - break; - } - - _cairo_pattern_init_for_surface (image_pattern, &image->base); - image_pattern->base.extend = pattern->extend; - cairo_matrix_init_translate (&tm, x, y); - status = cairo_matrix_invert (&tm); - /* translation matrices are invertibile */ - assert (status == CAIRO_STATUS_SUCCESS); - - image_pattern->base.matrix = pattern->matrix; - cairo_matrix_multiply (&image_pattern->base.matrix, &image_pattern->base.matrix, &tm); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_printing_surface_release_image_pattern (cairo_win32_printing_surface_t *surface, - const cairo_pattern_t *pattern, - cairo_surface_pattern_t *image_pattern, - void *image_extra) -{ - cairo_surface_t *surf = image_pattern->surface; - - _cairo_pattern_fini (&image_pattern->base); - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_pattern_t *surf_pat = (cairo_surface_pattern_t *) pattern; - cairo_image_surface_t *image = (cairo_image_surface_t *) surf; - _cairo_surface_release_source_image (surf_pat->surface, image, image_extra); - } break; - - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - _cairo_raster_source_pattern_release (pattern, surf); - break; - - case CAIRO_PATTERN_TYPE_SOLID: - case CAIRO_PATTERN_TYPE_LINEAR: - case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: - default: - ASSERT_NOT_REACHED; - break; - } -} - -static cairo_int_status_t -analyze_surface_pattern_transparency (cairo_win32_printing_surface_t *surface, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - cairo_surface_pattern_t image_pattern; - cairo_image_surface_t *image; - void *image_extra; - cairo_int_status_t status; - cairo_image_transparency_t transparency; - int pattern_width, pattern_height; - - status = _cairo_win32_printing_surface_acquire_image_pattern (surface, - pattern, - extents, - &image_pattern, - &pattern_width, - &pattern_height, - &image_extra); - if (status) - return status; - - image = (cairo_image_surface_t *)(image_pattern.surface); - transparency = _cairo_image_analyze_transparency (image); - switch (transparency) { - case CAIRO_IMAGE_UNKNOWN: - ASSERT_NOT_REACHED; - case CAIRO_IMAGE_IS_OPAQUE: - status = CAIRO_STATUS_SUCCESS; - break; - - case CAIRO_IMAGE_HAS_BILEVEL_ALPHA: - case CAIRO_IMAGE_HAS_ALPHA: - status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; - break; - } - - _cairo_win32_printing_surface_release_image_pattern (surface, pattern, &image_pattern, image_extra); - - return status; -} - -static cairo_bool_t -surface_pattern_supported (const cairo_surface_pattern_t *pattern) -{ - if (_cairo_surface_is_recording (pattern->surface)) - return TRUE; - - if (pattern->surface->backend->acquire_source_image == NULL) - { - return FALSE; - } - - return TRUE; -} - -static cairo_bool_t -pattern_supported (cairo_win32_printing_surface_t *surface, const cairo_pattern_t *pattern) -{ - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - return TRUE; - - case CAIRO_PATTERN_TYPE_LINEAR: - return surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT; - - case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: - return FALSE; - - case CAIRO_PATTERN_TYPE_SURFACE: - return surface_pattern_supported ((cairo_surface_pattern_t *) pattern); - - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - return TRUE; - - default: - ASSERT_NOT_REACHED; - return FALSE; - } -} - -static cairo_int_status_t -_cairo_win32_printing_surface_analyze_operation (cairo_win32_printing_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - if (! pattern_supported (surface, pattern)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (!(op == CAIRO_OPERATOR_SOURCE || - op == CAIRO_OPERATOR_OVER || - op == CAIRO_OPERATOR_CLEAR)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) - return CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN; - } - - if (op == CAIRO_OPERATOR_SOURCE || - op == CAIRO_OPERATOR_CLEAR) - return CAIRO_STATUS_SUCCESS; - - /* CAIRO_OPERATOR_OVER is only supported for opaque patterns. If - * the pattern contains transparency, we return - * CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY to the analysis - * surface. If the analysis surface determines that there is - * anything drawn under this operation, a fallback image will be - * used. Otherwise the operation will be replayed during the - * render stage and we blend the transarency into the white - * background to convert the pattern to opaque. - */ - - if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE || pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) - return analyze_surface_pattern_transparency (surface, pattern, extents); - - if (_cairo_pattern_is_opaque (pattern, NULL)) - return CAIRO_STATUS_SUCCESS; - else - return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY; -} - -static cairo_bool_t -_cairo_win32_printing_surface_operation_supported (cairo_win32_printing_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - if (_cairo_win32_printing_surface_analyze_operation (surface, op, pattern, extents) != CAIRO_INT_STATUS_UNSUPPORTED) - return TRUE; - else - return FALSE; -} - -static void -_cairo_win32_printing_surface_init_clear_color (cairo_win32_printing_surface_t *surface, - cairo_solid_pattern_t *color) -{ - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) - _cairo_pattern_init_solid (color, CAIRO_COLOR_WHITE); - else - _cairo_pattern_init_solid (color, CAIRO_COLOR_BLACK); -} - -static COLORREF -_cairo_win32_printing_surface_flatten_transparency (cairo_win32_printing_surface_t *surface, - const cairo_color_t *color) -{ - COLORREF c; - BYTE red, green, blue; - - red = color->red_short >> 8; - green = color->green_short >> 8; - blue = color->blue_short >> 8; - - if (!CAIRO_COLOR_IS_OPAQUE(color)) { - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) { - /* Blend into white */ - uint8_t one_minus_alpha = 255 - (color->alpha_short >> 8); - - red = (color->red_short >> 8) + one_minus_alpha; - green = (color->green_short >> 8) + one_minus_alpha; - blue = (color->blue_short >> 8) + one_minus_alpha; - } else { - /* Blend into black */ - red = (color->red_short >> 8); - green = (color->green_short >> 8); - blue = (color->blue_short >> 8); - } - } - c = RGB (red, green, blue); - - return c; -} - -static cairo_status_t -_cairo_win32_printing_surface_select_solid_brush (cairo_win32_printing_surface_t *surface, - const cairo_pattern_t *source) -{ - cairo_solid_pattern_t *pattern = (cairo_solid_pattern_t *) source; - COLORREF color; - - 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)"); - surface->old_brush = SelectObject (surface->win32.dc, surface->brush); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_win32_printing_surface_done_solid_brush (cairo_win32_printing_surface_t *surface) -{ - if (surface->old_brush) { - SelectObject (surface->win32.dc, surface->old_brush); - DeleteObject (surface->brush); - surface->old_brush = NULL; - } -} - -static cairo_status_t -_cairo_win32_printing_surface_get_ctm_clip_box (cairo_win32_printing_surface_t *surface, - RECT *clip) -{ - 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"); - 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"); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_paint_solid_pattern (cairo_win32_printing_surface_t *surface, - const cairo_pattern_t *pattern) -{ - RECT clip; - cairo_status_t status; - - GetClipBox (surface->win32.dc, &clip); - status = _cairo_win32_printing_surface_select_solid_brush (surface, pattern); - if (status) - return status; - - FillRect (surface->win32.dc, &clip, surface->brush); - _cairo_win32_printing_surface_done_solid_brush (surface); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_printing_surface_t *surface, - cairo_surface_pattern_t *pattern) -{ - cairo_content_t old_content; - cairo_matrix_t old_ctm; - cairo_bool_t old_has_ctm; - cairo_rectangle_int_t recording_extents; - cairo_int_status_t status; - cairo_extend_t extend; - cairo_matrix_t p2d; - XFORM xform; - int x_tile, y_tile, left, right, top, bottom; - RECT clip; - cairo_recording_surface_t *recording_surface = (cairo_recording_surface_t *) pattern->surface; - cairo_box_t bbox; - cairo_surface_t *free_me = NULL; - cairo_bool_t is_subsurface; - - extend = cairo_pattern_get_extend (&pattern->base); - - p2d = pattern->base.matrix; - status = cairo_matrix_invert (&p2d); - /* _cairo_pattern_set_matrix guarantees invertibility */ - assert (status == CAIRO_INT_STATUS_SUCCESS); - - old_ctm = surface->ctm; - old_has_ctm = surface->has_ctm; - cairo_matrix_multiply (&p2d, &p2d, &surface->ctm); - surface->ctm = p2d; - SaveDC (surface->win32.dc); - _cairo_matrix_to_win32_xform (&p2d, &xform); - - if (_cairo_surface_is_snapshot (&recording_surface->base)) { - free_me = _cairo_surface_snapshot_get_target (&recording_surface->base); - recording_surface = (cairo_recording_surface_t *) free_me; - } - - if (recording_surface->base.backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { - cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) recording_surface; - - recording_surface = (cairo_recording_surface_t *) (sub->target); - recording_extents = sub->extents; - is_subsurface = TRUE; - } else { - status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL); - if (status) - goto err; - - _cairo_box_round_to_rectangle (&bbox, &recording_extents); - } - - status = _cairo_win32_printing_surface_get_ctm_clip_box (surface, &clip); - if (status) - goto err; - - if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - left = floor (clip.left / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x)); - right = ceil (clip.right / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x)); - top = floor (clip.top / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y)); - bottom = ceil (clip.bottom / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y)); - } else { - left = 0; - right = 1; - top = 0; - bottom = 1; - } - - old_content = surface->content; - if (recording_surface->base.content == CAIRO_CONTENT_COLOR) { - surface->content = CAIRO_CONTENT_COLOR; - status = _cairo_win32_printing_surface_paint_solid_pattern (surface, - &_cairo_pattern_black.base); - if (status) - goto err; - } - - for (y_tile = top; y_tile < bottom; y_tile++) { - for (x_tile = left; x_tile < right; x_tile++) { - cairo_matrix_t m; - double x, y; - - SaveDC (surface->win32.dc); - m = p2d; - cairo_matrix_translate (&m, - x_tile*recording_extents.width, - y_tile*recording_extents.height); - if (extend == CAIRO_EXTEND_REFLECT) { - if (x_tile % 2) { - cairo_matrix_translate (&m, recording_extents.width, 0); - cairo_matrix_scale (&m, -1, 1); - } - if (y_tile % 2) { - cairo_matrix_translate (&m, 0, recording_extents.height); - cairo_matrix_scale (&m, 1, -1); - } - } - surface->ctm = m; - surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); - - /* Set clip path around bbox of the pattern. */ - BeginPath (surface->win32.dc); - - x = 0; - y = 0; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - MoveToEx (surface->win32.dc, (int) x, (int) y, NULL); - - x = recording_extents.width; - y = 0; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - LineTo (surface->win32.dc, (int) x, (int) y); - - x = recording_extents.width; - y = recording_extents.height; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - LineTo (surface->win32.dc, (int) x, (int) y); - - x = 0; - y = recording_extents.height; - cairo_matrix_transform_point (&surface->ctm, &x, &y); - LineTo (surface->win32.dc, (int) x, (int) y); - - CloseFigure (surface->win32.dc); - EndPath (surface->win32.dc); - SelectClipPath (surface->win32.dc, RGN_AND); - - SaveDC (surface->win32.dc); /* Allow clip path to be reset during replay */ - status = _cairo_recording_surface_replay_region (&recording_surface->base, - is_subsurface ? &recording_extents : NULL, - &surface->win32.base, - CAIRO_RECORDING_REGION_NATIVE); - assert (status != CAIRO_INT_STATUS_UNSUPPORTED); - /* Restore both the clip save and our earlier path SaveDC */ - RestoreDC (surface->win32.dc, -2); - - if (status) - goto err; - } - } - - surface->content = old_content; - surface->ctm = old_ctm; - surface->has_ctm = old_has_ctm; - RestoreDC (surface->win32.dc, -1); - - err: - cairo_surface_destroy (free_me); - return status; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_check_jpeg (cairo_win32_printing_surface_t *surface, - cairo_surface_t *source, - const unsigned char **data, - unsigned long *length, - cairo_image_info_t *info) -{ - const unsigned char *mime_data; - unsigned long mime_data_length; - cairo_int_status_t status; - DWORD result; - - if (!(surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG, - &mime_data, &mime_data_length); - if (mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_image_info_get_jpeg_info (info, mime_data, mime_data_length); - if (status) - return status; - - result = 0; - if (ExtEscape(surface->win32.dc, CHECKJPEGFORMAT, mime_data_length, (char *) mime_data, - sizeof(result), (char *) &result) <= 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (result != 1) - return CAIRO_INT_STATUS_UNSUPPORTED; - - *data = mime_data; - *length = mime_data_length; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_check_png (cairo_win32_printing_surface_t *surface, - cairo_surface_t *source, - const unsigned char **data, - unsigned long *length, - cairo_image_info_t *info) -{ - const unsigned char *mime_data; - unsigned long mime_data_length; - - cairo_int_status_t status; - DWORD result; - - if (!(surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_CHECK_PNG)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_PNG, - &mime_data, &mime_data_length); - if (mime_data == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - status = _cairo_image_info_get_png_info (info, mime_data, mime_data_length); - if (status) - return status; - - result = 0; - if (ExtEscape(surface->win32.dc, CHECKPNGFORMAT, mime_data_length, (char *) mime_data, - sizeof(result), (char *) &result) <= 0) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (result != 1) - return CAIRO_INT_STATUS_UNSUPPORTED; - - *data = mime_data; - *length = mime_data_length; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_paint_image_pattern (cairo_win32_printing_surface_t *surface, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - cairo_int_status_t status; - cairo_surface_pattern_t image_pattern; - cairo_image_surface_t *image; - void *image_extra; - cairo_image_surface_t *opaque_image = NULL; - BITMAPINFO bi; - cairo_matrix_t m; - int oldmode; - XFORM xform; - int x_tile, y_tile, left, right, top, bottom; - int pattern_width, pattern_height; - RECT clip; - const cairo_color_t *background_color; - const unsigned char *mime_data; - unsigned long mime_size; - cairo_image_info_t mime_info; - cairo_bool_t use_mime; - DWORD mime_type; - - /* If we can't use StretchDIBits with this surface, we can't do anything - * here. - */ - if (!(surface->win32.flags & CAIRO_WIN32_SURFACE_CAN_STRETCHDIB)) - return CAIRO_INT_STATUS_UNSUPPORTED; - - if (surface->content == CAIRO_CONTENT_COLOR_ALPHA) - background_color = CAIRO_COLOR_WHITE; - else - background_color = CAIRO_COLOR_BLACK; - - status = _cairo_win32_printing_surface_acquire_image_pattern (surface, - pattern, - extents, - &image_pattern, - &pattern_width, - &pattern_height, - &image_extra); - if (status) - return status; - - image = (cairo_image_surface_t *)(image_pattern.surface); - if (image->base.status) { - status = image->base.status; - goto CLEANUP_IMAGE; - } - - if (image->width == 0 || image->height == 0) { - status = CAIRO_STATUS_SUCCESS; - goto CLEANUP_IMAGE; - } - - mime_type = BI_JPEG; - status = _cairo_win32_printing_surface_check_jpeg (surface, - image_pattern.surface, - &mime_data, - &mime_size, - &mime_info); - if (status == CAIRO_INT_STATUS_UNSUPPORTED) { - mime_type = BI_PNG; - status = _cairo_win32_printing_surface_check_png (surface, - image_pattern.surface, - &mime_data, - &mime_size, - &mime_info); - } - if (_cairo_int_status_is_error (status)) - return status; - - use_mime = (status == CAIRO_INT_STATUS_SUCCESS); - - if (!use_mime && image->format != CAIRO_FORMAT_RGB24) { - cairo_surface_t *opaque_surface; - cairo_surface_pattern_t image_pattern; - cairo_solid_pattern_t background_pattern; - - opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, - image->width, - image->height); - if (opaque_surface->status) { - status = opaque_surface->status; - goto CLEANUP_OPAQUE_IMAGE; - } - - _cairo_pattern_init_solid (&background_pattern, - background_color); - status = _cairo_surface_paint (opaque_surface, - CAIRO_OPERATOR_SOURCE, - &background_pattern.base, - NULL); - if (status) - goto CLEANUP_OPAQUE_IMAGE; - - _cairo_pattern_init_for_surface (&image_pattern, &image->base); - status = _cairo_surface_paint (opaque_surface, - CAIRO_OPERATOR_OVER, - &image_pattern.base, - NULL); - _cairo_pattern_fini (&image_pattern.base); - if (status) - goto CLEANUP_OPAQUE_IMAGE; - - opaque_image = (cairo_image_surface_t *) opaque_surface; - } else { - opaque_image = image; - } - - bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bi.bmiHeader.biWidth = use_mime ? mime_info.width : opaque_image->width; - bi.bmiHeader.biHeight = use_mime ? - mime_info.height : -opaque_image->height; - bi.bmiHeader.biSizeImage = use_mime ? mime_size : 0; - bi.bmiHeader.biXPelsPerMeter = PELS_72DPI; - bi.bmiHeader.biYPelsPerMeter = PELS_72DPI; - bi.bmiHeader.biPlanes = 1; - bi.bmiHeader.biBitCount = 32; - bi.bmiHeader.biCompression = use_mime ? mime_type : BI_RGB; - bi.bmiHeader.biClrUsed = 0; - bi.bmiHeader.biClrImportant = 0; - - m = image_pattern.base.matrix; - status = cairo_matrix_invert (&m); - /* _cairo_pattern_set_matrix guarantees invertibility */ - assert (status == CAIRO_INT_STATUS_SUCCESS); - - cairo_matrix_multiply (&m, &m, &surface->ctm); - cairo_matrix_multiply (&m, &m, &surface->gdi_ctm); - SaveDC (surface->win32.dc); - _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"); - goto CLEANUP_OPAQUE_IMAGE; - } - - oldmode = SetStretchBltMode(surface->win32.dc, HALFTONE); - - GetClipBox (surface->win32.dc, &clip); - if (pattern->extend == CAIRO_EXTEND_REPEAT || pattern->extend == CAIRO_EXTEND_REFLECT) { - left = floor ( clip.left / (double) opaque_image->width); - right = ceil (clip.right / (double) opaque_image->width); - top = floor (clip.top / (double) opaque_image->height); - bottom = ceil (clip.bottom / (double) opaque_image->height); - } else { - left = 0; - right = 1; - top = 0; - bottom = 1; - } - - for (y_tile = top; y_tile < bottom; y_tile++) { - for (x_tile = left; x_tile < right; x_tile++) { - if (!StretchDIBits (surface->win32.dc, - x_tile*opaque_image->width, - y_tile*opaque_image->height, - opaque_image->width, - opaque_image->height, - 0, - 0, - use_mime ? mime_info.width : opaque_image->width, - use_mime ? mime_info.height : opaque_image->height, - use_mime ? mime_data : opaque_image->data, - &bi, - DIB_RGB_COLORS, - SRCCOPY)) - { - status = _cairo_win32_print_gdi_error ("_cairo_win32_printing_surface_paint(StretchDIBits)"); - goto CLEANUP_OPAQUE_IMAGE; - } - } - } - SetStretchBltMode(surface->win32.dc, oldmode); - RestoreDC (surface->win32.dc, -1); - -CLEANUP_OPAQUE_IMAGE: - if (opaque_image != image) - cairo_surface_destroy (&opaque_image->base); -CLEANUP_IMAGE: - _cairo_win32_printing_surface_release_image_pattern (surface, pattern, &image_pattern, image_extra); - - return status; -} - -static void -vertex_set_color (TRIVERTEX *vert, cairo_color_stop_t *color) -{ - /* MSDN says that the range here is 0x0000 .. 0xff00; - * that may well be a typo, but just chop the low bits - * here. */ - vert->Alpha = 0xff00; - vert->Red = color->red_short & 0xff00; - vert->Green = color->green_short & 0xff00; - vert->Blue = color->blue_short & 0xff00; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_paint_linear_pattern (cairo_win32_printing_surface_t *surface, - cairo_linear_pattern_t *pattern) -{ - TRIVERTEX *vert; - GRADIENT_RECT *rect; - RECT clip; - XFORM xform; - int i, num_stops; - cairo_matrix_t mat, rot; - double p1x, p1y, p2x, p2y, xd, yd, d, sn, cs; - cairo_extend_t extend; - int range_start, range_stop, num_ranges, num_rects, stop; - int total_verts, total_rects; - cairo_status_t status; - - extend = cairo_pattern_get_extend (&pattern->base.base); - SaveDC (surface->win32.dc); - - mat = pattern->base.base.matrix; - status = cairo_matrix_invert (&mat); - /* _cairo_pattern_set_matrix guarantees invertibility */ - assert (status == CAIRO_STATUS_SUCCESS); - - cairo_matrix_multiply (&mat, &surface->ctm, &mat); - - p1x = pattern->pd1.x; - p1y = pattern->pd1.y; - p2x = pattern->pd2.x; - p2y = pattern->pd2.y; - cairo_matrix_translate (&mat, p1x, p1y); - - xd = p2x - p1x; - yd = p2y - p1y; - d = sqrt (xd*xd + yd*yd); - sn = yd/d; - cs = xd/d; - cairo_matrix_init (&rot, - cs, sn, - -sn, cs, - 0, 0); - cairo_matrix_multiply (&mat, &rot, &mat); - - _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"); - - GetClipBox (surface->win32.dc, &clip); - - if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) { - range_start = floor (clip.left / d); - range_stop = ceil (clip.right / d); - } else { - range_start = 0; - range_stop = 1; - } - num_ranges = range_stop - range_start; - num_stops = pattern->base.n_stops; - num_rects = num_stops - 1; - - /* Add an extra four points and two rectangles for EXTEND_PAD */ - vert = _cairo_malloc (sizeof (TRIVERTEX) * (num_rects*2*num_ranges + 4)); - rect = _cairo_malloc (sizeof (GRADIENT_RECT) * (num_rects*num_ranges + 2)); - - for (i = 0; i < num_ranges*num_rects; i++) { - vert[i*2].y = (LONG) clip.top; - if (i%num_rects == 0) { - stop = 0; - if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2) - stop = num_rects; - vert[i*2].x = (LONG)(d*(range_start + i/num_rects)); - vertex_set_color (&vert[i*2], &pattern->base.stops[stop].color); - } else { - vert[i*2].x = vert[i*2-1].x; - vert[i*2].Red = vert[i*2-1].Red; - vert[i*2].Green = vert[i*2-1].Green; - vert[i*2].Blue = vert[i*2-1].Blue; - vert[i*2].Alpha = vert[i*2-1].Alpha; - } - - stop = i%num_rects + 1; - vert[i*2+1].x = (LONG)(d*(range_start + i/num_rects + pattern->base.stops[stop].offset)); - vert[i*2+1].y = (LONG) clip.bottom; - if (extend == CAIRO_EXTEND_REFLECT && (range_start+(i/num_rects))%2) - stop = num_rects - stop; - vertex_set_color (&vert[i*2+1], &pattern->base.stops[stop].color); - - rect[i].UpperLeft = i*2; - rect[i].LowerRight = i*2 + 1; - } - total_verts = 2*num_ranges*num_rects; - total_rects = num_ranges*num_rects; - - if (extend == CAIRO_EXTEND_PAD) { - vert[i*2].x = vert[i*2-1].x; - vert[i*2].y = (LONG) clip.top; - vert[i*2].Red = vert[i*2-1].Red; - vert[i*2].Green = vert[i*2-1].Green; - vert[i*2].Blue = vert[i*2-1].Blue; - vert[i*2].Alpha = 0xff00; - vert[i*2+1].x = clip.right; - vert[i*2+1].y = (LONG) clip.bottom; - vert[i*2+1].Red = vert[i*2-1].Red; - vert[i*2+1].Green = vert[i*2-1].Green; - vert[i*2+1].Blue = vert[i*2-1].Blue; - vert[i*2+1].Alpha = 0xff00; - rect[i].UpperLeft = i*2; - rect[i].LowerRight = i*2 + 1; - - i++; - - vert[i*2].x = clip.left; - vert[i*2].y = (LONG) clip.top; - vert[i*2].Red = vert[0].Red; - vert[i*2].Green = vert[0].Green; - vert[i*2].Blue = vert[0].Blue; - vert[i*2].Alpha = 0xff00; - vert[i*2+1].x = vert[0].x; - vert[i*2+1].y = (LONG) clip.bottom; - vert[i*2+1].Red = vert[0].Red; - vert[i*2+1].Green = vert[0].Green; - vert[i*2+1].Blue = vert[0].Blue; - vert[i*2+1].Alpha = 0xff00; - rect[i].UpperLeft = i*2; - rect[i].LowerRight = i*2 + 1; - - total_verts += 4; - total_rects += 2; - } - - if (!GradientFill (surface->win32.dc, - vert, total_verts, - rect, total_rects, - GRADIENT_FILL_RECT_H)) - return _cairo_win32_print_gdi_error ("_win32_printing_surface_paint_linear_pattern:GradientFill"); - - free (rect); - free (vert); - RestoreDC (surface->win32.dc, -1); - - return 0; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_paint_pattern (cairo_win32_printing_surface_t *surface, - const cairo_pattern_t *pattern, - const cairo_rectangle_int_t *extents) -{ - cairo_status_t status; - - switch (pattern->type) { - case CAIRO_PATTERN_TYPE_SOLID: - status = _cairo_win32_printing_surface_paint_solid_pattern (surface, pattern); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_SURFACE: { - cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern; - - if ( _cairo_surface_is_recording (surface_pattern->surface)) - status = _cairo_win32_printing_surface_paint_recording_pattern (surface, surface_pattern); - else - status = _cairo_win32_printing_surface_paint_image_pattern (surface, pattern, extents); - - if (status) - return status; - break; - } - case CAIRO_PATTERN_TYPE_RASTER_SOURCE: - status = _cairo_win32_printing_surface_paint_image_pattern (surface, pattern, extents); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_LINEAR: - status = _cairo_win32_printing_surface_paint_linear_pattern (surface, (cairo_linear_pattern_t *) pattern); - if (status) - return status; - break; - - case CAIRO_PATTERN_TYPE_RADIAL: - return CAIRO_INT_STATUS_UNSUPPORTED; - break; - - case CAIRO_PATTERN_TYPE_MESH: - ASSERT_NOT_REACHED; - } - - return CAIRO_STATUS_SUCCESS; -} - -typedef struct _win32_print_path_info { - cairo_win32_printing_surface_t *surface; -} win32_path_info_t; - -static cairo_status_t -_cairo_win32_printing_surface_path_move_to (void *closure, - const cairo_point_t *point) -{ - win32_path_info_t *path_info = closure; - - if (path_info->surface->has_ctm) { - double x, y; - - x = _cairo_fixed_to_double (point->x); - y = _cairo_fixed_to_double (point->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - MoveToEx (path_info->surface->win32.dc, (int) x, (int) y, NULL); - } else { - MoveToEx (path_info->surface->win32.dc, - _cairo_fixed_integer_part (point->x), - _cairo_fixed_integer_part (point->y), - NULL); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_path_line_to (void *closure, - const cairo_point_t *point) -{ - win32_path_info_t *path_info = closure; - - path_info->surface->path_empty = FALSE; - if (path_info->surface->has_ctm) { - double x, y; - - x = _cairo_fixed_to_double (point->x); - y = _cairo_fixed_to_double (point->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - LineTo (path_info->surface->win32.dc, (int) x, (int) y); - } else { - LineTo (path_info->surface->win32.dc, - _cairo_fixed_integer_part (point->x), - _cairo_fixed_integer_part (point->y)); - } - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_path_curve_to (void *closure, - const cairo_point_t *b, - const cairo_point_t *c, - const cairo_point_t *d) -{ - win32_path_info_t *path_info = closure; - POINT points[3]; - - path_info->surface->path_empty = FALSE; - if (path_info->surface->has_ctm) { - double x, y; - - x = _cairo_fixed_to_double (b->x); - y = _cairo_fixed_to_double (b->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - points[0].x = (LONG) x; - points[0].y = (LONG) y; - - x = _cairo_fixed_to_double (c->x); - y = _cairo_fixed_to_double (c->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - points[1].x = (LONG) x; - points[1].y = (LONG) y; - - x = _cairo_fixed_to_double (d->x); - y = _cairo_fixed_to_double (d->y); - cairo_matrix_transform_point (&path_info->surface->ctm, &x, &y); - points[2].x = (LONG) x; - points[2].y = (LONG) y; - } else { - points[0].x = _cairo_fixed_integer_part (b->x); - points[0].y = _cairo_fixed_integer_part (b->y); - points[1].x = _cairo_fixed_integer_part (c->x); - points[1].y = _cairo_fixed_integer_part (c->y); - points[2].x = _cairo_fixed_integer_part (d->x); - points[2].y = _cairo_fixed_integer_part (d->y); - } - PolyBezierTo (path_info->surface->win32.dc, points, 3); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_path_close_path (void *closure) -{ - win32_path_info_t *path_info = closure; - - CloseFigure (path_info->surface->win32.dc); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_emit_path (cairo_win32_printing_surface_t *surface, - const cairo_path_fixed_t *path) -{ - win32_path_info_t path_info; - - path_info.surface = surface; - return _cairo_path_fixed_interpret (path, - _cairo_win32_printing_surface_path_move_to, - _cairo_win32_printing_surface_path_line_to, - _cairo_win32_printing_surface_path_curve_to, - _cairo_win32_printing_surface_path_close_path, - &path_info); -} - -static cairo_int_status_t -_cairo_win32_printing_surface_show_page (void *abstract_surface) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - - /* Undo both SaveDC's that we did in start_page */ - RestoreDC (surface->win32.dc, -2); - - /* Invalidate extents since the size of the next page is not known at - * this point. - */ - surface->extents_valid = FALSE; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_status_t -_cairo_win32_printing_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper, - cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias) -{ - cairo_win32_printing_surface_t *surface = cairo_container_of (clipper, - cairo_win32_printing_surface_t, - clipper); - cairo_status_t status; - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) - return CAIRO_STATUS_SUCCESS; - - if (path == NULL) { - RestoreDC (surface->win32.dc, -1); - SaveDC (surface->win32.dc); - - return CAIRO_STATUS_SUCCESS; - } - - BeginPath (surface->win32.dc); - status = _cairo_win32_printing_surface_emit_path (surface, path); - EndPath (surface->win32.dc); - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - SetPolyFillMode (surface->win32.dc, WINDING); - break; - case CAIRO_FILL_RULE_EVEN_ODD: - SetPolyFillMode (surface->win32.dc, ALTERNATE); - break; - default: - ASSERT_NOT_REACHED; - } - - SelectClipPath (surface->win32.dc, RGN_AND); - - return status; -} - -static cairo_bool_t -_cairo_win32_printing_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - - if (surface->extents_valid) - *rectangle = surface->win32.extents; - - return surface->extents_valid; -} - -static void -_cairo_win32_printing_surface_get_font_options (void *abstract_surface, - cairo_font_options_t *options) -{ - _cairo_font_options_init_default (options); - - cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE); - cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_OFF); - cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY); - _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON); -} - -static cairo_int_status_t -_cairo_win32_printing_surface_paint (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_clip_t *clip) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - cairo_solid_pattern_t clear; - cairo_composite_rectangles_t extents; - cairo_status_t status; - - status = _cairo_composite_rectangles_init_for_paint (&extents, - &surface->win32.base, - op, source, clip); - if (unlikely (status)) - return status; - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - goto cleanup_composite; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - status = _cairo_win32_printing_surface_analyze_operation (surface, op, source, &extents.bounded); - goto cleanup_composite; - } - - assert (_cairo_win32_printing_surface_operation_supported (surface, op, source, &extents.bounded)); - - status = _cairo_win32_printing_surface_paint_pattern (surface, source, &extents.bounded); - - cleanup_composite: - _cairo_composite_rectangles_fini (&extents); - return status; -} - -static int -_cairo_win32_line_cap (cairo_line_cap_t cap) -{ - switch (cap) { - case CAIRO_LINE_CAP_BUTT: - return PS_ENDCAP_FLAT; - case CAIRO_LINE_CAP_ROUND: - return PS_ENDCAP_ROUND; - case CAIRO_LINE_CAP_SQUARE: - return PS_ENDCAP_SQUARE; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static int -_cairo_win32_line_join (cairo_line_join_t join) -{ - switch (join) { - case CAIRO_LINE_JOIN_MITER: - return PS_JOIN_MITER; - case CAIRO_LINE_JOIN_ROUND: - return PS_JOIN_ROUND; - case CAIRO_LINE_JOIN_BEVEL: - return PS_JOIN_BEVEL; - default: - ASSERT_NOT_REACHED; - return 0; - } -} - -static void -_cairo_matrix_factor_out_scale (cairo_matrix_t *m, double *scale) -{ - double s; - - s = fabs (m->xx); - if (fabs (m->xy) > s) - s = fabs (m->xy); - if (fabs (m->yx) > s) - s = fabs (m->yx); - if (fabs (m->yy) > s) - s = fabs (m->yy); - *scale = s; - s = 1.0/s; - cairo_matrix_scale (m, s, s); -} - -static cairo_int_status_t -_cairo_win32_printing_surface_stroke (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - const cairo_stroke_style_t *style, - const cairo_matrix_t *stroke_ctm, - const cairo_matrix_t *stroke_ctm_inverse, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - cairo_int_status_t status; - HPEN pen; - LOGBRUSH brush; - COLORREF color; - XFORM xform; - DWORD pen_style; - DWORD *dash_array; - HGDIOBJ obj; - unsigned int i; - cairo_solid_pattern_t clear; - cairo_matrix_t mat; - double scale; - cairo_composite_rectangles_t extents; - - status = _cairo_composite_rectangles_init_for_stroke (&extents, - &surface->win32.base, - op, source, - path, style, stroke_ctm, - clip); - if (unlikely (status)) - return status; - - /* use the more accurate extents */ - { - cairo_rectangle_int_t r; - cairo_box_t b; - - status = _cairo_path_fixed_stroke_extents (path, style, - stroke_ctm, stroke_ctm_inverse, - tolerance, - &r); - if (unlikely (status)) - goto cleanup_composite; - - _cairo_box_from_rectangle (&b, &r); - status = _cairo_composite_rectangles_intersect_mask_extents (&extents, &b); - if (unlikely (status)) - goto cleanup_composite; - } - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - goto cleanup_composite; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - /* Win32 does not support a dash offset. */ - if (style->num_dashes > 0 && style->dash_offset != 0.0) - status = CAIRO_INT_STATUS_UNSUPPORTED; - else - status = _cairo_win32_printing_surface_analyze_operation (surface, op, source, &extents.bounded); - - goto cleanup_composite; - } - - assert (_cairo_win32_printing_surface_operation_supported (surface, op, source, &extents.bounded)); - assert (!(style->num_dashes > 0 && style->dash_offset != 0.0)); - - cairo_matrix_multiply (&mat, stroke_ctm, &surface->ctm); - _cairo_matrix_factor_out_scale (&mat, &scale); - - pen_style = PS_GEOMETRIC; - dash_array = NULL; - if (style->num_dashes) { - pen_style |= PS_USERSTYLE; - dash_array = calloc (sizeof (DWORD), style->num_dashes); - for (i = 0; i < style->num_dashes; i++) { - dash_array[i] = (DWORD) (scale * style->dash[i]); - } - } else { - pen_style |= PS_SOLID; - } - - SetMiterLimit (surface->win32.dc, (FLOAT) (style->miter_limit), NULL); - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; - - - color = _cairo_win32_printing_surface_flatten_transparency (surface, - &solid->color); - } else { - /* Color not used as the pen will only be used by WidenPath() */ - color = RGB (0,0,0); - } - brush.lbStyle = BS_SOLID; - brush.lbColor = color; - brush.lbHatch = 0; - pen_style |= _cairo_win32_line_cap (style->line_cap); - pen_style |= _cairo_win32_line_join (style->line_join); - pen = ExtCreatePen(pen_style, - scale * style->line_width, - &brush, - style->num_dashes, - dash_array); - if (pen == NULL) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:ExtCreatePen"); - goto cleanup_composite; - } - - obj = SelectObject (surface->win32.dc, pen); - if (obj == NULL) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectObject"); - goto cleanup_composite; - } - - BeginPath (surface->win32.dc); - status = _cairo_win32_printing_surface_emit_path (surface, path); - EndPath (surface->win32.dc); - if (unlikely (status)) - goto cleanup_composite; - - /* - * Switch to user space to set line parameters - */ - SaveDC (surface->win32.dc); - - _cairo_matrix_to_win32_xform (&mat, &xform); - xform.eDx = 0.0f; - xform.eDy = 0.0f; - - if (!ModifyWorldTransform (surface->win32.dc, &xform, MWT_LEFTMULTIPLY)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SetWorldTransform"); - goto cleanup_composite; - } - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - StrokePath (surface->win32.dc); - } else { - if (!WidenPath (surface->win32.dc)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:WidenPath"); - goto cleanup_composite; - } - if (!SelectClipPath (surface->win32.dc, RGN_AND)) { - status = _cairo_win32_print_gdi_error ("_win32_surface_stroke:SelectClipPath"); - 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"); - goto cleanup_composite; - } - status = _cairo_win32_printing_surface_paint_pattern (surface, source, &extents.bounded); - } - RestoreDC (surface->win32.dc, -1); - DeleteObject (pen); - free (dash_array); - -cleanup_composite: - _cairo_composite_rectangles_fini (&extents); - return status; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_fill (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - const cairo_path_fixed_t *path, - cairo_fill_rule_t fill_rule, - double tolerance, - cairo_antialias_t antialias, - const cairo_clip_t *clip) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - cairo_int_status_t status; - cairo_solid_pattern_t clear; - cairo_composite_rectangles_t extents; - - status = _cairo_composite_rectangles_init_for_fill (&extents, - &surface->win32.base, - op, source, path, - clip); - if (unlikely (status)) - return status; - - /* use the more accurate extents */ - { - cairo_rectangle_int_t r; - cairo_box_t b; - - _cairo_path_fixed_fill_extents (path, - fill_rule, - tolerance, - &r); - - _cairo_box_from_rectangle (&b, &r); - status = _cairo_composite_rectangles_intersect_mask_extents (&extents, &b); - if (unlikely (status)) - goto cleanup_composite; - } - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - goto cleanup_composite; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - status = _cairo_win32_printing_surface_analyze_operation (surface, op, source, &extents.bounded); - goto cleanup_composite; - } - - assert (_cairo_win32_printing_surface_operation_supported (surface, op, source, &extents.bounded)); - - surface->path_empty = TRUE; - BeginPath (surface->win32.dc); - status = _cairo_win32_printing_surface_emit_path (surface, path); - EndPath (surface->win32.dc); - - switch (fill_rule) { - case CAIRO_FILL_RULE_WINDING: - SetPolyFillMode (surface->win32.dc, WINDING); - break; - case CAIRO_FILL_RULE_EVEN_ODD: - SetPolyFillMode (surface->win32.dc, ALTERNATE); - break; - default: - ASSERT_NOT_REACHED; - } - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - status = _cairo_win32_printing_surface_select_solid_brush (surface, source); - if (unlikely (status)) - goto cleanup_composite; - - FillPath (surface->win32.dc); - _cairo_win32_printing_surface_done_solid_brush (surface); - } else if (surface->path_empty == FALSE) { - SaveDC (surface->win32.dc); - SelectClipPath (surface->win32.dc, RGN_AND); - status = _cairo_win32_printing_surface_paint_pattern (surface, source, &extents.bounded); - RestoreDC (surface->win32.dc, -1); - } - - fflush(stderr); - -cleanup_composite: - _cairo_composite_rectangles_fini (&extents); - return status; -} - - -static cairo_int_status_t -_cairo_win32_printing_surface_emit_win32_glyphs (cairo_win32_printing_surface_t *surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) -{ - cairo_matrix_t ctm; - cairo_glyph_t *unicode_glyphs; - cairo_scaled_font_subsets_glyph_t subset_glyph; - int i, first; - cairo_bool_t sequence_is_unicode; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - - /* Where possible reverse the glyph indices back to unicode - * characters. Strings of glyphs that could not be reversed to - * unicode will be printed with ETO_GLYPH_INDEX. - * - * As _cairo_win32_scaled_font_index_to_ucs4() is a slow - * operation, the font subsetting function - * _cairo_scaled_font_subsets_map_glyph() is used to obtain - * the unicode value because it caches the reverse mapping in - * the subsets. - */ - - if (surface->has_ctm) { - for (i = 0; i < num_glyphs; i++) - cairo_matrix_transform_point (&surface->ctm, &glyphs[i].x, &glyphs[i].y); - cairo_matrix_multiply (&ctm, &scaled_font->ctm, &surface->ctm); - scaled_font = cairo_scaled_font_create (scaled_font->font_face, - &scaled_font->font_matrix, - &ctm, - &scaled_font->options); - } - - unicode_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); - if (unicode_glyphs == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - memcpy (unicode_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t)); - for (i = 0; i < num_glyphs; i++) { - status = _cairo_scaled_font_subsets_map_glyph (surface->font_subsets, - scaled_font, - glyphs[i].index, - NULL, 0, - &subset_glyph); - if (status) - goto fail; - - unicode_glyphs[i].index = subset_glyph.unicode; - } - - i = 0; - first = 0; - sequence_is_unicode = unicode_glyphs[0].index <= 0xffff; - while (i < num_glyphs) { - if (i == num_glyphs - 1 || - ((unicode_glyphs[i + 1].index < 0xffff) != sequence_is_unicode)) - { - status = _cairo_win32_surface_emit_glyphs (&surface->win32, - source, - sequence_is_unicode ? &unicode_glyphs[first] : &glyphs[first], - i - first + 1, - scaled_font, - ! sequence_is_unicode); - first = i + 1; - if (i < num_glyphs - 1) - sequence_is_unicode = unicode_glyphs[i + 1].index <= 0xffff; - } - i++; - } - -fail: - if (surface->has_ctm) - cairo_scaled_font_destroy (scaled_font); - - free (unicode_glyphs); - - return status; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_show_glyphs (void *abstract_surface, - cairo_operator_t op, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - const cairo_clip_t *clip) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - cairo_status_t status = CAIRO_STATUS_SUCCESS; - cairo_scaled_glyph_t *scaled_glyph; - cairo_pattern_t *opaque = NULL; - int i; - cairo_matrix_t old_ctm; - cairo_bool_t old_has_ctm; - cairo_solid_pattern_t clear; - cairo_composite_rectangles_t extents; - cairo_bool_t overlap; - - status = _cairo_composite_rectangles_init_for_glyphs (&extents, - &surface->win32.base, - op, source, - scaled_font, - glyphs, num_glyphs, - clip, - &overlap); - if (unlikely (status)) - return status; - - status = _cairo_surface_clipper_set_clip (&surface->clipper, clip); - if (unlikely (status)) - goto cleanup_composite; - - if (op == CAIRO_OPERATOR_CLEAR) { - _cairo_win32_printing_surface_init_clear_color (surface, &clear); - source = (cairo_pattern_t*) &clear; - op = CAIRO_OPERATOR_SOURCE; - } - - if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) { - /* When printing bitmap fonts to a printer DC, Windows may - * substitute an outline font for bitmap font. As the win32 - * font backend always uses a screen DC when obtaining the - * font metrics the metrics of the substituted font will not - * match the metrics that the win32 font backend returns. - * - * If we are printing a bitmap font, use fallback images to - * ensure the font is not substituted. - */ -#if CAIRO_HAS_WIN32_FONT - if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32) { - if (_cairo_win32_scaled_font_is_bitmap (scaled_font)) { - status = CAIRO_INT_STATUS_UNSUPPORTED; - goto cleanup_composite; - } else { - status = _cairo_win32_printing_surface_analyze_operation (surface, op, source, &extents.bounded); - goto cleanup_composite; - } - } -#endif - - /* For non win32 fonts we need to check that each glyph has a - * path available. If a path is not available, - * _cairo_scaled_glyph_lookup() will return - * CAIRO_INT_STATUS_UNSUPPORTED and a fallback image will be - * used. - */ - _cairo_scaled_font_freeze_cache (scaled_font); - for (i = 0; i < num_glyphs; i++) { - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - if (status) - break; - } - _cairo_scaled_font_thaw_cache (scaled_font); - if (unlikely (status)) - goto cleanup_composite; - - status = _cairo_win32_printing_surface_analyze_operation (surface, op, source, &extents.bounded); - goto cleanup_composite; - } - - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) source; - COLORREF color; - - color = _cairo_win32_printing_surface_flatten_transparency (surface, - &solid->color); - opaque = cairo_pattern_create_rgb (GetRValue (color) / 255.0, - GetGValue (color) / 255.0, - GetBValue (color) / 255.0); - if (unlikely (opaque->status)) { - status = opaque->status; - goto cleanup_composite; - } - source = opaque; - } - -#if CAIRO_HAS_WIN32_FONT - if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 && - source->type == CAIRO_PATTERN_TYPE_SOLID) - { - status = _cairo_win32_printing_surface_emit_win32_glyphs (surface, - op, - source, - glyphs, - num_glyphs, - scaled_font, - clip); - goto cleanup_composite; - } -#endif - - SaveDC (surface->win32.dc); - old_ctm = surface->ctm; - old_has_ctm = surface->has_ctm; - surface->has_ctm = TRUE; - surface->path_empty = TRUE; - _cairo_scaled_font_freeze_cache (scaled_font); - BeginPath (surface->win32.dc); - for (i = 0; i < num_glyphs; i++) { - status = _cairo_scaled_glyph_lookup (scaled_font, - glyphs[i].index, - CAIRO_SCALED_GLYPH_INFO_PATH, - &scaled_glyph); - if (status) - break; - surface->ctm = old_ctm; - cairo_matrix_translate (&surface->ctm, glyphs[i].x, glyphs[i].y); - status = _cairo_win32_printing_surface_emit_path (surface, scaled_glyph->path); - } - EndPath (surface->win32.dc); - _cairo_scaled_font_thaw_cache (scaled_font); - surface->ctm = old_ctm; - surface->has_ctm = old_has_ctm; - if (status == CAIRO_STATUS_SUCCESS && surface->path_empty == FALSE) { - if (source->type == CAIRO_PATTERN_TYPE_SOLID) { - status = _cairo_win32_printing_surface_select_solid_brush (surface, source); - if (unlikely (status)) - goto cleanup_composite; - - SetPolyFillMode (surface->win32.dc, WINDING); - FillPath (surface->win32.dc); - _cairo_win32_printing_surface_done_solid_brush (surface); - } else { - SelectClipPath (surface->win32.dc, RGN_AND); - status = _cairo_win32_printing_surface_paint_pattern (surface, source, &extents.bounded); - } - } - RestoreDC (surface->win32.dc, -1); - - if (opaque) - cairo_pattern_destroy (opaque); - -cleanup_composite: - _cairo_composite_rectangles_fini (&extents); - return status; -} - -static const char ** -_cairo_win32_printing_surface_get_supported_mime_types (void *abstract_surface) -{ - return _cairo_win32_printing_supported_mime_types; -} - -static cairo_status_t -_cairo_win32_printing_surface_finish (void *abstract_surface) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - - if (surface->font_subsets != NULL) - _cairo_scaled_font_subsets_destroy (surface->font_subsets); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_surface_t * -_cairo_win32_printing_surface_create_similar (void *abstract_surface, - cairo_content_t content, - int width, - int height) -{ - cairo_rectangle_t extents; - - extents.x = extents.y = 0; - extents.width = width; - extents.height = height; - return cairo_recording_surface_create (content, &extents); -} - -static cairo_int_status_t -_cairo_win32_printing_surface_start_page (void *abstract_surface) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - XFORM xform; - double x_res, y_res; - cairo_matrix_t inverse_ctm; - cairo_status_t status; - RECT rect; - - /* Since the page size may be changed after _show_page() and before the - * next drawing command, the extents are set in _start_page() and invalidated - * in _show_page(). The paginated surface will obtain the extents immediately - * after calling _show_page() and before any drawing commands. At this point - * the next page will not have been setup on the DC so we return invalid - * extents and the paginated surface will create an unbounded recording surface. - * Prior to replay of the record surface, the paginated surface will call - * _start_page and we setup the correct extents. - * - * Note that we always set the extents x,y to 0 so prevent replay from translating - * the coordinates of objects. Windows will clip anything outside of the page clip - * area. - */ - GetClipBox(surface->win32.dc, &rect); - surface->win32.extents.x = 0; - surface->win32.extents.y = 0; - surface->win32.extents.width = rect.right; - surface->win32.extents.height = rect.bottom; - surface->extents_valid = TRUE; - - SaveDC (surface->win32.dc); /* Save application context first, before doing MWT */ - - /* As the logical coordinates used by GDI functions (eg LineTo) - * are integers we need to do some additional work to prevent - * rounding errors. For example the obvious way to paint a recording - * pattern is to: - * - * SaveDC() - * transform the device context DC by the pattern to device matrix - * replay the recording surface - * RestoreDC() - * - * The problem here is that if the pattern to device matrix is - * [100 0 0 100 0 0], coordinates in the recording pattern such as - * (1.56, 2.23) which correspond to (156, 223) in device space - * will be rounded to (100, 200) due to (1.56, 2.23) being - * truncated to integers. - * - * This is solved by saving the current GDI CTM in surface->ctm, - * switch the GDI CTM to identity, and transforming all - * coordinates by surface->ctm before passing them to GDI. When - * painting a recording pattern, surface->ctm is transformed by the - * pattern to device matrix. - * - * For printing device contexts where 1 unit is 1 dpi, switching - * the GDI CTM to identity maximises the possible resolution of - * coordinates. - * - * If the device context is an EMF file, using an identity - * transform often provides insufficent resolution. The workaround - * is to set the GDI CTM to a scale < 1 eg [1.0/16 0 0 1/0/16 0 0] - * and scale the cairo CTM by [16 0 0 16 0 0]. The - * SetWorldTransform function call to scale the GDI CTM by 1.0/16 - * will be recorded in the EMF followed by all the graphics - * functions by their coordinateds multiplied by 16. - * - * To support allowing the user to set a GDI CTM with scale < 1, - * we avoid switching to an identity CTM if the CTM xx and yy is < 1. - */ - SetGraphicsMode (surface->win32.dc, GM_ADVANCED); - GetWorldTransform(surface->win32.dc, &xform); - if (xform.eM11 < 1 && xform.eM22 < 1) { - cairo_matrix_init_identity (&surface->ctm); - surface->gdi_ctm.xx = xform.eM11; - surface->gdi_ctm.xy = xform.eM21; - surface->gdi_ctm.yx = xform.eM12; - surface->gdi_ctm.yy = xform.eM22; - surface->gdi_ctm.x0 = xform.eDx; - surface->gdi_ctm.y0 = xform.eDy; - } else { - surface->ctm.xx = xform.eM11; - surface->ctm.xy = xform.eM21; - surface->ctm.yx = xform.eM12; - surface->ctm.yy = xform.eM22; - 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"); - } - - surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm); - surface->has_gdi_ctm = !_cairo_matrix_is_identity (&surface->gdi_ctm); - inverse_ctm = surface->ctm; - status = cairo_matrix_invert (&inverse_ctm); - if (status) - return status; - - x_res = GetDeviceCaps (surface->win32.dc, LOGPIXELSX); - y_res = GetDeviceCaps (surface->win32.dc, LOGPIXELSY); - cairo_matrix_transform_distance (&inverse_ctm, &x_res, &y_res); - _cairo_surface_set_resolution (&surface->win32.base, x_res, y_res); - - SaveDC (surface->win32.dc); /* Then save Cairo's known-good clip state, so the clip path can be reset */ - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_int_status_t -_cairo_win32_printing_surface_set_paginated_mode (void *abstract_surface, - cairo_paginated_mode_t paginated_mode) -{ - cairo_win32_printing_surface_t *surface = abstract_surface; - - surface->paginated_mode = paginated_mode; - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_surface) -{ - return TRUE; -} - -/** - * cairo_win32_printing_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 DC should be a printing DC; - * antialiasing will be ignored, and GDI will be used as much as - * possible to draw to the surface. - * - * The returned surface will be wrapped using the paginated surface to - * provide correct complex rendering behaviour; cairo_surface_show_page() and - * associated methods must be used for correct output. - * - * Return value: the newly created surface - * - * Since: 1.6 - **/ -cairo_surface_t * -cairo_win32_printing_surface_create (HDC hdc) -{ - cairo_win32_printing_surface_t *surface; - cairo_surface_t *paginated; - - surface = _cairo_malloc (sizeof (cairo_win32_printing_surface_t)); - if (surface == NULL) - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - -#if 0 - if (_cairo_win32_save_initial_clip (hdc, surface) != CAIRO_STATUS_SUCCESS) { - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } -#endif - - _cairo_surface_clipper_init (&surface->clipper, - _cairo_win32_printing_surface_clipper_intersect_clip_path); - - surface->win32.format = CAIRO_FORMAT_RGB24; - surface->content = CAIRO_CONTENT_COLOR_ALPHA; - - surface->win32.dc = hdc; - surface->extents_valid = FALSE; - - surface->brush = NULL; - surface->old_brush = NULL; - surface->font_subsets = _cairo_scaled_font_subsets_create_scaled (); - if (surface->font_subsets == NULL) { - free (surface); - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - } - - surface->win32.flags = _cairo_win32_flags_for_dc (surface->win32.dc, CAIRO_FORMAT_RGB24); - surface->win32.flags |= CAIRO_WIN32_SURFACE_FOR_PRINTING; - - _cairo_win32_printing_surface_init_ps_mode (surface); - _cairo_win32_printing_surface_init_image_support (surface); - _cairo_win32_printing_surface_init_language_pack (surface); - _cairo_surface_init (&surface->win32.base, - &cairo_win32_printing_surface_backend, - NULL, /* device */ - CAIRO_CONTENT_COLOR_ALPHA, - TRUE); /* is_vector */ - - paginated = _cairo_paginated_surface_create (&surface->win32.base, - CAIRO_CONTENT_COLOR_ALPHA, - &cairo_win32_surface_paginated_backend); - - /* paginated keeps the only reference to surface now, drop ours */ - cairo_surface_destroy (&surface->win32.base); - - return paginated; -} - -static const cairo_surface_backend_t cairo_win32_printing_surface_backend = { - CAIRO_SURFACE_TYPE_WIN32_PRINTING, - _cairo_win32_printing_surface_finish, - - _cairo_default_context_create, - - _cairo_win32_printing_surface_create_similar, - NULL, /* create similar image */ - NULL, /* map to image */ - NULL, /* unmap image */ - - _cairo_surface_default_source, - NULL, /* acquire_source_image */ - NULL, /* release_source_image */ - NULL, /* snapshot */ - - NULL, /* copy_page */ - _cairo_win32_printing_surface_show_page, - - _cairo_win32_printing_surface_get_extents, - _cairo_win32_printing_surface_get_font_options, - - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - - _cairo_win32_printing_surface_paint, - NULL, /* mask */ - _cairo_win32_printing_surface_stroke, - _cairo_win32_printing_surface_fill, - NULL, /* fill/stroke */ - _cairo_win32_printing_surface_show_glyphs, - NULL, /* has_show_text_glyphs */ - NULL, /* show_text_glyphs */ - _cairo_win32_printing_surface_get_supported_mime_types, -}; - -static const cairo_paginated_surface_backend_t cairo_win32_surface_paginated_backend = { - _cairo_win32_printing_surface_start_page, - _cairo_win32_printing_surface_set_paginated_mode, - NULL, /* set_bounding_box */ - NULL, /* _cairo_win32_printing_surface_has_fallback_images, */ - _cairo_win32_printing_surface_supports_fine_grained_fallbacks, -}; diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-private.h b/libs/cairo-1.16.0/src/win32/cairo-win32-private.h deleted file mode 100644 index 85f88a9..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-private.h +++ /dev/null @@ -1,248 +0,0 @@ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - */ - -#ifndef CAIRO_WIN32_PRIVATE_H -#define CAIRO_WIN32_PRIVATE_H - -#include "cairo-win32.h" - -#include "cairoint.h" - -#include "cairo-device-private.h" -#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 - -/* Surface DC flag values */ -enum { - /* If this is a surface created for printing or not */ - CAIRO_WIN32_SURFACE_FOR_PRINTING = (1<<0), - - /* Whether the DC is a display DC or not */ - CAIRO_WIN32_SURFACE_IS_DISPLAY = (1<<1), - - /* Whether we can use BitBlt with this surface */ - CAIRO_WIN32_SURFACE_CAN_BITBLT = (1<<2), - - /* Whether we can use AlphaBlend with this surface */ - CAIRO_WIN32_SURFACE_CAN_ALPHABLEND = (1<<3), - - /* Whether we can use StretchBlt with this surface */ - CAIRO_WIN32_SURFACE_CAN_STRETCHBLT = (1<<4), - - /* Whether we can use StretchDIBits with this surface */ - CAIRO_WIN32_SURFACE_CAN_STRETCHDIB = (1<<5), - - /* Whether we can use GradientFill rectangles with this surface */ - CAIRO_WIN32_SURFACE_CAN_RECT_GRADIENT = (1<<6), - - /* Whether we can use the CHECKJPEGFORMAT escape function */ - CAIRO_WIN32_SURFACE_CAN_CHECK_JPEG = (1<<7), - - /* Whether we can use the CHECKPNGFORMAT escape function */ - CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8), - - /* Whether we can use gdi drawing with solid rgb brush with this surface */ - CAIRO_WIN32_SURFACE_CAN_RGB_BRUSH = (1<<9), -}; - -typedef struct _cairo_win32_surface { - cairo_surface_t base; - - cairo_format_t format; - HDC dc; - - /* Surface DC flags */ - unsigned flags; - - /* We use the x and y parts of extents for situations where - * we're not supposed to draw to the entire surface. - * For example, during a paint event a program will get - * a DC that has been clipped to the dirty region. - * A cairo surface constructed for that DC will have extents - * that match bounds of the clipped region. - */ - cairo_rectangle_int_t extents; - - /* Offset added to extents, used when the extents start with a negative - * offset, which can occur on Windows for, and only for, desktop DC. This - * occurs when you have multiple monitors, and at least one monitor - * extends to the left, or above, the primaty monitor. The primary - * monitor on Windows always starts with offset (0,0), and any other points - * to the left, or above, have negative offsets. So the 'desktop DC' is - * in fact a 'virtual desktop' which can start with extents in the negative - * range. - * - * Why use new variables, and not the device transform? Simply because since - * the device transform functions are exposed, a lot of 3rd party libraries - * simply overwrite those, disregarding the prior content, instead of actually - * adding the offset. GTK for example simply resets the device transform of the - * desktop cairo surface to zero. So make some private member variables for - * this, which will not be fiddled with externally. - */ - int x_ofs, y_ofs; -} cairo_win32_surface_t; -#define to_win32_surface(S) ((cairo_win32_surface_t *)(S)) - -typedef struct _cairo_win32_display_surface { - cairo_win32_surface_t win32; - - /* We create off-screen surfaces as DIBs or DDBs, based on what we created - * originally */ - HBITMAP bitmap; - cairo_bool_t is_dib; - - /* Used to save the initial 1x1 monochrome bitmap for the DC to - * select back into the DC before deleting the DC and our - * bitmap. For Windows XP, this doesn't seem to be necessary - * ... we can just delete the DC and that automatically unselects - * our bitmap. But it's standard practice so apparently is needed - * on some versions of Windows. - */ - HBITMAP saved_dc_bitmap; - cairo_surface_t *image; - cairo_surface_t *fallback; - - HRGN initial_clip_rgn; - cairo_bool_t had_simple_clip; -} cairo_win32_display_surface_t; -#define to_win32_display_surface(S) ((cairo_win32_display_surface_t *)(S)) - -typedef struct _cairo_win32_printing_surface { - cairo_win32_surface_t win32; - - cairo_surface_clipper_t clipper; - - cairo_paginated_mode_t paginated_mode; - cairo_content_t content; - cairo_bool_t path_empty; - cairo_bool_t has_ctm; - cairo_matrix_t ctm; - cairo_bool_t has_gdi_ctm; - cairo_matrix_t gdi_ctm; - cairo_bool_t extents_valid; - HBRUSH brush, old_brush; - cairo_scaled_font_subsets_t *font_subsets; -} 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) - -cairo_private cairo_device_t * -_cairo_win32_device_get (void); - -const cairo_compositor_t * -_cairo_win32_gdi_compositor_get (void); - -cairo_status_t -_cairo_win32_print_gdi_error (const char *context); - -cairo_private void -_cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface); - -cairo_bool_t -_cairo_win32_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle); - -uint32_t -_cairo_win32_flags_for_dc (HDC dc, cairo_format_t format); - -cairo_int_status_t -_cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_bool_t glyph_indexing); - -static inline void -_cairo_matrix_to_win32_xform (const cairo_matrix_t *m, - XFORM *xform) -{ - xform->eM11 = (FLOAT) m->xx; - xform->eM21 = (FLOAT) m->xy; - xform->eM12 = (FLOAT) m->yx; - xform->eM22 = (FLOAT) m->yy; - xform->eDx = (FLOAT) m->x0; - xform->eDy = (FLOAT) m->y0; -} - -cairo_status_t -_cairo_win32_display_surface_set_clip (cairo_win32_display_surface_t *surface, - cairo_clip_t *clip); - -void -_cairo_win32_display_surface_unset_clip (cairo_win32_display_surface_t *surface); - -void -_cairo_win32_debug_dump_hrgn (HRGN rgn, char *header); - -cairo_bool_t -_cairo_win32_scaled_font_is_type1 (cairo_scaled_font_t *scaled_font); - -cairo_bool_t -_cairo_win32_scaled_font_is_bitmap (cairo_scaled_font_t *scaled_font); - -#endif /* CAIRO_WIN32_PRIVATE_H */ diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-surface.c b/libs/cairo-1.16.0/src/win32/cairo-win32-surface.c deleted file mode 100644 index f7285b9..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-surface.c +++ /dev/null @@ -1,334 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc. - * Copyright © 2012 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Stuart Parmenter - * Vladimir Vukicevic - */ - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include "cairoint.h" - -#include "cairo-default-context-private.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-paginated-private.h" -#include "cairo-pattern-private.h" -#include "cairo-win32-private.h" -#include "cairo-scaled-font-subsets-private.h" -#include "cairo-surface-fallback-private.h" -#include "cairo-surface-backend-private.h" - -#include -#include - -#if defined(__MINGW32__) && !defined(ETO_PDY) -# define ETO_PDY 0x2000 -#endif - -/** - * SECTION:cairo-win32 - * @Title: Win32 Surfaces - * @Short_Description: Microsoft Windows surface support - * @See_Also: #cairo_surface_t - * - * The Microsoft Windows surface is used to render cairo graphics to - * Microsoft Windows windows, bitmaps, and printing device contexts. - * - * The surface returned by cairo_win32_printing_surface_create() is of surface - * type %CAIRO_SURFACE_TYPE_WIN32_PRINTING and is a multi-page vector surface - * type. - * - * The surface returned by the other win32 constructors is of surface type - * %CAIRO_SURFACE_TYPE_WIN32 and is a raster surface type. - **/ - -/** - * CAIRO_HAS_WIN32_SURFACE: - * - * Defined if the Microsoft Windows surface backend is available. - * This macro can be used to conditionally compile backend-specific code. - * - * 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_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) -{ - cairo_win32_surface_t *surface = abstract_surface; - - *rectangle = surface->extents; - return TRUE; -} - -/** - * cairo_win32_surface_get_dc: - * @surface: a #cairo_surface_t - * - * Returns the HDC associated with this surface, or %NULL if none. - * Also returns %NULL if the surface is not a win32 surface. - * - * A call to cairo_surface_flush() is required before using the HDC to - * ensure that all pending drawing operations are finished and to - * restore any temporary modification cairo has made to its state. A - * call to cairo_surface_mark_dirty() is required after the state or - * the content of the HDC has been modified. - * - * Return value: HDC or %NULL if no HDC available. - * - * Since: 1.2 - **/ -HDC -cairo_win32_surface_get_dc (cairo_surface_t *surface) -{ - if (surface->backend->type == CAIRO_SURFACE_TYPE_WIN32) - return to_win32_surface(surface)->dc; - - if (_cairo_surface_is_paginated (surface)) { - cairo_surface_t *target = _cairo_paginated_surface_get_target (surface); - if (target->backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING) - return to_win32_surface(target)->dc; - } - - return NULL; -} - -/** - * _cairo_surface_is_win32: - * @surface: a #cairo_surface_t - * - * Checks if a surface is an #cairo_win32_surface_t - * - * Return value: %TRUE if the surface is an win32 surface - **/ -static inline cairo_bool_t -_cairo_surface_is_win32 (const cairo_surface_t *surface) -{ - /* _cairo_surface_nil sets a NULL backend so be safe */ - return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_WIN32; -} - -/** - * cairo_win32_surface_get_image: - * @surface: a #cairo_surface_t - * - * Returns a #cairo_surface_t image surface that refers to the same bits - * as the DIB of the Win32 surface. If the passed-in win32 surface - * is not a DIB surface, %NULL is returned. - * - * Return value: a #cairo_surface_t (owned by the win32 #cairo_surface_t), - * or %NULL if the win32 surface is not a DIB. - * - * Since: 1.4 - **/ -cairo_surface_t * -cairo_win32_surface_get_image (cairo_surface_t *surface) -{ - - if (! _cairo_surface_is_win32 (surface)) { - return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); - } - - GdiFlush(); - return to_win32_display_surface(surface)->image; -} - -#define STACK_GLYPH_SIZE 256 -cairo_int_status_t -_cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst, - const cairo_pattern_t *source, - cairo_glyph_t *glyphs, - int num_glyphs, - cairo_scaled_font_t *scaled_font, - cairo_bool_t glyph_indexing) -{ -#if CAIRO_HAS_WIN32_FONT - WORD glyph_buf_stack[STACK_GLYPH_SIZE]; - WORD *glyph_buf = glyph_buf_stack; - int dxy_buf_stack[2 * STACK_GLYPH_SIZE]; - int *dxy_buf = dxy_buf_stack; - - BOOL win_result = 0; - int i, j; - - cairo_solid_pattern_t *solid_pattern; - COLORREF color; - - cairo_matrix_t device_to_logical; - - int start_x, start_y; - double user_x, user_y; - int logical_x, logical_y; - unsigned int glyph_index_option; - - /* We can only handle win32 fonts */ - assert (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32); - - /* We can only handle opaque solid color sources and destinations */ - assert (_cairo_pattern_is_opaque_solid(source)); - assert (dst->format == CAIRO_FORMAT_RGB24); - - solid_pattern = (cairo_solid_pattern_t *)source; - color = RGB(((int)solid_pattern->color.red_short) >> 8, - ((int)solid_pattern->color.green_short) >> 8, - ((int)solid_pattern->color.blue_short) >> 8); - - cairo_win32_scaled_font_get_device_to_logical(scaled_font, &device_to_logical); - - SaveDC(dst->dc); - - cairo_win32_scaled_font_select_font(scaled_font, dst->dc); - SetTextColor(dst->dc, color); - SetTextAlign(dst->dc, TA_BASELINE | TA_LEFT); - SetBkMode(dst->dc, TRANSPARENT); - - if (num_glyphs > STACK_GLYPH_SIZE) { - glyph_buf = (WORD *) _cairo_malloc_ab (num_glyphs, sizeof(WORD)); - dxy_buf = (int *) _cairo_malloc_abc (num_glyphs, sizeof(int), 2); - } - - /* It is vital that dx values for dxy_buf are calculated from the delta of - * _logical_ x coordinates (not user x coordinates) or else the sum of all - * previous dx values may start to diverge from the current glyph's x - * coordinate due to accumulated rounding error. As a result strings could - * be painted shorter or longer than expected. */ - - user_x = glyphs[0].x; - user_y = glyphs[0].y; - - cairo_matrix_transform_point(&device_to_logical, - &user_x, &user_y); - - logical_x = _cairo_lround (user_x); - logical_y = _cairo_lround (user_y); - - start_x = logical_x; - start_y = logical_y; - - for (i = 0, j = 0; i < num_glyphs; ++i, j = 2 * i) { - glyph_buf[i] = (WORD) glyphs[i].index; - if (i == num_glyphs - 1) { - dxy_buf[j] = 0; - dxy_buf[j+1] = 0; - } else { - double next_user_x = glyphs[i+1].x; - double next_user_y = glyphs[i+1].y; - int next_logical_x, next_logical_y; - - cairo_matrix_transform_point(&device_to_logical, - &next_user_x, &next_user_y); - - next_logical_x = _cairo_lround (next_user_x); - next_logical_y = _cairo_lround (next_user_y); - - dxy_buf[j] = _cairo_lround (next_logical_x - logical_x); - dxy_buf[j+1] = _cairo_lround (next_logical_y - logical_y); - - logical_x = next_logical_x; - logical_y = next_logical_y; - } - } - - if (glyph_indexing) - glyph_index_option = ETO_GLYPH_INDEX; - else - glyph_index_option = 0; - - win_result = ExtTextOutW(dst->dc, - start_x, - start_y, - glyph_index_option | ETO_PDY, - NULL, - glyph_buf, - num_glyphs, - dxy_buf); - if (!win_result) { - _cairo_win32_print_gdi_error("_cairo_win32_surface_show_glyphs(ExtTextOutW failed)"); - } - - RestoreDC(dst->dc, -1); - - if (glyph_buf != glyph_buf_stack) { - free(glyph_buf); - free(dxy_buf); - } - return (win_result) ? CAIRO_STATUS_SUCCESS : CAIRO_INT_STATUS_UNSUPPORTED; -#else - return CAIRO_INT_STATUS_UNSUPPORTED; -#endif -} -#undef STACK_GLYPH_SIZE diff --git a/libs/cairo-1.16.0/src/win32/cairo-win32-system.c b/libs/cairo-1.16.0/src/win32/cairo-win32-system.c deleted file mode 100644 index 8785530..0000000 --- a/libs/cairo-1.16.0/src/win32/cairo-win32-system.c +++ /dev/null @@ -1,89 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* Cairo - a vector graphics library with display and print output - * - * Copyright © 2005 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Owen Taylor - * Stuart Parmenter - * Vladimir Vukicevic - */ - -/* This file should include code that is system-specific, not - * feature-specific. For example, the DLL initialization/finalization - * code on Win32 or OS/2 must live here (not in cairo-whatever-surface.c). - * Same about possible ELF-specific code. - * - * And no other function should live here. - */ - - -#include "cairoint.h" - -#if CAIRO_MUTEX_IMPL_WIN32 -#if !CAIRO_WIN32_STATIC_BUILD - -#define WIN32_LEAN_AND_MEAN -/* We require Windows 2000 features such as ETO_PDY */ -#if !defined(WINVER) || (WINVER < 0x0500) -# define WINVER 0x0500 -#endif -#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500) -# define _WIN32_WINNT 0x0500 -#endif - -#include - -/* 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) -{ - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - CAIRO_MUTEX_INITIALIZE (); - break; - - case DLL_PROCESS_DETACH: - CAIRO_MUTEX_FINALIZE (); - break; - } - - return TRUE; -} - -#endif -#endif -- cgit v1.2.1