Blame pango/pangowin32-fontcache.c

Packit 0ec9dd
/* Pango
Packit 0ec9dd
 * pangowin32-fontcache.c: Cache of HFONTs by LOGFONTW
Packit 0ec9dd
 *
Packit 0ec9dd
 * Copyright (C) 2000 Red Hat Software
Packit 0ec9dd
 * Copyright (C) 2000 Tor Lillqvist
Packit 0ec9dd
 * Copyright (C) 2007 Novell, Inc.
Packit 0ec9dd
 *
Packit 0ec9dd
 * This library is free software; you can redistribute it and/or
Packit 0ec9dd
 * modify it under the terms of the GNU Library General Public
Packit 0ec9dd
 * License as published by the Free Software Foundation; either
Packit 0ec9dd
 * version 2 of the License, or (at your option) any later version.
Packit 0ec9dd
 *
Packit 0ec9dd
 * This library is distributed in the hope that it will be useful,
Packit 0ec9dd
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0ec9dd
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
Packit 0ec9dd
 * Library General Public License for more details.
Packit 0ec9dd
 *
Packit 0ec9dd
 * You should have received a copy of the GNU Library General Public
Packit 0ec9dd
 * License along with this library; if not, write to the
Packit 0ec9dd
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Packit 0ec9dd
 * Boston, MA 02111-1307, USA.
Packit 0ec9dd
 */
Packit 0ec9dd
Packit 0ec9dd
#include "config.h"
Packit 0ec9dd
#include <stdio.h>
Packit 0ec9dd
Packit 0ec9dd
#include "pangowin32-private.h"
Packit 0ec9dd
Packit 0ec9dd
/* Font cache
Packit 0ec9dd
 */
Packit 0ec9dd
Packit 0ec9dd
/* Number of fonts to retain after they are not otherwise referenced.
Packit 0ec9dd
 */
Packit 0ec9dd
#define CACHE_SIZE 16
Packit 0ec9dd
Packit 0ec9dd
typedef struct _CacheEntry CacheEntry;
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * PangoWin32FontCache:
Packit 0ec9dd
 *
Packit 0ec9dd
 * A #PangoWin32FontCache caches HFONTs by their LOGFONT descriptions.
Packit 0ec9dd
 */
Packit 0ec9dd
struct _PangoWin32FontCache
Packit 0ec9dd
{
Packit 0ec9dd
  GHashTable *forward;
Packit 0ec9dd
  GHashTable *back;
Packit 0ec9dd
Packit 0ec9dd
  GList *mru;
Packit 0ec9dd
  GList *mru_tail;
Packit 0ec9dd
  int mru_count;
Packit 0ec9dd
};
Packit 0ec9dd
Packit 0ec9dd
struct _CacheEntry
Packit 0ec9dd
{
Packit 0ec9dd
  LOGFONTW logfontw;
Packit 0ec9dd
  HFONT hfont;
Packit 0ec9dd
Packit 0ec9dd
  gint ref_count;
Packit 0ec9dd
  GList *mru;
Packit 0ec9dd
};
Packit 0ec9dd
Packit 0ec9dd
static void
Packit 0ec9dd
free_cache_entry (LOGFONTW            *logfont,
Packit 0ec9dd
		  CacheEntry          *entry,
Packit 0ec9dd
		  PangoWin32FontCache *cache)
Packit 0ec9dd
{
Packit 0ec9dd
  if (!DeleteObject (entry->hfont))
Packit 0ec9dd
    PING (("DeleteObject for hfont %p failed", entry->hfont));
Packit 0ec9dd
Packit 0ec9dd
  g_slice_free (CacheEntry, entry);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_win32_font_cache_free:
Packit 0ec9dd
 * @cache: a #PangoWin32FontCache
Packit 0ec9dd
 *
Packit 0ec9dd
 * Frees a #PangoWin32FontCache and all associated memory. All fonts loaded
Packit 0ec9dd
 * through this font cache will be freed along with the cache.
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_win32_font_cache_free (PangoWin32FontCache *cache)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_if_fail (cache != NULL);
Packit 0ec9dd
Packit 0ec9dd
  g_hash_table_foreach (cache->forward, (GHFunc)free_cache_entry, cache);
Packit 0ec9dd
Packit 0ec9dd
  g_hash_table_destroy (cache->forward);
Packit 0ec9dd
  g_hash_table_destroy (cache->back);
Packit 0ec9dd
Packit 0ec9dd
  g_list_free (cache->mru);
Packit 0ec9dd
Packit 0ec9dd
  g_slice_free (PangoWin32FontCache, cache);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
static guint
Packit 0ec9dd
wcs_hash (gconstpointer v)
Packit 0ec9dd
{
Packit 0ec9dd
  /* 31 bit hash function */
Packit 0ec9dd
  const wchar_t *p = v;
Packit 0ec9dd
  guint32 h = *p;
Packit 0ec9dd
Packit 0ec9dd
  if (h)
Packit 0ec9dd
    for (p += 1; *p != '\0'; p++)
Packit 0ec9dd
      h = (h << 5) - h + *p;
Packit 0ec9dd
Packit 0ec9dd
  return h;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
static guint
Packit 0ec9dd
logfontw_hash (gconstpointer v)
Packit 0ec9dd
{
Packit 0ec9dd
  const LOGFONTW *lfp = v;
Packit 0ec9dd
Packit 0ec9dd
  return wcs_hash (lfp->lfFaceName) +
Packit 0ec9dd
    (lfp->lfItalic != 0) +
Packit 0ec9dd
    lfp->lfWeight/10 +
Packit 0ec9dd
    lfp->lfOrientation +
Packit 0ec9dd
    abs (lfp->lfHeight) * 10;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
static gint
Packit 0ec9dd
logfontw_equal (gconstpointer v1,
Packit 0ec9dd
		gconstpointer v2)
Packit 0ec9dd
{
Packit 0ec9dd
  const LOGFONTW *lfp1 = v1, *lfp2 = v2;
Packit 0ec9dd
Packit 0ec9dd
  return (wcscmp (lfp1->lfFaceName, lfp2->lfFaceName) == 0
Packit 0ec9dd
	  && lfp1->lfPitchAndFamily == lfp2->lfPitchAndFamily
Packit 0ec9dd
	  && lfp1->lfStrikeOut == lfp2->lfStrikeOut
Packit 0ec9dd
	  && lfp1->lfUnderline == lfp2->lfUnderline
Packit 0ec9dd
	  && (lfp1->lfItalic != 0) == (lfp2->lfItalic != 0)
Packit 0ec9dd
	  && lfp1->lfWeight == lfp2->lfWeight
Packit 0ec9dd
	  && lfp1->lfOrientation == lfp2->lfOrientation
Packit 0ec9dd
	  && lfp1->lfEscapement == lfp2->lfEscapement
Packit 0ec9dd
	  && lfp1->lfWidth == lfp2->lfWidth
Packit 0ec9dd
	  && lfp1->lfHeight == lfp2->lfHeight);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_win32_font_cache_new:
Packit 0ec9dd
 *
Packit 0ec9dd
 * Creates a font cache.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: The new font cache. This must be freed with
Packit 0ec9dd
 * pango_win32_font_cache_free().
Packit 0ec9dd
 **/
Packit 0ec9dd
PangoWin32FontCache *
Packit 0ec9dd
pango_win32_font_cache_new (void)
Packit 0ec9dd
{
Packit 0ec9dd
  PangoWin32FontCache *cache;
Packit 0ec9dd
Packit 0ec9dd
  cache = g_slice_new (PangoWin32FontCache);
Packit 0ec9dd
Packit 0ec9dd
  cache->forward = g_hash_table_new (logfontw_hash, logfontw_equal);
Packit 0ec9dd
  cache->back = g_hash_table_new (g_direct_hash, g_direct_equal);
Packit 0ec9dd
Packit 0ec9dd
  cache->mru = NULL;
Packit 0ec9dd
  cache->mru_tail = NULL;
Packit 0ec9dd
  cache->mru_count = 0;
Packit 0ec9dd
Packit 0ec9dd
  return cache;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
static void
Packit 0ec9dd
cache_entry_unref (PangoWin32FontCache *cache,
Packit 0ec9dd
		   CacheEntry          *entry)
Packit 0ec9dd
{
Packit 0ec9dd
  if (g_atomic_int_dec_and_test (&entry->ref_count))
Packit 0ec9dd
    {
Packit 0ec9dd
      PING (("removing cache entry %p", entry->hfont));
Packit 0ec9dd
Packit 0ec9dd
      g_hash_table_remove (cache->forward, &entry->logfontw);
Packit 0ec9dd
      g_hash_table_remove (cache->back, entry->hfont);
Packit 0ec9dd
Packit 0ec9dd
      free_cache_entry (NULL, entry, cache);
Packit 0ec9dd
    }
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_win32_font_cache_load:
Packit 0ec9dd
 * @cache: a #PangoWin32FontCache
Packit 0ec9dd
 * @logfont: a pointer to a LOGFONTA structure describing the font to load.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Creates a HFONT from a LOGFONTA. The
Packit 0ec9dd
 * result may be newly loaded, or it may have been previously
Packit 0ec9dd
 * stored
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: (nullable): The font structure, or %NULL if the font
Packit 0ec9dd
 * could not be loaded. In order to free this structure, you must call
Packit 0ec9dd
 * pango_win32_font_cache_unload().
Packit 0ec9dd
 **/
Packit 0ec9dd
HFONT
Packit 0ec9dd
pango_win32_font_cache_load (PangoWin32FontCache *cache,
Packit 0ec9dd
			     const LOGFONTA      *lfp)
Packit 0ec9dd
{
Packit 0ec9dd
  LOGFONTW lf;
Packit 0ec9dd
Packit 0ec9dd
  /* We know that the lfFaceName is the last member in the structs */
Packit 0ec9dd
  *(LOGFONTA *)&lf = *lfp;
Packit 0ec9dd
  
Packit 0ec9dd
  if (!MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
Packit 0ec9dd
			    lfp->lfFaceName, -1,
Packit 0ec9dd
			    lf.lfFaceName, G_N_ELEMENTS (lf.lfFaceName)))
Packit 0ec9dd
    return NULL;
Packit 0ec9dd
Packit 0ec9dd
  return pango_win32_font_cache_loadw (cache, &lf);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_win32_font_cache_loadw:
Packit 0ec9dd
 * @cache: a #PangoWin32FontCache
Packit 0ec9dd
 * @logfont: a pointer to a LOGFONTW structure describing the font to load.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Creates a HFONT from a LOGFONTW. The
Packit 0ec9dd
 * result may be newly loaded, or it may have been previously
Packit 0ec9dd
 * stored
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: (nullable): The font structure, or %NULL if the font
Packit 0ec9dd
 * could not be loaded. In order to free this structure, you must call
Packit 0ec9dd
 * pango_win32_font_cache_unload().
Packit 0ec9dd
 *
Packit 0ec9dd
 * Since: 1.16
Packit 0ec9dd
 **/
Packit 0ec9dd
HFONT
Packit 0ec9dd
pango_win32_font_cache_loadw (PangoWin32FontCache *cache,
Packit 0ec9dd
			      const LOGFONTW      *lfp)
Packit 0ec9dd
{
Packit 0ec9dd
  CacheEntry *entry;
Packit 0ec9dd
  LOGFONTW lf;
Packit 0ec9dd
  HFONT hfont;
Packit 0ec9dd
  int tries;
Packit 0ec9dd
Packit 0ec9dd
  g_return_val_if_fail (cache != NULL, NULL);
Packit 0ec9dd
  g_return_val_if_fail (lfp != NULL, NULL);
Packit 0ec9dd
Packit 0ec9dd
  entry = g_hash_table_lookup (cache->forward, lfp);
Packit 0ec9dd
Packit 0ec9dd
  if (entry)
Packit 0ec9dd
    {
Packit 0ec9dd
      g_atomic_int_inc (&entry->ref_count);
Packit 0ec9dd
      PING (("increased refcount for cache entry %p: %d", entry->hfont, entry->ref_count));
Packit 0ec9dd
    }
Packit 0ec9dd
  else
Packit 0ec9dd
    {
Packit 0ec9dd
      BOOL font_smoothing;
Packit 0ec9dd
      lf = *lfp;
Packit 0ec9dd
      SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &font_smoothing, 0);
Packit 0ec9dd
      /* If on XP or better, try to use ClearType if the global system
Packit 0ec9dd
       * settings ask for it.
Packit 0ec9dd
       */
Packit 0ec9dd
      if (font_smoothing &&
Packit 0ec9dd
	  (_pango_win32_os_version_info.dwMajorVersion > 5 ||
Packit 0ec9dd
	   (_pango_win32_os_version_info.dwMajorVersion == 5 &&
Packit 0ec9dd
	    _pango_win32_os_version_info.dwMinorVersion >= 1)))
Packit 0ec9dd
	{
Packit 0ec9dd
	  UINT smoothing_type;
Packit 0ec9dd
Packit 0ec9dd
#ifndef SPI_GETFONTSMOOTHINGTYPE
Packit 0ec9dd
#define SPI_GETFONTSMOOTHINGTYPE 0x200a
Packit 0ec9dd
#endif
Packit 0ec9dd
#ifndef FE_FONTSMOOTHINGCLEARTYPE
Packit 0ec9dd
#define FE_FONTSMOOTHINGCLEARTYPE 2
Packit 0ec9dd
#endif
Packit 0ec9dd
#ifndef CLEARTYPE_QUALITY
Packit 0ec9dd
#define CLEARTYPE_QUALITY 5
Packit 0ec9dd
#endif
Packit 0ec9dd
	  SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0);
Packit 0ec9dd
	  lf.lfQuality =
Packit 0ec9dd
	    (font_smoothing ?
Packit 0ec9dd
	     (smoothing_type == FE_FONTSMOOTHINGCLEARTYPE ?
Packit 0ec9dd
	      CLEARTYPE_QUALITY : ANTIALIASED_QUALITY) :
Packit 0ec9dd
	     DEFAULT_QUALITY);
Packit 0ec9dd
	}
Packit 0ec9dd
      else
Packit 0ec9dd
	lf.lfQuality = (font_smoothing ? ANTIALIASED_QUALITY : DEFAULT_QUALITY);
Packit 0ec9dd
      lf.lfCharSet = DEFAULT_CHARSET;
Packit 0ec9dd
      for (tries = 0; ; tries++)
Packit 0ec9dd
	{
Packit 0ec9dd
	  PING (("... trying CreateFontIndirect "
Packit 0ec9dd
		 "height=%ld,width=%ld,escapement=%ld,orientation=%ld,"
Packit 0ec9dd
		 "weight=%ld,%s%s%s"
Packit 0ec9dd
		 "charset=%d,outprecision=%d,clipprecision=%d,"
Packit 0ec9dd
		 "quality=%d,pitchandfamily=%#.02x,facename=\"%S\")",
Packit 0ec9dd
		 lf.lfHeight, lf.lfWidth, lf.lfEscapement, lf.lfOrientation,
Packit 0ec9dd
		 lf.lfWeight, (lf.lfItalic ? "italic," : ""),
Packit 0ec9dd
		 (lf.lfUnderline ? "underline," : ""),
Packit 0ec9dd
		 (lf.lfStrikeOut ? "strikeout," : ""),
Packit 0ec9dd
		 lf.lfCharSet, lf.lfOutPrecision, lf.lfClipPrecision,
Packit 0ec9dd
		 lf.lfQuality, lf.lfPitchAndFamily, lf.lfFaceName));
Packit 0ec9dd
	  hfont = CreateFontIndirectW (&lf);
Packit 0ec9dd
Packit 0ec9dd
	  if (hfont != NULL)
Packit 0ec9dd
	    {
Packit 0ec9dd
	      PING (("Success! hfont=%p", hfont));
Packit 0ec9dd
	      break;
Packit 0ec9dd
	    }
Packit 0ec9dd
Packit 0ec9dd
	  /* If we fail, try some similar fonts often found on Windows. */
Packit 0ec9dd
	  if (tries == 0)
Packit 0ec9dd
	    {
Packit 0ec9dd
	      gchar *p = g_utf16_to_utf8 (lf.lfFaceName, -1, NULL, NULL, NULL);
Packit 0ec9dd
	      if (!p)
Packit 0ec9dd
		; /* Nothing */
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "helvetica") == 0)
Packit 0ec9dd
		wcscpy (lf.lfFaceName, L"arial");
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "new century schoolbook") == 0)
Packit 0ec9dd
		wcscpy (lf.lfFaceName, L"century schoolbook");
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "courier") == 0)
Packit 0ec9dd
		wcscpy (lf.lfFaceName, L"courier new");
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "lucida") == 0)
Packit 0ec9dd
		wcscpy (lf.lfFaceName, L"lucida sans unicode");
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "lucidatypewriter") == 0)
Packit 0ec9dd
		wcscpy (lf.lfFaceName, L"lucida console");
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "times") == 0)
Packit 0ec9dd
		wcscpy (lf.lfFaceName, L"times new roman");
Packit 0ec9dd
	      g_free (p);
Packit 0ec9dd
	    }
Packit 0ec9dd
	  else if (tries == 1)
Packit 0ec9dd
	    {
Packit 0ec9dd
	      gchar *p = g_utf16_to_utf8 (lf.lfFaceName, -1, NULL, NULL, NULL);
Packit 0ec9dd
	      if (!p)
Packit 0ec9dd
		; /* Nothing */
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "courier") == 0)
Packit 0ec9dd
		{
Packit 0ec9dd
		  wcscpy (lf.lfFaceName, L"");
Packit 0ec9dd
		  lf.lfPitchAndFamily |= FF_MODERN;
Packit 0ec9dd
		}
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "times new roman") == 0)
Packit 0ec9dd
		{
Packit 0ec9dd
		  wcscpy (lf.lfFaceName, L"");
Packit 0ec9dd
		  lf.lfPitchAndFamily |= FF_ROMAN;
Packit 0ec9dd
		}
Packit 0ec9dd
	      else if (g_ascii_strcasecmp (p, "helvetica") == 0
Packit 0ec9dd
		       || g_ascii_strcasecmp (p, "lucida") == 0)
Packit 0ec9dd
		{
Packit 0ec9dd
		  wcscpy (lf.lfFaceName, L"");
Packit 0ec9dd
		  lf.lfPitchAndFamily |= FF_SWISS;
Packit 0ec9dd
		}
Packit 0ec9dd
	      else
Packit 0ec9dd
		{
Packit 0ec9dd
		  wcscpy (lf.lfFaceName, L"");
Packit 0ec9dd
		  lf.lfPitchAndFamily = (lf.lfPitchAndFamily & 0x0F) | FF_DONTCARE;
Packit 0ec9dd
		}
Packit 0ec9dd
	      g_free (p);
Packit 0ec9dd
	    }
Packit 0ec9dd
	  else
Packit 0ec9dd
	    break;
Packit 0ec9dd
	  tries++;
Packit 0ec9dd
	}
Packit 0ec9dd
Packit 0ec9dd
      if (!hfont)
Packit 0ec9dd
	return NULL;
Packit 0ec9dd
Packit 0ec9dd
      entry = g_slice_new (CacheEntry);
Packit 0ec9dd
Packit 0ec9dd
      entry->logfontw = lf;
Packit 0ec9dd
      entry->hfont = hfont;
Packit 0ec9dd
Packit 0ec9dd
      entry->ref_count = 1;
Packit 0ec9dd
      entry->mru = NULL;
Packit 0ec9dd
Packit 0ec9dd
      g_hash_table_insert (cache->forward, &entry->logfontw, entry);
Packit 0ec9dd
      g_hash_table_insert (cache->back, entry->hfont, entry);
Packit 0ec9dd
    }
Packit 0ec9dd
Packit 0ec9dd
  if (entry->mru)
Packit 0ec9dd
    {
Packit 0ec9dd
      if (cache->mru_count > 1 && entry->mru->prev)
Packit 0ec9dd
	{
Packit 0ec9dd
	  /* Move to the head of the mru list */
Packit 0ec9dd
Packit 0ec9dd
	  if (entry->mru == cache->mru_tail)
Packit 0ec9dd
	    {
Packit 0ec9dd
	      cache->mru_tail = cache->mru_tail->prev;
Packit 0ec9dd
	      cache->mru_tail->next = NULL;
Packit 0ec9dd
	    }
Packit 0ec9dd
	  else
Packit 0ec9dd
	    {
Packit 0ec9dd
	      entry->mru->prev->next = entry->mru->next;
Packit 0ec9dd
	      entry->mru->next->prev = entry->mru->prev;
Packit 0ec9dd
	    }
Packit 0ec9dd
Packit 0ec9dd
	  entry->mru->next = cache->mru;
Packit 0ec9dd
	  entry->mru->prev = NULL;
Packit 0ec9dd
	  cache->mru->prev = entry->mru;
Packit 0ec9dd
	  cache->mru = entry->mru;
Packit 0ec9dd
	}
Packit 0ec9dd
    }
Packit 0ec9dd
  else
Packit 0ec9dd
    {
Packit 0ec9dd
      g_atomic_int_inc (&entry->ref_count);
Packit 0ec9dd
Packit 0ec9dd
      /* Insert into the mru list */
Packit 0ec9dd
Packit 0ec9dd
      if (cache->mru_count == CACHE_SIZE)
Packit 0ec9dd
	{
Packit 0ec9dd
	  CacheEntry *old_entry = cache->mru_tail->data;
Packit 0ec9dd
Packit 0ec9dd
	  cache->mru_tail = cache->mru_tail->prev;
Packit 0ec9dd
	  cache->mru_tail->next = NULL;
Packit 0ec9dd
Packit 0ec9dd
	  g_list_free_1 (old_entry->mru);
Packit 0ec9dd
	  old_entry->mru = NULL;
Packit 0ec9dd
	  cache_entry_unref (cache, old_entry);
Packit 0ec9dd
	}
Packit 0ec9dd
      else
Packit 0ec9dd
	cache->mru_count++;
Packit 0ec9dd
Packit 0ec9dd
      cache->mru = g_list_prepend (cache->mru, entry);
Packit 0ec9dd
      if (!cache->mru_tail)
Packit 0ec9dd
	cache->mru_tail = cache->mru;
Packit 0ec9dd
      entry->mru = cache->mru;
Packit 0ec9dd
    }
Packit 0ec9dd
Packit 0ec9dd
  return entry->hfont;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_win32_font_cache_unload:
Packit 0ec9dd
 * @cache: a #PangoWin32FontCache
Packit 0ec9dd
 * @hfont: the HFONT to unload
Packit 0ec9dd
 *
Packit 0ec9dd
 * Frees a font structure previously loaded with pango_win32_font_cache_load().
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_win32_font_cache_unload (PangoWin32FontCache *cache,
Packit 0ec9dd
			       HFONT		    hfont)
Packit 0ec9dd
{
Packit 0ec9dd
  CacheEntry *entry;
Packit 0ec9dd
Packit 0ec9dd
  g_return_if_fail (cache != NULL);
Packit 0ec9dd
  g_return_if_fail (hfont != NULL);
Packit 0ec9dd
Packit 0ec9dd
  entry = g_hash_table_lookup (cache->back, hfont);
Packit 0ec9dd
  g_return_if_fail (entry != NULL);
Packit 0ec9dd
Packit 0ec9dd
  cache_entry_unref (cache, entry);
Packit 0ec9dd
}