[pango/userfont: 7/15] Add PangoUserFace and PangoUserFont
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/userfont: 7/15] Add PangoUserFace and PangoUserFont
- Date: Fri, 28 Jan 2022 14:04:51 +0000 (UTC)
commit 47eb3766394fa5d724596af22f9ffce9ba4a0a6b
Author: Matthias Clasen <mclasen redhat com>
Date: Fri Jan 28 00:12:59 2022 -0500
Add PangoUserFace and PangoUserFont
Move the user font code into its own classes,
and make PangoHbFontMap and friends deal with
both PangoHbFace and PangoUserface.
pango/meson.build | 4 +
pango/pango-generic-family-private.h | 3 +-
pango/pango-generic-family.c | 4 +-
pango/pango-hbface-private.h | 34 +--
pango/pango-hbface.c | 83 +------
pango/pango-hbface.h | 38 ---
pango/pango-hbfamily-private.h | 7 +-
pango/pango-hbfamily.c | 100 +++++---
pango/pango-hbfont-private.h | 20 +-
pango/pango-hbfont.c | 79 +-----
pango/pango-hbfontmap.c | 105 +++++---
pango/pango-hbfontmap.h | 4 +-
pango/pango-userface-private.h | 54 ++++
pango/pango-userface.c | 295 ++++++++++++++++++++++
pango/pango-userface.h | 73 ++++++
pango/pango-userfont-private.h | 39 +++
pango/pango-userfont.c | 470 +++++++++++++++++++++++++++++++++++
pango/pango-userfont.h | 47 ++++
pango/pango.h | 2 +
pango/pangofc-hbfontmap.c | 2 +-
20 files changed, 1170 insertions(+), 293 deletions(-)
---
diff --git a/pango/meson.build b/pango/meson.build
index 3be27319..5cf392ac 100644
--- a/pango/meson.build
+++ b/pango/meson.build
@@ -39,6 +39,8 @@ pango_sources = [
'pango-generic-family.c',
'pango-hbfont.c',
'pango-hbfontmap.c',
+ 'pango-userface.c',
+ 'pango-userfont.c',
]
pango_headers = [
@@ -73,6 +75,8 @@ pango_headers = [
'pango-hbface.h',
'pango-hbfont.h',
'pango-hbfontmap.h',
+ 'pango-userface.h',
+ 'pango-userfont.h',
]
pango_installed_headers = pango_headers + [ 'pango-version-macros.h' ]
diff --git a/pango/pango-generic-family-private.h b/pango/pango-generic-family-private.h
index 4ba8c865..78e17610 100644
--- a/pango/pango-generic-family-private.h
+++ b/pango/pango-generic-family-private.h
@@ -21,7 +21,6 @@
#pragma once
#include "pango-font.h"
-#include "pango-hbface.h"
#include "pango-generic-family.h"
#include "pango-hbfamily-private.h"
@@ -39,7 +38,7 @@ struct _PangoGenericFamily
void pango_generic_family_set_font_map (PangoGenericFamily *self,
PangoFontMap *map);
-PangoHbFace * pango_generic_family_find_face (PangoGenericFamily *self,
+PangoFontFace * pango_generic_family_find_face (PangoGenericFamily *self,
PangoFontDescription *description,
PangoLanguage *language,
gunichar wc);
diff --git a/pango/pango-generic-family.c b/pango/pango-generic-family.c
index ceca7399..fd555eab 100644
--- a/pango/pango-generic-family.c
+++ b/pango/pango-generic-family.c
@@ -133,13 +133,13 @@ pango_generic_family_set_font_map (PangoGenericFamily *self,
*
* Returns: (transfer none) (nullable): the face
*/
-PangoHbFace *
+PangoFontFace *
pango_generic_family_find_face (PangoGenericFamily *self,
PangoFontDescription *description,
PangoLanguage *language,
gunichar wc)
{
- PangoHbFace *face = NULL;
+ PangoFontFace *face = NULL;
for (int i = 0; i < self->families->len; i++)
{
diff --git a/pango/pango-hbface-private.h b/pango/pango-hbface-private.h
index 7899d264..b1118006 100644
--- a/pango/pango-hbface-private.h
+++ b/pango/pango-hbface-private.h
@@ -25,40 +25,40 @@
#include "pango-language-set-private.h"
#include <hb.h>
-typedef struct _PangoUserFontFuncs PangoUserFontFuncs;
-struct _PangoUserFontFuncs
-{
- PangoHbFaceGetFontExtentsFunc font_extents_func;
- PangoHbFaceGetNominalGlyphFunc glyph_func;
- PangoHbFaceGetGlyphAdvanceFunc advance_func;
- PangoHbFaceGetGlyphExtentsFunc glyph_extents_func;
- PangoHbFaceRenderGlyphFunc render_func;
- gpointer user_data;
- GDestroyNotify destroy;
+typedef struct _CommonFace CommonFace;
+struct _CommonFace {
+ PangoFontFace parent_instance;
+
+ PangoFontDescription *description;
+ char *name;
+ PangoFontFamily *family;
+ char *psname;
+ char *faceid;
};
struct _PangoHbFace
{
PangoFontFace parent_instance;
+ PangoFontDescription *description;
+ char *name;
+ PangoFontFamily *family;
+ char *psname;
+ char *faceid;
+
+ /* up to here shared with PangoUserFace */
+
unsigned int index;
int instance_id;
char *file;
hb_face_t *face;
- char *psname;
- char *faceid;
hb_variation_t *variations;
unsigned int n_variations;
- char *name;
- PangoFontFamily *family;
- PangoFontDescription *description;
PangoMatrix *matrix;
double x_scale, y_scale;
PangoLanguageSet *languages;
gboolean embolden;
gboolean synthetic;
-
- PangoUserFontFuncs *user_font;
};
void pango_hb_face_set_family (PangoHbFace *self,
diff --git a/pango/pango-hbface.c b/pango/pango-hbface.c
index ed433129..5adc1061 100644
--- a/pango/pango-hbface.c
+++ b/pango/pango-hbface.c
@@ -216,16 +216,9 @@ ensure_psname (PangoHbFace *self)
if (self->psname)
return;
- if (self->user_font)
- {
- self->psname = g_strconcat (pango_font_description_get_family (self->description), "_", self->name,
NULL);
- }
- else
- {
- ensure_hb_face (self);
+ ensure_hb_face (self);
- self->psname = get_name_from_hb_face (self->face, HB_OT_NAME_ID_POSTSCRIPT_NAME,
HB_OT_NAME_ID_INVALID);
- }
+ self->psname = get_name_from_hb_face (self->face, HB_OT_NAME_ID_POSTSCRIPT_NAME, HB_OT_NAME_ID_INVALID);
/* PostScript name should not contain problematic chars, but just in case,
* make sure we don't have any ' ', '=' or ',' that would give us parsing
@@ -302,13 +295,6 @@ pango_hb_face_finalize (GObject *object)
if (self->matrix)
g_free (self->matrix);
- if (self->user_font)
- {
- if (self->user_font->destroy)
- self->user_font->destroy (self->user_font->user_data);
- g_free (self->user_font);
- }
-
G_OBJECT_CLASS (pango_hb_face_parent_class)->finalize (object);
}
@@ -352,9 +338,6 @@ pango_hb_face_is_monospace (PangoFontFace *face)
{
PangoHbFace *self = PANGO_HB_FACE (face);
- if (self->user_font)
- return FALSE;
-
ensure_hb_face (self);
return hb_face_is_monospace (self->face);
@@ -365,9 +348,6 @@ pango_hb_face_is_variable (PangoFontFace *face)
{
PangoHbFace *self = PANGO_HB_FACE (face);
- if (self->user_font)
- return FALSE;
-
/* We don't consider named instances as variable, i.e.
* a font chooser UI should not expose axes for them.
*
@@ -519,9 +499,6 @@ pango_hb_face_has_char (PangoHbFace *self,
hb_codepoint_t glyph;
gboolean ret;
- if (self->user_font)
- return self->user_font->glyph_func (self, wc, &glyph, self->user_font->user_data);
-
ensure_hb_face (self);
hb_font = hb_font_create (self->face);
@@ -893,62 +870,6 @@ pango_hb_face_new_instance (PangoHbFace *face,
return self;
}
-/**
- * pango_hb_face_new_user:
- * @font_extents_func: the `PangoHbFaceGetFontExtentsFunc`
- * @glyph_func: the `PangoHbFaceGetNominalGlyphFunc`
- * @advance_func: the `PangoHbFaceGetGlyphAdvanceFunc`
- * @glyph_extents_func: the `PangoHbFaceGetGlyphExtentsFunc`
- * @render_func: the `PangoHbFaceRenderGlyphFunc`
- * @user_data: user data that will be assed to the callbacks
- * @destroy: destroy notify for @user_data
- * @name: name for the face
- * @description: (nullable): `PangoFontDescription` for the font
- *
- * Creates a new user font face.
- *
- * A user font face does not rely on font data from a font file,
- * but instead uses callbacks to determine glyph extents, positions
- * and rendering.
- *
- * Returns: (transfer full): a newly created `PangoHbFace`
- *
- * Since: 1.52
- */
-PangoHbFace *
-pango_hb_face_new_user (PangoHbFaceGetFontExtentsFunc font_extents_func,
- PangoHbFaceGetNominalGlyphFunc glyph_func,
- PangoHbFaceGetGlyphAdvanceFunc advance_func,
- PangoHbFaceGetGlyphExtentsFunc glyph_extents_func,
- PangoHbFaceRenderGlyphFunc render_func,
- gpointer user_data,
- GDestroyNotify destroy,
- const char *name,
- const PangoFontDescription *description)
-{
- PangoHbFace *self;
-
- self = g_object_new (PANGO_TYPE_HB_FACE, NULL);
-
- self->user_font = g_new0 (PangoUserFontFuncs, 1);
-
- self->user_font->font_extents_func = font_extents_func;
- self->user_font->glyph_func = glyph_func;
- self->user_font->advance_func = advance_func;
- self->user_font->glyph_extents_func = glyph_extents_func,
- self->user_font->render_func = render_func;
- self->user_font->user_data = user_data;
- self->user_font->destroy = destroy;
-
- self->synthetic = TRUE;
-
- self->name = g_strdup (name);
- self->description = pango_font_description_copy (description);
- self->languages = PANGO_LANGUAGE_SET (pango_language_set_simple_new ());
-
- return self;
-}
-
/**
* pango_hb_face_get_hb_face:
* @self: a `PangoHbFace`
diff --git a/pango/pango-hbface.h b/pango/pango-hbface.h
index 9d428f8c..04cac041 100644
--- a/pango/pango-hbface.h
+++ b/pango/pango-hbface.h
@@ -59,44 +59,6 @@ PangoHbFace * pango_hb_face_new_instance (PangoHbFace *fac
const char *name,
const PangoFontDescription *description);
-typedef void (* PangoHbFaceGetFontExtentsFunc) (PangoHbFace *face,
- int size,
- hb_font_extents_t *extents,
- gpointer user_data);
-
-typedef gboolean (* PangoHbFaceGetNominalGlyphFunc) (PangoHbFace *face,
- hb_codepoint_t unicode,
- hb_codepoint_t *glyph,
- gpointer user_data);
-
-typedef hb_position_t (* PangoHbFaceGetGlyphAdvanceFunc) (PangoHbFace *face,
- int size,
- hb_codepoint_t glyph,
- gpointer user_data);
-
-typedef gboolean (* PangoHbFaceGetGlyphExtentsFunc) (PangoHbFace *face,
- int size,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- gpointer user_data);
-
-typedef void (* PangoHbFaceRenderGlyphFunc) (PangoHbFace *face,
- int size,
- hb_codepoint_t glyph,
- gpointer user_data,
- gpointer backend_data);
-
-PANGO_AVAILABLE_IN_1_52
-PangoHbFace * pango_hb_face_new_user (PangoHbFaceGetFontExtentsFunc font_extents_func,
- PangoHbFaceGetNominalGlyphFunc glyph_func,
- PangoHbFaceGetGlyphAdvanceFunc advance_func,
- PangoHbFaceGetGlyphExtentsFunc glyph_extents_func,
- PangoHbFaceRenderGlyphFunc render_glyph,
- gpointer user_data,
- GDestroyNotify destroy,
- const char *name,
- const PangoFontDescription *description);
-
PANGO_AVAILABLE_IN_1_52
hb_face_t * pango_hb_face_get_hb_face (PangoHbFace *self);
diff --git a/pango/pango-hbfamily-private.h b/pango/pango-hbfamily-private.h
index 7b1dfa9a..40f9232a 100644
--- a/pango/pango-hbfamily-private.h
+++ b/pango/pango-hbfamily-private.h
@@ -21,7 +21,6 @@
#pragma once
#include "pango-font.h"
-#include "pango-hbface.h"
#define PANGO_TYPE_HB_FAMILY (pango_hb_family_get_type ())
@@ -44,12 +43,12 @@ void pango_hb_family_set_font_map (PangoHbFamily
PangoFontMap *map);
void pango_hb_family_add_face (PangoHbFamily *self,
- PangoHbFace *face);
+ PangoFontFace *face);
void pango_hb_family_remove_face (PangoHbFamily *self,
- PangoHbFace *face);
+ PangoFontFace *face);
-PangoHbFace * pango_hb_family_find_face (PangoHbFamily *self,
+PangoFontFace * pango_hb_family_find_face (PangoHbFamily *self,
PangoFontDescription *description,
PangoLanguage *language,
gunichar wc);
diff --git a/pango/pango-hbfamily.c b/pango/pango-hbfamily.c
index 814ec5f8..ebed6200 100644
--- a/pango/pango-hbfamily.c
+++ b/pango/pango-hbfamily.c
@@ -25,6 +25,7 @@
#include "pango-hbfamily-private.h"
#include "pango-impl-utils.h"
#include "pango-hbface-private.h"
+#include "pango-userface-private.h"
#include "pango-font-private.h"
/* {{{ GListModel implementation */
@@ -45,7 +46,7 @@ pango_hb_family_get_n_items (GListModel *list)
static gpointer
pango_hb_family_get_item (GListModel *list,
- guint position)
+ guint position)
{
PangoHbFamily *self = PANGO_HB_FAMILY (list);
@@ -66,28 +67,59 @@ pango_hb_family_list_model_init (GListModelInterface *iface)
/* }}} */
/* {{{ Utilities */
+static void
+face_set_family (PangoFontFace *face,
+ PangoFontFamily *family)
+{
+ if (PANGO_IS_HB_FACE (face))
+ pango_hb_face_set_family (PANGO_HB_FACE (face), family);
+ else
+ pango_user_face_set_family (PANGO_USER_FACE (face), family);
+}
+
+static const char *
+face_get_faceid (PangoFontFace *face)
+{
+ if (PANGO_IS_HB_FACE (face))
+ return pango_hb_face_get_faceid (PANGO_HB_FACE (face));
+ else
+ return pango_user_face_get_faceid (PANGO_USER_FACE (face));
+}
+
+static gboolean
+face_has_char (PangoFontFace *face,
+ gunichar wc)
+{
+ if (PANGO_IS_HB_FACE (face))
+ return pango_hb_face_has_char (PANGO_HB_FACE (face), wc);
+ else
+ return pango_user_face_has_char (PANGO_USER_FACE (face), wc);
+}
+
static int
-sort_face_func (PangoHbFace *face1,
- PangoHbFace *face2)
+sort_face_func (PangoFontFace *face1,
+ PangoFontFace *face2)
{
+ CommonFace *cf1 = (CommonFace *)face1;
+ CommonFace *cf2 = (CommonFace *)face2;
int a, b;
- a = pango_font_description_get_style (face1->description);
- b = pango_font_description_get_style (face2->description);
+ a = pango_font_description_get_style (cf1->description);
+ b = pango_font_description_get_style (cf2->description);
if (a != b)
return a - b;
- a = pango_font_description_get_weight (face1->description);
- b = pango_font_description_get_weight (face2->description);
+ a = pango_font_description_get_weight (cf1->description);
+ b = pango_font_description_get_weight (cf2->description);
if (a != b)
return a - b;
- a = pango_font_description_get_stretch (face1->description);
- b = pango_font_description_get_stretch (face2->description);
+ a = pango_font_description_get_stretch (cf1->description);
+ b = pango_font_description_get_stretch (cf2->description);
if (a != b)
return a - b;
- return strcmp (face1->name, face2->name);
+ return strcmp (cf1->name, cf2->name);
}
/* return 2 if face is a named instance,
@@ -95,11 +127,11 @@ sort_face_func (PangoHbFace *face1,
* 0 otherwise
*/
static int
-hb_face_get_variableness (PangoHbFace *face)
+face_get_variableness (PangoFontFace *face)
{
if (pango_font_face_is_variable (PANGO_FONT_FACE (face)))
{
- if (face->instance_id != -1)
+ if (PANGO_HB_FACE (face)->instance_id != -1)
return 2;
else
return 1;
@@ -250,7 +282,7 @@ pango_hb_family_new (const char *name)
* @map: (nullable): a `PangoFontMap`
*
* Sets the map of @self.
- */
+ G*/
void
pango_hb_family_set_font_map (PangoHbFamily *self,
PangoFontMap *map)
@@ -278,21 +310,24 @@ pango_hb_family_set_font_map (PangoHbFamily *self,
*/
void
pango_hb_family_add_face (PangoHbFamily *self,
- PangoHbFace *face)
+ PangoFontFace *face)
{
int position;
+ g_return_if_fail (PANGO_IS_HB_FACE (face) || PANGO_IS_USER_FACE (face));
+
position = 0;
while (position < self->faces->len)
{
- PangoHbFace *f = g_ptr_array_index (self->faces, position);
+ PangoFontFace *f = g_ptr_array_index (self->faces, position);
if (sort_face_func (face, f) < 0)
break;
position++;
}
g_ptr_array_insert (self->faces, position, face);
- pango_hb_face_set_family (face, PANGO_FONT_FAMILY (self));
+
+ face_set_family (face, PANGO_FONT_FAMILY (self));
g_list_model_items_changed (G_LIST_MODEL (self), position, 0, 1);
}
@@ -300,20 +335,23 @@ pango_hb_family_add_face (PangoHbFamily *self,
/*< private >
* pango_hb_family_remove_face:
* @self: a `PangoHbFamily`
- * @face: a `PangoHbFace`
+ * @face: a `PangoFontFace`
*
* Remove a `PangoFontFace` from a `PangoHbFamily`.
*/
void
pango_hb_family_remove_face (PangoHbFamily *self,
- PangoHbFace *face)
+ PangoFontFace *face)
{
unsigned int position;
+ g_return_if_fail (PANGO_IS_HB_FACE (face) || PANGO_IS_USER_FACE (face));
+
if (!g_ptr_array_find (self->faces, face, &position))
return;
- pango_hb_face_set_family (face, NULL);
+ face_set_family (face, NULL);
+
g_ptr_array_remove_index (self->faces, position);
g_list_model_items_changed (G_LIST_MODEL (self), position, 1, 0);
@@ -335,47 +373,49 @@ pango_hb_family_remove_face (PangoHbFamily *self,
*
* Returns: (transfer none) (nullable): the face
*/
-PangoHbFace *
+PangoFontFace *
pango_hb_family_find_face (PangoHbFamily *family,
PangoFontDescription *description,
PangoLanguage *language,
gunichar wc)
{
- PangoHbFace *face = NULL;
+ PangoFontFace *face = NULL;
int best_distance = G_MAXINT;
int best_variableness = 0;
/* First look for an exact match if the description has a faceid */
if (pango_font_description_get_set_fields (description) & PANGO_FONT_MASK_FACEID)
{
+ const char *faceid = pango_font_description_get_faceid (description);
+
for (int i = 0; i < family->faces->len; i++)
{
- PangoHbFace *face2 = g_ptr_array_index (family->faces, i);
+ PangoFontFace *face2 = g_ptr_array_index (family->faces, i);
+ const char *faceid2 = face_get_faceid (face2);
- if (g_strcmp0 (pango_font_description_get_faceid (description),
- pango_hb_face_get_faceid (face2)) == 0)
+ if (g_strcmp0 (faceid, faceid2) == 0)
return face2;
}
}
for (int i = 0; i < family->faces->len; i++)
{
- PangoHbFace *face2 = g_ptr_array_index (family->faces, i);
+ PangoFontFace *face2 = g_ptr_array_index (family->faces, i);
int distance;
int variableness;
- if (language && !pango_font_face_supports_language (PANGO_FONT_FACE (face2), language))
+ if (language && !pango_font_face_supports_language (face2, language))
continue;
- if (wc && !pango_hb_face_has_char (face2, wc))
+ if (wc && !face_has_char (face2, wc))
continue;
- if (!pango_font_description_is_similar (description, face2->description))
+ if (!pango_font_description_is_similar (description, ((CommonFace *)face2)->description))
continue;
- distance = pango_font_description_compute_distance (description, face2->description);
+ distance = pango_font_description_compute_distance (description, ((CommonFace *)face2)->description);
- variableness = hb_face_get_variableness (face2);
+ variableness = face_get_variableness (PANGO_FONT_FACE (face2));
if (distance < best_distance ||
(distance == best_distance && variableness > best_variableness))
{
diff --git a/pango/pango-hbfont-private.h b/pango/pango-hbfont-private.h
index 6c929099..e24f8889 100644
--- a/pango/pango-hbfont-private.h
+++ b/pango/pango-hbfont-private.h
@@ -38,19 +38,33 @@ struct _HexBoxInfo
double box_height;
};
+typedef struct _CommonFont CommonFont;
+struct _CommonFont
+{
+ PangoFont parent_instance;
+
+ int size;
+ float dpi;
+ PangoGravity gravity;
+ PangoMatrix matrix;
+};
+
struct _PangoHbFont
{
PangoFont parent_instance;
- PangoHbFace *face;
int size; /* point size, scaled by PANGO_SCALE */
float dpi;
+ PangoGravity gravity;
+ PangoMatrix matrix;
+
+ /* up to here shared with PangoUserFont */
+
+ PangoHbFace *face;
hb_feature_t *features;
unsigned int n_features;
hb_variation_t *variations;
unsigned int n_variations;
- PangoGravity gravity;
- PangoMatrix matrix;
HexBoxInfo *hex_box_info;
PangoLanguage *approximate_char_lang;
diff --git a/pango/pango-hbfont.c b/pango/pango-hbfont.c
index cb6f7d9b..916c466e 100644
--- a/pango/pango-hbfont.c
+++ b/pango/pango-hbfont.c
@@ -812,57 +812,6 @@ pango_hb_font_get_metrics (PangoFont *font,
return metrics;
}
-static hb_bool_t
-nominal_glyph_func (hb_font_t *font, void *font_data,
- hb_codepoint_t unicode,
- hb_codepoint_t *glyph,
- void *user_data)
-{
- PangoHbFont *self = font_data;
- PangoUserFontFuncs *user_font = self->face->user_font;
-
- return user_font->glyph_func (self->face, unicode, glyph, user_font->user_data);
-}
-
-static hb_position_t
-glyph_h_advance_func (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- void *user_data)
-{
- PangoHbFont *self = font_data;
- PangoUserFontFuncs *user_font = self->face->user_font;
- int size = self->size * self->dpi / 72.;
-
- return user_font->advance_func (self->face, size, glyph, user_font->user_data);
-}
-
-static hb_bool_t
-glyph_extents_func (hb_font_t *font, void *font_data,
- hb_codepoint_t glyph,
- hb_glyph_extents_t *extents,
- void *user_data)
-{
- PangoHbFont *self = font_data;
- PangoUserFontFuncs *user_font = self->face->user_font;
- int size = self->size * self->dpi / 72.;
-
- return user_font->glyph_extents_func (self->face, size, glyph, extents, user_font->user_data);
-}
-
-static hb_bool_t
-font_extents_func (hb_font_t *font, void *font_data,
- hb_font_extents_t *extents,
- void *user_data)
-{
- PangoHbFont *self = font_data;
- PangoUserFontFuncs *user_font = self->face->user_font;
- int size = self->size * self->dpi / 72.;
-
- user_font->font_extents_func (self->face, size, extents, user_font->user_data);
-
- return TRUE;
-}
-
static hb_font_t *
pango_hb_font_create_hb_font (PangoFont *font)
{
@@ -874,33 +823,7 @@ pango_hb_font_create_hb_font (PangoFont *font)
float *coords;
int size;
- if (self->face->user_font)
- {
- hb_blob_t *blob;
- hb_face_t *face;
- hb_font_funcs_t *funcs;
-
- blob = hb_blob_create ("", 0, HB_MEMORY_MODE_READONLY, NULL, NULL);
- face = hb_face_create (blob, 0);
- hb_font = hb_font_create (face);
-
- funcs = hb_font_funcs_create ();
-
- hb_font_funcs_set_nominal_glyph_func (funcs, nominal_glyph_func, NULL, NULL);
- hb_font_funcs_set_glyph_h_advance_func (funcs, glyph_h_advance_func, NULL, NULL);
- hb_font_funcs_set_glyph_extents_func (funcs, glyph_extents_func, NULL, NULL);
- hb_font_funcs_set_font_h_extents_func (funcs, font_extents_func, NULL, NULL);
-
- hb_font_set_funcs (hb_font, funcs, self, NULL);
-
- hb_font_funcs_destroy (funcs);
- hb_face_destroy (face);
- hb_blob_destroy (blob);
- }
- else
- {
- hb_font = hb_font_create (pango_hb_face_get_hb_face (self->face));
- }
+ hb_font = hb_font_create (pango_hb_face_get_hb_face (self->face));
size = self->size * self->dpi / 72.f;
x_scale = self->face->x_scale;
diff --git a/pango/pango-hbfontmap.c b/pango/pango-hbfontmap.c
index cfe486bc..4bc6d59a 100644
--- a/pango/pango-hbfontmap.c
+++ b/pango/pango-hbfontmap.c
@@ -28,6 +28,8 @@
#include "pango-generic-family-private.h"
#include "pango-hbface-private.h"
#include "pango-hbfont-private.h"
+#include "pango-userface-private.h"
+#include "pango-userfont-private.h"
#include "pango-fontset.h"
#include "pango-trace-private.h"
#include "pango-context.h"
@@ -152,6 +154,18 @@ pango_fontset_cached_finalize (GObject *object)
G_OBJECT_CLASS (pango_fontset_cached_parent_class)->finalize (object);
}
+static PangoFont *
+font_new_for_description (PangoFontFace *face,
+ const PangoFontDescription *description,
+ float dpi,
+ const PangoMatrix *matrix)
+{
+ if (PANGO_IS_HB_FACE (face))
+ return PANGO_FONT (pango_hb_font_new_for_description (PANGO_HB_FACE (face), description, dpi, matrix));
+ else
+ return PANGO_FONT (pango_user_font_new_for_description (PANGO_USER_FACE (face), description, dpi,
matrix));
+}
+
static PangoFont *
pango_fontset_cached_get_font (PangoFontset *fontset,
guint wc)
@@ -180,7 +194,7 @@ pango_fontset_cached_get_font (PangoFontset *fontset,
else if (PANGO_IS_GENERIC_FAMILY (item))
{
PangoGenericFamily *family = PANGO_GENERIC_FAMILY (item);
- PangoHbFace *face;
+ PangoFontFace *face;
/* Here is where we implement delayed picking for generic families.
* If a face does not cover the character and its family is generic,
@@ -192,10 +206,10 @@ pango_fontset_cached_get_font (PangoFontset *fontset,
wc);
if (face)
{
- retval = PANGO_FONT (pango_hb_font_new_for_description (face,
- self->description,
- self->dpi,
- self->matrix));
+ retval = font_new_for_description (face,
+ self->description,
+ self->dpi,
+ self->matrix);
break;
}
}
@@ -214,12 +228,12 @@ pango_fontset_cached_get_first_font (PangoFontsetCached *self)
item = g_ptr_array_index (self->items, 0);
- if (PANGO_IS_HB_FONT (item))
+ if (PANGO_IS_FONT (item))
return g_object_ref (PANGO_FONT (item));
else if (PANGO_IS_GENERIC_FAMILY (item))
{
- PangoHbFace *face = pango_generic_family_find_face (PANGO_GENERIC_FAMILY (item), self->description,
self->language, 0);
- return PANGO_FONT (pango_hb_font_new_for_description (face, self->description, self->dpi,
self->matrix));
+ PangoFontFace *face = pango_generic_family_find_face (PANGO_GENERIC_FAMILY (item), self->description,
self->language, 0);
+ return font_new_for_description (face, self->description, self->dpi, self->matrix);
}
return NULL;
@@ -265,12 +279,12 @@ pango_fontset_cached_foreach (PangoFontset *fontset,
gpointer item = g_ptr_array_index (self->items, i);
PangoFont *font = NULL;
- if (PANGO_IS_HB_FONT (item))
+ if (PANGO_IS_FONT (item))
font = g_object_ref (PANGO_FONT (item));
else if (PANGO_IS_GENERIC_FAMILY (item))
{
- PangoHbFace *face = pango_generic_family_find_face (PANGO_GENERIC_FAMILY (item),
self->description, self->language, 0);
- font = PANGO_FONT (pango_hb_font_new_for_description (face, self->description, self->dpi,
self->matrix));
+ PangoFontFace *face = pango_generic_family_find_face (PANGO_GENERIC_FAMILY (item),
self->description, self->language, 0);
+ font = font_new_for_description (face, self->description, self->dpi, self->matrix);
}
if ((*func) (fontset, font, data))
@@ -315,13 +329,20 @@ pango_fontset_cached_new (const PangoFontDescription *description,
static void
pango_fontset_cached_add_face (PangoFontsetCached *self,
- PangoHbFace *face)
+ PangoFontFace *face)
{
- g_ptr_array_add (self->items,
- pango_hb_font_new_for_description (face,
- self->description,
- self->dpi,
- self->matrix));
+ if (PANGO_IS_HB_FACE (face))
+ g_ptr_array_add (self->items,
+ pango_hb_font_new_for_description (PANGO_HB_FACE (face),
+ self->description,
+ self->dpi,
+ self->matrix));
+ else
+ g_ptr_array_add (self->items,
+ pango_user_font_new_for_description (PANGO_USER_FACE (face),
+ self->description,
+ self->dpi,
+ self->matrix));
}
static void
@@ -446,17 +467,18 @@ add_style_variation (PangoHbFamily *family,
{
PangoMatrix italic_matrix = { 1, 0.2, 0, 1, 0, 0 };
PangoFontDescription *desc;
+ PangoHbFace *variation;
desc = pango_font_description_new ();
pango_font_description_set_style (desc, style);
pango_font_description_set_weight (desc, weight);
- pango_hb_family_add_face (family,
- pango_hb_face_new_synthetic (face,
- style == PANGO_STYLE_ITALIC ? &italic_matrix : NULL,
- weight == PANGO_WEIGHT_BOLD,
- NULL,
- desc));
+ variation = pango_hb_face_new_synthetic (face,
+ style == PANGO_STYLE_ITALIC ? &italic_matrix : NULL,
+ weight == PANGO_WEIGHT_BOLD,
+ NULL,
+ desc);
+ pango_hb_family_add_face (family, PANGO_FONT_FACE (variation));
pango_font_description_free (desc);
}
@@ -481,6 +503,9 @@ synthesize_bold_and_italic_faces (PangoHbFontMap *map)
PangoStyle style;
int dist;
+ if (!PANGO_IS_HB_FACE (face))
+ continue;
+
weight = pango_font_description_get_weight (face->description);
style = pango_font_description_get_style (face->description);
@@ -528,7 +553,7 @@ synthesize_bold_and_italic_faces (PangoHbFontMap *map)
}
}
- /* }}} */
+/* }}} */
/* {{{ PangoFontMap implementation */
G_DEFINE_TYPE_WITH_CODE (PangoHbFontMap, pango_hb_font_map, PANGO_TYPE_FONT_MAP,
@@ -609,7 +634,7 @@ pango_hb_font_map_load_fontset (PangoFontMap *map,
char **families;
PangoFontDescription *copy;
PangoFontFamily *family;
- PangoHbFace *face;
+ PangoFontFace *face;
gboolean has_generic = FALSE;
gint64 before G_GNUC_UNUSED;
@@ -798,7 +823,7 @@ pango_hb_font_map_repopulate (PangoHbFontMap *self,
for (int i = 0; i < self->added_faces->len; i++)
{
- PangoHbFace *face = PANGO_HB_FACE (g_ptr_array_index (self->added_faces, i));
+ PangoFontFace *face = g_ptr_array_index (self->added_faces, i);
pango_hb_font_map_add_face (self, face);
}
@@ -837,7 +862,7 @@ pango_hb_font_map_new (void)
/**
* pango_hb_font_map_add_face:
* @self: a `PangoHbFontMap`
- * @face: (transfer full): a `PangoHbFace`
+ * @face: (transfer full): a `PangoFontFace`
*
* Adds @face to the `PangoHbFontMap`.
*
@@ -848,20 +873,28 @@ pango_hb_font_map_new (void)
*/
void
pango_hb_font_map_add_face (PangoHbFontMap *self,
- PangoHbFace *face)
+ PangoFontFace *face)
{
PangoFontMap *map = PANGO_FONT_MAP (self);
const char *family_name;
PangoHbFamily *family;
+ const PangoFontDescription *description;
+
+ g_return_if_fail (PANGO_IS_HB_FACE (face) || PANGO_IS_USER_FACE (face));
- if (pango_font_description_get_set_fields (face->description) &
+ if (PANGO_IS_HB_FACE (face))
+ description = PANGO_HB_FACE (face)->description;
+ else
+ description = PANGO_USER_FACE (face)->description;
+
+ if (pango_font_description_get_set_fields (description) &
(PANGO_FONT_MASK_VARIANT | PANGO_FONT_MASK_GRAVITY))
- g_warning ("Font description for PangoHbFace includes things that it shouldn't");
+ g_warning ("Font description for PangoFontFace includes things that it shouldn't");
if (!self->in_populate)
g_ptr_array_add (self->added_faces, g_object_ref (face));
- family_name = pango_font_description_get_family (face->description);
+ family_name = pango_font_description_get_family (description);
family = PANGO_HB_FAMILY (pango_font_map_get_family (map, family_name));
if (!family)
{
@@ -879,7 +912,7 @@ pango_hb_font_map_add_face (PangoHbFontMap *self,
/**
* pango_hb_font_map_remove_face:
* @self: a `PangoHbFontMap`
- * @face: a `PangoHbFace` that belongs to @map
+ * @face: a `PangoFontFace` that belongs to @map
*
* Removes @face from the `PangoHbFontMap`.
*
@@ -889,15 +922,17 @@ pango_hb_font_map_add_face (PangoHbFontMap *self,
*/
void
pango_hb_font_map_remove_face (PangoHbFontMap *self,
- PangoHbFace *face)
+ PangoFontFace *face)
{
PangoHbFamily *family;
unsigned int position;
+ g_return_if_fail (PANGO_IS_HB_FACE (face) || PANGO_IS_USER_FACE (face));
+
if (!g_ptr_array_find (self->added_faces, face, &position))
return;
- family = PANGO_HB_FAMILY (pango_font_face_get_family (PANGO_FONT_FACE (face)));
+ family = PANGO_HB_FAMILY (pango_font_face_get_family (face));
pango_hb_family_remove_face (family, face);
@@ -930,7 +965,7 @@ pango_hb_font_map_add_file (PangoHbFontMap *self,
PangoHbFace *face;
face = pango_hb_face_new_from_file (file, 0, -1, NULL, NULL);
- pango_hb_font_map_add_face (self, face);
+ pango_hb_font_map_add_face (self, PANGO_FONT_FACE (face));
}
/**
diff --git a/pango/pango-hbfontmap.h b/pango/pango-hbfontmap.h
index 3ced207d..6fab53a0 100644
--- a/pango/pango-hbfontmap.h
+++ b/pango/pango-hbfontmap.h
@@ -40,11 +40,11 @@ void pango_hb_font_map_add_file (PangoHbFontMap
PANGO_AVAILABLE_IN_1_52
void pango_hb_font_map_add_face (PangoHbFontMap *self,
- PangoHbFace *face);
+ PangoFontFace *face);
PANGO_AVAILABLE_IN_1_52
void pango_hb_font_map_remove_face (PangoHbFontMap *self,
- PangoHbFace *face);
+ PangoFontFace *face);
PANGO_AVAILABLE_IN_1_52
void pango_hb_font_map_add_family (PangoHbFontMap *self,
diff --git a/pango/pango-userface-private.h b/pango/pango-userface-private.h
new file mode 100644
index 00000000..3bbb8dd3
--- /dev/null
+++ b/pango/pango-userface-private.h
@@ -0,0 +1,54 @@
+/* Pango
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "pango-userface.h"
+#include "pango-fontmap.h"
+#include <hb.h>
+
+struct _PangoUserFace
+{
+ PangoFontFace parent_instance;
+
+ PangoFontDescription *description;
+ char *name;
+ PangoFontFamily *family;
+ char *psname;
+ char *faceid;
+
+ /* up to here shared with PangoHbFace */
+
+ PangoUserFaceGetFontExtentsFunc font_extents_func;
+ PangoUserFaceGetNominalGlyphFunc glyph_func;
+ PangoUserFaceGetGlyphAdvanceFunc advance_func;
+ PangoUserFaceGetGlyphExtentsFunc glyph_extents_func;
+ PangoUserFaceRenderGlyphFunc render_func;
+ gpointer user_data;
+ GDestroyNotify destroy;
+};
+
+void pango_user_face_set_family (PangoUserFace *self,
+ PangoFontFamily *family);
+
+gboolean pango_user_face_has_char (PangoUserFace *self,
+ gunichar wc);
+
+const char * pango_user_face_get_faceid (PangoUserFace *self);
diff --git a/pango/pango-userface.c b/pango/pango-userface.c
new file mode 100644
index 00000000..fcf3fa55
--- /dev/null
+++ b/pango/pango-userface.c
@@ -0,0 +1,295 @@
+/* Pango
+ *
+ * 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 "pango-font-private.h"
+#include "pango-userface-private.h"
+
+#include <string.h>
+#include <hb-ot.h>
+
+/**
+ * PangoUserFace:
+ *
+ * `PangoUserFace` is a `PangoFontFace` implementation that uses callbacks.
+ */
+
+ /* {{{ Utilities */
+
+static void
+ensure_psname (PangoUserFace *self)
+{
+ char *p;
+
+ if (self->psname)
+ return;
+
+ self->psname = g_strconcat (pango_font_description_get_family (self->description), "_", self->name, NULL);
+
+ /* PostScript name should not contain problematic chars, but just in case,
+ * make sure we don't have any ' ', '=' or ',' that would give us parsing
+ * problems.
+ */
+ p = self->psname;
+ while ((p = strpbrk (p, " =,")) != NULL)
+ *p = '?';
+}
+
+static const char *
+style_from_font_description (const PangoFontDescription *desc)
+{
+ PangoStyle style = pango_font_description_get_style (desc);
+ PangoWeight weight = pango_font_description_get_weight (desc);
+
+ switch (style)
+ {
+ case PANGO_STYLE_ITALIC:
+ if (weight == PANGO_WEIGHT_BOLD)
+ return "Bold Italic";
+ else
+ return "Italic";
+ break;
+ case PANGO_STYLE_OBLIQUE:
+ if (weight == PANGO_WEIGHT_BOLD)
+ return "Bold Oblique";
+ else
+ return "Oblique";
+ break;
+ case PANGO_STYLE_NORMAL:
+ if (weight == PANGO_WEIGHT_BOLD)
+ return "Bold";
+ else
+ return "Regular";
+ break;
+ default: ;
+ }
+
+ return NULL;
+}
+
+/* }}} */
+/* {{{ PangoFontFace implementation */
+
+struct _PangoUserFaceClass
+{
+ PangoFontFaceClass parent_class;
+};
+
+G_DEFINE_TYPE (PangoUserFace, pango_user_face, PANGO_TYPE_FONT_FACE)
+
+static void
+pango_user_face_init (PangoUserFace *self)
+{
+}
+
+static void
+pango_user_face_finalize (GObject *object)
+{
+ PangoUserFace *self = PANGO_USER_FACE (object);
+
+ pango_font_description_free (self->description);
+ g_free (self->name);
+ g_free (self->faceid);
+ if (self->destroy)
+ self->destroy (self->user_data);
+
+ G_OBJECT_CLASS (pango_user_face_parent_class)->finalize (object);
+}
+
+static const char *
+pango_user_face_get_face_name (PangoFontFace *face)
+{
+ PangoUserFace *self = PANGO_USER_FACE (face);
+
+ return self->name;
+}
+
+static PangoFontDescription *
+pango_user_face_describe (PangoFontFace *face)
+{
+ PangoUserFace *self = PANGO_USER_FACE (face);
+
+ if ((pango_font_description_get_set_fields (self->description) & PANGO_FONT_MASK_FACEID) == 0)
+ pango_font_description_set_faceid (self->description, pango_user_face_get_faceid (self));
+
+ return pango_font_description_copy (self->description);
+}
+
+static PangoFontFamily *
+pango_user_face_get_family (PangoFontFace *face)
+{
+ PangoUserFace *self = PANGO_USER_FACE (face);
+
+ return self->family;
+}
+
+static gboolean
+pango_user_face_is_synthesized (PangoFontFace *face)
+{
+ return TRUE;
+}
+
+static gboolean
+pango_user_face_is_monospace (PangoFontFace *face)
+{
+ return FALSE;
+}
+
+static gboolean
+pango_user_face_is_variable (PangoFontFace *face)
+{
+ return FALSE;
+}
+
+static void
+pango_user_face_class_init (PangoUserFaceClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontFaceClass *face_class = PANGO_FONT_FACE_CLASS (class);
+
+ object_class->finalize = pango_user_face_finalize;
+
+ face_class->get_face_name = pango_user_face_get_face_name;
+ face_class->describe = pango_user_face_describe;
+ face_class->list_sizes = NULL;
+ face_class->is_synthesized = pango_user_face_is_synthesized;
+ face_class->get_family = pango_user_face_get_family;
+ face_class->is_monospace = pango_user_face_is_monospace;
+ face_class->is_variable = pango_user_face_is_variable;
+}
+
+/* }}} */
+/* {{{ Private API */
+
+/*< private >
+ * pango_user_face_set_family:
+ * @self: a `PangoUserFace`
+ * @family: a `PangoFontFamily`
+ *
+ * Sets the font family of a `PangoUserFace`.
+ *
+ * This should only be called by fontmap implementations.
+ */
+void
+pango_user_face_set_family (PangoUserFace *self,
+ PangoFontFamily *family)
+{
+ self->family = family;
+}
+
+/*< private >
+ * pango_user_face_has_char:
+ * @self: a `PangoUserFace`
+ * @wc: a Unicode character
+ *
+ * Returns whether the face provides a glyph for this character.
+ *
+ * Returns: `TRUE` if @font can render @wc
+ */
+gboolean
+pango_user_face_has_char (PangoUserFace *self,
+ gunichar wc)
+{
+ hb_codepoint_t glyph;
+
+ return self->glyph_func (self, wc, &glyph, self->user_data);
+}
+
+/*< private >
+ * pango_user_face_get_faceid:
+ * @self: a `PangoUserFace`
+ *
+ * Returns the faceid of the face.
+ *
+ * Returns: (transfer none): the faceid
+ */
+const char *
+pango_user_face_get_faceid (PangoUserFace *self)
+{
+ if (!self->faceid)
+ {
+ ensure_psname (self);
+ self->faceid = g_strconcat ("user:", self->psname, NULL);
+ }
+
+ return self->faceid;
+}
+
+/* }}} */
+ /* {{{ Public API */
+
+/**
+ * pango_user_face_new:
+ * @font_extents_func: the `PangoUserFaceGetFontExtentsFunc`
+ * @glyph_func: the `PangoUserFaceGetNominalGlyphFunc`
+ * @advance_func: the `PangoUserFaceGetGlyphAdvanceFunc`
+ * @glyph_extents_func: the `PangoUserFaceGetGlyphExtentsFunc`
+ * @render_func: the `PangoUserFaceRenderGlyphFunc`
+ * @user_data: user data that will be assed to the callbacks
+ * @destroy: destroy notify for @user_data
+ * @name: name for the face
+ * @description: (nullable): `PangoFontDescription` for the font
+ *
+ * Creates a new user font face.
+ *
+ * A user font face does not rely on font data from a font file,
+ * but instead uses callbacks to determine glyph extents, positions
+ * and rendering.
+ *
+ * Returns: (transfer full): a newly created `PangoUserFace`
+ *
+ * Since: 1.52
+ */
+PangoUserFace *
+pango_user_face_new (PangoUserFaceGetFontExtentsFunc font_extents_func,
+ PangoUserFaceGetNominalGlyphFunc glyph_func,
+ PangoUserFaceGetGlyphAdvanceFunc advance_func,
+ PangoUserFaceGetGlyphExtentsFunc glyph_extents_func,
+ PangoUserFaceRenderGlyphFunc render_func,
+ gpointer user_data,
+ GDestroyNotify destroy,
+ const char *name,
+ const PangoFontDescription *description)
+{
+ PangoUserFace *self;
+
+ self = g_object_new (PANGO_TYPE_USER_FACE, NULL);
+
+ self->font_extents_func = font_extents_func;
+ self->glyph_func = glyph_func;
+ self->advance_func = advance_func;
+ self->glyph_extents_func = glyph_extents_func,
+ self->render_func = render_func;
+ self->user_data = user_data;
+ self->destroy = destroy;
+
+ if (!name)
+ name = style_from_font_description (description);
+
+ self->name = g_strdup (name);
+ self->description = pango_font_description_copy (description);
+
+ return self;
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-userface.h b/pango/pango-userface.h
new file mode 100644
index 00000000..cbf9f0a4
--- /dev/null
+++ b/pango/pango-userface.h
@@ -0,0 +1,73 @@
+/* Pango
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <pango/pango-types.h>
+#include <pango/pango-font.h>
+
+G_BEGIN_DECLS
+
+typedef struct _PangoUserFont PangoUserFont;
+
+#define PANGO_TYPE_USER_FACE (pango_user_face_get_type ())
+
+PANGO_AVAILABLE_IN_1_52
+G_DECLARE_FINAL_TYPE (PangoUserFace, pango_user_face, PANGO, USER_FACE, PangoFontFace)
+
+typedef void (* PangoUserFaceGetFontExtentsFunc) (PangoUserFace *face,
+ int size,
+ hb_font_extents_t *extents,
+ gpointer user_data);
+
+typedef gboolean (* PangoUserFaceGetNominalGlyphFunc) (PangoUserFace *face,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ gpointer user_data);
+
+typedef hb_position_t (* PangoUserFaceGetGlyphAdvanceFunc) (PangoUserFace *face,
+ int size,
+ hb_codepoint_t glyph,
+ gpointer user_data);
+
+typedef gboolean (* PangoUserFaceGetGlyphExtentsFunc) (PangoUserFace *face,
+ int size,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ gpointer user_data);
+
+typedef void (* PangoUserFaceRenderGlyphFunc) (PangoUserFace *face,
+ int size,
+ hb_codepoint_t glyph,
+ gpointer user_data,
+ gpointer backend_data);
+
+PANGO_AVAILABLE_IN_1_52
+PangoUserFace * pango_user_face_new (PangoUserFaceGetFontExtentsFunc font_extents_func,
+ PangoUserFaceGetNominalGlyphFunc glyph_func,
+ PangoUserFaceGetGlyphAdvanceFunc advance_func,
+ PangoUserFaceGetGlyphExtentsFunc glyph_extents_func,
+ PangoUserFaceRenderGlyphFunc render_glyph,
+ gpointer user_data,
+ GDestroyNotify destroy,
+ const char *name,
+ const PangoFontDescription *description);
+
+G_END_DECLS
diff --git a/pango/pango-userfont-private.h b/pango/pango-userfont-private.h
new file mode 100644
index 00000000..316807d6
--- /dev/null
+++ b/pango/pango-userfont-private.h
@@ -0,0 +1,39 @@
+/* Pango
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "pango-userfont.h"
+#include "pango-userface.h"
+#include <hb.h>
+
+struct _PangoUserFont
+{
+ PangoFont parent_instance;
+
+ int size; /* point size, scaled by PANGO_SCALE */
+ float dpi;
+ PangoGravity gravity;
+ PangoMatrix matrix;
+
+ /* up to here shared with PangoHbFont */
+
+ PangoUserFace *face;
+};
diff --git a/pango/pango-userfont.c b/pango/pango-userfont.c
new file mode 100644
index 00000000..6a46d5e2
--- /dev/null
+++ b/pango/pango-userfont.c
@@ -0,0 +1,470 @@
+/* Pango
+ *
+ * Copyright (C) 2021 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 "pango-userfont-private.h"
+
+#include "pango-font-private.h"
+#include "pango-coverage-private.h"
+#include "pango-userface-private.h"
+#include "pango-hbfamily-private.h"
+#include "pango-impl-utils.h"
+#include "pango-language-set-private.h"
+
+#include <hb-ot.h>
+
+/**
+ * PangoUserFont:
+ *
+ * `PangoUserFont` is a `PangoFont` implementation that uses callbacks.
+ */
+
+/* {{{ PangoFont implementation */
+
+struct _PangoUserFontClass
+{
+ PangoFontClass parent_class;
+};
+
+G_DEFINE_TYPE (PangoUserFont, pango_user_font, PANGO_TYPE_FONT)
+
+static void
+pango_user_font_init (PangoUserFont *self)
+{
+ self->gravity = PANGO_GRAVITY_AUTO;
+ self->matrix = (PangoMatrix) PANGO_MATRIX_INIT;
+}
+
+static void
+pango_user_font_finalize (GObject *object)
+{
+ PangoUserFont *self = PANGO_USER_FONT (object);
+
+ g_object_unref (self->face);
+
+ G_OBJECT_CLASS (pango_user_font_parent_class)->finalize (object);
+}
+
+static PangoFontDescription *
+pango_user_font_describe (PangoFont *font)
+{
+ PangoUserFont *self = PANGO_USER_FONT (font);
+ PangoFontDescription *desc;
+
+ desc = pango_font_face_describe (PANGO_FONT_FACE (self->face));
+ pango_font_description_set_gravity (desc, self->gravity);
+ pango_font_description_set_size (desc, self->size);
+
+ return desc;
+}
+
+static PangoFontDescription *
+pango_user_font_describe_absolute (PangoFont *font)
+{
+ PangoUserFont *self = PANGO_USER_FONT (font);
+ PangoFontDescription *desc;
+
+ desc = pango_user_font_describe (font);
+ pango_font_description_set_absolute_size (desc, self->size * self->dpi / 72.);
+
+ return desc;
+}
+
+static PangoCoverage *
+pango_user_font_get_coverage (PangoFont *font,
+ PangoLanguage *language G_GNUC_UNUSED)
+{
+ /* FIXME */
+ return pango_coverage_new ();
+}
+
+static void
+pango_user_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoUserFont *self = PANGO_USER_FONT (font);
+ hb_font_t *hb_font = pango_font_get_hb_font (font);
+ hb_glyph_extents_t extents;
+ hb_direction_t direction;
+ hb_font_extents_t font_extents;
+
+ direction = PANGO_GRAVITY_IS_VERTICAL (self->gravity)
+ ? HB_DIRECTION_TTB
+ : HB_DIRECTION_LTR;
+
+ hb_font_get_extents_for_direction (hb_font, direction, &font_extents);
+
+ if (glyph == PANGO_GLYPH_EMPTY || (glyph & PANGO_GLYPH_UNKNOWN_FLAG))
+ {
+ if (ink_rect)
+ ink_rect->x = ink_rect->y = ink_rect->width = ink_rect->height = 0;
+
+ if (logical_rect)
+ {
+ logical_rect->x = logical_rect->width = 0;
+ logical_rect->y = - font_extents.ascender;
+ logical_rect->height = font_extents.ascender - font_extents.descender;
+ }
+
+ return;
+ }
+
+ hb_font_get_glyph_extents (hb_font, glyph, &extents);
+
+ if (ink_rect)
+ {
+ PangoRectangle r;
+
+ r.x = extents.x_bearing;
+ r.y = - extents.y_bearing;
+ r.width = extents.width;
+ r.height = - extents.height;
+
+ switch (self->gravity)
+ {
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ ink_rect->x = r.x;
+ ink_rect->y = r.y;
+ ink_rect->width = r.width;
+ ink_rect->height = r.height;
+ break;
+ case PANGO_GRAVITY_NORTH:
+ ink_rect->x = - r.x;
+ ink_rect->y = - r.y;
+ ink_rect->width = - r.width;
+ ink_rect->height = - r.height;
+ break;
+ case PANGO_GRAVITY_EAST:
+ ink_rect->x = r.y;
+ ink_rect->y = - r.x - r.width;
+ ink_rect->width = r.height;
+ ink_rect->height = r.width;
+ break;
+ case PANGO_GRAVITY_WEST:
+ ink_rect->x = - r.y - r.height;
+ ink_rect->y = r.x;
+ ink_rect->width = r.height;
+ ink_rect->height = r.width;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (PANGO_GRAVITY_IS_IMPROPER (self->gravity))
+ {
+ PangoMatrix matrix = (PangoMatrix) PANGO_MATRIX_INIT;
+ pango_matrix_scale (&matrix, -1, -1);
+ pango_matrix_transform_rectangle (&matrix, ink_rect);
+ }
+ }
+
+ if (logical_rect)
+ {
+ hb_position_t h_advance;
+ hb_font_extents_t extents;
+
+ h_advance = hb_font_get_glyph_h_advance (hb_font, glyph);
+ hb_font_get_h_extents (hb_font, &extents);
+
+ logical_rect->x = 0;
+ logical_rect->y = - extents.ascender;
+
+ switch (self->gravity)
+ {
+ case PANGO_GRAVITY_AUTO:
+ case PANGO_GRAVITY_SOUTH:
+ logical_rect->y = - extents.ascender;
+ logical_rect->width = h_advance;
+ break;
+ case PANGO_GRAVITY_NORTH:
+ logical_rect->y = extents.descender;
+ logical_rect->width = h_advance;
+ break;
+ case PANGO_GRAVITY_EAST:
+ logical_rect->y = - logical_rect->height / 2;
+ logical_rect->width = logical_rect->height;
+ break;
+ case PANGO_GRAVITY_WEST:
+ logical_rect->y = - logical_rect->height / 2;
+ logical_rect->width = - logical_rect->height;
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (PANGO_GRAVITY_IS_IMPROPER (self->gravity))
+ {
+ logical_rect->height = - logical_rect->height;
+ logical_rect->y = - logical_rect->y;
+ }
+ }
+}
+
+static PangoFontMetrics *
+pango_user_font_get_metrics (PangoFont *font,
+ PangoLanguage *language)
+{
+ hb_font_t *hb_font = pango_font_get_hb_font (font);
+ PangoFontMetrics *metrics;
+ hb_font_extents_t extents;
+
+ metrics = pango_font_metrics_new ();
+
+ hb_font_get_extents_for_direction (hb_font, HB_DIRECTION_LTR, &extents);
+
+ metrics->descent = - extents.descender;
+ metrics->ascent = extents.ascender;
+ metrics->height = extents.ascender - extents.descender + extents.line_gap;
+
+ metrics->underline_thickness = PANGO_SCALE;
+ metrics->underline_position = - PANGO_SCALE;
+ metrics->strikethrough_thickness = PANGO_SCALE;
+ metrics->strikethrough_position = metrics->ascent / 2;
+ metrics->approximate_char_width = 0; /* FIXME */
+ metrics->approximate_digit_width = 0;
+
+ return metrics;
+}
+
+static PangoFontMap *
+pango_user_font_get_font_map (PangoFont *font)
+{
+ PangoUserFont *self = PANGO_USER_FONT (font);
+ PangoHbFamily *family = PANGO_HB_FAMILY (self->face->family);
+
+ return family->map;
+}
+
+static hb_bool_t
+nominal_glyph_func (hb_font_t *font, void *font_data,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ void *user_data)
+{
+ PangoUserFont *self = font_data;
+
+ return self->face->glyph_func (self->face, unicode, glyph, self->face->user_data);
+}
+
+static hb_position_t
+glyph_h_advance_func (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ void *user_data)
+{
+ PangoUserFont *self = font_data;
+ int size = self->size * self->dpi / 72.;
+
+ return self->face->advance_func (self->face, size, glyph, self->face->user_data);
+}
+
+static hb_bool_t
+glyph_extents_func (hb_font_t *font, void *font_data,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ void *user_data)
+{
+ PangoUserFont *self = font_data;
+ int size = self->size * self->dpi / 72.;
+
+ return self->face->glyph_extents_func (self->face, size, glyph, extents, self->face->user_data);
+}
+
+static hb_bool_t
+font_extents_func (hb_font_t *font, void *font_data,
+ hb_font_extents_t *extents,
+ void *user_data)
+{
+ PangoUserFont *self = font_data;
+ int size = self->size * self->dpi / 72.;
+
+ self->face->font_extents_func (self->face, size, extents, self->face->user_data);
+
+ return TRUE;
+}
+
+static hb_font_t *
+pango_user_font_create_hb_font (PangoFont *font)
+{
+ PangoUserFont *self = PANGO_USER_FONT (font);
+ hb_font_t *hb_font;
+ double x_scale, y_scale;
+ int size;
+ hb_blob_t *blob;
+ hb_face_t *face;
+ hb_font_funcs_t *funcs;
+
+ blob = hb_blob_create ("", 0, HB_MEMORY_MODE_READONLY, NULL, NULL);
+ face = hb_face_create (blob, 0);
+ hb_font = hb_font_create (face);
+
+ funcs = hb_font_funcs_create ();
+
+ hb_font_funcs_set_nominal_glyph_func (funcs, nominal_glyph_func, NULL, NULL);
+ hb_font_funcs_set_glyph_h_advance_func (funcs, glyph_h_advance_func, NULL, NULL);
+ hb_font_funcs_set_glyph_extents_func (funcs, glyph_extents_func, NULL, NULL);
+ hb_font_funcs_set_font_h_extents_func (funcs, font_extents_func, NULL, NULL);
+
+ hb_font_set_funcs (hb_font, funcs, self, NULL);
+
+ hb_font_funcs_destroy (funcs);
+ hb_face_destroy (face);
+ hb_blob_destroy (blob);
+
+ size = self->size * self->dpi / 72.f;
+ x_scale = y_scale = 1;
+
+ if (PANGO_GRAVITY_IS_IMPROPER (self->gravity))
+ {
+ x_scale = - x_scale;
+ y_scale = - y_scale;
+ }
+
+ hb_font_set_scale (hb_font, size * x_scale, size * y_scale);
+ hb_font_set_ptem (hb_font, self->size / PANGO_SCALE);
+
+ return hb_font;
+}
+
+static gboolean
+pango_user_font_has_char (PangoFont *font,
+ gunichar wc)
+{
+ hb_font_t *user_font = pango_font_get_hb_font (font);
+ hb_codepoint_t glyph;
+
+ return hb_font_get_nominal_glyph (user_font, wc, &glyph);
+}
+
+static PangoFontFace *
+pango_user_font_get_face (PangoFont *font)
+{
+ PangoUserFont *self = PANGO_USER_FONT (font);
+
+ return PANGO_FONT_FACE (self->face);
+}
+
+static void
+pango_user_font_class_init (PangoUserFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+ PangoFontClassPrivate *pclass;
+
+ object_class->finalize = pango_user_font_finalize;
+
+ font_class->describe = pango_user_font_describe;
+ font_class->describe_absolute = pango_user_font_describe_absolute;
+ font_class->get_coverage = pango_user_font_get_coverage;
+ font_class->get_glyph_extents = pango_user_font_get_glyph_extents;
+ font_class->get_metrics = pango_user_font_get_metrics;
+ font_class->get_font_map = pango_user_font_get_font_map;
+ font_class->create_hb_font = pango_user_font_create_hb_font;
+
+ pclass = g_type_class_get_private ((GTypeClass *) class, PANGO_TYPE_FONT);
+
+ pclass->has_char = pango_user_font_has_char;
+ pclass->get_face = pango_user_font_get_face;
+}
+
+/* }}} */
+ /* {{{ Public API */
+
+/**
+ * pango_user_font_new:
+ * @face: the `PangoUserFace` to use
+ * @size: the desired size in points, scaled by `PANGO_SCALE`
+ * @gravity: the gravity to use when rendering
+ * @dpi: the dpi used when rendering
+ * @matrix: (nullable): transformation matrix to use when rendering
+ *
+ * Creates a new `PangoUserFont`.
+ *
+ * Returns: a newly created `PangoUserFont`
+ *
+ * Since: 1.52
+ */
+PangoUserFont *
+pango_user_font_new (PangoUserFace *face,
+ int size,
+ PangoGravity gravity,
+ float dpi,
+ const PangoMatrix *matrix)
+{
+ PangoUserFont *self;
+
+ self = g_object_new (PANGO_TYPE_USER_FONT, NULL);
+
+ self->face = g_object_ref (face);
+
+ self->size = size;
+ self->dpi = dpi;
+ if (gravity != PANGO_GRAVITY_AUTO)
+ self->gravity = gravity;
+ if (matrix)
+ self->matrix = *matrix;
+
+ return self;
+}
+
+/**
+ * pango_user_font_new_for_description:
+ * @face: the `PangoUserFace` to use
+ * @description: a `PangoFontDescription`
+ * @dpi: the dpi used when rendering
+ * @matrix: (nullable): transformation matrix to use when rendering
+ *
+ * Creates a new `PangoUserFont` with size and gravity taken
+ * from a font description.
+ *
+ * Returns: a newly created `PangoHbFont`
+ *
+ * Since: 1.52
+ */
+
+PangoUserFont *
+pango_user_font_new_for_description (PangoUserFace *face,
+ const PangoFontDescription *description,
+ float dpi,
+ const PangoMatrix *matrix)
+{
+ int size;
+ PangoGravity gravity;
+
+ if (pango_font_description_get_size_is_absolute (description))
+ size = pango_font_description_get_size (description) * 72. / dpi;
+ else
+ size = pango_font_description_get_size (description);
+
+ if ((pango_font_description_get_set_fields (description) & PANGO_FONT_MASK_GRAVITY) != 0 &&
+ pango_font_description_get_gravity (description) != PANGO_GRAVITY_SOUTH)
+ gravity = pango_font_description_get_gravity (description);
+ else
+ gravity = PANGO_GRAVITY_AUTO;
+
+ return pango_user_font_new (face, size, gravity, dpi, matrix);
+}
+
+/* }}} */
+
+/* vim:set foldmethod=marker expandtab: */
diff --git a/pango/pango-userfont.h b/pango/pango-userfont.h
new file mode 100644
index 00000000..6b351573
--- /dev/null
+++ b/pango/pango-userfont.h
@@ -0,0 +1,47 @@
+/* Pango
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <pango/pango-types.h>
+#include <pango/pango-userface.h>
+#include <hb.h>
+
+G_BEGIN_DECLS
+
+#define PANGO_TYPE_USER_FONT (pango_user_font_get_type ())
+
+PANGO_AVAILABLE_IN_1_52
+G_DECLARE_FINAL_TYPE (PangoUserFont, pango_user_font, PANGO, USER_FONT, PangoFont)
+
+PANGO_AVAILABLE_IN_1_52
+PangoUserFont * pango_user_font_new (PangoUserFace *face,
+ int size,
+ PangoGravity gravity,
+ float dpi,
+ const PangoMatrix *matrix);
+
+PANGO_AVAILABLE_IN_1_52
+PangoUserFont * pango_user_font_new_for_description (PangoUserFace *face,
+ const PangoFontDescription *description,
+ float dpi,
+ const PangoMatrix *matrix);
+
+G_END_DECLS
diff --git a/pango/pango.h b/pango/pango.h
index 9d95b5e5..aa0b7975 100644
--- a/pango/pango.h
+++ b/pango/pango.h
@@ -52,6 +52,8 @@
#include <pango/pango-script.h>
#include <pango/pango-tabs.h>
#include <pango/pango-types.h>
+#include <pango/pango-userface.h>
+#include <pango/pango-userfont.h>
#include <pango/pango-utils.h>
#include <pango/pango-version-macros.h>
diff --git a/pango/pangofc-hbfontmap.c b/pango/pangofc-hbfontmap.c
index ceda2cbc..2f005059 100644
--- a/pango/pangofc-hbfontmap.c
+++ b/pango/pangofc-hbfontmap.c
@@ -346,7 +346,7 @@ pango_fc_hb_font_map_populate (PangoHbFontMap *map)
if (!face)
continue;
- pango_hb_font_map_add_face (PANGO_HB_FONT_MAP (self), face);
+ pango_hb_font_map_add_face (PANGO_HB_FONT_MAP (self), PANGO_FONT_FACE (face));
}
g_hash_table_unref (lang_hash);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]