summaryrefslogtreecommitdiffstats
path: root/gfx/cairo/cairo/src/win32
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/cairo/cairo/src/win32')
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp1549
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-dwrite-private.hpp (renamed from gfx/cairo/cairo/src/win32/cairo-dwrite-private.h)177
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-debug.c9
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-device.c9
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c51
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-font.c257
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c3
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c32
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-private.h9
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-refptr.hpp (renamed from gfx/cairo/cairo/src/win32/cairo-win32-refptr.h)6
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-surface.c82
-rw-r--r--gfx/cairo/cairo/src/win32/cairo-win32-system.c9
-rw-r--r--gfx/cairo/cairo/src/win32/d2d1-extra.h122
-rw-r--r--gfx/cairo/cairo/src/win32/dw-extra.h28
14 files changed, 1423 insertions, 920 deletions
diff --git a/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp b/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp
index a362007be1..cf516d41c3 100644
--- a/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp
+++ b/gfx/cairo/cairo/src/win32/cairo-dwrite-font.cpp
@@ -41,12 +41,35 @@
#include "cairo-surface-private.h"
#include "cairo-image-surface-private.h"
#include "cairo-clip-private.h"
-#include "cairo-win32-refptr.h"
-
-#include "cairo-dwrite-private.h"
+#include "cairo-win32-refptr.hpp"
+#include "cairo-dwrite-private.hpp"
#include "cairo-truetype-subset-private.h"
+#include "cairo-scaled-font-subsets-private.h"
+#include "cairo-dwrite.h"
+
#include <float.h>
+#include <wincodec.h>
+
+/**
+ * SECTION:cairo-dwrite-fonts
+ * @Title: DWrite Fonts
+ * @Short_Description: Font support for Microsoft DirectWrite
+ * @See_Also: #cairo_font_face_t
+ *
+ * The Microsoft DirectWrite font backend is primarily used to render text on
+ * Microsoft Windows systems.
+ **/
+
+/**
+ * CAIRO_HAS_DWRITE_FONT:
+ *
+ * Defined if the Microsoft DWrite font backend is available.
+ * This macro can be used to conditionally compile backend-specific code.
+ *
+ * Since: 1.18
+ **/
+
typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
D2D1_FACTORY_TYPE factoryType,
REFIID iid,
@@ -64,7 +87,7 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
COLORREF color,
const RECT &area);
-cairo_int_status_t
+static cairo_int_status_t
_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
DWRITE_MATRIX *transform,
DWRITE_GLYPH_RUN *run,
@@ -72,14 +95,52 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
cairo_dwrite_scaled_font_t *scaled_font,
const RECT &area);
+/**
+ * _cairo_dwrite_error:
+ * @hr HRESULT code
+ * @context: context string to display along with the error
+ *
+ * Helper function to print a human readable form a HRESULT.
+ *
+ * Return value: A cairo status code for the error code
+ **/
+static cairo_int_status_t
+_cairo_dwrite_error (HRESULT hr, const char *context)
+{
+ void *lpMsgBuf;
+
+ if (!FormatMessageW (FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ hr,
+ MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR) &lpMsgBuf,
+ 0, NULL)) {
+ fprintf (stderr, "%s: Unknown DWrite error HRESULT=0x%08lx\n", context, (unsigned long)hr);
+ } else {
+ fprintf (stderr, "%s: %S\n", context, (wchar_t *)lpMsgBuf);
+ LocalFree (lpMsgBuf);
+ }
+ fflush (stderr);
+
+ return (cairo_int_status_t)_cairo_error (CAIRO_STATUS_DWRITE_ERROR);
+}
+
class D2DFactory
{
public:
- static ID2D1Factory *Instance()
+ static RefPtr<ID2D1Factory> Instance()
{
if (!mFactoryInstance) {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory");
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
if (createD2DFactory) {
D2D1_FACTORY_OPTIONS options;
options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
@@ -92,7 +153,17 @@ public:
return mFactoryInstance;
}
- static ID2D1DCRenderTarget *RenderTarget()
+ static RefPtr<IDWriteFactory4> Instance4()
+ {
+ if (!mFactoryInstance4) {
+ if (Instance()) {
+ Instance()->QueryInterface(&mFactoryInstance4);
+ }
+ }
+ return mFactoryInstance4;
+ }
+
+ static RefPtr<ID2D1DCRenderTarget> RenderTarget()
{
if (!mRenderTarget) {
if (!Instance()) {
@@ -116,25 +187,145 @@ public:
}
private:
- static ID2D1Factory *mFactoryInstance;
- static ID2D1DCRenderTarget *mRenderTarget;
+ static RefPtr<ID2D1Factory> mFactoryInstance;
+ static RefPtr<IDWriteFactory4> mFactoryInstance4;
+ static RefPtr<ID2D1DCRenderTarget> mRenderTarget;
+};
+
+class WICImagingFactory
+{
+public:
+ static RefPtr<IWICImagingFactory> Instance()
+ {
+ if (!mFactoryInstance) {
+ CoInitialize(NULL);
+ CoCreateInstance(CLSID_WICImagingFactory,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&mFactoryInstance));
+ }
+ return mFactoryInstance;
+ }
+private:
+ static RefPtr<IWICImagingFactory> mFactoryInstance;
};
-IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
-IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
-IDWriteRenderingParams *DWriteFactory::mDefaultRenderingParams = NULL;
-IDWriteRenderingParams *DWriteFactory::mCustomClearTypeRenderingParams = NULL;
-IDWriteRenderingParams *DWriteFactory::mForceGDIClassicRenderingParams = NULL;
-FLOAT DWriteFactory::mGamma = -1.0;
-FLOAT DWriteFactory::mEnhancedContrast = -1.0;
-FLOAT DWriteFactory::mClearTypeLevel = -1.0;
-int DWriteFactory::mPixelGeometry = -1;
-int DWriteFactory::mRenderingMode = -1;
-
-ID2D1Factory *D2DFactory::mFactoryInstance = NULL;
-ID2D1DCRenderTarget *D2DFactory::mRenderTarget = NULL;
-
-/* Functions cairo_font_face_backend_t */
+
+RefPtr<IDWriteFactory> DWriteFactory::mFactoryInstance;
+RefPtr<IDWriteFactory1> DWriteFactory::mFactoryInstance1;
+RefPtr<IDWriteFactory2> DWriteFactory::mFactoryInstance2;
+RefPtr<IDWriteFactory3> DWriteFactory::mFactoryInstance3;
+RefPtr<IDWriteFactory4> DWriteFactory::mFactoryInstance4;
+
+RefPtr<IWICImagingFactory> WICImagingFactory::mFactoryInstance;
+RefPtr<IDWriteFontCollection> DWriteFactory::mSystemCollection;
+RefPtr<IDWriteRenderingParams> DWriteFactory::mDefaultRenderingParams;
+
+RefPtr<ID2D1Factory> D2DFactory::mFactoryInstance;
+RefPtr<ID2D1DCRenderTarget> D2DFactory::mRenderTarget;
+
+static int
+_quality_from_antialias_mode(cairo_antialias_t antialias)
+{
+ switch (antialias) {
+ case CAIRO_ANTIALIAS_NONE:
+ return NONANTIALIASED_QUALITY;
+ case CAIRO_ANTIALIAS_FAST:
+ case CAIRO_ANTIALIAS_GRAY:
+ return ANTIALIASED_QUALITY;
+ default:
+ break;
+ }
+ return CLEARTYPE_QUALITY;
+}
+
+static RefPtr<IDWriteRenderingParams>
+_create_rendering_params(IDWriteRenderingParams *params,
+ const cairo_font_options_t *options,
+ cairo_antialias_t antialias)
+{
+ if (!params)
+ params = DWriteFactory::DefaultRenderingParams();
+ FLOAT gamma = params->GetGamma();
+ FLOAT enhanced_contrast = params->GetEnhancedContrast();
+ FLOAT clear_type_level = params->GetClearTypeLevel();
+ DWRITE_PIXEL_GEOMETRY pixel_geometry = params->GetPixelGeometry();
+ DWRITE_RENDERING_MODE rendering_mode = params->GetRenderingMode();
+
+ cairo_bool_t modified = FALSE;
+ switch (antialias) {
+ case CAIRO_ANTIALIAS_NONE:
+ if (rendering_mode != DWRITE_RENDERING_MODE_ALIASED) {
+ rendering_mode = DWRITE_RENDERING_MODE_ALIASED;
+ modified = TRUE;
+ }
+ break;
+ case CAIRO_ANTIALIAS_FAST:
+ case CAIRO_ANTIALIAS_GRAY:
+ if (clear_type_level) {
+ clear_type_level = 0;
+ modified = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ auto subpixel_order = cairo_font_options_get_subpixel_order (options);
+ switch (subpixel_order) {
+ case CAIRO_SUBPIXEL_ORDER_RGB:
+ if (pixel_geometry != DWRITE_PIXEL_GEOMETRY_RGB) {
+ pixel_geometry = DWRITE_PIXEL_GEOMETRY_RGB;
+ modified = TRUE;
+ }
+ break;
+ case CAIRO_SUBPIXEL_ORDER_BGR:
+ if (pixel_geometry != DWRITE_PIXEL_GEOMETRY_BGR) {
+ pixel_geometry = DWRITE_PIXEL_GEOMETRY_BGR;
+ modified = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ if (!modified)
+ return params;
+
+ HRESULT hr;
+ RefPtr<IDWriteRenderingParams1> params1;
+ hr = params->QueryInterface(&params1);
+ if (FAILED(hr)) {
+ RefPtr<IDWriteRenderingParams> ret;
+ DWriteFactory::Instance()->CreateCustomRenderingParams(gamma, enhanced_contrast, clear_type_level, pixel_geometry, rendering_mode, &ret);
+ return ret;
+ }
+
+ FLOAT grayscaleEnhancedContrast = params1->GetGrayscaleEnhancedContrast();
+ RefPtr<IDWriteRenderingParams2> params2;
+ hr = params->QueryInterface(&params2);
+ if (FAILED(hr)) {
+ RefPtr<IDWriteRenderingParams1> ret;
+ DWriteFactory::Instance1()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode, &ret);
+ return ret;
+ }
+
+ DWRITE_GRID_FIT_MODE gridFitMode = params2->GetGridFitMode();
+ RefPtr<IDWriteRenderingParams3> params3;
+ hr = params->QueryInterface(&params3);
+ if (FAILED(hr)) {
+ RefPtr<IDWriteRenderingParams2> ret;
+ DWriteFactory::Instance2()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode, gridFitMode, &ret);
+ return ret;
+ }
+
+ DWRITE_RENDERING_MODE1 rendering_mode1 = params3->GetRenderingMode1();
+ if (antialias == CAIRO_ANTIALIAS_NONE)
+ rendering_mode1 = DWRITE_RENDERING_MODE1_ALIASED;
+ RefPtr<IDWriteRenderingParams3> ret;
+ DWriteFactory::Instance3()->CreateCustomRenderingParams(gamma, enhanced_contrast, grayscaleEnhancedContrast, clear_type_level, pixel_geometry, rendering_mode1, gridFitMode, &ret);
+ return ret;
+}
+
+/* Functions #cairo_font_face_backend_t */
static cairo_status_t
_cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
cairo_font_face_t **font_face);
@@ -155,27 +346,35 @@ const cairo_font_face_backend_t _cairo_dwrite_font_face_backend = {
_cairo_dwrite_font_face_scaled_font_create
};
-/* Functions cairo_scaled_font_backend_t */
+/* Functions #cairo_scaled_font_backend_t */
-void _cairo_dwrite_scaled_font_fini(void *scaled_font);
+static void _cairo_dwrite_scaled_font_fini(void *scaled_font);
static cairo_warn cairo_int_status_t
_cairo_dwrite_scaled_glyph_init(void *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info);
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color);
-cairo_int_status_t
+static cairo_int_status_t
_cairo_dwrite_load_truetype_table(void *scaled_font,
unsigned long tag,
long offset,
unsigned char *buffer,
unsigned long *length);
-unsigned long
-_cairo_dwrite_ucs4_to_index(void *scaled_font,
- uint32_t ucs4);
+static unsigned long
+_cairo_dwrite_ucs4_to_index(void *scaled_font,
+ uint32_t ucs4);
+
+static cairo_int_status_t
+_cairo_dwrite_is_synthetic(void *scaled_font,
+ cairo_bool_t *is_synthetic);
+
+static cairo_bool_t
+_cairo_dwrite_has_color_glyphs(void *scaled_font);
-const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
+static const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
CAIRO_FONT_TYPE_DWRITE,
_cairo_dwrite_scaled_font_fini,
_cairo_dwrite_scaled_glyph_init,
@@ -183,23 +382,24 @@ const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
_cairo_dwrite_ucs4_to_index,
_cairo_dwrite_load_truetype_table,
NULL, /* index_to_ucs4 */
- NULL, /* is_synthetic */
+ _cairo_dwrite_is_synthetic,
NULL, /* index_to_glyph_name */
NULL, /* load_type1_data */
- NULL, /* has_color_glyphs */
+ _cairo_dwrite_has_color_glyphs
};
/* Helper conversion functions */
/**
+ * _cairo_dwrite_matrix_from_matrix:
* Get a DirectWrite matrix from a cairo matrix. Note that DirectWrite uses row
* vectors where cairo uses column vectors. Hence the transposition.
*
* \param Cairo matrix
* \return DirectWrite matrix
- */
-DWRITE_MATRIX
+ **/
+static DWRITE_MATRIX
_cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
{
DWRITE_MATRIX dwmat;
@@ -212,16 +412,21 @@ _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
return dwmat;
}
-/* Helper functions for cairo_dwrite_scaled_glyph_init */
-cairo_int_status_t
-_cairo_dwrite_scaled_font_init_glyph_metrics
+/* Helper functions for cairo_dwrite_scaled_glyph_init() */
+static cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_metrics
(cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
-cairo_int_status_t
+static cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph,
+ const cairo_color_t *foreground_color);
+
+static cairo_int_status_t
_cairo_dwrite_scaled_font_init_glyph_surface
(cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
-cairo_int_status_t
+static cairo_int_status_t
_cairo_dwrite_scaled_font_init_glyph_path
(cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
@@ -242,11 +447,20 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
face_name = new WCHAR[face_name_len];
MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, face_name, face_name_len);
- IDWriteFontFamily *family = DWriteFactory::FindSystemFontFamily(face_name);
- delete face_name;
+ RefPtr<IDWriteFontFamily> family = DWriteFactory::FindSystemFontFamily(face_name);
+ delete[] face_name;
if (!family) {
- *font_face = (cairo_font_face_t*)&_cairo_font_face_nil;
- return CAIRO_STATUS_FONT_TYPE_MISMATCH;
+ /* If the family is not found, use the default that should always exist. */
+ face_name_len = MultiByteToWideChar(CP_UTF8, 0, CAIRO_FONT_FAMILY_DEFAULT, -1, NULL, 0);
+ face_name = new WCHAR[face_name_len];
+ MultiByteToWideChar(CP_UTF8, 0, CAIRO_FONT_FAMILY_DEFAULT, -1, face_name, face_name_len);
+
+ family = DWriteFactory::FindSystemFontFamily(face_name);
+ delete[] face_name;
+ if (!family) {
+ *font_face = (cairo_font_face_t*)&_cairo_font_face_nil;
+ return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
+ }
}
DWRITE_FONT_WEIGHT weight;
@@ -274,16 +488,17 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
break;
}
- cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)malloc(sizeof(cairo_dwrite_font_face_t));
- HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &face->font);
- if (SUCCEEDED(hr)) {
- // Cannot use C++ style new since cairo deallocates this.
- *font_face = (cairo_font_face_t*)face;
- _cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
- } else {
- free(face);
- }
+ RefPtr<IDWriteFont> font;
+ HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &font);
+ if (FAILED(hr))
+ return (cairo_status_t)_cairo_dwrite_error (hr, "GetFirstMatchingFont failed");
+
+ RefPtr<IDWriteFontFace> dwriteface;
+ hr = font->CreateFontFace(&dwriteface);
+ if (FAILED(hr))
+ return (cairo_status_t)_cairo_dwrite_error (hr, "CreateFontFace failed");
+ *font_face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface);
return CAIRO_STATUS_SUCCESS;
}
@@ -293,12 +508,11 @@ _cairo_dwrite_font_face_destroy (void *font_face)
cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face);
if (dwrite_font_face->dwriteface)
dwrite_font_face->dwriteface->Release();
- if (dwrite_font_face->font)
- dwrite_font_face->font->Release();
+ if (dwrite_font_face->rendering_params)
+ dwrite_font_face->rendering_params->Release();
return TRUE;
}
-
static inline unsigned short
read_short(const char *buf)
{
@@ -326,7 +540,7 @@ _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
run->isSideways = FALSE;
if (scaled_font->mat.xy == 0 && scaled_font->mat.yx == 0 &&
- scaled_font->mat.xx == scaled_font->base.font_matrix.xx &&
+ scaled_font->mat.xx == scaled_font->base.font_matrix.xx &&
scaled_font->mat.yy == scaled_font->base.font_matrix.yy) {
// Fast route, don't actually use a transform but just
// set the correct font size.
@@ -421,17 +635,42 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
const cairo_font_options_t *options,
cairo_scaled_font_t **font)
{
+ cairo_status_t status;
cairo_dwrite_font_face_t *font_face = static_cast<cairo_dwrite_font_face_t*>(abstract_face);
- // Must do malloc and not C++ new, since Cairo frees this.
- cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)malloc(sizeof(cairo_dwrite_scaled_font_t));
- *font = reinterpret_cast<cairo_scaled_font_t*>(dwriteFont);
- _cairo_scaled_font_init(&dwriteFont->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend);
+ /* Must do malloc and not C++ new, since Cairo frees this. */
+ cairo_dwrite_scaled_font_t *dwrite_font = (cairo_dwrite_scaled_font_t*)_cairo_malloc(
+ sizeof(cairo_dwrite_scaled_font_t));
+ if (unlikely(dwrite_font == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+ *font = reinterpret_cast<cairo_scaled_font_t*>(dwrite_font);
+ status = _cairo_scaled_font_init (&dwrite_font->base,
+ &font_face->base,
+ font_matrix,
+ ctm,
+ options,
+ &_cairo_dwrite_scaled_font_backend);
+ if (status) {
+ free(dwrite_font);
+ return status;
+ }
+
+ dwrite_font->mat = dwrite_font->base.ctm;
+ cairo_matrix_multiply(&dwrite_font->mat, &dwrite_font->mat, font_matrix);
+ dwrite_font->mat_inverse = dwrite_font->mat;
+ cairo_matrix_invert (&dwrite_font->mat_inverse);
cairo_font_extents_t extents;
DWRITE_FONT_METRICS metrics;
- font_face->dwriteface->GetMetrics(&metrics);
+ if (dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC ||
+ dwrite_font->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) {
+ DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&dwrite_font->mat);
+ font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &metrics);
+ } else {
+ font_face->dwriteface->GetMetrics(&metrics);
+ }
extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm;
extents.descent = (FLOAT)metrics.descent / metrics.designUnitsPerEm;
@@ -439,15 +678,8 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
extents.max_x_advance = 14.0;
extents.max_y_advance = 0.0;
- dwriteFont->mat = dwriteFont->base.ctm;
- cairo_matrix_multiply(&dwriteFont->mat, &dwriteFont->mat, font_matrix);
- dwriteFont->mat_inverse = dwriteFont->mat;
- cairo_matrix_invert (&dwriteFont->mat_inverse);
-
cairo_antialias_t default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
- dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_NATURAL;
-
// The following code detects the system quality at scaled_font creation time,
// this means that if cleartype settings are changed but the scaled_fonts
// are re-used, they might not adhere to the new system setting until re-
@@ -458,12 +690,10 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
break;
case ANTIALIASED_QUALITY:
default_quality = CAIRO_ANTIALIAS_GRAY;
- dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
break;
case DEFAULT_QUALITY:
// _get_system_quality() seems to think aliased is default!
default_quality = CAIRO_ANTIALIAS_NONE;
- dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
break;
}
@@ -474,31 +704,34 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
}
if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) {
- dwriteFont->antialias_mode = default_quality;
+ dwrite_font->antialias_mode = default_quality;
} else {
- dwriteFont->antialias_mode = options->antialias;
+ dwrite_font->antialias_mode = options->antialias;
}
- dwriteFont->rendering_mode =
- default_quality == CAIRO_ANTIALIAS_SUBPIXEL ?
- cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL : cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE;
+ dwrite_font->rendering_params = _create_rendering_params(font_face->rendering_params, options, dwrite_font->antialias_mode).forget().drop();
+ dwrite_font->measuring_mode = font_face->measuring_mode;
return _cairo_scaled_font_set_metrics (*font, &extents);
}
-/* Implementation cairo_dwrite_scaled_font_backend_t */
-void
+/* Implementation #cairo_dwrite_scaled_font_backend_t */
+static void
_cairo_dwrite_scaled_font_fini(void *scaled_font)
{
+ cairo_dwrite_scaled_font_t *dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+ if (dwrite_font->rendering_params)
+ dwrite_font->rendering_params->Release();
}
static cairo_int_status_t
_cairo_dwrite_scaled_glyph_init(void *scaled_font,
cairo_scaled_glyph_t *scaled_glyph,
- cairo_scaled_glyph_info_t info)
+ cairo_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
{
cairo_dwrite_scaled_font_t *scaled_dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
- cairo_int_status_t status;
+ cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
status = _cairo_dwrite_scaled_font_init_glyph_metrics (scaled_dwrite_font, scaled_glyph);
@@ -506,6 +739,12 @@ _cairo_dwrite_scaled_glyph_init(void *scaled_font,
return status;
}
+ if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ status = _cairo_dwrite_scaled_font_init_glyph_color_surface (scaled_dwrite_font, scaled_glyph, foreground_color);
+ if (status)
+ return status;
+ }
+
if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
status = _cairo_dwrite_scaled_font_init_glyph_surface (scaled_dwrite_font, scaled_glyph);
if (status)
@@ -521,7 +760,7 @@ _cairo_dwrite_scaled_glyph_init(void *scaled_font,
return CAIRO_INT_STATUS_SUCCESS;
}
-unsigned long
+static unsigned long
_cairo_dwrite_ucs4_to_index(void *scaled_font,
uint32_t ucs4)
{
@@ -533,9 +772,9 @@ _cairo_dwrite_ucs4_to_index(void *scaled_font,
return index;
}
-/* cairo_dwrite_scaled_glyph_init helper function bodies */
-cairo_int_status_t
-_cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font,
+/* cairo_dwrite_scaled_glyph_init() helper function bodies */
+static cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
UINT16 charIndex = (UINT16)_cairo_scaled_glyph_index (scaled_glyph);
@@ -544,17 +783,30 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_
DWRITE_GLYPH_METRICS metrics;
DWRITE_FONT_METRICS fontMetrics;
- font_face->dwriteface->GetMetrics(&fontMetrics);
- HRESULT hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics);
+ HRESULT hr;
+ if (font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_CLASSIC ||
+ font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL) {
+ DWRITE_MATRIX transform = _cairo_dwrite_matrix_from_matrix (&scaled_font->mat);
+ font_face->dwriteface->GetGdiCompatibleMetrics(1, 1, &transform, &fontMetrics);
+ BOOL natural = font_face->measuring_mode == DWRITE_MEASURING_MODE_GDI_NATURAL;
+ hr = font_face->dwriteface->GetGdiCompatibleGlyphMetrics (1, 1, &transform, natural, &charIndex, 1, &metrics, FALSE);
+ } else {
+ font_face->dwriteface->GetMetrics(&fontMetrics);
+ hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics);
+ }
if (FAILED(hr)) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
+ // GetGdiCompatibleMetrics may return a glyph metrics that yields a small nagative glyph height.
+ INT32 glyph_width = metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing;
+ INT32 glyph_height = metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing;
+ glyph_width = MAX(glyph_width, 0);
+ glyph_height = MAX(glyph_height, 0);
+
// TODO: Treat swap_xy.
- extents.width = (FLOAT)(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing) /
- fontMetrics.designUnitsPerEm;
- extents.height = (FLOAT)(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing) /
- fontMetrics.designUnitsPerEm;
+ extents.width = (FLOAT)glyph_width / fontMetrics.designUnitsPerEm;
+ extents.height = (FLOAT)glyph_height / fontMetrics.designUnitsPerEm;
extents.x_advance = (FLOAT)metrics.advanceWidth / fontMetrics.designUnitsPerEm;
extents.x_bearing = (FLOAT)metrics.leftSideBearing / fontMetrics.designUnitsPerEm;
extents.y_advance = 0.0;
@@ -564,10 +816,15 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_
// We pad the extents here because GetDesignGlyphMetrics returns "ideal" metrics
// for the glyph outline, without accounting for hinting/gridfitting/antialiasing,
// and therefore it does not always cover all pixels that will actually be touched.
- if (scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE &&
- extents.width > 0 && extents.height > 0) {
- extents.width += scaled_font->mat_inverse.xx * 2;
- extents.x_bearing -= scaled_font->mat_inverse.xx;
+ if (extents.width > 0 && extents.height > 0) {
+ double x = 1, y = 1;
+ cairo_matrix_transform_distance (&scaled_font->mat_inverse, &x, &y);
+ x = fabs(x);
+ y = fabs(y);
+ extents.width += x * 2;
+ extents.x_bearing -= x;
+ extents.height += y * 2;
+ extents.y_bearing -= y;
}
_cairo_scaled_glyph_set_metrics (scaled_glyph,
@@ -576,7 +833,7 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_
return CAIRO_INT_STATUS_SUCCESS;
}
-/**
+/*
* Stack-based helper implementing IDWriteGeometrySink.
* Used to determine the path of the glyphs.
*/
@@ -584,8 +841,9 @@ _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_
class GeometryRecorder : public IDWriteGeometrySink
{
public:
- GeometryRecorder(cairo_path_fixed_t *aCairoPath)
- : mCairoPath(aCairoPath) {}
+ GeometryRecorder(cairo_path_fixed_t *aCairoPath, const cairo_matrix_t &matrix)
+ : mCairoPath(aCairoPath)
+ , mMatrix(matrix) {}
// IUnknown interface
IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
@@ -622,38 +880,30 @@ public:
{
return;
}
-
- cairo_fixed_t GetFixedX(const D2D1_POINT_2F &point)
- {
- unsigned int control_word;
- _controlfp_s(&control_word, _CW_DEFAULT, MCW_PC);
- return _cairo_fixed_from_double(point.x);
- }
-
- cairo_fixed_t GetFixedY(const D2D1_POINT_2F &point)
- {
- unsigned int control_word;
- _controlfp_s(&control_word, _CW_DEFAULT, MCW_PC);
- return _cairo_fixed_from_double(point.y);
- }
IFACEMETHODIMP_(void) BeginFigure(
- D2D1_POINT_2F startPoint,
- D2D1_FIGURE_BEGIN figureBegin)
+ D2D1_POINT_2F startPoint,
+ D2D1_FIGURE_BEGIN figureBegin)
{
- mStartPoint = startPoint;
- cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath,
- GetFixedX(startPoint),
- GetFixedY(startPoint));
+ double x = startPoint.x;
+ double y = startPoint.y;
+ cairo_matrix_transform_point(&mMatrix, &x, &y);
+ mStartPointX = _cairo_fixed_from_double(x);
+ mStartPointY = _cairo_fixed_from_double(y);
+ cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath,
+ mStartPointX,
+ mStartPointY);
+ (void)status; /* squelch warning */
}
- IFACEMETHODIMP_(void) EndFigure(
- D2D1_FIGURE_END figureEnd)
+ IFACEMETHODIMP_(void) EndFigure(
+ D2D1_FIGURE_END figureEnd)
{
if (figureEnd == D2D1_FIGURE_END_CLOSED) {
cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
- GetFixedX(mStartPoint),
- GetFixedY(mStartPoint));
+ mStartPointX,
+ mStartPointY);
+ (void)status; /* squelch warning */
}
}
@@ -662,14 +912,24 @@ public:
UINT beziersCount)
{
for (unsigned int i = 0; i < beziersCount; i++) {
+ double x1 = beziers[i].point1.x;
+ double y1 = beziers[i].point1.y;
+ double x2 = beziers[i].point2.x;
+ double y2 = beziers[i].point2.y;
+ double x3 = beziers[i].point3.x;
+ double y3 = beziers[i].point3.y;
+ cairo_matrix_transform_point(&mMatrix, &x1, &y1);
+ cairo_matrix_transform_point(&mMatrix, &x2, &y2);
+ cairo_matrix_transform_point(&mMatrix, &x3, &y3);
cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath,
- GetFixedX(beziers[i].point1),
- GetFixedY(beziers[i].point1),
- GetFixedX(beziers[i].point2),
- GetFixedY(beziers[i].point2),
- GetFixedX(beziers[i].point3),
- GetFixedY(beziers[i].point3));
- }
+ _cairo_fixed_from_double(x1),
+ _cairo_fixed_from_double(y1),
+ _cairo_fixed_from_double(x2),
+ _cairo_fixed_from_double(y2),
+ _cairo_fixed_from_double(x3),
+ _cairo_fixed_from_double(y3));
+ (void)status; /* squelch warning */
+ }
}
IFACEMETHODIMP_(void) AddLines(
@@ -677,24 +937,31 @@ public:
UINT pointsCount)
{
for (unsigned int i = 0; i < pointsCount; i++) {
- cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
- GetFixedX(points[i]),
- GetFixedY(points[i]));
+ double x = points[i].x;
+ double y = points[i].y;
+ cairo_matrix_transform_point(&mMatrix, &x, &y);
+ cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
+ _cairo_fixed_from_double(x),
+ _cairo_fixed_from_double(y));
+ (void)status; /* squelch warning */
}
}
private:
cairo_path_fixed_t *mCairoPath;
- D2D1_POINT_2F mStartPoint;
+ const cairo_matrix_t &mMatrix;
+ cairo_fixed_t mStartPointX;
+ cairo_fixed_t mStartPointY;
};
-cairo_int_status_t
-_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
+static cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
+ cairo_int_status_t status;
cairo_path_fixed_t *path;
path = _cairo_path_fixed_create();
- GeometryRecorder recorder(path);
+ GeometryRecorder recorder(path, scaled_font->base.scale);
DWRITE_GLYPH_OFFSET offset;
offset.advanceOffset = 0;
@@ -702,67 +969,268 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
UINT16 glyphId = (UINT16)_cairo_scaled_glyph_index(scaled_glyph);
FLOAT advance = 0.0;
cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face;
- dwriteff->dwriteface->GetGlyphRunOutline((FLOAT)scaled_font->base.font_matrix.yy,
- &glyphId,
- &advance,
- &offset,
- 1,
- FALSE,
- FALSE,
- &recorder);
- _cairo_path_fixed_close_path(path);
-
- /* Now apply our transformation to the drawn path. */
- _cairo_path_fixed_transform(path, &scaled_font->base.ctm);
-
+
+ HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(1,
+ &glyphId,
+ &advance,
+ &offset,
+ 1,
+ FALSE,
+ FALSE,
+ &recorder);
+ if (!SUCCEEDED(hr))
+ return _cairo_dwrite_error (hr, "GetGlyphRunOutline failed");
+
+ status = (cairo_int_status_t)_cairo_path_fixed_close_path(path);
+
_cairo_scaled_glyph_set_path (scaled_glyph,
&scaled_font->base,
path);
- return CAIRO_INT_STATUS_SUCCESS;
+ return status;
}
-/* Helper function adapted from _compute_mask in cairo-win32-font.c */
-
-/* Compute an alpha-mask from a monochrome RGB24 image
- */
-static cairo_surface_t *
-_compute_a8_mask (cairo_surface_t *surface)
+static cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *scaled_font,
+ cairo_scaled_glyph_t *scaled_glyph,
+ const cairo_color_t *foreground_color)
{
- cairo_image_surface_t *glyph;
- cairo_image_surface_t *mask;
- int i, j;
+ int width, height;
+ double x1, y1, x2, y2;
+ cairo_bool_t uses_foreground_color = FALSE;
+
+ cairo_dwrite_font_face_t *dwrite_font_face = (cairo_dwrite_font_face_t *)scaled_font->base.font_face;
+ if (!dwrite_font_face->have_color) {
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
- glyph = (cairo_image_surface_t *)cairo_surface_map_to_image (surface, NULL);
- if (unlikely (glyph->base.status))
- return &glyph->base;
+ 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 = (int)(x2 - x1);
+ height = (int)(y2 - y1);
- /* No quality param, just use the non-ClearType path */
+ DWRITE_GLYPH_RUN run;
+ FLOAT advance = 0;
+ UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph);
+ DWRITE_GLYPH_OFFSET offset;
+ double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
+ double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
+ DWRITE_MATRIX matrix;
+ D2D1_POINT_2F origin = {0, 0};
+ RefPtr<IDWriteColorGlyphRunEnumerator1> run_enumerator;
+ HRESULT hr;
- /* Compute an alpha-mask by using the green channel of a (presumed monochrome)
- * RGB24 image.
+ /*
+ * We transform by the inverse transformation here. This will put our glyph
+ * locations in the space in which we draw. Which is later transformed by
+ * the transformation matrix that we use. This will transform the
+ * glyph positions back to where they were before when drawing, but the
+ * glyph shapes will be transformed by the transformation matrix.
*/
- 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);
+ cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
+ offset.advanceOffset = (FLOAT)x;
+ /* Y-axis is inverted */
+ offset.ascenderOffset = -(FLOAT)y;
+
+ run.fontFace = dwrite_font_face->dwriteface;
+ run.fontEmSize = 1;
+ run.glyphCount = 1;
+ run.glyphIndices = &index;
+ run.glyphAdvances = &advance;
+ run.glyphOffsets = &offset;
+ run.isSideways = FALSE;
+ run.bidiLevel = 0;
+
+ matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat);
+
+ /* The list of glyph image formats this renderer is prepared to support. */
+ DWRITE_GLYPH_IMAGE_FORMATS supported_formats =
+ DWRITE_GLYPH_IMAGE_FORMATS_COLR |
+ DWRITE_GLYPH_IMAGE_FORMATS_SVG |
+ DWRITE_GLYPH_IMAGE_FORMATS_PNG |
+ DWRITE_GLYPH_IMAGE_FORMATS_JPEG |
+ DWRITE_GLYPH_IMAGE_FORMATS_TIFF |
+ DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8;
+
+ RefPtr<IDWriteFontFace2> fontFace2;
+ UINT32 palette_count = 0;
+ if (SUCCEEDED(dwrite_font_face->dwriteface->QueryInterface(&fontFace2)))
+ palette_count = fontFace2->GetColorPaletteCount();
+
+ UINT32 palette_index = CAIRO_COLOR_PALETTE_DEFAULT;
+ if (scaled_font->base.options.palette_index < palette_count)
+ palette_index = scaled_font->base.options.palette_index;
+
+ hr = DWriteFactory::Instance4()->TranslateColorGlyphRun(
+ origin,
+ &run,
+ NULL, /* glyphRunDescription */
+ supported_formats,
+ dwrite_font_face->measuring_mode,
+ &matrix,
+ palette_index,
+ &run_enumerator);
+
+ if (hr == DWRITE_E_NOCOLOR) {
+ /* No color glyphs */
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "TranslateColorGlyphRun failed");
+
+ /* We have a color glyph(s). Use Direct2D to render it to a bitmap */
+ if (!WICImagingFactory::Instance() || !D2DFactory::Instance())
+ return _cairo_dwrite_error (hr, "Instance failed");
+
+ RefPtr<IWICBitmap> bitmap;
+ hr = WICImagingFactory::Instance()->CreateBitmap ((UINT)width,
+ (UINT)height,
+ GUID_WICPixelFormat32bppPBGRA,
+ WICBitmapCacheOnLoad,
+ &bitmap);
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "CreateBitmap failed");
+
+ D2D1_RENDER_TARGET_PROPERTIES properties = D2D1::RenderTargetProperties(
+ D2D1_RENDER_TARGET_TYPE_DEFAULT,
+ D2D1::PixelFormat(
+ DXGI_FORMAT_B8G8R8A8_UNORM,
+ D2D1_ALPHA_MODE_PREMULTIPLIED),
+ 0,
+ 0,
+ D2D1_RENDER_TARGET_USAGE_NONE,
+ D2D1_FEATURE_LEVEL_DEFAULT);
+
+ RefPtr<ID2D1RenderTarget> rt;
+ hr = D2DFactory::Instance()->CreateWicBitmapRenderTarget (bitmap, properties, &rt);
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "CreateWicBitmapRenderTarget failed");
+
+ RefPtr<ID2D1DeviceContext4> dc4;
+ hr = rt->QueryInterface(&dc4);
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "QueryInterface(&dc4) failed");
+
+ RefPtr<ID2D1SolidColorBrush> foreground_color_brush;
+ dc4->CreateSolidColorBrush(
+ D2D1::ColorF(foreground_color->red,
+ foreground_color->green,
+ foreground_color->blue,
+ foreground_color->alpha), &foreground_color_brush);
+
+ RefPtr<ID2D1SolidColorBrush> color_brush;
+ dc4->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &color_brush);
+
+ dc4->SetDpi(96, 96); /* 1 unit = 1 pixel */
+ rt->SetTransform(D2D1::Matrix3x2F(matrix.m11,
+ matrix.m12,
+ matrix.m21,
+ matrix.m22,
+ matrix.dx,
+ matrix.dy));
+
+ dc4->BeginDraw();
+ dc4->Clear(NULL); /* Transparent black */
+
+ while (true) {
+ BOOL have_run;
+ hr = run_enumerator->MoveNext(&have_run);
+ if (FAILED(hr) || !have_run)
+ break;
- for (j = 0; j < glyph->width; j++)
- *q++ = 255 - ((*p++ & 0x0000ff00) >> 8);
- }
+ DWRITE_COLOR_GLYPH_RUN1_WORKAROUND const* color_run;
+ hr = run_enumerator->GetCurrentRun(reinterpret_cast<const DWRITE_COLOR_GLYPH_RUN1**>(&color_run));
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "GetCurrentRun failed");
+
+ switch (color_run->glyphImageFormat) {
+ case DWRITE_GLYPH_IMAGE_FORMATS_PNG:
+ case DWRITE_GLYPH_IMAGE_FORMATS_JPEG:
+ case DWRITE_GLYPH_IMAGE_FORMATS_TIFF:
+ case DWRITE_GLYPH_IMAGE_FORMATS_PREMULTIPLIED_B8G8R8A8:
+ /* Bitmap glyphs */
+ dc4->DrawColorBitmapGlyphRun(color_run->glyphImageFormat,
+ origin,
+ &color_run->glyphRun,
+ dwrite_font_face->measuring_mode,
+ D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT);
+ break;
+
+ case DWRITE_GLYPH_IMAGE_FORMATS_SVG:
+ /* SVG glyphs */
+ dc4->DrawSvgGlyphRun(origin,
+ &color_run->glyphRun,
+ foreground_color_brush,
+ nullptr,
+ palette_index,
+ dwrite_font_face->measuring_mode);
+ uses_foreground_color = TRUE;
+ break;
+ case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE:
+ case DWRITE_GLYPH_IMAGE_FORMATS_CFF:
+ case DWRITE_GLYPH_IMAGE_FORMATS_COLR:
+ /* Outline glyphs */
+ if (color_run->paletteIndex == 0xFFFF) {
+ D2D1_COLOR_F color = foreground_color_brush->GetColor();
+ color_brush->SetColor(&color);
+ uses_foreground_color = TRUE;
+ } else {
+ double red, green, blue, alpha;
+ cairo_status_t status;
+ status = cairo_font_options_get_custom_palette_color (&scaled_font->base.options,
+ color_run->paletteIndex,
+ &red, &blue, &green, &alpha);
+ if (status == CAIRO_STATUS_SUCCESS) {
+ color_brush->SetColor(D2D1::ColorF(red, blue, green, alpha));
+ } else {
+ color_brush->SetColor(color_run->runColor);
+ }
+ }
+
+ dc4->DrawGlyphRun(origin,
+ &color_run->glyphRun,
+ color_run->glyphRunDescription,
+ color_brush,
+ dwrite_font_face->measuring_mode);
+ case DWRITE_GLYPH_IMAGE_FORMATS_NONE:
+ break;
+ }
}
- cairo_surface_unmap_image (surface, &glyph->base);
- return &mask->base;
+ hr = dc4->EndDraw();
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "EndDraw failed");
+
+ cairo_surface_t *image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+ int stride = cairo_image_surface_get_stride (image);
+ WICRect rect = { 0, 0, width, height };
+ bitmap->CopyPixels(&rect,
+ stride,
+ height * stride,
+ cairo_image_surface_get_data (image));
+ cairo_surface_mark_dirty (image);
+ cairo_surface_set_device_offset (image, -x1, -y1);
+ _cairo_scaled_glyph_set_color_surface (scaled_glyph,
+ &scaled_font->base,
+ (cairo_image_surface_t *) image,
+ uses_foreground_color ? foreground_color : NULL);
+ scaled_glyph->color_glyph = TRUE;
+ scaled_glyph->color_glyph_set = TRUE;
+
+ return CAIRO_INT_STATUS_SUCCESS;
}
-cairo_int_status_t
-_cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font,
+static cairo_int_status_t
+_cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font,
cairo_scaled_glyph_t *scaled_glyph)
{
cairo_int_status_t status;
- cairo_glyph_t glyph;
cairo_win32_surface_t *surface;
cairo_t *cr;
cairo_surface_t *image;
@@ -776,16 +1244,12 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
width = (int)(x2 - x1);
height = (int)(y2 - y1);
- glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
- glyph.x = -x1;
- glyph.y = -y1;
-
DWRITE_GLYPH_RUN run;
FLOAT advance = 0;
- UINT16 index = (UINT16)glyph.index;
+ UINT16 index = (UINT16)_cairo_scaled_glyph_index (scaled_glyph);
DWRITE_GLYPH_OFFSET offset;
- double x = glyph.x;
- double y = glyph.y;
+ double x = -x1 + .25 * _cairo_scaled_glyph_xphase (scaled_glyph);
+ double y = -y1 + .25 * _cairo_scaled_glyph_yphase (scaled_glyph);
RECT area;
DWRITE_MATRIX matrix;
@@ -800,7 +1264,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
if (status)
goto FAIL;
- /**
+ /*
* We transform by the inverse transformation here. This will put our glyph
* locations in the space in which we draw. Which is later transformed by
* the transformation matrix that we use. This will transform the
@@ -809,7 +1273,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
*/
cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
offset.advanceOffset = (FLOAT)x;
- /** Y-axis is inverted */
+ /* Y-axis is inverted */
offset.ascenderOffset = -(FLOAT)y;
area.top = 0;
@@ -835,7 +1299,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
GdiFlush();
- image = _compute_a8_mask (&surface->base);
+ image = _cairo_compute_glyph_mask (&surface->base, _quality_from_antialias_mode(scaled_font->antialias_mode));
status = (cairo_int_status_t)image->status;
if (status)
goto FAIL;
@@ -851,7 +1315,7 @@ _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_
return status;
}
-cairo_int_status_t
+static cairo_int_status_t
_cairo_dwrite_load_truetype_table(void *scaled_font,
unsigned long tag,
long offset,
@@ -865,11 +1329,14 @@ _cairo_dwrite_load_truetype_table(void *scaled_font,
UINT32 size;
void *tableContext;
BOOL exists;
- face->dwriteface->TryGetFontTable(be32_to_cpu (tag),
- &data,
- &size,
- &tableContext,
- &exists);
+ HRESULT hr;
+ hr = face->dwriteface->TryGetFontTable (be32_to_cpu (tag),
+ &data,
+ &size,
+ &tableContext,
+ &exists);
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "TryGetFontTable failed");
if (!exists) {
return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -887,59 +1354,256 @@ _cairo_dwrite_load_truetype_table(void *scaled_font,
return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
}
-// WIN32 Helper Functions
-cairo_font_face_t*
-cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrite_font_face)
+static cairo_int_status_t
+_cairo_dwrite_is_synthetic(void *scaled_font,
+ cairo_bool_t *is_synthetic)
+{
+ cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+ cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
+ HRESULT hr;
+ cairo_int_status_t status;
+
+ if (face->dwriteface->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
+ *is_synthetic = FALSE;
+ return CAIRO_INT_STATUS_SUCCESS;
+ }
+
+ RefPtr<IDWriteFontFace5> fontFace5;
+ if (FAILED(face->dwriteface->QueryInterface(&fontFace5))) {
+ /* If IDWriteFontFace5 is not available, assume this version of
+ * DirectWrite does not support variations.
+ */
+ *is_synthetic = FALSE;
+ return CAIRO_INT_STATUS_SUCCESS;
+ }
+
+ if (!fontFace5->HasVariations()) {
+ *is_synthetic = FALSE;
+ return CAIRO_INT_STATUS_SUCCESS;
+ }
+
+ RefPtr<IDWriteFontResource> fontResource;
+ hr = fontFace5->GetFontResource(&fontResource);
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "GetFontResource failed");
+
+ UINT32 axis_count = fontResource->GetFontAxisCount();
+ DWRITE_FONT_AXIS_VALUE *axis_defaults = new DWRITE_FONT_AXIS_VALUE[axis_count];
+ DWRITE_FONT_AXIS_VALUE *axis_values = new DWRITE_FONT_AXIS_VALUE[axis_count];
+
+ hr = fontResource->GetDefaultFontAxisValues(axis_defaults, axis_count);
+ if (FAILED(hr)) {
+ status = _cairo_dwrite_error (hr, "GetDefaultFontAxisValues failed");
+ goto cleanup;
+ }
+
+ hr = fontFace5->GetFontAxisValues(axis_values, axis_count);
+ if (FAILED(hr)) {
+ status = _cairo_dwrite_error (hr, "GetFontAxisValues failed");
+ goto cleanup;
+ }
+
+ /* The DirectWrite documentation does not state if the tags of the returned
+ * defaults and values arrays are in the same order. So assume they are not.
+ */
+ *is_synthetic = FALSE;
+ status = CAIRO_INT_STATUS_SUCCESS;
+ for (UINT32 i = 0; i< axis_count; i++) {
+ for (UINT32 j = 0; j < axis_count; j++) {
+ if (axis_values[i].axisTag == axis_defaults[j].axisTag) {
+ if (axis_values[i].value != axis_defaults[j].value) {
+ *is_synthetic = TRUE;
+ goto cleanup;
+ }
+ break;
+ }
+ }
+ }
+
+ cleanup:
+ delete[] axis_defaults;
+ delete[] axis_values;
+
+ return status;
+}
+
+static cairo_bool_t
+_cairo_dwrite_has_color_glyphs(void *scaled_font)
+{
+ cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
+
+ return ((cairo_dwrite_font_face_t *)dwritesf->base.font_face)->have_color;
+}
+
+/**
+ * cairo_dwrite_font_face_create_for_dwrite_fontface:
+ * @dwrite_font_face: A pointer to an #IDWriteFontFace specifying the
+ * DWrite font to use.
+ *
+ * Creates a new font for the DWrite font backend based on a
+ * DWrite font face. This font can then be used with
+ * cairo_set_font_face() or cairo_scaled_font_create().
+ *
+ * Here is an example of how this function might be used:
+ * <informalexample><programlisting><![CDATA[
+ * #include <cairo-dwrite.h>
+ * #include <dwrite.h>
+ *
+ * IDWriteFactory* dWriteFactory = NULL;
+ * HRESULT hr = DWriteCreateFactory(
+ * DWRITE_FACTORY_TYPE_SHARED,
+ * __uuidof(IDWriteFactory),
+ * reinterpret_cast<IUnknown**>(&dWriteFactory));
+ *
+ * IDWriteFontCollection *systemCollection;
+ * hr = dWriteFactory->GetSystemFontCollection(&systemCollection);
+ *
+ * UINT32 idx;
+ * BOOL found;
+ * systemCollection->FindFamilyName(L"Segoe UI Emoji", &idx, &found);
+ *
+ * IDWriteFontFamily *family;
+ * systemCollection->GetFontFamily(idx, &family);
+ *
+ * IDWriteFont *dwritefont;
+ * DWRITE_FONT_WEIGHT weight = DWRITE_FONT_WEIGHT_NORMAL;
+ * DWRITE_FONT_STYLE style = DWRITE_FONT_STYLE_NORMAL;
+ * hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &dwritefont);
+ *
+ * IDWriteFontFace *dwriteface;
+ * hr = dwritefont->CreateFontFace(&dwriteface);
+ *
+ * cairo_font_face_t *face;
+ * face = cairo_dwrite_font_face_create_for_dwrite_fontface(dwriteface);
+ * cairo_set_font_face(cr, face);
+ * cairo_set_font_size(cr, 70);
+ * cairo_move_to(cr, 100, 100);
+ * cairo_show_text(cr, "😃");
+ * ]]></programlisting></informalexample>
+ *
+ * Note: When printing a DWrite font to a
+ * #CAIRO_SURFACE_TYPE_WIN32_PRINTING surface, the printing surface
+ * will substitute each DWrite font with a Win32 font created from the same
+ * underlying font file. If the matching font file can not be found,
+ * the #CAIRO_SURFACE_TYPE_WIN32_PRINTING surface will convert each
+ * glyph to a filled path. If a DWrite font was not created from a system
+ * font, it is recommended that the font used to create the DWrite
+ * font be made available to GDI to avoid the undesirable fallback
+ * to emitting paths. This can be achieved using the GDI font loading functions
+ * such as AddFontMemResourceEx().
+ *
+ * Return value: a newly created #cairo_font_face_t. Free with
+ * cairo_font_face_destroy() when you are done using it.
+ *
+ * Since: 1.18
+ **/
+cairo_font_face_t *
+cairo_dwrite_font_face_create_for_dwrite_fontface (IDWriteFontFace *dwrite_font_face)
{
- IDWriteFont *dwritefont = static_cast<IDWriteFont*>(dwrite_font);
IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face);
- cairo_dwrite_font_face_t *face = new cairo_dwrite_font_face_t;
- cairo_font_face_t *font_face;
+ // Must do malloc and not C++ new, since Cairo frees this.
+ cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t *)_cairo_malloc(sizeof(cairo_dwrite_font_face_t));
+ if (unlikely (face == NULL)) {
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_font_face_t*)&_cairo_font_face_nil;
+ }
dwriteface->AddRef();
-
face->dwriteface = dwriteface;
- face->font = NULL;
+ face->have_color = false;
+ face->rendering_params = NULL;
+ face->measuring_mode = DWRITE_MEASURING_MODE_NATURAL;
+
+ /* Ensure IDWriteFactory4 is available before enabling color fonts */
+ if (DWriteFactory::Instance4()) {
+ RefPtr<IDWriteFontFace2> fontFace2;
+ if (SUCCEEDED(dwriteface->QueryInterface(&fontFace2))) {
+ if (fontFace2->IsColorFont())
+ face->have_color = true;
+ }
+ }
+ cairo_font_face_t *font_face;
font_face = (cairo_font_face_t*)face;
-
_cairo_font_face_init (&((cairo_dwrite_font_face_t*)font_face)->base, &_cairo_dwrite_font_face_backend);
return font_face;
}
-void
-cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force)
+/**
+ * cairo_dwrite_font_face_get_rendering_params:
+ * @font_face: The #cairo_dwrite_font_face_t object to query
+ *
+ * Gets the #IDWriteRenderingParams object of @font_face.
+ *
+ * Return value: the #IDWriteRenderingParams object or %NULL if none.
+ *
+ * Since: 1.18
+ **/
+IDWriteRenderingParams *
+cairo_dwrite_font_face_get_rendering_params (cairo_font_face_t *font_face)
{
- cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
- if (force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL) {
- font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC;
- } else if (!force && font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC) {
- font->rendering_mode = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL;
- }
+ cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face);
+ return dwface->rendering_params;
}
-cairo_bool_t
-cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font)
+/**
+ * cairo_dwrite_font_face_set_rendering_params:
+ * @font_face: The #cairo_dwrite_font_face_t object to modify
+ * @params: The #IDWriteRenderingParams object
+ *
+ * Sets the #IDWriteRenderingParams object to @font_face.
+ * This #IDWriteRenderingParams is used to render glyphs if default values of font options are used.
+ * If non-defalut values of font options are specified when creating a #cairo_scaled_font_t,
+ * cairo creates a new #IDWriteRenderingParams object for the #cairo_scaled_font_t object by overwriting the corresponding parameters.
+ *
+ * Since: 1.18
+ **/
+void
+cairo_dwrite_font_face_set_rendering_params (cairo_font_face_t *font_face, IDWriteRenderingParams *params)
{
- cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
- return font->rendering_mode == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC;
+ cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face);
+ if (dwface->rendering_params)
+ dwface->rendering_params->Release();
+ dwface->rendering_params = params;
+ if (dwface->rendering_params)
+ dwface->rendering_params->AddRef();
}
-void
-cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level,
- int geometry, int mode)
+/**
+ * cairo_dwrite_font_face_get_measuring_mode:
+ * @font_face: The #cairo_dwrite_font_face_t object to query
+ *
+ * Gets the #DWRITE_MEASURING_MODE enum of @font_face.
+ *
+ * Return value: The #DWRITE_MEASURING_MODE enum of @font_face.
+ *
+ * Since: 1.18
+ **/
+DWRITE_MEASURING_MODE
+cairo_dwrite_font_face_get_measuring_mode (cairo_font_face_t *font_face)
{
- DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode);
+ cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face);
+ return dwface->measuring_mode;
}
-int
-cairo_dwrite_get_cleartype_rendering_mode()
+/**
+ * cairo_dwrite_font_face_set_measuring_mode:
+ * @font_face: The #cairo_dwrite_font_face_t object to modify
+ * @mode: The #DWRITE_MEASURING_MODE enum.
+ *
+ * Sets the #DWRITE_MEASURING_MODE enum to @font_face.
+ *
+ * Since: 1.18
+ **/
+void
+cairo_dwrite_font_face_set_measuring_mode (cairo_font_face_t *font_face, DWRITE_MEASURING_MODE mode)
{
- return DWriteFactory::GetClearTypeRenderingMode();
+ cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t *>(font_face);
+ dwface->measuring_mode = mode;
}
-cairo_int_status_t
+static cairo_int_status_t
_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
DWRITE_MATRIX *transform,
DWRITE_GLYPH_RUN *run,
@@ -947,44 +1611,25 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
cairo_dwrite_scaled_font_t *scaled_font,
const RECT &area)
{
- IDWriteGdiInterop *gdiInterop;
+ RefPtr<IDWriteGdiInterop> gdiInterop;
DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
- IDWriteBitmapRenderTarget *rt;
- HRESULT rv;
-
- cairo_dwrite_scaled_font_t::TextRenderingState renderingState =
- scaled_font->rendering_mode;
+ RefPtr<IDWriteBitmapRenderTarget> rt;
+ HRESULT hr;
- rv = gdiInterop->CreateBitmapRenderTarget(surface->dc,
+ hr = gdiInterop->CreateBitmapRenderTarget(surface->dc,
area.right - area.left,
area.bottom - area.top,
&rt);
- if (FAILED(rv)) {
- if (rv == E_OUTOFMEMORY) {
+ if (FAILED(hr)) {
+ if (hr == E_OUTOFMEMORY) {
return (cairo_int_status_t)CAIRO_STATUS_NO_MEMORY;
} else {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
}
- if ((renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_NORMAL ||
- renderingState == cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC) &&
- !surface->base.permit_subpixel_antialiasing) {
- renderingState = cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE;
- IDWriteBitmapRenderTarget1* rt1;
- rv = rt->QueryInterface(&rt1);
-
- if (SUCCEEDED(rv) && rt1) {
- rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
- rt1->Release();
- }
- }
-
- IDWriteRenderingParams *params =
- DWriteFactory::RenderingParams(renderingState);
-
- /**
+ /*
* We set the number of pixels per DIP to 1.0. This is because we always want
* to draw in device pixels, and not device independent pixels. On high DPI
* systems this value will be higher than 1.0 and automatically upscale
@@ -992,35 +1637,29 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
*/
rt->SetPixelsPerDip(1.0);
+ float x = 0, y = 0;
if (transform) {
- rt->SetCurrentTransform(transform);
+ DWRITE_MATRIX matrix = *transform;
+ matrix.dx -= area.left;
+ matrix.dy -= area.top;
+ rt->SetCurrentTransform(&matrix);
+ } else {
+ x = (float) -area.left;
+ y = (float) -area.top;
}
BitBlt(rt->GetMemoryDC(),
0, 0,
area.right - area.left, area.bottom - area.top,
surface->dc,
- area.left, area.top,
+ area.left, area.top,
SRCCOPY | NOMIRRORBITMAP);
- DWRITE_MEASURING_MODE measureMode;
- switch (renderingState) {
- case cairo_dwrite_scaled_font_t::TEXT_RENDERING_GDI_CLASSIC:
- case cairo_dwrite_scaled_font_t::TEXT_RENDERING_NO_CLEARTYPE:
- measureMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
- break;
- default:
- measureMode = DWRITE_MEASURING_MODE_NATURAL;
- break;
- }
- HRESULT hr = rt->DrawGlyphRun(0, 0, measureMode, run, params, color);
+ rt->DrawGlyphRun(x, y, scaled_font->measuring_mode, run, scaled_font->rendering_params, color);
BitBlt(surface->dc,
area.left, area.top,
area.right - area.left, area.bottom - area.top,
rt->GetMemoryDC(),
- 0, 0,
+ 0, 0,
SRCCOPY | NOMIRRORBITMAP);
- params->Release();
- rt->Release();
- gdiInterop->Release();
return CAIRO_INT_STATUS_SUCCESS;
}
@@ -1031,33 +1670,26 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
COLORREF color,
const RECT &area)
{
- HRESULT rv;
+ HRESULT hr;
- ID2D1DCRenderTarget *rt = D2DFactory::RenderTarget();
+ RefPtr<ID2D1DCRenderTarget> rt = D2DFactory::RenderTarget();
// XXX don't we need to set RenderingParams on this RenderTarget?
- rv = rt->BindDC(surface->dc, &area);
-
- printf("Rendering to surface: %p\n", surface->dc);
-
- if (FAILED(rv)) {
- rt->Release();
+ hr = rt->BindDC(surface->dc, &area);
+ if (FAILED(hr))
return CAIRO_INT_STATUS_UNSUPPORTED;
- }
// D2D uses 0x00RRGGBB not 0x00BBGGRR like COLORREF.
color = (color & 0xFF) << 16 |
(color & 0xFF00) |
(color & 0xFF0000) >> 16;
- ID2D1SolidColorBrush *brush;
- rv = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush);
-
- if (FAILED(rv)) {
- rt->Release();
+ RefPtr<ID2D1SolidColorBrush> brush;
+ hr = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush);
+ if (FAILED(hr))
return CAIRO_INT_STATUS_UNSUPPORTED;
- }
+ float x = 0, y = 0;
if (transform) {
rt->SetTransform(D2D1::Matrix3x2F(transform->m11,
transform->m12,
@@ -1068,14 +1700,12 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
}
rt->BeginDraw();
rt->DrawGlyphRun(D2D1::Point2F(0, 0), run, brush);
- rt->EndDraw();
+ hr = rt->EndDraw();
if (transform) {
rt->SetTransform(D2D1::Matrix3x2F::Identity());
}
- brush->Release();
- if (FAILED(rv)) {
+ if (FAILED(hr))
return CAIRO_INT_STATUS_UNSUPPORTED;
- }
return CAIRO_INT_STATUS_SUCCESS;
}
@@ -1108,15 +1738,6 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
if (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER)
return CAIRO_INT_STATUS_UNSUPPORTED;
- /* If we have a fallback mask clip set on the dst, we have
- * to go through the fallback path */
- if (!_cairo_surface_is_win32_printing (&dst->base)) {
- if (clip != NULL)
- _cairo_win32_display_surface_set_clip (to_win32_display_surface (dst), clip);
- else
- _cairo_win32_display_surface_unset_clip (to_win32_display_surface (dst));
- }
-
/* 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
@@ -1131,97 +1752,8 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets);
BOOL transform = FALSE;
- /* Needed to calculate bounding box for efficient blitting */
- INT32 smallestX = INT_MAX;
- INT32 largestX = 0;
- INT32 smallestY = INT_MAX;
- INT32 largestY = 0;
- for (int i = 0; i < num_glyphs; i++) {
- if (glyphs[i].x < smallestX) {
- smallestX = (INT32)glyphs[i].x;
- }
- if (glyphs[i].x > largestX) {
- largestX = (INT32)glyphs[i].x;
- }
- if (glyphs[i].y < smallestY) {
- smallestY = (INT32)glyphs[i].y;
- }
- if (glyphs[i].y > largestY) {
- largestY = (INT32)glyphs[i].y;
- }
- }
- /**
- * Here we try to get a rough estimate of the area that this glyph run will
- * cover on the surface. Since we use GDI interop to draw we will be copying
- * data around the size of the area of the surface that we map. We will want
- * to map an area as small as possible to prevent large surfaces to be
- * copied around. We take the X/Y-size of the font as margin on the left/top
- * twice the X/Y-size of the font as margin on the right/bottom.
- * This should always cover the entire area where the glyphs are.
- */
- RECT fontArea;
- fontArea.left = (INT32)(smallestX - scaled_font->font_matrix.xx);
- fontArea.right = (INT32)(largestX + scaled_font->font_matrix.xx * 2);
- fontArea.top = (INT32)(smallestY - scaled_font->font_matrix.yy);
- fontArea.bottom = (INT32)(largestY + scaled_font->font_matrix.yy * 2);
- if (fontArea.left < 0)
- fontArea.left = 0;
- if (fontArea.top < 0)
- fontArea.top = 0;
- if (fontArea.bottom > dst->extents.height) {
- fontArea.bottom = dst->extents.height;
- }
- if (fontArea.right > dst->extents.width) {
- fontArea.right = dst->extents.width;
- }
- if (fontArea.right <= fontArea.left ||
- fontArea.bottom <= fontArea.top) {
- return CAIRO_INT_STATUS_SUCCESS;
- }
- if (fontArea.right > dst->extents.width) {
- fontArea.right = dst->extents.width;
- }
- if (fontArea.bottom > dst->extents.height) {
- fontArea.bottom = dst->extents.height;
- }
+ _cairo_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform);
- run.bidiLevel = 0;
- run.fontFace = dwriteff->dwriteface;
- run.isSideways = FALSE;
- if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
- dwritesf->mat.xx == scaled_font->font_matrix.xx &&
- dwritesf->mat.yy == scaled_font->font_matrix.yy) {
-
- for (int i = 0; i < num_glyphs; i++) {
- indices[i] = (WORD) glyphs[i].index;
- // Since we will multiply by our ctm matrix later for rotation effects
- // and such, adjust positions by the inverse matrix now.
- offsets[i].ascenderOffset = (FLOAT)(fontArea.top - glyphs[i].y);
- offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left);
- advances[i] = 0.0;
- }
- run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy;
- } else {
- transform = TRUE;
- // See comment about EPSILON in _cairo_dwrite_glyph_run_from_glyphs
- const double EPSILON = 0.0001;
- for (int i = 0; i < num_glyphs; i++) {
- indices[i] = (WORD) glyphs[i].index;
- double x = glyphs[i].x - fontArea.left + EPSILON;
- double y = glyphs[i].y - fontArea.top;
- cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
- /**
- * Since we will multiply by our ctm matrix later for rotation effects
- * and such, adjust positions by the inverse matrix now. The Y-axis
- * is inverted so the offset becomes negative.
- */
- offsets[i].ascenderOffset = -(FLOAT)y;
- offsets[i].advanceOffset = (FLOAT)x;
- advances[i] = 0.0;
- }
- run.fontEmSize = 1.0f;
- }
-
cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source;
COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8,
((int)solid_pattern->color.green_short) >> 8,
@@ -1236,18 +1768,31 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
mat = NULL;
}
- RECT area;
- area.left = dst->extents.x;
- area.top = dst->extents.y;
- area.right = area.left + dst->extents.width;
- area.bottom = area.top + dst->extents.height;
+ RefPtr<IDWriteGlyphRunAnalysis> runAnalysis;
+ HRESULT hr = DWriteFactory::Instance()->
+ CreateGlyphRunAnalysis(&run, 1, mat,
+ DWRITE_RENDERING_MODE_ALIASED,
+ dwritesf->measuring_mode,
+ 0, // baselineOriginX,
+ 0, // baselineOriginY,
+ &runAnalysis);
+ if (FAILED(hr))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ RECT fontArea;
+ hr = runAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_ALIASED_1x1, &fontArea);
+ if (FAILED(hr))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ InflateRect(&fontArea, 1, 1);
+ /* Needed to calculate bounding box for efficient blitting */
+ RECT copyArea, dstArea = { 0, 0, dst->extents.width, dst->extents.height };
+ IntersectRect(&copyArea, &fontArea, &dstArea);
#ifdef CAIRO_TRY_D2D_TO_GDI
status = _dwrite_draw_glyphs_to_gdi_surface_d2d(dst,
mat,
&run,
color,
- fontArea);
+ copyArea);
if (status == (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED) {
#endif
@@ -1256,7 +1801,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
&run,
color,
dwritesf,
- fontArea);
+ copyArea);
#ifdef CAIRO_TRY_D2D_TO_GDI
}
@@ -1265,104 +1810,100 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
return status;
}
-#define ENHANCED_CONTRAST_REGISTRY_KEY \
- HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel"
-
-void
-DWriteFactory::CreateRenderingParams()
+/* Check if a specific font table in a DWrite font and a scaled font is identical */
+static cairo_int_status_t
+compare_font_tables (cairo_dwrite_font_face_t *dwface,
+ cairo_scaled_font_t *scaled_font,
+ unsigned long tag,
+ cairo_bool_t *match)
{
- if (!Instance()) {
- return;
+ unsigned long size;
+ cairo_int_status_t status;
+ unsigned char *buffer = NULL;
+ const void *dw_data;
+ UINT32 dw_size;
+ void *dw_tableContext = NULL;
+ BOOL dw_exists = FALSE;
+ HRESULT hr;
+
+ hr = dwface->dwriteface->TryGetFontTable(be32_to_cpu (tag),
+ &dw_data,
+ &dw_size,
+ &dw_tableContext,
+ &dw_exists);
+ if (FAILED(hr))
+ return _cairo_dwrite_error (hr, "TryGetFontTable failed");
+
+ if (!dw_exists) {
+ *match = FALSE;
+ status = CAIRO_INT_STATUS_SUCCESS;
+ goto cleanup;
}
- Instance()->CreateRenderingParams(&mDefaultRenderingParams);
+ status = scaled_font->backend->load_truetype_table (scaled_font, tag, 0, NULL, &size);
+ if (unlikely(status))
+ goto cleanup;
- // For EnhancedContrast, we override the default if the user has not set it
- // in the registry (by using the ClearType Tuner).
- FLOAT contrast;
- if (mEnhancedContrast >= 0.0 && mEnhancedContrast <= 10.0) {
- contrast = mEnhancedContrast;
- } else {
- HKEY hKey;
- if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY,
- 0, KEY_READ, &hKey) == ERROR_SUCCESS)
- {
- contrast = mDefaultRenderingParams->GetEnhancedContrast();
- RegCloseKey(hKey);
- } else {
- contrast = 1.0;
- }
+ if (size != dw_size) {
+ *match = FALSE;
+ status = CAIRO_INT_STATUS_SUCCESS;
+ goto cleanup;
+ }
+
+ buffer = (unsigned char *) _cairo_malloc (size);
+ if (unlikely (buffer == NULL)) {
+ status = (cairo_int_status_t) _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ goto cleanup;
}
- // For parameters that have not been explicitly set via the SetRenderingParams API,
- // we copy values from default params (or our overridden value for contrast)
- FLOAT gamma =
- mGamma >= 1.0 && mGamma <= 2.2 ?
- mGamma : mDefaultRenderingParams->GetGamma();
- FLOAT clearTypeLevel =
- mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ?
- mClearTypeLevel : mDefaultRenderingParams->GetClearTypeLevel();
- DWRITE_PIXEL_GEOMETRY pixelGeometry =
- mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ?
- (DWRITE_PIXEL_GEOMETRY)mPixelGeometry : mDefaultRenderingParams->GetPixelGeometry();
- DWRITE_RENDERING_MODE renderingMode =
- mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ?
- (DWRITE_RENDERING_MODE)mRenderingMode : mDefaultRenderingParams->GetRenderingMode();
- Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
- pixelGeometry, renderingMode,
- &mCustomClearTypeRenderingParams);
- Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
- pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
- &mForceGDIClassicRenderingParams);
+ status = scaled_font->backend->load_truetype_table (scaled_font, tag, 0, buffer, &size);
+ if (unlikely(status))
+ goto cleanup;
+
+ *match = memcmp (dw_data, buffer, size) == 0;
+ status = CAIRO_INT_STATUS_SUCCESS;
+
+cleanup:
+ free (buffer);
+ if (dw_tableContext)
+ dwface->dwriteface->ReleaseFontTable(dw_tableContext);
+
+ return status;
}
-static cairo_bool_t
-_name_tables_match (cairo_scaled_font_t *font1,
- cairo_scaled_font_t *font2)
+/* Check if a DWrite font and a scaled font areis identical
+ *
+ * DWrite does not allow accessing the entire font data using tag=0 so we compare
+ * two of the font tables:
+ * - 'name' table
+ * - 'head' table since this contains the checksum for the entire font
+ */
+static cairo_int_status_t
+font_tables_match (cairo_dwrite_font_face_t *dwface,
+ cairo_scaled_font_t *scaled_font,
+ cairo_bool_t *match)
{
- unsigned long size1;
- unsigned long size2;
- cairo_int_status_t status1;
- cairo_int_status_t status2;
- unsigned char *buffer1;
- unsigned char *buffer2;
- cairo_bool_t result = false;
-
- if (!font1->backend || !font2->backend ||
- !font1->backend->load_truetype_table ||
- !font2->backend->load_truetype_table)
- return false;
-
- status1 = font1->backend->load_truetype_table (font1,
- TT_TAG_name, 0, NULL, &size1);
- status2 = font2->backend->load_truetype_table (font2,
- TT_TAG_name, 0, NULL, &size2);
- if (status1 || status2)
- return false;
- if (size1 != size2)
- return false;
-
- buffer1 = (unsigned char*)malloc (size1);
- buffer2 = (unsigned char*)malloc (size2);
-
- if (buffer1 && buffer2) {
- status1 = font1->backend->load_truetype_table (font1,
- TT_TAG_name, 0, buffer1, &size1);
- status2 = font2->backend->load_truetype_table (font2,
- TT_TAG_name, 0, buffer2, &size2);
- if (!status1 && !status2) {
- result = memcmp (buffer1, buffer2, size1) == 0;
- }
- }
-
- free (buffer1);
- free (buffer2);
- return result;
+ cairo_int_status_t status;
+
+ status = compare_font_tables (dwface, scaled_font, TT_TAG_name, match);
+ if (unlikely(status))
+ return status;
+
+ if (!*match)
+ return CAIRO_INT_STATUS_SUCCESS;
+
+ status = compare_font_tables (dwface, scaled_font, TT_TAG_head, match);
+ if (unlikely(status))
+ return status;
+
+ return CAIRO_INT_STATUS_SUCCESS;
}
-// Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
-// of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
-// paths or blitting glyph bitmaps.
+/*
+ * Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
+ * of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
+ * paths or blitting glyph bitmaps.
+ */
cairo_int_status_t
_cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font,
cairo_scaled_font_t **new_font)
@@ -1372,6 +1913,16 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_
}
cairo_font_face_t *face = cairo_scaled_font_get_font_face (scaled_font);
+ if (cairo_font_face_status (face) == CAIRO_STATUS_SUCCESS &&
+ cairo_font_face_get_type (face) == CAIRO_FONT_TYPE_TOY)
+ {
+ face = ((cairo_toy_font_face_t *)face)->impl_face;
+ }
+
+ if (face == NULL || cairo_font_face_get_type (face) != CAIRO_FONT_TYPE_DWRITE) {
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t*>(face);
RefPtr<IDWriteGdiInterop> gdiInterop;
@@ -1384,12 +1935,15 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_
if (FAILED(gdiInterop->ConvertFontFaceToLOGFONT (dwface->dwriteface, &logfont))) {
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- // DW must have been using an outline font, so we want GDI to use the same,
- // even if there's also a bitmap face available
+
+ /* DWrite must have been using an outline font, so we want GDI to use the same,
+ * even if there's also a bitmap face available
+ */
logfont.lfOutPrecision = OUT_OUTLINE_PRECIS;
cairo_font_face_t *win32_face = cairo_win32_font_face_create_for_logfontw (&logfont);
- if (!win32_face) {
+ if (cairo_font_face_status (win32_face)) {
+ cairo_font_face_destroy (win32_face);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -1400,6 +1954,7 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_
cairo_scaled_font_get_ctm (scaled_font, &ctm);
cairo_font_options_t options;
+ _cairo_font_options_init_default (&options);
cairo_scaled_font_get_font_options (scaled_font, &options);
cairo_scaled_font_t *font = cairo_scaled_font_create (win32_face,
@@ -1408,14 +1963,36 @@ _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_
&options);
cairo_font_face_destroy (win32_face);
- if (!font) {
+ if (cairo_scaled_font_status(font)) {
+ cairo_scaled_font_destroy (font);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
- if (!_name_tables_match (font, scaled_font)) {
- // If the font name tables aren't equal, then GDI may have failed to
- // find the right font and substituted a different font.
- cairo_scaled_font_destroy (font);
+ cairo_bool_t match;
+ cairo_int_status_t status;
+ status = font_tables_match (dwface, font, &match);
+ if (status) {
+ cairo_scaled_font_destroy (font);
+ return status;
+ }
+
+ /* If the font tables aren't equal, then GDI may have failed to
+ * find the right font and substituted a different font.
+ */
+ if (!match) {
+#if 0
+ char *ps_name;
+ char *font_name;
+ status = _cairo_truetype_read_font_name (scaled_font, &ps_name, &font_name);
+ printf("dwrite fontname: %s PS name: %s\n", font_name, ps_name);
+ free (font_name);
+ free (ps_name);
+ status = _cairo_truetype_read_font_name (font, &ps_name, &font_name);
+ printf("win32 fontname: %s PS name: %s\n", font_name, ps_name);
+ free (font_name);
+ free (ps_name);
+#endif
+ cairo_scaled_font_destroy (font);
return CAIRO_INT_STATUS_UNSUPPORTED;
}
diff --git a/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h b/gfx/cairo/cairo/src/win32/cairo-dwrite-private.hpp
index 5f2994cbc0..c7a24822a7 100644
--- a/gfx/cairo/cairo/src/win32/cairo-dwrite-private.h
+++ b/gfx/cairo/cairo/src/win32/cairo-dwrite-private.hpp
@@ -33,9 +33,28 @@
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*/
-#include <dwrite_1.h>
+
+#include "cairoint.h"
+#include "cairo-win32-refptr.hpp"
+#include <dwrite_3.h>
#include <d2d1.h>
+#ifdef __MINGW32__
+#include "dw-extra.h"
+#else
+typedef DWRITE_COLOR_GLYPH_RUN1 DWRITE_COLOR_GLYPH_RUN1_WORKAROUND;
+#endif
+
+/* If d2d1_3.h header required for color fonts is not available,
+ * include our own version containing just the functions we need.
+ */
+
+#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,
@@ -43,31 +62,32 @@ typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
IUnknown **factory
);
-/* cairo_scaled_font_t implementation */
+/* #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;
+ IDWriteRenderingParams *rendering_params;
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()
+ static RefPtr<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,
@@ -79,7 +99,47 @@ public:
return mFactoryInstance;
}
- static IDWriteFontCollection *SystemCollection()
+ static RefPtr<IDWriteFactory1> Instance1()
+ {
+ if (!mFactoryInstance1) {
+ if (Instance()) {
+ Instance()->QueryInterface(&mFactoryInstance1);
+ }
+ }
+ return mFactoryInstance1;
+ }
+
+ static RefPtr<IDWriteFactory2> Instance2()
+ {
+ if (!mFactoryInstance2) {
+ if (Instance()) {
+ Instance()->QueryInterface(&mFactoryInstance2);
+ }
+ }
+ return mFactoryInstance2;
+ }
+
+ static RefPtr<IDWriteFactory3> Instance3()
+ {
+ if (!mFactoryInstance3) {
+ if (Instance()) {
+ Instance()->QueryInterface(&mFactoryInstance3);
+ }
+ }
+ return mFactoryInstance3;
+ }
+
+ static RefPtr<IDWriteFactory4> Instance4()
+ {
+ if (!mFactoryInstance4) {
+ if (Instance()) {
+ Instance()->QueryInterface(&mFactoryInstance4);
+ }
+ }
+ return mFactoryInstance4;
+ }
+
+ static RefPtr<IDWriteFontCollection> SystemCollection()
{
if (!mSystemCollection) {
if (Instance()) {
@@ -90,7 +150,7 @@ public:
return mSystemCollection;
}
- static IDWriteFontFamily *FindSystemFontFamily(const WCHAR *aFamilyName)
+ static RefPtr<IDWriteFontFamily> FindSystemFontFamily(const WCHAR *aFamilyName)
{
UINT32 idx;
BOOL found;
@@ -102,76 +162,29 @@ public:
return NULL;
}
- IDWriteFontFamily *family;
+ RefPtr<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)
+ static RefPtr<IDWriteRenderingParams> DefaultRenderingParams()
{
- 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;
+ if (!mDefaultRenderingParams) {
+ if (Instance()) {
+ Instance()->CreateRenderingParams(&mDefaultRenderingParams);
+ }
}
- }
-
- static int GetClearTypeRenderingMode() {
- return mRenderingMode;
+ return mDefaultRenderingParams;
}
private:
- static void CreateRenderingParams();
-
- static IDWriteFactory *mFactoryInstance;
- 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;
+ static RefPtr<IDWriteFactory> mFactoryInstance;
+ static RefPtr<IDWriteFactory1> mFactoryInstance1;
+ static RefPtr<IDWriteFactory2> mFactoryInstance2;
+ static RefPtr<IDWriteFactory3> mFactoryInstance3;
+ static RefPtr<IDWriteFactory4> mFactoryInstance4;
+ static RefPtr<IDWriteFontCollection> mSystemCollection;
+ static RefPtr<IDWriteRenderingParams> mDefaultRenderingParams;
};
class AutoDWriteGlyphRun : public DWRITE_GLYPH_RUN
@@ -210,20 +223,12 @@ private:
UINT16 mAutoIndices[kNumAutoGlyphs];
};
-/* cairo_font_face_t implementation */
+/* #cairo_font_face_t implementation */
struct _cairo_dwrite_font_face {
cairo_font_face_t base;
- IDWriteFont *font;
- IDWriteFontFace *dwriteface;
+ IDWriteFontFace *dwriteface; /* Can't use RefPtr because this struct is malloc'd. */
+ cairo_bool_t have_color;
+ IDWriteRenderingParams *rendering_params; /* Can't use RefPtr because this struct is malloc'd. */
+ DWRITE_MEASURING_MODE measuring_mode;
};
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);
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-debug.c b/gfx/cairo/cairo/src/win32/cairo-win32-debug.c
index 5a971bd614..01410c8969 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-debug.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-debug.c
@@ -37,15 +37,6 @@
* Vladimir Vukicevic <vladimir@pobox.com>
*/
-#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"
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-device.c b/gfx/cairo/cairo/src/win32/cairo-win32-device.c
index 6fce722ecf..781ee0cde1 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-device.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-device.c
@@ -37,15 +37,6 @@
* Vladimir Vukicevic <vladimir@pobox.com>
*/
-#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"
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c
index 304d34aea0..e3b3eec2fe 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-display-surface.c
@@ -37,15 +37,6 @@
* Vladimir Vukicevic <vladimir@pobox.com>
*/
-#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"
@@ -129,6 +120,8 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface,
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_RGB96F:
+ case CAIRO_FORMAT_RGBA128F:
return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_RGB24:
@@ -164,6 +157,8 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface,
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_RGB96F:
+ case CAIRO_FORMAT_RGBA128F:
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
@@ -242,6 +237,8 @@ _create_dc_and_bitmap (cairo_win32_display_surface_t *surface,
case CAIRO_FORMAT_INVALID:
case CAIRO_FORMAT_RGB16_565:
case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_RGB96F:
+ case CAIRO_FORMAT_RGBA128F:
ASSERT_NOT_REACHED;
case CAIRO_FORMAT_ARGB32:
case CAIRO_FORMAT_RGB24:
@@ -981,11 +978,18 @@ cairo_win32_surface_create_with_format (HDC hdc, cairo_format_t format)
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;
+ case CAIRO_FORMAT_INVALID:
+ case CAIRO_FORMAT_A8:
+ case CAIRO_FORMAT_A1:
+ case CAIRO_FORMAT_RGB16_565:
+ case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_RGB96F:
+ case CAIRO_FORMAT_RGBA128F:
+ 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));
@@ -1096,14 +1100,19 @@ cairo_win32_surface_create_with_ddb (HDC hdc,
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;
+ case CAIRO_FORMAT_INVALID:
+ case CAIRO_FORMAT_A8:
+ case CAIRO_FORMAT_A1:
+ case CAIRO_FORMAT_RGB16_565:
+ case CAIRO_FORMAT_RGB30:
+ case CAIRO_FORMAT_RGB96F:
+ case CAIRO_FORMAT_RGBA128F:
+ default:
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+ case CAIRO_FORMAT_ARGB32:
+ case CAIRO_FORMAT_RGB24:
+ break;
}
if (!hdc) {
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-font.c b/gfx/cairo/cairo/src/win32/cairo-win32-font.c
index 3452c6cf4e..a561e74a44 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-font.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-font.c
@@ -33,15 +33,6 @@
* 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"
@@ -71,12 +62,15 @@
/**
* SECTION:cairo-win32-fonts
- * @Title: Win32 Fonts
+ * @Title: Win32 GDI 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.
+ *
+ * Note: Win32 GDI fonts do not support color fonts. Use DWrite fonts
+ * if color font support is required.
**/
/**
@@ -650,226 +644,6 @@ _cairo_win32_scaled_font_fini (void *abstract_font)
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)
@@ -1319,7 +1093,8 @@ _draw_glyphs_on_surface (cairo_win32_surface_t *surface,
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_scaled_glyph_info_t info,
+ const cairo_color_t *foreground_color)
{
cairo_win32_scaled_font_t *scaled_font = abstract_font;
cairo_status_t status;
@@ -1330,6 +1105,12 @@ _cairo_win32_scaled_font_glyph_init (void *abstract_font,
return status;
}
+ if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
+ scaled_glyph->color_glyph = FALSE;
+ scaled_glyph->color_glyph_set = TRUE;
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
status = _cairo_win32_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
if (status)
@@ -1554,9 +1335,9 @@ _cairo_win32_scaled_font_load_type1_data (void *abstract_font,
length);
}
-static cairo_surface_t *
-_compute_mask (cairo_surface_t *surface,
- int quality)
+cairo_surface_t *
+_cairo_compute_glyph_mask (cairo_surface_t *surface,
+ int quality)
{
cairo_image_surface_t *glyph;
cairo_image_surface_t *mask;
@@ -1640,7 +1421,7 @@ _cairo_win32_scaled_font_init_glyph_surface (cairo_win32_scaled_font_t *scaled_f
if (status)
goto FAIL;
- image = _compute_mask (surface, scaled_font->quality);
+ image = _cairo_compute_glyph_mask (surface, scaled_font->quality);
status = image->status;
if (status)
goto FAIL;
@@ -1843,7 +1624,7 @@ 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 */
+ NULL, /* _cairo_win32_scaled_font_text_to_glyphs */
_cairo_win32_scaled_font_ucs4_to_index,
_cairo_win32_scaled_font_load_truetype_table,
_cairo_win32_scaled_font_index_to_ucs4,
@@ -1960,7 +1741,7 @@ _cairo_win32_font_face_init_key (cairo_win32_font_face_t *key,
LOGFONTW *logfont,
HFONT font)
{
- unsigned long hash = _CAIRO_HASH_INIT_VALUE;
+ uintptr_t hash = _CAIRO_HASH_INIT_VALUE;
key->logfont = *logfont;
key->hfont = font;
@@ -2017,7 +1798,7 @@ _cairo_win32_font_face_scaled_font_create (void *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)) {
+ _is_scale (font_matrix, -font_face->logfont.lfHeight * WIN32_FONT_LOGICAL_SCALE)) {
hfont = font_face->hfont;
}
}
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c b/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c
index 1d1d7f8737..bc1f69e703 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-gdi-compositor.c
@@ -602,7 +602,8 @@ static cairo_bool_t check_glyphs (cairo_composite_rectangles_t *composite,
if (! _cairo_clip_is_region (composite->clip))
return FALSE;
- if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_WIN32)
+ cairo_font_type_t type = cairo_scaled_font_get_type (scaled_font);
+ if (type != CAIRO_FONT_TYPE_WIN32 && type != CAIRO_FONT_TYPE_DWRITE)
return FALSE;
if (! _cairo_pattern_is_opaque_solid (&composite->source_pattern.base))
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c
index 96e65893e0..a3dd907c2c 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-printing-surface.c
@@ -35,15 +35,6 @@
* Vladimir Vukicevic <vladimir@pobox.com>
*/
-#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"
@@ -167,8 +158,15 @@ _cairo_win32_printing_surface_init_language_pack (cairo_win32_printing_surface_t
module = GetModuleHandleW (L"GDI32.DLL");
if (module) {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wcast-function-type"
+#endif
gdi_init_lang_pack = (gdi_init_lang_pack_func_t)
GetProcAddress (module, "GdiInitializeLanguagePack");
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
if (gdi_init_lang_pack)
gdi_init_lang_pack (0);
}
@@ -656,6 +654,7 @@ _cairo_win32_printing_surface_paint_recording_pattern (cairo_win32_printing_surf
SaveDC (surface->win32.dc); /* Allow clip path to be reset during replay */
status = _cairo_recording_surface_replay_region (&recording_surface->base,
+ pattern->region_array_id,
is_subsurface ? &recording_extents : NULL,
&surface->win32.base,
CAIRO_RECORDING_REGION_NATIVE);
@@ -1521,7 +1520,7 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface,
cairo_matrix_multiply (&mat, stroke_ctm, &surface->ctm);
_cairo_matrix_factor_out_scale (&mat, &scale);
- pen_style = PS_GEOMETRIC;
+ pen_style = style->is_hairline ? PS_COSMETIC : PS_GEOMETRIC;
dash_array = NULL;
if (style->num_dashes) {
pen_style |= PS_USERSTYLE;
@@ -1547,10 +1546,12 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface,
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);
+ if (!style->is_hairline) {
+ 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,
+ style->is_hairline ? 1 : scale * style->line_width,
&brush,
style->num_dashes,
dash_array);
@@ -1871,6 +1872,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
if (status)
break;
@@ -1942,6 +1944,7 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
status = _cairo_scaled_glyph_lookup (scaled_font,
glyphs[i].index,
CAIRO_SCALED_GLYPH_INFO_PATH,
+ NULL, /* foreground color */
&scaled_glyph);
if (status)
break;
@@ -2151,6 +2154,9 @@ _cairo_win32_printing_surface_supports_fine_grained_fallbacks (void *abstract_su
* provide correct complex rendering behaviour; cairo_surface_show_page() and
* associated methods must be used for correct output.
*
+ * The following mime types are supported on source patterns:
+ * %CAIRO_MIME_TYPE_JPEG, %CAIRO_MIME_TYPE_PNG.
+ *
* Return value: the newly created surface
*
* Since: 1.6
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-private.h b/gfx/cairo/cairo/src/win32/cairo-win32-private.h
index e6be49b032..6af09c0e1f 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-private.h
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-private.h
@@ -214,6 +214,10 @@ cairo_bool_t
_cairo_win32_surface_get_extents (void *abstract_surface,
cairo_rectangle_int_t *rectangle);
+cairo_surface_t *
+_cairo_compute_glyph_mask (cairo_surface_t *surface,
+ int quality);
+
uint32_t
_cairo_win32_flags_for_dc (HDC dc, cairo_format_t format);
@@ -253,7 +257,10 @@ _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);
-#ifdef CAIRO_HAS_DWRITE_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,
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-refptr.h b/gfx/cairo/cairo/src/win32/cairo-win32-refptr.hpp
index f045ddf627..e361e4cf7f 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-refptr.h
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-refptr.hpp
@@ -38,7 +38,7 @@
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
@@ -99,7 +99,7 @@ public:
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
@@ -137,7 +137,7 @@ private:
}
};
-/**
+/*
* 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
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c
index e1e6494cce..9cd6f55fcc 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-surface.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-surface.c
@@ -37,15 +37,6 @@
* Vladimir Vukicevic <vladimir@pobox.com>
*/
-#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-backend-private.h"
@@ -171,46 +162,50 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface)
return NULL;
}
+/**
+ * cairo_win32_get_dc_with_clip:
+ * (Mozilla addition)
+ */
HDC
-cairo_win32_get_dc_with_clip (cairo_t *cr)
+cairo_win32_get_dc_with_clip(cairo_t* cr)
{
- cairo_surface_t *surface = cairo_get_target (cr);
- if (cr->backend->type == CAIRO_TYPE_DEFAULT) {
- cairo_default_context_t *c = (cairo_default_context_t *) cr;
- cairo_clip_t *clip = _cairo_clip_copy (_cairo_gstate_get_clip (c->gstate));
- if (_cairo_surface_is_win32 (surface)) {
- cairo_win32_display_surface_t *winsurf = (cairo_win32_display_surface_t *) surface;
+ cairo_surface_t* surface = cairo_get_target(cr);
+ if (cr->backend->type == CAIRO_TYPE_DEFAULT) {
+ cairo_default_context_t* c = (cairo_default_context_t*)cr;
+ cairo_clip_t* clip = _cairo_clip_copy(_cairo_gstate_get_clip(c->gstate));
+ if (_cairo_surface_is_win32(surface)) {
+ cairo_win32_display_surface_t* winsurf = (cairo_win32_display_surface_t*)surface;
- _cairo_win32_display_surface_set_clip (winsurf, clip);
+ _cairo_win32_display_surface_set_clip(winsurf, clip);
- _cairo_clip_destroy (clip);
- return winsurf->win32.dc;
- }
+ _cairo_clip_destroy(clip);
+ return winsurf->win32.dc;
+ }
- if (_cairo_surface_is_paginated (surface)) {
- cairo_surface_t *target;
+ if (_cairo_surface_is_paginated(surface)) {
+ cairo_surface_t* target;
- target = _cairo_paginated_surface_get_target (surface);
+ target = _cairo_paginated_surface_get_target(surface);
#ifndef CAIRO_OMIT_WIN32_PRINTING
- if (_cairo_surface_is_win32_printing (target)) {
- cairo_status_t status;
- cairo_win32_printing_surface_t *psurf = (cairo_win32_printing_surface_t *) target;
+ if (_cairo_surface_is_win32_printing(target)) {
+ cairo_status_t status;
+ cairo_win32_printing_surface_t* psurf = (cairo_win32_printing_surface_t*)target;
- status = _cairo_surface_clipper_set_clip (&psurf->clipper, clip);
+ status = _cairo_surface_clipper_set_clip(&psurf->clipper, clip);
- _cairo_clip_destroy (clip);
+ _cairo_clip_destroy(clip);
- if (status)
- return NULL;
+ if (status)
+ return NULL;
- return psurf->win32.dc;
- }
+ return psurf->win32.dc;
+ }
#endif
- }
- _cairo_clip_destroy (clip);
}
- return NULL;
+ _cairo_clip_destroy(clip);
+ }
+ return NULL;
}
/**
@@ -390,16 +385,15 @@ _cairo_win32_surface_emit_glyphs (cairo_win32_surface_t *dst,
#undef STACK_GLYPH_SIZE
cairo_status_t
-cairo_win32_surface_get_size (const cairo_surface_t *surface, int *width, int *height)
+cairo_win32_surface_get_size(const cairo_surface_t* surface, int* width, int* height)
{
- if (surface->type != CAIRO_SURFACE_TYPE_WIN32)
- return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
+ if (!_cairo_surface_is_win32(surface))
+ return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
- const cairo_win32_surface_t *winsurface = (const cairo_win32_surface_t *) surface;
+ const cairo_win32_surface_t* winsurface = (const cairo_win32_surface_t*)surface;
- *width = winsurface->extents.width;
- *height = winsurface->extents.height;
-
- return CAIRO_STATUS_SUCCESS;
-}
+ *width = winsurface->extents.width;
+ *height = winsurface->extents.height;
+ return CAIRO_STATUS_SUCCESS;
+} \ No newline at end of file
diff --git a/gfx/cairo/cairo/src/win32/cairo-win32-system.c b/gfx/cairo/cairo/src/win32/cairo-win32-system.c
index 878553009f..01bbe89dfb 100644
--- a/gfx/cairo/cairo/src/win32/cairo-win32-system.c
+++ b/gfx/cairo/cairo/src/win32/cairo-win32-system.c
@@ -50,15 +50,6 @@
#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 <windows.h>
/* declare to avoid "no previous prototype for 'DllMain'" warning */
diff --git a/gfx/cairo/cairo/src/win32/d2d1-extra.h b/gfx/cairo/cairo/src/win32/d2d1-extra.h
new file mode 100644
index 0000000000..7515a5c90f
--- /dev/null
+++ b/gfx/cairo/cairo/src/win32/d2d1-extra.h
@@ -0,0 +1,122 @@
+/* -*- 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;
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID2D1DeviceContext1, 0xd37f57e4, 0x6908, 0x459f, 0xa1, 0x99, 0xe7, 0x2f, 0x24, 0xf7, 0x99, 0x87)
+#endif
+
+
+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;
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID2D1DeviceContext2, 0x394ea6a3, 0x0c34, 0x4321, 0x95, 0x0b, 0x6c, 0xa2, 0x0f, 0x0b, 0xe6, 0xc7)
+#endif
+
+
+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;
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID2D1DeviceContext3, 0x235a7496, 0x8351, 0x414c, 0xbc, 0xd4, 0x66, 0x72, 0xab, 0x2d, 0x8e, 0x00)
+#endif
+
+
+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;
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID2D1SvgGlyphStyle, 0xaf671749, 0xd241, 0x4db8, 0x8e, 0x41, 0xdc, 0xc2, 0xe5, 0xc1, 0xa4, 0x38)
+#endif
+
+
+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;
+
+};
+#ifdef __CRT_UUID_DECL
+__CRT_UUID_DECL(ID2D1DeviceContext4, 0x8c427831, 0x3d90, 0x4476, 0xb6, 0x47, 0xc4, 0xfa, 0xe3, 0x49, 0xe4, 0xdb)
+#endif
+
+#endif
diff --git a/gfx/cairo/cairo/src/win32/dw-extra.h b/gfx/cairo/cairo/src/win32/dw-extra.h
new file mode 100644
index 0000000000..424fb606db
--- /dev/null
+++ b/gfx/cairo/cairo/src/win32/dw-extra.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+
+/* MinGW workarounds
+ *
+ * It doesn't define operators for DWRITE_GLYPH_IMAGE_FORMATS.
+ * The DWRITE_COLOR_GLYPH_RUN struct isn't valid.
+ * <https://sourceforge.net/p/mingw-w64/bugs/913/>
+ */
+
+#ifndef DWRITE_EXTRA_H
+#define DWRITE_EXTRA_H
+
+#if defined(__MINGW64_VERSION_MAJOR) && __MINGW64_VERSION_MAJOR < 10
+
+typedef struct DWRITE_COLOR_GLYPH_RUN1_WORKAROUND DWRITE_COLOR_GLYPH_RUN1_WORKAROUND;
+struct DWRITE_COLOR_GLYPH_RUN1_WORKAROUND : DWRITE_COLOR_GLYPH_RUN
+{
+ DWRITE_GLYPH_IMAGE_FORMATS glyphImageFormat;
+ DWRITE_MEASURING_MODE measuringMode;
+};
+
+#else
+typedef DWRITE_COLOR_GLYPH_RUN1 DWRITE_COLOR_GLYPH_RUN1_WORKAROUND;
+#endif
+
+DEFINE_ENUM_FLAG_OPERATORS(DWRITE_GLYPH_IMAGE_FORMATS);
+
+#endif /* DWRITE_EXTRA_H */