cairo: Use pango_cairo_context_set_resolution() to get font sizes correct.
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 15 Dec 2020 07:36:31 +0000 (23:36 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 20 Dec 2020 23:58:25 +0000 (15:58 -0800)
I never understood before why fonts didn't appear the right side in PDF
and PostScript output.  This fixes the problem.

src/output/cairo-fsm.c
src/output/cairo-fsm.h
src/output/cairo.c
src/ui/gui/psppire-output-view.c

index c9794d4630a942ece7cf0d9d0802d2a317bc7891..a9e4d4c68ddc2482a20d3891fc2bc2d7dd03db0d 100644 (file)
@@ -88,7 +88,7 @@ xr_fsm_style_equals (const struct xr_fsm_style *a,
       || a->min_break[V] != b->min_break[V]
       || a->use_system_colors != b->use_system_colors
       || a->transparent != b->transparent
-      || a->font_scale != b->font_scale)
+      || a->font_resolution != b->font_resolution)
     return false;
 
   for (size_t i = 0; i < XR_N_FONTS; i++)
@@ -608,13 +608,16 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell,
   if (font_style->typeface)
       desc = parse_font (
         font_style->typeface,
-        font_style->size ? font_style->size * 1000 * xr->style->font_scale : 10000,
+        font_style->size ? font_style->size * 1000 : 10000,
         font_style->bold, font_style->italic);
   if (!desc)
     desc = xr->style->fonts[font_type];
 
   assert (xr->cairo);
-  PangoLayout *layout = pango_cairo_create_layout (xr->cairo);
+  PangoContext *context = pango_cairo_create_context (xr->cairo);
+  pango_cairo_context_set_resolution (context, xr->style->font_resolution);
+  PangoLayout *layout = pango_layout_new (context);
+  g_object_unref (context);
   pango_layout_set_font_description (layout, desc);
 
   const char *text = cell->text;
@@ -1111,7 +1114,10 @@ xr_fsm_create (const struct output_item *item_,
 
   for (int i = 0; i < XR_N_FONTS; i++)
     {
-      PangoLayout *layout = pango_cairo_create_layout (cr);
+      PangoContext *context = pango_cairo_create_context (cr);
+      pango_cairo_context_set_resolution (context, style->font_resolution);
+      PangoLayout *layout = pango_layout_new (context);
+      g_object_unref (context);
       pango_layout_set_font_description (layout, style->fonts[i]);
 
       pango_layout_set_text (layout, "0", 1);
index 60a6efb489166241c1d52a4966166667395f8d6d..74b43860c8dcd062a0f1efc8048aaeccd180c259 100644 (file)
@@ -44,7 +44,13 @@ struct xr_fsm_style
     PangoFontDescription *fonts[XR_N_FONTS];
     bool use_system_colors;
     bool transparent;
-    double font_scale;
+
+    /* Resolution, in units per inch, used for measuring font "points".  If
+       this is 72.0, for example, then 1pt = 1 device unit, which is
+       appropriate for rendering to a surface created by
+       cairo_ps_surface_create() with its default transformation matrix of 72
+       units/inch.  For a screen-based surface, it is traditionally 96.0. */
+    double font_resolution;
   };
 struct xr_fsm_style *xr_fsm_style_ref (const struct xr_fsm_style *);
 void xr_fsm_style_unref (struct xr_fsm_style *);
index f5bf1f6a93de3ec3f1438e252d61d89636b1cdbf..c3cef5c62ade2f032f7d5ec9b63a559e04fa3d90 100644 (file)
@@ -117,7 +117,6 @@ struct xr_driver
 
     /* Internal state. */
     struct xr_fsm_style *style;
-    double font_scale;
     int char_width, char_height;
     cairo_t *cairo;
     cairo_surface_t *surface;
@@ -251,21 +250,13 @@ apply_options (struct xr_driver *xr, struct string_map *o)
 }
 
 static struct xr_driver *
-xr_allocate (const char *name, int device_type, struct string_map *o,
-             double font_scale)
+xr_allocate (const char *name, int device_type, struct string_map *o)
 {
   struct xr_driver *xr = xzalloc (sizeof *xr);
   struct output_driver *d = &xr->driver;
 
   output_driver_init (d, &cairo_driver_class, name, device_type);
 
-  /* This is a nasty kluge for an issue that does not make sense.  On any
-     surface other than a screen (e.g. for output to PDF or PS or SVG), the
-     fonts are way too big by default.  A "9-point" font seems to appear about
-     16 points tall.  We use a scale factor for these surfaces to help, but the
-     underlying issue is a mystery. */
-  xr->font_scale = font_scale;
-
   apply_options (xr, o);
 
   return xr;
@@ -295,7 +286,10 @@ xr_measure_fonts (cairo_t *cairo, PangoFontDescription *fonts[XR_N_FONTS],
   *char_height = 0;
   for (int i = 0; i < XR_N_FONTS; i++)
     {
-      PangoLayout *layout = pango_cairo_create_layout (cairo);
+      PangoContext *context = pango_cairo_create_context (cairo);
+      pango_cairo_context_set_resolution (context, 72.0);
+      PangoLayout *layout = pango_layout_new (context);
+      g_object_unref (context);
       pango_layout_set_font_description (layout, fonts[i]);
 
       pango_layout_set_text (layout, "0", 1);
@@ -322,7 +316,11 @@ xr_render_page_heading (cairo_t *cairo, const PangoFontDescription *font,
                         const struct page_heading *ph, int page_number,
                         int width, bool draw, int base_y)
 {
-  PangoLayout *layout = pango_cairo_create_layout (cairo);
+  PangoContext *context = pango_cairo_create_context (cairo);
+  pango_cairo_context_set_resolution (context, 72.0);
+  PangoLayout *layout = pango_layout_new (context);
+  g_object_unref (context);
+
   pango_layout_set_font_description (layout, font);
 
   int y = 0;
@@ -432,7 +430,7 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo)
         .min_break = { [H] = xr->min_break[H], [V] = xr->min_break[V] },
         .use_system_colors = xr->systemcolors,
         .transparent = xr->transparent,
-        .font_scale = xr->font_scale,
+        .font_resolution = 72.0,
       };
 
       for (size_t i = 0; i < XR_N_FONTS; i++)
@@ -449,7 +447,7 @@ xr_create (struct file_handle *fh, enum settings_output_devices device_type,
            struct string_map *o, enum xr_output_type file_type)
 {
   const char *file_name = fh_get_file_name (fh);
-  struct xr_driver *xr = xr_allocate (file_name, device_type, o, 72.0 / 128.0);
+  struct xr_driver *xr = xr_allocate (file_name, device_type, o);
 
   double paper_pt[TABLE_N_AXES];
   for (int a = 0; a < TABLE_N_AXES; a++)
@@ -729,7 +727,7 @@ static const struct output_driver_class cairo_driver_class =
 struct xr_driver *
 xr_driver_create (cairo_t *cairo, struct string_map *options)
 {
-  struct xr_driver *xr = xr_allocate ("cairo", 0, options, 1.0);
+  struct xr_driver *xr = xr_allocate ("cairo", 0, options);
   xr_set_cairo (xr, cairo);
   return xr;
 }
index 8ad190418471eda06c774dfe2296e5c924495c50..626d52e07e710c525a31c21e3eb0a959ec970582 100644 (file)
@@ -165,7 +165,7 @@ get_xr_fsm_style (struct psppire_output_view *view)
     },
     .use_system_colors = true,
     .transparent = true,
-    .font_scale = 1.0,
+    .font_resolution = 96.0,
   };
 
   return style;