pivot-table: Implement hiding footnotes.
[pspp] / src / output / cairo-fsm.c
index df8df7e68fec0b0f2303e8b156fffe587dd5185b..2df39754343b966b3305c6a7393b17a3c9989625 100644 (file)
@@ -38,6 +38,7 @@
 #include "output/charts/scree.h"
 #include "output/charts/spreadlevel-plot.h"
 #include "output/group-item.h"
+#include "output/image-item.h"
 #include "output/message-item.h"
 #include "output/page-eject-item.h"
 #include "output/page-setup-item.h"
@@ -760,14 +761,17 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell,
         }
 
       size_t footnote_ofs = ds_length (&body);
+      size_t n_footnotes = 0;
       for (size_t i = 0; i < value->n_footnotes; i++)
         {
-          if (i)
-            ds_put_byte (&body, ',');
-
-          size_t idx = value->footnote_indexes[i];
-          const struct pivot_footnote *f = pt->footnotes[idx];
-          pivot_value_format (f->marker, pt, &body);
+          const struct pivot_footnote *f
+            = pt->footnotes[value->footnote_indexes[i]];
+          if (f->show)
+            {
+              if (n_footnotes++)
+                ds_put_byte (&body, ',');
+              pivot_footnote_format_marker (f, pt, &body);
+            }
         }
 
       /* Allow footnote markers to occupy the right margin.  That way, numbers
@@ -811,8 +815,11 @@ xr_layout_cell_text (struct xr_fsm *xr, const struct table_cell *cell,
         add_attr (attrs, pango_attr_rise_new (-3000), subscript_ofs,
                   footnote_ofs - subscript_ofs);
       if (value->n_footnotes)
-        add_attr (attrs, pango_attr_rise_new (3000), footnote_ofs,
-                  PANGO_ATTR_INDEX_TO_TEXT_END);
+        {
+          bool superscript = pt->look->footnote_marker_superscripts;
+          add_attr (attrs, pango_attr_rise_new (superscript ? 3000 : -3000),
+                    footnote_ofs, PANGO_ATTR_INDEX_TO_TEXT_END);
+        }
     }
 
   /* Set the attributes, if any. */
@@ -987,6 +994,7 @@ xr_fsm_create (const struct output_item *item_,
   struct output_item *item;
   if (is_table_item (item_)
       || is_chart_item (item_)
+      || is_image_item (item_)
       || is_page_eject_item (item_))
     item = output_item_ref (item_);
   else if (is_message_item (item_))
@@ -1017,6 +1025,7 @@ xr_fsm_create (const struct output_item *item_,
     NOT_REACHED ();
   assert (is_table_item (item)
           || is_chart_item (item)
+          || is_image_item (item)
           || is_page_eject_item (item));
 
   size_t *layer_indexes = NULL;
@@ -1147,6 +1156,12 @@ xr_fsm_measure (struct xr_fsm *fsm, cairo_t *cr, int *wp, int *hp)
       w = CHART_WIDTH;
       h = CHART_HEIGHT;
     }
+  else if (is_image_item (fsm->item))
+    {
+      cairo_surface_t *image = to_image_item (fsm->item)->image;
+      w = cairo_image_surface_get_width (image);
+      h = cairo_image_surface_get_height (image);
+    }
   else
     NOT_REACHED ();
 
@@ -1171,6 +1186,18 @@ mul_XR_POINT (int x)
           : x * XR_POINT);
 }
 
+static void
+draw_image (cairo_surface_t *image, cairo_t *cr)
+{
+  cairo_save (cr);
+  cairo_set_source_surface (cr, image, 0, 0);
+  cairo_rectangle (cr, 0, 0, cairo_image_surface_get_width (image),
+                   cairo_image_surface_get_height (image));
+  cairo_clip (cr);
+  cairo_paint (cr);
+  cairo_restore (cr);
+}
+
 void
 xr_fsm_draw_region (struct xr_fsm *fsm, cairo_t *cr,
                     int x, int y, int w, int h)
@@ -1183,6 +1210,8 @@ xr_fsm_draw_region (struct xr_fsm *fsm, cairo_t *cr,
                                 mul_XR_POINT (w), mul_XR_POINT (h));
       fsm->cairo = NULL;
     }
+  else if (is_image_item (fsm->item))
+    draw_image (to_image_item (fsm->item)->image, cr);
   else if (is_chart_item (fsm->item))
     xr_draw_chart (to_chart_item (fsm->item), cr, CHART_WIDTH, CHART_HEIGHT);
   else if (is_page_eject_item (fsm->item))
@@ -1237,6 +1266,49 @@ xr_fsm_draw_chart (struct xr_fsm *fsm, int space)
   return chart_height;
 }
 
+static int
+xr_fsm_draw_image (struct xr_fsm *fsm, int space)
+{
+  cairo_surface_t *image = to_image_item (fsm->item)->image;
+  int width = cairo_image_surface_get_width (image) * XR_POINT;
+  int height = cairo_image_surface_get_height (image) * XR_POINT;
+  if (!width || !height)
+    goto error;
+
+  if (height > fsm->rp.size[V])
+    {
+      double scale = fsm->rp.size[V] / (double) height;
+      width *= scale;
+      height *= scale;
+      if (!width || !height)
+        goto error;
+
+      cairo_scale (fsm->cairo, scale, scale);
+    }
+
+  if (width > fsm->rp.size[H])
+    {
+      double scale = fsm->rp.size[H] / (double) width;
+      width *= scale;
+      height *= scale;
+      if (!width || !height)
+        goto error;
+
+      cairo_scale (fsm->cairo, scale, scale);
+    }
+
+  if (space < height)
+    return 0;
+
+  draw_image (image, fsm->cairo);
+  fsm->done = true;
+  return height;
+
+error:
+  fsm->done = true;
+  return 0;
+}
+
 static int
 xr_fsm_draw_eject (struct xr_fsm *fsm, int space)
 {
@@ -1250,13 +1322,14 @@ xr_fsm_draw_slice (struct xr_fsm *fsm, cairo_t *cr, int space)
 {
   assert (fsm->print);
 
-  if (fsm->done)
+  if (fsm->done || space <= 0)
     return 0;
 
   cairo_save (cr);
   fsm->cairo = cr;
   int used = (is_table_item (fsm->item) ? xr_fsm_draw_table (fsm, space)
               : is_chart_item (fsm->item) ? xr_fsm_draw_chart (fsm, space)
+              : is_image_item (fsm->item) ? xr_fsm_draw_image (fsm, space)
               : is_page_eject_item (fsm->item) ? xr_fsm_draw_eject (fsm, space)
               : (abort (), 0));
   fsm->cairo = NULL;