1########################################################################
2##
3## Copyright (C) 2010-2021 The Octave Project Developers
4##
5## See the file COPYRIGHT.md in the top-level directory of this
6## distribution or <https://octave.org/copyright/>.
7##
8## This file is part of Octave.
9##
10## Octave is free software: you can redistribute it and/or modify it
11## under the terms of the GNU General Public License as published by
12## the Free Software Foundation, either version 3 of the License, or
13## (at your option) any later version.
14##
15## Octave is distributed in the hope that it will be useful, but
16## WITHOUT ANY WARRANTY; without even the implied warranty of
17## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18## GNU General Public License for more details.
19##
20## You should have received a copy of the GNU General Public License
21## along with Octave; see the file COPYING.  If not, see
22## <https://www.gnu.org/licenses/>.
23##
24########################################################################
25
26## -*- texinfo -*-
27## @deftypefn {} {} __opengl_print__ (@var{@dots{}})
28## Undocumented internal function.
29## @end deftypefn
30
31function opts = __opengl_print__ (opts)
32
33  dos_shell = (ispc () && ! isunix ());
34
35  if (! isempty (opts.fig2dev_binary))
36    ## fig2dev is preferred for conversion to emf
37    fig2dev_devices = {"pstex", "mf", "emf"};
38  else
39    fig2dev_devices = {"pstex", "mf"};
40  endif
41
42  gl2ps_device = {};
43  pipeline = {};
44  switch (lower (opts.devopt))
45    case {"eps", "eps2", "epsc", "epsc2"}
46      ## format GL2PS_EPS
47      gl2ps_device = {"eps"};
48      ## FIXME: use epstool to tighten bbox and provide preview.
49      pipeline = {opts.epstool_cmd(opts, "-", opts.name)};
50    case {"epslatex", "pslatex", "pdflatex", "epslatexstandalone", ...
51          "pslatexstandalone", "pdflatexstandalone"}
52      ## format GL2PS_TEX
53      n = find (opts.devopt == "l", 1);
54      suffix = opts.devopt(1:n-1);
55      [ndir, name, ext] = fileparts (opts.name);
56      if (isempty (ext))
57        ext = "tex";
58      else
59        ext = ext(2:end);  # remove leading '.'
60      endif
61      if (any (strcmpi (ext, {suffix, "tex"})))
62        name = fullfile (ndir, name);
63        if (any (strcmpi (ext, {"eps", "ps", "pdf"})))
64          suffix = ext;  # If user provides eps/ps/pdf suffix, use it.
65        endif
66      else
67        error ("Octave:print:invalid-suffix",
68               "invalid suffix '%s' for device '%s'.",
69               ext, lower (opts.devopt));
70      endif
71      gl2ps_device = {sprintf("%snotxt", lower (suffix))};
72      gl2ps_device{2} = "tex";
73      if (dos_shell)
74        ## FIXME: this will only work on MinGW with the MSYS shell
75        pipeline = {sprintf('cat > "%s-inc.%s"', name, suffix)};
76        pipeline{2} = sprintf ('cat > "%s.tex"', name);
77      else
78        pipeline = {sprintf('cat > "%s-inc.%s"', name, suffix)};
79        pipeline{2} = sprintf ('cat > "%s.tex"', name);
80      endif
81    case "tikz"
82      ## format GL2PS_PGF
83      gl2ps_device = {"pgf"};
84      pipeline = {sprintf('cat > "%s"', opts.name)};
85    case "svg"
86      ## format GL2PS_SVG
87      gl2ps_device = {"svg"};
88      svgcmd = "";
89      if (opts.svgconvert)
90        svgcmd = opts.svgconvert_cmd (opts, opts.ghostscript.device);
91      endif
92      if (! isempty (svgcmd))
93        pipeline = {sprintf(svgcmd, "svg", opts.name)};
94      else
95        pipeline = {sprintf('cat > "%s"', opts.name)};
96      endif
97    case fig2dev_devices
98      cmd_fig2dev = opts.fig2dev_cmd (opts, opts.devopt);
99      if (strcmp (opts.devopt, "pstex"))
100        cmd_pstoedit = opts.pstoedit_cmd (opts, "fig", false);
101        [~, ~, ext] = fileparts (opts.name);
102        if (any (strcmpi (ext, {".ps", ".tex", "."})))
103          opts.name = opts.name(1:end-numel(ext));
104        endif
105        opts.name = [opts.name ".ps"];
106        cmd = sprintf ('%s | %s > "%s"', cmd_pstoedit, cmd_fig2dev, opts.name);
107        gl2ps_device = {"eps"};
108        pipeline = {cmd};
109        cmd_fig2dev = opts.fig2dev_cmd (opts, "pstex_t");
110        gl2ps_device{2} = "eps";
111        pipeline{2} = sprintf ('%s | %s > "%s"', cmd_pstoedit,
112                               cmd_fig2dev, strrep(opts.name, ".ps", ".tex"));
113      else
114        ## Using svgconvert
115        tmp = tempname ();
116        opts.unlink = [opts.unlink tmp];
117        cmd_pstoedit = sprintf (opts.pstoedit_cmd (opts, "fig"), ...
118                                "pdf", tmp, tmp);
119        cmd = sprintf ('%s | %s > "%s"', cmd_pstoedit, cmd_fig2dev, opts.name);
120        gl2ps_device = {"svg"};
121        pipeline = {cmd};
122      endif
123    case "aifm"
124      tmp = tempname ();
125      opts.unlink = [opts.unlink tmp];
126      cmd = sprintf (opts.pstoedit_cmd (opts, "ps2ai"), "pdf", tmp, tmp);
127      gl2ps_device = {"svg"};
128      pipeline = {sprintf("%s > %s", cmd, opts.name)};
129    case {"dxf", "emf", "fig", "hpgl"}
130      tmp = tempname ();
131      opts.unlink = [opts.unlink tmp];
132      cmd = sprintf (opts.pstoedit_cmd (opts), "pdf", tmp, tmp);
133      gl2ps_device = {"svg"};
134      pipeline = {sprintf('%s > "%s"', cmd, opts.name)};
135    case opts.ghostscript.device
136      svgcmd = "";
137      if (opts.svgconvert)
138        svgcmd = opts.svgconvert_cmd (opts, opts.ghostscript.device);
139      endif
140      dosvg = ! isempty (svgcmd);
141      if (! dosvg)
142        opts.ghostscript.source = "-";
143      else
144        tmp = tempname ();
145        opts.ghostscript.source = tmp;
146        opts.unlink = [opts.unlink tmp];
147        svgcmd = sprintf (svgcmd, "pdf", tmp);
148      endif
149
150      opts.ghostscript.output = opts.name;
151      if (opts.send_to_printer)
152        opts.unlink(strcmp (opts.unlink, opts.ghostscript.output)) = [];
153        opts.ghostscript.output = "-";
154      endif
155
156      [cmd_gs, cmd_cleanup] = __ghostscript__ (opts.ghostscript);
157      if (opts.send_to_printer || isempty (opts.name))
158        cmd_lpr = opts.lpr_cmd (opts);
159        cmd = sprintf ("%s | %s", cmd_gs, cmd_lpr);
160      elseif (dosvg)
161        if (dos_shell)
162          cmd = sprintf ("%s & %s", svgcmd, cmd_gs);
163        else
164          cmd = sprintf ("%s ; %s", svgcmd, cmd_gs);
165        endif
166      else
167        cmd = sprintf ("%s", cmd_gs);
168      endif
169
170      if (dosvg)
171        gl2ps_device = {"svg"};
172      else
173        gl2ps_device = {"eps"};
174      endif
175
176      if (! isempty (cmd_cleanup))
177        if (dos_shell)
178          pipeline = {sprintf("%s & %s", cmd, cmd_cleanup)};
179        else
180          pipeline = {sprintf("%s ; %s", cmd, cmd_cleanup)};
181        endif
182      else
183        pipeline = {cmd};
184      endif
185    otherwise
186      error (sprintf ("print:no%soutput", opts.devopt),
187             "print: %s output is not available for OpenGL toolkits",
188             upper (opts.devopt));
189  endswitch
190
191  opts.pipeline = pipeline;
192
193  for n = 1:numel (pipeline)
194    if (opts.debug)
195      fprintf ("opengl-pipeline: '%s'\n", pipeline{n});
196    endif
197
198    if (strcmp (get (opts.figure, "visible"), "on")
199        || (strcmp (get (opts.figure, "__graphics_toolkit__"), "qt")
200            && (strcmp (get (opts.figure, "__gl_window__"), "on")
201                || __have_feature__ ("QT_OFFSCREEN"))))
202      ## Use toolkits "print_figure" method
203      if (ispc () && ! isunix ())
204        drawnow (gl2ps_device{n}, ['| "' pipeline{n} '"']);
205      else
206        drawnow (gl2ps_device{n}, ["| " pipeline{n}]);
207      endif
208    else
209      error ("print: figure must be visible or qt toolkit must be used with __gl_window__ property 'on' or QT_OFFSCREEN feature available");
210    endif
211  endfor
212
213  if (! isempty (strfind (opts.devopt, "standalone")))
214    opts.latex_standalone (opts);
215  endif
216
217endfunction
218