/* Pango2 * * Copyright (C) 1999 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 "config.h" #include "pango-font-face-private.h" #include "pango-font-family.h" #ifdef __linux__ #include static inline char * get_backtrace (void) { void *buffer[1024]; int size; char **symbols; GString *s; size = backtrace (buffer, 1024); symbols = backtrace_symbols (buffer, size); s = g_string_new (""); for (int i = 0; i < size; i++) { g_string_append (s, symbols[i]); g_string_append_c (s, '\n'); } free (symbols); return g_string_free (s, FALSE); } #endif /** * Pango2FontFace: * * A `Pango2FontFace` is used to represent a group of fonts with * the same family, slant, weight, and width, but varying sizes. * * `Pango2FontFace` provides APIs to determine coverage information, * such as [method@Pango2.FontFace.has_char] and * [method@Pango2.FontFace.supports_language], as well as general * information about the font face like [method@Pango2.FontFace.is_monospace] * or [method@Pango2.FontFace.is_variable]. */ /* {{{ Pango2FontFace implementation */ enum { PROP_NAME = 1, PROP_DESCRIPTION, PROP_FAMILY, PROP_SYNTHESIZED, PROP_MONOSPACE, PROP_VARIABLE, N_PROPERTIES }; static GParamSpec *properties[N_PROPERTIES] = { NULL, }; G_DEFINE_ABSTRACT_TYPE (Pango2FontFace, pango2_font_face, G_TYPE_OBJECT) static gboolean pango2_font_face_default_is_monospace (Pango2FontFace *face) { return FALSE; } static gboolean pango2_font_face_default_is_variable (Pango2FontFace *face) { return FALSE; } static gboolean pango2_font_face_default_supports_language (Pango2FontFace *face, Pango2Language *language) { return TRUE; } static Pango2Language ** pango2_font_face_default_get_languages (Pango2FontFace *face) { return NULL; } static gboolean pango2_font_face_default_has_char (Pango2FontFace *face, gunichar wc) { return FALSE; } static const char * pango2_font_face_default_get_faceid (Pango2FontFace *face) { return ""; } static Pango2Font * pango2_font_face_default_create_font (Pango2FontFace *face, const Pango2FontDescription *desc, float dpi, const Pango2Matrix *ctm) { return NULL; } static void pango2_font_face_finalize (GObject *object) { Pango2FontFace *face = PANGO2_FONT_FACE (object); pango2_font_description_free (face->description); g_free (face->name); G_OBJECT_CLASS (pango2_font_face_parent_class)->finalize (object); } static void pango2_font_face_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { Pango2FontFace *face = PANGO2_FONT_FACE (object); switch (property_id) { case PROP_NAME: g_value_set_string (value, face->name); break; case PROP_DESCRIPTION: if ((pango2_font_description_get_set_fields (face->description) & PANGO2_FONT_MASK_FACEID) == 0) pango2_font_description_set_faceid (face->description, pango2_font_face_get_faceid (face)); g_value_set_boxed (value, face->description); break; case PROP_FAMILY: g_value_set_object (value, face->family); break; case PROP_SYNTHESIZED: g_value_set_boolean (value, pango2_font_face_is_synthesized (face)); break; case PROP_MONOSPACE: g_value_set_boolean (value, pango2_font_face_is_monospace (face)); break; case PROP_VARIABLE: g_value_set_boolean (value, pango2_font_face_is_variable (face)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } } static void pango2_font_face_class_init (Pango2FontFaceClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); object_class->finalize = pango2_font_face_finalize; object_class->get_property = pango2_font_face_get_property; class->is_monospace = pango2_font_face_default_is_monospace; class->is_variable = pango2_font_face_default_is_variable; class->get_languages = pango2_font_face_default_get_languages; class->supports_language = pango2_font_face_default_supports_language; class->has_char = pango2_font_face_default_has_char; class->get_faceid = pango2_font_face_default_get_faceid; class->create_font = pango2_font_face_default_create_font; /** * Pango2FontFace:name: (attributes org.gtk.Property.get=pango2_font_face_get_name) * * A name representing the style of this face. */ properties[PROP_NAME] = g_param_spec_string ("name", NULL, NULL, NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * Pango2FontFace:description: (attributes org.gtk.Property.get=pango2_font_face_describe) * * A font description that matches the face. * * The font description will have the family, style, * variant, weight and stretch of the face, but its size field * will be unset. */ properties[PROP_DESCRIPTION] = g_param_spec_boxed ("description", NULL, NULL, PANGO2_TYPE_FONT_DESCRIPTION, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * Pango2FontFace:family: (attributes org.gtk.Property.get=pango2_font_face_get_family) * * The `Pango2FontFamily` that the face belongs to. */ properties[PROP_FAMILY] = g_param_spec_object ("family", NULL, NULL, PANGO2_TYPE_FONT_FAMILY, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * Pango2FontFace:synthesized: (attributes org.gtk.Property.get=pango2_font_face_is_synthesized) * * `TRUE` if the face is synthesized. * * This will be the case if the underlying font rendering engine * creates this face from another face, by shearing, emboldening, * lightening or modifying it in some other way. */ properties[PROP_SYNTHESIZED] = g_param_spec_boolean ("synthesized", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * Pango2FontFace:monospace: (attributes org.gtk.Property.get=pango2_font_face_is_monospace) * * `TRUE` if the face is designed for text display where the the * characters form a regular grid. */ properties[PROP_MONOSPACE] = g_param_spec_boolean ("monospace", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); /** * Pango2FontFace:variable: (attributes org.gtk.Property.get=pango2_font_face_is_variable) * * `TRUE` if the face has axes that can be modified * to produce variations. */ properties[PROP_VARIABLE] = g_param_spec_boolean ("variable", NULL, NULL, FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); g_object_class_install_properties (object_class, N_PROPERTIES, properties); } static void pango2_font_face_init (Pango2FontFace *face G_GNUC_UNUSED) { } /* }}} */ /* {{{ Private API */ Pango2Font * pango2_font_face_create_font (Pango2FontFace *face, const Pango2FontDescription *desc, float dpi, const Pango2Matrix *ctm) { if (!PANGO2_IS_FONT_FACE (face)) { char *s = pango2_font_description_to_string (desc); #ifdef __linux__ char *bs = get_backtrace (); #else char *bs = g_strdup (""); #endif g_critical ("pango2_font_face_create_font called without a face for %s\n%s", s, bs); g_free (s); g_free (bs); } g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), NULL); return PANGO2_FONT_FACE_GET_CLASS (face)->create_font (face, desc, dpi, ctm); } /*< private > * pango2_font_face_get_faceid: * @self: a `Pango2HbFace` * * Returns the faceid of the face. * * The faceid is meant to uniquely identify the face among the * faces of its family. It includes an identifier for the font * file that is used (currently, we use the PostScript name for * this), the face index, the instance ID, as well as synthetic * tweaks such as emboldening and transforms and variations. * * [method@Pango2.FontFace.describe] adds the faceid to the font * description that it produces. * * See pango2_hb_family_find_face() for the code that takes the * faceid into account when searching for a face. It is careful * to fall back to approximate matching if an exact match for * the faceid isn't found. That should make it safe to preserve * faceids when saving font descriptions in configuration or * other data. * * There are no guarantees about the format of the string that * this function produces, except for that it does not contain * ' ', ',' or '=', so it can be safely embedded in the '@' part * of a serialized font description. * * Returns: (transfer none): the faceid */ const char * pango2_font_face_get_faceid (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), ""); return PANGO2_FONT_FACE_GET_CLASS (face)->get_faceid (face); } /* }}} */ /* {{{ Public API */ /** * pango2_font_face_describe: * @face: a `Pango2FontFace` * * Returns a font description that matches the face. * * The resulting font description will have the family, style, * variant, weight and stretch of the face, but its size field * will be unset. * * Return value: a newly-created `Pango2FontDescription` structure * holding the description of the face. Use [method@Pango2.FontDescription.free] * to free the result. */ Pango2FontDescription * pango2_font_face_describe (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), NULL); if ((pango2_font_description_get_set_fields (face->description) & PANGO2_FONT_MASK_FACEID) == 0) pango2_font_description_set_faceid (face->description, pango2_font_face_get_faceid (face)); return pango2_font_description_copy (face->description); } /** * pango2_font_face_is_synthesized: * @face: a `Pango2FontFace` * * Returns whether a `Pango2FontFace` is synthesized. * * This will be the case if the underlying font rendering engine * creates this face from another face, by shearing, emboldening, * lightening or modifying it in some other way. * * Return value: whether @face is synthesized */ gboolean pango2_font_face_is_synthesized (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), FALSE); if (PANGO2_FONT_FACE_GET_CLASS (face)->is_synthesized != NULL) return PANGO2_FONT_FACE_GET_CLASS (face)->is_synthesized (face); else return FALSE; } /** * pango2_font_face_get_name: * @face: a `Pango2FontFace`. * * Gets a name representing the style of this face. * * Note that a font family may contain multiple faces * with the same name (e.g. a variable and a non-variable * face for the same style). * * Return value: the name for the face. This string is * owned by the face object and must not be modified or freed. */ const char * pango2_font_face_get_name (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), NULL); return face->name; } /** * pango2_font_face_get_family: * @face: a `Pango2FontFace` * * Gets the `Pango2FontFamily` that the face belongs to. * * Returns: (transfer none): the `Pango2FontFamily` */ Pango2FontFamily * pango2_font_face_get_family (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), NULL); return face->family; } /** * pango2_font_face_is_monospace: * @face: a `Pango2FontFace` * * Returns whether this font face is monospace. * * A monospace font is a font designed for text display where the the * characters form a regular grid. * * For Western languages this would mean that the advance width of all * characters are the same, but this categorization also includes Asian * fonts which include double-width characters: characters that occupy * two grid cells. [func@GLib.unichar_iswide] returns a result that * indicates whether a character is typically double-width in a monospace * font. * * The best way to find out the grid-cell size is to call * [method@Pango2.FontMetrics.get_approximate_digit_width], since the * results of [method@Pango2.FontMetrics.get_approximate_char_width] may * be affected by double-width characters. * * Returns: `TRUE` if @face is monospace */ gboolean pango2_font_face_is_monospace (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), FALSE); return PANGO2_FONT_FACE_GET_CLASS (face)->is_monospace (face); } /** * pango2_font_face_is_variable: * @face: a `Pango2FontFace` * * Returns whether this font face is variable. * * A variable font is a font which has axes that can be modified * to produce variations. * * Such axes are also known as _variations_; see * [method@Pango2.FontDescription.set_variations] for more information. * * Returns: `TRUE` if @face is variable */ gboolean pango2_font_face_is_variable (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), FALSE); return PANGO2_FONT_FACE_GET_CLASS (face)->is_variable (face); } /** * pango2_font_face_supports_language: * @face: a `Pango2FontFace` * @language: a `Pango2Language` * * Returns whether the face has all the glyphs necessary to * support this language. * * Returns: `TRUE` if @face supports @language */ gboolean pango2_font_face_supports_language (Pango2FontFace *face, Pango2Language *language) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), FALSE); return PANGO2_FONT_FACE_GET_CLASS (face)->supports_language (face, language); } /** * pango2_font_face_get_languages: * @face: a `Pango2FontFace` * * Returns the languages that are supported by the face. * * If the font backend does not provide this information, * `NULL` is returned. For the fontconfig backend, this * corresponds to the `FC_LANG` member of the `FcPattern`. * * The returned array is only valid as long as the face * and its fontmap are valid. * * Returns: (transfer none) (nullable) (array zero-terminated=1) (element-type Pango2Language): * an array of `Pango2Language` */ Pango2Language ** pango2_font_face_get_languages (Pango2FontFace *face) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), FALSE); return PANGO2_FONT_FACE_GET_CLASS (face)->get_languages (face); } /** * pango2_font_face_has_char: * @face: a `Pango2FontFace` * @wc: a Unicode character * * Returns whether the face provides a glyph for this character. * * Returns: `TRUE` if @font can render @wc */ gboolean pango2_font_face_has_char (Pango2FontFace *face, gunichar wc) { g_return_val_if_fail (PANGO2_IS_FONT_FACE (face), FALSE); return PANGO2_FONT_FACE_GET_CLASS (face)->has_char (face, wc); } /* }}} */ /* vim:set foldmethod=marker expandtab: */