summaryrefslogtreecommitdiff
path: root/src/win32/cairo-dwrite-font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/win32/cairo-dwrite-font.cpp')
-rw-r--r--src/win32/cairo-dwrite-font.cpp760
1 files changed, 409 insertions, 351 deletions
diff --git a/src/win32/cairo-dwrite-font.cpp b/src/win32/cairo-dwrite-font.cpp
index c58827555..cf516d41c 100644
--- a/src/win32/cairo-dwrite-font.cpp
+++ b/src/win32/cairo-dwrite-font.cpp
@@ -45,10 +45,31 @@
#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,
@@ -191,22 +212,119 @@ private:
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<IDWriteRenderingParams> DWriteFactory::mCustomClearTypeRenderingParams;
-RefPtr<IDWriteRenderingParams> DWriteFactory::mForceGDIClassicRenderingParams;
-FLOAT DWriteFactory::mGamma = -1.0;
-FLOAT DWriteFactory::mEnhancedContrast = -1.0;
-FLOAT DWriteFactory::mClearTypeLevel = -1.0;
-int DWriteFactory::mPixelGeometry = -1;
-int DWriteFactory::mRenderingMode = -1;
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,
@@ -330,7 +448,7 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, face_name, face_name_len);
RefPtr<IDWriteFontFamily> family = DWriteFactory::FindSystemFontFamily(face_name);
- delete face_name;
+ delete[] face_name;
if (!family) {
/* 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);
@@ -338,7 +456,7 @@ _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
MultiByteToWideChar(CP_UTF8, 0, CAIRO_FONT_FAMILY_DEFAULT, -1, face_name, face_name_len);
family = DWriteFactory::FindSystemFontFamily(face_name);
- delete 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;
@@ -390,6 +508,8 @@ _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->rendering_params)
+ dwrite_font_face->rendering_params->Release();
return TRUE;
}
@@ -536,10 +656,21 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
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;
@@ -547,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;
- 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_antialias_t default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
- dwrite_font->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-
@@ -566,12 +690,10 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
break;
case ANTIALIASED_QUALITY:
default_quality = CAIRO_ANTIALIAS_GRAY;
- dwrite_font->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;
- dwrite_font->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
break;
}
@@ -587,9 +709,8 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
dwrite_font->antialias_mode = options->antialias;
}
- dwrite_font->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);
}
@@ -598,6 +719,9 @@ _cairo_dwrite_font_face_scaled_font_create (void *abstract_face,
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
@@ -659,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;
@@ -679,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,
@@ -699,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)
@@ -738,28 +881,18 @@ 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)
{
- mStartPoint = 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,
- GetFixedX(startPoint),
- GetFixedY(startPoint));
+ mStartPointX,
+ mStartPointY);
(void)status; /* squelch warning */
}
@@ -768,8 +901,8 @@ public:
{
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 */
}
}
@@ -779,13 +912,22 @@ 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 */
}
}
@@ -795,16 +937,21 @@ public:
UINT pointsCount)
{
for (unsigned int i = 0; i < pointsCount; 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,
- GetFixedX(points[i]),
- GetFixedY(points[i]));
+ _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;
};
static cairo_int_status_t
@@ -814,7 +961,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
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;
@@ -823,12 +970,7 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
FLOAT advance = 0.0;
cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face;
- /* GetGlyphRunOutline seems to ignore hinting so just use the em size to get the outline
- * to avoid rounding errors when converting to cairo_path_fixed_t.
- */
- DWRITE_FONT_METRICS metrics;
- dwriteff->dwriteface->GetMetrics(&metrics);
- HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(metrics.designUnitsPerEm,
+ HRESULT hr = dwriteff->dwriteface->GetGlyphRunOutline(1,
&glyphId,
&advance,
&offset,
@@ -841,12 +983,6 @@ _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_fon
status = (cairo_int_status_t)_cairo_path_fixed_close_path(path);
- /* Now scale the em size down to 1.0 and apply the font matrix and font ctm. */
- cairo_matrix_t mat = scaled_font->base.ctm;
- cairo_matrix_multiply(&mat, &scaled_font->base.font_matrix, &mat);
- cairo_matrix_scale (&mat, 1.0/metrics.designUnitsPerEm, 1.0/metrics.designUnitsPerEm);
- _cairo_path_fixed_transform(path, &mat);
-
_cairo_scaled_glyph_set_path (scaled_glyph,
&scaled_font->base,
path);
@@ -860,7 +996,6 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
{
int width, height;
double x1, y1, x2, y2;
- cairo_glyph_t glyph;
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;
@@ -877,22 +1012,18 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
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);
DWRITE_MATRIX matrix;
D2D1_POINT_2F origin = {0, 0};
RefPtr<IDWriteColorGlyphRunEnumerator1> run_enumerator;
HRESULT hr;
- /**
+ /*
* 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
@@ -901,7 +1032,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
*/
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;
run.fontFace = dwrite_font_face->dwriteface;
@@ -938,7 +1069,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
&run,
NULL, /* glyphRunDescription */
supported_formats,
- DWRITE_MEASURING_MODE_NATURAL,
+ dwrite_font_face->measuring_mode,
&matrix,
palette_index,
&run_enumerator);
@@ -1013,8 +1144,8 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
if (FAILED(hr) || !have_run)
break;
- DWRITE_COLOR_GLYPH_RUN1 const* color_run;
- hr = run_enumerator->GetCurrentRun(&color_run);
+ 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");
@@ -1027,7 +1158,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
dc4->DrawColorBitmapGlyphRun(color_run->glyphImageFormat,
origin,
&color_run->glyphRun,
- DWRITE_MEASURING_MODE_NATURAL,
+ dwrite_font_face->measuring_mode,
D2D1_COLOR_BITMAP_GLYPH_SNAP_OPTION_DEFAULT);
break;
@@ -1038,7 +1169,7 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
foreground_color_brush,
nullptr,
palette_index,
- DWRITE_MEASURING_MODE_NATURAL);
+ dwrite_font_face->measuring_mode);
uses_foreground_color = TRUE;
break;
case DWRITE_GLYPH_IMAGE_FORMATS_TRUETYPE:
@@ -1050,14 +1181,23 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
color_brush->SetColor(&color);
uses_foreground_color = TRUE;
} else {
- color_brush->SetColor(color_run->runColor);
+ 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_MEASURING_MODE_NATURAL);
+ dwrite_font_face->measuring_mode);
case DWRITE_GLYPH_IMAGE_FORMATS_NONE:
break;
}
@@ -1079,55 +1219,18 @@ _cairo_dwrite_scaled_font_init_glyph_color_surface(cairo_dwrite_scaled_font_t *s
_cairo_scaled_glyph_set_color_surface (scaled_glyph,
&scaled_font->base,
(cairo_image_surface_t *) image,
- uses_foreground_color);
+ uses_foreground_color ? foreground_color : NULL);
scaled_glyph->color_glyph = TRUE;
scaled_glyph->color_glyph_set = TRUE;
return CAIRO_INT_STATUS_SUCCESS;
}
-/* 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)
-{
- cairo_image_surface_t *glyph;
- cairo_image_surface_t *mask;
- int i, j;
-
- glyph = (cairo_image_surface_t *)cairo_surface_map_to_image (surface, NULL);
- if (unlikely (glyph->base.status))
- return &glyph->base;
-
- /* No quality param, just use the non-ClearType path */
-
- /* Compute an alpha-mask by using the green channel of a (presumed monochrome)
- * RGB24 image.
- */
- mask = (cairo_image_surface_t *)
- cairo_image_surface_create (CAIRO_FORMAT_A8, glyph->width, glyph->height);
- if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) {
- for (i = 0; i < glyph->height; i++) {
- uint32_t *p = (uint32_t *) (glyph->data + i * glyph->stride);
- uint8_t *q = (uint8_t *) (mask->data + i * mask->stride);
-
- for (j = 0; j < glyph->width; j++)
- *q++ = 255 - ((*p++ & 0x0000ff00) >> 8);
- }
- }
-
- cairo_surface_unmap_image (surface, &glyph->base);
- return &mask->base;
-}
-
static cairo_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;
@@ -1141,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;
@@ -1165,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
@@ -1174,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;
@@ -1200,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;
@@ -1336,8 +1435,70 @@ _cairo_dwrite_has_color_glyphs(void *scaled_font)
return ((cairo_dwrite_font_face_t *)dwritesf->base.font_face)->have_color;
}
-cairo_font_face_t*
-cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_face)
+/**
+ * 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)
{
IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face);
// Must do malloc and not C++ new, since Cairo frees this.
@@ -1350,6 +1511,8 @@ cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_fac
dwriteface->AddRef();
face->dwriteface = dwriteface;
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()) {
@@ -1367,35 +1530,77 @@ cairo_dwrite_font_face_create_for_dwrite_fontface_internal(void* dwrite_font_fac
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;
}
static cairo_int_status_t
@@ -1411,9 +1616,6 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
RefPtr<IDWriteBitmapRenderTarget> rt;
HRESULT hr;
- cairo_dwrite_scaled_font_t::TextRenderingState renderingState =
- scaled_font->rendering_mode;
-
hr = gdiInterop->CreateBitmapRenderTarget(surface->dc,
area.right - area.left,
area.bottom - area.top,
@@ -1427,22 +1629,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
}
}
- 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;
- RefPtr<IDWriteBitmapRenderTarget1> rt1;
- hr = rt->QueryInterface(&rt1);
-
- if (SUCCEEDED(hr) && rt1) {
- rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
- }
- }
-
- RefPtr<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
@@ -1450,8 +1637,15 @@ _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,
@@ -1459,17 +1653,7 @@ _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
surface->dc,
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;
- }
- 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,
@@ -1505,6 +1689,7 @@ _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
if (FAILED(hr))
return CAIRO_INT_STATUS_UNSUPPORTED;
+ float x = 0, y = 0;
if (transform) {
rt->SetTransform(D2D1::Matrix3x2F(transform->m11,
transform->m12,
@@ -1553,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
@@ -1576,96 +1752,7 @@ _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;
- }
-
- 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_dwrite_glyph_run_from_glyphs(glyphs, num_glyphs, dwritesf, &run, &transform);
cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source;
COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8,
@@ -1681,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
@@ -1701,7 +1801,7 @@ _cairo_dwrite_show_glyphs_on_surface(void *surface,
&run,
color,
dwritesf,
- fontArea);
+ copyArea);
#ifdef CAIRO_TRY_D2D_TO_GDI
}
@@ -1710,59 +1810,6 @@ _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()
-{
- if (!Instance()) {
- return;
- }
-
- Instance()->CreateRenderingParams(&mDefaultRenderingParams);
-
- // 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;
- }
- }
-
- // 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);
-}
-
/* 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,
@@ -1866,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;
@@ -1897,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,