[gtk/pango2] fontexplorer: Show glyph layers
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/pango2] fontexplorer: Show glyph layers
- Date: Sun, 10 Jul 2022 15:40:56 +0000 (UTC)
commit 390ec02e05f1f60aee9071751bd399cbc8abe9b7
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Jul 9 22:08:35 2022 -0400
fontexplorer: Show glyph layers
Let the user cycle through the layers of color glyphs
by clicking on them.
demos/font-explorer/fontview.c | 8 +-
demos/font-explorer/glyphview.c | 203 ++++++++++++++++++++++++++++++++++++----
demos/font-explorer/glyphview.h | 2 +
3 files changed, 193 insertions(+), 20 deletions(-)
---
diff --git a/demos/font-explorer/fontview.c b/demos/font-explorer/fontview.c
index 58252f74ca..8364dc636c 100644
--- a/demos/font-explorer/fontview.c
+++ b/demos/font-explorer/fontview.c
@@ -40,6 +40,7 @@ struct _FontView
char *variations;
char *features;
char *palette;
+ GQuark palette_quark;
int letterspacing;
float line_height;
GdkRGBA foreground;
@@ -68,6 +69,7 @@ font_view_init (FontView *self)
self->variations = g_strdup ("");
self->features = g_strdup ("");
self->palette = g_strdup (PANGO2_COLOR_PALETTE_DEFAULT);
+ self->palette_quark = g_quark_from_string (self->palette);
self->foreground = (GdkRGBA){0., 0., 0., 1. };
self->background = (GdkRGBA){1., 1., 1., 1. };
self->sample_text = g_strdup ("Some sample text is better than other sample text");
@@ -309,7 +311,8 @@ setup_glyph (GtkSignalListItemFactory *factory,
static void
bind_glyph (GtkSignalListItemFactory *factory,
- GObject *listitem)
+ GObject *listitem,
+ FontView *self)
{
GlyphView *view;
GObject *item;
@@ -318,6 +321,7 @@ bind_glyph (GtkSignalListItemFactory *factory,
item = gtk_list_item_get_item (GTK_LIST_ITEM (listitem));
glyph_view_set_font (view, glyph_item_get_font (GLYPH_ITEM (item)));
glyph_view_set_glyph (view, glyph_item_get_glyph (GLYPH_ITEM (item)));
+ glyph_view_set_palette (view, self->palette_quark);
}
static GtkWidget *
@@ -597,6 +601,8 @@ font_view_set_property (GObject *object,
case PROP_PALETTE:
g_free (self->palette);
self->palette = g_strdup (g_value_get_string (value));
+ self->palette_quark = g_quark_from_string (self->palette);
+ update_glyph_model (self);
break;
case PROP_SAMPLE_TEXT:
diff --git a/demos/font-explorer/glyphview.c b/demos/font-explorer/glyphview.c
index 5462403bed..2fd47a6ed7 100644
--- a/demos/font-explorer/glyphview.c
+++ b/demos/font-explorer/glyphview.c
@@ -7,7 +7,11 @@ struct _GlyphView
GtkWidget parent;
Pango2Font *font;
+ GQuark palette;
+ int palette_index;
hb_codepoint_t glyph;
+ int n_layers;
+ int layer;
};
struct _GlyphViewClass
@@ -17,9 +21,35 @@ struct _GlyphViewClass
G_DEFINE_TYPE(GlyphView, glyph_view, GTK_TYPE_WIDGET);
+static void
+click_cb (GtkGestureClick *gesture,
+ int n_press,
+ double x,
+ double y,
+ GlyphView *self)
+{
+ if (self->n_layers == 0)
+ return;
+
+ self->layer++;
+
+ if (self->layer == self->n_layers)
+ self->layer = -1;
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
static void
glyph_view_init (GlyphView *self)
{
+ GtkGesture *click;
+
+ self->n_layers = 0;
+ self->layer = -1;
+
+ click = gtk_gesture_click_new ();
+ g_signal_connect (click, "pressed", G_CALLBACK (click_cb), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (click));
}
static void
@@ -45,28 +75,75 @@ glyph_view_snapshot (GtkWidget *widget,
pango2_font_get_glyph_extents (self->font, self->glyph, &ink, &logical);
+ width = gtk_widget_get_width (widget);
+ height = gtk_widget_get_height (widget);
+
+ cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
+
glyphs = pango2_glyph_string_new ();
pango2_glyph_string_set_size (glyphs, 1);
- glyphs->glyphs[0].glyph = self->glyph;
+
glyphs->glyphs[0].geometry.width = ink.width;
glyphs->glyphs[0].geometry.x_offset = ink.x;
glyphs->glyphs[0].geometry.y_offset = -ink.y;
- width = gtk_widget_get_width (widget);
- height = gtk_widget_get_height (widget);
+ if (self->layer == -1)
+ {
+ glyphs->glyphs[0].glyph = self->glyph;
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ }
+ else
+ {
+ hb_face_t *face = hb_font_get_face (pango2_font_get_hb_font (self->font));
+ hb_ot_color_layer_t *layers;
+ unsigned int count;
- cr = gtk_snapshot_append_cairo (snapshot, &GRAPHENE_RECT_INIT (0, 0, width, height));
+ layers = g_newa (hb_ot_color_layer_t, self->n_layers);
+ count = self->n_layers;
+ hb_ot_color_glyph_get_layers (face,
+ self->glyph,
+ 0,
+ &count,
+ layers);
+ glyphs->glyphs[0].glyph = layers[self->layer].glyph;
+ if (layers[self->layer].color_index == 0xffff)
+ {
+ cairo_set_source_rgb (cr, 0, 0, 0);
+ }
+ else
+ {
+ hb_color_t *colors;
+ unsigned int n_colors;
+ hb_color_t color;
+
+ n_colors = hb_ot_color_palette_get_colors (face,
+ self->palette_index,
+ 0,
+ NULL,
+ NULL);
+ colors = g_newa (hb_color_t, n_colors);
+ hb_ot_color_palette_get_colors (face,
+ self->palette_index,
+ 0,
+ &n_colors,
+ colors);
+ color = colors[layers[self->layer].color_index];
+ cairo_set_source_rgba (cr, hb_color_get_red (color)/255.,
+ hb_color_get_green (color)/255.,
+ hb_color_get_blue (color)/255.,
+ hb_color_get_alpha (color)/255.);
+ }
+ }
- cairo_set_source_rgb (cr, 0, 0, 0);
cairo_move_to (cr, (width - logical.width/1024.)/2, (height - logical.height/1024.)/2);
- pango2_cairo_show_glyph_string (cr, self->font, glyphs);
+ pango2_cairo_show_color_glyph_string (cr, self->font, self->palette, glyphs);
- if (hb_font_get_glyph_name (pango2_font_get_hb_font (self->font), self->glyph, name, sizeof (name)))
{
Pango2Layout *layout;
Pango2FontDescription *desc;
- int w, h;
char gid[20];
+ hb_font_t *hb_font;
+ hb_face_t *hb_face;
g_snprintf (gid, sizeof (gid), "%d", self->glyph);
layout = gtk_widget_create_pango_layout (widget, gid);
@@ -78,19 +155,64 @@ glyph_view_snapshot (GtkWidget *widget,
gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (5, 5));
gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,0.7});
gtk_snapshot_restore (snapshot);
- g_object_unref (layout);
- layout = gtk_widget_create_pango_layout (widget, name);
- desc = pango2_font_description_from_string ("Cantarell 8");
- pango2_layout_set_font_description (layout, desc);
- pango2_font_description_free (desc);
+ hb_font = pango2_font_get_hb_font (self->font);
+ hb_face = hb_font_get_face (hb_font);
- pango2_lines_get_size (pango2_layout_get_lines (layout), &w, &h);
+ if (hb_ot_layout_has_glyph_classes (hb_face))
+ {
+ hb_ot_layout_glyph_class_t class;
+ const char *class_names[] = {
+ NULL, "Base", "Ligature", "Mark", "Component"
+ };
+ int w, h;
+
+ class = hb_ot_layout_get_glyph_class (hb_face, self->glyph);
+
+ if (class != HB_OT_LAYOUT_GLYPH_CLASS_UNCLASSIFIED)
+ {
+ pango2_layout_set_text (layout, class_names[class], -1);
+ pango2_lines_get_size (pango2_layout_get_lines (layout), &w, &h);
+
+ gtk_snapshot_save (snapshot);
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width - w/1024. - 5, 5));
+ gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,.7});
+ gtk_snapshot_restore (snapshot);
+ }
+ }
+
+ if (hb_font_get_glyph_name (hb_font, self->glyph, name, sizeof (name)))
+ {
+ int w, h;
+
+ pango2_layout_set_text (layout, name, -1);
+ pango2_lines_get_size (pango2_layout_get_lines (layout), &w, &h);
+
+ gtk_snapshot_save (snapshot);
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (5, height - h/1024. - 5));
+ gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,.7});
+ gtk_snapshot_restore (snapshot);
+ }
+
+ if (self->n_layers > 0)
+ {
+ char buf[128];
+ int w, h;
+
+ if (self->layer == -1)
+ g_snprintf (buf, sizeof (buf), "%d Layers", self->n_layers);
+ else
+ g_snprintf (buf, sizeof (buf), "Layer %d", self->layer);
+
+ pango2_layout_set_text (layout, buf, -1);
+ pango2_lines_get_size (pango2_layout_get_lines (layout), &w, &h);
+
+ gtk_snapshot_save (snapshot);
+ gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (width - w/1024. - 5, height - h/1024. -
5));
+ gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,.7});
+ gtk_snapshot_restore (snapshot);
+ }
- gtk_snapshot_save (snapshot);
- gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (5, height - h/1024. - 5));
- gtk_snapshot_append_layout (snapshot, layout, &(GdkRGBA){ 0.,0.,0.,1.});
- gtk_snapshot_restore (snapshot);
g_object_unref (layout);
}
}
@@ -142,6 +264,48 @@ glyph_view_set_font (GlyphView *self,
gtk_widget_queue_resize (GTK_WIDGET (self));
}
+static unsigned int
+find_palette_index_by_flag (hb_face_t *hbface,
+ hb_ot_color_palette_flags_t flag)
+{
+ unsigned int n_palettes;
+
+ n_palettes = hb_ot_color_palette_get_count (hbface);
+ for (unsigned int i = 0; i < n_palettes; i++)
+ {
+ if (hb_ot_color_palette_get_flags (hbface, i) & flag)
+ return i;
+ }
+
+ return 0;
+}
+
+void
+glyph_view_set_palette (GlyphView *self,
+ GQuark palette)
+{
+ if (self->palette == palette)
+ return;
+
+ self->palette = palette;
+
+ if (palette == g_quark_from_string (PANGO2_COLOR_PALETTE_DEFAULT))
+ self->palette_index = 0;
+ else if (palette == g_quark_from_string (PANGO2_COLOR_PALETTE_LIGHT))
+ self->palette_index = find_palette_index_by_flag (hb_font_get_face (pango2_font_get_hb_font
(self->font)), HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_LIGHT_BACKGROUND);
+ else if (palette == g_quark_from_string (PANGO2_COLOR_PALETTE_DARK))
+ self->palette_index = find_palette_index_by_flag (hb_font_get_face (pango2_font_get_hb_font
(self->font)), HB_OT_COLOR_PALETTE_FLAG_USABLE_WITH_DARK_BACKGROUND);
+ else
+ {
+ const char *str = g_quark_to_string (palette);
+ char *endp;
+ if (g_str_has_prefix (str, "palette"))
+ self->palette_index = g_ascii_strtoll (str + strlen ("palette"), &endp, 10);
+ }
+
+ gtk_widget_queue_resize (GTK_WIDGET (self));
+}
+
void
glyph_view_set_glyph (GlyphView *self,
hb_codepoint_t glyph)
@@ -150,6 +314,7 @@ glyph_view_set_glyph (GlyphView *self,
return;
self->glyph = glyph;
-
+ self->n_layers = hb_ot_color_glyph_get_layers (hb_font_get_face (pango2_font_get_hb_font (self->font)),
glyph, 0, NULL, NULL);
+ self->layer = -1;
gtk_widget_queue_resize (GTK_WIDGET (self));
}
diff --git a/demos/font-explorer/glyphview.h b/demos/font-explorer/glyphview.h
index 11c2fa1bd8..c89862dae3 100644
--- a/demos/font-explorer/glyphview.h
+++ b/demos/font-explorer/glyphview.h
@@ -15,5 +15,7 @@ GType glyph_view_get_type (void);
GlyphView * glyph_view_new (void);
void glyph_view_set_font (GlyphView *view,
Pango2Font *font);
+void glyph_view_set_palette (GlyphView *view,
+ GQuark palette);
void glyph_view_set_glyph (GlyphView *view,
hb_codepoint_t glyph);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]