Mercurial > octave
view scripts/plot/util/print.m @ 31253:a40c0b7aa376
maint: changes to follow Octave coding conventions.
* NEWS.8.md: Wrap lines to 72 chars.
* LSODE-opts.in: Use two spaces after sentence ending period.
* LSODE.cc: Use minimum of two spaces between code and start of comment.
* MemoizedFunction.m: Change copyright date to 2022 since this is the year it
was accepted into core. Don't wrap error() lines to 80 chars. Use newlines
to improve readability of switch statements. Use minimum of two spaces between
code and start of comment.
* del2.m, integral.m, interp1.m, interp2.m, griddata.m, inpolygon.m, waitbar.m,
cubehelix.m, ind2x.m, importdata.m, textread.m, logm.m, lighting.m, shading.m,
xticklabels.m, yticklabels.m, zticklabels.m, colorbar.m, meshc.m, print.m,
__gnuplot_draw_axes__.m, struct2hdl.m, ppval.m, ismember.m, iqr.m: Use a space
between comment character '#' and start of comment. Use hyphen for adjectives
describing dimensions such as "1-D".
* vectorize.m, ode23s.m: Use is_function_handle() instead of "isa (x, "function_handle")"
for clarity and performance.
* clearAllMemoizedCaches.m: Change copyright date to 2022 since this is the
year it was accepted into core. Remove input validation which is done by
interpreter. Use two newlines between end of code and start of BIST tests.
* memoize.m: Change copyright date to 2022 since this is the year it was
accepted into core. Re-wrap documentation to 80 chars. Use
is_function_handle() instead of "isa (x, "function_handle")" for clarity and
performance. Use two newlines between end of code and start of BIST tests.
Use semicolon for assert statements within %!test block. Re-write BIST tests
for input validation.
* __memoize__.m: Change copyright date to 2022 since this is the year it was
accepted into core. Use spaces in for statements to improve readability.
* unique.m: Add FIXME note to commented BIST test
* dec2bin.m: Remove stray newline at end of file.
* triplequad.m: Reduce doubly-commented BIST syntax using "#%!#" to "#%!".
* delaunayn.m: Use input variable names in error() statements. Use minimum of
two spaces between code and start of comment. Use hyphen for describing
dimensions. Use two newlines between end of code and start of BIST tests.
Update BIST tests to pass.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 03 Oct 2022 18:06:55 -0700 |
parents | 55415fa6a20f |
children | 96f751f8392c |
line wrap: on
line source
######################################################################## ## ## Copyright (C) 2008-2022 The Octave Project Developers ## ## See the file COPYRIGHT.md in the top-level directory of this ## distribution or <https://octave.org/copyright/>. ## ## This file is part of Octave. ## ## Octave is free software: you can redistribute it and/or modify it ## under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## Octave is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Octave; see the file COPYING. If not, see ## <https://www.gnu.org/licenses/>. ## ######################################################################## ## -*- texinfo -*- ## @deftypefn {} {} print () ## @deftypefnx {} {} print (@var{options}) ## @deftypefnx {} {} print (@var{filename}, @var{options}) ## @deftypefnx {} {} print (@var{hfig}, @dots{}) ## @deftypefnx {} {@var{RGB} =} print (@qcode{"-RGBImage"}, @dots{}) ## Format a figure for printing and either save it to a file, send it to a ## printer, or return an RGB image. ## ## @var{filename} defines the name of the output file. If the filename has ## no suffix then one is inferred from the specified device and appended to the ## filename. When neither a filename nor the @qcode{"-RGBImage"} option is ## present, the output is sent to the printer. The various options and ## filename arguments may be given in any order, except for the figure handle ## argument @var{hfig} which must be first if it is present. ## ## Example: Print to a file using PDF and JPEG formats. ## ## @example ## @group ## figure (1); ## clf (); ## surf (peaks); ## print figure1.pdf # The extension specifies the format ## print -djpg figure1 # Will produce "figure1.jpg" file ## @end group ## @end example ## ## If the first argument is a handle @var{hfig} to a figure object then it ## specifies the figure to print. By default, the current figure returned ## by @code{gcf} is printed. ## ## For outputs to paged formats, for example, PostScript and PDF, the page size ## is specified by the figure's @code{papersize} property together with the ## @code{paperunits} property. The location and size of the plot on the page ## are specified by the figure's @code{paperposition} property. The ## orientation of the page is specified by the figure's @code{paperorientation} ## property. ## ## For non-page formats---for example, image formats like JPEG---the width and ## height of the output are specified by the figure's @code{paperposition(3:4)} ## property values. ## ## The @code{print} command supports many @var{options}: ## ## @table @code ## @item -f@var{h} ## Specify the handle, @var{h}, of the figure to be printed. ## ## Example: Print figure 1. ## ## @example ## @group ## figure (1); ## clf (); ## surf (peaks); ## figure (2); ## print -f1 figure1.pdf ## ## Equivalent functional form: ## print (1, "figure1.pdf") ## @end group ## @end example ## ## @item -P@var{printer} ## Set the @var{printer} name to which the plot is sent if no @var{filename} ## is specified. ## ## Example: Print to printer named PS_printer using PostScript format. ## ## @example ## @group ## clf (); ## surf (peaks); ## print -dpswrite -PPS_printer ## @end group ## @end example ## ## @item -RGBImage ## Return an M-by-N-by-3 RGB image of the figure. The size of the image ## depends on the formatting options. This is similar to taking a screen ## capture of the plot, but formatting options may be changed such as the ## resolution or monochrome/color. ## ## Example: Get the pixels of a figure image. ## ## @example ## @group ## clf (); ## surf (peaks); ## @var{rgb} = print ("-RGBImage"); ## @end group ## @end example ## ## @item -image | -opengl ## @itemx -vector | -painters ## Specifies whether the pixel-based renderer (@env{-image} or @env{-opengl}) ## or vector-based renderer (@env{-vector} or @env{-painters}) is used. This ## is equivalent to changing the figure's @qcode{"Renderer"} property. When ## the figure @nospell{@qcode{"RendererMode"}} property is @qcode{"auto"} (the ## default) Octave will use the @qcode{"opengl"} renderer for raster formats ## (e.g., JPEG) and @qcode{"painters"} for vector formats (e.g., PDF)@. These ## options are only supported for the "qt" graphics toolkit. ## ## @item -svgconvert ## When using the @option{-painters} renderer, this enables a different ## backend toolchain with enhanced characteristics: ## ## @table @asis ## @item Font handling: ## For interpreters "none" and "tex", the actual font is embedded in the output ## file which allows for printing arbitrary characters and fonts in all vector ## formats. ## ## Strings using the @qcode{"latex"} interpreter, are rendered using path ## objects. This looks good but note that textual info (font, ## characters@dots{}) are lost. ## ## @item Output Simplification: ## By default, the option @option{-painters} renders patch and surface objects ## using assemblies of triangles. This may lead to anti-aliasing artifacts ## when viewing the file. The @option{-svgconvert} option reconstructs ## polygons in order to avoid those artifacts (particularly for 2-D figures). ## ## @item Transparency: ## Allows for printing transparent graphics objects in PDF format. ## For PostScript formats the presence of any transparent object will cause the ## output to be rasterized. ## @end table ## ## Caution: If Octave was built against Qt version earlier than 5.13, ## @option{-svgconvert} may lead to inaccurate rendering of image objects. ## ## @item -portrait ## @itemx -landscape ## Specify the orientation of the plot for printed output. ## For non-printed output the aspect ratio of the output corresponds to the ## plot area defined by the @qcode{"paperposition"} property in the ## orientation specified. This option is equivalent to changing the figure's ## @qcode{"paperorientation"} property. ## ## @item -fillpage ## @itemx -bestfit ## When using a page-based format (PDF, PostScript, printer) ignore the ## @qcode{"paperposition"} property and have the plot occupy the entire page. ## The option @option{-fillpage} will stretch the plot to occupy the page with ## 0.25 inch margins all around. The option @option{-bestfit} will expand the ## plot to take up as much room as possible on the page @strong{without} ## distorting the original aspect ratio of the plot. ## ## @item -color ## @itemx -mono ## Color or monochrome output. ## ## @item -solid ## @itemx -dashed ## Force all lines to be solid or dashed, respectively. ## ## @item -noui ## Don't print uicontrol objects such as pushbuttons which may overlay the ## plot. This is the default behavior and it is not possible to include ## uicontrol objects in the output without using an external screen capture ## tool. ## ## @item -r@var{NUM} ## Resolution of bitmaps in dots per inch (DPI). For both metafiles and SVG ## the default is the screen resolution; for other formats the default is 150 ## DPI@. To specify screen resolution, use @qcode{"-r0"}. ## ## Example: high resolution raster output. ## ## @example ## @group ## clf (); ## surf (peaks (), "facelighting", "gouraud"); ## light (); ## print ("-r600", "lit_peaks.png"); ## @end group ## @end example ## ## @item -S@var{xsize},@var{ysize} ## Plot size in pixels for raster formats including PNG, JPEG, PNG, and ## @emph{unusually} SVG@. For all vector formats, including PDF, PS, and EPS, ## the plot size is specified in points. This option is equivalent to changing ## the width and height of the output by setting the figure property ## @code{paperposition(3:4)}. When using the command form of the print ## function you must quote the @var{xsize},@var{ysize} option to prevent the ## Octave interpreter from recognizing the embedded comma (','). For example, ## by writing @w{"-S640,480"}. ## ## @item -tight ## @itemx -loose ## Force a tight or loose bounding box for EPS files. The default is tight. ## ## @item -@var{preview} ## Add a preview to EPS files. Supported formats are: ## ## @table @code ## @item -interchange ## Provide an interchange preview. ## ## @item -metafile ## Provide a metafile preview. ## ## @item -pict ## Provide a pict preview. ## ## @item -tiff ## Provide a TIFF preview. ## @end table ## ## @item -append ## Append PostScript or PDF output to an existing file of the same type. ## ## @item -F@var{fontname} ## @itemx -F@var{fontname}:@var{size} ## @itemx -F:@var{size} ## Use @var{fontname} and/or @var{fontsize} for all text. ## @var{fontname} is ignored for some devices: fig, etc. ## ## @item -d@var{device} ## The available output format is specified by the option @var{device}, and ## is one of the following (devices marked with a @qcode{'*'} are only ## available with the Gnuplot toolkit): ## ## Vector Formats ## ## @table @code ## @item svg ## Scalable Vector Graphics. ## ## @item pdf ## @itemx pdfcrop ## Portable Document Format. The @code{pdf} device formats the figure for ## printing on paper. The size of the surrounding page and the position of the ## figure inside the page are defined by the ## @ref{XREFfigurepaperorientation,, paper* figure properties}. ## ## Use @code{pdfcrop} if you don't want the surrounding page. ## ## By default, PDF inherits the same limitations as PostScript. ## For an enhanced output with complete text support and basic transparency, ## use the @option{-svgconvert} option. ## ## @item eps(2) ## @itemx epsc(2) ## Encapsulated PostScript (level 1 and 2, mono and color). ## ## The OpenGL-based graphics toolkits always generate PostScript level 3.0. ## They have limited support for text unless using the @option{-svgconvert} ## option. ## Limitations include using only ASCII characters (e.g., no Greek letters) ## and support for just three base PostScript fonts: Helvetica (the default), ## Times, or Courier. Any other font will be replaced by Helvetica. ## ## @item ps(2) ## @itemx psc(2) ## Same as @code{eps} except that the figure is formatted for printing on ## paper. The size of the surrounding page and position of the figure inside ## the page are defined by the ## @ref{XREFfigurepaperorientation,, paper* figure properties}. ## ## @item pslatex ## @itemx epslatex ## @itemx pdflatex ## @itemx pslatexstandalone ## @itemx epslatexstandalone ## @itemx pdflatexstandalone ## Generate a @LaTeX{} file @file{@var{filename}.tex} for the text portions ## of a plot and a file @file{@var{filename}.(ps|eps|pdf)} for the remaining ## graphics. The graphics file suffix .ps|eps|pdf is determined by the ## specified device type. The @LaTeX{} file produced by the @samp{standalone} ## option can be processed directly by @LaTeX{}. The file generated without ## the @samp{standalone} option is intended to be included from another ## @LaTeX{} document. In either case, the @LaTeX{} file contains an ## @code{\includegraphics} command so that the generated graphics file is ## automatically included when the @LaTeX{} file is processed. The text that ## is written to the @LaTeX{} file contains the strings @strong{exactly} as ## they were specified in the plot. If any special characters of the @TeX{} ## mode interpreter were used, the file must be edited before @LaTeX{} ## processing. Specifically, the special characters must be enclosed with ## dollar signs @w{(@code{$ @dots{} $})}, and other characters that are ## recognized by @LaTeX{} may also need editing (e.g., braces). The ## @samp{pdflatex} device, and any of the @samp{standalone} formats, are not ## available with the Gnuplot toolkit. ## ## @item epscairo* ## @itemx pdfcairo* ## @itemx epscairolatex* ## @itemx pdfcairolatex* ## @itemx epscairolatexstandalone* ## @itemx pdfcairolatexstandalone* ## Generate output with Cairo renderer. The devices @code{epscairo} and ## @code{pdfcairo} are synonymous with the @code{epsc} device. The @LaTeX{} ## variants generate a @LaTeX{} file, @file{@var{filename}.tex}, for the text ## portions of a plot, and an image file, @file{@var{filename}.(eps|pdf)}, for ## the graph portion of the plot. The @samp{standalone} variants behave as ## described for @samp{epslatexstandalone} above. ## ## @item canvas* ## Javascript-based drawing on an HTML5 canvas viewable in a web browser. ## ## @item emf ## @itemx meta ## Microsoft Enhanced Metafile ## ## @item fig ## XFig. For the Gnuplot graphics toolkit, the additional options ## @option{-textspecial} or @option{-textnormal} (default) can be used to ## control whether the special flag should be set for the text in the figure. ## ## @item latex* ## @itemx eepic* ## @LaTeX{} picture environment and extended picture environment. ## ## @item tikz ## @itemx tikzstandalone* ## Generate a @LaTeX{} file using PGF/TikZ format. The OpenGL-based ## toolkits create a PGF file while Gnuplot creates a TikZ file. The ## @samp{tikzstandalone} device produces a @LaTeX{} document which includes the ## TikZ file. ## ## @end table ## ## Raster Formats ## ## @table @code ## @item png ## Portable Network Graphics ## ## @item jpg ## @itemx jpeg ## JPEG image ## ## @item tif ## @itemx tiff ## @itemx tiffn ## TIFF image with LZW compression (@nospell{tif}, tiff) or uncompressed ## (@nospell{tiffn}). ## ## @item gif ## GIF image ## ## @item pbm ## PBMplus ## ## @item dumb* ## ASCII art ## ## @end table ## ## If the device is omitted, it is inferred from the file extension, ## or if there is no filename then it is sent to the printer as PostScript. ## ## @item -d@var{ghostscript_device} ## Additional devices are supported by Ghostscript. ## Some examples are: ## ## @table @code ## @item ljet2p ## HP LaserJet @nospell{IIP} ## ## @item pcx24b ## 24-bit color PCX file format ## ## @item ppm ## Portable Pixel Map file format ## @end table ## ## For a complete list of available formats and devices type ## @kbd{system ("gs -h")}. ## ## When Ghostscript output is sent to a printer the size is determined by ## the figure's @qcode{"papersize"} property. When the output is sent to a ## file the size is determined by the plot box defined by the figure's ## @qcode{"paperposition"} property. ## ## @item -G@var{ghostscript_command} ## Specify the command for calling Ghostscript. For Unix the default is ## @qcode{"gs"} and for Windows it is @qcode{"gswin32c"}. ## ## @item -TextAlphaBits=@var{n} ## @itemx -GraphicsAlphaBits=@var{n} ## Octave is able to produce output for various printers, bitmaps, and ## vector formats by using Ghostscript. For bitmap and printer output ## anti-aliasing is applied using Ghostscript's TextAlphaBits and ## GraphicsAlphaBits options. The default number of bits are 4 and 1 ## respectively. Allowed values for @var{N} are 1, 2, or 4. ## @end table ## ## @seealso{saveas, getframe, savefig, hgsave, orient, figure} ## @end deftypefn function RGB = print (varargin) opts = __print_parse_opts__ (varargin{:}); ## Check the requested file is writable if (! opts.rgb_output) folder = fileparts (opts.name); if (! isempty (folder) && ! isfolder (folder)) error ("print: directory %s does not exist", folder); endif do_unlink = (exist (opts.name, "file") != 2); fid = fopen (opts.name, "a"); if (fid == -1) error ("print: cannot open file %s for writing", opts.name); endif fclose (fid); if (do_unlink) unlink (opts.name); endif endif opts.pstoedit_cmd = @pstoedit; opts.fig2dev_cmd = @fig2dev; opts.latex_standalone = @latex_standalone; opts.lpr_cmd = @lpr; opts.epstool_cmd = @epstool; opts.svgconvert_cmd = @svgconvert; if (isempty (opts.figure) || ! isfigure (opts.figure)) error ("print: no figure to print"); endif if (isempty (findall (opts.figure, "-depth", 1, "type", "axes"))) error ("print: no axes object in figure to print"); endif orig_figure = get (0, "currentfigure"); set (0, "currentfigure", opts.figure); if (opts.append_to_file) [~, ~, ext] = fileparts (opts.ghostscript.output); opts.ghostscript.prepend = [tempname() ext]; copyfile (opts.ghostscript.output, opts.ghostscript.prepend); endif unwind_protect ## Modify properties as specified by options tk = get (opts.figure, "__graphics_toolkit__"); props = []; nfig = 0; drawnow (); ## Set the __printing__ property first props(1).h = opts.figure; props(1).name = "__printing__"; props(1).value = {"off"}; set (opts.figure, "__printing__", "on"); nfig += 1; ## print() requires children of axes to have units = "normalized" or "data" ## FIXME: Bug #59015. The only graphics object type to which this ## requirement applies seems to be 'text' objects. It is simpler, and ## clearer, to just select those objects. The old code is left commented ## out until sufficient testing has been done. ## Change made: 2020/09/02. ##hobj = findall (opts.figure, "-not", "type", "figure", ... ## "-not", "type", "axes", "-not", "type", "hggroup", ... ## "-property", "units", ... ## "-not", "units", "normalized", "-not", "units", "data"); ##hobj(strncmp (get (hobj, "type"), "ui", 2)) = []; hobj = findall (opts.figure, "type", "text", "-not", "units", "normalized", "-not", "units", "data"); for n = 1:numel (hobj) props(end+1).h = hobj(n); props(end).name = "units"; props(end).value = {get(hobj(n), "units")}; set (hobj(n), "units", "data"); nfig += 1; endfor if (strcmp (opts.renderer, "opengl")) ## Scale the figure to reach the required resolution scale = opts.ghostscript.resolution / 72; if (scale != 1) props(end+1).h = opts.figure; props(end).name = "__device_pixel_ratio__"; props(end).value{1} = get (opts.figure, "__device_pixel_ratio__"); set (opts.figure, "__device_pixel_ratio__", scale); nfig += 1; endif elseif (strcmp (tk, "qt")) ## Don't account for the actual pixel density props(end+1).h = opts.figure; props(end).name = "__device_pixel_ratio__"; props(end).value = {get(opts.figure, "__device_pixel_ratio__")}; set (opts.figure, "__device_pixel_ratio__", 1); nfig += 1; endif ## print() requires axes units = "normalized" hax = findall (opts.figure, "-depth", 1, "type", "axes", ... "-not", "units", "normalized"); for n = 1:numel (hax) props(end+1).h = hax(n); props(end).name = "units"; props(end).value = {get(hax(n), "units")}; set (hax(n), "units", "normalized"); nfig += 1; endfor ## With the -painters (gl2ps) renderer, line transparency is only ## handled for svg and pdf outputs using svgconvert. ## Otherwise, switch grid lines color to light gray so that the image ## output approximately matches on-screen experience. hax = findall (opts.figure, "type", "axes"); if (! strcmp (tk, "gnuplot") && ! strcmp (opts.renderer, "opengl") && ! (opts.svgconvert && strcmp (opts.devopt, "pdfwrite")) && ! strcmp (opts.devopt, "svg")) for n = 1:numel (hax) if (strcmp (get (hax(n), "gridcolormode"), "auto")) props(end+1).h = hax(n); props(end).name = "gridcolormode"; props(end).value = {"auto"}; props(end+1).h = hax(n); props(end).name = "gridcolor"; props(end).value = {get(hax(n), "gridcolor")}; set (hax(n), "gridcolor", [0.85 0.85 0.85]); nfig += 2; endif if (strcmp (get (hax(n), "gridalphamode"), "auto")) props(end+1).h = hax(n); props(end).name = "gridalphamode"; props(end).value = {"auto"}; props(end+1).h = hax(n); props(end).name = "gridalpha"; props(end).value = {get(hax(n), "gridalpha")}; set (hax(n), "gridalpha", 1); nfig += 2; endif if (strcmp (get (hax(n), "minorgridcolormode"), "auto")) props(end+1).h = hax(n); props(end).name = "minorgridcolormode"; props(end).value = {"auto"}; props(end+1).h = hax(n); props(end).name = "minorgridcolor"; props(end).value = {get(hax(n), "minorgridcolor")}; set (hax(n), "minorgridcolor", [0.75 0.75 0.75]); nfig += 2; endif if (strcmp (get (hax(n), "minorgridalphamode"), "auto")) props(end+1).h = hax(n); props(end).name = "minorgridalphamode"; props(end).value = {"auto"}; props(end+1).h = hax(n); props(end).name = "minorgridalpha"; props(end).value = {get(hax(n), "minorgridalpha")}; set (hax(n), "minorgridalpha", 1); nfig += 2; endif endfor endif ## print() requires figure units to be "pixels" props(end+1).h = opts.figure; props(end).name = "units"; props(end).value = {get(opts.figure, "units")}; set (opts.figure, "units", "pixels"); nfig += 1; ## graphics toolkit translates figure position to eps bbox (points) fpos = get (opts.figure, "position"); props(end+1).h = opts.figure; props(end).name = "position"; props(end).value = {fpos}; fpos(3:4) = opts.canvas_size; set (opts.figure, "position", fpos); nfig += 1; ## Implement InvertHardCopy option do_hardcopy = strcmp (get (opts.figure, "inverthardcopy"), "on"); if (do_hardcopy) ## Set figure background to white. props(end+1).h = opts.figure; props(end).name = "color"; props(end).value{1} = get (opts.figure, "color"); set (opts.figure, "color", "white"); nfig += 1; endif if (do_hardcopy) ## Set background to white for all top-level axes objects hax = findall (opts.figure, "-depth", 1, "type", "axes", "-not", "tag", "legend", "-not", "color", "none"); if (! isempty (hax)) for n = 1:numel (hax) props(end+1).h = hax(n); props(end).name = "color"; props(end).value{1} = get(hax(n), "color"); set (hax(n), "color", "white"); nfig += 1; endfor endif endif if (opts.force_solid != 0) h = findall (opts.figure, "-property", "linestyle"); m = numel (props); for n = 1:numel (h) props(m+n).h = h(n); props(m+n).name = "linestyle"; props(m+n).value = {get(h(n), "linestyle")}; endfor if (opts.force_solid > 0) linestyle = "-"; else linestyle = "--"; endif set (h, "linestyle", linestyle); endif if (opts.use_color < 0) color_props = {"color", "facecolor", "edgecolor", "colormap"}; for c = 1:numel (color_props) h = findall (opts.figure, "-property", color_props{c}); hnone = findall (opts.figure, color_props{c}, "none"); h = setdiff (h, hnone); m = numel (props); for n = 1:numel (h) if (ishghandle (h(n))) ## Need to verify objects exist since callbacks may delete objects ## as the colors for others are modified. rgb = get (h(n), color_props{c}); props(end+1).h = h(n); props(end).name = color_props{c}; props(end).value = {get(h(n), color_props{c})}; if (isnumeric (rgb)) ## convert RGB color to RGB gray scale xfer = repmat ([0.30, 0.59, 0.11], rows (rgb), 1); ggg = repmat (sum (xfer .* rgb, 2), 1, 3); set (h(n), color_props{c}, ggg); endif endif endfor endfor endif do_font = ! isempty (opts.font); do_scalefontsize = ! isempty (opts.scalefontsize) && opts.scalefontsize != 1; do_fontsize = ! isempty (opts.fontsize) || do_scalefontsize; if (do_font || do_fontsize) h = findall (opts.figure, "-property", "fontname"); m = numel (props); for n = 1:numel (h) if (ishghandle (h(n))) if (do_font) props(end+1).h = h(n); props(end).name = "fontname"; props(end).value = {get(h(n), "fontname")}; endif if (do_fontsize) props(end+1).h = h(n); props(end).name = "fontsize"; props(end).value = {get(h(n), "fontsize")}; endif endif endfor if (do_font) set (h(ishghandle (h)), "fontname", opts.font); endif if (do_fontsize) if (! isempty (opts.fontsize)) ## Changing all fontsizes to a fixed value if (ischar (opts.fontsize)) fontsize = str2double (opts.fontsize); else fontsize = opts.fontsize; endif if (do_scalefontsize) ## This is done to work around the bbox being whole numbers. fontsize *= opts.scalefontsize; endif ## FIXME: legend child objects need to be acted on first. ## or legend fontsize callback will destroy them. hlist = h(ishghandle (h)); haxes = strcmp (get (hlist, "type"), "axes"); set (hlist(! haxes), "fontsize", fontsize); set (hlist(haxes), "fontsize", fontsize); else ## Scaling fonts ## FIXME: legend child objects need to be acted on first. ## or legend fontsize callback will destroy them. hlist = h(ishghandle (h)); haxes = strcmp (get (hlist, "type"), "axes"); for h = hlist(! haxes).' fontsz = get (h, "fontsize"); set (h, "fontsize", fontsz * opts.scalefontsize); endfor for h = hlist(haxes).' fontsz = get (h, "fontsize"); set (h, "fontsize", fontsz * opts.scalefontsize); endfor endif endif endif ## When exporting latex files use "latex" for the ticklabelinterpreter. ## It will format tick labels in log axes correctly if (strfind (opts.devopt, "latex")) ## Disable warnings about Latex being unsupported since Octave will be ## passing Latex code directly to interpreter with no rendering. warning ("off", "Octave:text_interpreter", "local"); h = findall (opts.figure, "type", "axes"); for n = 1:numel (h) if (ishghandle (h(n))) props(end+1).h = h(n); props(end).name = "ticklabelinterpreter"; props(end).value = {get(h(n), "ticklabelinterpreter")}; set (h(n), "ticklabelinterpreter", "latex"); endif endfor endif ## call the graphics toolkit print script switch (tk) case "gnuplot" opts = __gnuplot_print__ (opts); otherwise if (strcmp (opts.renderer, "opengl")) if (opts.rgb_output) RGB = __get_frame__ (opts.figure); else compression = "none"; if (strcmp (opts.devopt, "tiff")) compression = "lzw"; elseif (strcmp (opts.devopt, "tiffn")) opts.devopt = "tiff"; endif imwrite (__get_frame__ (opts.figure), opts.name, ... opts.devopt, "Compression", compression); endif else opts = __opengl_print__ (opts); endif endswitch unwind_protect_cleanup ## restore modified properties if (isstruct (props)) ## Restore figure position and units first for n = nfig:-1:1 if (ishghandle (props(n).h)) set (props(n).h, props(n).name, props(n).value{1}); endif endfor for n = numel (props):-1:(nfig + 1) if (ishghandle (props(n).h)) set (props(n).h, props(n).name, props(n).value{1}); endif endfor endif ## Avoid a redraw since the figure should not have changed ## FIXME: Bug #57552, marker sizes, requires that redraw be done. ## set (gcf, "__modified__", "off"); ## Unlink temporary files for n = 1:numel (opts.unlink) [status, output] = unlink (opts.unlink{n}); if (status != 0) warning ("Octave:print:unlinkerror", ... "print: %s, '%s'", output, opts.unlink{n}); endif endfor end_unwind_protect if (isfigure (orig_figure)) set (0, "currentfigure", orig_figure); endif endfunction %!error <a graphics handle> %! hf = figure ("visible", "off"); %! unwind_protect %! x = 0:0.1:1; %! y1 = x; %! y2 = 2*x; %! ax = plotyy (x, y1, x, y2); %! saveas (ax, [tempname(), ".png"]); %! unwind_protect_cleanup %! close (hf); %! end_unwind_protect function cmd = epstool (opts, filein, fileout) ## As epstool does not work with pipes, a subshell is used to ## permit piping. Since this solution does not work with the DOS ## command shell, the -tight and -preview options are disabled if ## output must be piped. ## DOS Shell: ## gs.exe [...] -sOutputFile=<filein> - & epstool -bbox -preview-tiff <filein> <fileout> & del <filein> ## Unix Shell: ## cat > <filein> ; epstool -bbox -preview-tiff <filein> <fileout> ; rm <filein> dos_shell = (ispc () && ! isunix ()); ## HACK: Keep track of whether ghostscript supports epswrite or eps2write. persistent epsdevice; if (dos_shell && isempty (epsdevice)) if (isempty (opts.ghostscript.binary)) error ("Octave:print:nogs", "print: 'gs' (Ghostscript) is required for specified output format, but binary is not available in PATH"); endif [status, devlist] = system (sprintf ("%s -h", opts.ghostscript.binary)); if (isempty (strfind (devlist, "eps2write"))) epsdevice = "epswrite"; else epsdevice = "eps2write"; endif endif cleanup = ""; if (nargin < 3) fileout = opts.name; elseif (isempty (fileout)) fileout = "-"; endif if (nargin < 2 || strcmp (filein, "-") || isempty (filein)) pipein = true; filein = [tempname() ".eps"]; if (dos_shell) cleanup = sprintf ('& del "%s" ', strrep (filein, '/', '\')); else cleanup = sprintf ('; rm "%s" ', filein); endif else pipein = false; filein = ["'" strtrim(filein) "'"]; endif if (strcmp (fileout, "-")) pipeout = true; fileout = [tempname() ".eps"]; if (dos_shell) cleanup = [cleanup, sprintf('& del "%s" ', strrep (fileout, '/', '\'))]; else cleanup = [cleanup, sprintf('; rm "%s" ', fileout)]; endif else pipeout = false; fileout = ["'" strtrim(fileout) "'"]; endif if (! isempty (opts.preview) && opts.tight) warning ("Octave:print:previewandtight", "print: eps preview may not be combined with -tight"); endif if (! isempty (opts.preview) || opts.tight) if (isempty (opts.epstool_binary)) error ("Octave:print:noepstool", "print: 'epstool' is required for specified output format, but binary is not available in PATH"); endif if (opts.tight) cmd = "--copy --bbox"; elseif (! isempty (opts.preview)) switch (opts.preview) case "tiff" cmd = sprintf ("--add-%s-preview --device tiffg3", opts.preview); case {"tiff6u", "tiff6p", "metafile"} cmd = sprintf ("--add-%s-preview --device bmpgray", opts.preview); case {"tiff4", "interchange"} cmd = sprintf ("--add-%s-preview", opts.preview); case "pict" cmd = sprintf ("--add-%s-preview --mac-single", opts.preview); otherwise error ("Octave:print:invalidpreview", "print: epstool cannot include preview for format '%s'", opts.preview); endswitch if (! isempty (opts.ghostscript.resolution)) cmd = sprintf ("%s --dpi %d", cmd, fix (opts.ghostscript.resolution)); endif else cmd = ""; endif if (! isempty (cmd)) if (dos_shell) ## ghostscript expects double, not single, quotes fileout(fileout == "'") = '"'; ## epstool implicitly uses ghostscript and it needs the command name cmd = sprintf ("%s --gs %s --quiet %s %s %s ", opts.epstool_binary, opts.ghostscript.binary, cmd, filein, fileout); else cmd = sprintf ("%s --quiet %s %s %s ", opts.epstool_binary, cmd, filein, fileout); endif endif if (pipein) if (dos_shell) filein(filein=="'") = '"'; gs_cmd = __ghostscript__ ("binary", opts.ghostscript.binary, "device", epsdevice, "source", "-", "output", filein); cmd = sprintf ("%s %s & %s", gs_cmd, filein, cmd); else cmd = sprintf ("cat > %s ; %s", filein, cmd); endif endif if (pipeout) if (dos_shell) cmd = sprintf ("%s & type %s", cmd, fileout); else cmd = sprintf ("%s ; cat %s", cmd, fileout); endif endif if (! isempty (cleanup)) if (pipeout && dos_shell) error ("Octave:print:epstoolpipe", "print: cannot pipe output of 'epstool' for DOS shell"); elseif (pipeout) cmd = sprintf ("( %s %s )", cmd, cleanup); else cmd = sprintf ("%s %s", cmd, cleanup); endif endif else if (pipein && pipeout) if (dos_shell) cmd = __ghostscript__ ("binary", opts.ghostscript.binary, "device", epsdevice, "source", "-", "output", "-"); else cmd = " cat "; endif elseif (pipein && ! pipeout) if (dos_shell) ## ghostscript expects double, not single, quotes fileout(fileout=="'") = '"'; cmd = __ghostscript__ ("binary", opts.ghostscript.binary, "device", epsdevice, "source", "-", "output", fileout); else cmd = sprintf (" cat > %s ", fileout); endif elseif (! pipein && pipeout) if (dos_shell) cmd = sprintf (" type %s ", filein); else cmd = sprintf (" cat %s ", filein); endif else if (dos_shell) cmd = sprintf (" copy %s %s ", filein, fileout); else cmd = sprintf (" cp %s %s ", filein, fileout); endif endif endif if (opts.debug) fprintf ("epstool command: '%s'\n", cmd); endif endfunction function cmd = fig2dev (opts, devopt) if (nargin < 2) devopt = opts.devopt; endif if (isempty (opts.fig2dev_binary)) error ("Octave:print:nofig2dev", "print: 'fig2dev' is required for specified output format, but binary is not available in PATH"); endif dos_shell = (ispc () && ! isunix ()); if (dos_shell) ## FIXME: Is this the right thing to do for DOS? cmd = sprintf ("%s -L %s 2> NUL", opts.fig2dev_binary, devopt); else cmd = sprintf ("%s -L %s 2> /dev/null", opts.fig2dev_binary, devopt); endif if (opts.debug) fprintf ("fig2dev command: '%s'\n", cmd); endif endfunction function latex_standalone (opts) n = find (opts.name == ".", 1, "last"); if (! isempty (n)) opts.name = opts.name(1:n-1); endif latexfile = [opts.name ".tex"]; switch (opts.devopt) case {"pdflatexstandalone"} packages = "\\usepackage{graphicx,color}"; case {"pslatexstandalone"} packages = "\\usepackage{epsfig,color}"; otherwise packages = "\\usepackage{epsfig,color}"; endswitch packages = {packages "\\usepackage[utf8]{inputenc}"}; papersize = sprintf ("\\usepackage[papersize={%.2fbp,%.2fbp},text={%.2fbp,%.2fbp}]{geometry}", fix (opts.canvas_size), fix (opts.canvas_size)); prepend = {"\\documentclass{minimal}", packages{:}, papersize, ... "\\begin{document}", "\\centering"}; postpend = {"\\end{document}"}; fid = fopen (latexfile, "r"); if (fid < 0) error ("Octave:print:erroropeningfile", "print: error opening file '%s'", latexfile); endif latex = fscanf (fid, "%c", Inf); status = fclose (fid); if (status != 0) error ("Octave:print:errorclosingfile", "print: error closing file '%s'", latexfile); endif fid = fopen (latexfile, "w"); if (fid >= 0) fprintf (fid, "%s\n", prepend{:}); fprintf (fid, "%s", latex); fprintf (fid, "%s\n", postpend{:}); status = fclose (fid); if (status != 0) error ("Octave:print:errorclosingfile", "print: error closing file '%s'", latexfile); endif else error ("Octave:print:erroropeningfile", "print: error opening file '%s'", latexfile); endif endfunction function cmd = lpr (opts) if (nargin < 2) devopt = opts.devopt; endif if (! isempty (opts.lpr_binary)) cmd = opts.lpr_binary; if (! isempty (opts.lpr_options)) cmd = sprintf ("%s %s", cmd, opts.lpr_options); endif if (! isempty (opts.printer)) cmd = sprintf ("%s %s", cmd, opts.printer); endif elseif (isempty (opts.lpr_binary)) error ("Octave:print:nolpr", "print: 'lpr' not found in PATH"); endif if (opts.debug) fprintf ("lpr command: '%s'\n", cmd); endif endfunction function cmd = pstoedit (opts, devopt, do_svg = true) if (nargin < 2) devopt = opts.devopt; endif if (isempty (opts.pstoedit_binary)) error ("Octave:print:nopstoedit", ... "print: 'pstoedit' is required for specified output format, but binary is not available in PATH"); endif dos_shell = (ispc () && ! isunix ()); if (! do_svg) if (dos_shell) cmd = sprintf ("%s -f %s 2> NUL", opts.pstoedit_binary, devopt); else cmd = sprintf ("%s -f %s 2> /dev/null", opts.pstoedit_binary, devopt); endif else cmd = svgconvert (opts, devopt); if (dos_shell) cmd = sprintf ('%s & %s -ssp -f %s "%%s" 2> NUL', cmd, ... undo_string_escapes (opts.pstoedit_binary), ... undo_string_escapes (devopt)); else cmd = sprintf ('%s ; %s -ssp -f %s "%%s" 2> /dev/null', cmd, ... opts.pstoedit_binary, devopt); endif endif if (opts.debug) fprintf ("pstoedit command: '%s'\n", cmd); endif endfunction function cmd = svgconvert (opts, devopt) cmd = ""; if (nargin < 2) devopt = opts.devopt; endif if (isempty (opts.svgconvert_binary)) warning ("Octave:print:nosvgconvert", ... ["print: unable to find octave-svgconvert, ", ... "falling back to eps conversion"]); else fontdir = getenv ("OCTAVE_FONTS_DIR"); if (isempty (fontdir)) fontdir = __octave_config_info__ ("octfontsdir"); endif cmd = sprintf ('%s - %%s %3.2f "%s" %d "%%s"', ... undo_string_escapes (opts.svgconvert_binary), ... get (0, "screenpixelsperinch"), ... undo_string_escapes (fullfile (fontdir, "FreeSans.otf")), 1); if (opts.debug) fprintf ("svgconvert command: '%s'\n", cmd); endif endif endfunction