Blame pango/pango-fontmap.c

Packit 0ec9dd
/* Pango
Packit 0ec9dd
 * pango-fontmap.c: Font handling
Packit 0ec9dd
 *
Packit 0ec9dd
 * Copyright (C) 2000 Red Hat Software
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 "pango-fontmap.h"
Packit 0ec9dd
#include "pango-impl-utils.h"
Packit 0ec9dd
#include <stdlib.h>
Packit 0ec9dd
Packit 0ec9dd
static PangoFontset *pango_font_map_real_load_fontset (PangoFontMap               *fontmap,
Packit 0ec9dd
						       PangoContext               *context,
Packit 0ec9dd
						       const PangoFontDescription *desc,
Packit 0ec9dd
						       PangoLanguage              *language);
Packit 0ec9dd
Packit 0ec9dd
Packit 0ec9dd
G_DEFINE_ABSTRACT_TYPE (PangoFontMap, pango_font_map, G_TYPE_OBJECT)
Packit 0ec9dd
Packit 0ec9dd
static void
Packit 0ec9dd
pango_font_map_class_init (PangoFontMapClass *class)
Packit 0ec9dd
{
Packit 0ec9dd
  class->load_fontset = pango_font_map_real_load_fontset;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
static void
Packit 0ec9dd
pango_font_map_init (PangoFontMap *fontmap G_GNUC_UNUSED)
Packit 0ec9dd
{
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_font_map_create_context:
Packit 0ec9dd
 * @fontmap: a #PangoFontMap
Packit 0ec9dd
 *
Packit 0ec9dd
 * Creates a #PangoContext connected to @fontmap.  This is equivalent
Packit 0ec9dd
 * to pango_context_new() followed by pango_context_set_font_map().
Packit 0ec9dd
 *
Packit 0ec9dd
 * If you are using Pango as part of a higher-level system,
Packit 0ec9dd
 * that system may have it's own way of create a #PangoContext.
Packit 0ec9dd
 * For instance, the GTK+ toolkit has, among others,
Packit 0ec9dd
 * gdk_pango_context_get_for_screen(), and
Packit 0ec9dd
 * gtk_widget_get_pango_context().  Use those instead.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: (transfer full): the newly allocated #PangoContext,
Packit 0ec9dd
 *               which should be freed with g_object_unref().
Packit 0ec9dd
 *
Packit 0ec9dd
 * Since: 1.22
Packit 0ec9dd
 **/
Packit 0ec9dd
PangoContext *
Packit 0ec9dd
pango_font_map_create_context (PangoFontMap *fontmap)
Packit 0ec9dd
{
Packit 0ec9dd
  PangoContext *context;
Packit 0ec9dd
Packit 0ec9dd
  g_return_val_if_fail (fontmap != NULL, NULL);
Packit 0ec9dd
Packit 0ec9dd
  context = pango_context_new ();
Packit 0ec9dd
  pango_context_set_font_map (context, fontmap);
Packit 0ec9dd
Packit 0ec9dd
  return context;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_font_map_load_font:
Packit 0ec9dd
 * @fontmap: a #PangoFontMap
Packit 0ec9dd
 * @context: the #PangoContext the font will be used with
Packit 0ec9dd
 * @desc: a #PangoFontDescription describing the font to load
Packit 0ec9dd
 *
Packit 0ec9dd
 * Load the font in the fontmap that is the closest match for @desc.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Returns: (transfer full) (nullable): the newly allocated #PangoFont
Packit 0ec9dd
 *          loaded, or %NULL if no font matched.
Packit 0ec9dd
 **/
Packit 0ec9dd
PangoFont *
Packit 0ec9dd
pango_font_map_load_font  (PangoFontMap               *fontmap,
Packit 0ec9dd
			   PangoContext               *context,
Packit 0ec9dd
			   const PangoFontDescription *desc)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_val_if_fail (fontmap != NULL, NULL);
Packit 0ec9dd
Packit 0ec9dd
  return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_font (fontmap, context, desc);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_font_map_list_families:
Packit 0ec9dd
 * @fontmap: a #PangoFontMap
Packit 0ec9dd
 * @families: (out) (array length=n_families) (transfer container): location to store a pointer to an array of #PangoFontFamily *.
Packit 0ec9dd
 *            This array should be freed with g_free().
Packit 0ec9dd
 * @n_families: (out): location to store the number of elements in @families
Packit 0ec9dd
 *
Packit 0ec9dd
 * List all families for a fontmap.
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_font_map_list_families (PangoFontMap      *fontmap,
Packit 0ec9dd
			      PangoFontFamily ***families,
Packit 0ec9dd
			      int               *n_families)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_if_fail (fontmap != NULL);
Packit 0ec9dd
Packit 0ec9dd
  PANGO_FONT_MAP_GET_CLASS (fontmap)->list_families (fontmap, families, n_families);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_font_map_load_fontset:
Packit 0ec9dd
 * @fontmap: a #PangoFontMap
Packit 0ec9dd
 * @context: the #PangoContext the font will be used with
Packit 0ec9dd
 * @desc: a #PangoFontDescription describing the font to load
Packit 0ec9dd
 * @language: a #PangoLanguage the fonts will be used for
Packit 0ec9dd
 *
Packit 0ec9dd
 * Load a set of fonts in the fontmap that can be used to render
Packit 0ec9dd
 * a font matching @desc.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Returns: (transfer full) (nullable): the newly allocated
Packit 0ec9dd
 *          #PangoFontset loaded, or %NULL if no font matched.
Packit 0ec9dd
 **/
Packit 0ec9dd
PangoFontset *
Packit 0ec9dd
pango_font_map_load_fontset (PangoFontMap                 *fontmap,
Packit 0ec9dd
			     PangoContext                 *context,
Packit 0ec9dd
			     const PangoFontDescription   *desc,
Packit 0ec9dd
			     PangoLanguage                *language)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_val_if_fail (fontmap != NULL, NULL);
Packit 0ec9dd
Packit 0ec9dd
  return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_fontset (fontmap, context, desc, language);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
static void
Packit 0ec9dd
pango_font_map_fontset_add_fonts (PangoFontMap          *fontmap,
Packit 0ec9dd
				  PangoContext          *context,
Packit 0ec9dd
				  PangoFontsetSimple    *fonts,
Packit 0ec9dd
				  PangoFontDescription  *desc,
Packit 0ec9dd
				  const char            *family)
Packit 0ec9dd
{
Packit 0ec9dd
  PangoFont *font;
Packit 0ec9dd
Packit 0ec9dd
  pango_font_description_set_family_static (desc, family);
Packit 0ec9dd
  font = pango_font_map_load_font (fontmap, context, desc);
Packit 0ec9dd
  if (font)
Packit 0ec9dd
    pango_fontset_simple_append (fonts, font);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
static PangoFontset *
Packit 0ec9dd
pango_font_map_real_load_fontset (PangoFontMap               *fontmap,
Packit 0ec9dd
				  PangoContext               *context,
Packit 0ec9dd
				  const PangoFontDescription *desc,
Packit 0ec9dd
				  PangoLanguage              *language)
Packit 0ec9dd
{
Packit 0ec9dd
  PangoFontDescription *tmp_desc = pango_font_description_copy_static (desc);
Packit 0ec9dd
  const char *family;
Packit 0ec9dd
  char **families;
Packit 0ec9dd
  int i;
Packit 0ec9dd
  PangoFontsetSimple *fonts;
Packit 0ec9dd
  static GHashTable *warned_fonts = NULL; /* MT-safe */
Packit 0ec9dd
  G_LOCK_DEFINE_STATIC (warned_fonts);
Packit 0ec9dd
Packit 0ec9dd
  family = pango_font_description_get_family (desc);
Packit 0ec9dd
  families = g_strsplit (family ? family : "", ",", -1);
Packit 0ec9dd
Packit 0ec9dd
  fonts = pango_fontset_simple_new (language);
Packit 0ec9dd
Packit 0ec9dd
  for (i = 0; families[i]; i++)
Packit 0ec9dd
    pango_font_map_fontset_add_fonts (fontmap,
Packit 0ec9dd
				      context,
Packit 0ec9dd
				      fonts,
Packit 0ec9dd
				      tmp_desc,
Packit 0ec9dd
				      families[i]);
Packit 0ec9dd
Packit 0ec9dd
  g_strfreev (families);
Packit 0ec9dd
Packit 0ec9dd
  /* The font description was completely unloadable, try with
Packit 0ec9dd
   * family == "Sans"
Packit 0ec9dd
   */
Packit 0ec9dd
  if (pango_fontset_simple_size (fonts) == 0)
Packit 0ec9dd
    {
Packit 0ec9dd
      char *ctmp1, *ctmp2;
Packit 0ec9dd
Packit 0ec9dd
      pango_font_description_set_family_static (tmp_desc,
Packit 0ec9dd
						pango_font_description_get_family (desc));
Packit 0ec9dd
Packit 0ec9dd
      ctmp1 = pango_font_description_to_string (desc);
Packit 0ec9dd
      pango_font_description_set_family_static (tmp_desc, "Sans");
Packit 0ec9dd
Packit 0ec9dd
      G_LOCK (warned_fonts);
Packit 0ec9dd
      if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
Packit 0ec9dd
	{
Packit 0ec9dd
	  if (!warned_fonts)
Packit 0ec9dd
	    warned_fonts = g_hash_table_new (g_str_hash, g_str_equal);
Packit 0ec9dd
Packit 0ec9dd
	  g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
Packit 0ec9dd
Packit 0ec9dd
	  ctmp2 = pango_font_description_to_string (tmp_desc);
Packit 0ec9dd
	  g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
Packit 0ec9dd
		     "expect ugly output.", ctmp1, ctmp2);
Packit 0ec9dd
	  g_free (ctmp2);
Packit 0ec9dd
	}
Packit 0ec9dd
      G_UNLOCK (warned_fonts);
Packit 0ec9dd
      g_free (ctmp1);
Packit 0ec9dd
Packit 0ec9dd
      pango_font_map_fontset_add_fonts (fontmap,
Packit 0ec9dd
					context,
Packit 0ec9dd
					fonts,
Packit 0ec9dd
					tmp_desc,
Packit 0ec9dd
					"Sans");
Packit 0ec9dd
    }
Packit 0ec9dd
Packit 0ec9dd
  /* We couldn't try with Sans and the specified style. Try Sans Normal
Packit 0ec9dd
   */
Packit 0ec9dd
  if (pango_fontset_simple_size (fonts) == 0)
Packit 0ec9dd
    {
Packit 0ec9dd
      char *ctmp1, *ctmp2;
Packit 0ec9dd
Packit 0ec9dd
      pango_font_description_set_family_static (tmp_desc, "Sans");
Packit 0ec9dd
      ctmp1 = pango_font_description_to_string (tmp_desc);
Packit 0ec9dd
      pango_font_description_set_style (tmp_desc, PANGO_STYLE_NORMAL);
Packit 0ec9dd
      pango_font_description_set_weight (tmp_desc, PANGO_WEIGHT_NORMAL);
Packit 0ec9dd
      pango_font_description_set_variant (tmp_desc, PANGO_VARIANT_NORMAL);
Packit 0ec9dd
      pango_font_description_set_stretch (tmp_desc, PANGO_STRETCH_NORMAL);
Packit 0ec9dd
Packit 0ec9dd
      G_LOCK (warned_fonts);
Packit 0ec9dd
      if (!warned_fonts || !g_hash_table_lookup (warned_fonts, ctmp1))
Packit 0ec9dd
	{
Packit 0ec9dd
	  g_hash_table_insert (warned_fonts, g_strdup (ctmp1), GINT_TO_POINTER (1));
Packit 0ec9dd
Packit 0ec9dd
	  ctmp2 = pango_font_description_to_string (tmp_desc);
Packit 0ec9dd
Packit 0ec9dd
	  g_warning ("couldn't load font \"%s\", falling back to \"%s\", "
Packit 0ec9dd
		     "expect ugly output.", ctmp1, ctmp2);
Packit 0ec9dd
	  g_free (ctmp2);
Packit 0ec9dd
	}
Packit 0ec9dd
      G_UNLOCK (warned_fonts);
Packit 0ec9dd
      g_free (ctmp1);
Packit 0ec9dd
Packit 0ec9dd
      pango_font_map_fontset_add_fonts (fontmap,
Packit 0ec9dd
					context,
Packit 0ec9dd
					fonts,
Packit 0ec9dd
					tmp_desc,
Packit 0ec9dd
					"Sans");
Packit 0ec9dd
    }
Packit 0ec9dd
Packit 0ec9dd
  pango_font_description_free (tmp_desc);
Packit 0ec9dd
Packit 0ec9dd
  /* Everything failed, we are screwed, there is no way to continue,
Packit 0ec9dd
   * but lets just not crash here.
Packit 0ec9dd
   */
Packit 0ec9dd
  if (pango_fontset_simple_size (fonts) == 0)
Packit 0ec9dd
      g_warning ("All font fallbacks failed!!!!");
Packit 0ec9dd
Packit 0ec9dd
  return PANGO_FONTSET (fonts);
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_font_map_get_shape_engine_type:
Packit 0ec9dd
 * @fontmap: a #PangoFontMap
Packit 0ec9dd
 *
Packit 0ec9dd
 * Returns the render ID for shape engines for this fontmap.
Packit 0ec9dd
 * See the <structfield>render_type</structfield> field of
Packit 0ec9dd
 * #PangoEngineInfo.
Packit 0ec9dd
  *
Packit 0ec9dd
 * Return value: the ID string for shape engines for
Packit 0ec9dd
 *  this fontmap. Owned by Pango, should not be modified
Packit 0ec9dd
 *  or freed.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Since: 1.4
Packit 0ec9dd
 * Deprecated: 1.38
Packit 0ec9dd
 **/
Packit 0ec9dd
const char *
Packit 0ec9dd
pango_font_map_get_shape_engine_type (PangoFontMap *fontmap)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_val_if_fail (PANGO_IS_FONT_MAP (fontmap), NULL);
Packit 0ec9dd
Packit 0ec9dd
  return PANGO_FONT_MAP_GET_CLASS (fontmap)->shape_engine_type;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_font_map_get_serial:
Packit 0ec9dd
 * @fontmap: a #PangoFontMap
Packit 0ec9dd
 *
Packit 0ec9dd
 * Returns the current serial number of @fontmap.  The serial number is
Packit 0ec9dd
 * initialized to an small number larger than zero when a new fontmap
Packit 0ec9dd
 * is created and is increased whenever the fontmap is changed. It may
Packit 0ec9dd
 * wrap, but will never have the value 0. Since it can wrap, never compare
Packit 0ec9dd
 * it with "less than", always use "not equals".
Packit 0ec9dd
 *
Packit 0ec9dd
 * The fontmap can only be changed using backend-specific API, like changing
Packit 0ec9dd
 * fontmap resolution.
Packit 0ec9dd
 *
Packit 0ec9dd
 * This can be used to automatically detect changes to a #PangoFontMap, like
Packit 0ec9dd
 * in #PangoContext.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Return value: The current serial number of @fontmap.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Since: 1.32.4
Packit 0ec9dd
 **/
Packit 0ec9dd
guint
Packit 0ec9dd
pango_font_map_get_serial (PangoFontMap *fontmap)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_val_if_fail (PANGO_IS_FONT_MAP (fontmap), 0);
Packit 0ec9dd
Packit 0ec9dd
  if (PANGO_FONT_MAP_GET_CLASS (fontmap)->get_serial)
Packit 0ec9dd
    return PANGO_FONT_MAP_GET_CLASS (fontmap)->get_serial (fontmap);
Packit 0ec9dd
  else
Packit 0ec9dd
    return 1;
Packit 0ec9dd
}
Packit 0ec9dd
Packit 0ec9dd
/**
Packit 0ec9dd
 * pango_font_map_changed:
Packit 0ec9dd
 * @fontmap: a #PangoFontMap
Packit 0ec9dd
 *
Packit 0ec9dd
 * Forces a change in the context, which will cause any #PangoContext
Packit 0ec9dd
 * using this fontmap to change.
Packit 0ec9dd
 *
Packit 0ec9dd
 * This function is only useful when implementing a new backend
Packit 0ec9dd
 * for Pango, something applications won't do. Backends should
Packit 0ec9dd
 * call this function if they have attached extra data to the context
Packit 0ec9dd
 * and such data is changed.
Packit 0ec9dd
 *
Packit 0ec9dd
 * Since: 1.34
Packit 0ec9dd
 **/
Packit 0ec9dd
void
Packit 0ec9dd
pango_font_map_changed (PangoFontMap *fontmap)
Packit 0ec9dd
{
Packit 0ec9dd
  g_return_if_fail (PANGO_IS_FONT_MAP (fontmap));
Packit 0ec9dd
Packit 0ec9dd
  if (PANGO_FONT_MAP_GET_CLASS (fontmap)->changed)
Packit 0ec9dd
    PANGO_FONT_MAP_GET_CLASS (fontmap)->changed (fontmap);
Packit 0ec9dd
}