reverse-shooting

Matlab scripts for reverse shooting
Log | Files | Refs | README

exportfig.m (31654B)


      1 function varargout = exportfig(varargin)
      2 %EXPORTFIG  Export a figure.
      3 %   EXPORTFIG(H, FILENAME) writes the figure H to FILENAME.  H is
      4 %   a figure handle and FILENAME is a string that specifies the
      5 %   name of the output file.
      6 %
      7 %   EXPORTFIG(H, FILENAME, OPTIONS) writes the figure H to FILENAME
      8 %   with options initially specified by the structure OPTIONS. The
      9 %   field names of OPTIONS must be legal parameters listed below
     10 %   and the field values must be legal values for the corresponding
     11 %   parameter. Default options can be set in releases prior to R12
     12 %   by storing the OPTIONS structure in the root object's appdata
     13 %   with the command 
     14 %      setappdata(0,'exportfigdefaults', OPTIONS) 
     15 %   and for releases after R12 by setting the preference with the
     16 %   command 
     17 %      setpref('exportfig', 'defaults', OPTIONS) 
     18 %
     19 %   EXPORTFIG(...,PARAM1,VAL1,PARAM2,VAL2,...) specifies
     20 %   parameters that control various characteristics of the output
     21 %   file. Any parameter value can be the string 'auto' which means
     22 %   the parameter uses the default factory behavior, overriding
     23 %   any other default for the parameter.
     24 %
     25 %   Format Paramter:
     26 %     'Format'  a string
     27 %          specifies the output format. Defaults to 'eps'. For a
     28 %          list of export formats type 'help print'.
     29 %     'Preview' one of the strings 'none', 'tiff'
     30 %          specifies a preview for EPS files. Defaults to 'none'.
     31 %
     32 %   Size Parameters:
     33 %     'Width'   a positive scalar
     34 %          specifies the width in the figure's PaperUnits
     35 %     'Height'  a positive scalar
     36 %          specifies the height in the figure's PaperUnits
     37 %     'Bounds' one of the strings 'tight', 'loose'
     38 %          specifies a tight or loose bounding box. Defaults to 'tight'.
     39 %     'Reference' an axes handle or a string
     40 %          specifies that the width and height parameters
     41 %          are relative to the given axes. If a string is
     42 %          specified then it must evaluate to an axes handle.
     43 %
     44 %     Specifying only one dimension sets the other dimension
     45 %     so that the exported aspect ratio is the same as the
     46 %     figure's or reference axes' current aspect ratio. 
     47 %     If neither dimension is specified the size defaults to 
     48 %     the width and height from the figure's or reference
     49 %     axes' size. Tight bounding boxes are only computed for
     50 %     2-D views and in that case the computed bounds enclose all
     51 %     text objects.
     52 %           
     53 %   Rendering Parameters:
     54 %     'Color'     one of the strings 'bw', 'gray', 'cmyk'
     55 %         'bw'    specifies that lines and text are exported in
     56 %                 black and all other objects in grayscale
     57 %         'gray'  specifies that all objects are exported in grayscale
     58 %         'rgb'   specifies that all objects are exported in color
     59 %                 using the RGB color space
     60 %         'cmyk'  specifies that all objects are exported in color
     61 %                 using the CMYK color space
     62 %     'Renderer'  one of 'painters', 'zbuffer', 'opengl'
     63 %         specifies the renderer to use
     64 %     'Resolution'   a positive scalar
     65 %         specifies the resolution in dots-per-inch.
     66 %     'LockAxes'  one of 0 or 1
     67 %         specifies that all axes limits and ticks should be fixed
     68 %         while exporting.
     69 %     
     70 %     The default color setting is 'bw'.
     71 %
     72 %   Font Parameters:
     73 %     'FontMode'     one of the strings 'scaled', 'fixed'
     74 %     'FontSize'     a positive scalar
     75 %          in 'scaled' mode multiplies with the font size of each
     76 %          text object to obtain the exported font size
     77 %          in 'fixed' mode specifies the font size of all text
     78 %          objects in points
     79 %     'DefaultFixedFontSize' a positive scalar
     80 %          in 'fixed' mode specified the default font size in
     81 %          points
     82 %     'FontSizeMin' a positive scalar
     83 %          specifies the minimum font size allowed after scaling
     84 %     'FontSizeMax' a positive scalar
     85 %          specifies the maximum font size allowed after scaling
     86 %     'FontEncoding' one of the strings 'latin1', 'adobe'
     87 %          specifies the character encoding of the font
     88 %     'SeparateText' one of 0 or 1
     89 %          specifies that the text objects are stored in separate
     90 %          file as EPS with the base filename having '_t' appended.
     91 %
     92 %     If FontMode is 'scaled' but FontSize is not specified then a
     93 %     scaling factor is computed from the ratio of the size of the
     94 %     exported figure to the size of the actual figure.
     95 %
     96 %     The default 'FontMode' setting is 'scaled'.
     97 %
     98 %   Line Width Parameters:
     99 %     'LineMode'     one of the strings 'scaled', 'fixed'
    100 %     'LineWidth'    a positive scalar
    101 %     'DefaultFixedLineWidth' a positive scalar
    102 %     'LineWidthMin' a positive scalar
    103 %          specifies the minimum line width allowed after scaling
    104 %     'LineWidthMax' a positive scalar
    105 %          specifies the maximum line width allowed after scaling
    106 %     The semantics of 'Line' parameters are exactly the
    107 %     same as the corresponding 'Font' parameters, except that
    108 %     they apply to line widths instead of font sizes.
    109 %
    110 %   Style Map Parameter:
    111 %     'LineStyleMap'    one of [], 'bw', or a function name or handle
    112 %          specifies how to map line colors to styles. An empty
    113 %          style map means styles are not changed. The style map
    114 %          'bw' is a built-in mapping that maps lines with the same
    115 %          color to the same style and otherwise cycles through the
    116 %          available styles. A user-specified map is a function
    117 %          that takes as input a cell array of line objects and
    118 %          outputs a cell array of line style strings. The default
    119 %          map is [].
    120 %      
    121 %   Examples:
    122 %     exportfig(gcf,'fig1.eps','height',3);
    123 %       Exports the current figure to the file named 'fig1.eps' with
    124 %       a height of 3 inches (assuming the figure's PaperUnits is 
    125 %       inches) and an aspect ratio the same as the figure's aspect
    126 %       ratio on screen.
    127 %
    128 %     opts = struct('FontMode','fixed','FontSize',10,'height',3);
    129 %     exportfig(gcf, 'fig2.eps', opts, 'height', 5);
    130 %       Exports the current figure to 'fig2.eps' with all
    131 %       text in 10 point fonts and with height 5 inches.
    132 %
    133 %   See also PREVIEWFIG, APPLYTOFIG, RESTOREFIG, PRINT.
    134 
    135 %  Copyright 2000 Ben Hinkle
    136 %  Email bug reports and comments to bhinkle@mathworks.com
    137 
    138 if (nargin < 2)
    139   error('Too few input arguments');
    140 end
    141 
    142 % exportfig(H, filename, [options,] ...)
    143 H = varargin{1};
    144 if ~LocalIsHG(H,'figure')
    145   error('First argument must be a handle to a figure.');
    146 end
    147 filename = varargin{2};
    148 if ~ischar(filename)
    149   error('Second argument must be a string.');
    150 end
    151 paramPairs = {varargin{3:end}};
    152 if nargin > 2
    153   if isstruct(paramPairs{1})
    154     pcell = LocalToCell(paramPairs{1});
    155     paramPairs = {pcell{:}, paramPairs{2:end}};
    156   end
    157 end
    158 verstr = version;
    159 majorver = str2num(verstr(1));
    160 defaults = [];
    161 if majorver > 5
    162   if ispref('exportfig','defaults')
    163     defaults = getpref('exportfig','defaults');
    164   end
    165 elseif exist('getappdata')
    166   defaults = getappdata(0,'exportfigdefaults');
    167 end
    168 if ~isempty(defaults)
    169   dcell = LocalToCell(defaults);
    170   paramPairs = {dcell{:}, paramPairs{:}};
    171 end
    172 
    173 % Do some validity checking on param-value pairs
    174 if (rem(length(paramPairs),2) ~= 0)
    175   error(['Invalid input syntax. Optional parameters and values' ...
    176 	 ' must be in pairs.']);
    177 end
    178 
    179 auto.format = 'eps';
    180 auto.preview = 'none';
    181 auto.width = -1;
    182 auto.height = -1;
    183 auto.color = 'bw';
    184 auto.defaultfontsize=10;
    185 auto.fontsize = -1;
    186 auto.fontmode='scaled';
    187 auto.fontmin = 8;
    188 auto.fontmax = 60;
    189 auto.defaultlinewidth = 1.0;
    190 auto.linewidth = -1;
    191 auto.linemode=[];
    192 auto.linemin = 0.5;
    193 auto.linemax = 100;
    194 auto.fontencoding = 'latin1';
    195 auto.renderer = [];
    196 auto.resolution = [];
    197 auto.stylemap = [];
    198 auto.applystyle = 0;
    199 auto.refobj = -1;
    200 auto.bounds = 'tight';
    201 explicitbounds = 0;
    202 auto.lockaxes = 1;
    203 auto.separatetext = 0;
    204 opts = auto;
    205 
    206 % Process param-value pairs
    207 args = {};
    208 for k = 1:2:length(paramPairs)
    209   param = lower(paramPairs{k});
    210   if ~ischar(param)
    211     error('Optional parameter names must be strings');
    212   end
    213   value = paramPairs{k+1};
    214   
    215   switch (param)
    216    case 'format'
    217     opts.format = LocalCheckAuto(lower(value),auto.format);
    218     if strcmp(opts.format,'preview')
    219       error(['Format ''preview'' no longer supported. Use PREVIEWFIG' ...
    220 	     ' instead.']);
    221     end
    222    case 'preview'
    223     opts.preview = LocalCheckAuto(lower(value),auto.preview);
    224     if ~strcmp(opts.preview,{'none','tiff'})
    225       error('Preview must be ''none'' or ''tiff''.');
    226     end
    227    case 'width'
    228     opts.width = LocalToNum(value, auto.width);
    229     if ~ischar(value) | ~strcmp(value,'auto')
    230       if ~LocalIsPositiveScalar(opts.width)
    231 	error('Width must be a numeric scalar > 0');
    232       end
    233     end
    234    case 'height'
    235     opts.height = LocalToNum(value, auto.height);
    236     if ~ischar(value) | ~strcmp(value,'auto')
    237       if(~LocalIsPositiveScalar(opts.height))
    238 	error('Height must be a numeric scalar > 0');
    239       end
    240     end
    241    case 'color'
    242     opts.color = LocalCheckAuto(lower(value),auto.color);
    243     if ~strcmp(opts.color,{'bw','gray','rgb','cmyk'})
    244       error('Color must be ''bw'', ''gray'',''rgb'' or ''cmyk''.');
    245     end
    246    case 'fontmode'
    247     opts.fontmode = LocalCheckAuto(lower(value),auto.fontmode);
    248     if ~strcmp(opts.fontmode,{'scaled','fixed'})
    249       error('FontMode must be ''scaled'' or ''fixed''.');
    250     end
    251    case 'fontsize'
    252     opts.fontsize = LocalToNum(value,auto.fontsize);
    253     if ~ischar(value) | ~strcmp(value,'auto')
    254       if ~LocalIsPositiveScalar(opts.fontsize)
    255 	error('FontSize must be a numeric scalar > 0');
    256       end
    257     end
    258    case 'defaultfixedfontsize'
    259     opts.defaultfontsize = LocalToNum(value,auto.defaultfontsize);
    260     if ~ischar(value) | ~strcmp(value,'auto')
    261       if ~LocalIsPositiveScalar(opts.defaultfontsize)
    262 	error('DefaultFixedFontSize must be a numeric scalar > 0');
    263       end
    264     end
    265    case 'fontsizemin'
    266     opts.fontmin = LocalToNum(value,auto.fontmin);
    267     if ~ischar(value) | ~strcmp(value,'auto')
    268       if ~LocalIsPositiveScalar(opts.fontmin)
    269 	error('FontSizeMin must be a numeric scalar > 0');
    270       end
    271     end
    272    case 'fontsizemax'
    273     opts.fontmax = LocalToNum(value,auto.fontmax);
    274     if ~ischar(value) | ~strcmp(value,'auto')
    275       if ~LocalIsPositiveScalar(opts.fontmax)
    276 	error('FontSizeMax must be a numeric scalar > 0');
    277       end
    278     end
    279    case 'fontencoding'
    280     opts.fontencoding = LocalCheckAuto(lower(value),auto.fontencoding);
    281     if ~strcmp(opts.fontencoding,{'latin1','adobe'})
    282       error('FontEncoding must be ''latin1'' or ''adobe''.');
    283     end
    284    case 'linemode'
    285     opts.linemode = LocalCheckAuto(lower(value),auto.linemode);
    286     if ~strcmp(opts.linemode,{'scaled','fixed'})
    287       error('LineMode must be ''scaled'' or ''fixed''.');
    288     end
    289    case 'linewidth'
    290     opts.linewidth = LocalToNum(value,auto.linewidth);
    291     if ~ischar(value) | ~strcmp(value,'auto')
    292       if ~LocalIsPositiveScalar(opts.linewidth)
    293 	error('LineWidth must be a numeric scalar > 0');
    294       end
    295     end
    296    case 'defaultfixedlinewidth'
    297     opts.defaultlinewidth = LocalToNum(value,auto.defaultlinewidth);
    298     if ~ischar(value) | ~strcmp(value,'auto')
    299       if ~LocalIsPositiveScalar(opts.defaultlinewidth)
    300 	error(['DefaultFixedLineWidth must be a numeric scalar >' ...
    301 	       ' 0']);
    302       end
    303     end
    304    case 'linewidthmin'
    305     opts.linemin = LocalToNum(value,auto.linemin);
    306     if ~ischar(value) | ~strcmp(value,'auto')
    307       if ~LocalIsPositiveScalar(opts.linemin)
    308 	error('LineWidthMin must be a numeric scalar > 0');
    309       end
    310     end
    311    case 'linewidthmax'
    312     opts.linemax = LocalToNum(value,auto.linemax);
    313     if ~ischar(value) | ~strcmp(value,'auto')
    314       if ~LocalIsPositiveScalar(opts.linemax)
    315 	error('LineWidthMax must be a numeric scalar > 0');
    316       end
    317     end
    318    case 'linestylemap'
    319     opts.stylemap = LocalCheckAuto(value,auto.stylemap);
    320    case 'renderer'
    321     opts.renderer = LocalCheckAuto(lower(value),auto.renderer);
    322     if ~ischar(value) | ~strcmp(value,'auto')
    323       if ~strcmp(opts.renderer,{'painters','zbuffer','opengl'})
    324 	error(['Renderer must be ''painters'', ''zbuffer'' or' ...
    325 	       ' ''opengl''.']);
    326       end
    327     end
    328    case 'resolution'
    329     opts.resolution = LocalToNum(value,auto.resolution);
    330     if ~ischar(value) | ~strcmp(value,'auto')
    331       if ~(isnumeric(value) & (prod(size(value)) == 1) & (value >= 0));
    332 	error('Resolution must be a numeric scalar >= 0');
    333       end
    334     end
    335    case 'applystyle' % means to apply the options and not export
    336     opts.applystyle = 1;
    337    case 'reference'
    338     if ischar(value)
    339       if strcmp(value,'auto')
    340 	opts.refobj = auto.refobj;
    341       else
    342 	opts.refobj = eval(value);
    343       end
    344     else
    345       opts.refobj = value;
    346     end
    347     if ~LocalIsHG(opts.refobj,'axes')
    348       error('Reference object must evaluate to an axes handle.');
    349     end
    350    case 'bounds'
    351     opts.bounds = LocalCheckAuto(lower(value),auto.bounds);
    352     explicitbounds = 1;
    353     if ~strcmp(opts.bounds,{'tight','loose'})
    354       error('Bounds must be ''tight'' or ''loose''.');
    355     end
    356    case 'lockaxes'
    357     opts.lockaxes = LocalToNum(value,auto.lockaxes);
    358    case 'separatetext'
    359     opts.separatetext = LocalToNum(value,auto.separatetext);
    360    otherwise
    361     error(['Unrecognized option ' param '.']);
    362   end
    363 end
    364 
    365 % make sure figure is up-to-date
    366 drawnow;
    367 
    368 allLines  = findall(H, 'type', 'line');
    369 allText   = findall(H, 'type', 'text');
    370 allAxes   = findall(H, 'type', 'axes');
    371 allImages = findall(H, 'type', 'image');
    372 allLights = findall(H, 'type', 'light');
    373 allPatch  = findall(H, 'type', 'patch');
    374 allSurf   = findall(H, 'type', 'surface');
    375 allRect   = findall(H, 'type', 'rectangle');
    376 allFont   = [allText; allAxes];
    377 allColor  = [allLines; allText; allAxes; allLights];
    378 allMarker = [allLines; allPatch; allSurf];
    379 allEdge   = [allPatch; allSurf];
    380 allCData  = [allImages; allPatch; allSurf];
    381 
    382 old.objs = {};
    383 old.prop = {};
    384 old.values = {};
    385 
    386 % Process format
    387 if strncmp(opts.format,'eps',3) & ~strcmp(opts.preview,'none')
    388   args = {args{:}, ['-' opts.preview]};
    389 end
    390 
    391 hadError = 0;
    392 oldwarn = warning;
    393 try
    394 
    395   % lock axes limits, ticks and labels if requested
    396   if opts.lockaxes
    397     old = LocalManualAxesMode(old, allAxes, 'TickMode');
    398     old = LocalManualAxesMode(old, allAxes, 'TickLabelMode');
    399     old = LocalManualAxesMode(old, allAxes, 'LimMode');
    400   end  
    401 
    402   % Process size parameters
    403   figurePaperUnits = get(H, 'PaperUnits');
    404   oldFigureUnits = get(H, 'Units');
    405   oldFigPos = get(H,'Position');
    406   set(H, 'Units', figurePaperUnits);
    407   figPos = get(H,'Position');
    408   refsize = figPos(3:4);
    409   if opts.refobj ~= -1
    410     oldUnits = get(opts.refobj, 'Units');
    411     set(opts.refobj, 'Units', figurePaperUnits);
    412     r = get(opts.refobj, 'Position');
    413     refsize = r(3:4);
    414     set(opts.refobj, 'Units', oldUnits);
    415   end
    416   aspectRatio = refsize(1)/refsize(2);
    417   if (opts.width == -1) & (opts.height == -1)
    418     opts.width = refsize(1);
    419     opts.height = refsize(2);
    420   elseif (opts.width == -1)
    421     opts.width = opts.height * aspectRatio;
    422   elseif (opts.height == -1)
    423     opts.height = opts.width / aspectRatio;
    424   end
    425   wscale = opts.width/refsize(1);
    426   hscale = opts.height/refsize(2);
    427   sizescale = min(wscale,hscale);
    428   old = LocalPushOldData(old,H,'PaperPositionMode', ...
    429 			 get(H,'PaperPositionMode'));
    430   set(H, 'PaperPositionMode', 'auto');
    431   newPos = [figPos(1) figPos(2)+figPos(4)*(1-hscale) ...
    432 	    wscale*figPos(3) hscale*figPos(4)];
    433   set(H, 'Position', newPos);
    434   set(H, 'Units', oldFigureUnits);
    435   
    436   % process line-style map
    437   if ~isempty(opts.stylemap) & ~isempty(allLines)
    438     oldlstyle = LocalGetAsCell(allLines,'LineStyle');
    439     old = LocalPushOldData(old, allLines, {'LineStyle'}, ...
    440 			   oldlstyle);
    441     newlstyle = oldlstyle;
    442     if ischar(opts.stylemap) & strcmpi(opts.stylemap,'bw')
    443       newlstyle = LocalMapColorToStyle(allLines);
    444     else
    445       try
    446 	newlstyle = feval(opts.stylemap,allLines);
    447       catch
    448 	warning(['Skipping stylemap. ' lasterr]);
    449       end
    450     end
    451     set(allLines,{'LineStyle'},newlstyle);
    452   end
    453 
    454   % Process rendering parameters
    455   switch (opts.color)
    456    case {'bw', 'gray'}
    457     if ~strcmp(opts.color,'bw') & strncmp(opts.format,'eps',3)
    458       opts.format = [opts.format 'c'];
    459     end
    460     args = {args{:}, ['-d' opts.format]};
    461     
    462     %compute and set gray colormap
    463     oldcmap = get(H,'Colormap');
    464     newgrays = 0.30*oldcmap(:,1) + 0.59*oldcmap(:,2) + 0.11*oldcmap(:,3);
    465     newcmap = [newgrays newgrays newgrays];
    466     old = LocalPushOldData(old, H, 'Colormap', oldcmap);
    467     set(H, 'Colormap', newcmap);
    468 
    469     %compute and set ColorSpec and CData properties
    470     old = LocalUpdateColors(allColor, 'color', old);
    471     old = LocalUpdateColors(allAxes, 'xcolor', old);
    472     old = LocalUpdateColors(allAxes, 'ycolor', old);
    473     old = LocalUpdateColors(allAxes, 'zcolor', old);
    474     old = LocalUpdateColors(allMarker, 'MarkerEdgeColor', old);
    475     old = LocalUpdateColors(allMarker, 'MarkerFaceColor', old);
    476     old = LocalUpdateColors(allEdge, 'EdgeColor', old);
    477     old = LocalUpdateColors(allEdge, 'FaceColor', old);
    478     old = LocalUpdateColors(allCData, 'CData', old);
    479     
    480    case {'rgb','cmyk'}
    481     if strncmp(opts.format,'eps',3)
    482       opts.format = [opts.format 'c'];
    483       args = {args{:}, ['-d' opts.format]};
    484       if strcmp(opts.color,'cmyk')
    485 	args = {args{:}, '-cmyk'};
    486       end
    487     else
    488       args = {args{:}, ['-d' opts.format]};
    489     end
    490    otherwise
    491     error('Invalid Color parameter');
    492   end
    493   if (~isempty(opts.renderer))
    494     args = {args{:}, ['-' opts.renderer]};
    495   end
    496   if (~isempty(opts.resolution)) | ~strncmp(opts.format,'eps',3)
    497     if isempty(opts.resolution)
    498       opts.resolution = 0;
    499     end
    500     args = {args{:}, ['-r' int2str(opts.resolution)]};
    501   end
    502 
    503   % Process font parameters
    504   if ~isempty(opts.fontmode)
    505     oldfonts = LocalGetAsCell(allFont,'FontSize');
    506     oldfontunits = LocalGetAsCell(allFont,'FontUnits');
    507     set(allFont,'FontUnits','points');
    508     switch (opts.fontmode)
    509      case 'fixed'
    510       if (opts.fontsize == -1)
    511 	set(allFont,'FontSize',opts.defaultfontsize);
    512       else
    513 	set(allFont,'FontSize',opts.fontsize);
    514       end
    515      case 'scaled'
    516       if (opts.fontsize == -1)
    517 	scale = sizescale;
    518       else
    519 	scale = opts.fontsize;
    520       end
    521       newfonts = LocalScale(oldfonts,scale,opts.fontmin,opts.fontmax);
    522       set(allFont,{'FontSize'},newfonts);
    523      otherwise
    524       error('Invalid FontMode parameter');
    525     end
    526     old = LocalPushOldData(old, allFont, {'FontSize'}, oldfonts);
    527     old = LocalPushOldData(old, allFont, {'FontUnits'}, oldfontunits);
    528   end
    529   if strcmp(opts.fontencoding,'adobe') & strncmp(opts.format,'eps',3)
    530     args = {args{:}, '-adobecset'};
    531   end
    532 
    533   % Process line parameters
    534   if ~isempty(opts.linemode)
    535     oldlines = LocalGetAsCell(allMarker,'LineWidth');
    536     old = LocalPushOldData(old, allMarker, {'LineWidth'}, oldlines);
    537     switch (opts.linemode)
    538      case 'fixed'
    539       if (opts.linewidth == -1)
    540 	set(allMarker,'LineWidth',opts.defaultlinewidth);
    541       else
    542 	set(allMarker,'LineWidth',opts.linewidth);
    543       end
    544      case 'scaled'
    545       if (opts.linewidth == -1)
    546 	scale = sizescale;
    547       else
    548 	scale = opts.linewidth;
    549       end
    550       newlines = LocalScale(oldlines, scale, opts.linemin, opts.linemax);
    551       set(allMarker,{'LineWidth'},newlines);
    552     end
    553   end
    554 
    555   % adjust figure bounds to surround axes
    556   if strcmp(opts.bounds,'tight')
    557     if (~strncmp(opts.format,'eps',3) & LocalHas3DPlot(allAxes)) | ...
    558 	  (strncmp(opts.format,'eps',3) & opts.separatetext)
    559       if (explicitbounds == 1)
    560 	warning(['Cannot compute ''tight'' bounds. Using ''loose''' ...
    561 		 ' bounds.']);
    562       end
    563       opts.bounds = 'loose';
    564     end
    565   end
    566   warning('off');
    567   if ~isempty(allAxes)
    568     if strncmp(opts.format,'eps',3)
    569       if strcmp(opts.bounds,'loose')
    570 	args = {args{:}, '-loose'};
    571       end
    572       old = LocalPushOldData(old,H,'Position', oldFigPos);
    573     elseif strcmp(opts.bounds,'tight')
    574       oldaunits = LocalGetAsCell(allAxes,'Units');
    575       oldapos = LocalGetAsCell(allAxes,'Position');
    576       oldtunits = LocalGetAsCell(allText,'units');
    577       oldtpos = LocalGetAsCell(allText,'Position');
    578       set(allAxes,'units','points');
    579       apos = LocalGetAsCell(allAxes,'Position');
    580       oldunits = get(H,'Units');
    581       set(H,'units','points');
    582       origfr = get(H,'position');
    583       fr = [];
    584       for k=1:length(allAxes)
    585 	if ~strcmpi(get(allAxes(k),'Tag'),'legend')
    586 	  axesR = apos{k};
    587 	  r = LocalAxesTightBoundingBox(axesR, allAxes(k));
    588 	  r(1:2) = r(1:2) + axesR(1:2);
    589 	  fr = LocalUnionRect(fr,r);
    590 	end
    591       end
    592       if isempty(fr)
    593 	fr = [0 0 origfr(3:4)];
    594       end
    595       for k=1:length(allAxes)
    596 	ax = allAxes(k);
    597 	r = apos{k};
    598 	r(1:2) = r(1:2) - fr(1:2);
    599 	set(ax,'Position',r);
    600       end
    601       old = LocalPushOldData(old, allAxes, {'Position'}, oldapos);
    602       old = LocalPushOldData(old, allText, {'Position'}, oldtpos);
    603       old = LocalPushOldData(old, allText, {'Units'}, oldtunits);
    604       old = LocalPushOldData(old, allAxes, {'Units'}, oldaunits);
    605       old = LocalPushOldData(old, H, 'Position', oldFigPos);
    606       old = LocalPushOldData(old, H, 'Units', oldFigureUnits);
    607       r = [origfr(1) origfr(2)+origfr(4)-fr(4) fr(3:4)];
    608       set(H,'Position',r);
    609     else
    610       args = {args{:}, '-loose'};
    611       old = LocalPushOldData(old,H,'Position', oldFigPos);
    612     end
    613   end
    614   
    615   % Process text in a separate file if needed
    616   if opts.separatetext & ~opts.applystyle
    617     % First hide all text and export
    618     oldtvis = LocalGetAsCell(allText,'visible');
    619     set(allText,'visible','off');
    620     oldax = LocalGetAsCell(allAxes,'XTickLabel',1);
    621     olday = LocalGetAsCell(allAxes,'YTickLabel',1);
    622     oldaz = LocalGetAsCell(allAxes,'ZTickLabel',1);
    623     null = cell(length(oldax),1);
    624     [null{:}] = deal([]);
    625     set(allAxes,{'XTickLabel'},null);
    626     set(allAxes,{'YTickLabel'},null);
    627     set(allAxes,{'ZTickLabel'},null);
    628     print(H, filename, args{:});
    629     set(allText,{'Visible'},oldtvis);
    630     set(allAxes,{'XTickLabel'},oldax);
    631     set(allAxes,{'YTickLabel'},olday);
    632     set(allAxes,{'ZTickLabel'},oldaz);
    633     % Now hide all non-text and export as eps in painters
    634     [path, name, ext] = fileparts(filename);
    635     tfile = fullfile(path,[name '_t.eps']);
    636     tfile2 = fullfile(path,[name '_t2.eps']);
    637     foundRenderer = 0;
    638     for k=1:length(args)
    639       if strncmp('-d',args{k},2)
    640 	args{k} = '-deps';
    641       elseif strncmp('-zbuffer',args{k},8) | ...
    642 	    strncmp('-opengl', args{k},6)
    643 	args{k} = '-painters';
    644 	foundRenderer = 1;
    645       end
    646     end
    647     if ~foundRenderer
    648       args = {args{:}, '-painters'};
    649     end
    650     allNonText = [allLines; allLights; allPatch; ...
    651 		  allImages; allSurf; allRect];
    652     oldvis = LocalGetAsCell(allNonText,'visible');
    653     oldc = LocalGetAsCell(allAxes,'color');
    654     oldaxg = LocalGetAsCell(allAxes,'XGrid');
    655     oldayg = LocalGetAsCell(allAxes,'YGrid');
    656     oldazg = LocalGetAsCell(allAxes,'ZGrid');
    657     [null{:}] = deal('off');
    658     set(allAxes,{'XGrid'},null);
    659     set(allAxes,{'YGrid'},null);
    660     set(allAxes,{'ZGrid'},null);
    661     set(allNonText,'Visible','off');
    662     set(allAxes,'Color','none');
    663     print(H, tfile2, args{:});
    664     set(allNonText,{'Visible'},oldvis);
    665     set(allAxes,{'Color'},oldc);
    666     set(allAxes,{'XGrid'},oldaxg);
    667     set(allAxes,{'YGrid'},oldayg);
    668     set(allAxes,{'ZGrid'},oldazg);
    669     %hack up the postscript file
    670     fid1 = fopen(tfile,'w');
    671     fid2 = fopen(tfile2,'r');
    672     line = fgetl(fid2);
    673     while ischar(line)
    674       if strncmp(line,'%%Title',7)
    675 	fprintf(fid1,'%s\n',['%%Title: ', tfile]);
    676       elseif (length(line) < 3) 
    677 	fprintf(fid1,'%s\n',line);
    678       elseif ~strcmp(line(end-2:end),' PR') & ...
    679 	    ~strcmp(line(end-1:end),' L')
    680 	fprintf(fid1,'%s\n',line);
    681       end
    682       line = fgetl(fid2);
    683     end
    684     fclose(fid1);
    685     fclose(fid2);
    686     delete(tfile2);
    687     
    688   elseif ~opts.applystyle
    689     drawnow;
    690     print(H, filename, args{:});
    691   end
    692   warning(oldwarn);
    693   
    694 catch
    695   warning(oldwarn);
    696   hadError = 1;
    697 end
    698 
    699 % Restore figure settings
    700 if opts.applystyle
    701   varargout{1} = old;
    702 else
    703   for n=1:length(old.objs)
    704     if ~iscell(old.values{n}) & iscell(old.prop{n})
    705       old.values{n} = {old.values{n}};
    706     end
    707     set(old.objs{n}, old.prop{n}, old.values{n});
    708   end
    709 end
    710 
    711 if hadError
    712   error(deblank(lasterr));
    713 end
    714 
    715 %
    716 %  Local Functions
    717 %
    718 
    719 function outData = LocalPushOldData(inData, objs, prop, values)
    720 outData.objs = {objs, inData.objs{:}};
    721 outData.prop = {prop, inData.prop{:}};
    722 outData.values = {values, inData.values{:}};
    723 
    724 function cellArray = LocalGetAsCell(fig,prop,allowemptycell);
    725 cellArray = get(fig,prop);
    726 if nargin < 3
    727   allowemptycell = 0;
    728 end
    729 if ~iscell(cellArray) & (allowemptycell | ~isempty(cellArray))
    730   cellArray = {cellArray};
    731 end
    732 
    733 function newArray = LocalScale(inArray, scale, minv, maxv)
    734 n = length(inArray);
    735 newArray = cell(n,1);
    736 for k=1:n
    737   newArray{k} = min(maxv,max(minv,scale*inArray{k}(1)));
    738 end
    739 
    740 function gray = LocalMapToGray1(color)
    741 gray = color;
    742 if ischar(color)
    743   switch color(1)
    744    case 'y'
    745     color = [1 1 0];
    746    case 'm'
    747     color = [1 0 1];
    748    case 'c'
    749     color = [0 1 1];
    750    case 'r'
    751     color = [1 0 0];
    752    case 'g'
    753     color = [0 1 0];
    754    case 'b'
    755     color = [0 0 1];
    756    case 'w'
    757     color = [1 1 1];
    758    case 'k'
    759     color = [0 0 0];
    760   end
    761 end
    762 if ~ischar(color)
    763   gray = 0.30*color(1) + 0.59*color(2) + 0.11*color(3);
    764 end
    765 
    766 function newArray = LocalMapToGray(inArray);
    767 n = length(inArray);
    768 newArray = cell(n,1);
    769 for k=1:n
    770   color = inArray{k};
    771   if ~isempty(color)
    772     color = LocalMapToGray1(color);
    773   end
    774   if isempty(color) | ischar(color)
    775     newArray{k} = color;
    776   else
    777     newArray{k} = [color color color];
    778   end
    779 end
    780 
    781 function newArray = LocalMapColorToStyle(inArray);
    782 inArray = LocalGetAsCell(inArray,'Color');
    783 n = length(inArray);
    784 newArray = cell(n,1);
    785 styles = {'-','--',':','-.'};
    786 uniques = [];
    787 nstyles = length(styles);
    788 for k=1:n
    789   gray = LocalMapToGray1(inArray{k});
    790   if isempty(gray) | ischar(gray) | gray < .05
    791     newArray{k} = '-';
    792   else
    793     if ~isempty(uniques) & any(gray == uniques)
    794       ind = find(gray==uniques);
    795     else
    796       uniques = [uniques gray];
    797       ind = length(uniques);
    798     end
    799     newArray{k} = styles{mod(ind-1,nstyles)+1};
    800   end
    801 end
    802 
    803 function newArray = LocalMapCData(inArray);
    804 n = length(inArray);
    805 newArray = cell(n,1);
    806 for k=1:n
    807   color = inArray{k};
    808   if (ndims(color) == 3) & isa(color,'double')
    809     gray = 0.30*color(:,:,1) + 0.59*color(:,:,2) + 0.11*color(:,:,3);
    810     color(:,:,1) = gray;
    811     color(:,:,2) = gray;
    812     color(:,:,3) = gray;
    813   end
    814   newArray{k} = color;
    815 end
    816 
    817 function outData = LocalUpdateColors(inArray, prop, inData)
    818 value = LocalGetAsCell(inArray,prop);
    819 outData.objs = {inData.objs{:}, inArray};
    820 outData.prop = {inData.prop{:}, {prop}};
    821 outData.values = {inData.values{:}, value};
    822 if (~isempty(value))
    823   if strcmp(prop,'CData') 
    824     value = LocalMapCData(value);
    825   else
    826     value = LocalMapToGray(value);
    827   end
    828   set(inArray,{prop},value);
    829 end
    830 
    831 function bool = LocalIsPositiveScalar(value)
    832 bool = isnumeric(value) & ...
    833        prod(size(value)) == 1 & ...
    834        value > 0;
    835 
    836 function value = LocalToNum(value,auto)
    837 if ischar(value)
    838   if strcmp(value,'auto')
    839     value = auto;
    840   else
    841     value = str2num(value);
    842   end
    843 end
    844 
    845 %convert a struct to {field1,val1,field2,val2,...}
    846 function c = LocalToCell(s)
    847 f = fieldnames(s);
    848 v = struct2cell(s);
    849 opts = cell(2,length(f));
    850 opts(1,:) = f;
    851 opts(2,:) = v;
    852 c = {opts{:}};
    853 
    854 function c = LocalIsHG(obj,hgtype)
    855 c = 0;
    856 if (length(obj) == 1) & ishandle(obj) 
    857   c = strcmp(get(obj,'type'),hgtype);
    858 end
    859 
    860 function c = LocalHas3DPlot(a)
    861 zticks = LocalGetAsCell(a,'ZTickLabel');
    862 c = 0;
    863 for k=1:length(zticks)
    864   if ~isempty(zticks{k})
    865     c = 1;
    866     return;
    867   end
    868 end
    869 
    870 function r = LocalUnionRect(r1,r2)
    871 if isempty(r1)
    872   r = r2;
    873 elseif isempty(r2)
    874   r = r1;
    875 elseif max(r2(3:4)) > 0
    876   left = min(r1(1),r2(1));
    877   bot = min(r1(2),r2(2));
    878   right = max(r1(1)+r1(3),r2(1)+r2(3));
    879   top = max(r1(2)+r1(4),r2(2)+r2(4));
    880   r = [left bot right-left top-bot];
    881 else
    882   r = r1;
    883 end
    884 
    885 function c = LocalLabelsMatchTicks(labs,ticks)
    886 c = 0;
    887 try
    888   t1 = num2str(ticks(1));
    889   n = length(ticks);
    890   tend = num2str(ticks(n));
    891   c = strncmp(labs(1),t1,length(labs(1))) & ...
    892       strncmp(labs(n),tend,length(labs(n)));
    893 end
    894 
    895 function r = LocalAxesTightBoundingBox(axesR, a)
    896 r = [];
    897 atext = findall(a,'type','text','visible','on');
    898 if ~isempty(atext)
    899   set(atext,'units','points');
    900   res=LocalGetAsCell(atext,'extent');
    901   for n=1:length(atext)
    902     r = LocalUnionRect(r,res{n});
    903   end
    904 end
    905 if strcmp(get(a,'visible'),'on')
    906   r = LocalUnionRect(r,[0 0 axesR(3:4)]);
    907   oldunits = get(a,'fontunits');
    908   set(a,'fontunits','points');
    909   label = text(0,0,'','parent',a,...
    910 	       'units','points',...
    911 	       'fontsize',get(a,'fontsize'),...
    912 	       'fontname',get(a,'fontname'),...
    913 	       'fontweight',get(a,'fontweight'),...
    914 	       'fontangle',get(a,'fontangle'),...
    915 	       'visible','off');
    916   fs = get(a,'fontsize');
    917 
    918   % handle y axis tick labels
    919   ry = [0 -fs/2 0 axesR(4)+fs];
    920   ylabs = get(a,'yticklabels');
    921   yticks = get(a,'ytick');
    922   maxw = 0;
    923   if ~isempty(ylabs)
    924     for n=1:size(ylabs,1)
    925       set(label,'string',ylabs(n,:));
    926       ext = get(label,'extent');
    927       maxw = max(maxw,ext(3));
    928     end
    929     if ~LocalLabelsMatchTicks(ylabs,yticks) & ...
    930 	  strcmp(get(a,'xaxislocation'),'bottom')
    931       ry(4) = ry(4) + 1.5*ext(4);
    932     end
    933     if strcmp(get(a,'yaxislocation'),'left')
    934       ry(1) = -(maxw+5);
    935     else
    936       ry(1) = axesR(3);
    937     end
    938     ry(3) = maxw+5;
    939     r = LocalUnionRect(r,ry);
    940   end
    941 
    942   % handle x axis tick labels
    943   rx = [0 0 0 fs+5];
    944   xlabs = get(a,'xticklabels');
    945   xticks = get(a,'xtick');
    946   if ~isempty(xlabs)
    947     if strcmp(get(a,'xaxislocation'),'bottom')
    948       rx(2) = -(fs+5);
    949       if ~LocalLabelsMatchTicks(xlabs,xticks);
    950 	rx(4) = rx(4) + 2*fs;
    951 	rx(2) = rx(2) - 2*fs;
    952       end
    953     else
    954       rx(2) = axesR(4);
    955       % exponent is still below axes
    956       if ~LocalLabelsMatchTicks(xlabs,xticks);
    957 	rx(4) = rx(4) + axesR(4) + 2*fs;
    958 	rx(2) = -2*fs;
    959       end
    960     end
    961     set(label,'string',xlabs(1,:));
    962     ext1 = get(label,'extent');
    963     rx(1) = -ext1(3)/2;
    964     set(label,'string',xlabs(size(xlabs,1),:));
    965     ext2 = get(label,'extent');
    966     rx(3) = axesR(3) + (ext2(3) + ext1(3))/2;
    967     r = LocalUnionRect(r,rx);
    968   end
    969   set(a,'fontunits',oldunits);
    970   delete(label);
    971 end
    972 
    973 function c = LocalManualAxesMode(old, allAxes, base)
    974 xs = ['X' base];
    975 ys = ['Y' base];
    976 zs = ['Z' base];
    977 oldXMode = LocalGetAsCell(allAxes,xs);
    978 oldYMode = LocalGetAsCell(allAxes,ys);
    979 oldZMode = LocalGetAsCell(allAxes,zs);
    980 old = LocalPushOldData(old, allAxes, {xs}, oldXMode);
    981 old = LocalPushOldData(old, allAxes, {ys}, oldYMode);
    982 old = LocalPushOldData(old, allAxes, {zs}, oldZMode);
    983 set(allAxes,xs,'manual');
    984 set(allAxes,ys,'manual');
    985 set(allAxes,zs,'manual');
    986 c = old;
    987 
    988 function val = LocalCheckAuto(val, auto)
    989 if ischar(val) & strcmp(val,'auto')
    990   val = auto;
    991 end