diff options
author | Tor Lillqvist <tml@iki.fi> | 2000-07-15 01:06:08 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 2000-07-15 01:06:08 +0000 |
commit | 932fe1e3da39b3d8febfca65f6ca5312f0397ed1 (patch) | |
tree | d5583d408b5af1a4ed899a78937fc76ed46c442d /pango/pangowin32-fontcache.c | |
parent | d4fb416c99d0066aafed26306a421a7bd22289e3 (diff) | |
download | pango-932fe1e3da39b3d8febfca65f6ca5312f0397ed1.tar.gz |
pango/pangowin32.h pango/pangowin32-private.h pango/pangowin32-fontcache.c
2000-07-15 Tor Lillqvist <tml@iki.fi>
* pango/pangowin32.h
* pango/pangowin32-private.h
* pango/pangowin32-fontcache.c
* pango/pangowin32-fontmap.c
* modules/basic/basic-win32.c
* examples/viewer-win32.c
* examples/pangowin32.aliases: New files. Start of a Win32
implementation. Does not work yet.
* configure.in: Chek for dirent.h and unistd.h.
* pango/pango-utils.h
* pango/pango-utils.c (pango_get_sysconf_subdirectory,
pango_get_lib_subdirectory): New functions, for better
portability, to enable installation-time choice of directory (on
Windows) instead of compile-time. Use these instead of SYSCONFDIR
"/pango" and LIBDIR "/pango".
(pango_split_file_list): Fix comment, the function splits on
searchpath separators, not commas. Use G_SEARCHPATH_SEPARATOR_S
for portability. Don't try to expand '~' as home directory on
Windows.
(read_config): Use pango_get_sysconf_subdirectory().
* pango/modules.c (read_modules): Use pango_get_sysconf_subdirectory().
Don't crash if a module file cannot be opened.
* pango/querymodules.c: Include config.h Conditionalize inclusion
of dirent.h and unistd.h. Use platform-specific shared library
extension. Use pango_get_lib_subdirectory().
Diffstat (limited to 'pango/pangowin32-fontcache.c')
-rw-r--r-- | pango/pangowin32-fontcache.c | 341 |
1 files changed, 341 insertions, 0 deletions
diff --git a/pango/pangowin32-fontcache.c b/pango/pangowin32-fontcache.c new file mode 100644 index 00000000..40d6eae3 --- /dev/null +++ b/pango/pangowin32-fontcache.c @@ -0,0 +1,341 @@ +/* Pango + * pangowin32-fontcache.c: Cache of HFONTs by LOGFONT + * + * Copyright (C) 2000 Red Hat Software + * + * 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 <stdio.h> + +#include "pangowin32-private.h" + +/* Font cache + */ + +/* Number of fonts to retain after they are not otherwise referenced. + */ +#define CACHE_SIZE 16 + +typedef struct _CacheEntry CacheEntry; + +struct _PangoWin32FontCache +{ + GHashTable *forward; + GHashTable *back; + + GList *mru; + GList *mru_tail; + int mru_count; +}; + +struct _CacheEntry +{ + LOGFONT logfont; + HFONT hfont; + + gint ref_count; + GList *mru; +}; + +static void +free_cache_entry (LOGFONT *logfont, + CacheEntry *entry, + PangoWin32FontCache *cache) +{ + DeleteObject (entry->hfont); + + g_free (entry); +} + +/** + * pango_win32_font_cache_free: + * @cache: a #PangoWin32FontCache + * + * Free a #PangoWin32FontCache and all associated memory. All fonts loaded + * through this font cache will be freed along with the cache. + **/ +void +pango_win32_font_cache_free (PangoWin32FontCache *cache) +{ + g_return_if_fail (cache != NULL); + + g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache); + + g_hash_table_destroy (cache->forward); + g_hash_table_destroy (cache->back); + + g_list_free (cache->mru); +} + +static guint +logfont_hash (gconstpointer v) +{ + const LOGFONT *lfp = v; + + return g_str_hash (lfp->lfFaceName) + + lfp->lfItalic + + lfp->lfWeight/10 + + lfp->lfOrientation + + lfp->lfHeight * 10; +} + +static gint +logfont_equal (gconstpointer v1, + gconstpointer v2) +{ + const LOGFONT *lfp1 = v1, *lfp2 = v2; + + return (strcmp (lfp1->lfFaceName, lfp2->lfFaceName) == 0 + && lfp1->lfPitchAndFamily == lfp2->lfPitchAndFamily + && lfp1->lfStrikeOut == lfp2->lfStrikeOut + && lfp1->lfUnderline == lfp2->lfUnderline + && lfp1->lfItalic == lfp2->lfItalic + && lfp1->lfWeight == lfp2->lfWeight + && lfp1->lfOrientation == lfp2->lfOrientation + && lfp1->lfEscapement == lfp2->lfEscapement + && lfp1->lfWidth == lfp2->lfWidth + && lfp1->lfHeight == lfp2->lfHeight); +} + +/** + * pango_win32_font_cache_new: + * + * Create a font cache. + * + * Return value: The new font cache. This must be freed with + * pango_win32_font_cache_free(). + **/ +PangoWin32FontCache * +pango_win32_font_cache_new (void) +{ + PangoWin32FontCache *cache; + + cache = g_new (PangoWin32FontCache, 1); + + cache->forward = g_hash_table_new (logfont_hash, logfont_equal); + cache->back = g_hash_table_new (g_direct_hash, g_direct_equal); + + cache->mru = NULL; + cache->mru_tail = NULL; + cache->mru_count = 0; + + return cache; +} + +static void +cache_entry_unref (PangoWin32FontCache *cache, + CacheEntry *entry) +{ + entry->ref_count--; + if (entry->ref_count == 0) + { + g_hash_table_remove (cache->forward, &entry->logfont); + g_hash_table_remove (cache->back, entry->hfont); + + free_cache_entry (NULL, entry, cache); + } +} + +/** + * pango_win32_font_cache_load: + * @cache: a #PangoWin32FontCache + * @logfont: a pointer to a LOGFONT structure describing the font to load. + * + * Create a #HFONT from a LOGFONT. The + * result may be newly loaded, or it may have been previously + * stored + * + * Return value: The font structure, or %NULL if the font could + * not be loaded. In order to free this structure, you must call + * pango_win32_font_cache_unload(). + **/ +HFONT +pango_win32_font_cache_load (PangoWin32FontCache *cache, + const LOGFONT *lfp) +{ + CacheEntry *entry; + LOGFONT lf; + HFONT hfont; + int tries; + + g_return_val_if_fail (cache != NULL, NULL); + g_return_val_if_fail (lfp != NULL, NULL); + + entry = g_hash_table_lookup (cache->forward, lfp); + + if (entry) + { + entry->ref_count++; + } + else + { + lf = *lfp; + for (tries = 0; ; tries++) + { +#if 0 + PANGO_NOTE + (g_print + ("... trying CreateFontIndirect, " + "height=%d,width=%d,escapement=%d,orientation=%d," + "weight=%d,%s%s%s" + "charset=%d,outprecision=%d,clipprecision=%d," + "quality=%d,pitchandfamily=%#.02x,facename=\"%s\")\n", + lf.lfHeight, lf.lfWidth, lf.lfEscapement, lf.lfOrientation, + lf.lfWeight, (lf.lfItalic ? "italic," : ""), + (lf.lfUnderline ? "underline," : ""), + (lf.lfStrikeOut ? "strikeout," : ""), + lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision, + lf.lfQuality, lf.lfPitchAndFamily, lf.lfFaceName)); +#endif + hfont = CreateFontIndirect (&lf); + + if (hfont != NULL) + break; + + /* If we fail, try some similar fonts often found on Windows. */ + if (tries == 0) + { + if (g_strcasecmp (lf.lfFaceName, "helvetica") == 0) + strcpy (lf.lfFaceName, "arial"); + else if (g_strcasecmp (lf.lfFaceName, "new century schoolbook") == 0) + strcpy (lf.lfFaceName, "century schoolbook"); + else if (g_strcasecmp (lf.lfFaceName, "courier") == 0) + strcpy (lf.lfFaceName, "courier new"); + else if (g_strcasecmp (lf.lfFaceName, "lucida") == 0) + strcpy (lf.lfFaceName, "lucida sans unicode"); + else if (g_strcasecmp (lf.lfFaceName, "lucidatypewriter") == 0) + strcpy (lf.lfFaceName, "lucida console"); + else if (g_strcasecmp (lf.lfFaceName, "times") == 0) + strcpy (lf.lfFaceName, "times new roman"); + } + else if (tries == 1) + { + if (g_strcasecmp (lf.lfFaceName, "courier") == 0) + { + strcpy (lf.lfFaceName, ""); + lf.lfPitchAndFamily |= FF_MODERN; + } + else if (g_strcasecmp (lf.lfFaceName, "times new roman") == 0) + { + strcpy (lf.lfFaceName, ""); + lf.lfPitchAndFamily |= FF_ROMAN; + } + else if (g_strcasecmp (lf.lfFaceName, "helvetica") == 0 + || g_strcasecmp (lf.lfFaceName, "lucida") == 0) + { + strcpy (lf.lfFaceName, ""); + lf.lfPitchAndFamily |= FF_SWISS; + } + else + { + strcpy (lf.lfFaceName, ""); + lf.lfPitchAndFamily = (lf.lfPitchAndFamily & 0x0F) | FF_DONTCARE; + } + } + else + break; + tries++; + } + + if (!hfont) + return NULL; + + entry = g_new (CacheEntry, 1); + + entry->logfont = lf; + entry->hfont = hfont; + + entry->ref_count = 1; + entry->mru = NULL; + + g_hash_table_insert (cache->forward, &entry->logfont, entry); + g_hash_table_insert (cache->back, entry->hfont, entry); + } + + if (entry->mru) + { + if (cache->mru_count > 1 && entry->mru->prev) + { + /* Move to the head of the mru list */ + + if (entry->mru == cache->mru_tail) + { + cache->mru_tail = cache->mru_tail->prev; + cache->mru_tail->next = NULL; + } + else + { + entry->mru->prev->next = entry->mru->next; + entry->mru->next->prev = entry->mru->prev; + } + + entry->mru->next = cache->mru; + entry->mru->prev = NULL; + cache->mru->prev = entry->mru; + cache->mru = entry->mru; + } + } + else + { + entry->ref_count++; + + /* Insert into the mru list */ + + if (cache->mru_count == CACHE_SIZE) + { + CacheEntry *old_entry = cache->mru_tail->data; + + cache->mru_tail = cache->mru_tail->prev; + cache->mru_tail->next = NULL; + + g_list_free_1 (old_entry->mru); + old_entry->mru = NULL; + cache_entry_unref (cache, old_entry); + } + else + cache->mru_count++; + + cache->mru = g_list_prepend (cache->mru, entry); + if (!cache->mru_tail) + cache->mru_tail = cache->mru; + entry->mru = cache->mru; + } + + return entry->hfont; +} + +/** + * pango_win32_font_cache_unload: + * @cache: a #PangoWin32FontCache + * @hfont: the HFONT to unload + * + * Free a font structure previously loaded with pango_win32_font_cache_load() + **/ +void +pango_win32_font_cache_unload (PangoWin32FontCache *cache, + HFONT hfont) +{ + CacheEntry *entry; + + g_return_if_fail (cache != NULL); + g_return_if_fail (hfont != NULL); + + entry = g_hash_table_lookup (cache->back, hfont); + g_return_if_fail (entry != NULL); + + cache_entry_unref (cache, entry); +} |