diff options
Diffstat (limited to 'pango2/pango-generic-family.c')
-rw-r--r-- | pango2/pango-generic-family.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/pango2/pango-generic-family.c b/pango2/pango-generic-family.c new file mode 100644 index 00000000..c0697f00 --- /dev/null +++ b/pango2/pango-generic-family.c @@ -0,0 +1,226 @@ +/* Pango2 + * + * Copyright (C) 2022 Matthias Clasen + * + * 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 <gio/gio.h> + +#include "pango-generic-family-private.h" +#include "pango-hbfamily-private.h" +#include "pango-impl-utils.h" +#include "pango-hbface-private.h" +#include "pango-font-private.h" + +/** + * Pango2GenericFamily: + * + * An implementation of `Pango2FontFamily` + * that provides faces from other families. + * + * `Pango2GenericFamily can be used to e.g. assemble a + * generic 'sans-serif' family from a number of other + * font families. + */ + + +/* {{{ GListModel implementation */ + +static GType +pango2_generic_family_get_item_type (GListModel *list) +{ + return PANGO2_TYPE_FONT_FACE; +} + +static guint +pango2_generic_family_get_n_items (GListModel *list) +{ + Pango2GenericFamily *self = PANGO2_GENERIC_FAMILY (list); + guint n; + + n = 0; + for (int i = 0; i < self->families->len; i++) + { + Pango2HbFamily *family = g_ptr_array_index (self->families, i); + + n += g_list_model_get_n_items (G_LIST_MODEL (family)); + } + + return n; +} + +static gpointer +pango2_generic_family_get_item (GListModel *list, + guint position) +{ + Pango2GenericFamily *self = PANGO2_GENERIC_FAMILY (list); + guint pos; + + pos = position; + for (int i = 0; i < self->families->len; i++) + { + Pango2HbFamily *family = g_ptr_array_index (self->families, i); + + if (pos < g_list_model_get_n_items (G_LIST_MODEL (family))) + return g_list_model_get_item (G_LIST_MODEL (family), pos); + + pos -= g_list_model_get_n_items (G_LIST_MODEL (family)); + } + + return NULL; +} + +static void +pango2_generic_family_list_model_init (GListModelInterface *iface) +{ + iface->get_item_type = pango2_generic_family_get_item_type; + iface->get_n_items = pango2_generic_family_get_n_items; + iface->get_item = pango2_generic_family_get_item; +} + +/* }}} */ +/* {{{ Pango2FontFamily implementation */ + +struct _Pango2GenericFamilyClass +{ + Pango2FontFamilyClass parent_class; +}; + +G_DEFINE_FINAL_TYPE_WITH_CODE (Pango2GenericFamily, pango2_generic_family, PANGO2_TYPE_FONT_FAMILY, + G_IMPLEMENT_INTERFACE (G_TYPE_LIST_MODEL, pango2_generic_family_list_model_init)) + +static void +pango2_generic_family_init (Pango2GenericFamily *self) +{ + self->families = g_ptr_array_new_with_free_func (g_object_unref); +} + +static void +pango2_generic_family_finalize (GObject *object) +{ + Pango2GenericFamily *self = PANGO2_GENERIC_FAMILY (object); + + g_ptr_array_unref (self->families); + + G_OBJECT_CLASS (pango2_generic_family_parent_class)->finalize (object); +} + +static void +pango2_generic_family_class_init (Pango2GenericFamilyClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + + object_class->finalize = pango2_generic_family_finalize; +} + +/* }}} */ +/* {{{ Private API */ + +/*< private > + * pango2_generic_family_find_face: + * @family: a `Pango2GenericFamily` + * @description: `Pango2FontDescription` to match + * @language: (nullable): `Pango2Language` to support + * @wc: a Unicode character, or 0 to ignore + * + * Finds the face that best matches the font description while + * also supporting the given language and character, from the first + * family in @family that has any matching faces. + * + * Returns: (transfer none) (nullable): the face + */ +Pango2FontFace * +pango2_generic_family_find_face (Pango2GenericFamily *self, + Pango2FontDescription *description, + Pango2Language *language, + gunichar wc) +{ + Pango2FontFace *face = NULL; + + for (int i = 0; i < self->families->len; i++) + { + Pango2HbFamily *family = g_ptr_array_index (self->families, i); + + face = pango2_hb_family_find_face (family, description, language, wc); + if (face) + break; + } + + /* last resort */ + if (!face && self->families->len > 0) + { + Pango2HbFamily *family = g_ptr_array_index (self->families, 0); + face = g_list_model_get_item (G_LIST_MODEL (family), 0); + g_object_unref (face); + } + + return face; +} + +/* }}} */ +/* {{{ Public API */ + +/** + * pango2_generic_family_new: + * @name: the family name + * + * Creates a new `Pango2GenericFamily`. + * + * A generic family does not contain faces, but will return + * faces from other families that match a given query. + * + * Returns: a newly created `Pango2GenericFamily` + */ +Pango2GenericFamily * +pango2_generic_family_new (const char *name) +{ + Pango2GenericFamily *self; + + g_return_val_if_fail (name != NULL, NULL); + + self = g_object_new (PANGO2_TYPE_GENERIC_FAMILY, NULL); + + pango2_font_family_set_name (PANGO2_FONT_FAMILY (self), name); + + return self; +} + +/** + * pango2_generic_family_add_family: + * @self: a `Pango2GenericFamily` + * @family: (transfer none): a `Pango2FontFamily` to add + * + * Adds a `Pango2FontFamily` to a `Pango2GenericFamily`. + * + * It is an error to call this function more than + * once for the same family. + */ +void +pango2_generic_family_add_family (Pango2GenericFamily *self, + Pango2FontFamily *family) +{ + g_return_if_fail (PANGO2_IS_GENERIC_FAMILY (self)); + g_return_if_fail (PANGO2_IS_FONT_FAMILY (family)); + + g_ptr_array_add (self->families, g_object_ref (family)); +} + +/* }}} */ + +/* vim:set foldmethod=marker expandtab: */ |