]> Creatis software - CreaPhase.git/blob - octave_packages/m/plot/print.m
update packages
[CreaPhase.git] / octave_packages / m / plot / print.m
1 ## Copyright (C) 2008-2012 David Bateman
2 ##
3 ## This file is part of Octave.
4 ##
5 ## Octave is free software; you can redistribute it and/or modify it
6 ## under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 3 of the License, or (at
8 ## your option) any later version.
9 ##
10 ## Octave is distributed in the hope that it will be useful, but
11 ## WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 ## General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING.  If not, see
17 ## <http://www.gnu.org/licenses/>.
18
19 ## -*- texinfo -*-
20 ## @deftypefn  {Function File} {} print ()
21 ## @deftypefnx {Function File} {} print (@var{options})
22 ## @deftypefnx {Function File} {} print (@var{filename}, @var{options})
23 ## @deftypefnx {Function File} {} print (@var{h}, @var{filename}, @var{options})
24 ## Print a graph, or save it to a file
25 ##
26 ## @var{filename} defines the file name of the output file.  If the
27 ## file name has no suffix, one is inferred from the specified
28 ## device and appended to the file name.  If no
29 ## filename is specified, the output is sent to the printer.
30 ##
31 ## @var{h} specifies the figure handle.  If no handle is specified
32 ## the handle for the current figure is used.
33 ##
34 ## @var{options}:
35 ##
36 ## @table @code
37 ## @item -f@var{h}
38 ##   Specify the handle, @var{h}, of the figure to be printed.  The
39 ##   default is the current figure.
40 ##
41 ## @item -P@var{printer}
42 ##   Set the @var{printer} name to which the graph is sent if no
43 ##   @var{filename} is specified.
44 ##
45 ## @item -G@var{ghostscript_command}
46 ##   Specify the command for calling Ghostscript.  For Unix and Windows,
47 ## the defaults are 'gs' and 'gswin32c', respectively.
48 ##
49 ## @item -color
50 ## @itemx -mono
51 ##   Monochrome or color output.
52 ##
53 ## @item -solid
54 ## @itemx -dashed
55 ##   Forces all lines to be solid or dashed, respectively.
56 ##
57 ## @item -portrait
58 ## @itemx -landscape
59 ##   Specify the orientation of the plot for printed output.  For
60 ## non-printed output the aspect ratio of the output corresponds to
61 ## the plot area defined by the "paperposition" property in the
62 ## orientation specified.  This options is equivalent to changing
63 ## the figure's "paperorientation" property.
64 ##
65 ## @item -d@var{device}
66 ##   Output device, where @var{device} is one of:
67 ##   @table @code
68 ##   @item ps
69 ##   @itemx ps2
70 ##   @itemx psc
71 ##   @itemx psc2
72 ##     Postscript (level 1 and 2, mono and color).  The FLTK graphics
73 ##     toolkit generates Postscript level 3.0.
74 ##
75 ##   @item eps
76 ##   @itemx eps2
77 ##   @itemx epsc
78 ##   @itemx epsc2
79 ##     Encapsulated postscript (level 1 and 2, mono and color).  The FLTK
80 ## graphic toolkit generates Postscript level 3.0.
81 ##
82 ##   @item tex
83 ##   @itemx epslatex
84 ##   @itemx epslatexstandalone
85 ##   @itemx pstex
86 ##   @itemx pslatex
87 ##   @itemx pdflatex
88 ##     Generate a @LaTeX{} (or @TeX{}) file for labels, and eps/ps/pdf
89 ## for graphics.  The file produced by @code{epslatexstandalone} can be
90 ## processed directly by @LaTeX{}.  The other formats are intended to
91 ## be included in a @LaTeX{} (or @TeX{}) document.  The @code{tex} device
92 ## is the same as the @code{epslatex} device.  The @code{pdflatex} device
93 ## is only available for the FLTK graphics toolkit.
94 ##
95 ##   @item tikz
96 ##     Generate a @LaTeX{} file using PGF/TikZ@.  For the FLTK the result is
97 ##   PGF.
98 ##
99 ##   @item ill
100 ##   @itemx aifm
101 ##     Adobe Illustrator (Obsolete for Gnuplot versions > 4.2)
102 ##
103 ##   @item cdr
104 ##   @itemx @nospell{corel}
105 ##     CorelDraw
106 ##
107 ##   @item dxf
108 ##     AutoCAD
109 ##
110 ##   @item emf
111 ##   @itemx meta
112 ##     Microsoft Enhanced Metafile
113 ##
114 ##   @item fig
115 ##     XFig.  For the Gnuplot graphics toolkit, the additional options
116 ##     @option{-textspecial} or @option{-textnormal} can be used to control
117 ##     whether the special flag should be set for the text in
118 ##     the figure (default is @option{-textnormal}).
119 ##
120 ##   @item hpgl
121 ##     HP plotter language
122 ##
123 ##   @item mf
124 ##     Metafont
125 ##
126 ##   @item png
127 ##     Portable network graphics
128 ##
129 ##   @item jpg
130 ##   @itemx jpeg
131 ##     JPEG image
132 ##
133 ##   @item gif
134 ##     GIF image (only available for the Gnuplot graphics toolkit)
135 ##
136 ##   @item pbm
137 ##     PBMplus
138 ##
139 ##   @item svg
140 ##     Scalable vector graphics
141 ##
142 ##   @item pdf
143 ##     Portable document format
144 ##
145 ##     NOTE: The gnuplot binary as shipped by Debian cannot create PDF files, see http://bugs.debian.org/478677
146 ##
147 ##   @end table
148 ##
149 ##   If the device is omitted, it is inferred from the file extension,
150 ## or if there is no filename it is sent to the printer as postscript.
151 ##
152 ## @item -d@var{ghostscript_device}
153 ##   Additional devices are supported by Ghostscript.
154 ## Some examples are;
155 ##
156 ##   @table @code
157 ##   @item ljet2p
158 ##     HP LaserJet IIP
159 ##
160 ##   @item ljet3
161 ##     HP LaserJet III
162 ##
163 ##   @item deskjet
164 ##     HP DeskJet and DeskJet Plus
165 ##
166 ##   @item cdj550
167 ##     HP DeskJet 550C
168 ##
169 ##   @item paintjet
170 ##     HP PointJet
171 ##
172 ##   @item pcx24b
173 ##     24-bit color PCX file format
174 ##
175 ##   @item ppm
176 ##     Portable Pixel Map file format
177 ##
178 ##   @item pdfwrite
179 ##     Produces pdf output from eps
180 ##   @end table
181 ##
182 ##   For a complete list, type `system ("gs -h")' to see what formats
183 ## and devices are available.
184 ##
185 ##   When Ghostscript output is sent to a printer the size is determined
186 ## by the figure's "papersize" property.  When the output
187 ## is sent to a file the size is determined by the plot box defined by
188 ## the figure's "paperposition" property.
189 ##
190 ## @itemx -append
191 ##   Appends the PS, or PDF output to a pre-existing file of the
192 ## same type.
193 ##
194 ## @itemx -r@var{NUM}
195 ##   Resolution of bitmaps in pixels per inch.  For both metafiles and
196 ## SVG the default is the screen resolution, for other it is 150 dpi.
197 ## To specify screen resolution, use "-r0".
198 ##
199 ## @item -tight
200 ##   Forces a tight bounding box for eps-files.
201 ##
202 ## @item -@var{preview}
203 ##   Adds a preview to eps-files.  Supported formats are;
204 ##
205 ##   @table @code
206 ##   @item -interchange
207 ##     Provides an interchange preview.
208 ##
209 ##   @item -metalfile
210 ##     Provides a metafile preview.
211 ##
212 ##   @item -pict
213 ##     Provides pict preview.
214 ##
215 ##   @item -tiff
216 ##     Provides a tiff preview.
217 ##   @end table
218 ##
219 ## @item -S@var{xsize},@var{ysize}
220 ##   Plot size in pixels for EMF, GIF, JPEG, PBM, PNG and SVG@.  For
221 ## PS, EPS, PDF, and other vector formats the plot size is in points.
222 ## This option is equivalent to changing the size of the plot box
223 ## associated with "paperposition" property.  Using the command form of
224 ## the print function, you must quote the @var{xsize},@var{ysize}
225 ## option.  For example, by writing @w{@code{"-S640,480"}}.
226 ##
227 ## @item -F@var{fontname}
228 ## @itemx -F@var{fontname}:@var{size}
229 ## @itemx -F:@var{size}
230 ##   Associates all text with the @var{fontname} and/or @var{fontsize}.
231 ## @var{fontname} is ignored for some devices; dxf, fig, hpgl, etc.
232 ## @end table
233 ##
234 ## The filename and options can be given in any order.
235 ##
236 ## Example: Print to a file, using the svg device.
237 ##
238 ## @example
239 ## @group
240 ## figure (1);
241 ## clf ();
242 ## surf (peaks);
243 ## print -dsvg figure1.svg
244 ## @end group
245 ## @end example
246 ##
247 ## Example: Print to an HP Deskjet 550C.
248 ##
249 ## @example
250 ## @group
251 ## figure (1);
252 ## clf ();
253 ## surf (peaks);
254 ## print -dcdj550
255 ## @end group
256 ## @end example
257 ##
258 ## @seealso{figure, orient, saveas}
259 ## @end deftypefn
260
261 function print (varargin)
262
263   opts = __print_parse_opts__ (varargin{:});
264
265   opts.pstoedit_cmd = @pstoedit;
266   opts.fig2dev_cmd = @fig2dev;
267   opts.latex_standalone = @latex_standalone;
268   opts.lpr_cmd = @lpr;
269   opts.epstool_cmd = @epstool;
270
271   if (! isfigure (opts.figure))
272     error ("print: no figure to print");
273   endif
274
275   orig_figure = get (0, "currentfigure");
276   figure (opts.figure);
277
278   if (opts.append_to_file)
279     [~, ~, ext] = fileparts (opts.ghostscript.output);
280     opts.ghostscript.prepend = strcat (tmpnam (), ext);
281     copyfile (opts.ghostscript.output, opts.ghostscript.prepend);
282   endif
283
284   unwind_protect
285
286     ## Modify properties as specified by options
287     props = [];
288
289     ## graphics toolkit tranlates figure position to eps bbox in points
290     fpos = get (opts.figure, "position");
291     props(1).h = opts.figure;
292     props(1).name = "position";
293     props(1).value = {fpos};
294     fpos(3:4) = opts.canvas_size;
295     set (opts.figure, "position", fpos);
296
297     ## Set figure background to none. This is done both for
298     ## consistency with Matlab and to elliminate the visible
299     ## box along the figure's perimeter.
300     props(2).h = opts.figure;
301     props(2).name = "color";
302     props(2).value{1} = get (props(2).h, props(2).name);
303     set (props(2).h, props(2).name, "none");
304
305     if (opts.force_solid != 0)
306       h = findall (opts.figure, "-property", "linestyle");
307       m = numel (props);
308       for n = 1:numel(h)
309         props(m+n).h = h(n);
310         props(m+n).name = "linestyle";
311         props(m+n).value = {get(h(n), "linestyle")};
312       endfor
313       if (opts.force_solid > 0)
314         linestyle = "-";
315       else
316         linestyle = "--";
317       endif
318       set (h, "linestyle", linestyle);
319     endif
320
321     if (opts.use_color < 0
322         && ! strcmp (get (opts.figure, "__graphics_toolkit__"), "gnuplot"))
323       color_props = {"color", "facecolor", "edgecolor", "colormap"};
324       for c = 1:numel(color_props)
325         h = findall (opts.figure, "-property", color_props{c});
326         hnone = findall (opts.figure, color_props{c}, "none");
327         h = setdiff (h, hnone);
328         m = numel (props);
329         for n = 1:numel(h)
330           if (ishandle (h(n)))
331             ## Need to verify objects exist since callbacks may delete objects
332             ## as the colors for others are modified.
333             rgb = get (h(n), color_props{c});
334             props(end+1).h = h(n);
335             props(end).name = color_props{c};
336             props(end).value = {get(h(n), color_props{c})};
337             if (isnumeric (rgb))
338               ## convert RGB color to RGB gray scale
339               xfer = repmat ([0.30, 0.59, 0.11], size (rgb, 1), 1);
340               ggg = repmat (sum (xfer .* rgb, 2), 1, 3);
341               set (h(n), color_props{c}, ggg);
342             endif
343           endif
344         endfor
345       endfor
346     endif
347
348     if (! isempty (opts.font) || ! isempty (opts.fontsize))
349       h = findall (opts.figure, "-property", "fontname");
350       m = numel (props);
351       for n = 1:numel(h)
352         if (ishandle (h(n)))
353           if (! isempty (opts.font))
354             props(end+1).h = h(n);
355             props(end).name = "fontname";
356             props(end).value = {get(h(n), "fontname")};
357           endif
358         endif
359         if (ishandle (h(n)))
360           if (! isempty (opts.fontsize))
361             props(end+1).h = h(n);
362             props(end).name = "fontsize";
363             props(end).value = {get(h(n), "fontsize")};
364           endif
365         endif
366       endfor
367       if (! isempty (opts.font))
368         set (h(ishandle(h)), "fontname", opts.font);
369       endif
370       if (! isempty (opts.fontsize))
371         if (ischar (opts.fontsize))
372           fontsize = str2double (opts.fontsize);
373         else
374           fontsize = opts.fontsize;
375         endif
376         set (h(ishandle(h)), "fontsize", fontsize);
377       endif
378     endif
379
380     ## call the graphcis toolkit print script
381     switch (get (opts.figure, "__graphics_toolkit__"))
382     case "gnuplot"
383       opts = __gnuplot_print__ (opts);
384     otherwise
385       opts = __fltk_print__ (opts);
386     endswitch
387
388   unwind_protect_cleanup
389     ## restore modified properties
390     if (isstruct (props))
391       for n = 1:numel(props)
392         if (ishandle (props(n).h))
393           set (props(n).h, props(n).name, props(n).value{1});
394         endif
395       endfor
396     endif
397
398     ## Unlink temporary files
399     for n = 1:numel(opts.unlink)
400       [status, output] = unlink (opts.unlink{n});
401       if (status != 0)
402         warning ("print.m: %s, '%s'", output, opts.unlink{n});
403       endif
404     endfor
405   end_unwind_protect
406
407   if (isfigure (orig_figure))
408     figure (orig_figure);
409   endif
410
411 endfunction
412
413 function cmd = epstool (opts, filein, fileout)
414   ## As epstool does not work with pipes, a subshell is used to
415   ## permit piping. Since this solution does not work with the DOS
416   ## command shell, the -tight and -preview options are disabled if
417   ## output must be piped.
418
419   ## DOS Shell:
420   ##   gs.exe [...] -sOutputFile=<filein> - & epstool -bbox -preview-tiff <filein> <fileout> & del <filein>
421   ## Unix Shell;
422   ##   cat > <filein> ; epstool -bbox -preview-tiff <filein> <fileout> ; rm <filein>
423
424   dos_shell = (ispc () && ! isunix ());
425
426   cleanup = "";
427   if (nargin < 3)
428     fileout = opts.name;
429   elseif (isempty (fileout))
430     fileout = "-";
431   endif
432
433   if (nargin < 2 || strcmp (filein, "-") || isempty (filein))
434     pipein = true;
435     filein = strcat (tmpnam (), ".eps");
436     if (dos_shell)
437       cleanup = sprintf ("& del %s ", strrep (filein, '/', '\'));
438     else
439       cleanup = sprintf ("; rm %s ", filein);
440     endif
441   else
442     pipein = false;
443     filein = strcat ("'", strtrim (filein), "'");
444   endif
445   if (strcmp (fileout, "-"))
446     pipeout = true;
447     fileout = strcat (tmpnam (), ".eps");
448     if (dos_shell)
449       cleanup = horzcat (cleanup, sprintf ("& del %s ", strrep (fileout, '/', '\')));
450     else
451       cleanup = horzcat (cleanup, sprintf ("; rm %s ", fileout));
452     endif
453   else
454     pipeout = false;
455     fileout = strcat ("'", strtrim (fileout), "'");
456   endif
457
458   if (! isempty (opts.preview) && opts.tight_flag)
459     warning ("print:previewandtight",
460              "print.m: eps preview may not be combined with -tight");
461   endif
462   if (! isempty (opts.preview) || opts.tight_flag)
463     if (! isempty (opts.epstool_binary))
464       if (opts.tight_flag)
465         cmd = "--copy --bbox";
466       elseif (! isempty (opts.preview))
467         switch opts.preview
468         case "tiff"
469           cmd = sprintf ("--add-%s-preview --device tiffg3", opts.preview);
470         case {"tiff6u", "tiff6p", "metafile"}
471           cmd = sprintf ("--add-%s-preview --device bmpgray", opts.preview);
472         case {"tiff4", "interchange"}
473           cmd = sprintf ("--add-%s-preview", opts.preview);
474         case "pict"
475           cmd = sprintf ("--add-%s-preview --mac-single", opts.preview);
476         otherwise
477           error ("print:invalidpreview",
478                  "print.m: epstool cannot include preview for format '%s'",
479                  opts.preview);
480         endswitch
481         if (! isempty (opts.ghostscript.resolution))
482           cmd = sprintf ("%s --dpi %d", cmd, opts.ghostscript.resolution);
483         endif
484       else
485         cmd = "";
486       endif
487       if (! isempty (cmd))
488         cmd = sprintf ("%s --quiet %s %s %s ", opts.epstool_binary,
489                        cmd, filein, fileout);
490       endif
491       if (pipein)
492         if (dos_shell)
493           filein(filein=="'") = "\"";
494           gs_cmd = __ghostscript__ ("binary", opts.ghostscript.binary,
495                                     "device", "epswrite",
496                                     "source", "-",
497                                     "output", filein);
498           cmd = sprintf ("%s %s & %s", gs_cmd, filein, cmd);
499         else
500           cmd = sprintf ("cat > %s ; %s", filein, cmd);
501         endif
502       endif
503       if (pipeout)
504         if (dos_shell)
505           cmd = sprintf ("%s & type %s", cmd, fileout);
506         else
507           cmd = sprintf ("%s ; cat %s", cmd, fileout);
508         endif
509       endif
510       if (! isempty (cleanup))
511         if (pipeout && dos_shell)
512           error ("print:epstoolpipe",
513                  "print.m: cannot pipe output of 'epstool' for DOS shell");
514         elseif (pipeout)
515           cmd = sprintf ("( %s %s )", cmd, cleanup);
516         else
517           cmd = sprintf ("%s %s", cmd, cleanup);
518         endif
519       endif
520     elseif (isempty (opts.epstool_binary))
521       error ("print:noepstool", "print.m: 'epstool' not found in PATH");
522     endif
523   else
524     if (pipein && pipeout)
525       if (dos_shell)
526         cmd = __ghostscript__ ("binary", opts.ghostscript.binary,
527                                "device", "epswrite",
528                                "source", "-",
529                                "output", "-");
530       else
531         cmd = " cat ";
532       endif
533     elseif (pipein && ! pipeout)
534       if (dos_shell)
535         ## ghostscript expects double, not single, quotes
536         fileout(fileout=="'") = "\"";
537         cmd = __ghostscript__ ("binary", opts.ghostscript.binary,
538                                "device", "epswrite",
539                                "source", "-",
540                                "output", fileout);
541       else
542         cmd = sprintf (" cat > %s ", fileout);
543       endif
544     elseif (! pipein && pipeout)
545       if (dos_shell)
546         cmd = sprintf (" type %s ", filein);
547       else
548         cmd = sprintf (" cat %s ", filein);
549       endif
550     else
551       if (dos_shell)
552         cmd = sprintf (" copy %s %s ", filein, fileout);
553       else
554         cmd = sprintf (" cp %s %s ", filein, fileout);
555       endif
556     endif
557   endif
558   if (opts.debug)
559     fprintf ("epstool command: '%s'\n", cmd);
560   endif
561 endfunction
562
563 function cmd = fig2dev (opts, devopt)
564   if (nargin < 2)
565     devopt =  opts.devopt;
566   endif
567   dos_shell = (ispc () && ! isunix ());
568   if (! isempty (opts.fig2dev_binary))
569     if (dos_shell)
570       ## FIXME - is this the right thing to do for DOS?
571       cmd = sprintf ("%s -L %s 2> NUL", opts.fig2dev_binary, devopt);
572     else
573       cmd = sprintf ("%s -L %s 2> /dev/null", opts.fig2dev_binary, devopt);
574     endif
575   elseif (isempty (opts.fig2dev_binary))
576     error ("print:nofig2dev", "print.m: 'fig2dev' not found in PATH");
577   endif
578   if (opts.debug)
579     fprintf ("fig2dev command: '%s'\n", cmd);
580   endif
581 endfunction
582
583 function latex_standalone (opts)
584   n = find (opts.name == ".", 1, "last");
585   if (! isempty (n))
586     opts.name = opts.name(1:n-1);
587   endif
588   latexfile = strcat (opts.name, ".tex");
589   switch opts.devopt
590   case {"pdflatexstandalone"}
591     packages = "\\usepackage{graphicx,color}";
592     graphicsfile = strcat (opts.name, "-inc.pdf");
593   case {"pslatexstandalone"}
594     packages = "\\usepackage{epsfig,color}";
595     graphicsfile = strcat (opts.name, "-inc.ps");
596   otherwise
597     packages = "\\usepackage{epsfig,color}";
598     graphicsfile = strcat (opts.name, "-inc.eps");
599   endswitch
600   papersize = sprintf ("\\usepackage[papersize={%.2fbp,%.2fbp},text={%.2fbp,%.2fbp}]{geometry}",
601                        opts.canvas_size, opts.canvas_size);
602   prepend = {"\\documentclass{minimal}";
603              packages;
604              papersize;
605              "\\begin{document}";
606              "\\centering"};
607   postpend = {"\\end{document}"};
608   fid = fopen (latexfile, "r");
609   if (fid >= 0)
610     latex = fscanf (fid, "%c", Inf);
611     status = fclose (fid);
612     if (status != 0)
613       error ("print:errorclosingfile",
614              "print.m: error closing file '%s'", latexfile);
615     endif
616     ## TODO - should this be fixed in GL2PS?
617     latex = strrep (latex, "\\includegraphics{}",
618                     sprintf ("\\includegraphics{%s}", graphicsfile));
619   else
620     error ("print:erroropeningfile",
621            "print.m: error opening file '%s'", latexfile);
622   endif
623   fid = fopen (latexfile, "w");
624   if (fid >= 0)
625     fprintf (fid, "%s\n", prepend{:});
626     fprintf (fid, "%s", latex);
627     fprintf (fid, "%s\n", postpend{:});
628     status = fclose (fid);
629     if (status != 0)
630       error ("print:errorclosingfile",
631              "print.m: error closing file '%s'", latexfile);
632     endif
633   else
634     error ("print:erroropeningfile",
635            "print.m: error opening file '%s'", latexfile);
636   endif
637 endfunction
638
639 function cmd = lpr (opts)
640   if (nargin < 2)
641     devopt =  opts.devopt;
642   endif
643   if (! isempty (opts.lpr_binary))
644     cmd = opts.lpr_binary;
645     if (! isempty (opts.lpr_options))
646       cmd = sprintf ("%s %s", cmd, opts.lpr_options);
647     endif
648     if (! isempty (opts.printer))
649       cmd = sprintf ("%s -P %s", cmd, opts.printer);
650     endif
651   elseif (isempty (opts.lpr_binary))
652     error ("print:nolpr", "print.m: 'lpr' not found in PATH");
653   endif
654   if (opts.debug)
655     fprintf ("lpr command: '%s'\n", cmd);
656   endif
657 endfunction
658
659 function cmd = pstoedit (opts, devopt)
660   if (nargin < 2)
661     devopt =  opts.devopt;
662   endif
663   dos_shell = (ispc () && ! isunix ());
664   if (! isempty (opts.pstoedit_binary))
665     if (dos_shell)
666       cmd = sprintf ("%s -f %s 2> NUL", opts.pstoedit_binary, devopt);
667     else
668       ## FIXME - is this the right thing to do for DOS?
669       cmd = sprintf ("%s -f %s 2> /dev/null", opts.pstoedit_binary, devopt);
670     endif
671   elseif (isempty (opts.pstoedit_binary))
672     error ("print:nopstoedit", "print.m: 'pstoedit' not found in PATH");
673   endif
674   if (opts.debug)
675     fprintf ("pstoedit command: '%s'\n", cmd);
676   endif
677 endfunction
678
679