[pango/userfont: 4/5] cairoshape: Use a user font
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pango/userfont: 4/5] cairoshape: Use a user font
- Date: Fri, 28 Jan 2022 19:28:08 +0000 (UTC)
commit f57da740c044a9ac558dca28e2b30487045a3593
Author: Matthias Clasen <mclasen redhat com>
Date: Thu Jan 27 00:47:16 2022 -0500
cairoshape: Use a user font
examples/cairoshape.c | 212 +++++++++++++++++++++++++++++++++++---------------
1 file changed, 149 insertions(+), 63 deletions(-)
---
diff --git a/examples/cairoshape.c b/examples/cairoshape.c
index d288db14..266e241d 100644
--- a/examples/cairoshape.c
+++ b/examples/cairoshape.c
@@ -2,7 +2,7 @@
* inside a text layout, positioned by Pango. This has become possibly
* using the following API added in Pango 1.18:
*
- * pango_cairo_context_set_shape_renderer ()
+ * pango_cairo_context_set_shape_renderer ()
*
* This examples uses a small parser to convert shapes in the format of
* SVG paths to cairo instructions. You can typically extract these from
@@ -25,6 +25,9 @@
#include <string.h>
#include <pango/pangocairo.h>
+#include <pango/pangofc-hbfontmap.h>
+
+static PangoFontMap *fontmap;
#define BULLET "•"
@@ -52,8 +55,8 @@ static MiniSvg GnomeFootLogo = {
static void
mini_svg_render (MiniSvg *shape,
- cairo_t *cr,
- gboolean do_path)
+ cairo_t *cr,
+ gboolean do_path)
{
double x, y;
const char *p;
@@ -68,98 +71,79 @@ mini_svg_render (MiniSvg *shape,
{
case 'M':
{
- sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
- cairo_move_to (cr, x, y);
- break;
- }
+ sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
+ cairo_move_to (cr, x, y);
+ break;
+ }
case 'L':
{
- sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
- cairo_line_to (cr, x, y);
- break;
- }
+ sscanf (p, "%lf,%lf %n", &x, &y, &len); p += len;
+ cairo_line_to (cr, x, y);
+ break;
+ }
case 'C':
{
- double x1, y1, x2, y2, x3, y3;
- sscanf (p, "%lf,%lf %lf,%lf %lf,%lf %n", &x1, &y1, &x2, &y2, &x3, &y3, &len); p += len;
- cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
- break;
- }
+ double x1, y1, x2, y2, x3, y3;
+ sscanf (p, "%lf,%lf %lf,%lf %lf,%lf %n", &x1, &y1, &x2, &y2, &x3, &y3, &len); p += len;
+ cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
+ break;
+ }
case 'z':
{
- cairo_close_path (cr);
- break;
- }
+ cairo_close_path (cr);
+ break;
+ }
default:
{
- g_warning ("Invalid MiniSvg operation '%c'", *op);
- break;
- }
+ g_warning ("Invalid MiniSvg operation '%c'", *op);
+ break;
+ }
}
if (!do_path)
cairo_fill (cr);
}
-static void
-mini_svg_shape_renderer (cairo_t *cr,
- PangoAttrShape *attr,
- gboolean do_path,
- gpointer data G_GNUC_UNUSED)
-{
- MiniSvg *shape = (MiniSvg *) attr->data;
- double scale_x, scale_y;
-
- scale_x = (double) attr->ink_rect.width / (PANGO_SCALE * shape->width );
- scale_y = (double) attr->ink_rect.height / (PANGO_SCALE * shape->height);
-
- cairo_rel_move_to (cr,
- (double) attr->ink_rect.x / PANGO_SCALE,
- (double) attr->ink_rect.y / PANGO_SCALE);
- cairo_scale (cr, scale_x, scale_y);
-
- mini_svg_render (shape, cr, do_path);
-}
-
-
static PangoLayout *
get_layout (cairo_t *cr)
{
+ PangoContext *context;
PangoLayout *layout;
PangoAttrList *attrs;
- PangoRectangle ink_rect = {1 * PANGO_SCALE, -11 * PANGO_SCALE, 8 * PANGO_SCALE, 10 * PANGO_SCALE};
- PangoRectangle logical_rect = {0 * PANGO_SCALE, -12 * PANGO_SCALE, 10 * PANGO_SCALE, 12 * PANGO_SCALE};
const char *p;
/* Create a PangoLayout, set the font and text */
- layout = pango_cairo_create_layout (cr);
-
- pango_cairo_context_set_shape_renderer (pango_layout_get_context (layout),
- mini_svg_shape_renderer, NULL, NULL);
+ context = pango_font_map_create_context (fontmap);
+ layout = pango_layout_new (context);
+ g_object_unref (context);
pango_layout_set_text (layout, text, -1);
attrs = pango_attr_list_new ();
- /* Set gnome shape attributes for all bullets */
+ PangoFontDescription *font_desc = pango_font_description_from_string ("Bullets 12");
+
for (p = text; (p = strstr (p, BULLET)); p += strlen (BULLET))
{
PangoAttribute *attr;
-
- attr = pango_attr_shape_new_with_data (&ink_rect,
- &logical_rect,
- &GnomeFootLogo,
- NULL, NULL);
+ attr = pango_attr_font_desc_new (font_desc);
attr->start_index = p - text;
attr->end_index = attr->start_index + strlen (BULLET);
+ pango_attr_list_insert (attrs, attr);
+ attr = pango_attr_fallback_new (0);
+ attr->start_index = p - text;
+ attr->end_index = attr->start_index + strlen (BULLET);
pango_attr_list_insert (attrs, attr);
}
+ pango_font_description_free (font_desc);
+
pango_layout_set_attributes (layout, attrs);
pango_attr_list_unref (attrs);
+
return layout;
}
@@ -169,6 +153,8 @@ draw_text (cairo_t *cr, int *width, int *height)
PangoLayout *layout = get_layout (cr);
+ pango_layout_write_to_file (layout, PANGO_LAYOUT_SERIALIZE_OUTPUT, "out.layout", NULL);
+
/* Adds a fixed 10-pixel margin on the sides. */
if (width || height)
@@ -186,7 +172,108 @@ draw_text (cairo_t *cr, int *width, int *height)
g_object_unref (layout);
}
-int main (int argc, char **argv)
+static gboolean
+glyph_cb (PangoUserFace *face,
+ hb_codepoint_t unicode,
+ hb_codepoint_t *glyph,
+ gpointer data)
+{
+ if (unicode == 0x2022)
+ {
+ *glyph = unicode;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+glyph_info_cb (PangoUserFace *face,
+ int size,
+ hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents,
+ hb_position_t *h_advance,
+ hb_position_t *v_advance,
+ gboolean *is_color,
+ gpointer user_data)
+{
+ if (glyph == 0x2022)
+ {
+ extents->x_bearing = 0;
+ extents->y_bearing = - size;
+ extents->width = size;
+ extents->height = size;
+
+ *h_advance = size;
+ *v_advance = size;
+
+ *is_color = FALSE;
+ }
+
+ return FALSE;
+}
+
+static gboolean
+font_info_cb (PangoUserFace *face,
+ int size,
+ hb_font_extents_t *extents,
+ gpointer user_data)
+{
+ extents->ascender = size;
+ extents->descender = 0;
+ extents->line_gap = 0;
+
+ return TRUE;
+}
+
+static gboolean
+render_cb (PangoUserFace *face,
+ int size,
+ hb_codepoint_t glyph,
+ gpointer user_data,
+ const char *backend_id,
+ gpointer backend_data)
+{
+ cairo_t *cr = backend_data;
+
+ if (strcmp (backend_id, "cairo") != 0)
+ return FALSE;
+
+ if (glyph == 0x2022)
+ {
+ MiniSvg *shape = &GnomeFootLogo;
+
+ cairo_move_to (cr, 0, -1);
+ cairo_scale (cr, 1. / shape->width, 1. / shape->height);
+
+ mini_svg_render (shape, cr, FALSE);
+ }
+
+ return TRUE;
+}
+
+static void
+setup_fontmap (PangoHbFontMap *fontmap)
+{
+ PangoFontDescription *desc;
+ PangoUserFace *face;
+
+ desc = pango_font_description_new ();
+ pango_font_description_set_family (desc, "Bullets");
+
+ face = pango_user_face_new (font_info_cb,
+ glyph_cb,
+ glyph_info_cb,
+ NULL,
+ render_cb,
+ NULL, NULL, "Black", desc);
+ pango_hb_font_map_add_face (fontmap, PANGO_FONT_FACE (face));
+
+ pango_font_description_free (desc);
+}
+
+int
+main (int argc, char **argv)
{
cairo_t *cr;
char *filename;
@@ -202,18 +289,17 @@ int main (int argc, char **argv)
filename = argv[1];
- /* First create and use a 0x0 surface, to measure how large
- * the final surface needs to be */
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- 0, 0);
+ fontmap = PANGO_FONT_MAP (pango_fc_hb_font_map_new ());
+ setup_fontmap (PANGO_HB_FONT_MAP (fontmap));
+
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 0, 0);
cr = cairo_create (surface);
draw_text (cr, &width, &height);
cairo_destroy (cr);
cairo_surface_destroy (surface);
/* Now create the final surface and draw to it. */
- surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- width, height);
+ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
cr = cairo_create (surface);
cairo_set_source_rgb (cr, 1.0, 1.0, 1.0);
@@ -228,7 +314,7 @@ int main (int argc, char **argv)
if (status != CAIRO_STATUS_SUCCESS)
{
- g_printerr ("Could not save png to '%s'\n", filename);
+ g_printerr ("Could not save png to '%s': %s\n", filename, cairo_status_to_string (status));
return 1;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]