From a47f958ce1b7e1fedb58ae270ad8244a6623ece1 Mon Sep 17 00:00:00 2001 From: Yongsu Park Date: Tue, 19 May 2020 09:35:43 +0000 Subject: win32: Use GPrivate-managed display device context The document of [CreateDCA][1] says: > If lpszDriver or lpszDevice is DISPLAY, the thread that calls > CreateDC owns the HDC that is created. When this thread is > destroyed, the HDC is no longer valid. Thus, if you create the HDC > and pass it to another thread, then exit the first thread, > the second thread will not be able to use the HDC. So this change introduces GPrivate to fix potential problem. This also fixes the problem caused by accessing the global variable DC directly, which makes some early call to Pango functions fail. (e.g., failure of calling pango_win32_font_description_from_logfontw from _get_system_font_name in GTK.) [1]: https://docs.microsoft.com/windows/win32/api/wingdi/nf-wingdi-createdca --- pango/pangocairo-win32fontmap.c | 2 +- pango/pangowin32-fontmap.c | 59 +++++++++++++++++++++++++++-------------- pango/pangowin32-private.h | 4 ++- pango/pangowin32.c | 52 +++++++++++++++++++++++------------- 4 files changed, 76 insertions(+), 41 deletions(-) diff --git a/pango/pangocairo-win32fontmap.c b/pango/pangocairo-win32fontmap.c index b58d16f6..94500fd6 100644 --- a/pango/pangocairo-win32fontmap.c +++ b/pango/pangocairo-win32fontmap.c @@ -121,5 +121,5 @@ static void pango_cairo_win32_font_map_init (PangoCairoWin32FontMap *cwfontmap) { cwfontmap->serial = 1; - cwfontmap->dpi = GetDeviceCaps (pango_win32_get_dc (), LOGPIXELSY); + cwfontmap->dpi = GetDeviceCaps (_pango_win32_get_display_dc (), LOGPIXELSY); } diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c index 905fdee2..ff7a6e94 100644 --- a/pango/pangowin32-fontmap.c +++ b/pango/pangowin32-fontmap.c @@ -199,6 +199,12 @@ pango_win32_inner_enum_proc (LOGFONTW *lfp, return 1; } +struct EnumProcData +{ + HDC hdc; + PangoWin32FontMap *font_map; +}; + static int CALLBACK pango_win32_enum_proc (LOGFONTW *lfp, NEWTEXTMETRICW *metrics, @@ -206,6 +212,7 @@ pango_win32_enum_proc (LOGFONTW *lfp, LPARAM lParam) { LOGFONTW lf; + struct EnumProcData *data = (struct EnumProcData *) lParam; PING (("%S: %lu %lx", lfp->lfFaceName, fontType, metrics->ntmFlags)); @@ -213,9 +220,9 @@ pango_win32_enum_proc (LOGFONTW *lfp, { lf = *lfp; - EnumFontFamiliesExW (_pango_win32_hdc, &lf, + EnumFontFamiliesExW (data->hdc, &lf, (FONTENUMPROCW) pango_win32_inner_enum_proc, - lParam, 0); + (LPARAM) data->font_map, 0); } return 1; @@ -709,6 +716,8 @@ static void _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap) { LOGFONTW logfont; + HDC hdc = _pango_win32_get_display_dc (); + struct EnumProcData enum_proc_data; win32fontmap->families = g_hash_table_new_full ((GHashFunc) case_insensitive_str_hash, @@ -730,9 +739,13 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap) memset (&logfont, 0, sizeof (logfont)); logfont.lfCharSet = DEFAULT_CHARSET; - EnumFontFamiliesExW (_pango_win32_hdc, &logfont, + + enum_proc_data.hdc = hdc; + enum_proc_data.font_map = win32fontmap; + + EnumFontFamiliesExW (hdc, &logfont, (FONTENUMPROCW) pango_win32_enum_proc, - (LPARAM) win32fontmap, 0); + (LPARAM) &enum_proc_data, 0); g_hash_table_foreach (win32fontmap->families, synthesize_foreach, win32fontmap); @@ -744,7 +757,7 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap) create_standard_family (win32fontmap, "Fantasy"); create_standard_family (win32fontmap, "System-ui"); - win32fontmap->resolution = (PANGO_SCALE / (double) GetDeviceCaps (_pango_win32_hdc, LOGPIXELSY)) * 72.0; + win32fontmap->resolution = (PANGO_SCALE / (double) GetDeviceCaps (hdc, LOGPIXELSY)) * 72.0; } static void @@ -807,7 +820,7 @@ _pango_win32_font_map_class_init (PangoWin32FontMapClass *class) fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_WIN32; fontmap_class->get_face = pango_win32_font_map_get_face; - pango_win32_get_dc (); + _pango_win32_get_display_dc (); } /** @@ -1159,6 +1172,7 @@ get_family_nameA (const LOGFONTA *lfp) { HFONT hfont; HFONT oldhfont; + HDC hdc; struct name_header header; struct name_record record; @@ -1189,17 +1203,19 @@ get_family_nameA (const LOGFONTA *lfp) if ((hfont = CreateFontIndirect (lfp)) == NULL) goto fail0; - if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL) + hdc = _pango_win32_get_display_dc (); + + if ((oldhfont = SelectObject (hdc, hfont)) == NULL) goto fail1; - if (!_pango_win32_get_name_header (_pango_win32_hdc, &header)) + if (!_pango_win32_get_name_header (hdc, &header)) goto fail2; PING (("%d name records", header.num_records)); for (i = 0; i < header.num_records; i++) { - if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record)) + if (!_pango_win32_get_name_record (hdc, i, &record)) goto fail2; if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0) @@ -1234,11 +1250,11 @@ get_family_nameA (const LOGFONTA *lfp) else goto fail2; - if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record)) + if (!_pango_win32_get_name_record (hdc, name_ix, &record)) goto fail2; string = g_malloc (record.string_length + 1); - if (GetFontData (_pango_win32_hdc, NAME, + if (GetFontData (hdc, NAME, header.string_storage_offset + record.string_offset, string, record.string_length) != record.string_length) goto fail2; @@ -1264,14 +1280,14 @@ get_family_nameA (const LOGFONTA *lfp) PING (("%s", name)); - SelectObject (_pango_win32_hdc, oldhfont); + SelectObject (hdc, oldhfont); DeleteObject (hfont); return name; fail2: g_free (string); - SelectObject (_pango_win32_hdc, oldhfont); + SelectObject (hdc, oldhfont); fail1: DeleteObject (hfont); @@ -1343,6 +1359,7 @@ get_family_nameW (const LOGFONTW *lfp) { HFONT hfont; HFONT oldhfont; + HDC hdc; struct name_header header; struct name_record record; @@ -1373,17 +1390,19 @@ get_family_nameW (const LOGFONTW *lfp) if ((hfont = CreateFontIndirectW (lfp)) == NULL) goto fail0; - if ((oldhfont = SelectObject (_pango_win32_hdc, hfont)) == NULL) + hdc = _pango_win32_get_display_dc (); + + if ((oldhfont = SelectObject (hdc, hfont)) == NULL) goto fail1; - if (!_pango_win32_get_name_header (_pango_win32_hdc, &header)) + if (!_pango_win32_get_name_header (hdc, &header)) goto fail2; PING (("%d name records", header.num_records)); for (i = 0; i < header.num_records; i++) { - if (!_pango_win32_get_name_record (_pango_win32_hdc, i, &record)) + if (!_pango_win32_get_name_record (hdc, i, &record)) goto fail2; if ((record.name_id != 1 && record.name_id != 16) || record.string_length <= 0) @@ -1416,11 +1435,11 @@ get_family_nameW (const LOGFONTW *lfp) else goto fail2; - if (!_pango_win32_get_name_record (_pango_win32_hdc, name_ix, &record)) + if (!_pango_win32_get_name_record (hdc, name_ix, &record)) goto fail2; string = g_malloc (record.string_length + 1); - if (GetFontData (_pango_win32_hdc, NAME, + if (GetFontData (hdc, NAME, header.string_storage_offset + record.string_offset, string, record.string_length) != record.string_length) goto fail2; @@ -1446,14 +1465,14 @@ get_family_nameW (const LOGFONTW *lfp) PING (("%s", name)); - SelectObject (_pango_win32_hdc, oldhfont); + SelectObject (hdc, oldhfont); DeleteObject (hfont); return name; fail2: g_free (string); - SelectObject (_pango_win32_hdc, oldhfont); + SelectObject (hdc, oldhfont); fail1: DeleteObject (hfont); diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h index 082470e7..f5620b87 100644 --- a/pango/pangowin32-private.h +++ b/pango/pangowin32-private.h @@ -272,7 +272,9 @@ void _pango_win32_fontmap_cache_remove (PangoFontMap *fontmap, _PANGO_EXTERN HFONT _pango_win32_font_get_hfont (PangoFont *font); -extern HDC _pango_win32_hdc; +_PANGO_EXTERN +HDC _pango_win32_get_display_dc (void); + extern gboolean _pango_win32_debug; #endif /* __PANGOWIN32_PRIVATE_H__ */ diff --git a/pango/pangowin32.c b/pango/pangowin32.c index 737cfa14..8849d4af 100644 --- a/pango/pangowin32.c +++ b/pango/pangowin32.c @@ -43,7 +43,6 @@ #define MAX_FREED_FONTS 256 -HDC _pango_win32_hdc; gboolean _pango_win32_debug = FALSE; static void pango_win32_font_dispose (GObject *object); @@ -134,19 +133,21 @@ _pango_win32_font_init (PangoWin32Font *win32font) win32font->glyph_info = g_hash_table_new_full (NULL, NULL, NULL, g_free); } -/** - * pango_win32_get_dc: - * - * Obtains a handle to the Windows device context that is used by Pango. - * - * Return value: A handle to the Windows device context that is used by Pango. - **/ +static GPrivate display_dc_key = G_PRIVATE_INIT ((GDestroyNotify) DeleteDC); + HDC -pango_win32_get_dc (void) +_pango_win32_get_display_dc (void) { - if (g_once_init_enter (&_pango_win32_hdc)) + HDC hdc = g_private_get (&display_dc_key); + + if (hdc == NULL) { - HDC hdc = CreateDC ("DISPLAY", NULL, NULL, NULL); + hdc = CreateDC ("DISPLAY", NULL, NULL, NULL); + + if (G_UNLIKELY (hdc == NULL)) + g_warning ("CreateDC() failed"); + + g_private_set (&display_dc_key, hdc); /* Also do some generic pangowin32 initialisations... this function * is a suitable place for those as it is called from a couple @@ -156,10 +157,22 @@ pango_win32_get_dc (void) if (getenv ("PANGO_WIN32_DEBUG") != NULL) _pango_win32_debug = TRUE; #endif - g_once_init_leave (&_pango_win32_hdc, hdc); } - return _pango_win32_hdc; + return hdc; +} + +/** + * pango_win32_get_dc: + * + * Obtains a handle to the Windows device context that is used by Pango. + * + * Return value: A handle to the Windows device context that is used by Pango. + **/ +HDC +pango_win32_get_dc (void) +{ + return _pango_win32_get_display_dc (); } /** @@ -198,7 +211,7 @@ _pango_win32_font_class_init (PangoWin32FontClass *class) class->done_font = pango_win32_font_real_done_font; class->get_metrics_factor = pango_win32_font_real_get_metrics_factor; - pango_win32_get_dc (); + _pango_win32_get_display_dc (); } /** @@ -448,7 +461,7 @@ pango_win32_font_get_glyph_extents (PangoFont *font, if (!info) { - HDC hdc = pango_win32_get_dc (); + HDC hdc = _pango_win32_get_display_dc (); info = g_new0 (PangoWin32GlyphInfo, 1); @@ -478,7 +491,7 @@ pango_win32_font_get_glyph_extents (PangoFont *font, info->ink_rect.y = - PANGO_SCALE * gm.gmptGlyphOrigin.y; info->ink_rect.height = PANGO_SCALE * gm.gmBlackBoxY; - GetTextMetrics (_pango_win32_hdc, &tm); + GetTextMetrics (hdc, &tm); info->logical_rect.x = 0; info->logical_rect.width = PANGO_SCALE * gm.gmCellIncX; info->logical_rect.y = - PANGO_SCALE * tm.tmAscent; @@ -555,9 +568,10 @@ pango_win32_font_get_metrics (PangoFont *font, { PangoCoverage *coverage; TEXTMETRIC tm; + HDC hdc = _pango_win32_get_display_dc (); - SelectObject (_pango_win32_hdc, hfont); - GetTextMetrics (_pango_win32_hdc, &tm); + SelectObject (hdc, hfont); + GetTextMetrics (hdc, &tm); metrics->ascent = tm.tmAscent * PANGO_SCALE; metrics->descent = tm.tmDescent * PANGO_SCALE; @@ -1215,7 +1229,7 @@ hfont_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data) DWORD size; /* We have a common DC for our PangoWin32Font, so let's just use it */ - hdc = pango_win32_get_dc (); + hdc = _pango_win32_get_display_dc (); hfont = (HFONT) user_data; /* we want to restore things, just to be safe */ -- cgit v1.2.1 From 94ac19e4dc9ce6b8e93abc28087620019c6080e7 Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Wed, 15 Jan 2020 14:38:23 +0800 Subject: meson: Only use FreeType fallback only when needed Defer using the FreeType fallback until: -We need to really build FontConfig support -FreeType is not found even after checking the headers and lib's. --- meson.build | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index a0d2ecc4..fa98dabb 100644 --- a/meson.build +++ b/meson.build @@ -312,8 +312,7 @@ message('fontconfig has FcWeightFromOpenTypeDouble: ' + res) # The first version of freetype with a pkg-config file is 2.1.5 # We require both fontconfig and freetype if we are to have either. -freetype_dep = dependency('freetype2', required: false, - fallback: ['freetype2', 'freetype_dep']) +freetype_dep = dependency('freetype2', required: false) if freetype_dep.found() freetype2_pc = 'freetype2' @@ -330,6 +329,11 @@ else endif endif +if fontconfig_required and not freetype_dep.found() + freetype_dep = dependency('freetype2', required: false, + fallback: ['freetype2', 'freetype_dep']) +endif + # To build pangoft2, we need HarfBuzz, FontConfig and FreeType build_pangoft2 = harfbuzz_dep.found() and fontconfig_dep.found() and freetype_dep.found() if build_pangoft2 -- cgit v1.2.1 From bf84f87bb0342a0875a96a0e9b6548c6ff57b76f Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Wed, 15 Jan 2020 14:44:37 +0800 Subject: Visual Studio: Use -utf-8 when available This avoids the build erroring out on C4819 (Unicode handling issue in Visual Studio compilers), notably when running on Chinese, Japanese and Korean locales. --- meson.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson.build b/meson.build index fa98dabb..904027ba 100644 --- a/meson.build +++ b/meson.build @@ -57,8 +57,8 @@ common_ldflags = [] if cc.get_id() == 'msvc' # Compiler options taken from msvc_recommended_pragmas.h # in GLib, based on _Win32_Programming_ by Rector and Newcomer - test_cflags = [] - add_project_arguments([ '-FImsvc_recommended_pragmas.h' ], language: 'c') + test_cflags = ['-FImsvc_recommended_pragmas', '-utf-8'] + add_project_arguments(cc.get_supported_arguments(test_cflags), language: 'c') test_c_only_flags = [] elif cc.get_id() == 'gcc' or cc.get_id() == 'clang' test_c_only_flags = [ -- cgit v1.2.1 From fb2d89845196ac02e2db0dc9ccf40bc9338fea7e Mon Sep 17 00:00:00 2001 From: Chun-wei Fan Date: Wed, 15 Jan 2020 15:17:16 +0800 Subject: meson: Fix pkg-config file generation for HarfBuzz HarfBuzz may be found manually instead of via pkg-config, so only add it to Pango's pkg-config file if it is really found via pkg-config. --- pango/meson.build | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pango/meson.build b/pango/meson.build index 738bd36c..b2496373 100644 --- a/pango/meson.build +++ b/pango/meson.build @@ -152,11 +152,16 @@ libpango_dep = declare_dependency( sources: pango_dep_sources, ) +pango_pkg_requires = ['gobject-2.0'] +if harfbuzz_dep.type_name() == 'pkgconfig' + pango_pkg_requires += 'harfbuzz' +endif + pkgconfig.generate(libpango, name: 'Pango', description: 'Internationalized text handling', version: meson.project_version(), - requires: ['gobject-2.0', 'harfbuzz'], + requires: pango_pkg_requires, filebase: 'pango', subdirs: pango_api_name, install_dir: join_paths(pango_libdir, 'pkgconfig'), -- cgit v1.2.1 From 475e2d7cc399241441d06a36542bdcb577276ea3 Mon Sep 17 00:00:00 2001 From: Aaron Boxer Date: Thu, 28 May 2020 15:56:40 -0600 Subject: pangowin32-fontmap: load windows fallbacks and aliases in class init Currently, because of the g_once_init*, only the very first font map that is created will get the correct list of aliases. With these changes the fontmap class loads the aliases once, and this hash table is used by all fontmap objects. --- pango/pangowin32-fontmap.c | 27 ++++++++++----------------- pango/pangowin32-private.h | 2 +- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c index ff7a6e94..09de5fa0 100644 --- a/pango/pangowin32-fontmap.c +++ b/pango/pangowin32-fontmap.c @@ -611,19 +611,6 @@ read_windows_fallbacks (GHashTable *ht_aliases) #endif - -static gboolean -load_aliases (GHashTable *ht_aliases) -{ - -#ifdef HAVE_CAIRO_WIN32 - read_windows_fallbacks (ht_aliases); - read_builtin_aliases (ht_aliases); -#endif - - return TRUE; -} - static void lookup_aliases (GHashTable *aliases_ht, const char *fontname, @@ -634,9 +621,6 @@ lookup_aliases (GHashTable *aliases_ht, struct PangoAlias *alias; static gsize aliases_inited = 0; - if (g_once_init_enter (&aliases_inited)) - g_once_init_leave (&aliases_inited, load_aliases (aliases_ht)); - alias_key.alias = g_ascii_strdown (fontname, -1); alias = g_hash_table_lookup (aliases_ht, &alias_key); g_free (alias_key.alias); @@ -775,8 +759,9 @@ pango_win32_font_map_fontset_add_fonts (PangoFontMap *fontmap, int n_aliases; int j; PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (fontmap); + PangoWin32FontMapClass *class = (PangoWin32FontMapClass*)G_OBJECT_GET_CLASS(win32fontmap); - lookup_aliases (win32fontmap->aliases, family, &aliases, &n_aliases); + lookup_aliases (class->aliases, family, &aliases, &n_aliases); if (n_aliases) { for (j = 0; j < n_aliases; j++) @@ -819,6 +804,14 @@ _pango_win32_font_map_class_init (PangoWin32FontMapClass *class) fontmap_class->list_families = pango_win32_font_map_list_families; fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_WIN32; fontmap_class->get_face = pango_win32_font_map_get_face; + class->aliases = g_hash_table_new_full ((GHashFunc)alias_hash, + (GEqualFunc)alias_equal, + (GDestroyNotify)alias_free, + NULL); +#ifdef HAVE_CAIRO_WIN32 + read_windows_fallbacks (class->aliases); + read_builtin_aliases (class->aliases); +#endif _pango_win32_get_display_dc (); } diff --git a/pango/pangowin32-private.h b/pango/pangowin32-private.h index f5620b87..1c9c1c09 100644 --- a/pango/pangowin32-private.h +++ b/pango/pangowin32-private.h @@ -113,7 +113,7 @@ struct _PangoWin32FontMapClass PangoContext *context, PangoWin32Face *face, const PangoFontDescription *desc); - + GHashTable *aliases; }; struct _PangoWin32Font -- cgit v1.2.1 From a56ef2b701b115ebde57be7339a95d6745f8c1e6 Mon Sep 17 00:00:00 2001 From: Aaron Boxer Date: Fri, 5 Jun 2020 12:05:04 -0400 Subject: pangowin32-fontmap: delete no longer needed font map aliases --- pango/pangowin32-fontmap.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/pango/pangowin32-fontmap.c b/pango/pangowin32-fontmap.c index 09de5fa0..b43685c7 100644 --- a/pango/pangowin32-fontmap.c +++ b/pango/pangowin32-fontmap.c @@ -644,8 +644,9 @@ create_standard_family (PangoWin32FontMap *win32fontmap, int i; int n_aliases; char **aliases; + PangoWin32FontMapClass *class = (PangoWin32FontMapClass*) G_OBJECT_GET_CLASS (win32fontmap); - lookup_aliases (win32fontmap->aliases, standard_family_name, &aliases, &n_aliases); + lookup_aliases (class->aliases, standard_family_name, &aliases, &n_aliases); for (i = 0; i < n_aliases; i++) { PangoWin32Family *existing_family = g_hash_table_lookup (win32fontmap->families, aliases[i]); @@ -712,10 +713,6 @@ _pango_win32_font_map_init (PangoWin32FontMap *win32fontmap) win32fontmap->font_cache = pango_win32_font_cache_new (); win32fontmap->freed_fonts = g_queue_new (); - win32fontmap->aliases = g_hash_table_new_full ((GHashFunc)alias_hash, - (GEqualFunc)alias_equal, - (GDestroyNotify)alias_free, - NULL); win32fontmap->warned_fonts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, @@ -862,7 +859,6 @@ pango_win32_font_map_finalize (GObject *object) pango_win32_font_cache_free (win32fontmap->font_cache); g_hash_table_destroy (win32fontmap->warned_fonts); - g_hash_table_destroy (win32fontmap->aliases); g_hash_table_destroy (win32fontmap->fonts); g_hash_table_destroy (win32fontmap->families); -- cgit v1.2.1