render: Render table_items instead of tables.
[pspp] / src / output / render.c
index e1cec909f8b6ad1387d530e30f2270e79f12a5fe..5f2a9d024d89215cbc77c152acc6f14307b4ddc4 100644 (file)
@@ -25,6 +25,7 @@
 #include "libpspp/hash-functions.h"
 #include "libpspp/hmap.h"
 #include "output/render.h"
+#include "output/table-item.h"
 #include "output/table.h"
 
 #include "gl/minmax.h"
 
    May represent the layout of an entire table presented to
    render_page_create(), or a rectangular subregion of a table broken out using
-   render_break_next() to allow a table to be broken across multiple pages. */
+   render_break_next() to allow a table to be broken across multiple pages.
+
+   A page's size is not limited to the size passed in as part of render_params.
+   render_pager breaks a render_page into smaller render_pages that will fit in
+   the available space. */
 struct render_page
   {
     const struct render_params *params; /* Parameters of the target device. */
@@ -120,6 +125,11 @@ struct render_page
     int *join_crossing[TABLE_N_AXES];
   };
 
+static struct render_page *render_page_create (const struct render_params *,
+                                               const struct table *);
+
+static void render_page_unref (struct render_page *);
+
 /* Returns the offset in struct render_page's cp[axis] array of the rule with
    index RULE_IDX.  That is, if RULE_IDX is 0, then the offset is that of the
    leftmost or topmost rule; if RULE_IDX is 1, then the offset is that of the
@@ -607,7 +617,7 @@ set_join_crossings (struct render_page *page, enum table_axis axis,
    The new render_page will be suitable for rendering on a device whose page
    size is PARAMS->size, but the caller is responsible for actually breaking it
    up to fit on such a device, using the render_break abstraction.  */
-struct render_page *
+static struct render_page *
 render_page_create (const struct render_params *params,
                     const struct table *table_)
 {
@@ -783,18 +793,9 @@ render_page_create (const struct render_params *params,
   return page;
 }
 
-/* Increases PAGE's reference count. */
-struct render_page *
-render_page_ref (const struct render_page *page_)
-{
-  struct render_page *page = CONST_CAST (struct render_page *, page_);
-  page->ref_cnt++;
-  return page;
-}
-
 /* Decreases PAGE's reference count and destroys PAGE if this causes the
    reference count to fall to zero. */
-void
+static void
 render_page_unref (struct render_page *page)
 {
   if (page != NULL && --page->ref_cnt == 0)
@@ -1301,6 +1302,7 @@ cell_is_breakable (const struct render_break *b, int cell)
 struct render_pager
   {
     int width;
+    struct render_page *page;
     struct render_break x_break;
     struct render_break y_break;
   };
@@ -1308,11 +1310,13 @@ struct render_pager
 /* Creates and returns a new render_pager for breaking PAGE into smaller
    chunks.  Takes ownership of PAGE. */
 struct render_pager *
-render_pager_create (struct render_page *page)
+render_pager_create (const struct render_params *params,
+                     const struct table_item *table_item)
 {
   struct render_pager *p = xmalloc (sizeof *p);
-  p->width = page->params->size[H];
-  render_break_init (&p->x_break, page, H);
+  p->width = params->size[H];
+  p->page = render_page_create (params, table_item_get_table (table_item));
+  render_break_init (&p->x_break, p->page, H);
   render_break_init_empty (&p->y_break);
   return p;
 }
@@ -1325,6 +1329,7 @@ render_pager_destroy (struct render_pager *p)
     {
       render_break_destroy (&p->x_break);
       render_break_destroy (&p->y_break);
+      render_page_unref (p->page);
       free (p);
     }
 }
@@ -1355,17 +1360,59 @@ render_pager_has_next (const struct render_pager *p_)
   return true;
 }
 
-/* Returns the next render_page from P to render in a space that has vertical
-   size SPACE and the horizontal size as specified in render_params passed to
-   render_page_create().  The caller takes ownership of the returned
-   render_page.  If no content remains to render, or if SPACE is too small to
-   render anything, returns NULL. */
-struct render_page *
-render_pager_next (struct render_pager *p, int space)
+/* Draws a chunk of content from P to fit in a space that has vertical size
+   SPACE and the horizontal size specified in the render_params passed to
+   render_page_create().  Returns the amount of space actually used by the
+   rendered chunk, which will be 0 if SPACE is too small to render anything or
+   if no content remains (use render_pager_has_next() to distinguish these
+   cases). */
+int
+render_pager_draw_next (struct render_pager *p, int space)
+{
+  struct render_page *page = (render_pager_has_next (p)
+                              ? render_break_next (&p->y_break, space)
+                              : NULL);
+  if (page)
+    {
+      int used = render_page_get_size (page, V);
+
+      render_page_draw (page);
+      render_page_unref (page);
+      return used;
+    }
+  else
+    return 0;
+}
+
+/* Draws all of P's content. */
+void
+render_pager_draw (const struct render_pager *p)
+{
+  render_page_draw (p->page);
+}
+
+/* Draws the region of P's content that lies in the region (X,Y)-(X+W,Y+H).
+   Some extra content might be drawn; the device should perform clipping as
+   necessary. */
+void
+render_pager_draw_region (const struct render_pager *p,
+                          int x, int y, int w, int h)
+{
+  render_page_draw_region (p->page, x, y, w, h);
+}
+
+/* Returns the size of P's content along AXIS; i.e. the content's width if AXIS
+   is TABLE_HORZ and its length if AXIS is TABLE_VERT. */
+int
+render_pager_get_size (const struct render_pager *p, enum table_axis axis)
+{
+  return render_page_get_size (p->page, axis);
+}
+
+int
+render_pager_get_best_breakpoint (const struct render_pager *p, int height)
 {
-  return (render_pager_has_next (p)
-          ? render_break_next (&p->y_break, space)
-          : NULL);
+  return render_page_get_best_breakpoint (p->page, height);
 }
 \f
 /* render_page_select() and helpers. */