[pango/pango2: 298/301] Add a userfont to pango-view




commit 1e26fa207afed94074546984561510adbeb76613
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Jun 21 16:50:58 2022 -0700

    Add a userfont to pango-view
    
    To use it, call pango-view with
    
      --userfont --font "Userfont 20"

 utils/meson.build         |   1 +
 utils/userfont.c          | 182 ++++++++++++++++++++++++++++++++++++++++++++++
 utils/userfont.h          |   1 +
 utils/viewer-pangocairo.c |   8 ++
 4 files changed, 192 insertions(+)
---
diff --git a/utils/meson.build b/utils/meson.build
index f3db34926..0d2e0d518 100644
--- a/utils/meson.build
+++ b/utils/meson.build
@@ -2,6 +2,7 @@ pango_view_sources = [
   'pango-view.c',
   'viewer-main.c',
   'viewer-render.c',
+  'userfont.c',
 ]
 
 pango_view_deps = [
diff --git a/utils/userfont.c b/utils/userfont.c
new file mode 100644
index 000000000..f5fbf7954
--- /dev/null
+++ b/utils/userfont.c
@@ -0,0 +1,182 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <pango/pangocairo.h>
+#include "userfont.h"
+
+#define END_GLYPH 0
+#define STROKE 126
+#define CLOSE 127
+
+/* Simple glyph definition: 1 - 15 means lineto (or moveto for first
+ * point) for one of the points on this grid:
+ *
+ *      1  2  3
+ *      4  5  6
+ *      7  8  9
+ * ----10 11 12----(baseline)
+ *     13 14 15
+ */
+typedef struct
+{
+  gunichar ucs4;
+  int width;
+  char data[16];
+} test_scaled_font_glyph_t;
+
+/* Simple glyph definition: 1 - 15 means lineto (or moveto for first
+ * point) for one of the points on this grid:
+ *
+ *      1  2  3
+ *      4  5  6
+ *      7  8  9
+ * ----10 11 12----(baseline)
+ *     13 14 15
+ */
+static const test_scaled_font_glyph_t glyphs [] = {
+  { 'a',  3, { 4, 6, 12, 10, 7, 9, STROKE, END_GLYPH } },
+  { 'c',  3, { 6, 4, 10, 12, STROKE, END_GLYPH } },
+  { 'e',  3, { 12, 10, 4, 6, 9, 7, STROKE, END_GLYPH } },
+  { 'f',  3, { 3, 2, 11, STROKE, 4, 6, STROKE, END_GLYPH } },
+  { 'g',  3, { 12, 10, 4, 6, 15, 13, STROKE, END_GLYPH } },
+  { 'h',  3, { 1, 10, STROKE, 7, 5, 6, 12, STROKE, END_GLYPH } },
+  { 'i',  1, { 1, 1, STROKE, 4, 10, STROKE, END_GLYPH } },
+  { 'l',  1, { 1, 10, STROKE, END_GLYPH } },
+  { 'n',  3, { 10, 4, STROKE, 7, 5, 6, 12, STROKE, END_GLYPH } },
+  { 'o',  3, { 4, 10, 12, 6, CLOSE, END_GLYPH } },
+  { 'p',  3, { 4, 10, 12, 6, CLOSE, 4, 13, STROKE, END_GLYPH } },
+  { 'r',  3, { 4, 10, STROKE, 7, 5, 6, STROKE, END_GLYPH } },
+  { 's',  3, { 6, 4, 7, 9, 12, 10, STROKE, END_GLYPH } },
+  { 't',  3, { 2, 11, 12, STROKE, 4, 6, STROKE, END_GLYPH } },
+  { 'u',  3, { 4, 10, 12, 6, STROKE, END_GLYPH } },
+  { 'y',  3, { 4, 10, 12, 6, STROKE, 12, 15, 13, STROKE, END_GLYPH } },
+  { 'z',  3, { 4, 6, 10, 12, STROKE, END_GLYPH } },
+  { ' ',  1, { END_GLYPH } },
+  { '-',  2, { 7, 8, STROKE, END_GLYPH } },
+  { '.',  1, { 10, 10, STROKE, END_GLYPH } },
+  { 0xe000, 3, { 3, 2, 11, STROKE, 4, 6, STROKE, 3, 3, STROKE, 6, 12, STROKE, END_GLYPH } }, /* fi */
+  { -1,  0, { END_GLYPH } },
+};
+
+static gboolean
+glyph_cb (PangoUserFace  *face,
+          hb_codepoint_t  unicode,
+          hb_codepoint_t *glyph,
+          gpointer        user_data)
+{
+  test_scaled_font_glyph_t *glyphs = user_data;
+
+  for (int i = 0; glyphs[i].ucs4 != (gunichar) -1; i++)
+    {
+      if (glyphs[i].ucs4 == unicode)
+        {
+          *glyph = i;
+          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)
+{
+  test_scaled_font_glyph_t *glyphs = user_data;
+
+  extents->x_bearing = 0;
+  extents->y_bearing = - 0.75 * size;
+  extents->width = glyphs[glyph].width / 4.0 * size;
+  extents->height = size;
+
+  *h_advance = *v_advance = glyphs[glyph].width / 4.0 * size;
+
+  *is_color = FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+font_info_cb (PangoUserFace     *face,
+              int                size,
+              hb_font_extents_t *extents,
+              gpointer           user_data)
+{
+  extents->ascender = - 0.75 * size;
+  extents->descender = 0.25 * size;
+  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)
+{
+  test_scaled_font_glyph_t *glyphs = user_data;
+  cairo_t *cr = backend_data;
+  const char *data;
+  div_t d;
+  double x, y;
+
+  if (strcmp (backend_id, "cairo") != 0)
+    return FALSE;
+
+  cairo_set_line_width (cr, 0.1);
+  cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+  cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+
+  data = glyphs[glyph].data;
+  for (int i = 0; data[i] != END_GLYPH; i++)
+    {
+      switch (data[i])
+        {
+        case STROKE:
+          cairo_new_sub_path (cr);
+          break;
+
+        case CLOSE:
+          cairo_close_path (cr);
+          break;
+
+        default:
+          d = div (data[i] - 1, 3);
+          x = d.rem / 4.0 + 0.125;
+          y = d.quot / 5.0 + 0.4 - 1.0;
+          cairo_line_to (cr, x, y);
+        }
+    }
+
+  cairo_stroke (cr);
+
+  return TRUE;
+}
+
+void
+add_userfont (PangoFontMap *fontmap)
+{
+  PangoFontDescription *desc;
+  PangoUserFace *face;
+
+  desc = pango_font_description_new ();
+  pango_font_description_set_family (desc, "Userfont");
+  face = pango_user_face_new (font_info_cb,
+                              glyph_cb,
+                              glyph_info_cb,
+                              NULL,
+                              render_cb,
+                              (gpointer) glyphs, NULL,
+                              "Black", desc);
+  pango_font_map_add_face (fontmap, PANGO_FONT_FACE (face));
+  pango_font_description_free (desc);
+}
diff --git a/utils/userfont.h b/utils/userfont.h
new file mode 100644
index 000000000..f4d4f8be4
--- /dev/null
+++ b/utils/userfont.h
@@ -0,0 +1 @@
+void add_userfont (PangoFontMap *map);
diff --git a/utils/viewer-pangocairo.c b/utils/viewer-pangocairo.c
index 2851fc082..2bf2e0d69 100644
--- a/utils/viewer-pangocairo.c
+++ b/utils/viewer-pangocairo.c
@@ -23,13 +23,16 @@
 
 #include "viewer-render.h"
 #include "viewer-cairo.h"
+#include "userfont.h"
 
 #include <pango/pangocairo.h>
 #include <pango/pango-run.h>
 
 #include <hb-ot.h>
 
+
 static int opt_annotate = 0;
+static gboolean opt_userfont = 0;
 static char **opt_font_file = NULL;
 
 typedef struct
@@ -86,8 +89,12 @@ pangocairo_view_create (const PangoViewer *klass G_GNUC_UNUSED)
     {
       instance->fontmap = pango_font_map_new_default ();
     }
+
   pango_font_map_set_resolution (PANGO_FONT_MAP (instance->fontmap), opt_dpi);
 
+  if (opt_userfont)
+    add_userfont (instance->fontmap);
+
   instance->font_options = cairo_font_options_create ();
   if (opt_hinting != HINT_DEFAULT)
     {
@@ -965,6 +972,7 @@ pangocairo_view_get_option_group (const PangoViewer *klass G_GNUC_UNUSED)
   {
     {"annotate", 0, 0, G_OPTION_ARG_CALLBACK, parse_annotate_arg, annotate_arg_help, "FLAGS"},
     { "font-file", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &opt_font_file, "Create a fontmap with this font", 
"FILE" },
+    { "userfont", 0, 0, G_OPTION_ARG_NONE, &opt_userfont, "Add userfont" },
     {NULL}
   };
   GOptionGroup *group;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]