1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* Cairo - a vector graphics library with display and print output
3  *
4  * Copyright � 2010 Mozilla Foundation
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it either under the terms of the GNU Lesser General Public
8  * License version 2.1 as published by the Free Software Foundation
9  * (the "LGPL") or, at your option, under the terms of the Mozilla
10  * Public License Version 1.1 (the "MPL"). If you do not alter this
11  * notice, a recipient may use your version of this file under either
12  * the MPL or the LGPL.
13  *
14  * You should have received a copy of the LGPL along with this library
15  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  * You should have received a copy of the MPL along with this library
18  * in the file COPYING-MPL-1.1
19  *
20  * The contents of this file are subject to the Mozilla Public License
21  * Version 1.1 (the "License"); you may not use this file except in
22  * compliance with the License. You may obtain a copy of the License at
23  * http://www.mozilla.org/MPL/
24  *
25  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27  * the specific language governing rights and limitations.
28  *
29  * The Original Code is the cairo graphics library.
30  *
31  * The Initial Developer of the Original Code is the Mozilla Foundation
32  *
33  * Contributor(s):
34  *	Bas Schouten <bschouten@mozilla.com>
35  */
36 
37 #include "cairoint.h"
38 
39 #include "cairo-win32-private.h"
40 #include "cairo-surface-private.h"
41 #include "cairo-clip-private.h"
42 
43 #include "cairo-d2d-private.h"
44 #include "cairo-dwrite-private.h"
45 #include "cairo-truetype-subset-private.h"
46 #include <float.h>
47 
48 typedef HRESULT (WINAPI*D2D1CreateFactoryFunc)(
49     D2D1_FACTORY_TYPE factoryType,
50     REFIID iid,
51     CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
52     void **factory
53 );
54 
55 #define CAIRO_INT_STATUS_SUCCESS (cairo_int_status_t)CAIRO_STATUS_SUCCESS
56 
57 // Forward declarations
58 cairo_int_status_t
59 _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
60 				       DWRITE_MATRIX *transform,
61 				       DWRITE_GLYPH_RUN *run,
62 				       COLORREF color,
63 				       const RECT &area);
64 
65 cairo_int_status_t
66 _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
67 				       DWRITE_MATRIX *transform,
68 				       DWRITE_GLYPH_RUN *run,
69 				       COLORREF color,
70 				       cairo_dwrite_scaled_font_t *scaled_font,
71 				       const RECT &area);
72 
73 class D2DFactory
74 {
75 public:
Instance()76     static ID2D1Factory *Instance()
77     {
78 	if (!mFactoryInstance) {
79 	    D2D1CreateFactoryFunc createD2DFactory = (D2D1CreateFactoryFunc)
80 		GetProcAddress(LoadLibraryW(L"d2d1.dll"), "D2D1CreateFactory");
81 	    if (createD2DFactory) {
82 		D2D1_FACTORY_OPTIONS options;
83 		options.debugLevel = D2D1_DEBUG_LEVEL_NONE;
84 		createD2DFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
85 				 __uuidof(ID2D1Factory),
86 				 &options,
87 				 (void**)&mFactoryInstance);
88 	    }
89 	}
90 	return mFactoryInstance;
91     }
92 
RenderTarget()93     static ID2D1DCRenderTarget *RenderTarget()
94     {
95 	if (!mRenderTarget) {
96 	    if (!Instance()) {
97 		return NULL;
98 	    }
99 	    // Create a DC render target.
100 	    D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
101 		D2D1_RENDER_TARGET_TYPE_DEFAULT,
102 		D2D1::PixelFormat(
103 		    DXGI_FORMAT_B8G8R8A8_UNORM,
104 		    D2D1_ALPHA_MODE_PREMULTIPLIED),
105 		0,
106 		0,
107 		D2D1_RENDER_TARGET_USAGE_NONE,
108 		D2D1_FEATURE_LEVEL_DEFAULT
109 		);
110 
111 	    Instance()->CreateDCRenderTarget(&props, &mRenderTarget);
112 	}
113 	return mRenderTarget;
114     }
115 
116 private:
117     static ID2D1Factory *mFactoryInstance;
118     static ID2D1DCRenderTarget *mRenderTarget;
119 };
120 
121 IDWriteFactory *DWriteFactory::mFactoryInstance = NULL;
122 IDWriteFontCollection *DWriteFactory::mSystemCollection = NULL;
123 IDWriteRenderingParams *DWriteFactory::mDefaultRenderingParams = NULL;
124 IDWriteRenderingParams *DWriteFactory::mCustomClearTypeRenderingParams = NULL;
125 IDWriteRenderingParams *DWriteFactory::mForceGDIClassicRenderingParams = NULL;
126 FLOAT DWriteFactory::mGamma = -1.0;
127 FLOAT DWriteFactory::mEnhancedContrast = -1.0;
128 FLOAT DWriteFactory::mClearTypeLevel = -1.0;
129 int DWriteFactory::mPixelGeometry = -1;
130 int DWriteFactory::mRenderingMode = -1;
131 
132 ID2D1Factory *D2DFactory::mFactoryInstance = NULL;
133 ID2D1DCRenderTarget *D2DFactory::mRenderTarget = NULL;
134 
135 /* Functions cairo_font_face_backend_t */
136 static cairo_status_t
137 _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
138 					cairo_font_face_t      **font_face);
139 static void
140 _cairo_dwrite_font_face_destroy (void *font_face);
141 
142 static cairo_status_t
143 _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
144 					    const cairo_matrix_t	*font_matrix,
145 					    const cairo_matrix_t	*ctm,
146 					    const cairo_font_options_t *options,
147 					    cairo_scaled_font_t **font);
148 
149 const cairo_font_face_backend_t _cairo_dwrite_font_face_backend = {
150     CAIRO_FONT_TYPE_DWRITE,
151     _cairo_dwrite_font_face_create_for_toy,
152     _cairo_dwrite_font_face_destroy,
153     _cairo_dwrite_font_face_scaled_font_create
154 };
155 
156 /* Functions cairo_scaled_font_backend_t */
157 
158 void _cairo_dwrite_scaled_font_fini(void *scaled_font);
159 
160 static cairo_warn cairo_int_status_t
161 _cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
162 				cairo_scaled_glyph_t	     *scaled_glyph,
163 				cairo_scaled_glyph_info_t    info);
164 
165 cairo_warn cairo_int_status_t
166 _cairo_dwrite_scaled_show_glyphs(void			*scaled_font,
167 				 cairo_operator_t	 op,
168 				 const cairo_pattern_t	*pattern,
169 				 cairo_surface_t	*surface,
170 				 int			 source_x,
171 				 int			 source_y,
172 				 int			 dest_x,
173 				 int			 dest_y,
174 				 unsigned int		 width,
175 				 unsigned int		 height,
176 				 cairo_glyph_t		*glyphs,
177 				 int			 num_glyphs,
178 				 cairo_region_t		*clip_region,
179 				 int			*remaining_glyphs);
180 
181 cairo_int_status_t
182 _cairo_dwrite_load_truetype_table(void		       *scaled_font,
183 				  unsigned long         tag,
184 				  long                  offset,
185 				  unsigned char        *buffer,
186 				  unsigned long        *length);
187 
188 unsigned long
189 _cairo_dwrite_ucs4_to_index(void			     *scaled_font,
190 			    uint32_t			ucs4);
191 
192 const cairo_scaled_font_backend_t _cairo_dwrite_scaled_font_backend = {
193     CAIRO_FONT_TYPE_DWRITE,
194     _cairo_dwrite_scaled_font_fini,
195     _cairo_dwrite_scaled_glyph_init,
196     NULL,
197     _cairo_dwrite_ucs4_to_index,
198     _cairo_dwrite_scaled_show_glyphs,
199     _cairo_dwrite_load_truetype_table,
200     NULL,
201 };
202 
203 /* Helper conversion functions */
204 
205 /**
206  * Get a D2D matrix from a cairo matrix. Note that D2D uses row vectors where cairo
207  * uses column vectors. Hence the transposition.
208  *
209  * \param Cairo matrix
210  * \return D2D matrix
211  */
212 static D2D1::Matrix3x2F
_cairo_d2d_matrix_from_matrix(const cairo_matrix_t * matrix)213 _cairo_d2d_matrix_from_matrix(const cairo_matrix_t *matrix)
214 {
215     return D2D1::Matrix3x2F((FLOAT)matrix->xx,
216 			    (FLOAT)matrix->yx,
217 			    (FLOAT)matrix->xy,
218 			    (FLOAT)matrix->yy,
219 			    (FLOAT)matrix->x0,
220 			    (FLOAT)matrix->y0);
221 }
222 
223 
224 /**
225  * Get a DirectWrite matrix from a cairo matrix. Note that DirectWrite uses row
226  * vectors where cairo uses column vectors. Hence the transposition.
227  *
228  * \param Cairo matrix
229  * \return DirectWrite matrix
230  */
231 DWRITE_MATRIX
_cairo_dwrite_matrix_from_matrix(const cairo_matrix_t * matrix)232 _cairo_dwrite_matrix_from_matrix(const cairo_matrix_t *matrix)
233 {
234     DWRITE_MATRIX dwmat;
235     dwmat.m11 = (FLOAT)matrix->xx;
236     dwmat.m12 = (FLOAT)matrix->yx;
237     dwmat.m21 = (FLOAT)matrix->xy;
238     dwmat.m22 = (FLOAT)matrix->yy;
239     dwmat.dx = (FLOAT)matrix->x0;
240     dwmat.dy = (FLOAT)matrix->y0;
241     return dwmat;
242 }
243 
244 /* Helper functions for cairo_dwrite_scaled_glyph_init */
245 cairo_int_status_t
246 _cairo_dwrite_scaled_font_init_glyph_metrics
247     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
248 
249 cairo_int_status_t
250 _cairo_dwrite_scaled_font_init_glyph_surface
251     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
252 
253 cairo_int_status_t
254 _cairo_dwrite_scaled_font_init_glyph_path
255     (cairo_dwrite_scaled_font_t *scaled_font, cairo_scaled_glyph_t *scaled_glyph);
256 
257 /* implement the font backend interface */
258 
259 static cairo_status_t
_cairo_dwrite_font_face_create_for_toy(cairo_toy_font_face_t * toy_face,cairo_font_face_t ** font_face)260 _cairo_dwrite_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
261 					cairo_font_face_t      **font_face)
262 {
263     WCHAR *face_name;
264     int face_name_len;
265 
266     if (!DWriteFactory::Instance()) {
267 	return (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED;
268     }
269 
270     face_name_len = MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, NULL, 0);
271     face_name = new WCHAR[face_name_len];
272     MultiByteToWideChar(CP_UTF8, 0, toy_face->family, -1, face_name, face_name_len);
273 
274     IDWriteFontFamily *family = DWriteFactory::FindSystemFontFamily(face_name);
275     delete face_name;
276     if (!family) {
277 	*font_face = (cairo_font_face_t*)&_cairo_font_face_nil;
278 	return CAIRO_STATUS_FONT_TYPE_MISMATCH;
279     }
280 
281     DWRITE_FONT_WEIGHT weight;
282     switch (toy_face->weight) {
283     case CAIRO_FONT_WEIGHT_BOLD:
284 	weight = DWRITE_FONT_WEIGHT_BOLD;
285 	break;
286     case CAIRO_FONT_WEIGHT_NORMAL:
287     default:
288 	weight = DWRITE_FONT_WEIGHT_NORMAL;
289 	break;
290     }
291 
292     DWRITE_FONT_STYLE style;
293     switch (toy_face->slant) {
294     case CAIRO_FONT_SLANT_ITALIC:
295 	style = DWRITE_FONT_STYLE_ITALIC;
296 	break;
297     case CAIRO_FONT_SLANT_OBLIQUE:
298 	style = DWRITE_FONT_STYLE_OBLIQUE;
299 	break;
300     case CAIRO_FONT_SLANT_NORMAL:
301     default:
302 	style = DWRITE_FONT_STYLE_NORMAL;
303 	break;
304     }
305 
306     cairo_dwrite_font_face_t *face = (cairo_dwrite_font_face_t*)malloc(sizeof(cairo_dwrite_font_face_t));
307     HRESULT hr = family->GetFirstMatchingFont(weight, DWRITE_FONT_STRETCH_NORMAL, style, &face->font);
308     if (SUCCEEDED(hr)) {
309 	// Cannot use C++ style new since cairo deallocates this.
310 	*font_face = (cairo_font_face_t*)face;
311 	_cairo_font_face_init (&(*(_cairo_dwrite_font_face**)font_face)->base, &_cairo_dwrite_font_face_backend);
312     } else {
313 	free(face);
314     }
315 
316     return CAIRO_STATUS_SUCCESS;
317 }
318 
319 static void
_cairo_dwrite_font_face_destroy(void * font_face)320 _cairo_dwrite_font_face_destroy (void *font_face)
321 {
322     cairo_dwrite_font_face_t *dwrite_font_face = static_cast<cairo_dwrite_font_face_t*>(font_face);
323     if (dwrite_font_face->dwriteface)
324 	dwrite_font_face->dwriteface->Release();
325     if (dwrite_font_face->font)
326 	dwrite_font_face->font->Release();
327 }
328 
329 
330 static inline unsigned short
read_short(const char * buf)331 read_short(const char *buf)
332 {
333     return be16_to_cpu(*(unsigned short*)buf);
334 }
335 
336 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)337 _cairo_dwrite_glyph_run_from_glyphs(cairo_glyph_t *glyphs,
338 				    int num_glyphs,
339 				    cairo_dwrite_scaled_font_t *scaled_font,
340 				    AutoDWriteGlyphRun *run,
341 				    cairo_bool_t *transformed)
342 {
343     run->allocate(num_glyphs);
344 
345     UINT16 *indices = const_cast<UINT16*>(run->glyphIndices);
346     FLOAT *advances = const_cast<FLOAT*>(run->glyphAdvances);
347     DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run->glyphOffsets);
348 
349     cairo_dwrite_font_face_t *dwriteff = reinterpret_cast<cairo_dwrite_font_face_t*>(scaled_font->base.font_face);
350 
351     run->bidiLevel = 0;
352     run->fontFace = dwriteff->dwriteface;
353     run->glyphCount = num_glyphs;
354     run->isSideways = FALSE;
355 
356     if (scaled_font->mat.xy == 0 && scaled_font->mat.yx == 0 &&
357 	scaled_font->mat.xx == scaled_font->base.font_matrix.xx &&
358 	scaled_font->mat.yy == scaled_font->base.font_matrix.yy) {
359 	// Fast route, don't actually use a transform but just
360 	// set the correct font size.
361 	*transformed = 0;
362 
363 	run->fontEmSize = (FLOAT)scaled_font->base.font_matrix.yy;
364 
365 	for (int i = 0; i < num_glyphs; i++) {
366 	    indices[i] = (WORD) glyphs[i].index;
367 
368 	    offsets[i].ascenderOffset = -(FLOAT)(glyphs[i].y);
369 	    offsets[i].advanceOffset = (FLOAT)(glyphs[i].x);
370 	    advances[i] = 0.0;
371 	}
372     } else {
373 	*transformed = 1;
374         // Transforming positions by the inverse matrix, then by the original
375         // matrix later may introduce small errors, especially because the
376         // D2D matrix is single-precision whereas the cairo one is double.
377         // This is a problem when glyph positions were originally at exactly
378         // half-pixel locations, which eventually round to whole pixels for
379         // GDI rendering - the errors introduced here cause them to round in
380         // unpredictable directions, instead of all rounding in a consistent
381         // way, leading to poor glyph spacing (bug 675383).
382         // To mitigate this, nudge the positions by a tiny amount to try and
383         // ensure that after the two transforms, they'll still round in a
384         // consistent direction.
385         const double EPSILON = 0.0001;
386 	for (int i = 0; i < num_glyphs; i++) {
387 	    indices[i] = (WORD) glyphs[i].index;
388 	    double x = glyphs[i].x + EPSILON;
389 	    double y = glyphs[i].y;
390 	    cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
391 	    // Since we will multiply by our ctm matrix later for rotation effects
392 	    // and such, adjust positions by the inverse matrix now. Y-axis is
393 	    // inverted! Therefor the offset is -y.
394 	    offsets[i].ascenderOffset = -(FLOAT)y;
395 	    offsets[i].advanceOffset = (FLOAT)x;
396 	    advances[i] = 0.0;
397 	}
398 	// The font matrix takes care of the scaling if we have a transform,
399 	// emSize should be 1.
400 	run->fontEmSize = 1.0f;
401     }
402 }
403 
404 #define GASP_TAG 0x70736167
405 #define GASP_DOGRAY 0x2
406 
407 static cairo_bool_t
do_grayscale(IDWriteFontFace * dwface,unsigned int ppem)408 do_grayscale(IDWriteFontFace *dwface, unsigned int ppem)
409 {
410     void *tableContext;
411     char *tableData;
412     UINT32 tableSize;
413     BOOL exists;
414     dwface->TryGetFontTable(GASP_TAG, (const void**)&tableData, &tableSize, &tableContext, &exists);
415 
416     if (exists) {
417 	if (tableSize < 4) {
418 	    dwface->ReleaseFontTable(tableContext);
419 	    return true;
420 	}
421 	struct gaspRange {
422 	    unsigned short maxPPEM; // Stored big-endian
423 	    unsigned short behavior; // Stored big-endian
424 	};
425 	unsigned short numRanges = read_short(tableData + 2);
426 	if (tableSize < (UINT)4 + numRanges * 4) {
427 	    dwface->ReleaseFontTable(tableContext);
428 	    return true;
429 	}
430 	gaspRange *ranges = (gaspRange *)(tableData + 4);
431 	for (int i = 0; i < numRanges; i++) {
432 	    if (be16_to_cpu(ranges[i].maxPPEM) > ppem) {
433 		if (!(be16_to_cpu(ranges[i].behavior) & GASP_DOGRAY)) {
434 		    dwface->ReleaseFontTable(tableContext);
435 		    return false;
436 		}
437 		break;
438 	    }
439 	}
440 	dwface->ReleaseFontTable(tableContext);
441     }
442     return true;
443 }
444 
445 static cairo_status_t
_cairo_dwrite_font_face_scaled_font_create(void * abstract_face,const cairo_matrix_t * font_matrix,const cairo_matrix_t * ctm,const cairo_font_options_t * options,cairo_scaled_font_t ** font)446 _cairo_dwrite_font_face_scaled_font_create (void			*abstract_face,
447 					    const cairo_matrix_t	*font_matrix,
448 					    const cairo_matrix_t	*ctm,
449 					    const cairo_font_options_t  *options,
450 					    cairo_scaled_font_t **font)
451 {
452     cairo_dwrite_font_face_t *font_face = static_cast<cairo_dwrite_font_face_t*>(abstract_face);
453 
454     // Must do malloc and not C++ new, since Cairo frees this.
455     cairo_dwrite_scaled_font_t *dwriteFont = (cairo_dwrite_scaled_font_t*)malloc(sizeof(cairo_dwrite_scaled_font_t));
456     *font = reinterpret_cast<cairo_scaled_font_t*>(dwriteFont);
457     _cairo_scaled_font_init(&dwriteFont->base, &font_face->base, font_matrix, ctm, options, &_cairo_dwrite_scaled_font_backend);
458 
459     cairo_font_extents_t extents;
460 
461     DWRITE_FONT_METRICS metrics;
462     font_face->dwriteface->GetMetrics(&metrics);
463 
464     extents.ascent = (FLOAT)metrics.ascent / metrics.designUnitsPerEm;
465     extents.descent = (FLOAT)metrics.descent / metrics.designUnitsPerEm;
466     extents.height = (FLOAT)(metrics.ascent + metrics.descent + metrics.lineGap) / metrics.designUnitsPerEm;
467     extents.max_x_advance = 14.0;
468     extents.max_y_advance = 0.0;
469 
470     dwriteFont->mat = dwriteFont->base.ctm;
471     cairo_matrix_multiply(&dwriteFont->mat, &dwriteFont->mat, font_matrix);
472     dwriteFont->mat_inverse = dwriteFont->mat;
473     cairo_matrix_invert (&dwriteFont->mat_inverse);
474 
475     cairo_antialias_t default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
476 
477     dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_NATURAL;
478 
479     // The following code detects the system quality at scaled_font creation time,
480     // this means that if cleartype settings are changed but the scaled_fonts
481     // are re-used, they might not adhere to the new system setting until re-
482     // creation.
483     switch (cairo_win32_get_system_text_quality()) {
484 	case CLEARTYPE_QUALITY:
485 	    default_quality = CAIRO_ANTIALIAS_SUBPIXEL;
486 	    break;
487 	case ANTIALIASED_QUALITY:
488 	    default_quality = CAIRO_ANTIALIAS_GRAY;
489 	    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
490 	    break;
491 	case DEFAULT_QUALITY:
492 	    // _get_system_quality() seems to think aliased is default!
493 	    default_quality = CAIRO_ANTIALIAS_NONE;
494 	    dwriteFont->measuring_mode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
495 	    break;
496     }
497 
498     if (default_quality == CAIRO_ANTIALIAS_GRAY) {
499 	if (!do_grayscale(font_face->dwriteface, (unsigned int)_cairo_round(font_matrix->yy))) {
500 	    default_quality = CAIRO_ANTIALIAS_NONE;
501 	}
502     }
503 
504     if (options->antialias == CAIRO_ANTIALIAS_DEFAULT) {
505 	dwriteFont->antialias_mode = default_quality;
506     } else {
507 	dwriteFont->antialias_mode = options->antialias;
508     }
509 
510     dwriteFont->manual_show_glyphs_allowed = TRUE;
511     dwriteFont->rendering_mode =
512         default_quality == CAIRO_ANTIALIAS_SUBPIXEL ?
513             cairo_d2d_surface_t::TEXT_RENDERING_NORMAL : cairo_d2d_surface_t::TEXT_RENDERING_NO_CLEARTYPE;
514 
515     return _cairo_scaled_font_set_metrics (*font, &extents);
516 }
517 
518 /* Implementation cairo_dwrite_scaled_font_backend_t */
519 void
_cairo_dwrite_scaled_font_fini(void * scaled_font)520 _cairo_dwrite_scaled_font_fini(void *scaled_font)
521 {
522 }
523 
524 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)525 _cairo_dwrite_scaled_glyph_init(void			     *scaled_font,
526 				cairo_scaled_glyph_t	     *scaled_glyph,
527 				cairo_scaled_glyph_info_t    info)
528 {
529     cairo_dwrite_scaled_font_t *scaled_dwrite_font = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
530     cairo_int_status_t status;
531 
532     if ((info & CAIRO_SCALED_GLYPH_INFO_METRICS) != 0) {
533 	status = _cairo_dwrite_scaled_font_init_glyph_metrics (scaled_dwrite_font, scaled_glyph);
534 	if (status)
535 	    return status;
536     }
537 
538     if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
539 	status = _cairo_dwrite_scaled_font_init_glyph_surface (scaled_dwrite_font, scaled_glyph);
540 	if (status)
541 	    return status;
542     }
543 
544     if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0) {
545 	status = _cairo_dwrite_scaled_font_init_glyph_path (scaled_dwrite_font, scaled_glyph);
546 	if (status)
547 	    return status;
548     }
549 
550     return CAIRO_INT_STATUS_SUCCESS;
551 }
552 
553 unsigned long
_cairo_dwrite_ucs4_to_index(void * scaled_font,uint32_t ucs4)554 _cairo_dwrite_ucs4_to_index(void			     *scaled_font,
555 			    uint32_t		      ucs4)
556 {
557     cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
558     cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
559 
560     UINT16 index;
561     face->dwriteface->GetGlyphIndicesA(&ucs4, 1, &index);
562     return index;
563 }
564 
565 cairo_warn cairo_int_status_t
_cairo_dwrite_scaled_show_glyphs(void * scaled_font,cairo_operator_t op,const cairo_pattern_t * pattern,cairo_surface_t * generic_surface,int source_x,int source_y,int dest_x,int dest_y,unsigned int width,unsigned int height,cairo_glyph_t * glyphs,int num_glyphs,cairo_region_t * clip_region,int * remaining_glyphs)566 _cairo_dwrite_scaled_show_glyphs(void			*scaled_font,
567 				 cairo_operator_t	 op,
568 				 const cairo_pattern_t	*pattern,
569 				 cairo_surface_t	*generic_surface,
570 				 int			 source_x,
571 				 int			 source_y,
572 				 int			 dest_x,
573 				 int			 dest_y,
574 				 unsigned int		 width,
575 				 unsigned int		 height,
576 				 cairo_glyph_t		*glyphs,
577 				 int			 num_glyphs,
578 				 cairo_region_t		*clip_region,
579 				 int			*remaining_glyphs)
580 {
581     cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
582     cairo_int_status_t status;
583 
584     if (width == 0 || height == 0)
585 	return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
586 
587     if (_cairo_surface_is_win32 (generic_surface) &&
588 	surface->format == CAIRO_FORMAT_RGB24 &&
589 	op == CAIRO_OPERATOR_OVER) {
590 
591 	    //XXX: we need to set the clip region here
592 
593 	status = (cairo_int_status_t)_cairo_dwrite_show_glyphs_on_surface (surface, op, pattern,
594 									  glyphs, num_glyphs,
595 									  (cairo_scaled_font_t*)scaled_font, NULL);
596 
597 	return status;
598     } else {
599 	cairo_dwrite_scaled_font_t *dwritesf =
600 	    static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
601 	BOOL transform = FALSE;
602 
603 	AutoDWriteGlyphRun run;
604 	run.allocate(num_glyphs);
605         UINT16 *indices = const_cast<UINT16*>(run.glyphIndices);
606         FLOAT *advances = const_cast<FLOAT*>(run.glyphAdvances);
607         DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets);
608 
609 	run.bidiLevel = 0;
610 	run.fontFace = ((cairo_dwrite_font_face_t*)dwritesf->base.font_face)->dwriteface;
611 	run.isSideways = FALSE;
612     	IDWriteGlyphRunAnalysis *analysis;
613 
614 	if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
615 	    dwritesf->mat.xx == dwritesf->base.font_matrix.xx &&
616 	    dwritesf->mat.yy == dwritesf->base.font_matrix.yy) {
617 
618 	    for (int i = 0; i < num_glyphs; i++) {
619 		indices[i] = (WORD) glyphs[i].index;
620 		// Since we will multiply by our ctm matrix later for rotation effects
621 		// and such, adjust positions by the inverse matrix now.
622 		offsets[i].ascenderOffset = (FLOAT)dest_y - (FLOAT)glyphs[i].y;
623 		offsets[i].advanceOffset = (FLOAT)glyphs[i].x - dest_x;
624 		advances[i] = 0.0;
625 	    }
626 	    run.fontEmSize = (FLOAT)dwritesf->base.font_matrix.yy;
627 	} else {
628 	    transform = TRUE;
629 
630 	    for (int i = 0; i < num_glyphs; i++) {
631 		indices[i] = (WORD) glyphs[i].index;
632 		double x = glyphs[i].x - dest_x;
633 		double y = glyphs[i].y - dest_y;
634 		cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
635 		// Since we will multiply by our ctm matrix later for rotation effects
636 		// and such, adjust positions by the inverse matrix now.
637 		offsets[i].ascenderOffset = -(FLOAT)y;
638 		offsets[i].advanceOffset = (FLOAT)x;
639 		advances[i] = 0.0;
640 	    }
641 	    run.fontEmSize = 1.0f;
642 	}
643 
644 	HRESULT hr;
645 	if (!transform) {
646 	    hr = DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
647 							      1.0f,
648 							      NULL,
649 							      DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
650 							      DWRITE_MEASURING_MODE_NATURAL,
651 							      0,
652 							      0,
653 							      &analysis);
654 	} else {
655 	    DWRITE_MATRIX dwmatrix = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
656 	    hr = DWriteFactory::Instance()->CreateGlyphRunAnalysis(&run,
657 							      1.0f,
658 							      &dwmatrix,
659 							      DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC,
660 							      DWRITE_MEASURING_MODE_NATURAL,
661 							      0,
662 							      0,
663 							      &analysis);
664 	}
665 
666 	if (FAILED(hr) || !analysis) {
667 	    return CAIRO_INT_STATUS_UNSUPPORTED;
668 	}
669 
670 	RECT r;
671 	r.left = 0;
672 	r.top = 0;
673 	r.right = width;
674 	r.bottom = height;
675 
676 	BYTE *surface = new BYTE[width * height * 3];
677 
678 	analysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &r, surface, width * height * 3);
679 
680 	cairo_image_surface_t *mask_surface =
681 	    (cairo_image_surface_t*)cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
682 
683 	cairo_surface_flush(&mask_surface->base);
684 
685 	for (unsigned int y = 0; y < height; y++) {
686 	    for (unsigned int x = 0; x < width; x++) {
687 		mask_surface->data[y * mask_surface->stride + x * 4] = surface[y * width * 3 + x * 3 + 1];
688 		mask_surface->data[y * mask_surface->stride + x * 4 + 1] = surface[y * width * 3 + x * 3 + 1];
689 		mask_surface->data[y * mask_surface->stride + x * 4 + 2] = surface[y * width * 3 + x * 3 + 1];
690 		mask_surface->data[y * mask_surface->stride + x * 4 + 3] = surface[y * width * 3 + x * 3 + 1];
691 	    }
692 	}
693 	cairo_surface_mark_dirty(&mask_surface->base);
694 
695 	pixman_image_set_component_alpha(mask_surface->pixman_image, 1);
696 
697 	cairo_surface_pattern_t mask;
698 	_cairo_pattern_init_for_surface (&mask, &mask_surface->base);
699 
700 	status = (cairo_int_status_t)_cairo_surface_composite (op, pattern,
701 							       &mask.base,
702 							       generic_surface,
703 							       source_x, source_y,
704 							       0, 0,
705 							       dest_x, dest_y,
706 							       width, height,
707 							       clip_region);
708 
709 	_cairo_pattern_fini (&mask.base);
710 
711 	analysis->Release();
712 	delete [] surface;
713 
714 	cairo_surface_destroy (&mask_surface->base);
715 	*remaining_glyphs = 0;
716 
717 	return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
718     }
719 }
720 
721 /* cairo_dwrite_scaled_glyph_init helper function bodies */
722 cairo_int_status_t
_cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t * scaled_font,cairo_scaled_glyph_t * scaled_glyph)723 _cairo_dwrite_scaled_font_init_glyph_metrics(cairo_dwrite_scaled_font_t *scaled_font,
724 					     cairo_scaled_glyph_t *scaled_glyph)
725 {
726     UINT16 charIndex = (UINT16)_cairo_scaled_glyph_index (scaled_glyph);
727     cairo_dwrite_font_face_t *font_face = (cairo_dwrite_font_face_t*)scaled_font->base.font_face;
728     cairo_text_extents_t extents;
729 
730     DWRITE_GLYPH_METRICS metrics;
731     DWRITE_FONT_METRICS fontMetrics;
732     font_face->dwriteface->GetMetrics(&fontMetrics);
733     HRESULT hr = font_face->dwriteface->GetDesignGlyphMetrics(&charIndex, 1, &metrics);
734     if (FAILED(hr)) {
735 	return CAIRO_INT_STATUS_UNSUPPORTED;
736     }
737 
738     // TODO: Treat swap_xy.
739     extents.width = (FLOAT)(metrics.advanceWidth - metrics.leftSideBearing - metrics.rightSideBearing) /
740 	fontMetrics.designUnitsPerEm;
741     extents.height = (FLOAT)(metrics.advanceHeight - metrics.topSideBearing - metrics.bottomSideBearing) /
742 	fontMetrics.designUnitsPerEm;
743     extents.x_advance = (FLOAT)metrics.advanceWidth / fontMetrics.designUnitsPerEm;
744     extents.x_bearing = (FLOAT)metrics.leftSideBearing / fontMetrics.designUnitsPerEm;
745     extents.y_advance = 0.0;
746     extents.y_bearing = (FLOAT)(metrics.topSideBearing - metrics.verticalOriginY) /
747 	fontMetrics.designUnitsPerEm;
748 
749     // We pad the extents here because GetDesignGlyphMetrics returns "ideal" metrics
750     // for the glyph outline, without accounting for hinting/gridfitting/antialiasing,
751     // and therefore it does not always cover all pixels that will actually be touched.
752     if (scaled_font->base.options.antialias != CAIRO_ANTIALIAS_NONE &&
753 	extents.width > 0 && extents.height > 0) {
754 	extents.width += scaled_font->mat_inverse.xx * 2;
755 	extents.x_bearing -= scaled_font->mat_inverse.xx;
756     }
757 
758     _cairo_scaled_glyph_set_metrics (scaled_glyph,
759 				     &scaled_font->base,
760 				     &extents);
761     return CAIRO_INT_STATUS_SUCCESS;
762 }
763 
764 /**
765  * Stack-based helper implementing IDWriteGeometrySink.
766  * Used to determine the path of the glyphs.
767  */
768 
769 class GeometryRecorder : public IDWriteGeometrySink
770 {
771 public:
GeometryRecorder(cairo_path_fixed_t * aCairoPath)772     GeometryRecorder(cairo_path_fixed_t *aCairoPath)
773 	: mCairoPath(aCairoPath) {}
774 
775     // IUnknown interface
IFACEMETHOD(QueryInterface)776     IFACEMETHOD(QueryInterface)(IID const& iid, OUT void** ppObject)
777     {
778 	if (iid != __uuidof(IDWriteGeometrySink))
779 	    return E_NOINTERFACE;
780 
781 	*ppObject = static_cast<IDWriteGeometrySink*>(this);
782 
783 	return S_OK;
784     }
785 
IFACEMETHOD_(ULONG,AddRef)786     IFACEMETHOD_(ULONG, AddRef)()
787     {
788 	return 1;
789     }
790 
IFACEMETHOD_(ULONG,Release)791     IFACEMETHOD_(ULONG, Release)()
792     {
793 	return 1;
794     }
795 
SetFillMode(D2D1_FILL_MODE fillMode)796     IFACEMETHODIMP_(void) SetFillMode(D2D1_FILL_MODE fillMode)
797     {
798 	return;
799     }
800 
Close()801     STDMETHODIMP Close()
802     {
803 	return S_OK;
804     }
805 
SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags)806     IFACEMETHODIMP_(void) SetSegmentFlags(D2D1_PATH_SEGMENT vertexFlags)
807     {
808 	return;
809     }
810 
GetFixedX(const D2D1_POINT_2F & point)811     cairo_fixed_t GetFixedX(const D2D1_POINT_2F &point)
812     {
813 	unsigned int control_word;
814 	_controlfp_s(&control_word, _CW_DEFAULT, MCW_PC);
815 	return _cairo_fixed_from_double(point.x);
816     }
817 
GetFixedY(const D2D1_POINT_2F & point)818     cairo_fixed_t GetFixedY(const D2D1_POINT_2F &point)
819     {
820 	unsigned int control_word;
821 	_controlfp_s(&control_word, _CW_DEFAULT, MCW_PC);
822 	return _cairo_fixed_from_double(point.y);
823     }
824 
BeginFigure(D2D1_POINT_2F startPoint,D2D1_FIGURE_BEGIN figureBegin)825     IFACEMETHODIMP_(void) BeginFigure(
826 	D2D1_POINT_2F startPoint,
827 	D2D1_FIGURE_BEGIN figureBegin)
828     {
829 	mStartPoint = startPoint;
830 	cairo_status_t status = _cairo_path_fixed_move_to(mCairoPath,
831 							  GetFixedX(startPoint),
832 							  GetFixedY(startPoint));
833     }
834 
EndFigure(D2D1_FIGURE_END figureEnd)835     IFACEMETHODIMP_(void) EndFigure(
836 	D2D1_FIGURE_END figureEnd)
837     {
838 	if (figureEnd == D2D1_FIGURE_END_CLOSED) {
839 	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
840 							      GetFixedX(mStartPoint),
841 							      GetFixedY(mStartPoint));
842 	}
843     }
844 
AddBeziers(const D2D1_BEZIER_SEGMENT * beziers,UINT beziersCount)845     IFACEMETHODIMP_(void) AddBeziers(
846 	const D2D1_BEZIER_SEGMENT *beziers,
847 	UINT beziersCount)
848     {
849 	for (unsigned int i = 0; i < beziersCount; i++) {
850 	    cairo_status_t status = _cairo_path_fixed_curve_to(mCairoPath,
851 							       GetFixedX(beziers[i].point1),
852 							       GetFixedY(beziers[i].point1),
853 							       GetFixedX(beziers[i].point2),
854 							       GetFixedY(beziers[i].point2),
855 							       GetFixedX(beziers[i].point3),
856 							       GetFixedY(beziers[i].point3));
857 	}
858     }
859 
AddLines(const D2D1_POINT_2F * points,UINT pointsCount)860     IFACEMETHODIMP_(void) AddLines(
861 	const D2D1_POINT_2F *points,
862 	UINT pointsCount)
863     {
864 	for (unsigned int i = 0; i < pointsCount; i++) {
865 	    cairo_status_t status = _cairo_path_fixed_line_to(mCairoPath,
866 		GetFixedX(points[i]),
867 		GetFixedY(points[i]));
868 	}
869     }
870 
871 private:
872     cairo_path_fixed_t *mCairoPath;
873     D2D1_POINT_2F mStartPoint;
874 };
875 
876 cairo_int_status_t
_cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t * scaled_font,cairo_scaled_glyph_t * scaled_glyph)877 _cairo_dwrite_scaled_font_init_glyph_path(cairo_dwrite_scaled_font_t *scaled_font,
878 					  cairo_scaled_glyph_t *scaled_glyph)
879 {
880     cairo_path_fixed_t *path;
881     path = _cairo_path_fixed_create();
882     GeometryRecorder recorder(path);
883 
884     DWRITE_GLYPH_OFFSET offset;
885     offset.advanceOffset = 0;
886     offset.ascenderOffset = 0;
887     UINT16 glyphId = (UINT16)_cairo_scaled_glyph_index(scaled_glyph);
888     FLOAT advance = 0.0;
889     cairo_dwrite_font_face_t *dwriteff = (cairo_dwrite_font_face_t*)scaled_font->base.font_face;
890     dwriteff->dwriteface->GetGlyphRunOutline((FLOAT)scaled_font->base.font_matrix.yy,
891 					     &glyphId,
892 					     &advance,
893 					     &offset,
894 					     1,
895 					     FALSE,
896 					     FALSE,
897 					     &recorder);
898     _cairo_path_fixed_close_path(path);
899 
900     /* Now apply our transformation to the drawn path. */
901     _cairo_path_fixed_transform(path, &scaled_font->base.ctm);
902 
903     _cairo_scaled_glyph_set_path (scaled_glyph,
904 				  &scaled_font->base,
905 				  path);
906     return CAIRO_INT_STATUS_SUCCESS;
907 }
908 
909 /* Helper function also stolen from cairo-win32-font.c */
910 
911 /* Compute an alpha-mask from a monochrome RGB24 image
912  */
913 static cairo_surface_t *
_compute_a8_mask(cairo_win32_surface_t * mask_surface)914 _compute_a8_mask (cairo_win32_surface_t *mask_surface)
915 {
916     cairo_image_surface_t *image24 = (cairo_image_surface_t *)mask_surface->image;
917     cairo_image_surface_t *image8;
918     int i, j;
919 
920     if (image24->base.status)
921 	return cairo_surface_reference (&image24->base);
922 
923     image8 = (cairo_image_surface_t *)cairo_image_surface_create (CAIRO_FORMAT_A8,
924 								  image24->width, image24->height);
925     if (image8->base.status)
926 	return &image8->base;
927 
928     for (i = 0; i < image24->height; i++) {
929 	uint32_t *p = (uint32_t *) (image24->data + i * image24->stride);
930 	unsigned char *q = (unsigned char *) (image8->data + i * image8->stride);
931 
932 	for (j = 0; j < image24->width; j++) {
933 	    *q = 255 - ((*p & 0x0000ff00) >> 8);
934 	    p++;
935 	    q++;
936 	}
937     }
938 
939     return &image8->base;
940 }
941 
942 cairo_int_status_t
_cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t * scaled_font,cairo_scaled_glyph_t * scaled_glyph)943 _cairo_dwrite_scaled_font_init_glyph_surface(cairo_dwrite_scaled_font_t *scaled_font,
944 					     cairo_scaled_glyph_t	*scaled_glyph)
945 {
946     cairo_int_status_t status;
947     cairo_glyph_t glyph;
948     cairo_win32_surface_t *surface;
949     cairo_t *cr;
950     cairo_surface_t *image;
951     int width, height;
952     double x1, y1, x2, y2;
953 
954     x1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
955     y1 = _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
956     x2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x);
957     y2 = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y);
958     width = (int)(x2 - x1);
959     height = (int)(y2 - y1);
960 
961     glyph.index = _cairo_scaled_glyph_index (scaled_glyph);
962     glyph.x = -x1;
963     glyph.y = -y1;
964 
965     DWRITE_GLYPH_RUN run;
966     FLOAT advance = 0;
967     UINT16 index = (UINT16)glyph.index;
968     DWRITE_GLYPH_OFFSET offset;
969     double x = glyph.x;
970     double y = glyph.y;
971     RECT area;
972     DWRITE_MATRIX matrix;
973 
974     surface = (cairo_win32_surface_t *)
975 	cairo_win32_surface_create_with_dib (CAIRO_FORMAT_RGB24, width, height);
976 
977     cr = cairo_create (&surface->base);
978     cairo_set_source_rgb (cr, 1, 1, 1);
979     cairo_paint (cr);
980     status = (cairo_int_status_t)cairo_status (cr);
981     cairo_destroy(cr);
982     if (status)
983 	goto FAIL;
984 
985     /**
986      * We transform by the inverse transformation here. This will put our glyph
987      * locations in the space in which we draw. Which is later transformed by
988      * the transformation matrix that we use. This will transform the
989      * glyph positions back to where they were before when drawing, but the
990      * glyph shapes will be transformed by the transformation matrix.
991      */
992     cairo_matrix_transform_point(&scaled_font->mat_inverse, &x, &y);
993     offset.advanceOffset = (FLOAT)x;
994     /** Y-axis is inverted */
995     offset.ascenderOffset = -(FLOAT)y;
996 
997     area.top = 0;
998     area.bottom = height;
999     area.left = 0;
1000     area.right = width;
1001 
1002     run.glyphCount = 1;
1003     run.glyphAdvances = &advance;
1004     run.fontFace = ((cairo_dwrite_font_face_t*)scaled_font->base.font_face)->dwriteface;
1005     run.fontEmSize = 1.0f;
1006     run.bidiLevel = 0;
1007     run.glyphIndices = &index;
1008     run.isSideways = FALSE;
1009     run.glyphOffsets = &offset;
1010 
1011     matrix = _cairo_dwrite_matrix_from_matrix(&scaled_font->mat);
1012 
1013     status = _dwrite_draw_glyphs_to_gdi_surface_gdi (surface, &matrix, &run,
1014             RGB(0,0,0), scaled_font, area);
1015     if (status)
1016 	goto FAIL;
1017 
1018     GdiFlush();
1019 
1020     image = _compute_a8_mask (surface);
1021     status = (cairo_int_status_t)image->status;
1022     if (status)
1023 	goto FAIL;
1024 
1025     cairo_surface_set_device_offset (image, -x1, -y1);
1026     _cairo_scaled_glyph_set_surface (scaled_glyph,
1027 				     &scaled_font->base,
1028 				     (cairo_image_surface_t *) image);
1029 
1030   FAIL:
1031     cairo_surface_destroy (&surface->base);
1032 
1033     return status;
1034 }
1035 
1036 cairo_int_status_t
_cairo_dwrite_load_truetype_table(void * scaled_font,unsigned long tag,long offset,unsigned char * buffer,unsigned long * length)1037 _cairo_dwrite_load_truetype_table(void                 *scaled_font,
1038 				  unsigned long         tag,
1039 				  long                  offset,
1040 				  unsigned char        *buffer,
1041 				  unsigned long        *length)
1042 {
1043     cairo_dwrite_scaled_font_t *dwritesf = static_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
1044     cairo_dwrite_font_face_t *face = reinterpret_cast<cairo_dwrite_font_face_t*>(dwritesf->base.font_face);
1045 
1046     const void *data;
1047     UINT32 size;
1048     void *tableContext;
1049     BOOL exists;
1050     face->dwriteface->TryGetFontTable(be32_to_cpu (tag),
1051 				      &data,
1052 				      &size,
1053 				      &tableContext,
1054 				      &exists);
1055 
1056     if (!exists) {
1057 	return CAIRO_INT_STATUS_UNSUPPORTED;
1058     }
1059 
1060     if (buffer && *length && (UINT32)offset < size) {
1061         size = MIN(size - (UINT32)offset, *length);
1062         memcpy(buffer, (const char*)data + offset, size);
1063     }
1064     *length = size;
1065 
1066     if (tableContext) {
1067 	face->dwriteface->ReleaseFontTable(tableContext);
1068     }
1069     return (cairo_int_status_t)CAIRO_STATUS_SUCCESS;
1070 }
1071 
1072 // WIN32 Helper Functions
1073 cairo_font_face_t*
cairo_dwrite_font_face_create_for_dwrite_fontface(void * dwrite_font,void * dwrite_font_face)1074 cairo_dwrite_font_face_create_for_dwrite_fontface(void* dwrite_font, void* dwrite_font_face)
1075 {
1076     IDWriteFont *dwritefont = static_cast<IDWriteFont*>(dwrite_font);
1077     IDWriteFontFace *dwriteface = static_cast<IDWriteFontFace*>(dwrite_font_face);
1078     cairo_dwrite_font_face_t *face = new cairo_dwrite_font_face_t;
1079     cairo_font_face_t *font_face;
1080 
1081     dwriteface->AddRef();
1082 
1083     face->dwriteface = dwriteface;
1084     face->font = NULL;
1085 
1086     font_face = (cairo_font_face_t*)face;
1087 
1088     _cairo_font_face_init (&((cairo_dwrite_font_face_t*)font_face)->base, &_cairo_dwrite_font_face_backend);
1089 
1090     return font_face;
1091 }
1092 
1093 void
cairo_dwrite_scaled_font_allow_manual_show_glyphs(cairo_scaled_font_t * dwrite_scaled_font,cairo_bool_t allowed)1094 cairo_dwrite_scaled_font_allow_manual_show_glyphs(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t allowed)
1095 {
1096     cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
1097     font->manual_show_glyphs_allowed = allowed;
1098 }
1099 
1100 void
cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t * dwrite_scaled_font,cairo_bool_t force)1101 cairo_dwrite_scaled_font_set_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font, cairo_bool_t force)
1102 {
1103     cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
1104     if (force && font->rendering_mode == cairo_d2d_surface_t::TEXT_RENDERING_NORMAL) {
1105         font->rendering_mode = cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC;
1106     } else if (!force && font->rendering_mode == cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC) {
1107         font->rendering_mode = cairo_d2d_surface_t::TEXT_RENDERING_NORMAL;
1108     }
1109 }
1110 
1111 cairo_bool_t
cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t * dwrite_scaled_font)1112 cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scaled_font)
1113 {
1114     cairo_dwrite_scaled_font_t *font = reinterpret_cast<cairo_dwrite_scaled_font_t*>(dwrite_scaled_font);
1115     return font->rendering_mode == cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC;
1116 }
1117 
1118 void
cairo_dwrite_set_cleartype_params(FLOAT gamma,FLOAT contrast,FLOAT level,int geometry,int mode)1119 cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level,
1120 				  int geometry, int mode)
1121 {
1122     DWriteFactory::SetRenderingParams(gamma, contrast, level, geometry, mode);
1123 }
1124 
1125 int
cairo_dwrite_get_cleartype_rendering_mode()1126 cairo_dwrite_get_cleartype_rendering_mode()
1127 {
1128     return DWriteFactory::GetClearTypeRenderingMode();
1129 }
1130 
1131 cairo_int_status_t
_dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t * surface,DWRITE_MATRIX * transform,DWRITE_GLYPH_RUN * run,COLORREF color,cairo_dwrite_scaled_font_t * scaled_font,const RECT & area)1132 _dwrite_draw_glyphs_to_gdi_surface_gdi(cairo_win32_surface_t *surface,
1133 				       DWRITE_MATRIX *transform,
1134 				       DWRITE_GLYPH_RUN *run,
1135 				       COLORREF color,
1136 				       cairo_dwrite_scaled_font_t *scaled_font,
1137 				       const RECT &area)
1138 {
1139     IDWriteGdiInterop *gdiInterop;
1140     DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
1141     IDWriteBitmapRenderTarget *rt;
1142     HRESULT rv;
1143 
1144     cairo_d2d_surface_t::TextRenderingState renderingState =
1145       scaled_font->rendering_mode;
1146 
1147     rv = gdiInterop->CreateBitmapRenderTarget(surface->dc,
1148 					      area.right - area.left,
1149 					      area.bottom - area.top,
1150 					      &rt);
1151 
1152     if (FAILED(rv)) {
1153 	if (rv == E_OUTOFMEMORY) {
1154 	    return (cairo_int_status_t)CAIRO_STATUS_NO_MEMORY;
1155 	} else {
1156 	    return CAIRO_INT_STATUS_UNSUPPORTED;
1157 	}
1158     }
1159 
1160     if ((renderingState == cairo_d2d_surface_t::TEXT_RENDERING_NORMAL ||
1161          renderingState == cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC) &&
1162         !surface->base.permit_subpixel_antialiasing) {
1163       renderingState = cairo_d2d_surface_t::TEXT_RENDERING_NO_CLEARTYPE;
1164       IDWriteBitmapRenderTarget1* rt1;
1165       rv = rt->QueryInterface(&rt1);
1166 
1167       if (SUCCEEDED(rv) && rt1) {
1168         rt1->SetTextAntialiasMode(DWRITE_TEXT_ANTIALIAS_MODE_GRAYSCALE);
1169         rt1->Release();
1170       }
1171     }
1172 
1173     IDWriteRenderingParams *params =
1174         DWriteFactory::RenderingParams(renderingState);
1175 
1176     /**
1177      * We set the number of pixels per DIP to 1.0. This is because we always want
1178      * to draw in device pixels, and not device independent pixels. On high DPI
1179      * systems this value will be higher than 1.0 and automatically upscale
1180      * fonts, we don't want this since we do our own upscaling for various reasons.
1181      */
1182     rt->SetPixelsPerDip(1.0);
1183 
1184     if (transform) {
1185 	rt->SetCurrentTransform(transform);
1186     }
1187     BitBlt(rt->GetMemoryDC(),
1188 	   0, 0,
1189 	   area.right - area.left, area.bottom - area.top,
1190 	   surface->dc,
1191 	   area.left, area.top,
1192 	   SRCCOPY | NOMIRRORBITMAP);
1193     DWRITE_MEASURING_MODE measureMode;
1194     switch (renderingState) {
1195     case cairo_d2d_surface_t::TEXT_RENDERING_GDI_CLASSIC:
1196     case cairo_d2d_surface_t::TEXT_RENDERING_NO_CLEARTYPE:
1197         measureMode = DWRITE_MEASURING_MODE_GDI_CLASSIC;
1198         break;
1199     default:
1200         measureMode = DWRITE_MEASURING_MODE_NATURAL;
1201         break;
1202     }
1203     HRESULT hr = rt->DrawGlyphRun(0, 0, measureMode, run, params, color);
1204     BitBlt(surface->dc,
1205 	   area.left, area.top,
1206 	   area.right - area.left, area.bottom - area.top,
1207 	   rt->GetMemoryDC(),
1208 	   0, 0,
1209 	   SRCCOPY | NOMIRRORBITMAP);
1210     params->Release();
1211     rt->Release();
1212     gdiInterop->Release();
1213     return CAIRO_INT_STATUS_SUCCESS;
1214 }
1215 
1216 cairo_int_status_t
_dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t * surface,DWRITE_MATRIX * transform,DWRITE_GLYPH_RUN * run,COLORREF color,const RECT & area)1217 _dwrite_draw_glyphs_to_gdi_surface_d2d(cairo_win32_surface_t *surface,
1218 				       DWRITE_MATRIX *transform,
1219 				       DWRITE_GLYPH_RUN *run,
1220 				       COLORREF color,
1221 				       const RECT &area)
1222 {
1223     HRESULT rv;
1224 
1225     ID2D1DCRenderTarget *rt = D2DFactory::RenderTarget();
1226 
1227     // XXX don't we need to set RenderingParams on this RenderTarget?
1228 
1229     rv = rt->BindDC(surface->dc, &area);
1230 
1231     printf("Rendering to surface: %p\n", surface->dc);
1232 
1233     if (FAILED(rv)) {
1234 	rt->Release();
1235 	return CAIRO_INT_STATUS_UNSUPPORTED;
1236     }
1237 
1238     // D2D uses 0x00RRGGBB not 0x00BBGGRR like COLORREF.
1239     color = (color & 0xFF) << 16 |
1240 	(color & 0xFF00) |
1241 	(color & 0xFF0000) >> 16;
1242     ID2D1SolidColorBrush *brush;
1243     rv = rt->CreateSolidColorBrush(D2D1::ColorF(color, 1.0), &brush);
1244 
1245     if (FAILED(rv)) {
1246 	rt->Release();
1247 	return CAIRO_INT_STATUS_UNSUPPORTED;
1248     }
1249 
1250     if (transform) {
1251 	rt->SetTransform(D2D1::Matrix3x2F(transform->m11,
1252 					  transform->m12,
1253 					  transform->m21,
1254 					  transform->m22,
1255 					  transform->dx,
1256 					  transform->dy));
1257     }
1258     rt->BeginDraw();
1259     rt->DrawGlyphRun(D2D1::Point2F(0, 0), run, brush);
1260     rt->EndDraw();
1261     if (transform) {
1262 	rt->SetTransform(D2D1::Matrix3x2F::Identity());
1263     }
1264     brush->Release();
1265     if (FAILED(rv)) {
1266 	return CAIRO_INT_STATUS_UNSUPPORTED;
1267     }
1268 
1269     return CAIRO_INT_STATUS_SUCCESS;
1270 }
1271 
1272 /* Surface helper function */
1273 cairo_int_status_t
_cairo_dwrite_show_glyphs_on_surface(void * surface,cairo_operator_t op,const cairo_pattern_t * source,cairo_glyph_t * glyphs,int num_glyphs,cairo_scaled_font_t * scaled_font,cairo_clip_t * clip)1274 _cairo_dwrite_show_glyphs_on_surface(void			*surface,
1275 				    cairo_operator_t	 op,
1276 				    const cairo_pattern_t	*source,
1277 				    cairo_glyph_t		*glyphs,
1278 				    int			 num_glyphs,
1279 				    cairo_scaled_font_t	*scaled_font,
1280 				    cairo_clip_t	*clip)
1281 {
1282     // TODO: Check font & surface for types.
1283     cairo_dwrite_scaled_font_t *dwritesf = reinterpret_cast<cairo_dwrite_scaled_font_t*>(scaled_font);
1284     cairo_dwrite_font_face_t *dwriteff = reinterpret_cast<cairo_dwrite_font_face_t*>(scaled_font->font_face);
1285     cairo_win32_surface_t *dst = reinterpret_cast<cairo_win32_surface_t*>(surface);
1286     cairo_int_status_t status;
1287     /* We can only handle dwrite fonts */
1288     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE)
1289 	return CAIRO_INT_STATUS_UNSUPPORTED;
1290 
1291     /* We can only handle opaque solid color sources */
1292     if (!_cairo_pattern_is_opaque_solid(source))
1293 	return CAIRO_INT_STATUS_UNSUPPORTED;
1294 
1295     /* We can only handle operator SOURCE or OVER with the destination
1296      * having no alpha */
1297     if (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_OVER)
1298 	return CAIRO_INT_STATUS_UNSUPPORTED;
1299 
1300     /* If we have a fallback mask clip set on the dst, we have
1301      * to go through the fallback path */
1302     if (clip != NULL) {
1303 	if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) == 0) {
1304 	    cairo_region_t *clip_region;
1305 	    cairo_int_status_t status;
1306 
1307 	    status = _cairo_clip_get_region (clip, &clip_region);
1308 	    assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
1309 	    if (status)
1310 		return status;
1311 
1312 	    _cairo_win32_surface_set_clip_region (dst, clip_region);
1313 	}
1314     } else {
1315 	_cairo_win32_surface_set_clip_region (surface, NULL);
1316     }
1317 
1318     /* It is vital that dx values for dxy_buf are calculated from the delta of
1319      * _logical_ x coordinates (not user x coordinates) or else the sum of all
1320      * previous dx values may start to diverge from the current glyph's x
1321      * coordinate due to accumulated rounding error. As a result strings could
1322      * be painted shorter or longer than expected. */
1323 
1324     AutoDWriteGlyphRun run;
1325     run.allocate(num_glyphs);
1326 
1327     UINT16 *indices = const_cast<UINT16*>(run.glyphIndices);
1328     FLOAT *advances = const_cast<FLOAT*>(run.glyphAdvances);
1329     DWRITE_GLYPH_OFFSET *offsets = const_cast<DWRITE_GLYPH_OFFSET*>(run.glyphOffsets);
1330 
1331     BOOL transform = FALSE;
1332     /* Needed to calculate bounding box for efficient blitting */
1333     INT32 smallestX = INT_MAX;
1334     INT32 largestX = 0;
1335     INT32 smallestY = INT_MAX;
1336     INT32 largestY = 0;
1337     for (int i = 0; i < num_glyphs; i++) {
1338 	if (glyphs[i].x < smallestX) {
1339 	    smallestX = (INT32)glyphs[i].x;
1340 	}
1341 	if (glyphs[i].x > largestX) {
1342 	    largestX = (INT32)glyphs[i].x;
1343 	}
1344 	if (glyphs[i].y < smallestY) {
1345 	    smallestY = (INT32)glyphs[i].y;
1346 	}
1347 	if (glyphs[i].y > largestY) {
1348 	    largestY = (INT32)glyphs[i].y;
1349 	}
1350     }
1351     /**
1352      * Here we try to get a rough estimate of the area that this glyph run will
1353      * cover on the surface. Since we use GDI interop to draw we will be copying
1354      * data around the size of the area of the surface that we map. We will want
1355      * to map an area as small as possible to prevent large surfaces to be
1356      * copied around. We take the X/Y-size of the font as margin on the left/top
1357      * twice the X/Y-size of the font as margin on the right/bottom.
1358      * This should always cover the entire area where the glyphs are.
1359      */
1360     RECT fontArea;
1361     fontArea.left = (INT32)(smallestX - scaled_font->font_matrix.xx);
1362     fontArea.right = (INT32)(largestX + scaled_font->font_matrix.xx * 2);
1363     fontArea.top = (INT32)(smallestY - scaled_font->font_matrix.yy);
1364     fontArea.bottom = (INT32)(largestY + scaled_font->font_matrix.yy * 2);
1365     if (fontArea.left < 0)
1366 	fontArea.left = 0;
1367     if (fontArea.top < 0)
1368 	fontArea.top = 0;
1369     if (fontArea.bottom > dst->extents.height) {
1370 	fontArea.bottom = dst->extents.height;
1371     }
1372     if (fontArea.right > dst->extents.width) {
1373 	fontArea.right = dst->extents.width;
1374     }
1375     if (fontArea.right <= fontArea.left ||
1376 	fontArea.bottom <= fontArea.top) {
1377 	return CAIRO_INT_STATUS_SUCCESS;
1378     }
1379     if (fontArea.right > dst->extents.width) {
1380 	fontArea.right = dst->extents.width;
1381     }
1382     if (fontArea.bottom > dst->extents.height) {
1383 	fontArea.bottom = dst->extents.height;
1384     }
1385 
1386     run.bidiLevel = 0;
1387     run.fontFace = dwriteff->dwriteface;
1388     run.isSideways = FALSE;
1389     if (dwritesf->mat.xy == 0 && dwritesf->mat.yx == 0 &&
1390 	dwritesf->mat.xx == scaled_font->font_matrix.xx &&
1391 	dwritesf->mat.yy == scaled_font->font_matrix.yy) {
1392 
1393 	for (int i = 0; i < num_glyphs; i++) {
1394 	    indices[i] = (WORD) glyphs[i].index;
1395 	    // Since we will multiply by our ctm matrix later for rotation effects
1396 	    // and such, adjust positions by the inverse matrix now.
1397 	    offsets[i].ascenderOffset = (FLOAT)(fontArea.top - glyphs[i].y);
1398 	    offsets[i].advanceOffset = (FLOAT)(glyphs[i].x - fontArea.left);
1399 	    advances[i] = 0.0;
1400 	}
1401 	run.fontEmSize = (FLOAT)scaled_font->font_matrix.yy;
1402     } else {
1403 	transform = TRUE;
1404         // See comment about EPSILON in _cairo_dwrite_glyph_run_from_glyphs
1405         const double EPSILON = 0.0001;
1406 	for (int i = 0; i < num_glyphs; i++) {
1407 	    indices[i] = (WORD) glyphs[i].index;
1408 	    double x = glyphs[i].x - fontArea.left + EPSILON;
1409 	    double y = glyphs[i].y - fontArea.top;
1410 	    cairo_matrix_transform_point(&dwritesf->mat_inverse, &x, &y);
1411 	    /**
1412 	     * Since we will multiply by our ctm matrix later for rotation effects
1413 	     * and such, adjust positions by the inverse matrix now. The Y-axis
1414 	     * is inverted so the offset becomes negative.
1415 	     */
1416 	    offsets[i].ascenderOffset = -(FLOAT)y;
1417 	    offsets[i].advanceOffset = (FLOAT)x;
1418 	    advances[i] = 0.0;
1419 	}
1420 	run.fontEmSize = 1.0f;
1421     }
1422 
1423     cairo_solid_pattern_t *solid_pattern = (cairo_solid_pattern_t *)source;
1424     COLORREF color = RGB(((int)solid_pattern->color.red_short) >> 8,
1425 		((int)solid_pattern->color.green_short) >> 8,
1426 		((int)solid_pattern->color.blue_short) >> 8);
1427 
1428     DWRITE_MATRIX matrix = _cairo_dwrite_matrix_from_matrix(&dwritesf->mat);
1429 
1430     DWRITE_MATRIX *mat;
1431     if (transform) {
1432 	mat = &matrix;
1433     } else {
1434 	mat = NULL;
1435     }
1436 
1437     RECT area;
1438     area.left = dst->extents.x;
1439     area.top = dst->extents.y;
1440     area.right = area.left + dst->extents.width;
1441     area.bottom = area.top + dst->extents.height;
1442 
1443 #ifdef CAIRO_TRY_D2D_TO_GDI
1444     status = _dwrite_draw_glyphs_to_gdi_surface_d2d(dst,
1445 						    mat,
1446 						    &run,
1447 						    color,
1448 						    fontArea);
1449 
1450     if (status == (cairo_status_t)CAIRO_INT_STATUS_UNSUPPORTED) {
1451 #endif
1452 	status = _dwrite_draw_glyphs_to_gdi_surface_gdi(dst,
1453 							mat,
1454 							&run,
1455 							color,
1456 							dwritesf,
1457 							fontArea);
1458 
1459 #ifdef CAIRO_TRY_D2D_TO_GDI
1460     }
1461 #endif
1462 
1463     return status;
1464 }
1465 
1466 #define ENHANCED_CONTRAST_REGISTRY_KEY \
1467     HKEY_CURRENT_USER, "Software\\Microsoft\\Avalon.Graphics\\DISPLAY1\\EnhancedContrastLevel"
1468 
1469 void
CreateRenderingParams()1470 DWriteFactory::CreateRenderingParams()
1471 {
1472     if (!Instance()) {
1473 	return;
1474     }
1475 
1476     Instance()->CreateRenderingParams(&mDefaultRenderingParams);
1477 
1478     // For EnhancedContrast, we override the default if the user has not set it
1479     // in the registry (by using the ClearType Tuner).
1480     FLOAT contrast;
1481     if (mEnhancedContrast >= 0.0 && mEnhancedContrast <= 10.0) {
1482 	contrast = mEnhancedContrast;
1483     } else {
1484 	HKEY hKey;
1485 	if (RegOpenKeyExA(ENHANCED_CONTRAST_REGISTRY_KEY,
1486 			  0, KEY_READ, &hKey) == ERROR_SUCCESS)
1487 	{
1488 	    contrast = mDefaultRenderingParams->GetEnhancedContrast();
1489 	    RegCloseKey(hKey);
1490 	} else {
1491 	    contrast = 1.0;
1492 	}
1493     }
1494 
1495     // For parameters that have not been explicitly set via the SetRenderingParams API,
1496     // we copy values from default params (or our overridden value for contrast)
1497     FLOAT gamma =
1498         mGamma >= 1.0 && mGamma <= 2.2 ?
1499             mGamma : mDefaultRenderingParams->GetGamma();
1500     FLOAT clearTypeLevel =
1501         mClearTypeLevel >= 0.0 && mClearTypeLevel <= 1.0 ?
1502             mClearTypeLevel : mDefaultRenderingParams->GetClearTypeLevel();
1503     DWRITE_PIXEL_GEOMETRY pixelGeometry =
1504         mPixelGeometry >= DWRITE_PIXEL_GEOMETRY_FLAT && mPixelGeometry <= DWRITE_PIXEL_GEOMETRY_BGR ?
1505             (DWRITE_PIXEL_GEOMETRY)mPixelGeometry : mDefaultRenderingParams->GetPixelGeometry();
1506     DWRITE_RENDERING_MODE renderingMode =
1507         mRenderingMode >= DWRITE_RENDERING_MODE_DEFAULT && mRenderingMode <= DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC ?
1508             (DWRITE_RENDERING_MODE)mRenderingMode : mDefaultRenderingParams->GetRenderingMode();
1509     Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
1510 	pixelGeometry, renderingMode,
1511 	&mCustomClearTypeRenderingParams);
1512     Instance()->CreateCustomRenderingParams(gamma, contrast, clearTypeLevel,
1513         pixelGeometry, DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC,
1514         &mForceGDIClassicRenderingParams);
1515 }
1516 
1517 static cairo_bool_t
_name_tables_match(cairo_scaled_font_t * font1,cairo_scaled_font_t * font2)1518 _name_tables_match (cairo_scaled_font_t *font1,
1519                     cairo_scaled_font_t *font2)
1520 {
1521     unsigned long size1;
1522     unsigned long size2;
1523     cairo_int_status_t status1;
1524     cairo_int_status_t status2;
1525     unsigned char *buffer1;
1526     unsigned char *buffer2;
1527     cairo_bool_t result = false;
1528 
1529     if (!font1->backend || !font2->backend ||
1530         !font1->backend->load_truetype_table ||
1531         !font2->backend->load_truetype_table)
1532         return false;
1533 
1534     status1 = font1->backend->load_truetype_table (font1,
1535                                                    TT_TAG_name, 0, NULL, &size1);
1536     status2 = font2->backend->load_truetype_table (font2,
1537                                                    TT_TAG_name, 0, NULL, &size2);
1538     if (status1 || status2)
1539         return false;
1540     if (size1 != size2)
1541         return false;
1542 
1543     buffer1 = (unsigned char*)malloc (size1);
1544     buffer2 = (unsigned char*)malloc (size2);
1545 
1546     if (buffer1 && buffer2) {
1547         status1 = font1->backend->load_truetype_table (font1,
1548                                                        TT_TAG_name, 0, buffer1, &size1);
1549         status2 = font2->backend->load_truetype_table (font2,
1550                                                        TT_TAG_name, 0, buffer2, &size2);
1551         if (!status1 && !status2) {
1552             result = memcmp (buffer1, buffer2, size1) == 0;
1553         }
1554     }
1555 
1556     free (buffer1);
1557     free (buffer2);
1558     return result;
1559 }
1560 
1561 // Helper for _cairo_win32_printing_surface_show_glyphs to create a win32 equivalent
1562 // of a dwrite scaled_font so that we can print using ExtTextOut instead of drawing
1563 // paths or blitting glyph bitmaps.
1564 cairo_int_status_t
_cairo_dwrite_scaled_font_create_win32_scaled_font(cairo_scaled_font_t * scaled_font,cairo_scaled_font_t ** new_font)1565 _cairo_dwrite_scaled_font_create_win32_scaled_font (cairo_scaled_font_t *scaled_font,
1566                                                     cairo_scaled_font_t **new_font)
1567 {
1568     if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_DWRITE) {
1569         return CAIRO_INT_STATUS_UNSUPPORTED;
1570     }
1571 
1572     cairo_font_face_t *face = cairo_scaled_font_get_font_face (scaled_font);
1573     cairo_dwrite_font_face_t *dwface = reinterpret_cast<cairo_dwrite_font_face_t*>(face);
1574 
1575     RefPtr<IDWriteGdiInterop> gdiInterop;
1576     DWriteFactory::Instance()->GetGdiInterop(&gdiInterop);
1577     if (!gdiInterop) {
1578         return CAIRO_INT_STATUS_UNSUPPORTED;
1579     }
1580 
1581     LOGFONTW logfont;
1582     if (FAILED(gdiInterop->ConvertFontFaceToLOGFONT (dwface->dwriteface, &logfont))) {
1583 	return CAIRO_INT_STATUS_UNSUPPORTED;
1584     }
1585     // DW must have been using an outline font, so we want GDI to use the same,
1586     // even if there's also a bitmap face available
1587     logfont.lfOutPrecision = OUT_OUTLINE_PRECIS;
1588 
1589     cairo_font_face_t *win32_face = cairo_win32_font_face_create_for_logfontw (&logfont);
1590     if (!win32_face) {
1591         return CAIRO_INT_STATUS_UNSUPPORTED;
1592     }
1593 
1594     cairo_matrix_t font_matrix;
1595     cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
1596 
1597     cairo_matrix_t ctm;
1598     cairo_scaled_font_get_ctm (scaled_font, &ctm);
1599 
1600     cairo_font_options_t options;
1601     cairo_scaled_font_get_font_options (scaled_font, &options);
1602 
1603     cairo_scaled_font_t *font = cairo_scaled_font_create (win32_face,
1604 			                                  &font_matrix,
1605 			                                  &ctm,
1606 			                                  &options);
1607     cairo_font_face_destroy (win32_face);
1608 
1609     if (!font) {
1610         return CAIRO_INT_STATUS_UNSUPPORTED;
1611     }
1612 
1613     if (!_name_tables_match (font, scaled_font)) {
1614         // If the font name tables aren't equal, then GDI may have failed to
1615         // find the right font and substituted a different font.
1616         cairo_scaled_font_destroy (font);
1617         return CAIRO_INT_STATUS_UNSUPPORTED;
1618     }
1619 
1620     *new_font = font;
1621     return CAIRO_INT_STATUS_SUCCESS;
1622 }
1623