cairo: Fix memory leak of pango_layout_iter.
[pspp] / src / output / cairo.c
index a3070dddef3e2e69dc65ff58a3c4c8f1b82d7739..1a8c78c69fe0d0062dcb379aa0f4d758c2ebb48c 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
 #include "libpspp/str.h"
 #include "libpspp/string-map.h"
 #include "libpspp/version.h"
+#include "data/file-handle-def.h"
 #include "output/cairo-chart.h"
 #include "output/chart-item-provider.h"
 #include "output/charts/boxplot.h"
@@ -475,24 +476,30 @@ xr_create (const char *file_name, enum settings_output_devices device_type,
 }
 
 static struct output_driver *
-xr_pdf_create (const char *file_name, enum settings_output_devices device_type,
+xr_pdf_create (struct  file_handle *fh, enum settings_output_devices device_type,
                struct string_map *o)
 {
-  return xr_create (file_name, device_type, o, XR_PDF);
+  struct output_driver *od = xr_create (fh_get_file_name (fh), device_type, o, XR_PDF);
+  fh_unref (fh);
+  return od ;
 }
 
 static struct output_driver *
-xr_ps_create (const char *file_name, enum settings_output_devices device_type,
+xr_ps_create (struct  file_handle *fh, enum settings_output_devices device_type,
                struct string_map *o)
 {
-  return xr_create (file_name, device_type, o, XR_PS);
+  struct output_driver *od =  xr_create (fh_get_file_name (fh), device_type, o, XR_PS);
+  fh_unref (fh);
+  return od ;
 }
 
 static struct output_driver *
-xr_svg_create (const char *file_name, enum settings_output_devices device_type,
+xr_svg_create (struct file_handle *fh, enum settings_output_devices device_type,
                struct string_map *o)
 {
-  return xr_create (file_name, device_type, o, XR_SVG);
+  struct output_driver *od = xr_create (fh_get_file_name (fh), device_type, o, XR_SVG);
+  fh_unref (fh);
+  return od ;
 }
 
 static void
@@ -704,9 +711,9 @@ xr_draw_line (void *xr_, int bb[TABLE_N_AXES][2],
   const int x3 = bb[H][1];
   const int y3 = bb[V][1];
   const int top = styles[H][0];
-  const int left = styles[V][0];
   const int bottom = styles[H][1];
-  const int right = styles[V][1];
+  const int start_of_line = render_direction_rtl() ? styles[V][1]: styles[V][0];
+  const int end_of_line   = render_direction_rtl() ? styles[V][0]: styles[V][1];
 
   /* The algorithm here is somewhat subtle, to allow it to handle
      all the kinds of intersections that we need.
@@ -746,7 +753,7 @@ xr_draw_line (void *xr_, int bb[TABLE_N_AXES][2],
      (It doesn't make sense to have different kinds of line on the
      same axis, so we don't try to gracefully handle that case.) */
   bool double_vert = top == RENDER_LINE_DOUBLE || bottom == RENDER_LINE_DOUBLE;
-  bool double_horz = left == RENDER_LINE_DOUBLE || right == RENDER_LINE_DOUBLE;
+  bool double_horz = start_of_line == RENDER_LINE_DOUBLE || end_of_line == RENDER_LINE_DOUBLE;
 
   /* When horizontal lines are doubled,
      the left-side line along y1 normally runs from x0 to x2,
@@ -781,8 +788,8 @@ xr_draw_line (void *xr_, int bb[TABLE_N_AXES][2],
   int x1 = xc - horz_line_ofs;
   int x2 = xc + horz_line_ofs;
 
-  bool shorten_x1_lines = left == RENDER_LINE_DOUBLE;
-  bool shorten_x2_lines = right == RENDER_LINE_DOUBLE;
+  bool shorten_x1_lines = start_of_line == RENDER_LINE_DOUBLE;
+  bool shorten_x2_lines = end_of_line == RENDER_LINE_DOUBLE;
   bool shorten_xc_line = shorten_x1_lines && shorten_x2_lines;
   int vert_line_ofs = double_horz ? double_line_ofs : 0;
   int yc = (y0 + y3) / 2;
@@ -790,11 +797,11 @@ xr_draw_line (void *xr_, int bb[TABLE_N_AXES][2],
   int y2 = yc + vert_line_ofs;
 
   if (!double_horz)
-    horz_line (xr, x0, x1, x2, x3, yc, left, right, shorten_yc_line);
+    horz_line (xr, x0, x1, x2, x3, yc, start_of_line, end_of_line, shorten_yc_line);
   else
     {
-      horz_line (xr, x0, x1, x2, x3, y1, left, right, shorten_y1_lines);
-      horz_line (xr, x0, x1, x2, x3, y2, left, right, shorten_y2_lines);
+      horz_line (xr, x0, x1, x2, x3, y1, start_of_line, end_of_line, shorten_y1_lines);
+      horz_line (xr, x0, x1, x2, x3, y2, start_of_line, end_of_line, shorten_y2_lines);
     }
 
   if (!double_vert)
@@ -842,8 +849,6 @@ xr_measure_cell_height (void *xr_, const struct table_cell *cell,
 
   bb[H][0] = 0;
   bb[H][1] = width - xr->cell_margin * 2;
-  if (bb[H][1] <= 0)
-    return 0;
   bb[V][0] = 0;
   bb[V][1] = INT_MAX;
   clip[H][0] = clip[H][1] = clip[V][0] = clip[V][1] = 0;
@@ -1079,6 +1084,7 @@ xr_layout_cell_text (struct xr_driver *xr,
             break;
         }
       while (pango_layout_iter_next_line (iter));
+      pango_layout_iter_free (iter);
 
       /* If enabled, draws a green line across the chosen breakpoint, which can
          be useful for debugging issues with breaking.  */