changeset 9107:d0d507cbd123

Improvements to printing functionality.
author Ben Abbott <bpabbott@mac.com>
date Fri, 10 Apr 2009 12:11:14 -0400
parents 1eb5b24186b6
children b2459d21a207
files scripts/ChangeLog scripts/plot/__gnuplot_get_var__.m scripts/plot/gnuplot_drawnow.m scripts/plot/print.m
diffstat 4 files changed, 159 insertions(+), 105 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,3 +1,14 @@
+2009-04-10  Ben Abbott <bpabbott@mac.com>
+
+	* plot/print.m: If no pdf support in gnuplot, then "convert" from
+	postscript to pdf. For gnuplot 4.2.x use "convert", if it is present,
+	to produce pdf output. Only render a full page for ps/pdf output.
+	Rename variable, "size" to "canvas_size". Reformat help text to
+	eliminate unintended spaces. Minor improvements to the code.
+	* plot/gnuplot_drawnow.m: Place canvas size at the end of the terminal
+	spec, and remove trailing semicolon. Minor improvments to the code.
+	* plot/__gnuplot_get_var__.m: If fifo fails to open, try 2nd time.
+
 2009-04-08  Jaroslav Hajek  <highegg@gmail.com>
 
 	* special-matrix/vander.m: Optimize.
--- a/scripts/plot/__gnuplot_get_var__.m
+++ b/scripts/plot/__gnuplot_get_var__.m
@@ -82,6 +82,10 @@
       fflush (ostream);
       [gpin, err] = fopen (gpin_name, "r");
       if (err != 0)
+        ## Try a second time, and then give an error.
+        [gpin, err] = fopen (gpin_name, "r");
+      endif
+      if (err != 0)
         error ("__gnuplot_get_var__: Can not open fifo.");
       endif
       gp_cmd = sprintf ("\nif (exists(\"%s\")) print %s; else print NaN\n",
--- a/scripts/plot/gnuplot_drawnow.m
+++ b/scripts/plot/gnuplot_drawnow.m
@@ -41,8 +41,7 @@
     printing = ! output_to_screen (gnuplot_trim_term (term));
     default_plot_stream = get (h, "__plot_stream__");
     unwind_protect
-      plot_stream = open_gnuplot_stream (2, []);
-      set (h, "__plot_stream__", plot_stream);
+      plot_stream = open_gnuplot_stream (2, h);
       if (__gnuplot_has_feature__ ("variable_GPVAL_TERMINALS"))
         available_terminals = __gnuplot_get_var__ (plot_stream, "GPVAL_TERMINALS");
         available_terminals = regexp (available_terminals, "\\b\\w+\\b", "match");
@@ -191,7 +190,7 @@
           ## Get size of the printed plot in inches.
           gnuplot_size = get_papersize (h);
           if (term_units_are_pixels (term))
- 	    ## Convert to inches using the property set by print().
+	    ## Convert to inches using the property set by print().
 	    gnuplot_size = gnuplot_size * get (h, "__pixels_per_inch__");
 	  else
 	    ## Implicit margins are in units of "inches"
@@ -277,16 +276,16 @@
       if (! isempty (title_str))
         term_str = sprintf ("%s %s", term_str, title_str);
       endif
+      if (nargin > 3 && ischar (opts_str))
+        ## Options must go last.
+        term_str = sprintf ("%s %s", term_str, opts_str);
+      endif
       if (! isempty (size_str) && new_stream)
         ## size_str goes last to permit specification of canvas size
         ## for terminals cdr/corel.
         term_str = sprintf ("%s %s", term_str, size_str);
       endif
-      if (nargin > 3 && ischar (opts_str))
-        ## Options must go last.
-        term_str = sprintf ("%s %s", term_str, opts_str);
-      endif
-      fprintf (plot_stream, sprintf ("%s;\n", term_str));
+      fprintf (plot_stream, "%s\n", term_str);
     else
       ## gnuplot will pick up the GNUTERM environment variable itself
       ## so no need to set the terminal type if not also setting the
@@ -356,7 +355,7 @@
 endfunction
 
 function ret = term_units_are_pixels (term)
-  ret = any (strcmpi ({"png", "jpeg", "gif", "pbm", "svg"}, term));
+  ret = any (strcmpi ({"emf", "gif", "jpeg", "pbm", "png", "svg"}, term));
 endfunction
 
 function [fig_size, fig_pos] = get_figsize (h)
--- a/scripts/plot/print.m
+++ b/scripts/plot/print.m
@@ -61,10 +61,10 @@
 ##   @itemx pstex
 ##   @itemx pslatex
 ##     Generate a LaTeX (or TeX) file for labels, and eps/ps for
-##     graphics.  The file produced by @code{epslatexstandalone} can be
-##     processed directly by LaTeX.  The other formats are intended to
-##     be included in a LaTeX (or TeX) document.  The @code{tex} device
-##     is the same as the @code{epslatex} device.
+## graphics.  The file produced by @code{epslatexstandalone} can be
+## processed directly by LaTeX.  The other formats are intended to
+## be included in a LaTeX (or TeX) document.  The @code{tex} device
+## is the same as the @code{epslatex} device.
 ##   @item ill
 ##   @itemx aifm
 ##     Adobe Illustrator
@@ -74,12 +74,13 @@
 ##   @item dxf
 ##     AutoCAD
 ##   @item emf
+##   @itemx meta
 ##     Microsoft Enhanced Metafile
 ##   @item fig
 ##     XFig.  If this format is selected the additional options
 ##     @code{-textspecial} or @code{-textnormal} can be used to control
-##     whether the special flag should be set for the text in the figure
-##     (default is @code{-textnormal}). 
+##     whether the special flag should be set for the text in
+##     the figure (default is @code{-textnormal}). 
 ##   @item hpgl
 ##     HP plotter language
 ##   @item mf
@@ -100,27 +101,31 @@
 ##   @end table
 ##
 ##   Other devices are supported by "convert" from ImageMagick.  Type
-##   system("convert") to see what formats are available.
+## system("convert") to see what formats are available.
 ##
 ##   If the device is omitted, it is inferred from the file extension,
-##   or if there is no filename it is sent to the printer as postscript.
+## or if there is no filename it is sent to the printer as postscript.
 ##
 ## @itemx -r@var{NUM}
-##   Resolution of bitmaps in pixels per inch.
+##   Resolution of bitmaps in pixels per inch. For both metafiles and 
+## SVG the default is the screen resolution, for other it is 150 dpi.
+## To specify screen resolution, use "-r0".
 ##
 ## @itemx -S@var{xsize},@var{ysize}
-##   Plot size in pixels for PNG and SVG.  If using the command form of
-##   the print function, you must quote the @var{xsize},@var{ysize}
-##   option.  For example, by writing @code{"-S640,480"}.
+##   Plot size in pixels for EMF, GIF, JPEG, PBM, PNG and SVG. If
+## using the command form of the print function, you must quote the
+## @var{xsize},@var{ysize} option.  For example, by writing
+## @code{"-S640,480"}.  The size defaults to that specified by the
+## figure's paperposition property.
 ##
 ## @item -F@var{fontname}
 ## @itemx -F@var{fontname}:@var{size}
 ## @itemx -F:@var{size}
 ##   @var{fontname} set the postscript font (for use with postscript,
-##   aifm, corel and fig).  By default, 'Helvetica' is set for PS/Aifm,
-##   and 'SwitzerlandLight' for Corel.  It can also be 'Times-Roman'.
-##   @var{size} is given in points.  @var{fontname} is ignored for the
-##   fig device.
+## aifm, corel and fig).  By default, 'Helvetica' is set for PS/Aifm,
+## and 'SwitzerlandLight' for Corel.  It can also be 'Times-Roman'.
+## @var{size} is given in points.  @var{fontname} is ignored for the
+## fig device.
 ## @end table
 ##
 ## The filename and options can be given in any order.
@@ -136,7 +141,7 @@
   force_solid = 0; # 0=default, -1=dashed, +1=solid
   fontsize = "";
   font = "";
-  size = "";
+  canvas_size = "";
   name = "";
   devopt = "";
   printer = "";
@@ -155,7 +160,7 @@
       arg = varargin{i};
       if (ischar (arg))
         if (strcmp (arg, "-color"))
-	use_color = 1;
+	  use_color = 1;
         elseif (strcmp (arg, "-mono"))
 	  use_color = -1;
         elseif (strcmp (arg, "-solid"))
@@ -174,7 +179,7 @@
 	    debug_file = arg(8:end);
 	  endif
         elseif (length (arg) > 2 && arg(1:2) == "-d")
-	  devopt = arg(3:end);
+	  devopt = tolower(arg(3:end));
         elseif (length (arg) > 2 && arg(1:2) == "-P")
 	  printer = arg;
         elseif (length (arg) > 2 && arg(1:2) == "-F")
@@ -186,7 +191,7 @@
 	    font = arg(3:length(arg));
 	  endif
         elseif (length (arg) > 2 && arg(1:2) == "-S")
-	  size = arg(3:length(arg));
+	  canvas_size = arg(3:length(arg));
         elseif (length (arg) > 2 && arg(1:2) == "-r")
 	  resolution = arg(3:length(arg));
         elseif (length (arg) >= 1 && arg(1) == "-")
@@ -232,50 +237,59 @@
       dev = "aifm";
     elseif (strcmp (dev, "cdr"))
       dev = "corel";
+    elseif (strcmp (dev, "meta"))
+      dev = "emf";
+    elseif (strcmp (dev, "jpg"))
+      dev = "jpeg";
     endif
 
-    ## check if we have to use convert
-    dev_list = {"aifm", "corel", "fig", "png", "jpg", "jpeg", ...
-	      "gif", "pbm", "dxf", "mf", "svg", "hpgl", ...
-	      "ps", "ps2", "psc", "psc2", "eps", "eps2", ...
-	      "epsc", "epsc2", "emf", "pdf", "pslatex", ...
-	      "epslatex", "epslatexstandalone", "pstex"};
-    convertname = "";
-    [idx, errmsg] = cellidx (dev_list, dev);
-    if (! idx)
+    ## Check if the specified device is one that is supported by
+    ## gnuplot. If not assume it is one supported by ImageMagick's
+    ## "convert" utility.
+    dev_list = {"aifm", "corel", "fig", "png", "jpeg", ...
+		"gif", "pbm", "dxf", "mf", "svg", "hpgl", ...
+		"ps", "ps2", "psc", "psc2", "eps", "eps2", ...
+		"epsc", "epsc2", "emf", "pdf", "pslatex", ...
+		"epslatex", "epslatexstandalone", "pstex"};
+    if (! any (strcmp (dev, dev_list)))
       if (! isempty (devopt))
-        convertname = cstrcat (devopt, ":", name);
+	## Device has been specified but is not supported by gnuplot.
+        convert_name = cstrcat (devopt, ":", name);
       else
-        convertname = name;
+	## Device has *not* been specified and is not supported by gnuplot.
+        convert_name = name;
       endif
       dev = "epsc";
       name = cstrcat (tmpnam, ".eps");
+    else
+      convert_name = "";
     endif
 
-    if (strcmp (dev, "ps") || strcmp (dev, "ps2")
-        || strcmp (dev, "psc")  || strcmp (dev, "psc2")
-        || strcmp (dev, "epsc") || strcmp (dev, "epsc2")
-        || strcmp (dev, "eps")  || strcmp (dev, "eps2")
-        || strcmp (dev, "pstex")|| strcmp (dev, "pslatex")
-        || strcmp (dev, "epslatex") || strcmp (dev, "epslatexstandalone"))
+    termn = dev;
+
+    ## SVG isn't actually a bitmap, but gnuplot treats its size option as it
+    ## does the bitmap terminals.
+    bitmap_devices = {"emf", "gif", "jpeg", "pbm", "png", "svg"};
+
+    if (any (strcmp (dev, {"ps", "ps2", "psc", "psc2", "epsc", "epsc2", ...
+                           "eps", "eps2", "pstex", "pslatex", "epslatex", ...
+                           "epslatexstandalone"})))
 
       ## Various postscript options
-      if (strcmp (dev, "pstex")|| strcmp (dev, "pslatex")
-	|| strcmp (dev, "epslatex"))
-        termn = dev;
+      if (any (strcmp (dev, {"pstex", "pslatex", "epslatex"})))
         options = "";
       elseif (strcmp (dev, "epslatexstandalone"))
         if (__gnuplot_has_feature__ ("epslatexstandalone_terminal"))
-	termn = "epslatex";
-	options = "standalone ";
+	  termn = "epslatex";
+	  options = "standalone ";
         else
-	error ("print: epslatexstandalone needs gnuplot 4.2 or higher");
+	  error ("print: epslatexstandalone needs gnuplot 4.2 or higher");
         endif
       else
         if (dev(1) == "e")
-	options = "eps ";
+	  options = "eps ";
         else
-	options = cstrcat (orientation, " ");
+	  options = cstrcat (orientation, " ");
         endif
         termn = "postscript";
       endif
@@ -317,8 +331,6 @@
         options = cstrcat (options, " ", fontsize);
       endif
 
-      new_terminal = cstrcat (dev, " ", options);
-
     elseif (strcmp (dev, "fig"))
       ## XFig
       options = orientation;
@@ -332,8 +344,6 @@
         options = cstrcat (options, " fontsize ", fontsize);
       endif
 
-      new_terminal = cstrcat ("fig ", options);
-
     elseif (strcmp (dev, "emf"))
       ## Enhanced Metafile format
       options = " ";
@@ -352,44 +362,25 @@
         options = cstrcat (options, " ", fontsize);
       endif
 
-      new_terminal = cstrcat ("emf ", options);
-
-    elseif (strcmp (dev, "png") || strcmp (dev, "gif")
-	  || strcmp (dev, "jpg") || strcmp (dev, "jpeg")
-	  || strcmp (dev, "pbm"))
-      if (strcmp (dev, "jpg"))
-        dev = "jpeg";
-      endif
-      ## Portable network graphics, PBMplus
+    elseif (any (strcmp (dev, bitmap_devices)))
 
-      ## FIXME -- New PNG interface takes color as "xRRGGBB"
-      ## where x is the literal character 'x' and 'RRGGBB' are the red,
-      ## green and blue components in hex.  For now we just ignore it
-      ## and use default.  The png terminal now is so rich with options,
-      ## that one perhaps has to write a separate printpng.m function.
-      ## DAS
-
-      if (isempty (size) && isempty (resolution))
-        options = " large";
-      elseif (! isempty (size))
-        options = cstrcat (" size ", size);
+      if (isempty (canvas_size) && isempty (resolution) 
+	  && any (strcmp (dev, {"pbm", "gif", "jpeg", "png"})))
+        options = "large";
+      elseif (strcmp (dev, "svg"))
+	## Referring to size, either "dynamic" or "fixed"
+	options = "fixed";
       else
 	options = "";
+      end
+      if (! isempty (canvas_size))
+        options = cstrcat (options, " size ", canvas_size);
       endif
-      new_terminal = cstrcat (dev, options);
-
-    elseif (strcmp (dev, "dxf") || strcmp (dev, "mf") || strcmp (dev, "hpgl"))
-      ## AutoCad DXF, METAFONT, HPGL
-      new_terminal = dev;
 
-    elseif (strcmp (dev, "svg"))
-      ## SVG
+    elseif (any (strcmp (dev, {"dxf", "mf", "hpgl"})))
+      ## AutoCad DXF, METAFONT, HPGL
       options = "";
-      if (! isempty (size))
-        options = cstrcat (" size ", size);
-      endif
-      new_terminal = cstrcat ("svg", options);
-      
+
     elseif (strcmp (dev, "pdf"))
       ## Portable Document format
       options = " ";
@@ -398,8 +389,8 @@
       else
         options = "mono";
       endif
-      if (force_solid > 0)
-         options = cstrcat (options, " solid");
+      if (force_solid >= 0)
+        options = cstrcat (options, " solid");
       elseif (force_solid < 0)
         options = cstrcat (options, " dashed");
       endif
@@ -410,16 +401,58 @@
         options = cstrcat (options, " ", fontsize);
       endif
 
-      new_terminal = cstrcat ("pdf ", options);
+    endif
+ 
+    if (__gnuplot_has_feature__ ("variable_GPVAL_TERMINALS"))
+        available_terminals = __gnuplot_get_var__ (gcf, "GPVAL_TERMINALS");
+        available_terminals = regexp (available_terminals, "\\b\\w+\\b", "match");
+        gnuplot_supports_term = any (strcmp (available_terminals, termn));
+    elseif (isunix () && strcmp (termn, "pdf"))
+      ## Some Linux variants do not include a "pdf" capable gnuplot.
+      ## To be safe, use "convert".
+      [status, output] = system ("which convert");
+      have_convert = (status == 0);
+      if (have_convert)
+        gnuplot_supports_term = false;
+      else
+        gnuplot_supports_term = true;
+      endif
+    else
+      gnuplot_supports_term = true;
+    endif
 
+    if (! gnuplot_supports_term)
+      ## If the terminal is not supported by the local gnuplot, try "convert".
+      if (strcmp (termn, "pdf"))
+	if (strfind (name, ".pdf") == numel (name) - 3)
+          convert_name = name;
+	else
+	  convert_name = strcat (name, ".pdf");
+	endif
+        name = cstrcat (tmpnam, ".ps");
+        termn = "postscript";
+	options = cstrcat (options, " portrait");
+	## All "options" for pdf work for postscript as well.
+      else
+        error ("print: the gnuplot terminal, \"%s\", is not available.", termn)
+      endif
     endif
 
+    new_terminal = cstrcat (termn, " ", options);
+
     mono = use_color < 0;
 
     if (isempty (resolution))
-      resolution = get (0, "screenpixelsperinch");
+      if (any (strcmp (termn, {"emf", "svg"})))
+        resolution = get (0, "screenpixelsperinch");
+      else
+        resolution = 150;
+      endif
     else
       resolution = str2num (resolution);
+      if (resolution == 0)
+        resolution = get (0, "screenpixelsperinch");
+      endif
     endif
     figure_properties = get (gcf);
     if (! isfield (figure_properties, "__pixels_per_inch__"))
@@ -428,22 +461,29 @@
     set (gcf, "__pixels_per_inch__", resolution)
 
     unwind_protect
-      if (! isempty (size) || any (strfind (dev, "eps") == 1))
+      paper_position_mode = get (gcf, "paperpositionmode");
+      term_for_prn = {"postscript", "pdf"};
+      restore_properties = false;
+      if (! any (strncmp (termn, term_for_prn, numel(termn)))
+	  || strncmp (dev, "eps", 3))
+	## If not pdf and not plain postscript, render an image the size of
+	## the paperposition box.
+        restore_properties = true;
         p.paperunits = get (gcf, "paperunits");
         p.papertype = get (gcf, "papertype");
         p.papersize = get (gcf, "papersize");
         p.paperposition = get (gcf, "paperposition");
         p.paperpositionmode = get (gcf, "paperpositionmode");
         set (gcf, "paperunits", "inches");
-        if (any (strfind (dev, "eps") == 1))
-          paperposition_in_inches = get (gcf, "paperposition") + 1/72;
-          paperposition_in_inches(1:2) = 0;
-          papersize_in_inches = paperposition_in_inches(3:4);
-        else
-          size_in_pixels = sscanf (size ,"%d, %d");
+	if (! isempty (canvas_size))
+          size_in_pixels = sscanf (canvas_size ,"%d, %d");
           size_in_pixels = reshape (size_in_pixels, [1, numel(size_in_pixels)]);
           papersize_in_inches = size_in_pixels ./ resolution;
           paperposition_in_inches = [0, 0, papersize_in_inches];
+	else
+          paperposition_in_inches = get (gcf, "paperposition");
+          paperposition_in_inches(1:2) = 0;
+          papersize_in_inches = paperposition_in_inches(3:4);
         endif
         set (gcf, "papertype", "<custom>");
         set (gcf, "papersize", papersize_in_inches);
@@ -457,7 +497,7 @@
       endif
     unwind_protect_cleanup
       ## FIXME - it would be nice to delete "__pixels_per_inch__" property here.
-      if (! isempty (size) || any (strfind (dev, "eps") == 1))
+      if (restore_properties)
         props = fieldnames (p);
         for n = 1:numel(props)
           set (gcf, props{n}, p.(props{n}))
@@ -465,12 +505,12 @@
       endif
     end_unwind_protect
 
-    if (! isempty (convertname))
-      command = sprintf ("convert '%s' '%s'", name, convertname);
+    if (! isempty (convert_name))
+      command = sprintf ("convert '%s' '%s'", name, convert_name);
       [errcode, output] = system (command);
       unlink (name);
       if (errcode)
-        error ("print: could not convert");
+        error ("print: could not convert; %s -> %s.", name, convert_name);
       endif
     endif