FORMATS: Allow an optional slash before each set of variable names.
[pspp-builds.git] / src / output / render.c
index 1b92b8bb5ee22d73f7c4c2b1c35d730b4a6cb3eb..6722a13dc2e1100a99fc0f3d8b971a14150e665e 100644 (file)
@@ -359,9 +359,14 @@ distribute_spanned_width (int width,
      w1 by the common denominator of all three calculations (d), dividing that
      out in the column width calculation, and then keeping the remainder for
      the next iteration.
      w1 by the common denominator of all three calculations (d), dividing that
      out in the column width calculation, and then keeping the remainder for
      the next iteration.
+
+     (We actually compute the unspanned width of a column as twice the
+     unspanned width, plus the width of the rule on the left, plus the width of
+     the rule on the right.  That way each rule contributes to both the cell on
+     its left and on its right.)
   */
   d0 = n;
   */
   d0 = n;
-  d1 = total_unspanned * 2.0;
+  d1 = 2.0 * (total_unspanned > 0 ? total_unspanned : 1.0);
   d = d0 * d1;
   if (total_unspanned > 0)
     d *= 2.0;
   d = d0 * d1;
   if (total_unspanned > 0)
     d *= 2.0;
@@ -778,6 +783,7 @@ render_page_unref (struct render_page *page)
 {
   if (page != NULL && --page->ref_cnt == 0)
     {
 {
   if (page != NULL && --page->ref_cnt == 0)
     {
+      int i;
       struct render_overflow *overflow, *next;
 
       HMAP_FOR_EACH_SAFE (overflow, next, struct render_overflow, node,
       struct render_overflow *overflow, *next;
 
       HMAP_FOR_EACH_SAFE (overflow, next, struct render_overflow, node,
@@ -786,8 +792,13 @@ render_page_unref (struct render_page *page)
       hmap_destroy (&page->overflows);
 
       table_unref (page->table);
       hmap_destroy (&page->overflows);
 
       table_unref (page->table);
-      free (page->cp[H]);
-      free (page->cp[V]);
+      
+      for (i = 0; i < TABLE_N_AXES; ++i)
+       {
+         free (page->join_crossing[i]);
+         free (page->cp[i]);
+       }
+
       free (page);
     }
 }
       free (page);
     }
 }
@@ -902,15 +913,15 @@ render_cell (const struct render_page *page, const struct table_cell *cell)
   page->params->draw_cell (page->params->aux, cell, bb, clip);
 }
 
   page->params->draw_cell (page->params->aux, cell, bb, clip);
 }
 
-/* Renders PAGE, by calling the 'draw_line' and 'draw_cell' functions from the
-   render_params provided to render_page_create(). */
-void
-render_page_draw (const struct render_page *page)
+/* Draws the cells of PAGE indicated in BB. */
+static void
+render_page_draw_cells (const struct render_page *page,
+                        int bb[TABLE_N_AXES][2])
 {
   int x, y;
 
 {
   int x, y;
 
-  for (y = 0; y <= page->n[V] * 2; y++)
-    for (x = 0; x <= page->n[H] * 2; )
+  for (y = bb[V][0]; y < bb[V][1]; y++)
+    for (x = bb[H][0]; x < bb[H][1]; )
       if (is_rule (x) || is_rule (y))
         {
           int d[TABLE_N_AXES];
       if (is_rule (x) || is_rule (y))
         {
           int d[TABLE_N_AXES];
@@ -924,12 +935,91 @@ render_page_draw (const struct render_page *page)
           struct table_cell cell;
 
           table_get_cell (page->table, x / 2, y / 2, &cell);
           struct table_cell cell;
 
           table_get_cell (page->table, x / 2, y / 2, &cell);
-          if (y / 2 == cell.d[V][0])
+          if (y == bb[V][0] || y / 2 == cell.d[V][0])
             render_cell (page, &cell);
           x = rule_ofs (cell.d[H][1]);
           table_cell_free (&cell);
         }
 }
             render_cell (page, &cell);
           x = rule_ofs (cell.d[H][1]);
           table_cell_free (&cell);
         }
 }
+
+/* Renders PAGE, by calling the 'draw_line' and 'draw_cell' functions from the
+   render_params provided to render_page_create(). */
+void
+render_page_draw (const struct render_page *page)
+{
+  int bb[TABLE_N_AXES][2];
+
+  bb[H][0] = 0;
+  bb[H][1] = page->n[H] * 2 + 1;
+  bb[V][0] = 0;
+  bb[V][1] = page->n[V] * 2 + 1;
+
+  render_page_draw_cells (page, bb);
+}
+
+/* Returns the greatest value i, 0 <= i < n, such that cp[i] <= x0. */
+static int
+get_clip_min_extent (int x0, const int cp[], int n)
+{
+  int low, high, best;
+
+  low = 0;
+  high = n;
+  best = 0;
+  while (low < high)
+    {
+      int middle = low + (high - low) / 2;
+
+      if (cp[middle] <= x0)
+        {
+          best = middle;
+          low = middle + 1;
+        }
+      else
+        high = middle;
+    }
+
+  return best;
+}
+
+/* Returns the least value i, 0 <= i < n, such that cp[i + 1] >= x1. */
+static int
+get_clip_max_extent (int x1, const int cp[], int n)
+{
+  int low, high, best;
+
+  low = 0;
+  high = n;
+  best = n;
+  while (low < high)
+    {
+      int middle = low + (high - low) / 2;
+
+      if (cp[middle] >= x1)
+        best = high = middle;
+      else
+        low = middle + 1;
+    }
+
+  return best;
+}
+
+/* Renders the cells of PAGE that intersect (X,Y)-(X+W,Y+H), by calling the
+   'draw_line' and 'draw_cell' functions from the render_params provided to
+   render_page_create(). */
+void
+render_page_draw_region (const struct render_page *page,
+                         int x, int y, int w, int h)
+{
+  int bb[TABLE_N_AXES][2];
+
+  bb[H][0] = get_clip_min_extent (x, page->cp[H], page->n[H] * 2 + 1);
+  bb[H][1] = get_clip_max_extent (x + w, page->cp[H], page->n[H] * 2 + 1);
+  bb[V][0] = get_clip_min_extent (y, page->cp[V], page->n[V] * 2 + 1);
+  bb[V][1] = get_clip_max_extent (y + h, page->cp[V], page->n[V] * 2 + 1);
+
+  render_page_draw_cells (page, bb);
+}
 \f
 /* Breaking up tables to fit on a page. */
 
 \f
 /* Breaking up tables to fit on a page. */
 
@@ -972,7 +1062,10 @@ void
 render_break_destroy (struct render_break *b)
 {
   if (b != NULL)
 render_break_destroy (struct render_break *b)
 {
   if (b != NULL)
-    render_page_unref (b->page);
+    {
+      render_page_unref (b->page);
+      b->page = NULL;
+    }
 }
 
 /* Returns true if B still has cells that are yet to be returned,
 }
 
 /* Returns true if B still has cells that are yet to be returned,
@@ -1124,7 +1217,7 @@ render_page_select (const struct render_page *page, enum table_axis axis,
   if (z0 == page->h[a][0] && p0 == 0
       && z1 == page->n[a] - page->h[a][1] && p1 == 0)
     {
   if (z0 == page->h[a][0] && p0 == 0
       && z1 == page->n[a] - page->h[a][1] && p1 == 0)
     {
-      struct render_page *page_rw = (struct render_page *) page;
+      struct render_page *page_rw = CONST_CAST (struct render_page *, page);
       page_rw->ref_cnt++;
       return page_rw;
     }
       page_rw->ref_cnt++;
       return page_rw;
     }
@@ -1311,4 +1404,3 @@ insert_overflow (struct render_page_selection *s,
 
   return of;
 }
 
   return of;
 }
-