Merge branch 'win32-color-fonts' into 'master'

Windows color fonts

See merge request cairo/cairo!244
This commit is contained in:
Adrian Johnson 2022-03-05 03:54:58 +00:00
commit 135327c112
23 changed files with 2546 additions and 12 deletions

View file

@ -1,4 +1,4 @@
project('cairo', 'c',
project('cairo', 'c', 'cpp',
meson_version: '>= 0.56.0',
version: run_command(find_program('version.py'), check: true).stdout().strip(),
default_options: ['warning_level=2'],
@ -501,6 +501,35 @@ if host_machine.system() == 'windows'
'deps': win32_extra_deps,
}
]
cpp_compiler = meson.get_compiler('cpp')
d2d_dep = cpp_compiler.find_library('d2d1', required: false)
dwrite_dep = cpp_compiler.find_library('dwrite', required: false)
d2d_header = cpp_compiler.has_header('d2d1.h')
d2d_3_header = cpp_compiler.has_header('d2d1_3.h')
dwrite_header = cpp_compiler.has_header('dwrite.h')
dwrite_3_header = cpp_compiler.has_header('dwrite_3.h')
wincodec_dep = cpp_compiler.find_library('windowscodecs', required: false)
wincodec_header = cpp_compiler.has_header('wincodec.h')
if d2d_dep.found() and dwrite_dep.found() and d2d_header and dwrite_header and wincodec_dep.found() and wincodec_header
feature_conf.set('CAIRO_HAS_DWRITE_FONT', 1)
built_features += [{
'name': 'cairo-win32-dwrite-font',
'description': 'Microsoft Windows DWrite font backend',
'deps': [dwrite_dep, d2d_dep, wincodec_dep],
}]
deps += [dwrite_dep, d2d_dep, wincodec_dep]
if cpp_compiler.has_header('d2d1_3.h')
conf.set('HAVE_D2D1_3_H', 1)
endif
# Exclude MinGW dwrite_3.h because it has a broken definition of DWRITE_COLOR_GLYPH_RUN1.
if cpp_compiler.has_header('dwrite_3.h') and cpp_compiler.get_define('__MINGW32__') == ''
conf.set('HAVE_DWRITE_3_H', 1)
endif
endif
endif
# GL / GLESV2 / GLESV3 are mutually exclusive
@ -941,6 +970,7 @@ summary({
'FreeType': feature_conf.get('CAIRO_HAS_FT_FONT', 0) == 1,
'Fontconfig': feature_conf.get('CAIRO_HAS_FC_FONT', 0) == 1,
'Win32': feature_conf.get('CAIRO_HAS_WIN32_FONT', 0) == 1,
'Win32 DWrite': feature_conf.get('CAIRO_HAS_DWRITE_FONT', 0) == 1,
'Quartz': feature_conf.get('CAIRO_HAS_QUARTZ_FONT', 0) == 1,
}, section: 'Font Backends', bool_yn: true)

View file

@ -313,7 +313,7 @@ _cairo_atomic_int_cmpxchg (cairo_atomic_int_t *x,
cairo_atomic_int_t oldv,
cairo_atomic_int_t newv)
{
return InterlockedCompareExchange (x, newv, oldv) == oldv;
return InterlockedCompareExchange ((unsigned int*)x, (unsigned int)newv, (unsigned int)oldv) == oldv;
}
static cairo_always_inline void *

View file

@ -163,6 +163,7 @@ _cairo_device_create_in_error (cairo_status_t status)
case CAIRO_STATUS_FREETYPE_ERROR:
case CAIRO_STATUS_WIN32_GDI_ERROR:
case CAIRO_STATUS_TAG_ERROR:
case CAIRO_STATUS_DWRITE_ERROR:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_device_t *) &_nil_device;

View file

@ -98,6 +98,7 @@ enum _cairo_int_status {
CAIRO_INT_STATUS_FREETYPE_ERROR,
CAIRO_INT_STATUS_WIN32_GDI_ERROR,
CAIRO_INT_STATUS_TAG_ERROR,
CAIRO_INT_STATUS_DWRITE_ERROR,
CAIRO_INT_STATUS_LAST_STATUS,

View file

@ -174,6 +174,8 @@ cairo_status_to_string (cairo_status_t status)
return "error occurred in the Windows Graphics Device Interface";
case CAIRO_STATUS_TAG_ERROR:
return "invalid tag name, attributes, or nesting";
case CAIRO_STATUS_DWRITE_ERROR:
return "Window Direct Write error";
default:
case CAIRO_STATUS_LAST_STATUS:
return "<unknown error status>";

View file

@ -111,6 +111,7 @@ _cairo_region_create_in_error (cairo_status_t status)
case CAIRO_STATUS_FREETYPE_ERROR:
case CAIRO_STATUS_WIN32_GDI_ERROR:
case CAIRO_STATUS_TAG_ERROR:
case CAIRO_STATUS_DWRITE_ERROR:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_region_t *) &_cairo_region_nil;

View file

@ -132,6 +132,7 @@ _cairo_scan_converter_create_in_error (cairo_status_t status)
case CAIRO_STATUS_FREETYPE_ERROR:
case CAIRO_STATUS_WIN32_GDI_ERROR:
case CAIRO_STATUS_TAG_ERROR:
case CAIRO_STATUS_DWRITE_ERROR:
default:
break;
}
@ -249,6 +250,7 @@ _cairo_span_renderer_create_in_error (cairo_status_t status)
case CAIRO_STATUS_FREETYPE_ERROR: RETURN_NIL;
case CAIRO_STATUS_WIN32_GDI_ERROR: RETURN_NIL;
case CAIRO_STATUS_TAG_ERROR: RETURN_NIL;
case CAIRO_STATUS_DWRITE_ERROR: RETURN_NIL;
default:
break;
}

View file

@ -3073,6 +3073,7 @@ _cairo_surface_create_in_error (cairo_status_t status)
case CAIRO_STATUS_PNG_ERROR:
case CAIRO_STATUS_FREETYPE_ERROR:
case CAIRO_STATUS_WIN32_GDI_ERROR:
case CAIRO_INT_STATUS_DWRITE_ERROR:
case CAIRO_STATUS_TAG_ERROR:
default:
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);

View file

@ -107,6 +107,16 @@ cairo_win32_scaled_font_get_device_to_logical (cairo_scaled_font_t *scaled_font,
#endif /* CAIRO_HAS_WIN32_FONT */
#if CAIRO_HAS_DWRITE_FONT
/*
* Win32 DirectWrite font support
*/
cairo_public cairo_font_face_t *
cairo_dwrite_font_face_create_for_dwrite_fontface (void *dwrite_font_face);
#endif /* CAIRO_HAS_DWRITE_FONT */
CAIRO_END_DECLS
#else /* CAIRO_HAS_WIN32_SURFACE */

View file

@ -371,8 +371,8 @@ static const cairo_t _cairo_nil[] = {
DEFINE_NIL_CONTEXT (CAIRO_STATUS_PNG_ERROR),
DEFINE_NIL_CONTEXT (CAIRO_STATUS_FREETYPE_ERROR),
DEFINE_NIL_CONTEXT (CAIRO_STATUS_WIN32_GDI_ERROR),
DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR)
DEFINE_NIL_CONTEXT (CAIRO_STATUS_TAG_ERROR),
DEFINE_NIL_CONTEXT (CAIRO_STATUS_DWRITE_ERROR)
};
COMPILE_TIME_ASSERT (ARRAY_LENGTH (_cairo_nil) == CAIRO_STATUS_LAST_STATUS - 1);

View file

@ -296,6 +296,7 @@ typedef struct _cairo_user_data_key {
* @CAIRO_STATUS_FREETYPE_ERROR: error occurred in libfreetype (Since 1.16)
* @CAIRO_STATUS_WIN32_GDI_ERROR: error occurred in the Windows Graphics Device Interface (Since 1.16)
* @CAIRO_STATUS_TAG_ERROR: invalid tag name, attributes, or nesting (Since 1.16)
* @CAIRO_STATUS_DWRITE_ERROR: error occurred in the Windows Direct Write API (Since 1.18)
* @CAIRO_STATUS_LAST_STATUS: this is a special value indicating the number of
* status values defined in this enumeration. When using this value, note
* that the version of cairo at run-time may have additional status values
@ -356,6 +357,7 @@ typedef enum _cairo_status {
CAIRO_STATUS_FREETYPE_ERROR,
CAIRO_STATUS_WIN32_GDI_ERROR,
CAIRO_STATUS_TAG_ERROR,
CAIRO_STATUS_DWRITE_ERROR,
CAIRO_STATUS_LAST_STATUS
} cairo_status_t;
@ -1545,6 +1547,7 @@ cairo_font_face_status (cairo_font_face_t *font_face);
* @CAIRO_FONT_TYPE_QUARTZ: The font is of type Quartz (Since: 1.6, in 1.2 and
* 1.4 it was named CAIRO_FONT_TYPE_ATSUI)
* @CAIRO_FONT_TYPE_USER: The font was create using cairo's user font api (Since: 1.8)
* @CAIRO_FONT_TYPE_DWRITE: The font is of type Win32 DWrite (Since: 1.18)
*
* #cairo_font_type_t is used to describe the type of a given font
* face or scaled font. The font types are also known as "font
@ -1581,7 +1584,8 @@ typedef enum _cairo_font_type {
CAIRO_FONT_TYPE_FT,
CAIRO_FONT_TYPE_WIN32,
CAIRO_FONT_TYPE_QUARTZ,
CAIRO_FONT_TYPE_USER
CAIRO_FONT_TYPE_USER,
CAIRO_FONT_TYPE_DWRITE
} cairo_font_type_t;
cairo_public cairo_font_type_t

View file

@ -677,6 +677,12 @@ extern const cairo_private struct _cairo_font_face_backend _cairo_win32_font_fac
#endif
#if CAIRO_HAS_DWRITE_FONT
extern const cairo_private struct _cairo_font_face_backend _cairo_dwrite_font_face_backend;
#endif
#if CAIRO_HAS_QUARTZ_FONT
extern const cairo_private struct _cairo_font_face_backend _cairo_quartz_font_face_backend;
@ -705,11 +711,17 @@ struct _cairo_surface_attributes {
#define CAIRO_FONT_WEIGHT_DEFAULT CAIRO_FONT_WEIGHT_NORMAL
#define CAIRO_WIN32_FONT_FAMILY_DEFAULT "Arial"
#define CAIRO_DWRITE_FONT_FAMILY_DEFAULT "Arial"
#define CAIRO_QUARTZ_FONT_FAMILY_DEFAULT "Helvetica"
#define CAIRO_FT_FONT_FAMILY_DEFAULT ""
#define CAIRO_USER_FONT_FAMILY_DEFAULT "@cairo:"
#if CAIRO_HAS_WIN32_FONT
#if CAIRO_HAS_DWRITE_FONT
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_DWRITE_FONT_FAMILY_DEFAULT
#define CAIRO_FONT_FACE_BACKEND_DEFAULT &_cairo_dwrite_font_face_backend
#elif CAIRO_HAS_WIN32_FONT
#define CAIRO_FONT_FAMILY_DEFAULT CAIRO_WIN32_FONT_FAMILY_DEFAULT
#define CAIRO_FONT_FACE_BACKEND_DEFAULT &_cairo_win32_font_face_backend

View file

@ -177,6 +177,9 @@ cairo_feature_sources = {
'cairo-win32-font': [
'win32/cairo-win32-font.c',
],
'cairo-win32-dwrite-font': [
'win32/cairo-dwrite-font.cpp',
],
'cairo-gl': [
'cairo-gl-composite.c',
'cairo-gl-device.c',

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,266 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* Cairo - a vector graphics library with display and print output
*
* Copyright © 2010 Mozilla Foundation
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 the Mozilla Foundation
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*/
#include "cairoint.h"
#include <dwrite.h>
#include <d2d1.h>
/* If either of the dwrite_2.h or d2d1_3.h headers required for color fonts
* is not available, include our own version containing just the functions we need.
*/
#if HAVE_DWRITE_3_H
#include <dwrite_3.h>
#else
#include "dw-extra.h"
#endif
#if HAVE_D2D1_3_H
#include <d2d1_3.h>
#else
#include "d2d1-extra.h"
#endif
// DirectWrite is not available on all platforms.
typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
DWRITE_FACTORY_TYPE factoryType,
REFIID iid,
IUnknown **factory
);
/* #cairo_scaled_font_t implementation */
struct _cairo_dwrite_scaled_font {
cairo_scaled_font_t base;
cairo_matrix_t mat;
cairo_matrix_t mat_inverse;
cairo_antialias_t antialias_mode;
DWRITE_MEASURING_MODE measuring_mode;
enum TextRenderingState {
TEXT_RENDERING_UNINITIALIZED,
TEXT_RENDERING_NO_CLEARTYPE,
TEXT_RENDERING_NORMAL,
TEXT_RENDERING_GDI_CLASSIC
};
TextRenderingState rendering_mode;
};
typedef struct _cairo_dwrite_scaled_font cairo_dwrite_scaled_font_t;
class DWriteFactory
{
public:
static IDWriteFactory *Instance()
{
if (!mFactoryInstance) {
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
DWriteCreateFactoryFunc createDWriteFactory = (DWriteCreateFactoryFunc)
GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory");
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
if (createDWriteFactory) {
HRESULT hr = createDWriteFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&mFactoryInstance));
assert(SUCCEEDED(hr));
}
}
return mFactoryInstance;
}
static IDWriteFactory4 *Instance4()
{
if (!mFactoryInstance4) {
if (Instance()) {
Instance()->QueryInterface(&mFactoryInstance4);
}
}
return mFactoryInstance4;
}
static IDWriteFontCollection *SystemCollection()
{
if (!mSystemCollection) {
if (Instance()) {
HRESULT hr = Instance()->GetSystemFontCollection(&mSystemCollection);
assert(SUCCEEDED(hr));
}
}
return mSystemCollection;
}
static IDWriteFontFamily *FindSystemFontFamily(const WCHAR *aFamilyName)
{
UINT32 idx;
BOOL found;
if (!SystemCollection()) {
return NULL;
}
SystemCollection()->FindFamilyName(aFamilyName, &idx, &found);
if (!found) {
return NULL;
}
IDWriteFontFamily *family;
SystemCollection()->GetFontFamily(idx, &family);
return family;
}
static IDWriteRenderingParams *RenderingParams(cairo_dwrite_scaled_font_t::TextRenderingState mode)
{
if (!mDefaultRenderingParams ||
!mForceGDIClassicRenderingParams ||
!mCustomClearTypeRenderingParams)
{
CreateRenderingParams();
}
IDWriteRenderingParams *params;
if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE) {
params = mDefaultRenderingParams;
} else if (mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC && mRenderingMode < 0) {
params = mForceGDIClassicRenderingParams;
} else {
params = mCustomClearTypeRenderingParams;
}
if (params) {
params->AddRef();
}
return params;
}
static void SetRenderingParams(FLOAT aGamma,
FLOAT aEnhancedContrast,
FLOAT aClearTypeLevel,
int aPixelGeometry,
int aRenderingMode)
{
mGamma = aGamma;
mEnhancedContrast = aEnhancedContrast;
mClearTypeLevel = aClearTypeLevel;
mPixelGeometry = aPixelGeometry;
mRenderingMode = aRenderingMode;
// discard any current RenderingParams objects
if (mCustomClearTypeRenderingParams) {
mCustomClearTypeRenderingParams->Release();
mCustomClearTypeRenderingParams = NULL;
}
if (mForceGDIClassicRenderingParams) {
mForceGDIClassicRenderingParams->Release();
mForceGDIClassicRenderingParams = NULL;
}
if (mDefaultRenderingParams) {
mDefaultRenderingParams->Release();
mDefaultRenderingParams = NULL;
}
}
static int GetClearTypeRenderingMode() {
return mRenderingMode;
}
private:
static void CreateRenderingParams();
static IDWriteFactory *mFactoryInstance;
static IDWriteFactory4 *mFactoryInstance4;
static IDWriteFontCollection *mSystemCollection;
static IDWriteRenderingParams *mDefaultRenderingParams;
static IDWriteRenderingParams *mCustomClearTypeRenderingParams;
static IDWriteRenderingParams *mForceGDIClassicRenderingParams;
static FLOAT mGamma;
static FLOAT mEnhancedContrast;
static FLOAT mClearTypeLevel;
static int mPixelGeometry;
static int mRenderingMode;
};
class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN
{
static const int kNumAutoGlyphs = 256;
public:
AutoDWriteGlyphRun() {
glyphCount = 0;
}
~AutoDWriteGlyphRun() {
if (glyphCount > kNumAutoGlyphs) {
delete[] glyphIndices;
delete[] glyphAdvances;
delete[] glyphOffsets;
}
}
void allocate(int aNumGlyphs) {
glyphCount = aNumGlyphs;
if (aNumGlyphs <= kNumAutoGlyphs) {
glyphIndices = &mAutoIndices[0];
glyphAdvances = &mAutoAdvances[0];
glyphOffsets = &mAutoOffsets[0];
} else {
glyphIndices = new UINT16[aNumGlyphs];
glyphAdvances = new FLOAT[aNumGlyphs];
glyphOffsets = new DWRITE_GLYPH_OFFSET[aNumGlyphs];
}
}
private:
DWRITE_GLYPH_OFFSET mAutoOffsets[kNumAutoGlyphs];
FLOAT mAutoAdvances[kNumAutoGlyphs];
UINT16 mAutoIndices[kNumAutoGlyphs];
};
/* #cairo_font_face_t implementation */
struct _cairo_dwrite_font_face {
cairo_font_face_t base;
IDWriteFontFace *dwriteface;
cairo_bool_t have_color;
};
typedef struct _cairo_dwrite_font_face cairo_dwrite_font_face_t;
DWRITE_MATRIX _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix);
// This will initialize a DWrite glyph run from cairo glyphs and a scaled_font.
void
_cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
int num_glyphs,
cairo_dwrite_scaled_font_t *scaled_font,
AutoDWriteGlyphRun *run,
cairo_bool_t *transformed);

View file

@ -168,7 +168,7 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface,
case CAIRO_FORMAT_RGB30:
case CAIRO_FORMAT_RGB96F:
case CAIRO_FORMAT_RGBA128F:
ASSERT_NOT_REACHED;
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

View file

@ -286,8 +286,8 @@ _have_cleartype_quality (void)
version_info.dwMinorVersion >= 1)); /* XP or newer */
}
static BYTE
_get_system_quality (void)
BYTE
cairo_win32_get_system_text_quality (void)
{
BOOL font_smoothing;
UINT smoothing_type;
@ -354,7 +354,7 @@ _win32_scaled_font_create (LOGFONTW *logfont,
* here is the hint_metrics options.
*/
if (options->antialias == CAIRO_ANTIALIAS_DEFAULT)
f->quality = _get_system_quality ();
f->quality = cairo_win32_get_system_text_quality ();
else {
switch (options->antialias) {
case CAIRO_ANTIALIAS_NONE:

View file

@ -251,7 +251,7 @@ _cairo_win32_printing_surface_acquire_image_pattern (
case CAIRO_PATTERN_TYPE_MESH:
default:
ASSERT_NOT_REACHED;
break;
return CAIRO_INT_STATUS_UNSUPPORTED;
}
_cairo_pattern_init_for_surface (image_pattern, &image->base);
@ -1818,6 +1818,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
cairo_solid_pattern_t clear;
cairo_composite_rectangles_t extents;
cairo_bool_t overlap;
cairo_scaled_font_t *local_scaled_font = NULL;
status = _cairo_composite_rectangles_init_for_glyphs (&extents,
&surface->win32.base,
@ -1861,6 +1862,13 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
}
#endif
#if CAIRO_HAS_DWRITE_FONT
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_DWRITE) {
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
@ -1901,6 +1909,23 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
source = opaque;
}
#if CAIRO_HAS_DWRITE_FONT
/* For a printer, the dwrite path is not desirable as it goes through the
* bitmap-blitting GDI interop route. Better to create a win32 (GDI) font
* so that ExtTextOut can be used, giving the printer driver the chance
* to do the right thing with the text.
*/
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_DWRITE) {
status = _cairo_dwrite_scaled_font_create_win32_scaled_font (scaled_font, &local_scaled_font);
if (status == CAIRO_STATUS_SUCCESS) {
scaled_font = local_scaled_font;
} else {
/* Reset status; we'll fall back to drawing glyphs as paths */
status = CAIRO_STATUS_SUCCESS;
}
}
#endif
#if CAIRO_HAS_WIN32_FONT
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_WIN32 &&
source->type == CAIRO_PATTERN_TYPE_SOLID)
@ -1960,6 +1985,10 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
cleanup_composite:
_cairo_composite_rectangles_fini (&extents);
if (local_scaled_font)
cairo_scaled_font_destroy (local_scaled_font);
return status;
}
@ -2193,6 +2222,12 @@ cairo_win32_printing_surface_create (HDC hdc)
return paginated;
}
cairo_bool_t
_cairo_surface_is_win32_printing (const cairo_surface_t *surface)
{
return surface->backend && surface->backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING;
}
static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
_cairo_win32_printing_surface_finish,

View file

@ -53,6 +53,8 @@
#define WIN32_FONT_LOGICAL_SCALE 32
CAIRO_BEGIN_DECLS
/* Surface DC flag values */
enum {
/* If this is a surface created for printing or not */
@ -199,6 +201,12 @@ _cairo_win32_gdi_compositor_get (void);
cairo_status_t
_cairo_win32_print_gdi_error (const char *context);
cairo_bool_t
_cairo_surface_is_win32 (const cairo_surface_t *surface);
cairo_bool_t
_cairo_surface_is_win32_printing (const cairo_surface_t *surface);
cairo_private void
_cairo_win32_display_surface_discard_fallback (cairo_win32_display_surface_t *surface);
@ -245,4 +253,26 @@ _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);
cairo_public BYTE
cairo_win32_get_system_text_quality (void);
#if CAIRO_HAS_DWRITE_FONT
cairo_int_status_t
_cairo_dwrite_show_glyphs_on_surface (void *surface,
cairo_operator_t op,
const cairo_pattern_t *source,
cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font,
cairo_clip_t *clip);
cairo_int_status_t
_cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font,
cairo_scaled_font_t **new_font);
#endif /* CAIRO_HAS_DWRITE_FONT */
CAIRO_END_DECLS
#endif /* CAIRO_WIN32_PRIVATE_H */

View file

@ -0,0 +1,178 @@
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* Cairo - a vector graphics library with display and print output
*
* Copyright <A9> 2010 Mozilla Foundation
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 the Mozilla Foundation
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*/
#ifndef CAIRO_WIN32_REFPTR_H
#define CAIRO_WIN32_REFPTR_H
template<typename T> class TemporaryRef;
/*
* RefPtr points to a refcounted thing that has AddRef and Release
* methods to increase/decrease the refcount, respectively. After a
* RefPtr<T> is assigned a T*, the T* can be used through the RefPtr
* as if it were a T*.
*
* A RefPtr can forget its underlying T*, which results in the T*
* being wrapped in a temporary object until the T* is either
* re-adopted from or released by the temporary.
*/
template<typename T>
class RefPtr
{
// To allow them to use unref()
friend class TemporaryRef<T>;
struct dontRef {};
public:
RefPtr() : ptr(0) { }
RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
RefPtr(T* t) : ptr(ref(t)) {}
template<typename U>
RefPtr(const RefPtr<U>& o) : ptr(ref(o.get())) {}
~RefPtr() { unref(ptr); }
RefPtr& operator=(const RefPtr& o) {
assign(ref(o.ptr));
return *this;
}
RefPtr& operator=(const TemporaryRef<T>& o) {
assign(o.drop());
return *this;
}
RefPtr& operator=(T* t) {
assign(ref(t));
return *this;
}
template<typename U>
RefPtr& operator=(const RefPtr<U>& o) {
assign(ref(o.get()));
return *this;
}
TemporaryRef<T> forget() {
T* tmp = ptr;
ptr = 0;
return TemporaryRef<T>(tmp, dontRef());
}
T* get() const { return ptr; }
operator T*() const { return ptr; }
T* operator->() const { return ptr; }
T& operator*() const { return *ptr; }
template<typename U>
operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
/**
* WARNING for ease of use, passing a reference will release/clear out ptr!
* We null out the ptr before returning its address so people passing byref
* as input will most likely get functions returning errors rather than accessing
* freed memory. Further more accessing it after this point if it hasn't
* been set will produce a null pointer dereference.
*/
T** operator&()
{
if (ptr) {
ptr->Release();
ptr = NULL;
}
return &ptr;
}
private:
void assign(T* t) {
unref(ptr);
ptr = t;
}
T* ptr;
static inline T* ref(T* t) {
if (t) {
t->AddRef();
}
return t;
}
static inline void unref(T* t) {
if (t) {
t->Release();
}
}
};
/*
* TemporaryRef<T> represents an object that holds a temporary
* reference to a T. TemporaryRef objects can't be manually ref'd or
* unref'd (being temporaries, not lvalues), so can only relinquish
* references to other objects, or unref on destruction.
*/
template<typename T>
class TemporaryRef
{
// To allow it to construct TemporaryRef from a bare T*
friend class RefPtr<T>;
typedef typename RefPtr<T>::dontRef dontRef;
public:
TemporaryRef(T* t) : ptr(RefPtr<T>::ref(t)) {}
TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {}
template<typename U>
TemporaryRef(const TemporaryRef<U>& o) : ptr(o.drop()) {}
~TemporaryRef() { RefPtr<T>::unref(ptr); }
T* drop() const {
T* tmp = ptr;
ptr = 0;
return tmp;
}
private:
TemporaryRef(T* t, const dontRef&) : ptr(t) {}
mutable T* ptr;
TemporaryRef();
TemporaryRef& operator=(const TemporaryRef&);
};
#endif

View file

@ -48,6 +48,7 @@
#include "cairoint.h"
#include "cairo-backend-private.h"
#include "cairo-default-context-private.h"
#include "cairo-error-private.h"
#include "cairo-image-surface-private.h"
@ -178,7 +179,7 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
*
* Return value: %TRUE if the surface is an win32 surface
**/
static inline cairo_bool_t
cairo_bool_t
_cairo_surface_is_win32 (const cairo_surface_t *surface)
{
/* _cairo_surface_nil sets a NULL backend so be safe */
@ -219,6 +220,16 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
cairo_scaled_font_t *scaled_font,
cairo_bool_t glyph_indexing)
{
#if CAIRO_HAS_DWRITE_FONT
if (scaled_font->backend->type == CAIRO_FONT_TYPE_DWRITE) {
if (!glyph_indexing) return CAIRO_INT_STATUS_UNSUPPORTED;
// FIXME: fake values for params that aren't currently passed in here
cairo_operator_t op = CAIRO_OPERATOR_SOURCE;
cairo_clip_t *clip = NULL;
return _cairo_dwrite_show_glyphs_on_surface (dst, op, source, glyphs, num_glyphs, scaled_font, clip /* , glyph_indexing */ );
}
#endif
#if CAIRO_HAS_WIN32_FONT
WORD glyph_buf_stack[STACK_GLYPH_SIZE];
WORD *glyph_buf = glyph_buf_stack;

111
src/win32/d2d1-extra.h Normal file
View file

@ -0,0 +1,111 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* Mingw-w64 does not have d2d1_2.h and d2d2_3.h.
*
*
* We only need the definitions of two functions:
* ID2D1DeviceContext4::DrawColorBitmapGlyphRun()
* ID2D1DeviceContext4::DrawSvgGlyphRun()
*
* But we need to include all the prior functions in the same struct,
* and parent structs, so that the functions are in the correct position
* in the vtable. The parameters of the unused functions are not
* required as we only need a function in the struct to create a
* function pointer in the vtable.
*/
#ifndef D2D1_EXTRA_H
#define D2D1_EXTRA_H
#include <d2d1_1.h>
interface ID2D1DeviceContext1;
interface ID2D1DeviceContext2;
interface ID2D1DeviceContext3;
interface ID2D1DeviceContext4;
interface ID2D1SvgGlyphStyle;
enum D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION {
D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT,
D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DISABLE,
D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_FORCE_DWORD
};
DEFINE_GUID(IID_ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87);
MIDL_INTERFACE("d37f57e4-6908-459f-a199-e72f24f79987")
ID2D1DeviceContext1 : public ID2D1DeviceContext
{
virtual void STDMETHODCALLTYPE CreateFilledGeometryRealization() = 0;
virtual void STDMETHODCALLTYPE CreateStrokedGeometryRealization() = 0;
virtual void STDMETHODCALLTYPE DrawGeometryRealization() = 0;
};
__CRT_UUID_DECL(ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87)
DEFINE_GUID(IID_ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7);
MIDL_INTERFACE("394ea6a3-0c34-4321-950b-6ca20f0be6c7")
ID2D1DeviceContext2 : public ID2D1DeviceContext1
{
virtual void STDMETHODCALLTYPE CreateInk() = 0;
virtual void STDMETHODCALLTYPE CreateInkStyle() = 0;
virtual void STDMETHODCALLTYPE CreateGradientMesh() = 0;
virtual void STDMETHODCALLTYPE CreateImageSourceFromWic() = 0;
virtual void STDMETHODCALLTYPE CreateLookupTable3D() = 0;
virtual void STDMETHODCALLTYPE CreateImageSourceFromDxgi() = 0;
virtual void STDMETHODCALLTYPE GetGradientMeshWorldBounds() = 0;
virtual void STDMETHODCALLTYPE DrawInk() = 0;
virtual void STDMETHODCALLTYPE DrawGradientMesh() = 0;
virtual void STDMETHODCALLTYPE DrawGdiMetafile() = 0;
virtual void STDMETHODCALLTYPE CreateTransformedImageSource() = 0;
};
__CRT_UUID_DECL(ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7)
DEFINE_GUID(IID_ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00);
MIDL_INTERFACE("235a7496-8351-414c-bcd4-6672ab2d8e00")
ID2D1DeviceContext3 : public ID2D1DeviceContext2
{
virtual void STDMETHODCALLTYPE CreateSpriteBatch() = 0;
virtual void STDMETHODCALLTYPE DrawSpriteBatch() = 0;
};
__CRT_UUID_DECL(ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00)
DEFINE_GUID(IID_ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38);
MIDL_INTERFACE("af671749-d241-4db8-8e41-dcc2e5c1a438")
ID2D1SvgGlyphStyle : public ID2D1Resource
{
virtual void STDMETHODCALLTYPE SetFill() = 0;
virtual void STDMETHODCALLTYPE GetFill() = 0;
virtual void STDMETHODCALLTYPE SetStroke() = 0;
virtual void STDMETHODCALLTYPE GetStrokeDashesCount() = 0;
virtual void STDMETHODCALLTYPE GetStroke() = 0;
};
__CRT_UUID_DECL(ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38)
DEFINE_GUID(IID_ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb);
MIDL_INTERFACE("8c427831-3d90-4476-b647-c4fae349e4db")
ID2D1DeviceContext4 : public ID2D1DeviceContext3
{
virtual void STDMETHODCALLTYPE CreateSvgGlyphStyle() = 0;
virtual void STDMETHODCALLTYPE DrawText() = 0;
virtual void STDMETHODCALLTYPE DrawTextLayout() = 0;
virtual void STDMETHODCALLTYPE DrawColorBitmapGlyphRun(
DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat,
D2D1_POINT_2F baselineOrigin,
const DWRITE_GLYPH_RUN *glyphRun,
DWRITE_MEASURING_MODE measuringMode,
D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION bitmapSnapOption) = 0;
virtual void STDMETHODCALLTYPE DrawSvgGlyphRun(
D2D1_POINT_2F baselineOrigin,
const DWRITE_GLYPH_RUN *glyphRun,
ID2D1Brush *defaultFillBrush,
ID2D1SvgGlyphStyle *svgGlyphStyle,
UINT32 colorPaletteIndex,
DWRITE_MEASURING_MODE measuringMode) = 0;
};
__CRT_UUID_DECL(ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb)
#endif

78
src/win32/dw-extra.h Normal file
View file

@ -0,0 +1,78 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* Mingw-w64 dwrite_3.h is broken
*
* We only need the definitions of one function and its dependencies.
* IDWriteFactory4::TranslateColorGlyphRun
*
* But we need to include all the prior functions in the same struct,
* and parent structs, so that the functions are in the correct position
* in the vtable. The parameters of the unused functions are not
* required as we only need a function in the struct to create a
* function pointer in the vtable.
*/
#ifndef DWRITE_EXTRA_H
#define DWRITE_EXTRA_H
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#include <dwrite_2.h>
interface IDWriteFactory3;
interface IDWriteFactory4;
interface IDWriteColorGlyphRunEnumerator1;
DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS);
struct DWRITE_COLOR_GLYPH_RUN1 : DWRITE_COLOR_GLYPH_RUN
{
DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat;
DWRITE_MEASURING_MODE measuringMode;
};
DEFINE_GUID(IID_IDWriteColorGlyphRunEnumerator1, 0x7c5f86da, 0xc7a1, 0x4f05, 0xb8,0xe1, 0x55,0xa1,0x79,0xfe,0x5a,0x35);
MIDL_INTERFACE("7c5f86da-c7a1-4f05-b8e1-55a179fe5a35")
IDWriteColorGlyphRunEnumerator1 : public IDWriteColorGlyphRunEnumerator
{
virtual HRESULT STDMETHODCALLTYPE GetCurrentRun(
const DWRITE_COLOR_GLYPH_RUN1 **run) = 0;
};
__CRT_UUID_DECL(IDWriteColorGlyphRunEnumerator1, 0x7c5f86da, 0xc7a1, 0x4f05, 0xb8,0xe1, 0x55,0xa1,0x79,0xfe,0x5a,0x35)
DEFINE_GUID(IID_IDWriteFactory3, 0x9a1b41c3, 0xd3bb, 0x466a, 0x87,0xfc, 0xfe,0x67,0x55,0x6a,0x3b,0x65);
MIDL_INTERFACE("9a1b41c3-d3bb-466a-87fc-fe67556a3b65")
IDWriteFactory3 : public IDWriteFactory2
{
virtual void STDMETHODCALLTYPE CreateGlyphRunAnalysis() = 0;
virtual void STDMETHODCALLTYPE CreateCustomRenderingParams() = 0;
virtual void STDMETHODCALLTYPE CreateFontFaceReference() = 0;
virtual void STDMETHODCALLTYPE CreateFontFaceReference2() = 0;
virtual void STDMETHODCALLTYPE GetSystemFontSet() = 0;
virtual void STDMETHODCALLTYPE CreateFontSetBuilder() = 0;
virtual void STDMETHODCALLTYPE CreateFontCollectionFromFontSet() = 0;
virtual void STDMETHODCALLTYPE GetSystemFontCollection() = 0;
virtual void STDMETHODCALLTYPE GetFontDownloadQueue() = 0;
};
__CRT_UUID_DECL(IDWriteFactory3, 0x9a1b41c3, 0xd3bb, 0x466a, 0x87,0xfc, 0xfe,0x67,0x55,0x6a,0x3b,0x65)
DEFINE_GUID(IID_IDWriteFactory4, 0x4b0b5bd3, 0x0797, 0x4549, 0x8a,0xc5, 0xfe,0x91,0x5c,0xc5,0x38,0x56);
MIDL_INTERFACE("4b0b5bd3-0797-4549-8ac5-fe915cc53856")
IDWriteFactory4 : public IDWriteFactory3
{
virtual HRESULT STDMETHODCALLTYPE TranslateColorGlyphRun(
D2D1_POINT_2F baselineOrigin,
DWRITE_GLYPH_RUN const *glyphRun,
DWRITE_GLYPH_RUN_DESCRIPTION const *glyphRunDescription,
DWRITE_GLYPH_IMAGE_FORMATS desiredGlyphImageFormats,
DWRITE_MEASURING_MODE measuringMode,
DWRITE_MATRIX const *worldAndDpiTransform,
UINT32 colorPaletteIndex,
IDWriteColorGlyphRunEnumerator1 **colorLayers) = 0;
};
__CRT_UUID_DECL(IDWriteFactory4, 0x4b0b5bd3, 0x0797, 0x4549, 0x8a,0xc5, 0xfe,0x91,0x5c,0xc5,0x38,0x56)
#endif /* DWRITE_EXTRA_H */