📄 pangowin32-fontmap.c
字号:
/* Pango * pangowin32-fontmap.c: Win32 font handling * * Copyright (C) 2000 Red Hat Software * Copyright (C) 2000 Tor Lillqvist * Copyright (C) 2001 Alexander Larsson * Copyright (C) 2007 Novell, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */#include <config.h>#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include "pango-fontmap.h"#include "pango-impl-utils.h"#include "pangowin32-private.h"#include "modules.h"typedef struct _PangoWin32Family PangoWin32Family;typedef struct _PangoWin32SizeInfo PangoWin32SizeInfo;struct _PangoWin32Family{ PangoFontFamily parent_instance; char *family_name; GSList *font_entries; gboolean is_monospace;};struct _PangoWin32SizeInfo{ GSList *logfontws;};#if !defined(NTM_PS_OPENTYPE)# define NTM_PS_OPENTYPE 0x20000#endif#if !defined(NTM_TYPE1)# define NTM_TYPE1 0x100000#endif#define PANGO_WIN32_TYPE_FAMILY (pango_win32_family_get_type ())#define PANGO_WIN32_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_WIN32_TYPE_FAMILY, PangoWin32Family))#define PANGO_WIN32_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_WIN32_TYPE_FAMILY))#define PANGO_WIN32_TYPE_FACE (pango_win32_face_get_type ())#define PANGO_WIN32_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_WIN32_TYPE_FACE, PangoWin32Face))#define PANGO_WIN32_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_WIN32_TYPE_FACE))static GType pango_win32_face_get_type (void);static GType pango_win32_family_get_type (void);static void pango_win32_face_list_sizes (PangoFontFace *face, int **sizes, int *n_sizes);static void pango_win32_font_map_finalize (GObject *object);static PangoFont *pango_win32_font_map_load_font (PangoFontMap *fontmap, PangoContext *context, const PangoFontDescription *description);static void pango_win32_font_map_list_families (PangoFontMap *fontmap, PangoFontFamily ***families, int *n_families);static PangoFont *pango_win32_font_map_real_find_font (PangoWin32FontMap *win32fontmap, PangoContext *context, PangoWin32Face *face, const PangoFontDescription *description);static void pango_win32_fontmap_cache_clear (PangoWin32FontMap *win32fontmap);static void pango_win32_insert_font (PangoWin32FontMap *fontmap, LOGFONTW *lfp, gboolean is_synthetic);static PangoWin32FontMap *default_fontmap = NULL;G_DEFINE_TYPE (PangoWin32FontMap, _pango_win32_font_map, PANGO_TYPE_FONT_MAP)#define TOLOWER(c) \ (((c) >= 'A' && (c) <= 'Z') ? (c) - 'A' + 'a' : (c))static guintcase_insensitive_str_hash (const char *key){ const char *p = key; guint h = TOLOWER (*p); if (h) { for (p += 1; *p != '\0'; p++) h = (h << 5) - h + TOLOWER (*p); } return h;}static gbooleancase_insensitive_str_equal (const char *key1, const char *key2){ while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2)) key1++, key2++; return (!*key1 && !*key2);}static guintcase_insensitive_wcs_hash (const wchar_t *key){ const wchar_t *p = key; guint h = TOLOWER (*p); if (h) { for (p += 1; *p != '\0'; p++) h = (h << 5) - h + TOLOWER (*p); } return h;}static gbooleancase_insensitive_wcs_equal (const wchar_t *key1, const wchar_t *key2){ while (*key1 && *key2 && TOLOWER (*key1) == TOLOWER (*key2)) key1++, key2++; return (!*key1 && !*key2);}/* A hash function for LOGFONTWs that takes into consideration only * those fields that indicate a specific .ttf file is in use: * lfFaceName, lfItalic and lfWeight. Dunno how correct this is. */static guintlogfontw_nosize_hash (const LOGFONTW *lfp){ return case_insensitive_wcs_hash (lfp->lfFaceName) + (lfp->lfItalic != 0) + lfp->lfWeight;}/* Ditto comparison function */static gbooleanlogfontw_nosize_equal (const LOGFONTW *lfp1, const LOGFONTW *lfp2){ return (case_insensitive_wcs_equal (lfp1->lfFaceName, lfp2->lfFaceName) && (lfp1->lfItalic != 0) == (lfp2->lfItalic != 0) && lfp1->lfWeight == lfp2->lfWeight);}static int CALLBACKpango_win32_inner_enum_proc (LOGFONTW *lfp, TEXTMETRICW *metrics, DWORD fontType, LPARAM lParam){ PangoWin32FontMap *win32fontmap = (PangoWin32FontMap *)lParam; /* Windows generates synthetic vertical writing versions of East * Asian fonts with @ prepended to their name, ignore them. */ if (lfp->lfFaceName[0] != '@') pango_win32_insert_font (win32fontmap, lfp, FALSE); return 1;}static int CALLBACKpango_win32_enum_proc (LOGFONTW *lfp, NEWTEXTMETRICW *metrics, DWORD fontType, LPARAM lParam){ LOGFONTW lf; PING(("%S: %lu %lx", lfp->lfFaceName, fontType, metrics->ntmFlags)); if (fontType == TRUETYPE_FONTTYPE || (_pango_win32_os_version_info.dwMajorVersion >= 5 && ((metrics->ntmFlags & NTM_PS_OPENTYPE) || (metrics->ntmFlags & NTM_TYPE1)))) { lf = *lfp; EnumFontFamiliesExW (_pango_win32_hdc, &lf, (FONTENUMPROCW) pango_win32_inner_enum_proc, lParam, 0); } return 1;}typedef struct _ItalicHelper{ PangoWin32FontMap *fontmap; GSList *list;} ItalicHelper;static voidensure_italic (gpointer key, gpointer value, gpointer user_data){ ItalicHelper *helper = (ItalicHelper *)user_data; PangoWin32SizeInfo *sip = (PangoWin32SizeInfo *) value; GSList *list = sip->logfontws; while (list) { LOGFONTW *lfp = (LOGFONTW *) list->data; PING(("%S it=%d wt=%ld", lfp->lfFaceName, lfp->lfItalic, lfp->lfWeight)); if (!lfp->lfItalic) { /* we have a non italic variant, look if there is an italic */ LOGFONTW logfontw = *lfp; logfontw.lfItalic = 1; sip = (PangoWin32SizeInfo *) g_hash_table_lookup (helper->fontmap->size_infos, &logfontw); if (!sip) { /* remember the non italic variant to be added later as italic */ PING(("synthesizing italic")); helper->list = g_slist_append (helper->list, lfp); } } list = list->next; }}static void_pango_win32_font_map_init (PangoWin32FontMap *win32fontmap){ LOGFONTW logfont; ItalicHelper helper = { win32fontmap, NULL }; GSList *list; win32fontmap->families = g_hash_table_new ((GHashFunc) case_insensitive_str_hash, (GEqualFunc) case_insensitive_str_equal); win32fontmap->size_infos = g_hash_table_new ((GHashFunc) logfontw_nosize_hash, (GEqualFunc) logfontw_nosize_equal); win32fontmap->n_fonts = 0; win32fontmap->font_cache = pango_win32_font_cache_new (); win32fontmap->freed_fonts = g_queue_new (); memset (&logfont, 0, sizeof (logfont)); logfont.lfCharSet = DEFAULT_CHARSET; EnumFontFamiliesExW (_pango_win32_hdc, &logfont, (FONTENUMPROCW) pango_win32_enum_proc, (LPARAM) win32fontmap, 0); /* Create synthetic italic entries */ g_hash_table_foreach (win32fontmap->size_infos, ensure_italic, &helper); /* Can't modify while iterating */ list = helper.list; while (list) { LOGFONTW logfontw = *((LOGFONTW *)list->data); logfontw.lfItalic = 1; pango_win32_insert_font (win32fontmap, &logfontw, TRUE); list = list->next; } g_slist_free (helper.list); win32fontmap->resolution = (PANGO_SCALE / (double) GetDeviceCaps (_pango_win32_hdc, LOGPIXELSY)) * 72.0;}static void_pango_win32_font_map_class_init (PangoWin32FontMapClass *class){ GObjectClass *object_class = G_OBJECT_CLASS (class); PangoFontMapClass *fontmap_class = PANGO_FONT_MAP_CLASS (class); int i; class->find_font = pango_win32_font_map_real_find_font; object_class->finalize = pango_win32_font_map_finalize; fontmap_class->load_font = pango_win32_font_map_load_font; fontmap_class->list_families = pango_win32_font_map_list_families; fontmap_class->shape_engine_type = PANGO_RENDER_TYPE_WIN32; pango_win32_get_dc (); for (i = 0; _pango_included_win32_modules[i].list; i++) pango_module_register (&_pango_included_win32_modules[i]);}/** * pango_win32_font_map_for_display: * * Returns a #PangoWin32FontMap. Font maps are cached and should * not be freed. If the font map is no longer needed, it can * be released with pango_win32_shutdown_display(). * * Return value: a #PangoFontMap. **/PangoFontMap *pango_win32_font_map_for_display (void){ /* Make sure that the type system is initialized */ g_type_init (); if (default_fontmap != NULL) return PANGO_FONT_MAP (default_fontmap); default_fontmap = g_object_new (PANGO_TYPE_WIN32_FONT_MAP, NULL); return PANGO_FONT_MAP (default_fontmap);}/** * pango_win32_shutdown_display: * * Free cached resources. **/voidpango_win32_shutdown_display (void){ if (default_fontmap) { pango_win32_fontmap_cache_clear (default_fontmap); g_object_unref (default_fontmap); default_fontmap = NULL; }}static voidpango_win32_font_map_finalize (GObject *object){ PangoWin32FontMap *win32fontmap = PANGO_WIN32_FONT_MAP (object); g_list_foreach (win32fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL); g_queue_free (win32fontmap->freed_fonts); pango_win32_font_cache_free (win32fontmap->font_cache); G_OBJECT_CLASS (_pango_win32_font_map_parent_class)->finalize (object);}/* * PangoWin32Family */static voidpango_win32_family_list_faces (PangoFontFamily *family, PangoFontFace ***faces, int *n_faces){ PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family); *n_faces = g_slist_length (win32family->font_entries); if (faces) { GSList *tmp_list; int i = 0; *faces = g_new (PangoFontFace *, *n_faces); tmp_list = win32family->font_entries; while (tmp_list) { (*faces)[i++] = tmp_list->data; tmp_list = tmp_list->next; } }}static const char *pango_win32_family_get_name (PangoFontFamily *family){ PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family); return win32family->family_name;}static gbooleanpango_win32_family_is_monospace (PangoFontFamily *family){ PangoWin32Family *win32family = PANGO_WIN32_FAMILY (family); return win32family->is_monospace;}static voidpango_win32_family_class_init (PangoFontFamilyClass *class){ class->list_faces = pango_win32_family_list_faces; class->get_name = pango_win32_family_get_name; class->is_monospace = pango_win32_family_is_monospace;}static GTypepango_win32_family_get_type (void){ static GType object_type = 0; if (G_UNLIKELY (!object_type)) { const GTypeInfo object_info = { sizeof (PangoFontFamilyClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pango_win32_family_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (PangoWin32Family), 0, /* n_preallocs */ (GInstanceInitFunc) NULL, }; object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY, I_("PangoWin32Family"), &object_info, 0); } return object_type;}static voidlist_families_foreach (gpointer key, gpointer value, gpointer user_data){ GSList **list = user_data; *list = g_slist_prepend (*list, value);}static void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -