cairo: Get rid of xr_render_fsm.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 7 Dec 2020 03:40:39 +0000 (19:40 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 13 Dec 2020 19:25:12 +0000 (11:25 -0800)
src/output/cairo.c

index 2556ab6fc16e621e366784ca9538f351e789193f..f08e27b3193cae9a4373a1c425ba1b9db971e299 100644 (file)
@@ -114,18 +114,6 @@ struct xr_font
     PangoLayout *layout;
   };
 
-/* An output item whose rendering is in progress. */
-struct xr_render_fsm
-  {
-    /* Renders as much of itself as it can on the current page.  Returns true
-       if rendering is complete, false if the output item needs another
-       page. */
-    bool (*render) (struct xr_render_fsm *, struct xr_driver *);
-
-    /* Destroys the output item. */
-    void (*destroy) (struct xr_render_fsm *);
-  };
-
 /* Cairo output driver. */
 struct xr_driver
   {
@@ -157,13 +145,14 @@ struct xr_driver
 
     /* Internal state. */
     struct render_params *params;
+    struct xr_fsm_style *style;
     double font_scale;
     int char_width, char_height;
     cairo_t *cairo;
     cairo_surface_t *surface;
     int page_number;           /* Current page number. */
     int y;
-    struct xr_render_fsm *fsm;
+    struct xr_fsm *fsm;
   };
 
 static const struct output_driver_class cairo_driver_class;
@@ -184,9 +173,6 @@ static void xr_draw_cell (void *, const struct table_cell *, int color_idx,
                           int clip[TABLE_N_AXES][2]);
 static int xr_adjust_break (void *, const struct table_cell *,
                             int width, int height);
-
-static struct xr_render_fsm *xr_render_output_item (
-  struct xr_driver *, const struct output_item *);
 \f
 /* Output driver basics. */
 
@@ -531,6 +517,22 @@ xr_set_cairo (struct xr_driver *xr, cairo_t *cairo)
       xr->params->rtl = render_direction_rtl ();
     }
 
+  if (xr->style == NULL)
+    {
+      xr->style = xmalloc (sizeof *xr->style);
+      *xr->style = (struct xr_fsm_style) {
+        .ref_cnt = 1,
+        .size = { [H] = xr->width, [V] = xr->length },
+        .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,
+      };
+
+      for (size_t i = 0; i < XR_N_FONTS; i++)
+        xr->style->fonts[i] = pango_font_description_copy (xr->fonts[i].desc);
+    }
+
   if (!xr->systemcolors)
     cairo_set_source_rgb (xr->cairo,
                          xr->fg.r / 255.0, xr->fg.g / 255.0, xr->fg.b / 255.0);
@@ -625,6 +627,7 @@ xr_destroy (struct output_driver *driver)
         g_object_unref (font->layout);
     }
 
+  xr_fsm_style_unref (xr->style);
   free (xr->params);
   free (xr);
 }
@@ -757,7 +760,7 @@ xr_driver_output_item (struct xr_driver *xr,
                        const struct output_item *output_item)
 {
   assert (xr->fsm == NULL);
-  xr->fsm = xr_render_output_item (xr, output_item);
+  xr->fsm = xr_fsm_create (output_item, xr->style, xr->cairo);
   xr_driver_run_fsm (xr);
 }
 
@@ -780,18 +783,24 @@ xr_driver_is_page_blank (const struct xr_driver *xr)
 static void
 xr_driver_destroy_fsm (struct xr_driver *xr)
 {
-  if (xr->fsm != NULL)
-    {
-      xr->fsm->destroy (xr->fsm);
-      xr->fsm = NULL;
-    }
+  xr_fsm_destroy (xr->fsm);
+  xr->fsm = NULL;
 }
 
 static void
 xr_driver_run_fsm (struct xr_driver *xr)
 {
-  if (xr->fsm != NULL && !xr->fsm->render (xr->fsm, xr))
-    xr_driver_destroy_fsm (xr);
+  if (xr->fsm != NULL)
+    {
+      cairo_save (xr->cairo);
+      cairo_translate (xr->cairo, 0, xr_to_pt (xr->y));
+      int used = xr_fsm_draw_slice (xr->fsm, xr->cairo, xr->length - xr->y);
+      xr->y += used;
+      cairo_restore (xr->cairo);
+
+      if (xr_fsm_is_empty (xr->fsm))
+        xr_driver_destroy_fsm (xr);
+    }
 }
 \f
 static void
@@ -1695,179 +1704,3 @@ xr_draw_eps_chart (const struct chart_item *item,
   return file_name;
 }
 
-\f
-
-struct xr_table_state
-  {
-    struct xr_render_fsm fsm;
-    struct render_pager *p;
-  };
-
-static bool
-xr_table_render (struct xr_render_fsm *fsm, struct xr_driver *xr)
-{
-  struct xr_table_state *ts = UP_CAST (fsm, struct xr_table_state, fsm);
-
-  while (render_pager_has_next (ts->p))
-    {
-      int used;
-
-      used = render_pager_draw_next (ts->p, xr->length - xr->y);
-      if (!used)
-        {
-          assert (xr->y > 0);
-          return true;
-        }
-      else
-        xr->y += used;
-    }
-  return false;
-}
-
-static void
-xr_table_destroy (struct xr_render_fsm *fsm)
-{
-  struct xr_table_state *ts = UP_CAST (fsm, struct xr_table_state, fsm);
-
-  render_pager_destroy (ts->p);
-  free (ts);
-}
-
-static struct xr_render_fsm *
-xr_render_table (struct xr_driver *xr, struct table_item *table_item)
-{
-  struct xr_table_state *ts;
-
-  ts = xmalloc (sizeof *ts);
-  ts->fsm.render = xr_table_render;
-  ts->fsm.destroy = xr_table_destroy;
-
-  if (xr->y > 0)
-    xr->y += xr->char_height;
-
-  ts->p = render_pager_create (xr->params, table_item);
-  table_item_unref (table_item);
-
-  return &ts->fsm;
-}
-\f
-struct xr_chart_state
-  {
-    struct xr_render_fsm fsm;
-    struct chart_item *chart_item;
-  };
-
-static bool
-xr_chart_render (struct xr_render_fsm *fsm, struct xr_driver *xr)
-{
-  struct xr_chart_state *cs = UP_CAST (fsm, struct xr_chart_state, fsm);
-
-  const int chart_height = 0.8 * (xr->length < xr->width ? xr->length : xr->width);
-
-  if (xr->y > xr->length - chart_height)
-    return true;
-
-  if (xr->cairo != NULL)
-    {
-      xr_draw_chart (cs->chart_item, xr->cairo,
-                    0.0,
-                    xr_to_pt (xr->y),
-                    xr_to_pt (xr->width),
-                    xr_to_pt (chart_height));
-    }
-  xr->y += chart_height;
-
-  return false;
-}
-
-static void
-xr_chart_destroy (struct xr_render_fsm *fsm)
-{
-  struct xr_chart_state *cs = UP_CAST (fsm, struct xr_chart_state, fsm);
-
-  chart_item_unref (cs->chart_item);
-  free (cs);
-}
-
-static struct xr_render_fsm *
-xr_render_chart (const struct chart_item *chart_item)
-{
-  struct xr_chart_state *cs;
-
-  cs = xmalloc (sizeof *cs);
-  cs->fsm.render = xr_chart_render;
-  cs->fsm.destroy = xr_chart_destroy;
-  cs->chart_item = chart_item_ref (chart_item);
-
-  return &cs->fsm;
-}
-\f
-static bool
-xr_eject_render (struct xr_render_fsm *fsm UNUSED, struct xr_driver *xr)
-{
-  return xr->y > 0;
-}
-
-static void
-xr_eject_destroy (struct xr_render_fsm *fsm UNUSED)
-{
-  /* Nothing to do. */
-}
-
-static struct xr_render_fsm *
-xr_render_eject (void)
-{
-  static struct xr_render_fsm eject_renderer =
-    {
-      xr_eject_render,
-      xr_eject_destroy
-    };
-
-  return &eject_renderer;
-}
-\f
-static struct xr_render_fsm *
-xr_render_text (struct xr_driver *xr, const struct text_item *text_item)
-{
-  enum text_item_type type = text_item_get_type (text_item);
-
-  switch (type)
-    {
-    case TEXT_ITEM_PAGE_TITLE:
-      break;
-
-    default:
-      return xr_render_table (
-        xr, text_item_to_table_item (text_item_ref (text_item)));
-    }
-
-  return NULL;
-}
-
-static struct xr_render_fsm *
-xr_render_message (struct xr_driver *xr,
-                   const struct message_item *message_item)
-{
-  char *s = msg_to_string (message_item_get_msg (message_item));
-  struct text_item *item = text_item_create (TEXT_ITEM_LOG, s);
-  free (s);
-  return xr_render_table (xr, text_item_to_table_item (item));
-}
-
-static struct xr_render_fsm *
-xr_render_output_item (struct xr_driver *xr,
-                       const struct output_item *output_item)
-{
-  if (is_table_item (output_item))
-    return xr_render_table (xr, table_item_ref (to_table_item (output_item)));
-  else if (is_chart_item (output_item))
-    return xr_render_chart (to_chart_item (output_item));
-  else if (is_text_item (output_item))
-    return xr_render_text (xr, to_text_item (output_item));
-  else if (is_page_eject_item (output_item))
-    return xr->y > 0 ? xr_render_eject () : NULL;
-  else if (is_message_item (output_item))
-    return xr_render_message (xr, to_message_item (output_item));
-  else
-    return NULL;
-}