scripts/plot/gnuplot_drawnow.m
author Ben Abbott <bpabbott@mac.com>
Thu Aug 06 07:30:34 2009 +0200 (2009-08-06)
changeset 9395 54a3fa5d4376
parent 9367 a7dbfd45c2aa
child 9416 7ed8182b783d
permissions -rw-r--r--
Avoid the flickering x11 window seen with rapid gnuplot updates.
     1 ## Copyright (C) 2005, 2006, 2007, 2008, 2009 John W. Eaton
     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} {} drawnow ()
    21 ## Update and display the current graphics.
    22 ##
    23 ## Octave automatically calls drawnow just before printing a prompt,
    24 ## when @code{sleep} or @code{pause} is called, or while waiting for
    25 ## command-line input.
    26 ## @end deftypefn
    27 
    28 ## Author: jwe
    29 
    30 function gnuplot_drawnow (h, term, file, mono, debug_file)
    31 
    32   if (nargin < 4)
    33     mono = false;
    34   endif
    35 
    36   if (nargin >= 3 && nargin <= 5)
    37     ## Produce various output formats, or redirect gnuplot stream to a
    38     ## debug file.
    39     plot_stream = [];
    40     fid = [];
    41     printing = ! output_to_screen (gnuplot_trim_term (term));
    42     default_plot_stream = get (h, "__plot_stream__");
    43     unwind_protect
    44       plot_stream = __gnuplot_open_stream__ (2, h);
    45       if (__gnuplot_has_feature__ ("variable_GPVAL_TERMINALS"))
    46         available_terminals = __gnuplot_get_var__ (plot_stream, "GPVAL_TERMINALS");
    47         available_terminals = regexp (available_terminals, "\\b\\w+\\b", "match");
    48         gnuplot_supports_term = any (strcmpi (available_terminals,
    49                                               gnuplot_trim_term (term)));
    50       else
    51         gnuplot_supports_term = true;
    52       endif
    53       if (gnuplot_supports_term)
    54         [enhanced, implicit_margin] = gnuplot_set_term (plot_stream (1), true,
    55                                                         h, term, file);
    56         __go_draw_figure__ (h, plot_stream(1), enhanced, mono, printing, implicit_margin);
    57         if (nargin == 5)
    58           fid = fopen (debug_file, "wb");
    59           [enhanced, implicit_margin] = gnuplot_set_term (fid, true, h, term, file);
    60           __go_draw_figure__ (h, fid, enhanced, mono, printing, implicit_margin);
    61         endif
    62       else
    63         error ("gnuplot_drawnow: the gnuplot terminal, \"%s\", is not available.",
    64                gnuplot_trim_term (term))
    65       endif
    66     unwind_protect_cleanup
    67       set (h, "__plot_stream__", default_plot_stream);
    68       if (! isempty (plot_stream))
    69         pclose (plot_stream(1));
    70         if (numel (plot_stream) == 2)
    71           pclose (plot_stream(2));
    72         endif
    73       endif
    74       if (! isempty (fid))
    75         fclose (fid);
    76       endif
    77     end_unwind_protect
    78   elseif (nargin == 1)
    79     ##  Graphics terminal for display.
    80     plot_stream = get (h, "__plot_stream__");
    81     if (isempty (plot_stream))
    82       plot_stream = __gnuplot_open_stream__ (2, h);
    83       new_stream = true;
    84     else
    85       new_stream = false;
    86     endif
    87     enhanced = gnuplot_set_term (plot_stream (1), new_stream, h);
    88     __go_draw_figure__ (h, plot_stream (1), enhanced, mono, 0);
    89     fflush (plot_stream (1));
    90   else
    91     print_usage ();
    92   endif
    93 
    94 endfunction
    95 
    96 function implicit_margin = gnuplot_implicit_margin (term, opts_str)
    97   ## gnuplot has an implicit margin of 50pts for PS output.
    98   if (strcmpi (term, "postscript"))
    99     if (isempty (strfind (opts_str, " eps"))
   100         && isempty (strfind (opts_str, "eps ")))
   101       implicit_margin = 50/72;
   102     else
   103       ## When zero, the behavior of gnuplot changes.
   104       implicit_margin = 1/72;
   105     endif
   106   else
   107     implicit_margin = 0.0;
   108   endif
   109 endfunction
   110 
   111 function [enhanced, implicit_margin] = gnuplot_set_term (plot_stream, new_stream, h, term, file)
   112   ## Generate the gnuplot "set terminal <term> ..." command.
   113   ## When "term" originates from print.m, it may include other options.
   114   if (nargin < 4)
   115     ## This supports the gnuplot backend.
   116     term = gnuplot_default_term ();
   117     opts_str = "";
   118   else
   119     ## Get the one word terminal id and save the remaining as options to
   120     ## be passed on to gnuplot.  The terminal may respect the backend.
   121     [term, opts_str] = gnuplot_trim_term (term);
   122     if (strcmpi (term, "pdf") && strcmpi (opts_str, "color"))
   123       ## FIXME -- "color" for the pdf terminal produces a gnuplot error.
   124       opts_str = "";
   125     endif
   126   endif
   127 
   128   implicit_margin = gnuplot_implicit_margin (term, opts_str);
   129 
   130   enhanced = gnuplot_is_enhanced_term (term);
   131 
   132   ## Set the terminal.
   133   if (! isempty (term))
   134 
   135     if (enhanced)
   136       enh_str = "enhanced";
   137     else
   138       enh_str = "";
   139     endif
   140 
   141     if (! isempty (h) && isfigure (h))
   142 
   143       ## Generate gnuoplot title string for backend plot windows.
   144       if (output_to_screen (term))
   145         fig.numbertitle = get (h, "numbertitle");
   146         fig.name = get (h, "name");
   147         if (strcmpi (get (h, "numbertitle"), "on"))
   148           title_str = sprintf ("Figure %d", h);
   149         else
   150           title_str = "";
   151         endif
   152         if (! isempty (fig.name) && ! isempty (title_str))
   153           title_str = sprintf ("%s: %s", title_str, fig.name);
   154         elseif (! isempty (fig.name) && isempty (title_str))
   155           title_str = fig.name;
   156         endif
   157         if (! isempty (title_str))
   158           title_str = sprintf ("title \"%s\"", title_str);
   159         endif
   160       else
   161         title_str = "";
   162       endif
   163       if (! (any (strfind (opts_str, " size ") > 0) 
   164 	  || any (strfind (opts_str, "size ") == 1)))
   165         ## Convert position to units used by gnuplot.
   166         if (output_to_screen (term))
   167           ## Get figure size in pixels.  Rely on listener
   168 	  ## to handle coversion of position property.
   169 	  units = get (h, "units");
   170 	  unwind_protect
   171 	    set (h, "units", "pixels");
   172 	    position_in_pixesl = get (h, "position");
   173 	  unwind_protect_cleanup
   174 	    set (h, "units", units);
   175 	  end_unwind_protect
   176 	  gnuplot_pos = position_in_pixesl(1:2);
   177 	  gnuplot_size = position_in_pixesl(3:4);
   178         else
   179           ## Get size of the printed plot in inches. Rely on listener
   180 	  ## to handle coversion of papersize property.
   181 	  paperunits = get (h, "paperunits");
   182 	  unwind_protect
   183 	    set (h, "paperunits", "inches");
   184             gnuplot_size = get (h, "papersize");
   185 	  unwind_protect_cleanup
   186 	    set (h, "paperunits", paperunits);
   187 	  end_unwind_protect
   188           if (term_units_are_pixels (term))
   189 	    ## Convert to inches using the property set by print().
   190 	    gnuplot_size = gnuplot_size * get (h, "__pixels_per_inch__");
   191 	  else
   192 	    ## Implicit margins are in units of "inches"
   193 	    gnuplot_size = gnuplot_size - implicit_margin;
   194           endif
   195         endif
   196 	[begin_match, end_match, te, match] = regexp (opts_str, "(\\s-r\\d+)|(^-r\\d+)");
   197 	if (! isempty (begin_match))
   198 	  error ("gnuplot_drawnow.m: specifying resultion, '%s', not supported for terminal '%s'",
   199 	         strtrim (match{1}), term)
   200 	endif
   201         if (all (gnuplot_size > 0))
   202           ## Set terminal size.
   203           terminals_with_size = {"emf", "gif", "jpeg", "latex", "pbm", ...
   204                                  "pdf", "png", "postscript", "svg", ...
   205                                  "epslatex", "pstex", "pslatex"};
   206           if (__gnuplot_has_feature__ ("x11_figure_position"))
   207             terminals_with_size{end+1} = "x11";
   208           endif
   209           if (__gnuplot_has_feature__ ("wxt_figure_size"))
   210             terminals_with_size{end+1} = "wxt";
   211           endif
   212           if (any (strncmpi (term, terminals_with_size, 3)))
   213 	    if (term_units_are_pixels (term))
   214               size_str = sprintf ("size %d,%d", gnuplot_size);
   215 	    else
   216               size_str = sprintf ("size %.15g,%.15g", gnuplot_size);
   217 	    endif
   218             if (strncmpi (term, "X11", 3) && __gnuplot_has_feature__ ("x11_figure_position"))
   219 	      ## X11 allows the window to be positioned as well.
   220 	      units = get (0, "units");
   221 	      unwind_protect
   222 	        set (0, "units", "pixels");
   223 	        screen_size = get (0, "screensize")(3:4);
   224 	      unwind_protect_cleanup
   225 	        set (0, "units", units);
   226 	      end_unwind_protect
   227               if (all (screen_size > 0))
   228                 ## For X11, set the figure positon as well as the size
   229                 ## gnuplot position is UL, Octave's is LL (same for screen/window)
   230                 gnuplot_pos(2) = screen_size(2) - gnuplot_pos(2) - gnuplot_size(2);
   231                 gnuplot_pos = max (gnuplot_pos, 1);
   232                 size_str = sprintf ("%s position %d,%d", size_str, 
   233                                     gnuplot_pos(1), gnuplot_pos(2));
   234               endif
   235             endif
   236           elseif (strncmpi (term, "aqua", 3))
   237             ## Aqua has size, but the format is different.
   238             size_str = sprintf ("size %d %d", gnuplot_size);
   239           elseif (strncmpi (term, "fig", 3))
   240             ## Fig also has size, but the format is different.
   241             size_str = sprintf ("size %.15g %.15g", gnuplot_size);
   242           elseif (any (strncmpi (term, {"corel", "hpgl"}, 3)))
   243             ## The size for corel and hpgl are goes at the end (implicit).
   244             size_str = sprintf ("%.15g %.15g", gnuplot_size);
   245           elseif (any (strncmpi (term, {"dxf"}, 3)))
   246             ## DXF uses autocad units.
   247             size_str = "";
   248           else
   249             size_str = "";
   250           endif
   251         else
   252           size_str = "";
   253 	  warning ("gnuplot_set_term: size is zero")
   254         endif
   255       else
   256         ## A specified size take priority over the figure properies.
   257         size_str = "";
   258       endif
   259     else
   260       if isempty (h)
   261         disp ("gnuplot_set_term: figure handle is empty")
   262       elseif !isfigure(h)
   263         disp ("gnuplot_set_term: not a figure handle")
   264       endif
   265       title_str = "";
   266       size_str = "";
   267     endif
   268 
   269     ## Set the gnuplot terminal (type, enhanced, title, options & size).
   270     term_str = sprintf ("set terminal %s", term);
   271     if (! isempty (enh_str))
   272       term_str = sprintf ("%s %s", term_str, enh_str);
   273     endif
   274     if (! isempty (title_str))
   275       term_str = sprintf ("%s %s", term_str, title_str);
   276     endif
   277     if (nargin > 3 && ischar (opts_str))
   278       ## Options must go last.
   279       term_str = sprintf ("%s %s", term_str, opts_str);
   280     endif
   281     if (! isempty (size_str) && new_stream)
   282       ## size_str comes after other options to permit specification of
   283       ## the canvas size for terminals cdr/corel.
   284       term_str = sprintf ("%s %s", term_str, size_str);
   285     endif
   286     ## Work around the gnuplot feature of growing the x11 window when
   287     ## the mouse and multiplot are set.
   288     fputs (plot_stream, "unset multiplot;\n");
   289     if (! strcmp (term, "x11")
   290         || numel (findall (h, "type", "axes")) > 1
   291         || numel (findall (h, "type", "image")) > 0)
   292       fprintf (plot_stream, "%s\n", term_str);
   293       if (nargin == 5)
   294         if (! isempty (file))
   295           fprintf (plot_stream, "set output '%s';\n", file);
   296         endif
   297       endif
   298       fputs (plot_stream, "set multiplot;\n");
   299     elseif (strcmp (term, "x11"))
   300       fprintf (plot_stream, "%s\n", term_str);
   301       if (nargin == 5)
   302         if (! isempty (file))
   303           fprintf (plot_stream, "set output '%s';\n", file);
   304         endif
   305       endif
   306     endif
   307   else
   308     ## gnuplot will pick up the GNUTERM environment variable itself
   309     ## so no need to set the terminal type if not also setting the
   310     ## figure title, enhanced mode, or position.
   311   endif
   312 
   313 
   314 endfunction
   315 
   316 function term = gnuplot_default_term ()
   317   term = getenv ("GNUTERM");
   318   ## If not specified, guess the terminal type.
   319   if (isempty (term))
   320     if (ismac ())
   321       term = "aqua";
   322     elseif (! isunix ())
   323       term = "windows";
   324     else
   325       term = "x11";
   326     endif
   327   endif
   328 endfunction
   329 
   330 function [term, opts] = gnuplot_trim_term (string)
   331   ## Extract the terminal type and terminal options (from print.m)
   332   string = deblank (string);
   333   n = strfind (string, ' ');
   334   if (isempty (n))
   335     term = string;
   336     opts = "";
   337   else
   338     term = string(1:(n-1));
   339     opts = string((n+1):end);
   340   endif
   341 endfunction
   342 
   343 function have_enhanced = gnuplot_is_enhanced_term (term)
   344   persistent enhanced_terminals;
   345   if (isempty (enhanced_terminals))
   346     ## Don't include pstex, pslatex or epslatex here as the TeX commands
   347     ## should not be interpreted in that case.
   348     enhanced_terminals = {"aqua", "dumb", "png", "jpeg", "gif", "pm", ...
   349                           "windows", "wxt", "svg", "postscript", "x11", "pdf"};
   350   endif
   351   if (nargin < 1)
   352     ## Determine the default gnuplot terminal.
   353     term = gnuplot_default_term ();
   354   endif
   355   have_enhanced = any (strncmp (enhanced_terminals, term, min (numel (term), 3)));
   356 endfunction
   357 
   358 function ret = output_to_screen (term)
   359   ret = any (strcmpi ({"aqua", "wxt", "x11", "windows", "pm"}, term));
   360 endfunction
   361 
   362 function ret = term_units_are_pixels (term)
   363   ret = any (strncmpi ({"emf", "gif", "jpeg", "pbm", "png", "svg"}, term, 3));
   364 endfunction
   365