source: issm/oecreview/Archive/20545-21336/ISSM-21314-21315.diff@ 21337

Last change on this file since 21337 was 21337, checked in by Mathieu Morlighem, 8 years ago

CHG: added Archive/20545-21336

File size: 207.4 KB
RevLine 
[21337]1Index: ../trunk-jpl/externalpackages/export_fig/append_pdfs.m
2===================================================================
3--- ../trunk-jpl/externalpackages/export_fig/append_pdfs.m (revision 21314)
4+++ ../trunk-jpl/externalpackages/export_fig/append_pdfs.m (revision 21315)
5@@ -32,17 +32,40 @@
6 % Issue resolved (to best of my ability) 1/6/2011, using the prepress
7 % setting
8
9+% 26/02/15: If temp dir is not writable, use the output folder for temp
10+% files when appending (Javier Paredes); sanity check of inputs
11+
12 function append_pdfs(varargin)
13+
14+if nargin < 2, return; end % sanity check
15+
16 % Are we appending or creating a new file
17 append = exist(varargin{1}, 'file') == 2;
18-if append
19- output = [tempname '.pdf'];
20-else
21+output = [tempname '.pdf'];
22+try
23+ % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
24+ fid = fopen(output,'w');
25+ fwrite(fid,1);
26+ fclose(fid);
27+ delete(output);
28+ isTempDirOk = true;
29+catch
30+ % Temp dir is not writable, so use the output folder
31+ [dummy,fname,fext] = fileparts(output); %#ok<ASGLU>
32+ fpath = fileparts(varargin{1});
33+ output = fullfile(fpath,[fname fext]);
34+ isTempDirOk = false;
35+end
36+if ~append
37 output = varargin{1};
38 varargin = varargin(2:end);
39 end
40 % Create the command file
41-cmdfile = [tempname '.txt'];
42+if isTempDirOk
43+ cmdfile = [tempname '.txt'];
44+else
45+ cmdfile = fullfile(fpath,[fname '.txt']);
46+end
47 fh = fopen(cmdfile, 'w');
48 fprintf(fh, '-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile="%s" -f', output);
49 fprintf(fh, ' "%s"', varargin{:});
50Index: ../trunk-jpl/externalpackages/export_fig/crop_borders.m
51===================================================================
52--- ../trunk-jpl/externalpackages/export_fig/crop_borders.m (revision 21314)
53+++ ../trunk-jpl/externalpackages/export_fig/crop_borders.m (revision 21315)
54@@ -1,81 +1,157 @@
55+function [A, vA, vB, bb_rel] = crop_borders(A, bcol, padding, crop_amounts)
56 %CROP_BORDERS Crop the borders of an image or stack of images
57 %
58-% [B, v] = crop_borders(A, bcol, [padding])
59+% [B, vA, vB, bb_rel] = crop_borders(A, bcol, [padding])
60 %
61 %IN:
62 % A - HxWxCxN stack of images.
63 % bcol - Cx1 background colour vector.
64-% padding - scalar indicating how many pixels padding to have. Default: 0.
65+% padding - scalar indicating how much padding to have in relation to
66+% the cropped-image-size (0<=padding<=1). Default: 0
67+% crop_amounts - 4-element vector of crop amounts: [top,right,bottom,left]
68+% where NaN/Inf indicate auto-cropping, 0 means no cropping,
69+% and any other value mean cropping in pixel amounts.
70 %
71 %OUT:
72 % B - JxKxCxN cropped stack of images.
73-% v - 1x4 vector of start and end indices for first two dimensions, s.t.
74-% B = A(v(1):v(2),v(3):v(4),:,:).
75+% vA - coordinates in A that contain the cropped image
76+% vB - coordinates in B where the cropped version of A is placed
77+% bb_rel - relative bounding box (used for eps-cropping)
78
79-function [A, v] = crop_borders(A, bcol, padding)
80-if nargin < 3
81- padding = 0;
82-end
83-[h, w, c, n] = size(A);
84-if isscalar(bcol)
85- bcol = bcol(ones(c, 1));
86-end
87-bail = false;
88-for l = 1:w
89- for a = 1:c
90- if ~all(col(A(:,l,a,:)) == bcol(a))
91- bail = true;
92- break;
93- end
94+%{
95+% 06/03/15: Improved image cropping thanks to Oscar Hartogensis
96+% 08/06/15: Fixed issue #76: case of transparent figure bgcolor
97+% 21/02/16: Enabled specifying non-automated crop amounts
98+% 04/04/16: Fix per Luiz Carvalho for old Matlab releases
99+% 23/10/16: Fixed issue #175: there used to be a 1px minimal padding in case of crop, now removed
100+%}
101+
102+ if nargin < 3
103+ padding = 0;
104 end
105- if bail
106- break;
107+ if nargin < 4
108+ crop_amounts = nan(1,4); % =auto-cropping
109 end
110-end
111-bcol = A(ceil(end/2),w,:,1);
112-bail = false;
113-for r = w:-1:l
114- for a = 1:c
115- if ~all(col(A(:,r,a,:)) == bcol(a))
116- bail = true;
117- break;
118+ crop_amounts(end+1:4) = NaN; % fill missing values with NaN
119+
120+ [h, w, c, n] = size(A);
121+ if isempty(bcol) % case of transparent bgcolor
122+ bcol = A(ceil(end/2),1,:,1);
123+ end
124+ if isscalar(bcol)
125+ bcol = bcol(ones(c, 1));
126+ end
127+
128+ % Crop margin from left
129+ if ~isfinite(crop_amounts(4))
130+ bail = false;
131+ for l = 1:w
132+ for a = 1:c
133+ if ~all(col(A(:,l,a,:)) == bcol(a))
134+ bail = true;
135+ break;
136+ end
137+ end
138+ if bail
139+ break;
140+ end
141 end
142+ else
143+ l = 1 + abs(crop_amounts(4));
144 end
145- if bail
146- break;
147+
148+ % Crop margin from right
149+ if ~isfinite(crop_amounts(2))
150+ bcol = A(ceil(end/2),w,:,1);
151+ bail = false;
152+ for r = w:-1:l
153+ for a = 1:c
154+ if ~all(col(A(:,r,a,:)) == bcol(a))
155+ bail = true;
156+ break;
157+ end
158+ end
159+ if bail
160+ break;
161+ end
162+ end
163+ else
164+ r = w - abs(crop_amounts(2));
165 end
166-end
167-bcol = A(1,ceil(end/2),:,1);
168-bail = false;
169-for t = 1:h
170- for a = 1:c
171- if ~all(col(A(t,:,a,:)) == bcol(a))
172- bail = true;
173- break;
174+
175+ % Crop margin from top
176+ if ~isfinite(crop_amounts(1))
177+ bcol = A(1,ceil(end/2),:,1);
178+ bail = false;
179+ for t = 1:h
180+ for a = 1:c
181+ if ~all(col(A(t,:,a,:)) == bcol(a))
182+ bail = true;
183+ break;
184+ end
185+ end
186+ if bail
187+ break;
188+ end
189 end
190+ else
191+ t = 1 + abs(crop_amounts(1));
192 end
193- if bail
194- break;
195+
196+ % Crop margin from bottom
197+ bcol = A(h,ceil(end/2),:,1);
198+ if ~isfinite(crop_amounts(3))
199+ bail = false;
200+ for b = h:-1:t
201+ for a = 1:c
202+ if ~all(col(A(b,:,a,:)) == bcol(a))
203+ bail = true;
204+ break;
205+ end
206+ end
207+ if bail
208+ break;
209+ end
210+ end
211+ else
212+ b = h - abs(crop_amounts(3));
213 end
214-end
215-bcol = A(h,ceil(end/2),:,1);
216-bail = false;
217-for b = h:-1:t
218- for a = 1:c
219- if ~all(col(A(b,:,a,:)) == bcol(a))
220- bail = true;
221- break;
222+
223+ if padding == 0 % no padding
224+ % Issue #175: there used to be a 1px minimal padding in case of crop, now removed
225+ %{
226+ if ~isequal([t b l r], [1 h 1 w]) % Check if we're actually croppping
227+ padding = 1; % Leave one boundary pixel to avoid bleeding on resize
228+ bcol(:) = nan; % make the 1px padding transparent
229 end
230+ %}
231+ elseif abs(padding) < 1 % pad value is a relative fraction of image size
232+ padding = sign(padding)*round(mean([b-t r-l])*abs(padding)); % ADJUST PADDING
233+ else % pad value is in units of 1/72" points
234+ padding = round(padding); % fix cases of non-integer pad value
235 end
236- if bail
237- break;
238+
239+ if padding > 0 % extra padding
240+ % Create an empty image, containing the background color, that has the
241+ % cropped image size plus the padded border
242+ B = repmat(bcol,[(b-t)+1+padding*2,(r-l)+1+padding*2,1,n]); % Fix per Luiz Carvalho
243+ % vA - coordinates in A that contain the cropped image
244+ vA = [t b l r];
245+ % vB - coordinates in B where the cropped version of A will be placed
246+ vB = [padding+1, (b-t)+1+padding, padding+1, (r-l)+1+padding];
247+ % Place the original image in the empty image
248+ B(vB(1):vB(2), vB(3):vB(4), :, :) = A(vA(1):vA(2), vA(3):vA(4), :, :);
249+ A = B;
250+ else % extra cropping
251+ vA = [t-padding b+padding l-padding r+padding];
252+ A = A(vA(1):vA(2), vA(3):vA(4), :, :);
253+ vB = [NaN NaN NaN NaN];
254 end
255+
256+ % For EPS cropping, determine the relative BoundingBox - bb_rel
257+ bb_rel = [l-1 h-b-1 r+1 h-t+1]./[w h w h];
258 end
259-% Crop the background, leaving one boundary pixel to avoid bleeding on resize
260-v = [max(t-padding, 1) min(b+padding, h) max(l-padding, 1) min(r+padding, w)];
261-A = A(v(1):v(2),v(3):v(4),:,:);
262-end
263
264 function A = col(A)
265-A = A(:);
266+ A = A(:);
267 end
268Index: ../trunk-jpl/externalpackages/export_fig/using_hg2.m
269===================================================================
270--- ../trunk-jpl/externalpackages/export_fig/using_hg2.m (revision 21314)
271+++ ../trunk-jpl/externalpackages/export_fig/using_hg2.m (revision 21315)
272@@ -1,4 +1,4 @@
273-%USING_HG2 Determine if the HG2 graphics pipeline is used
274+%USING_HG2 Determine if the HG2 graphics engine is used
275 %
276 % tf = using_hg2(fig)
277 %
278@@ -6,13 +6,31 @@
279 % fig - handle to the figure in question.
280 %
281 %OUT:
282-% tf - boolean indicating whether the HG2 graphics pipeline is being used
283+% tf - boolean indicating whether the HG2 graphics engine is being used
284 % (true) or not (false).
285
286+% 19/06/2015 - Suppress warning in R2015b; cache result for improved performance
287+% 06/06/2016 - Fixed issue #156 (bad return value in R2016b)
288+
289 function tf = using_hg2(fig)
290-try
291- tf = ~graphicsversion(fig, 'handlegraphics');
292-catch
293- tf = false;
294+ persistent tf_cached
295+ if isempty(tf_cached)
296+ try
297+ if nargin < 1, fig = figure('visible','off'); end
298+ oldWarn = warning('off','MATLAB:graphicsversion:GraphicsVersionRemoval');
299+ try
300+ % This generates a [supressed] warning in R2015b:
301+ tf = ~graphicsversion(fig, 'handlegraphics');
302+ catch
303+ tf = ~verLessThan('matlab','8.4'); % =R2014b
304+ end
305+ warning(oldWarn);
306+ catch
307+ tf = false;
308+ end
309+ if nargin < 1, delete(fig); end
310+ tf_cached = tf;
311+ else
312+ tf = tf_cached;
313+ end
314 end
315-end
316Index: ../trunk-jpl/externalpackages/export_fig/print2eps.m
317===================================================================
318--- ../trunk-jpl/externalpackages/export_fig/print2eps.m (revision 21314)
319+++ ../trunk-jpl/externalpackages/export_fig/print2eps.m (revision 21315)
320@@ -1,3 +1,4 @@
321+function print2eps(name, fig, export_options, varargin)
322 %PRINT2EPS Prints figures to eps with improved line styles
323 %
324 % Examples:
325@@ -3,13 +4,12 @@
326 % print2eps filename
327 % print2eps(filename, fig_handle)
328-% print2eps(filename, fig_handle, bb_padding)
329-% print2eps(filename, fig_handle, bb_padding, options)
330+% print2eps(filename, fig_handle, export_options)
331+% print2eps(filename, fig_handle, export_options, print_options)
332 %
333 % This function saves a figure as an eps file, with two improvements over
334 % MATLAB's print command. First, it improves the line style, making dashed
335-% lines more like those on screen and giving grid lines their own dotted
336-% style. Secondly, it substitutes original font names back into the eps
337-% file, where these have been changed by MATLAB, for up to 11 different
338-% fonts.
339+% lines more like those on screen and giving grid lines a dotted line style.
340+% Secondly, it substitutes original font names back into the eps file,
341+% where these have been changed by MATLAB, for up to 11 different fonts.
342 %
343 %IN:
344@@ -19,21 +19,29 @@
345 % ".eps" extension is added if not there already. If a path is
346 % not specified, the figure is saved in the current directory.
347 % fig_handle - The handle of the figure to be saved. Default: gcf().
348-% bb_padding - Scalar value of amount of padding to add to border around
349-% the figure, in points. Can be negative as well as
350-% positive. Default: 0.
351-% options - Additional parameter strings to be passed to print.
352+% export_options - array or struct of optional scalar values:
353+% bb_padding - Scalar value of amount of padding to add to border around
354+% the cropped image, in points (if >1) or percent (if <1).
355+% Can be negative as well as positive; Default: 0
356+% crop - Cropping flag. Deafult: 0
357+% fontswap - Whether to swap non-default fonts in figure. Default: true
358+% renderer - Renderer used to generate bounding-box. Default: 'opengl'
359+% crop_amounts - 4-element vector of crop amounts: [top,right,bottom,left]
360+% (available only via the struct alternative)
361+% print_options - Additional parameter strings to be passed to the print command
362
363-% Copyright (C) Oliver Woodford 2008-2014
364+%{
365+% Copyright (C) Oliver Woodford 2008-2014, Yair Altman 2015-
366
367 % The idea of editing the EPS file to change line styles comes from Jiro
368 % Doke's FIXPSLINESTYLE (fex id: 17928)
369 % The idea of changing dash length with line width came from comments on
370 % fex id: 5743, but the implementation is mine :)
371-
372-% 14/11/2011: Fix a MATLAB bug rendering black or white text incorrectly.
373-% Thanks to Mathieu Morlighem for reporting the issue and
374-% obtaining a fix from TMW.
375+%}
376+%{
377+% 14/11/11: Fix a MATLAB bug rendering black or white text incorrectly.
378+% Thanks to Mathieu Morlighem for reporting the issue and
379+% obtaining a fix from TMW.
380 % 08/12/11: Added ability to correct fonts. Several people have requested
381 % this at one time or another, and also pointed me to printeps
382 % (fex id: 7501), so thank you to them. My implementation (which
383@@ -56,158 +64,466 @@
384 % 23/07/13: Bug fix to font swapping. Thanks to George for reporting the
385 % issue.
386 % 13/08/13: Fix MATLAB feature of not exporting white lines correctly.
387-% Thanks to Sebastian Heßlinger for reporting it.
388+% Thanks to Sebastian Hesslinger for reporting it.
389+% 24/02/15: Fix for Matlab R2014b bug (issue #31): LineWidths<0.75 are not
390+% set in the EPS (default line width is used)
391+% 25/02/15: Fixed issue #32: BoundingBox problem caused uncropped EPS/PDF files
392+% 05/03/15: Fixed issue #43: Inability to perform EPS file post-processing
393+% 06/03/15: Improved image padding & cropping thanks to Oscar Hartogensis
394+% 21/03/15: Fixed edge-case of missing handles having a 'FontName' property
395+% 26/03/15: Attempt to fix issue #45: white lines in subplots do not print correctly
396+% 27/03/15: Attempt to fix issue #44: white artifact lines appearing in patch exports
397+% 30/03/15: Fixed issue #52: improved performance on HG2 (R2014b+)
398+% 09/04/15: Comment blocks consolidation and minor code cleanup (no real code change)
399+% 12/04/15: Fixed issue #56: bad cropping
400+% 14/04/15: Workaround for issue #45: lines in image subplots are exported in invalid color
401+% 07/07/15: Added option to avoid font-swapping in EPS/PDF
402+% 07/07/15: Fixed issue #83: use numeric handles in HG1
403+% 22/07/15: Fixed issue #91 (thanks to Carlos Moffat)
404+% 28/09/15: Fixed issue #108 (thanks to JacobD10)
405+% 01/11/15: Fixed issue #112: optional renderer for bounding-box computation (thanks to Jesús Pestana Puerta)
406+% 21/02/16: Enabled specifying non-automated crop amounts
407+% 22/02/16: Better support + backward compatibility for transparency (issue #108)
408+% 10/06/16: Fixed issue #159: text handles get cleared by Matlab in the print() command
409+% 12/06/16: Improved the fix for issue #159 (in the previous commit)
410+% 12/06/16: Fixed issue #158: transparent patch color in PDF/EPS
411+%}
412
413-function print2eps(name, fig, bb_padding, varargin)
414-options = {'-depsc2'};
415-if nargin > 3
416- options = [options varargin];
417-elseif nargin < 3
418- bb_padding = 0;
419- if nargin < 2
420- fig = gcf();
421+ options = {'-loose'};
422+ if nargin > 3
423+ options = [options varargin];
424+ elseif nargin < 3
425+ export_options = 0;
426+ if nargin < 2
427+ fig = gcf();
428+ end
429 end
430-end
431-% Construct the filename
432-if numel(name) < 5 || ~strcmpi(name(end-3:end), '.eps')
433- name = [name '.eps']; % Add the missing extension
434-end
435-% Set paper size
436-old_pos_mode = get(fig, 'PaperPositionMode');
437-old_orientation = get(fig, 'PaperOrientation');
438-set(fig, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait');
439-% Find all the used fonts in the figure
440-font_handles = findall(fig, '-property', 'FontName');
441-fonts = get(font_handles, 'FontName');
442-if ~iscell(fonts)
443- fonts = {fonts};
444-end
445-% Map supported font aliases onto the correct name
446-fontsl = lower(fonts);
447-for a = 1:numel(fonts)
448- f = fontsl{a};
449- f(f==' ') = [];
450- switch f
451- case {'times', 'timesnewroman', 'times-roman'}
452- fontsl{a} = 'times-roman';
453- case {'arial', 'helvetica'}
454- fontsl{a} = 'helvetica';
455- case {'newcenturyschoolbook', 'newcenturyschlbk'}
456- fontsl{a} = 'newcenturyschlbk';
457- otherwise
458+
459+ % Retrieve padding, crop & font-swap values
460+ crop_amounts = nan(1,4); % auto-crop all 4 sides by default
461+ if isstruct(export_options)
462+ try fontswap = export_options.fontswap; catch, fontswap = true; end
463+ try bb_crop = export_options.crop; catch, bb_crop = 0; end
464+ try crop_amounts = export_options.crop_amounts; catch, end
465+ try bb_padding = export_options.bb_padding; catch, bb_padding = 0; end
466+ try renderer = export_options.rendererStr; catch, renderer = 'opengl'; end % fix for issue #110
467+ if renderer(1)~='-', renderer = ['-' renderer]; end
468+ else
469+ if numel(export_options) > 2 % font-swapping
470+ fontswap = export_options(3);
471+ else
472+ fontswap = true;
473+ end
474+ if numel(export_options) > 1 % cropping
475+ bb_crop = export_options(2);
476+ else
477+ bb_crop = 0; % scalar value, so use default bb_crop value of 0
478+ end
479+ if numel(export_options) > 0 % padding
480+ bb_padding = export_options(1);
481+ else
482+ bb_padding = 0;
483+ end
484+ renderer = '-opengl';
485 end
486-end
487-fontslu = unique(fontsl);
488-% Determine the font swap table
489-matlab_fonts = {'Helvetica', 'Times-Roman', 'Palatino', 'Bookman', 'Helvetica-Narrow', 'Symbol', ...
490- 'AvantGarde', 'NewCenturySchlbk', 'Courier', 'ZapfChancery', 'ZapfDingbats'};
491-matlab_fontsl = lower(matlab_fonts);
492-require_swap = find(~ismember(fontslu, matlab_fontsl));
493-unused_fonts = find(~ismember(matlab_fontsl, fontslu));
494-font_swap = cell(3, min(numel(require_swap), numel(unused_fonts)));
495-fonts_new = fonts;
496-for a = 1:size(font_swap, 2)
497- font_swap{1,a} = find(strcmp(fontslu{require_swap(a)}, fontsl));
498- font_swap{2,a} = matlab_fonts{unused_fonts(a)};
499- font_swap{3,a} = fonts{font_swap{1,a}(1)};
500- fonts_new(font_swap{1,a}) = {font_swap{2,a}};
501-end
502-% Swap the fonts
503-if ~isempty(font_swap)
504- fonts_size = get(font_handles, 'FontSize');
505- if iscell(fonts_size)
506- fonts_size = cell2mat(fonts_size);
507+
508+ % Construct the filename
509+ if numel(name) < 5 || ~strcmpi(name(end-3:end), '.eps')
510+ name = [name '.eps']; % Add the missing extension
511 end
512- M = false(size(font_handles));
513- % Loop because some changes may not stick first time, due to listeners
514- c = 0;
515- update = zeros(1000, 1);
516- for b = 1:10 % Limit number of loops to avoid infinite loop case
517- for a = 1:numel(M)
518- M(a) = ~isequal(get(font_handles(a), 'FontName'), fonts_new{a}) || ~isequal(get(font_handles(a), 'FontSize'), fonts_size(a));
519- if M(a)
520- set(font_handles(a), 'FontName', fonts_new{a}, 'FontSize', fonts_size(a));
521- c = c + 1;
522- update(c) = a;
523+
524+ % Set paper size
525+ old_pos_mode = get(fig, 'PaperPositionMode');
526+ old_orientation = get(fig, 'PaperOrientation');
527+ set(fig, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait');
528+
529+ % Find all the used fonts in the figure
530+ font_handles = findall(fig, '-property', 'FontName');
531+ fonts = get(font_handles, 'FontName');
532+ if isempty(fonts)
533+ fonts = {};
534+ elseif ~iscell(fonts)
535+ fonts = {fonts};
536+ end
537+
538+ % Map supported font aliases onto the correct name
539+ fontsl = lower(fonts);
540+ for a = 1:numel(fonts)
541+ f = fontsl{a};
542+ f(f==' ') = [];
543+ switch f
544+ case {'times', 'timesnewroman', 'times-roman'}
545+ fontsl{a} = 'times-roman';
546+ case {'arial', 'helvetica'}
547+ fontsl{a} = 'helvetica';
548+ case {'newcenturyschoolbook', 'newcenturyschlbk'}
549+ fontsl{a} = 'newcenturyschlbk';
550+ otherwise
551+ end
552+ end
553+ fontslu = unique(fontsl);
554+
555+ % Determine the font swap table
556+ if fontswap
557+ matlab_fonts = {'Helvetica', 'Times-Roman', 'Palatino', 'Bookman', 'Helvetica-Narrow', 'Symbol', ...
558+ 'AvantGarde', 'NewCenturySchlbk', 'Courier', 'ZapfChancery', 'ZapfDingbats'};
559+ matlab_fontsl = lower(matlab_fonts);
560+ require_swap = find(~ismember(fontslu, matlab_fontsl));
561+ unused_fonts = find(~ismember(matlab_fontsl, fontslu));
562+ font_swap = cell(3, min(numel(require_swap), numel(unused_fonts)));
563+ fonts_new = fonts;
564+ for a = 1:size(font_swap, 2)
565+ font_swap{1,a} = find(strcmp(fontslu{require_swap(a)}, fontsl));
566+ font_swap{2,a} = matlab_fonts{unused_fonts(a)};
567+ font_swap{3,a} = fonts{font_swap{1,a}(1)};
568+ fonts_new(font_swap{1,a}) = font_swap(2,a);
569+ end
570+ else
571+ font_swap = [];
572+ end
573+
574+ % Swap the fonts
575+ if ~isempty(font_swap)
576+ fonts_size = get(font_handles, 'FontSize');
577+ if iscell(fonts_size)
578+ fonts_size = cell2mat(fonts_size);
579+ end
580+ M = false(size(font_handles));
581+
582+ % Loop because some changes may not stick first time, due to listeners
583+ c = 0;
584+ update = zeros(1000, 1);
585+ for b = 1:10 % Limit number of loops to avoid infinite loop case
586+ for a = 1:numel(M)
587+ M(a) = ~isequal(get(font_handles(a), 'FontName'), fonts_new{a}) || ~isequal(get(font_handles(a), 'FontSize'), fonts_size(a));
588+ if M(a)
589+ set(font_handles(a), 'FontName', fonts_new{a}, 'FontSize', fonts_size(a));
590+ c = c + 1;
591+ update(c) = a;
592+ end
593 end
594+ if ~any(M)
595+ break;
596+ end
597 end
598- if ~any(M)
599- break;
600+
601+ % Compute the order to revert fonts later, without the need of a loop
602+ [update, M] = unique(update(1:c));
603+ [M, M] = sort(M);
604+ update = reshape(update(M), 1, []);
605+ end
606+
607+ % MATLAB bug fix - black and white text can come out inverted sometimes
608+ % Find the white and black text
609+ black_text_handles = findall(fig, 'Type', 'text', 'Color', [0 0 0]);
610+ white_text_handles = findall(fig, 'Type', 'text', 'Color', [1 1 1]);
611+ % Set the font colors slightly off their correct values
612+ set(black_text_handles, 'Color', [0 0 0] + eps);
613+ set(white_text_handles, 'Color', [1 1 1] - eps);
614+
615+ % MATLAB bug fix - white lines can come out funny sometimes
616+ % Find the white lines
617+ white_line_handles = findall(fig, 'Type', 'line', 'Color', [1 1 1]);
618+ % Set the line color slightly off white
619+ set(white_line_handles, 'Color', [1 1 1] - 0.00001);
620+
621+ % Workaround for issue #45: lines in image subplots are exported in invalid color
622+ % In this case the -depsc driver solves the problem, but then all the other workarounds
623+ % below (for all the other issues) will fail, so it's better to let the user decide by
624+ % just issuing a warning and accepting the '-depsc' input parameter
625+ epsLevel2 = ~any(strcmpi(options,'-depsc'));
626+ if epsLevel2
627+ % Use -depsc2 (EPS color level-2) if -depsc (EPS color level-3) was not specifically requested
628+ options{end+1} = '-depsc2';
629+ % Issue a warning if multiple images & lines were found in the figure, and HG1 with painters renderer is used
630+ isPainters = any(strcmpi(options,'-painters'));
631+ if isPainters && ~using_hg2 && numel(findall(fig,'Type','image'))>1 && ~isempty(findall(fig,'Type','line'))
632+ warning('YMA:export_fig:issue45', ...
633+ ['Multiple images & lines detected. In such cases, the lines might \n' ...
634+ 'appear with an invalid color due to an internal MATLAB bug (fixed in R2014b). \n' ...
635+ 'Possible workaround: add a ''-depsc'' or ''-opengl'' parameter to the export_fig command.']);
636 end
637 end
638- % Compute the order to revert fonts later, without the need of a loop
639- [update, M] = unique(update(1:c));
640- [M, M] = sort(M);
641- update = reshape(update(M), 1, []);
642-end
643-% MATLAB bug fix - black and white text can come out inverted sometimes
644-% Find the white and black text
645-white_text_handles = findobj(fig, 'Type', 'text');
646-M = get(white_text_handles, 'Color');
647-if iscell(M)
648- M = cell2mat(M);
649-end
650-M = sum(M, 2);
651-black_text_handles = white_text_handles(M == 0);
652-white_text_handles = white_text_handles(M == 3);
653-% Set the font colors slightly off their correct values
654-set(black_text_handles, 'Color', [0 0 0] + eps);
655-set(white_text_handles, 'Color', [1 1 1] - eps);
656-% MATLAB bug fix - white lines can come out funny sometimes
657-% Find the white lines
658-white_line_handles = findobj(fig, 'Type', 'line');
659-M = get(white_line_handles, 'Color');
660-if iscell(M)
661- M = cell2mat(M);
662-end
663-white_line_handles = white_line_handles(sum(M, 2) == 3);
664-% Set the line color slightly off white
665-set(white_line_handles, 'Color', [1 1 1] - 0.00001);
666-% Print to eps file
667-print(fig, options{:}, name);
668-% Reset the font and line colors
669-set(black_text_handles, 'Color', [0 0 0]);
670-set(white_text_handles, 'Color', [1 1 1]);
671-set(white_line_handles, 'Color', [1 1 1]);
672-% Reset paper size
673-set(fig, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation);
674-% Reset the font names in the figure
675-if ~isempty(font_swap)
676- for a = update
677- set(font_handles(a), 'FontName', fonts{a}, 'FontSize', fonts_size(a));
678+
679+ % Fix issue #83: use numeric handles in HG1
680+ if ~using_hg2(fig), fig = double(fig); end
681+
682+ % Workaround for when transparency is lost through conversion fig>EPS>PDF (issue #108)
683+ % Replace transparent patch RGB values with an ID value (rare chance that ID color is being used already)
684+ if using_hg2
685+ origAlphaColors = eps_maintainAlpha(fig);
686 end
687-end
688-% Do post-processing on the eps file
689-try
690- fstrm = read_write_entire_textfile(name);
691-catch
692- warning('Loading EPS file failed, so unable to perform post-processing. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.');
693- return
694-end
695-% Replace the font names
696-if ~isempty(font_swap)
697- for a = 1:size(font_swap, 2)
698- %fstrm = regexprep(fstrm, [font_swap{1,a} '-?[a-zA-Z]*\>'], font_swap{3,a}(~isspace(font_swap{3,a})));
699- fstrm = regexprep(fstrm, font_swap{2,a}, font_swap{3,a}(~isspace(font_swap{3,a})));
700+
701+ % Print to eps file
702+ print(fig, options{:}, name);
703+
704+ % Do post-processing on the eps file
705+ try
706+ % Read the EPS file into memory
707+ fstrm = read_write_entire_textfile(name);
708+ catch
709+ fstrm = '';
710 end
711+
712+ % Restore colors for transparent patches/lines and apply the
713+ % setopacityalpha setting in the EPS file (issue #108)
714+ if using_hg2
715+ [~,fstrm,foundFlags] = eps_maintainAlpha(fig, fstrm, origAlphaColors);
716+
717+ % If some of the transparencies were not found in the EPS file, then rerun the
718+ % export with only the found transparencies modified (backward compatibility)
719+ if ~isempty(fstrm) && ~all(foundFlags)
720+ foundIdx = find(foundFlags);
721+ for objIdx = 1 : sum(foundFlags)
722+ colorsIdx = foundIdx(objIdx);
723+ colorsData = origAlphaColors{colorsIdx};
724+ hObj = colorsData{1};
725+ propName = colorsData{2};
726+ newColor = colorsData{4};
727+ hObj.(propName).ColorData = newColor;
728+ end
729+ delete(name);
730+ print(fig, options{:}, name);
731+ fstrm = read_write_entire_textfile(name);
732+ [~,fstrm] = eps_maintainAlpha(fig, fstrm, origAlphaColors(foundFlags));
733+ end
734+ end
735+
736+ % Fix for Matlab R2014b bug (issue #31): LineWidths<0.75 are not set in the EPS (default line width is used)
737+ try
738+ if ~isempty(fstrm) && using_hg2(fig)
739+ % Convert miter joins to line joins
740+ %fstrm = regexprep(fstrm, '\n10.0 ML\n', '\n1 LJ\n');
741+ % This is faster (the original regexprep could take many seconds when the axes contains many lines):
742+ fstrm = strrep(fstrm, sprintf('\n10.0 ML\n'), sprintf('\n1 LJ\n'));
743+
744+ % In HG2, grid lines and axes Ruler Axles have a default LineWidth of 0.5 => replace en-bulk (assume that 1.0 LineWidth = 1.333 LW)
745+ % hAxes=gca; hAxes.YGridHandle.LineWidth, hAxes.YRuler.Axle.LineWidth
746+ %fstrm = regexprep(fstrm, '(GC\n2 setlinecap\n1 LJ)\nN', '$1\n0.667 LW\nN');
747+ % This is faster:
748+ fstrm = strrep(fstrm, sprintf('GC\n2 setlinecap\n1 LJ\nN'), sprintf('GC\n2 setlinecap\n1 LJ\n0.667 LW\nN'));
749+
750+ % This is more accurate but *MUCH* slower (issue #52)
751+ %{
752+ % Modify all thin lines in the figure to have 10x LineWidths
753+ hLines = findall(fig,'Type','line');
754+ hThinLines = [];
755+ for lineIdx = 1 : numel(hLines)
756+ thisLine = hLines(lineIdx);
757+ if thisLine.LineWidth < 0.75 && strcmpi(thisLine.Visible,'on')
758+ hThinLines(end+1) = thisLine; %#ok<AGROW>
759+ thisLine.LineWidth = thisLine.LineWidth * 10;
760+ end
761+ end
762+
763+ % If any thin lines were found
764+ if ~isempty(hThinLines)
765+ % Prepare an EPS with large-enough line widths
766+ print(fig, options{:}, name);
767+ % Restore the original LineWidths in the figure
768+ for lineIdx = 1 : numel(hThinLines)
769+ thisLine = handle(hThinLines(lineIdx));
770+ thisLine.LineWidth = thisLine.LineWidth / 10;
771+ end
772+
773+ % Compare the original and the new EPS files and correct the original stream's LineWidths
774+ fstrm_new = read_write_entire_textfile(name);
775+ idx = 500; % skip heading with its possibly-different timestamp
776+ markerStr = sprintf('10.0 ML\nN');
777+ markerLen = length(markerStr);
778+ while ~isempty(idx) && idx < length(fstrm)
779+ lastIdx = min(length(fstrm), length(fstrm_new));
780+ delta = fstrm(idx+1:lastIdx) - fstrm_new(idx+1:lastIdx);
781+ idx = idx + find(delta,1);
782+ if ~isempty(idx) && ...
783+ isequal(fstrm(idx-markerLen+1:idx), markerStr) && ...
784+ ~isempty(regexp(fstrm_new(idx-markerLen+1:idx+12),'10.0 ML\n[\d\.]+ LW\nN')) %#ok<RGXP1>
785+ value = str2double(regexprep(fstrm_new(idx:idx+12),' .*',''));
786+ if isnan(value), break; end % something's wrong... - bail out
787+ newStr = sprintf('%0.3f LW\n',value/10);
788+ fstrm = [fstrm(1:idx-1) newStr fstrm(idx:end)];
789+ idx = idx + 12;
790+ else
791+ break;
792+ end
793+ end
794+ end
795+ %}
796+
797+ % This is much faster although less accurate: fix all non-gray lines to have a LineWidth of 0.75 (=1 LW)
798+ % Note: This will give incorrect LineWidth of 075 for lines having LineWidth<0.75, as well as for non-gray grid-lines (if present)
799+ % However, in practice these edge-cases are very rare indeed, and the difference in LineWidth should not be noticeable
800+ %fstrm = regexprep(fstrm, '([CR]C\n2 setlinecap\n1 LJ)\nN', '$1\n1 LW\nN');
801+ % This is faster (the original regexprep could take many seconds when the axes contains many lines):
802+ fstrm = strrep(fstrm, sprintf('\n2 setlinecap\n1 LJ\nN'), sprintf('\n2 setlinecap\n1 LJ\n1 LW\nN'));
803+ end
804+ catch err
805+ fprintf(2, 'Error fixing LineWidths in EPS file: %s\n at %s:%d\n', err.message, err.stack(1).file, err.stack(1).line);
806+ end
807+
808+ % Reset the font and line colors
809+ try
810+ set(black_text_handles, 'Color', [0 0 0]);
811+ set(white_text_handles, 'Color', [1 1 1]);
812+ catch
813+ % Fix issue #159: redo findall() '*text_handles'
814+ black_text_handles = findall(fig, 'Type', 'text', 'Color', [0 0 0]+eps);
815+ white_text_handles = findall(fig, 'Type', 'text', 'Color', [1 1 1]-eps);
816+ set(black_text_handles, 'Color', [0 0 0]);
817+ set(white_text_handles, 'Color', [1 1 1]);
818+ end
819+ set(white_line_handles, 'Color', [1 1 1]);
820+
821+ % Reset paper size
822+ set(fig, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation);
823+
824+ % Reset the font names in the figure
825+ if ~isempty(font_swap)
826+ for a = update
827+ set(font_handles(a), 'FontName', fonts{a}, 'FontSize', fonts_size(a));
828+ end
829+ end
830+
831+ % Bail out if EPS post-processing is not possible
832+ if isempty(fstrm)
833+ warning('Loading EPS file failed, so unable to perform post-processing. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.');
834+ return
835+ end
836+
837+ % Replace the font names
838+ if ~isempty(font_swap)
839+ for a = 1:size(font_swap, 2)
840+ %fstrm = regexprep(fstrm, [font_swap{1,a} '-?[a-zA-Z]*\>'], font_swap{3,a}(~isspace(font_swap{3,a})));
841+ fstrm = regexprep(fstrm, font_swap{2,a}, font_swap{3,a}(~isspace(font_swap{3,a})));
842+ end
843+ end
844+
845+ % Move the bounding box to the top of the file (HG2 only), or fix the line styles (HG1 only)
846+ if using_hg2(fig)
847+ % Move the bounding box to the top of the file (HG2 only)
848+ [s, e] = regexp(fstrm, '%%BoundingBox: [^%]*%%');
849+ if numel(s) == 2
850+ fstrm = fstrm([1:s(1)-1 s(2):e(2)-2 e(1)-1:s(2)-1 e(2)-1:end]);
851+ end
852+ else
853+ % Fix the line styles (HG1 only)
854+ fstrm = fix_lines(fstrm);
855+ end
856+
857+ % Apply the bounding box padding & cropping, replacing Matlab's print()'s bounding box
858+ if bb_crop
859+ % Calculate a new bounding box based on a bitmap print using crop_border.m
860+ % 1. Determine the Matlab BoundingBox and PageBoundingBox
861+ [s,e] = regexp(fstrm, '%%BoundingBox: [^%]*%%'); % location BB in eps file
862+ if numel(s)==2, s=s(2); e=e(2); end
863+ aa = fstrm(s+15:e-3); % dimensions bb - STEP1
864+ bb_matlab = cell2mat(textscan(aa,'%f32%f32%f32%f32')); % dimensions bb - STEP2
865+
866+ [s,e] = regexp(fstrm, '%%PageBoundingBox: [^%]*%%'); % location bb in eps file
867+ if numel(s)==2, s=s(2); e=e(2); end
868+ aa = fstrm(s+19:e-3); % dimensions bb - STEP1
869+ pagebb_matlab = cell2mat(textscan(aa,'%f32%f32%f32%f32')); % dimensions bb - STEP2
870+
871+ % 2. Create a bitmap image and use crop_borders to create the relative
872+ % bb with respect to the PageBoundingBox
873+ [A, bcol] = print2array(fig, 1, renderer);
874+ [aa, aa, aa, bb_rel] = crop_borders(A, bcol, bb_padding, crop_amounts);
875+
876+ % 3. Calculate the new Bounding Box
877+ pagew = pagebb_matlab(3)-pagebb_matlab(1);
878+ pageh = pagebb_matlab(4)-pagebb_matlab(2);
879+ %bb_new = [pagebb_matlab(1)+pagew*bb_rel(1) pagebb_matlab(2)+pageh*bb_rel(2) ...
880+ % pagebb_matlab(1)+pagew*bb_rel(3) pagebb_matlab(2)+pageh*bb_rel(4)];
881+ bb_new = pagebb_matlab([1,2,1,2]) + [pagew,pageh,pagew,pageh].*bb_rel; % clearer
882+ bb_offset = (bb_new-bb_matlab) + [-1,-1,1,1]; % 1px margin so that cropping is not TOO tight
883+
884+ % Apply the bounding box padding
885+ if bb_padding
886+ if abs(bb_padding)<1
887+ bb_padding = round((mean([bb_new(3)-bb_new(1) bb_new(4)-bb_new(2)])*bb_padding)/0.5)*0.5; % ADJUST BB_PADDING
888+ end
889+ add_padding = @(n1, n2, n3, n4) sprintf(' %d', str2double({n1, n2, n3, n4}) + [-bb_padding -bb_padding bb_padding bb_padding] + bb_offset);
890+ else
891+ add_padding = @(n1, n2, n3, n4) sprintf(' %d', str2double({n1, n2, n3, n4}) + bb_offset); % fix small but noticeable bounding box shift
892+ end
893+ fstrm = regexprep(fstrm, '%%BoundingBox:[ ]+([-]?\d+)[ ]+([-]?\d+)[ ]+([-]?\d+)[ ]+([-]?\d+)', '%%BoundingBox:${add_padding($1, $2, $3, $4)}');
894+ end
895+
896+ % Fix issue #44: white artifact lines appearing in patch exports
897+ % Note: the problem is due to the fact that Matlab's print() function exports patches
898+ % as a combination of filled triangles, and a white line appears where the triangles touch
899+ % In the workaround below, we will modify such dual-triangles into a filled rectangle.
900+ % We are careful to only modify regexps that exactly match specific patterns - it's better to not
901+ % correct some white-line artifacts than to change the geometry of a patch, or to corrupt the EPS.
902+ % e.g.: '0 -450 937 0 0 450 3 MP PP 937 0 0 -450 0 450 3 MP PP' => '0 -450 937 0 0 450 0 0 4 MP'
903+ fstrm = regexprep(fstrm, '\n([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) 3 MP\nPP\n\2 \1 \3 3 MP\nPP\n','\n$1 $2 $3 0 0 4 MP\nPP\n');
904+ fstrm = regexprep(fstrm, '\n([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) 3 MP\nPP\n\2 \3 \1 3 MP\nPP\n','\n$1 $2 $3 0 0 4 MP\nPP\n');
905+ fstrm = regexprep(fstrm, '\n([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) 3 MP\nPP\n\3 \1 \2 3 MP\nPP\n','\n$1 $2 $3 0 0 4 MP\nPP\n');
906+ fstrm = regexprep(fstrm, '\n([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) ([-\d.]+ [-\d.]+) 3 MP\nPP\n\3 \2 \1 3 MP\nPP\n','\n$1 $2 $3 0 0 4 MP\nPP\n');
907+
908+ % Write out the fixed eps file
909+ read_write_entire_textfile(name, fstrm);
910 end
911-if using_hg2(fig)
912- % Convert miter joins to line joins
913- fstrm = regexprep(fstrm, '10.0 ML\n', '1 LJ\n');
914- % Move the bounding box to the top of the file
915- [s, e] = regexp(fstrm, '%%BoundingBox: [\w\s()]*%%');
916- if numel(s) == 2
917- fstrm = fstrm([1:s(1)-1 s(2):e(2)-2 e(1)-1:s(2)-1 e(2)-1:end]);
918+
919+function [StoredColors, fstrm, foundFlags] = eps_maintainAlpha(fig, fstrm, StoredColors)
920+ if nargin == 1 % in: convert transparency in Matlab figure into unique RGB colors
921+ hObjs = findall(fig); %findobj(fig,'Type','Area');
922+ StoredColors = {};
923+ propNames = {'Face','Edge'};
924+ for objIdx = 1:length(hObjs)
925+ hObj = hObjs(objIdx);
926+ for propIdx = 1 : numel(propNames)
927+ try
928+ propName = propNames{propIdx};
929+ if strcmp(hObj.(propName).ColorType, 'truecoloralpha')
930+ nColors = length(StoredColors);
931+ oldColor = hObj.(propName).ColorData;
932+ newColor = uint8([101; 102+floor(nColors/255); mod(nColors,255); 255]);
933+ StoredColors{end+1} = {hObj, propName, oldColor, newColor};
934+ hObj.(propName).ColorData = newColor;
935+ end
936+ catch
937+ % Never mind - ignore (either doesn't have the property or cannot change it)
938+ end
939+ end
940+ end
941+ else % restore transparency in Matlab figure by converting back from the unique RGBs
942+ %Find the transparent patches
943+ wasError = false;
944+ nColors = length(StoredColors);
945+ foundFlags = false(1,nColors);
946+ for objIdx = 1 : nColors
947+ colorsData = StoredColors{objIdx};
948+ hObj = colorsData{1};
949+ propName = colorsData{2};
950+ origColor = colorsData{3};
951+ newColor = colorsData{4};
952+ try
953+ %Restore the EPS files patch color
954+ colorID = num2str(round(double(newColor(1:3)') /255,3),'%.3g %.3g %.3g'); %ID for searching
955+ origRGB = num2str(round(double(origColor(1:3)')/255,3),'%.3g %.3g %.3g'); %Replace with original color
956+ origAlpha = num2str(round(double(origColor(end)) /255,3),'%.3g'); %Convert alpha value for EPS
957+
958+ %Find and replace the RGBA values within the EPS text fstrm
959+ if strcmpi(propName,'Face')
960+ oldStr = sprintf(['\n' colorID ' RC\nN\n']);
961+ newStr = sprintf(['\n' origRGB ' RC\n' origAlpha ' .setopacityalpha true\nN\n']);
962+ else %'Edge'
963+ oldStr = sprintf(['\n' colorID ' RC\n1 LJ\n']);
964+ newStr = sprintf(['\n' origRGB ' RC\n' origAlpha ' .setopacityalpha true\n']);
965+ end
966+ foundFlags(objIdx) = ~isempty(strfind(fstrm, oldStr));
967+ fstrm = strrep(fstrm, oldStr, newStr);
968+
969+ %Restore the figure object's original color
970+ hObj.(propName).ColorData = origColor;
971+ catch err
972+ % something is wrong - cannot restore transparent color...
973+ if ~wasError
974+ fprintf(2, 'Error maintaining transparency in EPS file: %s\n at %s:%d\n', err.message, err.stack(1).file, err.stack(1).line);
975+ wasError = true;
976+ end
977+ end
978+ end
979 end
980-else
981- % Fix the line styles
982- fstrm = fix_lines(fstrm);
983 end
984-% Apply the bounding box padding
985-if bb_padding
986- add_padding = @(n1, n2, n3, n4) sprintf(' %d', str2double({n1, n2, n3, n4}) + [-bb_padding -bb_padding bb_padding bb_padding]);
987- fstrm = regexprep(fstrm, '%%BoundingBox:[ ]+([-]?\d+)[ ]+([-]?\d+)[ ]+([-]?\d+)[ ]+([-]?\d+)', '%%BoundingBox:${add_padding($1, $2, $3, $4)}');
988-end
989-% Write out the fixed eps file
990-read_write_entire_textfile(name, fstrm);
991-end
992Index: ../trunk-jpl/externalpackages/export_fig/LICENSE
993===================================================================
994--- ../trunk-jpl/externalpackages/export_fig/LICENSE (revision 21314)
995+++ ../trunk-jpl/externalpackages/export_fig/LICENSE (revision 21315)
996@@ -1,4 +1,4 @@
997-Copyright (c) 2014, Oliver J. Woodford
998+Copyright (c) 2014, Oliver J. Woodford, Yair M. Altman
999 All rights reserved.
1000
1001 Redistribution and use in source and binary forms, with or without
1002Index: ../trunk-jpl/externalpackages/export_fig/copyfig.m
1003===================================================================
1004--- ../trunk-jpl/externalpackages/export_fig/copyfig.m (revision 21314)
1005+++ ../trunk-jpl/externalpackages/export_fig/copyfig.m (revision 21315)
1006@@ -1,3 +1,4 @@
1007+function fh = copyfig(fh)
1008 %COPYFIG Create a copy of a figure, without changing the figure
1009 %
1010 % Examples:
1011@@ -14,20 +15,37 @@
1012
1013 % Copyright (C) Oliver Woodford 2012
1014
1015-function fh = copyfig(fh)
1016-% Set the default
1017-if nargin == 0
1018- fh = gcf;
1019+% 26/02/15: If temp dir is not writable, use the dest folder for temp
1020+% destination files (Javier Paredes)
1021+% 15/04/15: Suppress warnings during copyobj (Dun Kirk comment on FEX page 2013-10-02)
1022+
1023+ % Set the default
1024+ if nargin == 0
1025+ fh = gcf;
1026+ end
1027+ % Is there a legend?
1028+ if isempty(findall(fh, 'Type', 'axes', 'Tag', 'legend'))
1029+ % Safe to copy using copyobj
1030+ oldWarn = warning('off'); %#ok<WNOFF> %Suppress warnings during copyobj (Dun Kirk comment on FEX page 2013-10-02)
1031+ fh = copyobj(fh, 0);
1032+ warning(oldWarn);
1033+ else
1034+ % copyobj will change the figure, so save and then load it instead
1035+ tmp_nam = [tempname '.fig'];
1036+ try
1037+ % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
1038+ fid = fopen(tmp_nam,'w');
1039+ fwrite(fid,1);
1040+ fclose(fid);
1041+ delete(tmp_nam); % cleanup
1042+ catch
1043+ % Temp dir is not writable, so use the current folder
1044+ [dummy,fname,fext] = fileparts(tmp_nam); %#ok<ASGLU>
1045+ fpath = pwd;
1046+ tmp_nam = fullfile(fpath,[fname fext]);
1047+ end
1048+ hgsave(fh, tmp_nam);
1049+ fh = hgload(tmp_nam);
1050+ delete(tmp_nam);
1051+ end
1052 end
1053-% Is there a legend?
1054-if isempty(findall(fh, 'Type', 'axes', 'Tag', 'legend'))
1055- % Safe to copy using copyobj
1056- fh = copyobj(fh, 0);
1057-else
1058- % copyobj will change the figure, so save and then load it instead
1059- tmp_nam = [tempname '.fig'];
1060- hgsave(fh, tmp_nam);
1061- fh = hgload(tmp_nam);
1062- delete(tmp_nam);
1063-end
1064-end
1065Index: ../trunk-jpl/externalpackages/export_fig/ImageSelection.class
1066===================================================================
1067Cannot display: file marked as a binary type.
1068svn:mime-type = application/octet-stream
1069
1070Property changes on: ../trunk-jpl/externalpackages/export_fig/ImageSelection.class
1071___________________________________________________________________
1072Added: svn:executable
1073 + *
1074Added: svn:mime-type
1075 + application/octet-stream
1076
1077Index: ../trunk-jpl/externalpackages/export_fig/README.md
1078===================================================================
1079--- ../trunk-jpl/externalpackages/export_fig/README.md (revision 21314)
1080+++ ../trunk-jpl/externalpackages/export_fig/README.md (revision 21315)
1081@@ -24,7 +24,7 @@
1082 |:-------:|:---------:|:----------:|
1083 |![](https://farm6.staticflickr.com/5616/15589249291_16e485c29a_o_d.png)|![](https://farm4.staticflickr.com/3944/15406302850_4d2e1c7afa_o_d.png)|![](https://farm6.staticflickr.com/5607/15568225476_8ce9bd5f6b_o_d.png)|
1084
1085-Note that the size and background colour of test2.png (the output of export_fig) are the same as those of the on screen figure, in contrast to test.png. Of course, if you want want the figure background to be white (or any other colour) in the exported file then you can set this prior to exporting using:
1086+Note that the size and background colour of test2.png (the output of export_fig) are the same as those of the on screen figure, in contrast to test.png. Of course, if you want the figure background to be white (or any other colour) in the exported file then you can set this prior to exporting using:
1087 ```Matlab
1088 set(gcf, 'Color', 'w');
1089 ```
1090@@ -148,7 +148,7 @@
1091
1092 **Cropping** - by default, export_fig crops its output to minimize the amount of empty space around the figure. If you'd prefer the figure to be uncropped, and instead have the same appearance (in terms of border width) as the on screen figure, then use the `-nocrop` option.
1093
1094-**Colourspace** - by default, export_fig generates files in the RGB [colourspace](http://en.wikipedia.org/wiki/Color_space). However, you can also export in greyscale or the CMYK colourspace, using the `-grey` (or `-gray`) and `-cmyk` options respectively. The CMYK option is useful for publishers who require documents in this colourspace, but the option is only supported for PDF, EPS and TIFF files.
1095+**Colourspace** - by default, export_fig generates files in the RGB [colourspace](https://en.wikipedia.org/wiki/Color_space). However, you can also export in greyscale or the CMYK colourspace, using the `-grey` (or `-gray`) and `-cmyk` options respectively. The CMYK option is useful for publishers who require documents in this colourspace, but the option is only supported for PDF, EPS and TIFF files.
1096
1097 **Specifying a target directory** - you can get export_fig to save output files to any directory (for which you have write permission), simply by specifying the full or relative path in the filename. For example:
1098 ```Matlab
1099@@ -170,11 +170,11 @@
1100
1101 **Specifying the figure/axes** - if you have mutiple figures open you can specify which figure to export using its handle:
1102 ```Matlab
1103-export_fig(figure_handle, 'filename.fmt');
1104+export_fig(figure_handle, filename);
1105 ```
1106 Equally, if your figure contains several subplots then you can export just one of them by giving export_fig the handle to the relevant axes:
1107 ```Matlab
1108-export_fig(axes_handle, 'filename.fmt');
1109+export_fig(axes_handle, filename);
1110 ```
1111
1112 **Multiple formats** - save time by exporting to multiple formats simultaneously. E.g.:
1113@@ -194,9 +194,14 @@
1114
1115 **Appending to a file** - you can use the `-append` option to append the figure to the end of an image/document, if it already exists. This is supported for PDF and TIFF files only. Note that if you wish to append a lot of figures consecutively to a PDF, it can be more efficient to save all the figures to PDF separately then append them all in one go at the end (e.g. using [append_pdfs](http://www.mathworks.com/matlabcentral/fileexchange/31215-appendpdfs)).
1116
1117+**Output to clipboard** - you can use the `-clipboard` option to copy the specified figure or axes to the system clipboard, for easy paste into other documents (e.g., Word or PowerPoint). Note that the image is copied in bitmap (not vector) format.
1118+
1119 **Font size** - if you want to place an exported figure in a document with the font a particular size then you need to set the font to that size in the figure, and not resize the output of export_fig in the document. To avoid resizing, simply make sure that the on screen figure is the size you want the output to be in the document before exporting.
1120
1121-**Renderers** - MATLAB has three renderers for displaying and exporting figures: painters, OpenGL and ZBuffer. The different renderers have different [features](http://www.mathworks.com/access/helpdesk/help/techdoc/creating_plots/f3-84337.html#f3-102410), so if you aren't happy with the result from one renderer try another. By default, vector formats (i.e. PDF and EPS outputs) use the painters renderer, while other formats use the OpenGL renderer. Non-default renderers can be selected by using one of these three export_fig input options: `-painters`, `-opengl`, `-zbuffer`.
1122+**Renderers** - MATLAB has three renderers for displaying and exporting figures: painters, OpenGL and ZBuffer. The different renderers have different [features](http://www.mathworks.com/access/helpdesk/help/techdoc/creating_plots/f3-84337.html#f3-102410), so if you aren't happy with the result from one renderer try another. By default, vector formats (i.e. PDF and EPS outputs) use the painters renderer, while other formats use the OpenGL renderer. Non-default renderers can be selected by using one of these three export_fig input options: `-painters`, `-opengl`, `-zbuffer`:
1123+```Matlab
1124+export_fig test.png -painters
1125+```
1126
1127 **Artifacts** - sometimes the output that you get from export_fig is not what you expected. If an output file contains artifacts that aren't in the on screen figure then make sure that the renderer used for rendering the figure on screen is the same as that used for exporting. To set the renderer used to display the figure, use:
1128 ```Matlab
1129@@ -214,32 +219,33 @@
1130 to this location using the dialogue box.
1131
1132 **Undefined function errors** - If you download and run export_fig and get an error similar to this:
1133-```Matlab
1134+```
1135 ??? Undefined function or method 'print2array' for input arguments of type 'double'.
1136 ```
1137 then you are missing one or more of the files that come in the export_fig package. Make sure that you click the "Get from GitHub" button at the top-right of the download [page](http://www.mathworks.co.uk/matlabcentral/fileexchange/23629-exportfig), then extract all the files in the zip file to the same directory. You should then have all the necessary files.
1138
1139 ### Known issues
1140-There are lots of problems with MATLAB's exporting functions, and unfortunately export_fig, which is simply a glorified wrapper for MATLAB's print function, doesn't solve all of them (yet?). Some of the problems I know about are:
1141+There are lots of problems with MATLAB's exporting functions, especially `print`. Export_fig is simply a glorified wrapper for MATLAB's `print` function, and doesn't solve all of its bugs (yet?). Some of the problems I know about are:
1142
1143-**Fonts** - when using the painters renderer, MATLAB can only export a small number of fonts, details of which can be found [here](http://www.mathworks.com/access/helpdesk/help/techdoc/creating_plots/f3-103191.html#f3-96545). Export_fig attempts to correct font names in the resulting EPS file (for upto a maximum of 11 different fonts in one figure), but this is not always guaranteed to work. In particular, the text positions will be affected. It also does not work for text blocks where the 'Interpreter' property is set to 'latex'.
1144+**Fonts** - when using the painters renderer, MATLAB can only export a small number of fonts, details of which can be found [here](http://www.mathworks.com/help/releases/R2014a/matlab/creating_plots/choosing-a-printer-driver.html#f3-96545). Export_fig attempts to correct font names in the resulting EPS file (up to a maximum of 11 different fonts in one figure), but this is not always guaranteed to work. In particular, the text positions will be affected. It also does not work for text blocks where the 'Interpreter' property is set to 'latex'.
1145
1146-Also, when using the painters renderer, ghostscript will sometimes throw an error such as `Error: /undefined in /findfont`. This suggests that ghostscript could not find a definition file for one of your fonts. One possible fix for this is to make sure the file `EXPORT_FIG_PATH/.ignore/gs_font_path.txt` exists and contains a list of paths to the folder(s) containing the necessary font definitions (make sure they're TrueType definitions), separated by a semicolon.
1147+Also, when using the painters renderer, ghostscript will sometimes throw an error such as `Error: /undefined in /findfont`. This suggests that ghostscript could not find a definition file for one of your fonts. One possible fix for this is to make sure the file `EXPORT_FIG_PATH/.ignore/gs_font_path.txt` exists and contains a list of paths to the folder(s) containing the necessary font definitions (make sure that they are TrueType definitions!), separated by a semicolon.
1148
1149-**RGB color data not yet supported in Painter's mode** - you will see this as a warning if you try to export a figure which contains patch objects whose face or vertex colors are specified as a an RGB colour, rather than an index into the colormap, using the painters renderer (the default renderer for vector output). This problem can arise if you use `pcolor`, for example. This is a problem with MATLAB's painters renderer, which also affects `print`; there is currently no fix available in export_fig (other than to export to bitmap). The suggested workaround is to avoid colouring patches using RGB. First, try to use colours in the figure's colourmap (instructions [here](http://www.mathworks.co.uk/support/solutions/en/data/1-6OTPQE/)) - change the colourmap, if necessary. If you are using `pcolor`, try using [uimagesc](http://www.mathworks.com/matlabcentral/fileexchange/11368) (on the file exchange) instead.
1150+**RGB color data not yet supported in Painter's mode** - you will see this as a warning if you try to export a figure which contains patch objects whose face or vertex colors are specified as an RGB colour, rather than an index into the colormap, using the painters renderer (the default renderer for vector output). This problem can arise if you use `pcolor`, for example. This is a problem with MATLAB's painters renderer, which also affects `print`; there is currently no fix available in export_fig (other than to export to bitmap). The suggested workaround is to avoid colouring patches using RGB. First, try to use colours in the figure's colourmap (instructions [here](http://www.mathworks.co.uk/support/solutions/en/data/1-6OTPQE/)) - change the colourmap, if necessary. If you are using `pcolor`, try using [uimagesc](http://www.mathworks.com/matlabcentral/fileexchange/11368) (on the file exchange) instead.
1151
1152 **Dashed contour lines appear solid** - when using the painters renderer, MATLAB cannot generate dashed lines using the `contour` function (either on screen or in exported PDF and EPS files). Details can be found [here](http://www.mathworks.com/support/solutions/en/data/1-14PPHB/?solution=1-14PPHB).
1153
1154 **Text size** - when using the OpenGL or ZBuffer renderers, large text can be resized relative to the figure when exporting at non-screen-resolution (including using anti-alising at screen resolution). This is a feature of MATLAB's `print `function. In this case, try using the `-painters` option.
1155
1156-**Lighting and transparency** - when using the painters renderer, transparency and lighting effects are not supported. Sorry, but this is a feature of the renderer. To find out more about the capabilities of each rendering method, see [here](http://www.mathworks.com/access/helpdesk/help/techdoc/creating_plots/f3-84337.html#f3-102410). You can still export transparent objects to vector format (SVG) using the excellent [plot2svg](http://www.mathworks.com/matlabcentral/fileexchange/7401) package, then convert this to PDF, for example using [Inkscape](http://inkscape.org/). However, it can't handle lighting.
1157+**Lighting and transparency** - when using the painters renderer, transparency and lighting effects are not supported. Sorry, but this is an inherent feature of MATLAB's painters renderer. To find out more about the capabilities of each rendering method, see [here](http://www.mathworks.com/access/helpdesk/help/techdoc/creating_plots/f3-84337.html#f3-102410). You can still export transparent objects to vector format (SVG) using the excellent [plot2svg](http://www.mathworks.com/matlabcentral/fileexchange/7401) package, then convert this to PDF, for example using [Inkscape](http://inkscape.org/). However, it can't handle lighting.
1158
1159-**Lines in patch objects** - when exporting patch objects to PDF using the painters renderer (default), sometimes the output can appear to have lines across the middle of rectangular patches; these lines are the colour of the background, as if there is a crack in the patch, allowing you to see through. This issue is a feature of the software used to display the PDF, rather than the PDF itself. Sometimes disabling anti-aliasing in this software can get rid of the lines.
1160+**Lines in patch objects** - when exporting patch objects to PDF using the painters renderer (default), sometimes the output can appear to have lines across the middle of rectangular patches; these lines are the colour of the background, as if there is a crack in the patch, allowing you to see through. This appears to be due to bugs in MATLAB's internal vector rendering code. These lines can often be removed from the PDF using software such as [InkScape](https://inkscape.org). Sometimes disabling anti-aliasing in the PDF-reader software can get rid of the lines ([discussion](https://github.com/altmany/export_fig/issues/44)).
1161
1162 **Out of memory** - if you run into memory issues when using export_fig, some ways to get round this are:
1163 1. Reduce the level of anti-aliasing.
1164- 2. Reduce the size of the on screen figure.
1165- 3. Reduce the resolution (dpi) the figure is exported at.
1166+ 2. Reduce the size of the figure.
1167+ 3. Reduce the export resolution (dpi).
1168+ 4. Change the renderer to painters or ZBuffer.
1169
1170 **Errors** - the other common type of errors people get with export_fig are OpenGL errors. This isn't a fault of export_fig, but either a bug in MATLAB's `print`, or your graphics driver getting itself into a state. Always make sure your graphics driver is up-to-date. If it still doesn't work, try using the ZBuffer renderer.
1171
1172@@ -248,12 +254,17 @@
1173
1174 Secondly, if exporting to bitmap, do try all the renderers (i.e. try the options `-opengl`, `-zbuffer` and `-painters` separately), to see if one of them does produce an acceptable output, and if so, use that.
1175
1176-If the figure looks correct on screen, but an error exists in the exported output (which cannot be solved using a different renderer) then please feel free to raise an [issue](https://github.com/ojwoodford/export_fig/issues). Please be sure to include the .fig file, the export_fig command you use, the output you get, and a description of what you expected. I can't promise anything, but if it's easy to fix I probably will do it. Often I will find that the error is due to a bug in MATLAB's print function, in which case I will suggest you submit it as a bug to TheMathWorks, and inform me of any fix they suggest. Also, if there's a feature you'd like that isn't supported please tell me what it is and I'll consider implementing it.
1177+If this still does not help, then ensure that you are using the latest version of export_fig, which is available [here](https://github.com/altmany/export_fig/archive/master.zip).
1178+
1179+If the figure looks correct on screen, but an error exists in the exported output (which cannot be solved using a different renderer) then please feel free to raise an [issue](https://github.com/altmany/export_fig/issues). Please be sure to include the .fig file, the export_fig command you use, the output you get, and a description of what you expected. I can't promise anything, but if it's easy to fix I may indeed do it. Often I will find that the error is due to a bug in MATLAB's `print` function, in which case I will suggest you submit it as a bug to TheMathWorks, and inform me of any fix they suggest. Also, if there's a feature you'd like that isn't supported please tell me what it is and I'll consider implementing it.
1180
1181 ### And finally...
1182
1183 ![](https://farm4.staticflickr.com/3956/15591911455_b9008bd77e_o_d.jpg)
1184
1185-If you've ever wondered what's going on in the icon on the export_fig download page (reproduced on the left), then this explanantion is for you. The icon is designed to demonstrate as many of export_fig's features as possible. Given a
1186-figure containing a translucent mesh (top right), export_fig can export to pdf (bottom centre), which allows the figure to be zoomed in without losing quality (because it's a vector graphic), but isn't able to reproduce the translucency, and also, depending on the viewer, creates small gaps between the patches, which are seen here as thin white lines. By contrast, when exporting to png (top left), translucency is preserved (see how the graphic below shows through), the figure is anti-aliased, but zooming in does not reveal more detail.
1187+If you've ever wondered what's going on in the logo on the export_fig download page (reproduced here), then this explanantion is for you. The logo is designed to demonstrate as many of export_fig's features as possible:
1188+
1189+Given a figure containing a translucent mesh (top right), export_fig can export to pdf (bottom centre), which allows the figure to be zoomed-in without losing quality (because it's a vector graphic), but isn't able to reproduce the translucency. Also, depending on the PDF viewer program, small gaps appear between the patches, which are seen here as thin white lines.
1190+
1191+By contrast, when exporting to png (top left), translucency is preserved (see how the graphic below shows through), and the figure is anti-aliased. However, zooming-in does not reveal more detail since png is a bitmap format. Also, lines appear less sharp than in the pdf output.
1192
1193Index: ../trunk-jpl/externalpackages/export_fig/README
1194===================================================================
1195--- ../trunk-jpl/externalpackages/export_fig/README (revision 0)
1196+++ ../trunk-jpl/externalpackages/export_fig/README (revision 21315)
1197@@ -0,0 +1,17 @@
1198+Downloaded from https://www.mathworks.com/matlabcentral/fileexchange/23629-export-fig
1199+
1200+We had to patch export_fig.m to force export_fig to use the renderers painter, otherwise it is just way to slow (opengl is the default if we have patches)
1201+
1202+Line 585:
1203+
1204+
1205+if ~options.renderer
1206+ if hasTransparency || hasPatches
1207+ % This is *MUCH* slower, but more accurate for patches and transparent annotations (issue #39)
1208+ renderer = '-opengl';
1209+ else
1210+ renderer = '-painters';
1211+ end
1212+end
1213+
1214+change to painters all the time
1215Index: ../trunk-jpl/externalpackages/export_fig/eps2pdf.m
1216===================================================================
1217--- ../trunk-jpl/externalpackages/export_fig/eps2pdf.m (revision 21314)
1218+++ ../trunk-jpl/externalpackages/export_fig/eps2pdf.m (revision 21315)
1219@@ -1,3 +1,4 @@
1220+function eps2pdf(source, dest, crop, append, gray, quality, gs_options)
1221 %EPS2PDF Convert an eps file to pdf format using ghostscript
1222 %
1223 % Examples:
1224@@ -6,6 +7,7 @@
1225 % eps2pdf(source, dest, crop, append)
1226 % eps2pdf(source, dest, crop, append, gray)
1227 % eps2pdf(source, dest, crop, append, gray, quality)
1228+% eps2pdf(source, dest, crop, append, gray, quality, gs_options)
1229 %
1230 % This function converts an eps file to pdf format. The output can be
1231 % optionally cropped and also converted to grayscale. If the output pdf
1232@@ -16,23 +18,25 @@
1233 % This function requires that you have ghostscript installed on your
1234 % system. Ghostscript can be downloaded from: http://www.ghostscript.com
1235 %
1236-%IN:
1237-% source - filename of the source eps file to convert. The filename is
1238-% assumed to already have the extension ".eps".
1239-% dest - filename of the destination pdf file. The filename is assumed to
1240-% already have the extension ".pdf".
1241-% crop - boolean indicating whether to crop the borders off the pdf.
1242-% Default: true.
1243-% append - boolean indicating whether the eps should be appended to the
1244-% end of the pdf as a new page (if the pdf exists already).
1245-% Default: false.
1246-% gray - boolean indicating whether the output pdf should be grayscale or
1247-% not. Default: false.
1248+% Inputs:
1249+% source - filename of the source eps file to convert. The filename is
1250+% assumed to already have the extension ".eps".
1251+% dest - filename of the destination pdf file. The filename is assumed
1252+% to already have the extension ".pdf".
1253+% crop - boolean indicating whether to crop the borders off the pdf.
1254+% Default: true.
1255+% append - boolean indicating whether the eps should be appended to the
1256+% end of the pdf as a new page (if the pdf exists already).
1257+% Default: false.
1258+% gray - boolean indicating whether the output pdf should be grayscale
1259+% or not. Default: false.
1260 % quality - scalar indicating the level of image bitmap quality to
1261 % output. A larger value gives a higher quality. quality > 100
1262 % gives lossless output. Default: ghostscript prepress default.
1263+% gs_options - optional ghostscript options (e.g.: '-dNoOutputFonts'). If
1264+% multiple options are needed, enclose in call array: {'-a','-b'}
1265
1266-% Copyright (C) Oliver Woodford 2009-2011
1267+% Copyright (C) Oliver Woodford 2009-2014, Yair Altman 2015-
1268
1269 % Suggestion of appending pdf files provided by Matt C at:
1270 % http://www.mathworks.com/matlabcentral/fileexchange/23629
1271@@ -43,92 +47,143 @@
1272 % which was fixed for lossless compression settings.
1273
1274 % 9/12/2011 Pass font path to ghostscript.
1275+% 26/02/15: If temp dir is not writable, use the dest folder for temp
1276+% destination files (Javier Paredes)
1277+% 28/02/15: Enable users to specify optional ghostscript options (issue #36)
1278+% 01/03/15: Upon GS error, retry without the -sFONTPATH= option (this might solve
1279+% some /findfont errors according to James Rankin, FEX Comment 23/01/15)
1280+% 23/06/15: Added extra debug info in case of ghostscript error; code indentation
1281+% 04/10/15: Suggest a workaround for issue #41 (missing font path; thanks Mariia Fedotenkova)
1282+% 22/02/16: Bug fix from latest release of this file (workaround for issue #41)
1283
1284-function eps2pdf(source, dest, crop, append, gray, quality)
1285-% Intialise the options string for ghostscript
1286-options = ['-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile="' dest '"'];
1287-% Set crop option
1288-if nargin < 3 || crop
1289- options = [options ' -dEPSCrop'];
1290-end
1291-% Set the font path
1292-fp = font_path();
1293-if ~isempty(fp)
1294- options = [options ' -sFONTPATH="' fp '"'];
1295-end
1296-% Set the grayscale option
1297-if nargin > 4 && gray
1298- options = [options ' -sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray'];
1299-end
1300-% Set the bitmap quality
1301-if nargin > 5 && ~isempty(quality)
1302- options = [options ' -dAutoFilterColorImages=false -dAutoFilterGrayImages=false'];
1303- if quality > 100
1304- options = [options ' -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode -c ".setpdfwrite << /ColorImageDownsampleThreshold 10 /GrayImageDownsampleThreshold 10 >> setdistillerparams"'];
1305- else
1306- options = [options ' -dColorImageFilter=/DCTEncode -dGrayImageFilter=/DCTEncode'];
1307- v = 1 + (quality < 80);
1308- quality = 1 - quality / 100;
1309- s = sprintf('<< /QFactor %.2f /Blend 1 /HSample [%d 1 1 %d] /VSample [%d 1 1 %d] >>', quality, v, v, v, v);
1310- options = sprintf('%s -c ".setpdfwrite << /ColorImageDict %s /GrayImageDict %s >> setdistillerparams"', options, s, s);
1311+ % Intialise the options string for ghostscript
1312+ options = ['-q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dPDFSETTINGS=/prepress -sOutputFile="' dest '"'];
1313+ % Set crop option
1314+ if nargin < 3 || crop
1315+ options = [options ' -dEPSCrop'];
1316 end
1317-end
1318-% Check if the output file exists
1319-if nargin > 3 && append && exist(dest, 'file') == 2
1320- % File exists - append current figure to the end
1321- tmp_nam = tempname;
1322- % Copy the file
1323- copyfile(dest, tmp_nam);
1324- % Add the output file names
1325- options = [options ' -f "' tmp_nam '" "' source '"'];
1326- try
1327- % Convert to pdf using ghostscript
1328- [status, message] = ghostscript(options);
1329- catch me
1330+ % Set the font path
1331+ fp = font_path();
1332+ if ~isempty(fp)
1333+ options = [options ' -sFONTPATH="' fp '"'];
1334+ end
1335+ % Set the grayscale option
1336+ if nargin > 4 && gray
1337+ options = [options ' -sColorConversionStrategy=Gray -dProcessColorModel=/DeviceGray'];
1338+ end
1339+ % Set the bitmap quality
1340+ if nargin > 5 && ~isempty(quality)
1341+ options = [options ' -dAutoFilterColorImages=false -dAutoFilterGrayImages=false'];
1342+ if quality > 100
1343+ options = [options ' -dColorImageFilter=/FlateEncode -dGrayImageFilter=/FlateEncode -c ".setpdfwrite << /ColorImageDownsampleThreshold 10 /GrayImageDownsampleThreshold 10 >> setdistillerparams"'];
1344+ else
1345+ options = [options ' -dColorImageFilter=/DCTEncode -dGrayImageFilter=/DCTEncode'];
1346+ v = 1 + (quality < 80);
1347+ quality = 1 - quality / 100;
1348+ s = sprintf('<< /QFactor %.2f /Blend 1 /HSample [%d 1 1 %d] /VSample [%d 1 1 %d] >>', quality, v, v, v, v);
1349+ options = sprintf('%s -c ".setpdfwrite << /ColorImageDict %s /GrayImageDict %s >> setdistillerparams"', options, s, s);
1350+ end
1351+ end
1352+ % Enable users to specify optional ghostscript options (issue #36)
1353+ if nargin > 6 && ~isempty(gs_options)
1354+ if iscell(gs_options)
1355+ gs_options = sprintf(' %s',gs_options{:});
1356+ elseif ~ischar(gs_options)
1357+ error('gs_options input argument must be a string or cell-array of strings');
1358+ else
1359+ gs_options = [' ' gs_options];
1360+ end
1361+ options = [options gs_options];
1362+ end
1363+ % Check if the output file exists
1364+ if nargin > 3 && append && exist(dest, 'file') == 2
1365+ % File exists - append current figure to the end
1366+ tmp_nam = tempname;
1367+ try
1368+ % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
1369+ fid = fopen(tmp_nam,'w');
1370+ fwrite(fid,1);
1371+ fclose(fid);
1372+ delete(tmp_nam);
1373+ catch
1374+ % Temp dir is not writable, so use the dest folder
1375+ [dummy,fname,fext] = fileparts(tmp_nam); %#ok<ASGLU>
1376+ fpath = fileparts(dest);
1377+ tmp_nam = fullfile(fpath,[fname fext]);
1378+ end
1379+ % Copy the file
1380+ copyfile(dest, tmp_nam);
1381+ % Add the output file names
1382+ options = [options ' -f "' tmp_nam '" "' source '"'];
1383+ try
1384+ % Convert to pdf using ghostscript
1385+ [status, message] = ghostscript(options);
1386+ catch me
1387+ % Delete the intermediate file
1388+ delete(tmp_nam);
1389+ rethrow(me);
1390+ end
1391 % Delete the intermediate file
1392 delete(tmp_nam);
1393- rethrow(me);
1394- end
1395- % Delete the intermediate file
1396- delete(tmp_nam);
1397-else
1398- % File doesn't exist or should be over-written
1399- % Add the output file names
1400- options = [options ' -f "' source '"'];
1401- % Convert to pdf using ghostscript
1402- [status, message] = ghostscript(options);
1403-end
1404-% Check for error
1405-if status
1406- % Report error
1407- if isempty(message)
1408- error('Unable to generate pdf. Check destination directory is writable.');
1409 else
1410- error(message);
1411+ % File doesn't exist or should be over-written
1412+ % Add the output file names
1413+ options = [options ' -f "' source '"'];
1414+ % Convert to pdf using ghostscript
1415+ [status, message] = ghostscript(options);
1416 end
1417+ % Check for error
1418+ if status
1419+ % Retry without the -sFONTPATH= option (this might solve some GS
1420+ % /findfont errors according to James Rankin, FEX Comment 23/01/15)
1421+ orig_options = options;
1422+ if ~isempty(fp)
1423+ options = regexprep(options, ' -sFONTPATH=[^ ]+ ',' ');
1424+ status = ghostscript(options);
1425+ if ~status, return; end % hurray! (no error)
1426+ end
1427+ % Report error
1428+ if isempty(message)
1429+ error('Unable to generate pdf. Check destination directory is writable.');
1430+ elseif ~isempty(strfind(message,'/typecheck in /findfont'))
1431+ % Suggest a workaround for issue #41 (missing font path)
1432+ font_name = strtrim(regexprep(message,'.*Operand stack:\s*(.*)\s*Execution.*','$1'));
1433+ fprintf(2, 'Ghostscript error: could not find the following font(s): %s\n', font_name);
1434+ fpath = fileparts(mfilename('fullpath'));
1435+ gs_fonts_file = fullfile(fpath, '.ignore', 'gs_font_path.txt');
1436+ fprintf(2, ' try to add the font''s folder to your %s file\n\n', gs_fonts_file);
1437+ error('export_fig error');
1438+ else
1439+ fprintf(2, '\nGhostscript error: perhaps %s is open by another application\n', dest);
1440+ if ~isempty(gs_options)
1441+ fprintf(2, ' or maybe the%s option(s) are not accepted by your GS version\n', gs_options);
1442+ end
1443+ fprintf(2, 'Ghostscript options: %s\n\n', orig_options);
1444+ error(message);
1445+ end
1446+ end
1447 end
1448-end
1449
1450 % Function to return (and create, where necessary) the font path
1451 function fp = font_path()
1452-fp = user_string('gs_font_path');
1453-if ~isempty(fp)
1454- return
1455-end
1456-% Create the path
1457-% Start with the default path
1458-fp = getenv('GS_FONTPATH');
1459-% Add on the typical directories for a given OS
1460-if ispc
1461+ fp = user_string('gs_font_path');
1462 if ~isempty(fp)
1463- fp = [fp ';'];
1464+ return
1465 end
1466- fp = [fp getenv('WINDIR') filesep 'Fonts'];
1467-else
1468- if ~isempty(fp)
1469- fp = [fp ':'];
1470+ % Create the path
1471+ % Start with the default path
1472+ fp = getenv('GS_FONTPATH');
1473+ % Add on the typical directories for a given OS
1474+ if ispc
1475+ if ~isempty(fp)
1476+ fp = [fp ';'];
1477+ end
1478+ fp = [fp getenv('WINDIR') filesep 'Fonts'];
1479+ else
1480+ if ~isempty(fp)
1481+ fp = [fp ':'];
1482+ end
1483+ fp = [fp '/usr/share/fonts:/usr/local/share/fonts:/usr/share/fonts/X11:/usr/local/share/fonts/X11:/usr/share/fonts/truetype:/usr/local/share/fonts/truetype'];
1484 end
1485- fp = [fp '/usr/share/fonts:/usr/local/share/fonts:/usr/share/fonts/X11:/usr/local/share/fonts/X11:/usr/share/fonts/truetype:/usr/local/share/fonts/truetype'];
1486+ user_string('gs_font_path', fp);
1487 end
1488-user_string('gs_font_path', fp);
1489-end
1490Index: ../trunk-jpl/externalpackages/export_fig/user_string.m
1491===================================================================
1492--- ../trunk-jpl/externalpackages/export_fig/user_string.m (revision 21314)
1493+++ ../trunk-jpl/externalpackages/export_fig/user_string.m (revision 21315)
1494@@ -1,24 +1,27 @@
1495+function string = user_string(string_name, string)
1496 %USER_STRING Get/set a user specific string
1497 %
1498 % Examples:
1499-% string = user_string(string_name)
1500-% saved = user_string(string_name, new_string)
1501+% string = user_string(string_name)
1502+% isSaved = user_string(string_name, new_string)
1503 %
1504 % Function to get and set a string in a system or user specific file. This
1505 % enables, for example, system specific paths to binaries to be saved.
1506 %
1507+% The specified string will be saved in a file named <string_name>.txt,
1508+% either in a subfolder named .ignore under this file's folder, or in the
1509+% user's prefdir folder (in case this file's folder is non-writable).
1510+%
1511 % IN:
1512-% string_name - String containing the name of the string required. The
1513-% string is extracted from a file called (string_name).txt,
1514-% stored in the same directory as user_string.m.
1515-% new_string - The new string to be saved under the name given by
1516-% string_name.
1517+% string_name - String containing the name of the string required, which
1518+% sets the filename storing the string: <string_name>.txt
1519+% new_string - The new string to be saved in the <string_name>.txt file
1520 %
1521 % OUT:
1522-% string - The currently saved string. Default: ''.
1523-% saved - Boolean indicating whether the save was succesful
1524+% string - The currently saved string. Default: ''
1525+% isSaved - Boolean indicating whether the save was succesful
1526
1527-% Copyright (C) Oliver Woodford 2011-2013
1528+% Copyright (C) Oliver Woodford 2011-2014, Yair Altman 2015-
1529
1530 % This method of saving paths avoids changing .m files which might be in a
1531 % version control system. Instead it saves the user dependent paths in
1532@@ -27,61 +30,76 @@
1533 % approach.
1534
1535 % 10/01/2013 - Access files in text, not binary mode, as latter can cause
1536-% errors. Thanks to Christian for pointing this out.
1537+% errors. Thanks to Christian for pointing this out.
1538+% 29/05/2015 - Save file in prefdir if current folder is non-writable (issue #74)
1539
1540-function string = user_string(string_name, string)
1541-if ~ischar(string_name)
1542- error('string_name must be a string.');
1543-end
1544-% Create the full filename
1545-string_name = fullfile(fileparts(mfilename('fullpath')), '.ignore', [string_name '.txt']);
1546-if nargin > 1
1547- % Set string
1548- if ~ischar(string)
1549- error('new_string must be a string.');
1550+ if ~ischar(string_name)
1551+ error('string_name must be a string.');
1552 end
1553- % Make sure the save directory exists
1554- dname = fileparts(string_name);
1555- if ~exist(dname, 'dir')
1556- % Create the directory
1557- try
1558- if ~mkdir(dname)
1559+ % Create the full filename
1560+ fname = [string_name '.txt'];
1561+ dname = fullfile(fileparts(mfilename('fullpath')), '.ignore');
1562+ file_name = fullfile(dname, fname);
1563+ if nargin > 1
1564+ % Set string
1565+ if ~ischar(string)
1566+ error('new_string must be a string.');
1567+ end
1568+ % Make sure the save directory exists
1569+ %dname = fileparts(file_name);
1570+ if ~exist(dname, 'dir')
1571+ % Create the directory
1572+ try
1573+ if ~mkdir(dname)
1574+ string = false;
1575+ return
1576+ end
1577+ catch
1578 string = false;
1579 return
1580 end
1581+ % Make it hidden
1582+ try
1583+ fileattrib(dname, '+h');
1584+ catch
1585+ end
1586+ end
1587+ % Write the file
1588+ fid = fopen(file_name, 'wt');
1589+ if fid == -1
1590+ % file cannot be created/updated - use prefdir if file does not already exist
1591+ % (if file exists but is simply not writable, don't create a duplicate in prefdir)
1592+ if ~exist(file_name,'file')
1593+ file_name = fullfile(prefdir, fname);
1594+ fid = fopen(file_name, 'wt');
1595+ end
1596+ if fid == -1
1597+ string = false;
1598+ return;
1599+ end
1600+ end
1601+ try
1602+ fprintf(fid, '%s', string);
1603 catch
1604+ fclose(fid);
1605 string = false;
1606 return
1607 end
1608- % Make it hidden
1609- try
1610- fileattrib(dname, '+h');
1611- catch
1612+ fclose(fid);
1613+ string = true;
1614+ else
1615+ % Get string
1616+ fid = fopen(file_name, 'rt');
1617+ if fid == -1
1618+ % file cannot be read, try to read the file in prefdir
1619+ file_name = fullfile(prefdir, fname);
1620+ fid = fopen(file_name, 'rt');
1621+ if fid == -1
1622+ string = '';
1623+ return
1624+ end
1625 end
1626- end
1627- % Write the file
1628- fid = fopen(string_name, 'wt');
1629- if fid == -1
1630- string = false;
1631- return
1632- end
1633- try
1634- fprintf(fid, '%s', string);
1635- catch
1636+ string = fgetl(fid);
1637 fclose(fid);
1638- string = false;
1639- return
1640 end
1641- fclose(fid);
1642- string = true;
1643-else
1644- % Get string
1645- fid = fopen(string_name, 'rt');
1646- if fid == -1
1647- string = '';
1648- return
1649- end
1650- string = fgetl(fid);
1651- fclose(fid);
1652 end
1653-end
1654Index: ../trunk-jpl/externalpackages/export_fig/export_fig.m
1655===================================================================
1656--- ../trunk-jpl/externalpackages/export_fig/export_fig.m (revision 21314)
1657+++ ../trunk-jpl/externalpackages/export_fig/export_fig.m (revision 21315)
1658@@ -1,11 +1,13 @@
1659-%EXPORT_FIG Exports figures suitable for publication
1660+function [imageData, alpha] = export_fig(varargin)
1661+%EXPORT_FIG Exports figures in a publication-quality format
1662 %
1663 % Examples:
1664-% im = export_fig
1665-% [im alpha] = export_fig
1666+% imageData = export_fig
1667+% [imageData, alpha] = export_fig
1668 % export_fig filename
1669 % export_fig filename -format1 -format2
1670 % export_fig ... -nocrop
1671+% export_fig ... -c[<val>,<val>,<val>,<val>]
1672 % export_fig ... -transparent
1673 % export_fig ... -native
1674 % export_fig ... -m<val>
1675@@ -13,29 +15,34 @@
1676 % export_fig ... -a<val>
1677 % export_fig ... -q<val>
1678 % export_fig ... -p<val>
1679+% export_fig ... -d<gs_option>
1680+% export_fig ... -depsc
1681 % export_fig ... -<renderer>
1682 % export_fig ... -<colorspace>
1683 % export_fig ... -append
1684 % export_fig ... -bookmark
1685+% export_fig ... -clipboard
1686+% export_fig ... -update
1687+% export_fig ... -nofontswap
1688 % export_fig(..., handle)
1689 %
1690 % This function saves a figure or single axes to one or more vector and/or
1691-% bitmap file formats, and/or outputs a rasterized version to the
1692-% workspace, with the following properties:
1693+% bitmap file formats, and/or outputs a rasterized version to the workspace,
1694+% with the following properties:
1695 % - Figure/axes reproduced as it appears on screen
1696 % - Cropped borders (optional)
1697 % - Embedded fonts (vector formats)
1698 % - Improved line and grid line styles
1699 % - Anti-aliased graphics (bitmap formats)
1700 % - Render images at native resolution (optional for bitmap formats)
1701-% - Transparent background supported (pdf, eps, png)
1702-% - Semi-transparent patch objects supported (png only)
1703+% - Transparent background supported (pdf, eps, png, tif)
1704+% - Semi-transparent patch objects supported (png & tif only)
1705 % - RGB, CMYK or grayscale output (CMYK only with pdf, eps, tiff)
1706 % - Variable image compression, including lossless (pdf, eps, jpg)
1707 % - Optionally append to file (pdf, tiff)
1708 % - Vector formats: pdf, eps
1709-% - Bitmap formats: png, tiff, jpg, bmp, export to workspace
1710-%
1711+% - Bitmap formats: png, tiff, jpg, bmp, export to workspace
1712+%
1713 % This function is especially suited to exporting figures for use in
1714 % publications and presentations, because of the high quality and
1715 % portability of media produced.
1716@@ -45,21 +52,20 @@
1717 % output file. For transparent background (and semi-transparent patch
1718 % objects), use the -transparent option or set the figure 'Color' property
1719 % to 'none'. To make axes transparent set the axes 'Color' property to
1720-% 'none'. Pdf, eps and png are the only file formats to support a
1721-% transparent background, whilst the png format alone supports transparency
1722-% of patch objects.
1723+% 'none'. PDF, EPS, TIF & PNG are the only formats that support a transparent
1724+% background; only TIF & PNG formats support transparency of patch objects.
1725 %
1726 % The choice of renderer (opengl, zbuffer or painters) has a large impact
1727-% on the quality of output. Whilst the default value (opengl for bitmaps,
1728-% painters for vector formats) generally gives good results, if you aren't
1729-% satisfied then try another renderer. Notes: 1) For vector formats (eps,
1730-% pdf), only painters generates vector graphics. 2) For bitmaps, only
1731+% on the quality of output. The default value (opengl for bitmaps, painters
1732+% for vector formats) generally gives good results, but if you aren't
1733+% satisfied then try another renderer. Notes: 1) For vector formats (EPS,
1734+% PDF), only painters generates vector graphics. 2) For bitmaps, only
1735 % opengl can render transparent patch objects correctly. 3) For bitmaps,
1736 % only painters will correctly scale line dash and dot lengths when
1737 % magnifying or anti-aliasing. 4) Fonts may be substitued with Courier when
1738 % using painters.
1739 %
1740-% When exporting to vector format (pdf & eps) and bitmap format using the
1741+% When exporting to vector format (PDF & EPS) and bitmap format using the
1742 % painters renderer, this function requires that ghostscript is installed
1743 % on your system. You can download this from:
1744 % http://www.ghostscript.com
1745@@ -67,7 +73,7 @@
1746 % suite of functions. You can download this from:
1747 % http://www.foolabs.com/xpdf
1748 %
1749-%IN:
1750+% Inputs:
1751 % filename - string containing the name (optionally including full or
1752 % relative path) of the file the figure is to be saved as. If
1753 % a path is not specified, the figure is saved in the current
1754@@ -82,11 +88,15 @@
1755 % of formats are valid.
1756 % -nocrop - option indicating that the borders of the output are not to
1757 % be cropped.
1758+% -c[<val>,<val>,<val>,<val>] - option indicating crop amounts. Must be
1759+% a 4-element vector of numeric values: [top,right,bottom,left]
1760+% where NaN/Inf indicate auto-cropping, 0 means no cropping,
1761+% and any other value mean cropping in pixel amounts.
1762 % -transparent - option indicating that the figure background is to be
1763-% made transparent (png, pdf and eps output only).
1764+% made transparent (png, pdf, tif and eps output only).
1765 % -m<val> - option where val indicates the factor to magnify the
1766 % on-screen figure pixel dimensions by when generating bitmap
1767-% outputs. Default: '-m1'.
1768+% outputs (does not affect vector formats). Default: '-m1'.
1769 % -r<val> - option val indicates the resolution (in pixels per inch) to
1770 % export bitmap and vector outputs at, keeping the dimensions
1771 % of the on-screen figure. Default: '-r864' (for vector output
1772@@ -105,9 +115,10 @@
1773 % -a1, -a2, -a3, -a4 - option indicating the amount of anti-aliasing to
1774 % use for bitmap outputs. '-a1' means no anti-
1775 % aliasing; '-a4' is the maximum amount (default).
1776-% -<renderer> - option to force a particular renderer (painters, opengl
1777-% or zbuffer) to be used over the default: opengl for
1778-% bitmaps; painters for vector formats.
1779+% -<renderer> - option to force a particular renderer (painters, opengl or
1780+% zbuffer). Default value: opengl for bitmap formats or
1781+% figures with patches and/or transparent annotations;
1782+% painters for vector formats without patches/transparencies.
1783 % -<colorspace> - option indicating which colorspace color figures should
1784 % be saved in: RGB (default), CMYK or gray. CMYK is only
1785 % supported in pdf, eps and tiff output.
1786@@ -118,29 +129,45 @@
1787 % default for pdf & eps. Note: lossless compression can
1788 % sometimes give a smaller file size than the default lossy
1789 % compression, depending on the type of images.
1790-% -p<val> - option to add a border of width val to eps and pdf files,
1791-% where val is in units of the intermediate eps file. Default:
1792-% 0 (i.e. no padding).
1793+% -p<val> - option to pad a border of width val to exported files, where
1794+% val is either a relative size with respect to cropped image
1795+% size (i.e. p=0.01 adds a 1% border). For EPS & PDF formats,
1796+% val can also be integer in units of 1/72" points (abs(val)>1).
1797+% val can be positive (padding) or negative (extra cropping).
1798+% If used, the -nocrop flag will be ignored, i.e. the image will
1799+% always be cropped and then padded. Default: 0 (i.e. no padding).
1800 % -append - option indicating that if the file (pdfs only) already
1801 % exists, the figure is to be appended as a new page, instead
1802 % of being overwritten (default).
1803 % -bookmark - option to indicate that a bookmark with the name of the
1804 % figure is to be created in the output file (pdf only).
1805-% handle - The handle of the figure, axes or uipanels (can be an array of
1806-% handles, but the objects must be in the same figure) to be
1807-% saved. Default: gcf.
1808+% -clipboard - option to save output as an image on the system clipboard.
1809+% Note: background transparency is not preserved in clipboard
1810+% -d<gs_option> - option to indicate a ghostscript setting. For example,
1811+% -dMaxBitmap=0 or -dNoOutputFonts (Ghostscript 9.15+).
1812+% -depsc - option to use EPS level-3 rather than the default level-2 print
1813+% device. This solves some bugs with Matlab's default -depsc2 device
1814+% such as discolored subplot lines on images (vector formats only).
1815+% -update - option to download and install the latest version of export_fig
1816+% -nofontswap - option to avoid font swapping. Font swapping is automatically
1817+% done in vector formats (only): 11 standard Matlab fonts are
1818+% replaced by the original figure fonts. This option prevents this.
1819+% handle - The handle of the figure, axes or uipanels (can be an array of
1820+% handles, but the objects must be in the same figure) to be
1821+% saved. Default: gcf.
1822 %
1823-%OUT:
1824-% im - MxNxC uint8 image array of the figure.
1825-% alpha - MxN single array of alphamatte values in range [0,1], for the
1826-% case when the background is transparent.
1827+% Outputs:
1828+% imageData - MxNxC uint8 image array of the exported image.
1829+% alpha - MxN single array of alphamatte values in the range [0,1],
1830+% for the case when the background is transparent.
1831 %
1832 % Some helpful examples and tips can be found at:
1833-% https://github.com/ojwoodford/export_fig
1834+% https://github.com/altmany/export_fig
1835 %
1836-% See also PRINT, SAVEAS.
1837+% See also PRINT, SAVEAS, ScreenCapture (on the Matlab File Exchange)
1838
1839-% Copyright (C) Oliver Woodford 2008-2014
1840+%{
1841+% Copyright (C) Oliver Woodford 2008-2014, Yair Altman 2015-
1842
1843 % The idea of using ghostscript is inspired by Peder Axensten's SAVEFIG
1844 % (fex id: 10889) which is itself inspired by EPS2PDF (fex id: 5782).
1845@@ -161,639 +188,1095 @@
1846 % fix anyway.
1847 % Thanks to Tammy Threadgill for reporting a bug where an axes is not
1848 % isolated from gui objects.
1849-
1850+%}
1851+%{
1852 % 23/02/12: Ensure that axes limits don't change during printing
1853-% 14/03/12: Fix bug in fixing the axes limits (thanks to Tobias Lamour for
1854-% reporting it).
1855-% 02/05/12: Incorporate patch of Petr Nechaev (many thanks), enabling
1856-% bookmarking of figures in pdf files.
1857-% 09/05/12: Incorporate patch of Arcelia Arrieta (many thanks), to keep
1858-% tick marks fixed.
1859-% 12/12/12: Add support for isolating uipanels. Thanks to michael for
1860-% suggesting it.
1861-% 25/09/13: Add support for changing resolution in vector formats. Thanks
1862-% to Jan Jaap Meijer for suggesting it.
1863-% 07/05/14: Add support for '~' at start of path. Thanks to Sally Warner
1864-% for suggesting it.
1865+% 14/03/12: Fix bug in fixing the axes limits (thanks to Tobias Lamour for reporting it).
1866+% 02/05/12: Incorporate patch of Petr Nechaev (many thanks), enabling bookmarking of figures in pdf files.
1867+% 09/05/12: Incorporate patch of Arcelia Arrieta (many thanks), to keep tick marks fixed.
1868+% 12/12/12: Add support for isolating uipanels. Thanks to michael for suggesting it.
1869+% 25/09/13: Add support for changing resolution in vector formats. Thanks to Jan Jaap Meijer for suggesting it.
1870+% 07/05/14: Add support for '~' at start of path. Thanks to Sally Warner for suggesting it.
1871+% 24/02/15: Fix Matlab R2014b bug (issue #34): plot markers are not displayed when ZLimMode='manual'
1872+% 25/02/15: Fix issue #4 (using HG2 on R2014a and earlier)
1873+% 25/02/15: Fix issue #21 (bold TeX axes labels/titles in R2014b)
1874+% 26/02/15: If temp dir is not writable, use the user-specified folder for temporary EPS/PDF files (Javier Paredes)
1875+% 27/02/15: Modified repository URL from github.com/ojwoodford to /altmany
1876+% Indented main function
1877+% Added top-level try-catch block to display useful workarounds
1878+% 28/02/15: Enable users to specify optional ghostscript options (issue #36)
1879+% 06/03/15: Improved image padding & cropping thanks to Oscar Hartogensis
1880+% 26/03/15: Fixed issue #49 (bug with transparent grayscale images); fixed out-of-memory issue
1881+% 26/03/15: Fixed issue #42: non-normalized annotations on HG1
1882+% 26/03/15: Fixed issue #46: Ghostscript crash if figure units <> pixels
1883+% 27/03/15: Fixed issue #39: bad export of transparent annotations/patches
1884+% 28/03/15: Fixed issue #50: error on some Matlab versions with the fix for issue #42
1885+% 29/03/15: Fixed issue #33: bugs in Matlab's print() function with -cmyk
1886+% 29/03/15: Improved processing of input args (accept space between param name & value, related to issue #51)
1887+% 30/03/15: When exporting *.fig files, then saveas *.fig if figure is open, otherwise export the specified fig file
1888+% 30/03/15: Fixed edge case bug introduced yesterday (commit #ae1755bd2e11dc4e99b95a7681f6e211b3fa9358)
1889+% 09/04/15: Consolidated header comment sections; initialize output vars only if requested (nargout>0)
1890+% 14/04/15: Workaround for issue #45: lines in image subplots are exported in invalid color
1891+% 15/04/15: Fixed edge-case in parsing input parameters; fixed help section to show the -depsc option (issue #45)
1892+% 21/04/15: Bug fix: Ghostscript croaks on % chars in output PDF file (reported by Sven on FEX page, 15-Jul-2014)
1893+% 22/04/15: Bug fix: Pdftops croaks on relative paths (reported by Tintin Milou on FEX page, 19-Jan-2015)
1894+% 04/05/15: Merged fix #63 (Kevin Mattheus Moerman): prevent tick-label changes during export
1895+% 07/05/15: Partial fix for issue #65: PDF export used painters rather than opengl renderer (thanks Nguyenr)
1896+% 08/05/15: Fixed issue #65: bad PDF append since commit #e9f3cdf 21/04/15 (thanks Robert Nguyen)
1897+% 12/05/15: Fixed issue #67: exponent labels cropped in export, since fix #63 (04/05/15)
1898+% 28/05/15: Fixed issue #69: set non-bold label font only if the string contains symbols (\beta etc.), followup to issue #21
1899+% 29/05/15: Added informative error message in case user requested SVG output (issue #72)
1900+% 09/06/15: Fixed issue #58: -transparent removed anti-aliasing when exporting to PNG
1901+% 19/06/15: Added -update option to download and install the latest version of export_fig
1902+% 07/07/15: Added -nofontswap option to avoid font-swapping in EPS/PDF
1903+% 16/07/15: Fixed problem with anti-aliasing on old Matlab releases
1904+% 11/09/15: Fixed issue #103: magnification must never become negative; also fixed reported error msg in parsing input params
1905+% 26/09/15: Alert if trying to export transparent patches/areas to non-PNG outputs (issue #108)
1906+% 04/10/15: Do not suggest workarounds for certain errors that have already been handled previously
1907+% 01/11/15: Fixed issue #112: use same renderer in print2eps as export_fig (thanks to Jesús Pestana Puerta)
1908+% 10/11/15: Custom GS installation webpage for MacOS. Thanks to Andy Hueni via FEX
1909+% 19/11/15: Fixed clipboard export in R2015b (thanks to Dan K via FEX)
1910+% 21/02/16: Added -c option for indicating specific crop amounts (idea by Cedric Noordam on FEX)
1911+% 08/05/16: Added message about possible error reason when groot.Units~=pixels (issue #149)
1912+% 17/05/16: Fixed case of image YData containing more than 2 elements (issue #151)
1913+% 08/08/16: Enabled exporting transparency to TIF, in addition to PNG/PDF (issue #168)
1914+%}
1915
1916-function [im, alpha] = export_fig(varargin)
1917-% Make sure the figure is rendered correctly _now_ so that properties like
1918-% axes limits are up-to-date.
1919-drawnow;
1920-% Parse the input arguments
1921-[fig, options] = parse_args(nargout, varargin{:});
1922-% Isolate the subplot, if it is one
1923-cls = all(ismember(get(fig, 'Type'), {'axes', 'uipanel'}));
1924-if cls
1925- % Given handles of one or more axes, so isolate them from the rest
1926- fig = isolate_axes(fig);
1927-else
1928- % Check we have a figure
1929- if ~isequal(get(fig, 'Type'), 'figure');
1930- error('Handle must be that of a figure, axes or uipanel');
1931+ if nargout
1932+ [imageData, alpha] = deal([]);
1933 end
1934- % Get the old InvertHardcopy mode
1935- old_mode = get(fig, 'InvertHardcopy');
1936-end
1937-% Hack the font units where necessary (due to a font rendering bug in
1938-% print?). This may not work perfectly in all cases. Also it can change the
1939-% figure layout if reverted, so use a copy.
1940-magnify = options.magnify * options.aa_factor;
1941-if isbitmap(options) && magnify ~= 1
1942- fontu = findobj(fig, 'FontUnits', 'normalized');
1943- if ~isempty(fontu)
1944- % Some normalized font units found
1945- if ~cls
1946- fig = copyfig(fig);
1947- set(fig, 'Visible', 'off');
1948- fontu = findobj(fig, 'FontUnits', 'normalized');
1949- cls = true;
1950+ hadError = false;
1951+ displaySuggestedWorkarounds = true;
1952+
1953+ % Ensure the figure is rendered correctly _now_ so that properties like axes limits are up-to-date
1954+ drawnow;
1955+ pause(0.05); % this solves timing issues with Java Swing's EDT (http://undocumentedmatlab.com/blog/solving-a-matlab-hang-problem)
1956+
1957+ % Parse the input arguments
1958+ fig = get(0, 'CurrentFigure');
1959+ [fig, options] = parse_args(nargout, fig, varargin{:});
1960+
1961+ % Ensure that we have a figure handle
1962+ if isequal(fig,-1)
1963+ return; % silent bail-out
1964+ elseif isempty(fig)
1965+ error('No figure found');
1966+ end
1967+
1968+ % Isolate the subplot, if it is one
1969+ cls = all(ismember(get(fig, 'Type'), {'axes', 'uipanel'}));
1970+ if cls
1971+ % Given handles of one or more axes, so isolate them from the rest
1972+ fig = isolate_axes(fig);
1973+ else
1974+ % Check we have a figure
1975+ if ~isequal(get(fig, 'Type'), 'figure');
1976+ error('Handle must be that of a figure, axes or uipanel');
1977 end
1978- set(fontu, 'FontUnits', 'points');
1979+ % Get the old InvertHardcopy mode
1980+ old_mode = get(fig, 'InvertHardcopy');
1981 end
1982-end
1983-% MATLAB "feature": axes limits and tick marks can change when printing
1984-Hlims = findall(fig, 'Type', 'axes');
1985-if ~cls
1986- % Record the old axes limit and tick modes
1987- Xlims = make_cell(get(Hlims, 'XLimMode'));
1988- Ylims = make_cell(get(Hlims, 'YLimMode'));
1989- Zlims = make_cell(get(Hlims, 'ZLimMode'));
1990- Xtick = make_cell(get(Hlims, 'XTickMode'));
1991- Ytick = make_cell(get(Hlims, 'YTickMode'));
1992- Ztick = make_cell(get(Hlims, 'ZTickMode'));
1993-end
1994-% Set all axes limit and tick modes to manual, so the limits and ticks can't change
1995-set(Hlims, 'XLimMode', 'manual', 'YLimMode', 'manual', 'ZLimMode', 'manual');
1996-set_tick_mode(Hlims, 'X');
1997-set_tick_mode(Hlims, 'Y');
1998-set_tick_mode(Hlims, 'Z');
1999-% Set to print exactly what is there
2000-set(fig, 'InvertHardcopy', 'off');
2001-% Set the renderer
2002-switch options.renderer
2003- case 1
2004- renderer = '-opengl';
2005- case 2
2006- renderer = '-zbuffer';
2007- case 3
2008- renderer = '-painters';
2009- otherwise
2010- renderer = '-opengl'; % Default for bitmaps
2011-end
2012-% Do the bitmap formats first
2013-if isbitmap(options)
2014- % Get the background colour
2015- if options.transparent && (options.png || options.alpha)
2016- % Get out an alpha channel
2017- % MATLAB "feature": black colorbar axes can change to white and vice versa!
2018- hCB = findobj(fig, 'Type', 'axes', 'Tag', 'Colorbar');
2019- if isempty(hCB)
2020- yCol = [];
2021- xCol = [];
2022- else
2023- yCol = get(hCB, 'YColor');
2024- xCol = get(hCB, 'XColor');
2025- if iscell(yCol)
2026- yCol = cell2mat(yCol);
2027- xCol = cell2mat(xCol);
2028+
2029+ % Hack the font units where necessary (due to a font rendering bug in print?).
2030+ % This may not work perfectly in all cases.
2031+ % Also it can change the figure layout if reverted, so use a copy.
2032+ magnify = options.magnify * options.aa_factor;
2033+ if isbitmap(options) && magnify ~= 1
2034+ fontu = findall(fig, 'FontUnits', 'normalized');
2035+ if ~isempty(fontu)
2036+ % Some normalized font units found
2037+ if ~cls
2038+ fig = copyfig(fig);
2039+ set(fig, 'Visible', 'off');
2040+ fontu = findall(fig, 'FontUnits', 'normalized');
2041+ cls = true;
2042 end
2043- yCol = sum(yCol, 2);
2044- xCol = sum(xCol, 2);
2045+ set(fontu, 'FontUnits', 'points');
2046 end
2047- % MATLAB "feature": apparently figure size can change when changing
2048- % colour in -nodisplay mode
2049- pos = get(fig, 'Position');
2050- % Set the background colour to black, and set size in case it was
2051- % changed internally
2052- tcol = get(fig, 'Color');
2053- set(fig, 'Color', 'k', 'Position', pos);
2054- % Correct the colorbar axes colours
2055- set(hCB(yCol==0), 'YColor', [0 0 0]);
2056- set(hCB(xCol==0), 'XColor', [0 0 0]);
2057- % Print large version to array
2058- B = print2array(fig, magnify, renderer);
2059- % Downscale the image
2060- B = downsize(single(B), options.aa_factor);
2061- % Set background to white (and set size)
2062- set(fig, 'Color', 'w', 'Position', pos);
2063- % Correct the colorbar axes colours
2064- set(hCB(yCol==3), 'YColor', [1 1 1]);
2065- set(hCB(xCol==3), 'XColor', [1 1 1]);
2066- % Print large version to array
2067- A = print2array(fig, magnify, renderer);
2068- % Downscale the image
2069- A = downsize(single(A), options.aa_factor);
2070- % Set the background colour (and size) back to normal
2071- set(fig, 'Color', tcol, 'Position', pos);
2072- % Compute the alpha map
2073- alpha = round(sum(B - A, 3)) / (255 * 3) + 1;
2074- A = alpha;
2075- A(A==0) = 1;
2076- A = B ./ A(:,:,[1 1 1]);
2077- clear B
2078- % Convert to greyscale
2079- if options.colourspace == 2
2080- A = rgb2grey(A);
2081- end
2082- A = uint8(A);
2083- % Crop the background
2084- if options.crop
2085- [alpha, v] = crop_borders(alpha, 0, 1);
2086- A = A(v(1):v(2),v(3):v(4),:);
2087- end
2088- if options.png
2089- % Compute the resolution
2090- res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
2091- % Save the png
2092- imwrite(A, [options.name '.png'], 'Alpha', double(alpha), 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
2093- % Clear the png bit
2094- options.png = false;
2095- end
2096- % Return only one channel for greyscale
2097- if isbitmap(options)
2098- A = check_greyscale(A);
2099- end
2100- if options.alpha
2101- % Store the image
2102- im = A;
2103- % Clear the alpha bit
2104- options.alpha = false;
2105- end
2106- % Get the non-alpha image
2107- if isbitmap(options)
2108- alph = alpha(:,:,ones(1, size(A, 3)));
2109- A = uint8(single(A) .* alph + 255 * (1 - alph));
2110- clear alph
2111- end
2112- if options.im
2113- % Store the new image
2114- im = A;
2115- end
2116- else
2117- % Print large version to array
2118- if options.transparent
2119- % MATLAB "feature": apparently figure size can change when changing
2120- % colour in -nodisplay mode
2121- pos = get(fig, 'Position');
2122- tcol = get(fig, 'Color');
2123- set(fig, 'Color', 'w', 'Position', pos);
2124- A = print2array(fig, magnify, renderer);
2125- set(fig, 'Color', tcol, 'Position', pos);
2126- tcol = 255;
2127- else
2128- [A, tcol] = print2array(fig, magnify, renderer);
2129- end
2130- % Crop the background
2131- if options.crop
2132- A = crop_borders(A, tcol, 1);
2133- end
2134- % Downscale the image
2135- A = downsize(A, options.aa_factor);
2136- if options.colourspace == 2
2137- % Convert to greyscale
2138- A = rgb2grey(A);
2139- else
2140- % Return only one channel for greyscale
2141- A = check_greyscale(A);
2142- end
2143- % Outputs
2144- if options.im
2145- im = A;
2146- end
2147- if options.alpha
2148- im = A;
2149- alpha = zeros(size(A, 1), size(A, 2), 'single');
2150- end
2151 end
2152- % Save the images
2153- if options.png
2154- res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
2155- imwrite(A, [options.name '.png'], 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
2156- end
2157- if options.bmp
2158- imwrite(A, [options.name '.bmp']);
2159- end
2160- % Save jpeg with given quality
2161- if options.jpg
2162- quality = options.quality;
2163- if isempty(quality)
2164- quality = 95;
2165+
2166+ try
2167+ % MATLAB "feature": axes limits and tick marks can change when printing
2168+ Hlims = findall(fig, 'Type', 'axes');
2169+ if ~cls
2170+ % Record the old axes limit and tick modes
2171+ Xlims = make_cell(get(Hlims, 'XLimMode'));
2172+ Ylims = make_cell(get(Hlims, 'YLimMode'));
2173+ Zlims = make_cell(get(Hlims, 'ZLimMode'));
2174+ Xtick = make_cell(get(Hlims, 'XTickMode'));
2175+ Ytick = make_cell(get(Hlims, 'YTickMode'));
2176+ Ztick = make_cell(get(Hlims, 'ZTickMode'));
2177+ Xlabel = make_cell(get(Hlims, 'XTickLabelMode'));
2178+ Ylabel = make_cell(get(Hlims, 'YTickLabelMode'));
2179+ Zlabel = make_cell(get(Hlims, 'ZTickLabelMode'));
2180 end
2181- if quality > 100
2182- imwrite(A, [options.name '.jpg'], 'Mode', 'lossless');
2183- else
2184- imwrite(A, [options.name '.jpg'], 'Quality', quality);
2185+
2186+ % Set all axes limit and tick modes to manual, so the limits and ticks can't change
2187+ % Fix Matlab R2014b bug (issue #34): plot markers are not displayed when ZLimMode='manual'
2188+ set(Hlims, 'XLimMode', 'manual', 'YLimMode', 'manual');
2189+ set_tick_mode(Hlims, 'X');
2190+ set_tick_mode(Hlims, 'Y');
2191+ if ~using_hg2(fig)
2192+ set(Hlims,'ZLimMode', 'manual');
2193+ set_tick_mode(Hlims, 'Z');
2194 end
2195+ catch
2196+ % ignore - fix issue #4 (using HG2 on R2014a and earlier)
2197 end
2198- % Save tif images in cmyk if wanted (and possible)
2199- if options.tif
2200- if options.colourspace == 1 && size(A, 3) == 3
2201- A = double(255 - A);
2202- K = min(A, [], 3);
2203- K_ = 255 ./ max(255 - K, 1);
2204- C = (A(:,:,1) - K) .* K_;
2205- M = (A(:,:,2) - K) .* K_;
2206- Y = (A(:,:,3) - K) .* K_;
2207- A = uint8(cat(3, C, M, Y, K));
2208- clear C M Y K K_
2209+
2210+ % Fix issue #21 (bold TeX axes labels/titles in R2014b when exporting to EPS/PDF)
2211+ try
2212+ if using_hg2(fig) && isvector(options)
2213+ % Set the FontWeight of axes labels/titles to 'normal'
2214+ % Fix issue #69: set non-bold font only if the string contains symbols (\beta etc.)
2215+ texLabels = findall(fig, 'type','text', 'FontWeight','bold');
2216+ symbolIdx = ~cellfun('isempty',strfind({texLabels.String},'\'));
2217+ set(texLabels(symbolIdx), 'FontWeight','normal');
2218 end
2219- append_mode = {'overwrite', 'append'};
2220- imwrite(A, [options.name '.tif'], 'Resolution', options.magnify*get(0, 'ScreenPixelsPerInch'), 'WriteMode', append_mode{options.append+1});
2221+ catch
2222+ % ignore
2223 end
2224-end
2225-% Now do the vector formats
2226-if isvector(options)
2227- % Set the default renderer to painters
2228- if ~options.renderer
2229- renderer = '-painters';
2230- end
2231- % Generate some filenames
2232- tmp_nam = [tempname '.eps'];
2233- if options.pdf
2234- pdf_nam = [options.name '.pdf'];
2235- else
2236- pdf_nam = [tempname '.pdf'];
2237- end
2238- % Generate the options for print
2239- p2eArgs = {renderer, sprintf('-r%d', options.resolution)};
2240- if options.colourspace == 1
2241- p2eArgs = [p2eArgs {'-cmyk'}];
2242- end
2243- if ~options.crop
2244- p2eArgs = [p2eArgs {'-loose'}];
2245- end
2246+
2247+ % Fix issue #42: non-normalized annotations on HG1 (internal Matlab bug)
2248+ annotationHandles = [];
2249 try
2250- % Generate an eps
2251- print2eps(tmp_nam, fig, options.bb_padding, p2eArgs{:});
2252- % Remove the background, if desired
2253- if options.transparent && ~isequal(get(fig, 'Color'), 'none')
2254- eps_remove_background(tmp_nam, 1 + using_hg2(fig));
2255- end
2256- % Add a bookmark to the PDF if desired
2257- if options.bookmark
2258- fig_nam = get(fig, 'Name');
2259- if isempty(fig_nam)
2260- warning('export_fig:EmptyBookmark', 'Bookmark requested for figure with no name. Bookmark will be empty.');
2261+ if ~using_hg2(fig)
2262+ annotationHandles = findall(fig,'Type','hggroup','-and','-property','Units','-and','-not','Units','norm');
2263+ try % suggested by Jesús Pestana Puerta (jespestana) 30/9/2015
2264+ originalUnits = get(annotationHandles,'Units');
2265+ set(annotationHandles,'Units','norm');
2266+ catch
2267 end
2268- add_bookmark(tmp_nam, fig_nam);
2269 end
2270- % Generate a pdf
2271- eps2pdf(tmp_nam, pdf_nam, 1, options.append, options.colourspace==2, options.quality);
2272- catch ex
2273- % Delete the eps
2274- delete(tmp_nam);
2275- rethrow(ex);
2276+ catch
2277+ % should never happen, but ignore in any case - issue #50
2278 end
2279- % Delete the eps
2280- delete(tmp_nam);
2281- if options.eps
2282- try
2283- % Generate an eps from the pdf
2284- pdf2eps(pdf_nam, [options.name '.eps']);
2285- catch ex
2286- if ~options.pdf
2287- % Delete the pdf
2288- delete(pdf_nam);
2289- end
2290- rethrow(ex);
2291+
2292+ % Fix issue #46: Ghostscript crash if figure units <> pixels
2293+ oldFigUnits = get(fig,'Units');
2294+ set(fig,'Units','pixels');
2295+
2296+ % Set to print exactly what is there
2297+ set(fig, 'InvertHardcopy', 'off');
2298+ % Set the renderer
2299+ switch options.renderer
2300+ case 1
2301+ renderer = '-opengl';
2302+ case 2
2303+ renderer = '-zbuffer';
2304+ case 3
2305+ renderer = '-painters';
2306+ otherwise
2307+ renderer = '-opengl'; % Default for bitmaps
2308+ end
2309+
2310+ % Handle transparent patches
2311+ hasTransparency = ~isempty(findall(fig,'-property','FaceAlpha','-and','-not','FaceAlpha',1));
2312+ hasPatches = ~isempty(findall(fig,'type','patch'));
2313+ if hasTransparency
2314+ % Alert if trying to export transparent patches/areas to non-supported outputs (issue #108)
2315+ % http://www.mathworks.com/matlabcentral/answers/265265-can-export_fig-or-else-draw-vector-graphics-with-transparent-surfaces
2316+ % TODO - use transparency when exporting to PDF by not passing via print2eps
2317+ msg = 'export_fig currently supports transparent patches/areas only in PNG output. ';
2318+ if options.pdf
2319+ warning('export_fig:transparency', '%s\nTo export transparent patches/areas to PDF, use the print command:\n print(gcf, ''-dpdf'', ''%s.pdf'');', msg, options.name);
2320+ elseif ~options.png && ~options.tif % issue #168
2321+ warning('export_fig:transparency', '%s\nTo export the transparency correctly, try using the ScreenCapture utility on the Matlab File Exchange: http://bit.ly/1QFrBip', msg);
2322 end
2323- if ~options.pdf
2324- % Delete the pdf
2325- delete(pdf_nam);
2326- end
2327 end
2328-end
2329-if cls
2330- % Close the created figure
2331- close(fig);
2332-else
2333- % Reset the hardcopy mode
2334- set(fig, 'InvertHardcopy', old_mode);
2335- % Reset the axes limit and tick modes
2336- for a = 1:numel(Hlims)
2337- set(Hlims(a), 'XLimMode', Xlims{a}, 'YLimMode', Ylims{a}, 'ZLimMode', Zlims{a}, 'XTickMode', Xtick{a}, 'YTickMode', Ytick{a}, 'ZTickMode', Ztick{a});
2338- end
2339-end
2340-end
2341
2342-function [fig, options] = parse_args(nout, varargin)
2343-% Parse the input arguments
2344-% Set the defaults
2345-fig = get(0, 'CurrentFigure');
2346-options = struct('name', 'export_fig_out', ...
2347- 'crop', true, ...
2348- 'transparent', false, ...
2349- 'renderer', 0, ... % 0: default, 1: OpenGL, 2: ZBuffer, 3: Painters
2350- 'pdf', false, ...
2351- 'eps', false, ...
2352- 'png', false, ...
2353- 'tif', false, ...
2354- 'jpg', false, ...
2355- 'bmp', false, ...
2356- 'colourspace', 0, ... % 0: RGB/gray, 1: CMYK, 2: gray
2357- 'append', false, ...
2358- 'im', nout == 1, ...
2359- 'alpha', nout == 2, ...
2360- 'aa_factor', 0, ...
2361- 'bb_padding', 0, ...
2362- 'magnify', [], ...
2363- 'resolution', [], ...
2364- 'bookmark', false, ...
2365- 'quality', []);
2366-native = false; % Set resolution to native of an image
2367+ try
2368+ % Do the bitmap formats first
2369+ if isbitmap(options)
2370+ if abs(options.bb_padding) > 1
2371+ displaySuggestedWorkarounds = false;
2372+ error('For bitmap output (png,jpg,tif,bmp) the padding value (-p) must be between -1<p<1')
2373+ end
2374+ % Get the background colour
2375+ if options.transparent && (options.png || options.alpha)
2376+ % Get out an alpha channel
2377+ % MATLAB "feature": black colorbar axes can change to white and vice versa!
2378+ hCB = findall(fig, 'Type','axes', 'Tag','Colorbar');
2379+ if isempty(hCB)
2380+ yCol = [];
2381+ xCol = [];
2382+ else
2383+ yCol = get(hCB, 'YColor');
2384+ xCol = get(hCB, 'XColor');
2385+ if iscell(yCol)
2386+ yCol = cell2mat(yCol);
2387+ xCol = cell2mat(xCol);
2388+ end
2389+ yCol = sum(yCol, 2);
2390+ xCol = sum(xCol, 2);
2391+ end
2392+ % MATLAB "feature": apparently figure size can change when changing
2393+ % colour in -nodisplay mode
2394+ pos = get(fig, 'Position');
2395+ % Set the background colour to black, and set size in case it was
2396+ % changed internally
2397+ tcol = get(fig, 'Color');
2398+ set(fig, 'Color', 'k', 'Position', pos);
2399+ % Correct the colorbar axes colours
2400+ set(hCB(yCol==0), 'YColor', [0 0 0]);
2401+ set(hCB(xCol==0), 'XColor', [0 0 0]);
2402
2403-% Go through the other arguments
2404-for a = 1:nargin-1
2405- if all(ishandle(varargin{a}))
2406- fig = varargin{a};
2407- elseif ischar(varargin{a}) && ~isempty(varargin{a})
2408- if varargin{a}(1) == '-'
2409- switch lower(varargin{a}(2:end))
2410- case 'nocrop'
2411- options.crop = false;
2412- case {'trans', 'transparent'}
2413- options.transparent = true;
2414- case 'opengl'
2415- options.renderer = 1;
2416- case 'zbuffer'
2417- options.renderer = 2;
2418- case 'painters'
2419- options.renderer = 3;
2420- case 'pdf'
2421- options.pdf = true;
2422- case 'eps'
2423- options.eps = true;
2424- case 'png'
2425- options.png = true;
2426- case {'tif', 'tiff'}
2427- options.tif = true;
2428- case {'jpg', 'jpeg'}
2429- options.jpg = true;
2430- case 'bmp'
2431- options.bmp = true;
2432- case 'rgb'
2433- options.colourspace = 0;
2434- case 'cmyk'
2435- options.colourspace = 1;
2436- case {'gray', 'grey'}
2437- options.colourspace = 2;
2438- case {'a1', 'a2', 'a3', 'a4'}
2439- options.aa_factor = str2double(varargin{a}(3));
2440- case 'append'
2441- options.append = true;
2442- case 'bookmark'
2443- options.bookmark = true;
2444- case 'native'
2445- native = true;
2446- otherwise
2447- val = str2double(regexp(varargin{a}, '(?<=-(m|M|r|R|q|Q|p|P))-?\d*.?\d+', 'match'));
2448- if ~isscalar(val)
2449- error('option %s not recognised', varargin{a});
2450+ % The following code might cause out-of-memory errors
2451+ try
2452+ % Print large version to array
2453+ B = print2array(fig, magnify, renderer);
2454+ % Downscale the image
2455+ B = downsize(single(B), options.aa_factor);
2456+ catch
2457+ % This is more conservative in memory, but kills transparency (issue #58)
2458+ B = single(print2array(fig, magnify/options.aa_factor, renderer));
2459+ end
2460+
2461+ % Set background to white (and set size)
2462+ set(fig, 'Color', 'w', 'Position', pos);
2463+ % Correct the colorbar axes colours
2464+ set(hCB(yCol==3), 'YColor', [1 1 1]);
2465+ set(hCB(xCol==3), 'XColor', [1 1 1]);
2466+
2467+ % The following code might cause out-of-memory errors
2468+ try
2469+ % Print large version to array
2470+ A = print2array(fig, magnify, renderer);
2471+ % Downscale the image
2472+ A = downsize(single(A), options.aa_factor);
2473+ catch
2474+ % This is more conservative in memory, but kills transparency (issue #58)
2475+ A = single(print2array(fig, magnify/options.aa_factor, renderer));
2476+ end
2477+
2478+ % Set the background colour (and size) back to normal
2479+ set(fig, 'Color', tcol, 'Position', pos);
2480+ % Compute the alpha map
2481+ alpha = round(sum(B - A, 3)) / (255 * 3) + 1;
2482+ A = alpha;
2483+ A(A==0) = 1;
2484+ A = B ./ A(:,:,[1 1 1]);
2485+ clear B
2486+ % Convert to greyscale
2487+ if options.colourspace == 2
2488+ A = rgb2grey(A);
2489+ end
2490+ A = uint8(A);
2491+ % Crop the background
2492+ if options.crop
2493+ %[alpha, v] = crop_borders(alpha, 0, 1, options.crop_amounts);
2494+ %A = A(v(1):v(2),v(3):v(4),:);
2495+ [alpha, vA, vB] = crop_borders(alpha, 0, options.bb_padding, options.crop_amounts);
2496+ if ~any(isnan(vB)) % positive padding
2497+ B = repmat(uint8(zeros(1,1,size(A,3))),size(alpha));
2498+ B(vB(1):vB(2), vB(3):vB(4), :) = A(vA(1):vA(2), vA(3):vA(4), :); % ADDED BY OH
2499+ A = B;
2500+ else % negative padding
2501+ A = A(vA(1):vA(2), vA(3):vA(4), :);
2502 end
2503- switch lower(varargin{a}(2))
2504- case 'm'
2505- options.magnify = val;
2506- case 'r'
2507- options.resolution = val;
2508- case 'q'
2509- options.quality = max(val, 0);
2510- case 'p'
2511- options.bb_padding = val;
2512+ end
2513+ if options.png
2514+ % Compute the resolution
2515+ res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
2516+ % Save the png
2517+ imwrite(A, [options.name '.png'], 'Alpha', double(alpha), 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
2518+ % Clear the png bit
2519+ options.png = false;
2520+ end
2521+ % Return only one channel for greyscale
2522+ if isbitmap(options)
2523+ A = check_greyscale(A);
2524+ end
2525+ if options.alpha
2526+ % Store the image
2527+ imageData = A;
2528+ % Clear the alpha bit
2529+ options.alpha = false;
2530+ end
2531+ % Get the non-alpha image
2532+ if isbitmap(options)
2533+ alph = alpha(:,:,ones(1, size(A, 3)));
2534+ A = uint8(single(A) .* alph + 255 * (1 - alph));
2535+ clear alph
2536+ end
2537+ if options.im
2538+ % Store the new image
2539+ imageData = A;
2540+ end
2541+ else
2542+ % Print large version to array
2543+ if options.transparent
2544+ % MATLAB "feature": apparently figure size can change when changing
2545+ % colour in -nodisplay mode
2546+ pos = get(fig, 'Position');
2547+ tcol = get(fig, 'Color');
2548+ set(fig, 'Color', 'w', 'Position', pos);
2549+ A = print2array(fig, magnify, renderer);
2550+ set(fig, 'Color', tcol, 'Position', pos);
2551+ tcol = 255;
2552+ else
2553+ [A, tcol] = print2array(fig, magnify, renderer);
2554+ end
2555+ % Crop the background
2556+ if options.crop
2557+ A = crop_borders(A, tcol, options.bb_padding, options.crop_amounts);
2558+ end
2559+ % Downscale the image
2560+ A = downsize(A, options.aa_factor);
2561+ if options.colourspace == 2
2562+ % Convert to greyscale
2563+ A = rgb2grey(A);
2564+ else
2565+ % Return only one channel for greyscale
2566+ A = check_greyscale(A);
2567+ end
2568+ % Outputs
2569+ if options.im
2570+ imageData = A;
2571+ end
2572+ if options.alpha
2573+ imageData = A;
2574+ alpha = zeros(size(A, 1), size(A, 2), 'single');
2575+ end
2576+ end
2577+ % Save the images
2578+ if options.png
2579+ res = options.magnify * get(0, 'ScreenPixelsPerInch') / 25.4e-3;
2580+ imwrite(A, [options.name '.png'], 'ResolutionUnit', 'meter', 'XResolution', res, 'YResolution', res);
2581+ end
2582+ if options.bmp
2583+ imwrite(A, [options.name '.bmp']);
2584+ end
2585+ % Save jpeg with given quality
2586+ if options.jpg
2587+ quality = options.quality;
2588+ if isempty(quality)
2589+ quality = 95;
2590+ end
2591+ if quality > 100
2592+ imwrite(A, [options.name '.jpg'], 'Mode', 'lossless');
2593+ else
2594+ imwrite(A, [options.name '.jpg'], 'Quality', quality);
2595+ end
2596+ end
2597+ % Save tif images in cmyk if wanted (and possible)
2598+ if options.tif
2599+ if options.colourspace == 1 && size(A, 3) == 3
2600+ A = double(255 - A);
2601+ K = min(A, [], 3);
2602+ K_ = 255 ./ max(255 - K, 1);
2603+ C = (A(:,:,1) - K) .* K_;
2604+ M = (A(:,:,2) - K) .* K_;
2605+ Y = (A(:,:,3) - K) .* K_;
2606+ A = uint8(cat(3, C, M, Y, K));
2607+ clear C M Y K K_
2608+ end
2609+ append_mode = {'overwrite', 'append'};
2610+ imwrite(A, [options.name '.tif'], 'Resolution', options.magnify*get(0, 'ScreenPixelsPerInch'), 'WriteMode', append_mode{options.append+1});
2611+ end
2612+ end
2613+
2614+ % Now do the vector formats
2615+ if isvector(options)
2616+ % Set the default renderer to painters
2617+ if ~options.renderer
2618+ if hasTransparency || hasPatches
2619+ % This is *MUCH* slower, but more accurate for patches and transparent annotations (issue #39)
2620+ renderer = '-painters';
2621+ else
2622+ renderer = '-painters';
2623+ end
2624+ end
2625+ options.rendererStr = renderer; % fix for issue #112
2626+ % Generate some filenames
2627+ tmp_nam = [tempname '.eps'];
2628+ try
2629+ % Ensure that the temp dir is writable (Javier Paredes 30/1/15)
2630+ fid = fopen(tmp_nam,'w');
2631+ fwrite(fid,1);
2632+ fclose(fid);
2633+ delete(tmp_nam);
2634+ isTempDirOk = true;
2635+ catch
2636+ % Temp dir is not writable, so use the user-specified folder
2637+ [dummy,fname,fext] = fileparts(tmp_nam); %#ok<ASGLU>
2638+ fpath = fileparts(options.name);
2639+ tmp_nam = fullfile(fpath,[fname fext]);
2640+ isTempDirOk = false;
2641+ end
2642+ if isTempDirOk
2643+ pdf_nam_tmp = [tempname '.pdf'];
2644+ else
2645+ pdf_nam_tmp = fullfile(fpath,[fname '.pdf']);
2646+ end
2647+ if options.pdf
2648+ pdf_nam = [options.name '.pdf'];
2649+ try copyfile(pdf_nam, pdf_nam_tmp, 'f'); catch, end % fix for issue #65
2650+ else
2651+ pdf_nam = pdf_nam_tmp;
2652+ end
2653+ % Generate the options for print
2654+ p2eArgs = {renderer, sprintf('-r%d', options.resolution)};
2655+ if options.colourspace == 1 % CMYK
2656+ % Issue #33: due to internal bugs in Matlab's print() function, we can't use its -cmyk option
2657+ %p2eArgs{end+1} = '-cmyk';
2658+ end
2659+ if ~options.crop
2660+ % Issue #56: due to internal bugs in Matlab's print() function, we can't use its internal cropping mechanism,
2661+ % therefore we always use '-loose' (in print2eps.m) and do our own cropping (in crop_borders)
2662+ %p2eArgs{end+1} = '-loose';
2663+ end
2664+ if any(strcmpi(varargin,'-depsc'))
2665+ % Issue #45: lines in image subplots are exported in invalid color.
2666+ % The workaround is to use the -depsc parameter instead of the default -depsc2
2667+ p2eArgs{end+1} = '-depsc';
2668+ end
2669+ try
2670+ % Generate an eps
2671+ print2eps(tmp_nam, fig, options, p2eArgs{:});
2672+ % Remove the background, if desired
2673+ if options.transparent && ~isequal(get(fig, 'Color'), 'none')
2674+ eps_remove_background(tmp_nam, 1 + using_hg2(fig));
2675+ end
2676+ % Fix colorspace to CMYK, if requested (workaround for issue #33)
2677+ if options.colourspace == 1 % CMYK
2678+ % Issue #33: due to internal bugs in Matlab's print() function, we can't use its -cmyk option
2679+ change_rgb_to_cmyk(tmp_nam);
2680+ end
2681+ % Add a bookmark to the PDF if desired
2682+ if options.bookmark
2683+ fig_nam = get(fig, 'Name');
2684+ if isempty(fig_nam)
2685+ warning('export_fig:EmptyBookmark', 'Bookmark requested for figure with no name. Bookmark will be empty.');
2686 end
2687+ add_bookmark(tmp_nam, fig_nam);
2688+ end
2689+ % Generate a pdf
2690+ eps2pdf(tmp_nam, pdf_nam_tmp, 1, options.append, options.colourspace==2, options.quality, options.gs_options);
2691+ % Ghostscript croaks on % chars in the output PDF file, so use tempname and then rename the file
2692+ try movefile(pdf_nam_tmp, pdf_nam, 'f'); catch, end
2693+ catch ex
2694+ % Delete the eps
2695+ delete(tmp_nam);
2696+ rethrow(ex);
2697 end
2698+ % Delete the eps
2699+ delete(tmp_nam);
2700+ if options.eps
2701+ try
2702+ % Generate an eps from the pdf
2703+ % since pdftops can't handle relative paths (e.g., '..\'), use a temp file
2704+ eps_nam_tmp = strrep(pdf_nam_tmp,'.pdf','.eps');
2705+ pdf2eps(pdf_nam, eps_nam_tmp);
2706+ movefile(eps_nam_tmp, [options.name '.eps'], 'f');
2707+ catch ex
2708+ if ~options.pdf
2709+ % Delete the pdf
2710+ delete(pdf_nam);
2711+ end
2712+ try delete(eps_nam_tmp); catch, end
2713+ rethrow(ex);
2714+ end
2715+ if ~options.pdf
2716+ % Delete the pdf
2717+ delete(pdf_nam);
2718+ end
2719+ end
2720+ end
2721+
2722+ % Revert the figure or close it (if requested)
2723+ if cls || options.closeFig
2724+ % Close the created figure
2725+ close(fig);
2726 else
2727- [p, options.name, ext] = fileparts(varargin{a});
2728- if ~isempty(p)
2729- options.name = [p filesep options.name];
2730+ % Reset the hardcopy mode
2731+ set(fig, 'InvertHardcopy', old_mode);
2732+ % Reset the axes limit and tick modes
2733+ for a = 1:numel(Hlims)
2734+ try
2735+ set(Hlims(a), 'XLimMode', Xlims{a}, 'YLimMode', Ylims{a}, 'ZLimMode', Zlims{a},...
2736+ 'XTickMode', Xtick{a}, 'YTickMode', Ytick{a}, 'ZTickMode', Ztick{a},...
2737+ 'XTickLabelMode', Xlabel{a}, 'YTickLabelMode', Ylabel{a}, 'ZTickLabelMode', Zlabel{a});
2738+ catch
2739+ % ignore - fix issue #4 (using HG2 on R2014a and earlier)
2740+ end
2741 end
2742- switch lower(ext)
2743- case {'.tif', '.tiff'}
2744- options.tif = true;
2745- case {'.jpg', '.jpeg'}
2746- options.jpg = true;
2747- case '.png'
2748- options.png = true;
2749- case '.bmp'
2750- options.bmp = true;
2751- case '.eps'
2752- options.eps = true;
2753- case '.pdf'
2754- options.pdf = true;
2755- otherwise
2756- options.name = varargin{a};
2757+ % Revert the tex-labels font weights
2758+ try set(texLabels, 'FontWeight','bold'); catch, end
2759+ % Revert annotation units
2760+ for handleIdx = 1 : numel(annotationHandles)
2761+ try
2762+ oldUnits = originalUnits{handleIdx};
2763+ catch
2764+ oldUnits = originalUnits;
2765+ end
2766+ try set(annotationHandles(handleIdx),'Units',oldUnits); catch, end
2767 end
2768+ % Revert figure units
2769+ set(fig,'Units',oldFigUnits);
2770 end
2771+
2772+ % Output to clipboard (if requested)
2773+ if options.clipboard
2774+ % Delete the output file if unchanged from the default name ('export_fig_out.png')
2775+ if strcmpi(options.name,'export_fig_out')
2776+ try
2777+ fileInfo = dir('export_fig_out.png');
2778+ if ~isempty(fileInfo)
2779+ timediff = now - fileInfo.datenum;
2780+ ONE_SEC = 1/24/60/60;
2781+ if timediff < ONE_SEC
2782+ delete('export_fig_out.png');
2783+ end
2784+ end
2785+ catch
2786+ % never mind...
2787+ end
2788+ end
2789+
2790+ % Save the image in the system clipboard
2791+ % credit: Jiro Doke's IMCLIPBOARD: http://www.mathworks.com/matlabcentral/fileexchange/28708-imclipboard
2792+ try
2793+ error(javachk('awt', 'export_fig -clipboard output'));
2794+ catch
2795+ warning('export_fig -clipboard output failed: requires Java to work');
2796+ return;
2797+ end
2798+ try
2799+ % Import necessary Java classes
2800+ import java.awt.Toolkit
2801+ import java.awt.image.BufferedImage
2802+ import java.awt.datatransfer.DataFlavor
2803+
2804+ % Get System Clipboard object (java.awt.Toolkit)
2805+ cb = Toolkit.getDefaultToolkit.getSystemClipboard();
2806+
2807+ % Add java class (ImageSelection) to the path
2808+ if ~exist('ImageSelection', 'class')
2809+ javaaddpath(fileparts(which(mfilename)), '-end');
2810+ end
2811+
2812+ % Get image size
2813+ ht = size(imageData, 1);
2814+ wd = size(imageData, 2);
2815+
2816+ % Convert to Blue-Green-Red format
2817+ try
2818+ imageData2 = imageData(:, :, [3 2 1]);
2819+ catch
2820+ % Probably gray-scaled image (2D, without the 3rd [RGB] dimension)
2821+ imageData2 = imageData(:, :, [1 1 1]);
2822+ end
2823+
2824+ % Convert to 3xWxH format
2825+ imageData2 = permute(imageData2, [3, 2, 1]);
2826+
2827+ % Append Alpha data (unused - transparency is not supported in clipboard copy)
2828+ alphaData2 = uint8(permute(255*alpha,[3,2,1])); %=255*ones(1,wd,ht,'uint8')
2829+ imageData2 = cat(1, imageData2, alphaData2);
2830+
2831+ % Create image buffer
2832+ imBuffer = BufferedImage(wd, ht, BufferedImage.TYPE_INT_RGB);
2833+ imBuffer.setRGB(0, 0, wd, ht, typecast(imageData2(:), 'int32'), 0, wd);
2834+
2835+ % Create ImageSelection object from the image buffer
2836+ imSelection = ImageSelection(imBuffer);
2837+
2838+ % Set clipboard content to the image
2839+ cb.setContents(imSelection, []);
2840+ catch
2841+ warning('export_fig -clipboard output failed: %s', lasterr); %#ok<LERR>
2842+ end
2843+ end
2844+
2845+ % Don't output the data to console unless requested
2846+ if ~nargout
2847+ clear imageData alpha
2848+ end
2849+ catch err
2850+ % Display possible workarounds before the error message
2851+ if displaySuggestedWorkarounds && ~strcmpi(err.message,'export_fig error')
2852+ if ~hadError, fprintf(2, 'export_fig error. '); end
2853+ fprintf(2, 'Please ensure:\n');
2854+ fprintf(2, ' that you are using the <a href="https://github.com/altmany/export_fig/archive/master.zip">latest version</a> of export_fig\n');
2855+ if ismac
2856+ fprintf(2, ' and that you have <a href="http://pages.uoregon.edu/koch">Ghostscript</a> installed\n');
2857+ else
2858+ fprintf(2, ' and that you have <a href="http://www.ghostscript.com">Ghostscript</a> installed\n');
2859+ end
2860+ try
2861+ if options.eps
2862+ fprintf(2, ' and that you have <a href="http://www.foolabs.com/xpdf">pdftops</a> installed\n');
2863+ end
2864+ catch
2865+ % ignore - probably an error in parse_args
2866+ end
2867+ fprintf(2, ' and that you do not have <a href="matlab:which export_fig -all">multiple versions</a> of export_fig installed by mistake\n');
2868+ fprintf(2, ' and that you did not made a mistake in the <a href="matlab:help export_fig">expected input arguments</a>\n');
2869+ try
2870+ % Alert per issue #149
2871+ if ~strncmpi(get(0,'Units'),'pixel',5)
2872+ fprintf(2, ' or try to set groot''s Units property back to its default value of ''pixels'' (<a href="matlab:web(''https://github.com/altmany/export_fig/issues/149'',''-browser'');">details</a>)\n');
2873+ end
2874+ catch
2875+ % ignore - maybe an old MAtlab release
2876+ end
2877+ fprintf(2, '\nIf the problem persists, then please <a href="https://github.com/altmany/export_fig/issues">report a new issue</a>.\n\n');
2878+ end
2879+ rethrow(err)
2880 end
2881 end
2882
2883-% Set default anti-aliasing now we know the renderer
2884-if options.aa_factor == 0
2885- options.aa_factor = 1 + 2 * (~(using_hg2(fig) && strcmp(get(ancestor(fig, 'figure'), 'GraphicsSmoothing'), 'on')) | (options.renderer == 3));
2886+function options = default_options()
2887+ % Default options used by export_fig
2888+ options = struct(...
2889+ 'name', 'export_fig_out', ...
2890+ 'crop', true, ...
2891+ 'crop_amounts', nan(1,4), ... % auto-crop all 4 image sides
2892+ 'transparent', false, ...
2893+ 'renderer', 0, ... % 0: default, 1: OpenGL, 2: ZBuffer, 3: Painters
2894+ 'pdf', false, ...
2895+ 'eps', false, ...
2896+ 'png', false, ...
2897+ 'tif', false, ...
2898+ 'jpg', false, ...
2899+ 'bmp', false, ...
2900+ 'clipboard', false, ...
2901+ 'colourspace', 0, ... % 0: RGB/gray, 1: CMYK, 2: gray
2902+ 'append', false, ...
2903+ 'im', false, ...
2904+ 'alpha', false, ...
2905+ 'aa_factor', 0, ...
2906+ 'bb_padding', 0, ...
2907+ 'magnify', [], ...
2908+ 'resolution', [], ...
2909+ 'bookmark', false, ...
2910+ 'closeFig', false, ...
2911+ 'quality', [], ...
2912+ 'update', false, ...
2913+ 'fontswap', true, ...
2914+ 'gs_options', {{}});
2915 end
2916
2917-% Convert user dir '~' to full path
2918-if numel(options.name) > 2 && options.name(1) == '~' && (options.name(2) == '/' || options.name(2) == '\')
2919- options.name = fullfile(char(java.lang.System.getProperty('user.home')), options.name(2:end));
2920-end
2921+function [fig, options] = parse_args(nout, fig, varargin)
2922+ % Parse the input arguments
2923
2924-% Compute the magnification and resolution
2925-if isempty(options.magnify)
2926- if isempty(options.resolution)
2927- options.magnify = 1;
2928- options.resolution = 864;
2929- else
2930- options.magnify = options.resolution ./ get(0, 'ScreenPixelsPerInch');
2931+ % Set the defaults
2932+ native = false; % Set resolution to native of an image
2933+ options = default_options();
2934+ options.im = (nout == 1); % user requested imageData output
2935+ options.alpha = (nout == 2); % user requested alpha output
2936+
2937+ % Go through the other arguments
2938+ skipNext = false;
2939+ for a = 1:nargin-2
2940+ if skipNext
2941+ skipNext = false;
2942+ continue;
2943+ end
2944+ if all(ishandle(varargin{a}))
2945+ fig = varargin{a};
2946+ elseif ischar(varargin{a}) && ~isempty(varargin{a})
2947+ if varargin{a}(1) == '-'
2948+ switch lower(varargin{a}(2:end))
2949+ case 'nocrop'
2950+ options.crop = false;
2951+ options.crop_amounts = [0,0,0,0];
2952+ case {'trans', 'transparent'}
2953+ options.transparent = true;
2954+ case 'opengl'
2955+ options.renderer = 1;
2956+ case 'zbuffer'
2957+ options.renderer = 2;
2958+ case 'painters'
2959+ options.renderer = 3;
2960+ case 'pdf'
2961+ options.pdf = true;
2962+ case 'eps'
2963+ options.eps = true;
2964+ case 'png'
2965+ options.png = true;
2966+ case {'tif', 'tiff'}
2967+ options.tif = true;
2968+ case {'jpg', 'jpeg'}
2969+ options.jpg = true;
2970+ case 'bmp'
2971+ options.bmp = true;
2972+ case 'rgb'
2973+ options.colourspace = 0;
2974+ case 'cmyk'
2975+ options.colourspace = 1;
2976+ case {'gray', 'grey'}
2977+ options.colourspace = 2;
2978+ case {'a1', 'a2', 'a3', 'a4'}
2979+ options.aa_factor = str2double(varargin{a}(3));
2980+ case 'append'
2981+ options.append = true;
2982+ case 'bookmark'
2983+ options.bookmark = true;
2984+ case 'native'
2985+ native = true;
2986+ case 'clipboard'
2987+ options.clipboard = true;
2988+ options.im = true;
2989+ options.alpha = true;
2990+ case 'svg'
2991+ msg = ['SVG output is not supported by export_fig. Use one of the following alternatives:\n' ...
2992+ ' 1. saveas(gcf,''filename.svg'')\n' ...
2993+ ' 2. plot2svg utility: http://github.com/jschwizer99/plot2svg\n' ...
2994+ ' 3. export_fig to EPS/PDF, then convert to SVG using generic (non-Matlab) tools\n'];
2995+ error(sprintf(msg)); %#ok<SPERR>
2996+ case 'update'
2997+ % Download the latest version of export_fig into the export_fig folder
2998+ try
2999+ zipFileName = 'https://github.com/altmany/export_fig/archive/master.zip';
3000+ folderName = fileparts(which(mfilename('fullpath')));
3001+ targetFileName = fullfile(folderName, datestr(now,'yyyy-mm-dd.zip'));
3002+ urlwrite(zipFileName,targetFileName);
3003+ catch
3004+ error('Could not download %s into %s\n',zipFileName,targetFileName);
3005+ end
3006+
3007+ % Unzip the downloaded zip file in the export_fig folder
3008+ try
3009+ unzip(targetFileName,folderName);
3010+ catch
3011+ error('Could not unzip %s\n',targetFileName);
3012+ end
3013+ case 'nofontswap'
3014+ options.fontswap = false;
3015+ otherwise
3016+ try
3017+ wasError = false;
3018+ if strcmpi(varargin{a}(1:2),'-d')
3019+ varargin{a}(2) = 'd'; % ensure lowercase 'd'
3020+ options.gs_options{end+1} = varargin{a};
3021+ elseif strcmpi(varargin{a}(1:2),'-c')
3022+ if numel(varargin{a})==2
3023+ skipNext = true;
3024+ vals = str2num(varargin{a+1}); %#ok<ST2NM>
3025+ else
3026+ vals = str2num(varargin{a}(3:end)); %#ok<ST2NM>
3027+ end
3028+ if numel(vals)~=4
3029+ wasError = true;
3030+ error('option -c cannot be parsed: must be a 4-element numeric vector');
3031+ end
3032+ options.crop_amounts = vals;
3033+ options.crop = true;
3034+ else % scalar parameter value
3035+ val = str2double(regexp(varargin{a}, '(?<=-(m|M|r|R|q|Q|p|P))-?\d*.?\d+', 'match'));
3036+ if isempty(val) || isnan(val)
3037+ % Issue #51: improved processing of input args (accept space between param name & value)
3038+ val = str2double(varargin{a+1});
3039+ if isscalar(val) && ~isnan(val)
3040+ skipNext = true;
3041+ end
3042+ end
3043+ if ~isscalar(val) || isnan(val)
3044+ wasError = true;
3045+ error('option %s is not recognised or cannot be parsed', varargin{a});
3046+ end
3047+ switch lower(varargin{a}(2))
3048+ case 'm'
3049+ % Magnification may never be negative
3050+ if val <= 0
3051+ wasError = true;
3052+ error('Bad magnification value: %g (must be positive)', val);
3053+ end
3054+ options.magnify = val;
3055+ case 'r'
3056+ options.resolution = val;
3057+ case 'q'
3058+ options.quality = max(val, 0);
3059+ case 'p'
3060+ options.bb_padding = val;
3061+ end
3062+ end
3063+ catch err
3064+ % We might have reached here by raising an intentional error
3065+ if wasError % intentional raise
3066+ rethrow(err)
3067+ else % unintentional
3068+ error(['Unrecognized export_fig input option: ''' varargin{a} '''']);
3069+ end
3070+ end
3071+ end
3072+ else
3073+ [p, options.name, ext] = fileparts(varargin{a});
3074+ if ~isempty(p)
3075+ options.name = [p filesep options.name];
3076+ end
3077+ switch lower(ext)
3078+ case {'.tif', '.tiff'}
3079+ options.tif = true;
3080+ case {'.jpg', '.jpeg'}
3081+ options.jpg = true;
3082+ case '.png'
3083+ options.png = true;
3084+ case '.bmp'
3085+ options.bmp = true;
3086+ case '.eps'
3087+ options.eps = true;
3088+ case '.pdf'
3089+ options.pdf = true;
3090+ case '.fig'
3091+ % If no open figure, then load the specified .fig file and continue
3092+ if isempty(fig)
3093+ fig = openfig(varargin{a},'invisible');
3094+ varargin{a} = fig;
3095+ options.closeFig = true;
3096+ else
3097+ % save the current figure as the specified .fig file and exit
3098+ saveas(fig(1),varargin{a});
3099+ fig = -1;
3100+ return
3101+ end
3102+ case '.svg'
3103+ msg = ['SVG output is not supported by export_fig. Use one of the following alternatives:\n' ...
3104+ ' 1. saveas(gcf,''filename.svg'')\n' ...
3105+ ' 2. plot2svg utility: http://github.com/jschwizer99/plot2svg\n' ...
3106+ ' 3. export_fig to EPS/PDF, then convert to SVG using generic (non-Matlab) tools\n'];
3107+ error(sprintf(msg)); %#ok<SPERR>
3108+ otherwise
3109+ options.name = varargin{a};
3110+ end
3111+ end
3112+ end
3113 end
3114-elseif isempty(options.resolution)
3115- options.resolution = 864;
3116-end
3117
3118-% Check we have a figure handle
3119-if isempty(fig)
3120- error('No figure found');
3121-end
3122+ % Quick bail-out if no figure found
3123+ if isempty(fig), return; end
3124
3125-% Set the default format
3126-if ~isvector(options) && ~isbitmap(options)
3127- options.png = true;
3128-end
3129+ % Do border padding with repsect to a cropped image
3130+ if options.bb_padding
3131+ options.crop = true;
3132+ end
3133
3134-% Check whether transparent background is wanted (old way)
3135-if isequal(get(ancestor(fig(1), 'figure'), 'Color'), 'none')
3136- options.transparent = true;
3137-end
3138+ % Set default anti-aliasing now we know the renderer
3139+ if options.aa_factor == 0
3140+ try isAA = strcmp(get(ancestor(fig, 'figure'), 'GraphicsSmoothing'), 'on'); catch, isAA = false; end
3141+ options.aa_factor = 1 + 2 * (~(using_hg2(fig) && isAA) | (options.renderer == 3));
3142+ end
3143
3144-% If requested, set the resolution to the native vertical resolution of the
3145-% first suitable image found
3146-if native && isbitmap(options)
3147- % Find a suitable image
3148- list = findobj(fig, 'Type', 'image', 'Tag', 'export_fig_native');
3149- if isempty(list)
3150- list = findobj(fig, 'Type', 'image', 'Visible', 'on');
3151+ % Convert user dir '~' to full path
3152+ if numel(options.name) > 2 && options.name(1) == '~' && (options.name(2) == '/' || options.name(2) == '\')
3153+ options.name = fullfile(char(java.lang.System.getProperty('user.home')), options.name(2:end));
3154 end
3155- for hIm = list(:)'
3156- % Check height is >= 2
3157- height = size(get(hIm, 'CData'), 1);
3158- if height < 2
3159- continue
3160+
3161+ % Compute the magnification and resolution
3162+ if isempty(options.magnify)
3163+ if isempty(options.resolution)
3164+ options.magnify = 1;
3165+ options.resolution = 864;
3166+ else
3167+ options.magnify = options.resolution ./ get(0, 'ScreenPixelsPerInch');
3168 end
3169- % Account for the image filling only part of the axes, or vice
3170- % versa
3171- yl = get(hIm, 'YData');
3172- if isscalar(yl)
3173- yl = [yl(1)-0.5 yl(1)+height+0.5];
3174- else
3175- if ~diff(yl)
3176+ elseif isempty(options.resolution)
3177+ options.resolution = 864;
3178+ end
3179+
3180+ % Set the default format
3181+ if ~isvector(options) && ~isbitmap(options)
3182+ options.png = true;
3183+ end
3184+
3185+ % Check whether transparent background is wanted (old way)
3186+ if isequal(get(ancestor(fig(1), 'figure'), 'Color'), 'none')
3187+ options.transparent = true;
3188+ end
3189+
3190+ % If requested, set the resolution to the native vertical resolution of the
3191+ % first suitable image found
3192+ if native && isbitmap(options)
3193+ % Find a suitable image
3194+ list = findall(fig, 'Type','image', 'Tag','export_fig_native');
3195+ if isempty(list)
3196+ list = findall(fig, 'Type','image', 'Visible','on');
3197+ end
3198+ for hIm = list(:)'
3199+ % Check height is >= 2
3200+ height = size(get(hIm, 'CData'), 1);
3201+ if height < 2
3202 continue
3203 end
3204- yl = yl + [-0.5 0.5] * (diff(yl) / (height - 1));
3205+ % Account for the image filling only part of the axes, or vice versa
3206+ yl = get(hIm, 'YData');
3207+ if isscalar(yl)
3208+ yl = [yl(1)-0.5 yl(1)+height+0.5];
3209+ else
3210+ yl = [min(yl), max(yl)]; % fix issue #151 (case of yl containing more than 2 elements)
3211+ if ~diff(yl)
3212+ continue
3213+ end
3214+ yl = yl + [-0.5 0.5] * (diff(yl) / (height - 1));
3215+ end
3216+ hAx = get(hIm, 'Parent');
3217+ yl2 = get(hAx, 'YLim');
3218+ % Find the pixel height of the axes
3219+ oldUnits = get(hAx, 'Units');
3220+ set(hAx, 'Units', 'pixels');
3221+ pos = get(hAx, 'Position');
3222+ set(hAx, 'Units', oldUnits);
3223+ if ~pos(4)
3224+ continue
3225+ end
3226+ % Found a suitable image
3227+ % Account for stretch-to-fill being disabled
3228+ pbar = get(hAx, 'PlotBoxAspectRatio');
3229+ pos = min(pos(4), pbar(2)*pos(3)/pbar(1));
3230+ % Set the magnification to give native resolution
3231+ options.magnify = abs((height * diff(yl2)) / (pos * diff(yl))); % magnification must never be negative: issue #103
3232+ break
3233 end
3234- hAx = get(hIm, 'Parent');
3235- yl2 = get(hAx, 'YLim');
3236- % Find the pixel height of the axes
3237- oldUnits = get(hAx, 'Units');
3238- set(hAx, 'Units', 'pixels');
3239- pos = get(hAx, 'Position');
3240- set(hAx, 'Units', oldUnits);
3241- if ~pos(4)
3242- continue
3243- end
3244- % Found a suitable image
3245- % Account for stretch-to-fill being disabled
3246- pbar = get(hAx, 'PlotBoxAspectRatio');
3247- pos = min(pos(4), pbar(2)*pos(3)/pbar(1));
3248- % Set the magnification to give native resolution
3249- options.magnify = (height * diff(yl2)) / (pos * diff(yl));
3250- break
3251 end
3252 end
3253-end
3254
3255 function A = downsize(A, factor)
3256-% Downsample an image
3257-if factor == 1
3258- % Nothing to do
3259- return
3260-end
3261-try
3262- % Faster, but requires image processing toolbox
3263- A = imresize(A, 1/factor, 'bilinear');
3264-catch
3265- % No image processing toolbox - resize manually
3266- % Lowpass filter - use Gaussian as is separable, so faster
3267- % Compute the 1d Gaussian filter
3268- filt = (-factor-1:factor+1) / (factor * 0.6);
3269- filt = exp(-filt .* filt);
3270- % Normalize the filter
3271- filt = single(filt / sum(filt));
3272- % Filter the image
3273- padding = floor(numel(filt) / 2);
3274- for a = 1:size(A, 3)
3275- A(:,:,a) = conv2(filt, filt', single(A([ones(1, padding) 1:end repmat(end, 1, padding)],[ones(1, padding) 1:end repmat(end, 1, padding)],a)), 'valid');
3276+ % Downsample an image
3277+ if factor == 1
3278+ % Nothing to do
3279+ return
3280 end
3281- % Subsample
3282- A = A(1+floor(mod(end-1, factor)/2):factor:end,1+floor(mod(end-1, factor)/2):factor:end,:);
3283+ try
3284+ % Faster, but requires image processing toolbox
3285+ A = imresize(A, 1/factor, 'bilinear');
3286+ catch
3287+ % No image processing toolbox - resize manually
3288+ % Lowpass filter - use Gaussian as is separable, so faster
3289+ % Compute the 1d Gaussian filter
3290+ filt = (-factor-1:factor+1) / (factor * 0.6);
3291+ filt = exp(-filt .* filt);
3292+ % Normalize the filter
3293+ filt = single(filt / sum(filt));
3294+ % Filter the image
3295+ padding = floor(numel(filt) / 2);
3296+ for a = 1:size(A, 3)
3297+ A(:,:,a) = conv2(filt, filt', single(A([ones(1, padding) 1:end repmat(end, 1, padding)],[ones(1, padding) 1:end repmat(end, 1, padding)],a)), 'valid');
3298+ end
3299+ % Subsample
3300+ A = A(1+floor(mod(end-1, factor)/2):factor:end,1+floor(mod(end-1, factor)/2):factor:end,:);
3301+ end
3302 end
3303-end
3304
3305 function A = rgb2grey(A)
3306-A = cast(reshape(reshape(single(A), [], 3) * single([0.299; 0.587; 0.114]), size(A, 1), size(A, 2)), class(A));
3307+ A = cast(reshape(reshape(single(A), [], 3) * single([0.299; 0.587; 0.114]), size(A, 1), size(A, 2)), class(A)); %#ok<ZEROLIKE>
3308 end
3309
3310 function A = check_greyscale(A)
3311-% Check if the image is greyscale
3312-if size(A, 3) == 3 && ...
3313- all(reshape(A(:,:,1) == A(:,:,2), [], 1)) && ...
3314- all(reshape(A(:,:,2) == A(:,:,3), [], 1))
3315- A = A(:,:,1); % Save only one channel for 8-bit output
3316+ % Check if the image is greyscale
3317+ if size(A, 3) == 3 && ...
3318+ all(reshape(A(:,:,1) == A(:,:,2), [], 1)) && ...
3319+ all(reshape(A(:,:,2) == A(:,:,3), [], 1))
3320+ A = A(:,:,1); % Save only one channel for 8-bit output
3321+ end
3322 end
3323-end
3324
3325 function eps_remove_background(fname, count)
3326-% Remove the background of an eps file
3327-% Open the file
3328-fh = fopen(fname, 'r+');
3329-if fh == -1
3330- error('Not able to open file %s.', fname);
3331-end
3332-% Read the file line by line
3333-while count
3334- % Get the next line
3335- l = fgets(fh);
3336- if isequal(l, -1)
3337- break; % Quit, no rectangle found
3338+ % Remove the background of an eps file
3339+ % Open the file
3340+ fh = fopen(fname, 'r+');
3341+ if fh == -1
3342+ error('Not able to open file %s.', fname);
3343 end
3344- % Check if the line contains the background rectangle
3345- if isequal(regexp(l, ' *0 +0 +\d+ +\d+ +r[fe] *[\n\r]+', 'start'), 1)
3346- % Set the line to whitespace and quit
3347- l(1:regexp(l, '[\n\r]', 'start', 'once')-1) = ' ';
3348- fseek(fh, -numel(l), 0);
3349- fprintf(fh, l);
3350- % Reduce the count
3351- count = count - 1;
3352+ % Read the file line by line
3353+ while count
3354+ % Get the next line
3355+ l = fgets(fh);
3356+ if isequal(l, -1)
3357+ break; % Quit, no rectangle found
3358+ end
3359+ % Check if the line contains the background rectangle
3360+ if isequal(regexp(l, ' *0 +0 +\d+ +\d+ +r[fe] *[\n\r]+', 'start'), 1)
3361+ % Set the line to whitespace and quit
3362+ l(1:regexp(l, '[\n\r]', 'start', 'once')-1) = ' ';
3363+ fseek(fh, -numel(l), 0);
3364+ fprintf(fh, l);
3365+ % Reduce the count
3366+ count = count - 1;
3367+ end
3368 end
3369+ % Close the file
3370+ fclose(fh);
3371 end
3372-% Close the file
3373-fclose(fh);
3374-end
3375
3376 function b = isvector(options)
3377-b = options.pdf || options.eps;
3378+ b = options.pdf || options.eps;
3379 end
3380
3381 function b = isbitmap(options)
3382-b = options.png || options.tif || options.jpg || options.bmp || options.im || options.alpha;
3383+ b = options.png || options.tif || options.jpg || options.bmp || options.im || options.alpha;
3384 end
3385
3386 % Helper function
3387 function A = make_cell(A)
3388-if ~iscell(A)
3389- A = {A};
3390+ if ~iscell(A)
3391+ A = {A};
3392+ end
3393 end
3394-end
3395
3396 function add_bookmark(fname, bookmark_text)
3397-% Adds a bookmark to the temporary EPS file after %%EndPageSetup
3398-% Read in the file
3399-fh = fopen(fname, 'r');
3400-if fh == -1
3401- error('File %s not found.', fname);
3402-end
3403-try
3404- fstrm = fread(fh, '*char')';
3405-catch ex
3406+ % Adds a bookmark to the temporary EPS file after %%EndPageSetup
3407+ % Read in the file
3408+ fh = fopen(fname, 'r');
3409+ if fh == -1
3410+ error('File %s not found.', fname);
3411+ end
3412+ try
3413+ fstrm = fread(fh, '*char')';
3414+ catch ex
3415+ fclose(fh);
3416+ rethrow(ex);
3417+ end
3418 fclose(fh);
3419- rethrow(ex);
3420-end
3421-fclose(fh);
3422
3423-% Include standard pdfmark prolog to maximize compatibility
3424-fstrm = strrep(fstrm, '%%BeginProlog', sprintf('%%%%BeginProlog\n/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse'));
3425-% Add page bookmark
3426-fstrm = strrep(fstrm, '%%EndPageSetup', sprintf('%%%%EndPageSetup\n[ /Title (%s) /OUT pdfmark',bookmark_text));
3427+ % Include standard pdfmark prolog to maximize compatibility
3428+ fstrm = strrep(fstrm, '%%BeginProlog', sprintf('%%%%BeginProlog\n/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse'));
3429+ % Add page bookmark
3430+ fstrm = strrep(fstrm, '%%EndPageSetup', sprintf('%%%%EndPageSetup\n[ /Title (%s) /OUT pdfmark',bookmark_text));
3431
3432-% Write out the updated file
3433-fh = fopen(fname, 'w');
3434-if fh == -1
3435- error('Unable to open %s for writing.', fname);
3436-end
3437-try
3438- fwrite(fh, fstrm, 'char*1');
3439-catch ex
3440+ % Write out the updated file
3441+ fh = fopen(fname, 'w');
3442+ if fh == -1
3443+ error('Unable to open %s for writing.', fname);
3444+ end
3445+ try
3446+ fwrite(fh, fstrm, 'char*1');
3447+ catch ex
3448+ fclose(fh);
3449+ rethrow(ex);
3450+ end
3451 fclose(fh);
3452- rethrow(ex);
3453 end
3454-fclose(fh);
3455-end
3456
3457 function set_tick_mode(Hlims, ax)
3458-% Set the tick mode of linear axes to manual
3459-% Leave log axes alone as these are tricky
3460-M = get(Hlims, [ax 'Scale']);
3461-if ~iscell(M)
3462- M = {M};
3463+ % Set the tick mode of linear axes to manual
3464+ % Leave log axes alone as these are tricky
3465+ M = get(Hlims, [ax 'Scale']);
3466+ if ~iscell(M)
3467+ M = {M};
3468+ end
3469+ M = cellfun(@(c) strcmp(c, 'linear'), M);
3470+ set(Hlims(M), [ax 'TickMode'], 'manual');
3471+ %set(Hlims(M), [ax 'TickLabelMode'], 'manual'); % this hides exponent label in HG2!
3472 end
3473-M = cellfun(@(c) strcmp(c, 'linear'), M);
3474-set(Hlims(M), [ax 'TickMode'], 'manual');
3475+
3476+function change_rgb_to_cmyk(fname) % convert RGB => CMYK within an EPS file
3477+ % Do post-processing on the eps file
3478+ try
3479+ % Read the EPS file into memory
3480+ fstrm = read_write_entire_textfile(fname);
3481+
3482+ % Replace all gray-scale colors
3483+ fstrm = regexprep(fstrm, '\n([\d.]+) +GC\n', '\n0 0 0 ${num2str(1-str2num($1))} CC\n');
3484+
3485+ % Replace all RGB colors
3486+ fstrm = regexprep(fstrm, '\n[0.]+ +[0.]+ +[0.]+ +RC\n', '\n0 0 0 1 CC\n'); % pure black
3487+ fstrm = regexprep(fstrm, '\n([\d.]+) +([\d.]+) +([\d.]+) +RC\n', '\n${sprintf(''%.4g '',[1-[str2num($1),str2num($2),str2num($3)]/max([str2num($1),str2num($2),str2num($3)]),1-max([str2num($1),str2num($2),str2num($3)])])} CC\n');
3488+
3489+ % Overwrite the file with the modified contents
3490+ read_write_entire_textfile(fname, fstrm);
3491+ catch
3492+ % never mind - leave as is...
3493+ end
3494 end
3495Index: ../trunk-jpl/externalpackages/export_fig/ghostscript.m
3496===================================================================
3497--- ../trunk-jpl/externalpackages/export_fig/ghostscript.m (revision 21314)
3498+++ ../trunk-jpl/externalpackages/export_fig/ghostscript.m (revision 21315)
3499@@ -1,3 +1,4 @@
3500+function varargout = ghostscript(cmd)
3501 %GHOSTSCRIPT Calls a local GhostScript executable with the input command
3502 %
3503 % Example:
3504@@ -19,140 +20,177 @@
3505 % status - 0 iff command ran without problem.
3506 % result - Output from ghostscript.
3507
3508-% Copyright: Oliver Woodford, 2009-2013
3509-
3510-% Thanks to Jonas Dorn for the fix for the title of the uigetdir window on
3511-% Mac OS.
3512-% Thanks to Nathan Childress for the fix to the default location on 64-bit
3513-% Windows systems.
3514-% 27/4/11 - Find 64-bit Ghostscript on Windows. Thanks to Paul Durack and
3515-% Shaun Kline for pointing out the issue
3516-% 4/5/11 - Thanks to David Chorlian for pointing out an alternative
3517-% location for gs on linux.
3518+% Copyright: Oliver Woodford, 2009-2015, Yair Altman 2015-
3519+%{
3520+% Thanks to Jonas Dorn for the fix for the title of the uigetdir window on Mac OS.
3521+% Thanks to Nathan Childress for the fix to default location on 64-bit Windows systems.
3522+% 27/04/11 - Find 64-bit Ghostscript on Windows. Thanks to Paul Durack and
3523+% Shaun Kline for pointing out the issue
3524+% 04/05/11 - Thanks to David Chorlian for pointing out an alternative
3525+% location for gs on linux.
3526 % 12/12/12 - Add extra executable name on Windows. Thanks to Ratish
3527-% Punnoose for highlighting the issue.
3528-% 28/6/13 - Fix error using GS 9.07 in Linux. Many thanks to Jannick
3529-% Steinbring for proposing the fix.
3530-% 24/10/13 - Fix error using GS 9.07 in Linux. Many thanks to Johannes
3531-% for the fix.
3532-% 23/01/2014 - Add full path to ghostscript.txt in warning. Thanks to Koen
3533-% Vermeer for raising the issue.
3534+% Punnoose for highlighting the issue.
3535+% 28/06/13 - Fix error using GS 9.07 in Linux. Many thanks to Jannick
3536+% Steinbring for proposing the fix.
3537+% 24/10/13 - Fix error using GS 9.07 in Linux. Many thanks to Johannes
3538+% for the fix.
3539+% 23/01/14 - Add full path to ghostscript.txt in warning. Thanks to Koen
3540+% Vermeer for raising the issue.
3541+% 27/02/15 - If Ghostscript croaks, display suggested workarounds
3542+% 30/03/15 - Improved performance by caching status of GS path check, if ok
3543+% 14/05/15 - Clarified warning message in case GS path could not be saved
3544+% 29/05/15 - Avoid cryptic error in case the ghostscipt path cannot be saved (issue #74)
3545+% 10/11/15 - Custom GS installation webpage for MacOS. Thanks to Andy Hueni via FEX
3546+%}
3547
3548-function varargout = ghostscript(cmd)
3549-% Initialize any required system calls before calling ghostscript
3550-shell_cmd = '';
3551-if isunix
3552- shell_cmd = 'export LD_LIBRARY_PATH=""; '; % Avoids an error on Linux with GS 9.07
3553+ try
3554+ % Call ghostscript
3555+ [varargout{1:nargout}] = system([gs_command(gs_path()) cmd]);
3556+ catch err
3557+ % Display possible workarounds for Ghostscript croaks
3558+ url1 = 'https://github.com/altmany/export_fig/issues/12#issuecomment-61467998'; % issue #12
3559+ url2 = 'https://github.com/altmany/export_fig/issues/20#issuecomment-63826270'; % issue #20
3560+ hg2_str = ''; if using_hg2, hg2_str = ' or Matlab R2014a'; end
3561+ fprintf(2, 'Ghostscript error. Rolling back to GS 9.10%s may possibly solve this:\n * <a href="%s">%s</a> ',hg2_str,url1,url1);
3562+ if using_hg2
3563+ fprintf(2, '(GS 9.10)\n * <a href="%s">%s</a> (R2014a)',url2,url2);
3564+ end
3565+ fprintf('\n\n');
3566+ if ismac || isunix
3567+ url3 = 'https://github.com/altmany/export_fig/issues/27'; % issue #27
3568+ fprintf(2, 'Alternatively, this may possibly be due to a font path issue:\n * <a href="%s">%s</a>\n\n',url3,url3);
3569+ % issue #20
3570+ fpath = which(mfilename);
3571+ if isempty(fpath), fpath = [mfilename('fullpath') '.m']; end
3572+ fprintf(2, 'Alternatively, if you are using csh, modify shell_cmd from "export..." to "setenv ..."\nat the bottom of <a href="matlab:opentoline(''%s'',174)">%s</a>\n\n',fpath,fpath);
3573+ end
3574+ rethrow(err);
3575+ end
3576 end
3577-if ismac
3578- shell_cmd = 'export DYLD_LIBRARY_PATH=""; '; % Avoids an error on Mac with GS 9.07
3579-end
3580-% Call ghostscript
3581-[varargout{1:nargout}] = system(sprintf('%s"%s" %s', shell_cmd, gs_path, cmd));
3582-end
3583
3584 function path_ = gs_path
3585-% Return a valid path
3586-% Start with the currently set path
3587-path_ = user_string('ghostscript');
3588-% Check the path works
3589-if check_gs_path(path_)
3590- return
3591-end
3592-% Check whether the binary is on the path
3593-if ispc
3594- bin = {'gswin32c.exe', 'gswin64c.exe', 'gs'};
3595-else
3596- bin = {'gs'};
3597-end
3598-for a = 1:numel(bin)
3599- path_ = bin{a};
3600- if check_store_gs_path(path_)
3601+ % Return a valid path
3602+ % Start with the currently set path
3603+ path_ = user_string('ghostscript');
3604+ % Check the path works
3605+ if check_gs_path(path_)
3606 return
3607 end
3608-end
3609-% Search the obvious places
3610-if ispc
3611- default_location = 'C:\Program Files\gs\';
3612- dir_list = dir(default_location);
3613- if isempty(dir_list)
3614- default_location = 'C:\Program Files (x86)\gs\'; % Possible location on 64-bit systems
3615+ % Check whether the binary is on the path
3616+ if ispc
3617+ bin = {'gswin32c.exe', 'gswin64c.exe', 'gs'};
3618+ else
3619+ bin = {'gs'};
3620+ end
3621+ for a = 1:numel(bin)
3622+ path_ = bin{a};
3623+ if check_store_gs_path(path_)
3624+ return
3625+ end
3626+ end
3627+ % Search the obvious places
3628+ if ispc
3629+ default_location = 'C:\Program Files\gs\';
3630 dir_list = dir(default_location);
3631- end
3632- executable = {'\bin\gswin32c.exe', '\bin\gswin64c.exe'};
3633- ver_num = 0;
3634- % If there are multiple versions, use the newest
3635- for a = 1:numel(dir_list)
3636- ver_num2 = sscanf(dir_list(a).name, 'gs%g');
3637- if ~isempty(ver_num2) && ver_num2 > ver_num
3638- for b = 1:numel(executable)
3639- path2 = [default_location dir_list(a).name executable{b}];
3640- if exist(path2, 'file') == 2
3641- path_ = path2;
3642- ver_num = ver_num2;
3643+ if isempty(dir_list)
3644+ default_location = 'C:\Program Files (x86)\gs\'; % Possible location on 64-bit systems
3645+ dir_list = dir(default_location);
3646+ end
3647+ executable = {'\bin\gswin32c.exe', '\bin\gswin64c.exe'};
3648+ ver_num = 0;
3649+ % If there are multiple versions, use the newest
3650+ for a = 1:numel(dir_list)
3651+ ver_num2 = sscanf(dir_list(a).name, 'gs%g');
3652+ if ~isempty(ver_num2) && ver_num2 > ver_num
3653+ for b = 1:numel(executable)
3654+ path2 = [default_location dir_list(a).name executable{b}];
3655+ if exist(path2, 'file') == 2
3656+ path_ = path2;
3657+ ver_num = ver_num2;
3658+ end
3659 end
3660 end
3661 end
3662- end
3663- if check_store_gs_path(path_)
3664- return
3665- end
3666-else
3667- executable = {'/usr/bin/gs', '/usr/local/bin/gs'};
3668- for a = 1:numel(executable)
3669- path_ = executable{a};
3670 if check_store_gs_path(path_)
3671 return
3672 end
3673+ else
3674+ executable = {'/usr/bin/gs', '/usr/local/bin/gs'};
3675+ for a = 1:numel(executable)
3676+ path_ = executable{a};
3677+ if check_store_gs_path(path_)
3678+ return
3679+ end
3680+ end
3681 end
3682-end
3683-% Ask the user to enter the path
3684-while 1
3685- if strncmp(computer, 'MAC', 3) % Is a Mac
3686- % Give separate warning as the uigetdir dialogue box doesn't have a
3687- % title
3688- uiwait(warndlg('Ghostscript not found. Please locate the program.'))
3689- end
3690- base = uigetdir('/', 'Ghostcript not found. Please locate the program.');
3691- if isequal(base, 0)
3692- % User hit cancel or closed window
3693- break;
3694- end
3695- base = [base filesep];
3696- bin_dir = {'', ['bin' filesep], ['lib' filesep]};
3697- for a = 1:numel(bin_dir)
3698- for b = 1:numel(bin)
3699- path_ = [base bin_dir{a} bin{b}];
3700- if exist(path_, 'file') == 2
3701- if check_store_gs_path(path_)
3702- return
3703+ % Ask the user to enter the path
3704+ while true
3705+ if strncmp(computer, 'MAC', 3) % Is a Mac
3706+ % Give separate warning as the uigetdir dialogue box doesn't have a
3707+ % title
3708+ uiwait(warndlg('Ghostscript not found. Please locate the program.'))
3709+ end
3710+ base = uigetdir('/', 'Ghostcript not found. Please locate the program.');
3711+ if isequal(base, 0)
3712+ % User hit cancel or closed window
3713+ break;
3714+ end
3715+ base = [base filesep]; %#ok<AGROW>
3716+ bin_dir = {'', ['bin' filesep], ['lib' filesep]};
3717+ for a = 1:numel(bin_dir)
3718+ for b = 1:numel(bin)
3719+ path_ = [base bin_dir{a} bin{b}];
3720+ if exist(path_, 'file') == 2
3721+ if check_store_gs_path(path_)
3722+ return
3723+ end
3724 end
3725 end
3726 end
3727 end
3728+ if ismac
3729+ error('Ghostscript not found. Have you installed it (http://pages.uoregon.edu/koch)?');
3730+ else
3731+ error('Ghostscript not found. Have you installed it from www.ghostscript.com?');
3732+ end
3733 end
3734-error('Ghostscript not found. Have you installed it from www.ghostscript.com?');
3735-end
3736
3737 function good = check_store_gs_path(path_)
3738-% Check the path is valid
3739-good = check_gs_path(path_);
3740-if ~good
3741- return
3742+ % Check the path is valid
3743+ good = check_gs_path(path_);
3744+ if ~good
3745+ return
3746+ end
3747+ % Update the current default path to the path found
3748+ if ~user_string('ghostscript', path_)
3749+ filename = fullfile(fileparts(which('user_string.m')), '.ignore', 'ghostscript.txt');
3750+ warning('Path to ghostscript installation could not be saved in %s (perhaps a permissions issue). You can manually create this file and set its contents to %s, to improve performance in future invocations (this warning is safe to ignore).', filename, path_);
3751+ return
3752+ end
3753 end
3754-% Update the current default path to the path found
3755-if ~user_string('ghostscript', path_)
3756- warning('Path to ghostscript installation could not be saved. Enter it manually in %s.', fullfile(fileparts(which('user_string.m')), '.ignore', 'ghostscript.txt'));
3757- return
3758-end
3759-end
3760
3761 function good = check_gs_path(path_)
3762-% Check the path is valid
3763-shell_cmd = '';
3764-if ismac
3765- shell_cmd = 'export DYLD_LIBRARY_PATH=""; '; % Avoids an error on Mac with GS 9.07
3766+ persistent isOk
3767+ if isempty(path_)
3768+ isOk = false;
3769+ elseif ~isequal(isOk,true)
3770+ % Check whether the path is valid
3771+ [status, message] = system([gs_command(path_) '-h']); %#ok<ASGLU>
3772+ isOk = status == 0;
3773+ end
3774+ good = isOk;
3775 end
3776-[good, message] = system(sprintf('%s"%s" -h', shell_cmd, path_));
3777-good = good == 0;
3778+
3779+function cmd = gs_command(path_)
3780+ % Initialize any required system calls before calling ghostscript
3781+ % TODO: in Unix/Mac, find a way to determine whether to use "export" (bash) or "setenv" (csh/tcsh)
3782+ shell_cmd = '';
3783+ if isunix
3784+ shell_cmd = 'export LD_LIBRARY_PATH=""; '; % Avoids an error on Linux with GS 9.07
3785+ end
3786+ if ismac
3787+ shell_cmd = 'export DYLD_LIBRARY_PATH=""; '; % Avoids an error on Mac with GS 9.07
3788+ end
3789+ % Construct the command string
3790+ cmd = sprintf('%s"%s" ', shell_cmd, path_);
3791 end
3792Index: ../trunk-jpl/externalpackages/export_fig/print2array.m
3793===================================================================
3794--- ../trunk-jpl/externalpackages/export_fig/print2array.m (revision 21314)
3795+++ ../trunk-jpl/externalpackages/export_fig/print2array.m (revision 21315)
3796@@ -1,3 +1,4 @@
3797+function [A, bcol] = print2array(fig, res, renderer, gs_options)
3798 %PRINT2ARRAY Exports a figure to an image array
3799 %
3800 % Examples:
3801@@ -5,6 +6,7 @@
3802 % A = print2array(figure_handle)
3803 % A = print2array(figure_handle, resolution)
3804 % A = print2array(figure_handle, resolution, renderer)
3805+% A = print2array(figure_handle, resolution, renderer, gs_options)
3806 % [A bcol] = print2array(...)
3807 %
3808 % This function outputs a bitmap image of the given figure, at the desired
3809@@ -19,180 +21,224 @@
3810 % resolution. Default: 1.
3811 % renderer - string containing the renderer paramater to be passed to
3812 % print. Default: '-opengl'.
3813+% gs_options - optional ghostscript options (e.g.: '-dNoOutputFonts'). If
3814+% multiple options are needed, enclose in call array: {'-a','-b'}
3815 %
3816 % OUT:
3817 % A - MxNx3 uint8 image of the figure.
3818 % bcol - 1x3 uint8 vector of the background color
3819
3820-% Copyright (C) Oliver Woodford 2008-2012
3821-
3822+% Copyright (C) Oliver Woodford 2008-2014, Yair Altman 2015-
3823+%{
3824 % 05/09/11: Set EraseModes to normal when using opengl or zbuffer
3825-% renderers. Thanks to Pawel Kocieniewski for reporting the
3826-% issue.
3827-% 21/09/11: Bug fix: unit8 -> uint8! Thanks to Tobias Lamour for reporting
3828-% the issue.
3829-% 14/11/11: Bug fix: stop using hardcopy(), as it interfered with figure
3830-% size and erasemode settings. Makes it a bit slower, but more
3831-% reliable. Thanks to Phil Trinh and Meelis Lootus for reporting
3832-% the issues.
3833+% renderers. Thanks to Pawel Kocieniewski for reporting the issue.
3834+% 21/09/11: Bug fix: unit8 -> uint8! Thanks to Tobias Lamour for reporting it.
3835+% 14/11/11: Bug fix: stop using hardcopy(), as it interfered with figure size
3836+% and erasemode settings. Makes it a bit slower, but more reliable.
3837+% Thanks to Phil Trinh and Meelis Lootus for reporting the issues.
3838 % 09/12/11: Pass font path to ghostscript.
3839 % 27/01/12: Bug fix affecting painters rendering tall figures. Thanks to
3840 % Ken Campbell for reporting it.
3841-% 03/04/12: Bug fix to median input. Thanks to Andy Matthews for reporting
3842-% it.
3843+% 03/04/12: Bug fix to median input. Thanks to Andy Matthews for reporting it.
3844 % 26/10/12: Set PaperOrientation to portrait. Thanks to Michael Watts for
3845 % reporting the issue.
3846+% 26/02/15: If temp dir is not writable, use the current folder for temp
3847+% EPS/TIF files (Javier Paredes)
3848+% 27/02/15: Display suggested workarounds to internal print() error (issue #16)
3849+% 28/02/15: Enable users to specify optional ghostscript options (issue #36)
3850+% 10/03/15: Fixed minor warning reported by Paul Soderlind; fixed code indentation
3851+% 28/05/15: Fixed issue #69: patches with LineWidth==0.75 appear wide (internal bug in Matlab's print() func)
3852+% 07/07/15: Fixed issue #83: use numeric handles in HG1
3853+%}
3854
3855-function [A, bcol] = print2array(fig, res, renderer)
3856-% Generate default input arguments, if needed
3857-if nargin < 2
3858- res = 1;
3859- if nargin < 1
3860- fig = gcf;
3861+ % Generate default input arguments, if needed
3862+ if nargin < 2
3863+ res = 1;
3864+ if nargin < 1
3865+ fig = gcf;
3866+ end
3867 end
3868-end
3869-% Warn if output is large
3870-old_mode = get(fig, 'Units');
3871-set(fig, 'Units', 'pixels');
3872-px = get(fig, 'Position');
3873-set(fig, 'Units', old_mode);
3874-npx = prod(px(3:4)*res)/1e6;
3875-if npx > 30
3876- % 30M pixels or larger!
3877- warning('MATLAB:LargeImage', 'print2array generating a %.1fM pixel image. This could be slow and might also cause memory problems.', npx);
3878-end
3879-% Retrieve the background colour
3880-bcol = get(fig, 'Color');
3881-% Set the resolution parameter
3882-res_str = ['-r' num2str(ceil(get(0, 'ScreenPixelsPerInch')*res))];
3883-% Generate temporary file name
3884-tmp_nam = [tempname '.tif'];
3885-if nargin > 2 && strcmp(renderer, '-painters')
3886- % Print to eps file
3887- tmp_eps = [tempname '.eps'];
3888- print2eps(tmp_eps, fig, 0, renderer, '-loose');
3889+ % Warn if output is large
3890+ old_mode = get(fig, 'Units');
3891+ set(fig, 'Units', 'pixels');
3892+ px = get(fig, 'Position');
3893+ set(fig, 'Units', old_mode);
3894+ npx = prod(px(3:4)*res)/1e6;
3895+ if npx > 30
3896+ % 30M pixels or larger!
3897+ warning('MATLAB:LargeImage', 'print2array generating a %.1fM pixel image. This could be slow and might also cause memory problems.', npx);
3898+ end
3899+ % Retrieve the background colour
3900+ bcol = get(fig, 'Color');
3901+ % Set the resolution parameter
3902+ res_str = ['-r' num2str(ceil(get(0, 'ScreenPixelsPerInch')*res))];
3903+ % Generate temporary file name
3904+ tmp_nam = [tempname '.tif'];
3905 try
3906- % Initialize the command to export to tiff using ghostscript
3907- cmd_str = ['-dEPSCrop -q -dNOPAUSE -dBATCH ' res_str ' -sDEVICE=tiff24nc'];
3908- % Set the font path
3909- fp = font_path();
3910- if ~isempty(fp)
3911- cmd_str = [cmd_str ' -sFONTPATH="' fp '"'];
3912+ % Ensure that the temp dir is writable (Javier Paredes 26/2/15)
3913+ fid = fopen(tmp_nam,'w');
3914+ fwrite(fid,1);
3915+ fclose(fid);
3916+ delete(tmp_nam); % cleanup
3917+ isTempDirOk = true;
3918+ catch
3919+ % Temp dir is not writable, so use the current folder
3920+ [dummy,fname,fext] = fileparts(tmp_nam); %#ok<ASGLU>
3921+ fpath = pwd;
3922+ tmp_nam = fullfile(fpath,[fname fext]);
3923+ isTempDirOk = false;
3924+ end
3925+ % Enable users to specify optional ghostscript options (issue #36)
3926+ if nargin > 3 && ~isempty(gs_options)
3927+ if iscell(gs_options)
3928+ gs_options = sprintf(' %s',gs_options{:});
3929+ elseif ~ischar(gs_options)
3930+ error('gs_options input argument must be a string or cell-array of strings');
3931+ else
3932+ gs_options = [' ' gs_options];
3933 end
3934- % Add the filenames
3935- cmd_str = [cmd_str ' -sOutputFile="' tmp_nam '" "' tmp_eps '"'];
3936- % Execute the ghostscript command
3937- ghostscript(cmd_str);
3938- catch me
3939- % Delete the intermediate file
3940- delete(tmp_eps);
3941- rethrow(me);
3942+ else
3943+ gs_options = '';
3944 end
3945- % Delete the intermediate file
3946- delete(tmp_eps);
3947- % Read in the generated bitmap
3948- A = imread(tmp_nam);
3949- % Delete the temporary bitmap file
3950- delete(tmp_nam);
3951- % Set border pixels to the correct colour
3952- if isequal(bcol, 'none')
3953- bcol = [];
3954- elseif isequal(bcol, [1 1 1])
3955- bcol = uint8([255 255 255]);
3956- else
3957- for l = 1:size(A, 2)
3958- if ~all(reshape(A(:,l,:) == 255, [], 1))
3959- break;
3960- end
3961+ if nargin > 2 && strcmp(renderer, '-painters')
3962+ % Print to eps file
3963+ if isTempDirOk
3964+ tmp_eps = [tempname '.eps'];
3965+ else
3966+ tmp_eps = fullfile(fpath,[fname '.eps']);
3967 end
3968- for r = size(A, 2):-1:l
3969- if ~all(reshape(A(:,r,:) == 255, [], 1))
3970- break;
3971+ print2eps(tmp_eps, fig, 0, renderer, '-loose');
3972+ try
3973+ % Initialize the command to export to tiff using ghostscript
3974+ cmd_str = ['-dEPSCrop -q -dNOPAUSE -dBATCH ' res_str ' -sDEVICE=tiff24nc'];
3975+ % Set the font path
3976+ fp = font_path();
3977+ if ~isempty(fp)
3978+ cmd_str = [cmd_str ' -sFONTPATH="' fp '"'];
3979 end
3980+ % Add the filenames
3981+ cmd_str = [cmd_str ' -sOutputFile="' tmp_nam '" "' tmp_eps '"' gs_options];
3982+ % Execute the ghostscript command
3983+ ghostscript(cmd_str);
3984+ catch me
3985+ % Delete the intermediate file
3986+ delete(tmp_eps);
3987+ rethrow(me);
3988 end
3989- for t = 1:size(A, 1)
3990- if ~all(reshape(A(t,:,:) == 255, [], 1))
3991- break;
3992+ % Delete the intermediate file
3993+ delete(tmp_eps);
3994+ % Read in the generated bitmap
3995+ A = imread(tmp_nam);
3996+ % Delete the temporary bitmap file
3997+ delete(tmp_nam);
3998+ % Set border pixels to the correct colour
3999+ if isequal(bcol, 'none')
4000+ bcol = [];
4001+ elseif isequal(bcol, [1 1 1])
4002+ bcol = uint8([255 255 255]);
4003+ else
4004+ for l = 1:size(A, 2)
4005+ if ~all(reshape(A(:,l,:) == 255, [], 1))
4006+ break;
4007+ end
4008 end
4009- end
4010- for b = size(A, 1):-1:t
4011- if ~all(reshape(A(b,:,:) == 255, [], 1))
4012- break;
4013+ for r = size(A, 2):-1:l
4014+ if ~all(reshape(A(:,r,:) == 255, [], 1))
4015+ break;
4016+ end
4017 end
4018+ for t = 1:size(A, 1)
4019+ if ~all(reshape(A(t,:,:) == 255, [], 1))
4020+ break;
4021+ end
4022+ end
4023+ for b = size(A, 1):-1:t
4024+ if ~all(reshape(A(b,:,:) == 255, [], 1))
4025+ break;
4026+ end
4027+ end
4028+ bcol = uint8(median(single([reshape(A(:,[l r],:), [], size(A, 3)); reshape(A([t b],:,:), [], size(A, 3))]), 1));
4029+ for c = 1:size(A, 3)
4030+ A(:,[1:l-1, r+1:end],c) = bcol(c);
4031+ A([1:t-1, b+1:end],:,c) = bcol(c);
4032+ end
4033 end
4034- bcol = uint8(median(single([reshape(A(:,[l r],:), [], size(A, 3)); reshape(A([t b],:,:), [], size(A, 3))]), 1));
4035- for c = 1:size(A, 3)
4036- A(:,[1:l-1, r+1:end],c) = bcol(c);
4037- A([1:t-1, b+1:end],:,c) = bcol(c);
4038+ else
4039+ if nargin < 3
4040+ renderer = '-opengl';
4041 end
4042- end
4043-else
4044- if nargin < 3
4045- renderer = '-opengl';
4046- end
4047- err = false;
4048- % Set paper size
4049- old_pos_mode = get(fig, 'PaperPositionMode');
4050- old_orientation = get(fig, 'PaperOrientation');
4051- set(fig, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait');
4052- try
4053- % Print to tiff file
4054- print(fig, renderer, res_str, '-dtiff', tmp_nam);
4055- % Read in the printed file
4056- A = imread(tmp_nam);
4057- % Delete the temporary file
4058- delete(tmp_nam);
4059- catch ex
4060- err = true;
4061- end
4062- % Reset paper size
4063- set(fig, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation);
4064- % Throw any error that occurred
4065- if err
4066- rethrow(ex);
4067- end
4068- % Set the background color
4069- if isequal(bcol, 'none')
4070- bcol = [];
4071- else
4072- bcol = bcol * 255;
4073- if isequal(bcol, round(bcol))
4074- bcol = uint8(bcol);
4075+ err = false;
4076+ % Set paper size
4077+ old_pos_mode = get(fig, 'PaperPositionMode');
4078+ old_orientation = get(fig, 'PaperOrientation');
4079+ set(fig, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait');
4080+ try
4081+ % Workaround for issue #69: patches with LineWidth==0.75 appear wide (internal bug in Matlab's print() function)
4082+ fp = []; % in case we get an error below
4083+ fp = findall(fig, 'Type','patch', 'LineWidth',0.75);
4084+ set(fp, 'LineWidth',0.5);
4085+ % Fix issue #83: use numeric handles in HG1
4086+ if ~using_hg2(fig), fig = double(fig); end
4087+ % Print to tiff file
4088+ print(fig, renderer, res_str, '-dtiff', tmp_nam);
4089+ % Read in the printed file
4090+ A = imread(tmp_nam);
4091+ % Delete the temporary file
4092+ delete(tmp_nam);
4093+ catch ex
4094+ err = true;
4095+ end
4096+ set(fp, 'LineWidth',0.75); % restore original figure appearance
4097+ % Reset paper size
4098+ set(fig, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation);
4099+ % Throw any error that occurred
4100+ if err
4101+ % Display suggested workarounds to internal print() error (issue #16)
4102+ fprintf(2, 'An error occured with Matlab''s builtin print function.\nTry setting the figure Renderer to ''painters'' or use opengl(''software'').\n\n');
4103+ rethrow(ex);
4104+ end
4105+ % Set the background color
4106+ if isequal(bcol, 'none')
4107+ bcol = [];
4108 else
4109- bcol = squeeze(A(1,1,:));
4110+ bcol = bcol * 255;
4111+ if isequal(bcol, round(bcol))
4112+ bcol = uint8(bcol);
4113+ else
4114+ bcol = squeeze(A(1,1,:));
4115+ end
4116 end
4117 end
4118-end
4119-% Check the output size is correct
4120-if isequal(res, round(res))
4121- px = [px([4 3])*res 3];
4122- if ~isequal(size(A), px)
4123- % Correct the output size
4124- A = A(1:min(end,px(1)),1:min(end,px(2)),:);
4125+ % Check the output size is correct
4126+ if isequal(res, round(res))
4127+ px = round([px([4 3])*res 3]); % round() to avoid an indexing warning below
4128+ if ~isequal(size(A), px)
4129+ % Correct the output size
4130+ A = A(1:min(end,px(1)),1:min(end,px(2)),:);
4131+ end
4132 end
4133 end
4134-end
4135
4136 % Function to return (and create, where necessary) the font path
4137 function fp = font_path()
4138-fp = user_string('gs_font_path');
4139-if ~isempty(fp)
4140- return
4141-end
4142-% Create the path
4143-% Start with the default path
4144-fp = getenv('GS_FONTPATH');
4145-% Add on the typical directories for a given OS
4146-if ispc
4147+ fp = user_string('gs_font_path');
4148 if ~isempty(fp)
4149- fp = [fp ';'];
4150+ return
4151 end
4152- fp = [fp getenv('WINDIR') filesep 'Fonts'];
4153-else
4154- if ~isempty(fp)
4155- fp = [fp ':'];
4156+ % Create the path
4157+ % Start with the default path
4158+ fp = getenv('GS_FONTPATH');
4159+ % Add on the typical directories for a given OS
4160+ if ispc
4161+ if ~isempty(fp)
4162+ fp = [fp ';'];
4163+ end
4164+ fp = [fp getenv('WINDIR') filesep 'Fonts'];
4165+ else
4166+ if ~isempty(fp)
4167+ fp = [fp ':'];
4168+ end
4169+ fp = [fp '/usr/share/fonts:/usr/local/share/fonts:/usr/share/fonts/X11:/usr/local/share/fonts/X11:/usr/share/fonts/truetype:/usr/local/share/fonts/truetype'];
4170 end
4171- fp = [fp '/usr/share/fonts:/usr/local/share/fonts:/usr/share/fonts/X11:/usr/local/share/fonts/X11:/usr/share/fonts/truetype:/usr/local/share/fonts/truetype'];
4172+ user_string('gs_font_path', fp);
4173 end
4174-user_string('gs_font_path', fp);
4175-end
4176Index: ../trunk-jpl/externalpackages/export_fig/ImageSelection.java
4177===================================================================
4178--- ../trunk-jpl/externalpackages/export_fig/ImageSelection.java (revision 0)
4179+++ ../trunk-jpl/externalpackages/export_fig/ImageSelection.java (revision 21315)
4180@@ -0,0 +1,38 @@
4181+/*
4182+ * Based on code snippet from
4183+ * http://java.sun.com/developer/technicalArticles/releases/data/
4184+ *
4185+ * Copyright © 2008, 2010 Oracle and/or its affiliates. All rights reserved. Use is subject to license terms.
4186+ */
4187+
4188+import java.awt.image.BufferedImage;
4189+import java.awt.datatransfer.*;
4190+
4191+public class ImageSelection implements Transferable {
4192+
4193+ private static final DataFlavor flavors[] =
4194+ {DataFlavor.imageFlavor};
4195+
4196+ private BufferedImage image;
4197+
4198+ public ImageSelection(BufferedImage image) {
4199+ this.image = image;
4200+ }
4201+
4202+ // Transferable
4203+ public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
4204+ if (flavor.equals(flavors[0]) == false) {
4205+ throw new UnsupportedFlavorException(flavor);
4206+ }
4207+ return image;
4208+ }
4209+
4210+ public DataFlavor[] getTransferDataFlavors() {
4211+ return flavors;
4212+ }
4213+
4214+ public boolean isDataFlavorSupported(DataFlavor
4215+ flavor) {
4216+ return flavor.equals(flavors[0]);
4217+ }
4218+}
4219\ No newline at end of file
4220
4221Property changes on: ../trunk-jpl/externalpackages/export_fig/ImageSelection.java
4222___________________________________________________________________
4223Added: svn:executable
4224 + *
4225
4226Index: ../trunk-jpl/externalpackages/export_fig/pdftops.m
4227===================================================================
4228--- ../trunk-jpl/externalpackages/export_fig/pdftops.m (revision 21314)
4229+++ ../trunk-jpl/externalpackages/export_fig/pdftops.m (revision 21315)
4230@@ -15,7 +15,7 @@
4231 % http://www.foolabs.com/xpdf
4232 %
4233 % IN:
4234-% cmd - Command string to be passed into pdftops.
4235+% cmd - Command string to be passed into pdftops (e.g. '-help').
4236 %
4237 % OUT:
4238 % status - 0 iff command ran without problem.
4239@@ -23,87 +23,128 @@
4240
4241 % Copyright: Oliver Woodford, 2009-2010
4242
4243-% Thanks to Jonas Dorn for the fix for the title of the uigetdir window on
4244-% Mac OS.
4245-% Thanks to Christoph Hertel for pointing out a bug in check_xpdf_path
4246-% under linux.
4247+% Thanks to Jonas Dorn for the fix for the title of the uigetdir window on Mac OS.
4248+% Thanks to Christoph Hertel for pointing out a bug in check_xpdf_path under linux.
4249 % 23/01/2014 - Add full path to pdftops.txt in warning.
4250+% 27/05/2015 - Fixed alert in case of missing pdftops; fixed code indentation
4251+% 02/05/2016 - Added possible error explanation suggested by Michael Pacer (issue #137)
4252+% 02/05/2016 - Search additional possible paths suggested by Jonas Stein (issue #147)
4253+% 03/05/2016 - Display the specific error message if pdftops fails for some reason (issue #148)
4254
4255-% Call pdftops
4256-[varargout{1:nargout}] = system(sprintf('"%s" %s', xpdf_path, cmd));
4257+ % Call pdftops
4258+ [varargout{1:nargout}] = system(sprintf('"%s" %s', xpdf_path, cmd));
4259 end
4260
4261 function path_ = xpdf_path
4262-% Return a valid path
4263-% Start with the currently set path
4264-path_ = user_string('pdftops');
4265-% Check the path works
4266-if check_xpdf_path(path_)
4267- return
4268-end
4269-% Check whether the binary is on the path
4270-if ispc
4271- bin = 'pdftops.exe';
4272-else
4273- bin = 'pdftops';
4274-end
4275-if check_store_xpdf_path(bin)
4276- path_ = bin;
4277- return
4278-end
4279-% Search the obvious places
4280-if ispc
4281- path_ = 'C:\Program Files\xpdf\pdftops.exe';
4282-else
4283- path_ = '/usr/local/bin/pdftops';
4284-end
4285-if check_store_xpdf_path(path_)
4286- return
4287-end
4288-% Ask the user to enter the path
4289-while 1
4290- if strncmp(computer,'MAC',3) % Is a Mac
4291- % Give separate warning as the uigetdir dialogue box doesn't have a
4292- % title
4293- uiwait(warndlg('Pdftops not found. Please locate the program, or install xpdf-tools from http://users.phg-online.de/tk/MOSXS/.'))
4294+ % Return a valid path
4295+ % Start with the currently set path
4296+ path_ = user_string('pdftops');
4297+ % Check the path works
4298+ if check_xpdf_path(path_)
4299+ return
4300 end
4301- base = uigetdir('/', 'Pdftops not found. Please locate the program.');
4302- if isequal(base, 0)
4303- % User hit cancel or closed window
4304- break;
4305+ % Check whether the binary is on the path
4306+ if ispc
4307+ bin = 'pdftops.exe';
4308+ else
4309+ bin = 'pdftops';
4310 end
4311- base = [base filesep];
4312- bin_dir = {'', ['bin' filesep], ['lib' filesep]};
4313- for a = 1:numel(bin_dir)
4314- path_ = [base bin_dir{a} bin];
4315- if exist(path_, 'file') == 2
4316- break;
4317+ if check_store_xpdf_path(bin)
4318+ path_ = bin;
4319+ return
4320+ end
4321+ % Search the obvious places
4322+ if ispc
4323+ paths = {'C:\Program Files\xpdf\pdftops.exe', 'C:\Program Files (x86)\xpdf\pdftops.exe'};
4324+ else
4325+ paths = {'/usr/bin/pdftops', '/usr/local/bin/pdftops'};
4326+ end
4327+ for a = 1:numel(paths)
4328+ path_ = paths{a};
4329+ if check_store_xpdf_path(path_)
4330+ return
4331 end
4332 end
4333- if check_store_xpdf_path(path_)
4334- return
4335+
4336+ % Ask the user to enter the path
4337+ errMsg1 = 'Pdftops not found. Please locate the program, or install xpdf-tools from ';
4338+ url1 = 'http://foolabs.com/xpdf';
4339+ fprintf(2, '%s\n', [errMsg1 '<a href="matlab:web(''-browser'',''' url1 ''');">' url1 '</a>']);
4340+ errMsg1 = [errMsg1 url1];
4341+ %if strncmp(computer,'MAC',3) % Is a Mac
4342+ % % Give separate warning as the MacOS uigetdir dialogue box doesn't have a title
4343+ % uiwait(warndlg(errMsg1))
4344+ %end
4345+
4346+ % Provide an alternative possible explanation as per issue #137
4347+ errMsg2 = 'If you have pdftops installed, perhaps Matlab is shaddowing it as described in ';
4348+ url2 = 'https://github.com/altmany/export_fig/issues/137';
4349+ fprintf(2, '%s\n', [errMsg2 '<a href="matlab:web(''-browser'',''' url2 ''');">issue #137</a>']);
4350+ errMsg2 = [errMsg2 url1];
4351+
4352+ state = 0;
4353+ while 1
4354+ if state
4355+ option1 = 'Install pdftops';
4356+ else
4357+ option1 = 'Issue #137';
4358+ end
4359+ answer = questdlg({errMsg1,'',errMsg2},'Pdftops error',option1,'Locate pdftops','Cancel','Cancel');
4360+ drawnow; % prevent a Matlab hang: http://undocumentedmatlab.com/blog/solving-a-matlab-hang-problem
4361+ switch answer
4362+ case 'Install pdftops'
4363+ web('-browser',url1);
4364+ case 'Issue #137'
4365+ web('-browser',url2);
4366+ state = 1;
4367+ case 'Locate pdftops'
4368+ base = uigetdir('/', errMsg1);
4369+ if isequal(base, 0)
4370+ % User hit cancel or closed window
4371+ break
4372+ end
4373+ base = [base filesep]; %#ok<AGROW>
4374+ bin_dir = {'', ['bin' filesep], ['lib' filesep]};
4375+ for a = 1:numel(bin_dir)
4376+ path_ = [base bin_dir{a} bin];
4377+ if exist(path_, 'file') == 2
4378+ break
4379+ end
4380+ end
4381+ if check_store_xpdf_path(path_)
4382+ return
4383+ end
4384+
4385+ otherwise % User hit Cancel or closed window
4386+ break
4387+ end
4388 end
4389+ error('pdftops executable not found.');
4390 end
4391-error('pdftops executable not found.');
4392-end
4393
4394 function good = check_store_xpdf_path(path_)
4395-% Check the path is valid
4396-good = check_xpdf_path(path_);
4397-if ~good
4398- return
4399+ % Check the path is valid
4400+ good = check_xpdf_path(path_);
4401+ if ~good
4402+ return
4403+ end
4404+ % Update the current default path to the path found
4405+ if ~user_string('pdftops', path_)
4406+ warning('Path to pdftops executable could not be saved. Enter it manually in %s.', fullfile(fileparts(which('user_string.m')), '.ignore', 'pdftops.txt'));
4407+ return
4408+ end
4409 end
4410-% Update the current default path to the path found
4411-if ~user_string('pdftops', path_)
4412- warning('Path to pdftops executable could not be saved. Enter it manually in %s.', fullfile(fileparts(which('user_string.m')), '.ignore', 'pdftops.txt'));
4413- return
4414-end
4415-end
4416
4417 function good = check_xpdf_path(path_)
4418-% Check the path is valid
4419-[good, message] = system(sprintf('"%s" -h', path_));
4420-% system returns good = 1 even when the command runs
4421-% Look for something distinct in the help text
4422-good = ~isempty(strfind(message, 'PostScript'));
4423+ % Check the path is valid
4424+ [good, message] = system(sprintf('"%s" -h', path_)); %#ok<ASGLU>
4425+ % system returns good = 1 even when the command runs
4426+ % Look for something distinct in the help text
4427+ good = ~isempty(strfind(message, 'PostScript'));
4428+
4429+ % Display the error message if the pdftops executable exists but fails for some reason
4430+ if ~good && exist(path_,'file') % file exists but generates an error
4431+ fprintf('Error running %s:\n', path_);
4432+ fprintf(2,'%s\n\n',message);
4433+ end
4434 end
4435Index: ../trunk-jpl/externalpackages/export_fig/fix_lines.m
4436===================================================================
4437--- ../trunk-jpl/externalpackages/export_fig/fix_lines.m (revision 21314)
4438+++ ../trunk-jpl/externalpackages/export_fig/fix_lines.m (revision 21315)
4439@@ -37,8 +37,16 @@
4440 % Thank you to Laurence K for suggesting the check to see if the file was
4441 % opened.
4442
4443+% 01/03/15: Issue #20: warn users if using this function in HG2 (R2014b+)
4444+% 27/03/15: Fixed out of memory issue with enormous EPS files (generated by print() with OpenGL renderer), related to issue #39
4445+
4446 function fstrm = fix_lines(fstrm, fname2)
4447
4448+% Issue #20: warn users if using this function in HG2 (R2014b+)
4449+if using_hg2
4450+ warning('export_fig:hg2','The fix_lines function should not be used in this Matlab version.');
4451+end
4452+
4453 if nargout == 0 || nargin > 1
4454 if nargin < 2
4455 % Overwrite the input file
4456@@ -113,11 +121,6 @@
4457 end
4458 end
4459
4460-% Isolate line style definition section
4461-first_sec = strfind(fstrm, '% line types:');
4462-[second_sec, remaining] = strtok(fstrm(first_sec+1:end), '/');
4463-[remaining, remaining] = strtok(remaining, '%');
4464-
4465 % Define the new styles, including the new GR format
4466 % Dot and dash lengths have two parts: a constant amount plus a line width
4467 % variable amount. The constant amount comes after dpi2point, and the
4468@@ -134,7 +137,12 @@
4469 '/GR { [0 dpi2point mul 4 dpi2point mul] 0 setdash 1 setlinecap } bdef'}; % Grid lines - dot spacing remains constant
4470
4471 % Construct the output
4472-fstrm = [fstrm(1:first_sec) second_sec sprintf('%s\r', new_style{:}) remaining];
4473+% This is the original (memory-intensive) code:
4474+%first_sec = strfind(fstrm, '% line types:'); % Isolate line style definition section
4475+%[second_sec, remaining] = strtok(fstrm(first_sec+1:end), '/');
4476+%[remaining, remaining] = strtok(remaining, '%');
4477+%fstrm = [fstrm(1:first_sec) second_sec sprintf('%s\r', new_style{:}) remaining];
4478+fstrm = regexprep(fstrm,'(% line types:.+?)/.+?%',['$1',sprintf('%s\r',new_style{:}),'%']);
4479
4480 % Write the output file
4481 if nargout == 0 || nargin > 1
4482Index: ../trunk-jpl/externalpackages/export_fig/isolate_axes.m
4483===================================================================
4484--- ../trunk-jpl/externalpackages/export_fig/isolate_axes.m (revision 21314)
4485+++ ../trunk-jpl/externalpackages/export_fig/isolate_axes.m (revision 21315)
4486@@ -1,3 +1,4 @@
4487+function fh = isolate_axes(ah, vis)
4488 %ISOLATE_AXES Isolate the specified axes in a figure on their own
4489 %
4490 % Examples:
4491@@ -21,99 +22,109 @@
4492 % Copyright (C) Oliver Woodford 2011-2013
4493
4494 % Thank you to Rosella Blatt for reporting a bug to do with axes in GUIs
4495-% 16/3/2012 Moved copyfig to its own function. Thanks to Bob Fratantonio
4496-% for pointing out that the function is also used in export_fig.m.
4497-% 12/12/12 - Add support for isolating uipanels. Thanks to michael for
4498-% suggesting it.
4499-% 08/10/13 - Bug fix to allchildren suggested by Will Grant (many thanks!).
4500-% 05/12/13 - Bug fix to axes having different units. Thanks to Remington
4501-% Reid for reporting the issue.
4502+% 16/03/12: Moved copyfig to its own function. Thanks to Bob Fratantonio
4503+% for pointing out that the function is also used in export_fig.m
4504+% 12/12/12: Add support for isolating uipanels. Thanks to michael for suggesting it
4505+% 08/10/13: Bug fix to allchildren suggested by Will Grant (many thanks!)
4506+% 05/12/13: Bug fix to axes having different units. Thanks to Remington Reid for reporting
4507+% 21/04/15: Bug fix for exporting uipanels with legend/colorbar on HG1 (reported by Alvaro
4508+% on FEX page as a comment on 24-Apr-2014); standardized indentation & help section
4509+% 22/04/15: Bug fix: legends and colorbars were not exported when exporting axes handle in HG2
4510
4511-function fh = isolate_axes(ah, vis)
4512-% Make sure we have an array of handles
4513-if ~all(ishandle(ah))
4514- error('ah must be an array of handles');
4515-end
4516-% Check that the handles are all for axes or uipanels, and are all in the same figure
4517-fh = ancestor(ah(1), 'figure');
4518-nAx = numel(ah);
4519-for a = 1:nAx
4520- if ~ismember(get(ah(a), 'Type'), {'axes', 'uipanel'})
4521- error('All handles must be axes or uipanel handles.');
4522+ % Make sure we have an array of handles
4523+ if ~all(ishandle(ah))
4524+ error('ah must be an array of handles');
4525 end
4526- if ~isequal(ancestor(ah(a), 'figure'), fh)
4527- error('Axes must all come from the same figure.');
4528+ % Check that the handles are all for axes or uipanels, and are all in the same figure
4529+ fh = ancestor(ah(1), 'figure');
4530+ nAx = numel(ah);
4531+ for a = 1:nAx
4532+ if ~ismember(get(ah(a), 'Type'), {'axes', 'uipanel'})
4533+ error('All handles must be axes or uipanel handles.');
4534+ end
4535+ if ~isequal(ancestor(ah(a), 'figure'), fh)
4536+ error('Axes must all come from the same figure.');
4537+ end
4538 end
4539-end
4540-% Tag the objects so we can find them in the copy
4541-old_tag = get(ah, 'Tag');
4542-if nAx == 1
4543- old_tag = {old_tag};
4544-end
4545-set(ah, 'Tag', 'ObjectToCopy');
4546-% Create a new figure exactly the same as the old one
4547-fh = copyfig(fh); %copyobj(fh, 0);
4548-if nargin < 2 || ~vis
4549- set(fh, 'Visible', 'off');
4550-end
4551-% Reset the object tags
4552-for a = 1:nAx
4553- set(ah(a), 'Tag', old_tag{a});
4554-end
4555-% Find the objects to save
4556-ah = findall(fh, 'Tag', 'ObjectToCopy');
4557-if numel(ah) ~= nAx
4558- close(fh);
4559- error('Incorrect number of objects found.');
4560-end
4561-% Set the axes tags to what they should be
4562-for a = 1:nAx
4563- set(ah(a), 'Tag', old_tag{a});
4564-end
4565-% Keep any legends and colorbars which overlap the subplots
4566-lh = findall(fh, 'Type', 'axes', '-and', {'Tag', 'legend', '-or', 'Tag', 'Colorbar'});
4567-nLeg = numel(lh);
4568-if nLeg > 0
4569- set([ah(:); lh(:)], 'Units', 'normalized');
4570- ax_pos = get(ah, 'OuterPosition');
4571- if nAx > 1
4572- ax_pos = cell2mat(ax_pos(:));
4573+ % Tag the objects so we can find them in the copy
4574+ old_tag = get(ah, 'Tag');
4575+ if nAx == 1
4576+ old_tag = {old_tag};
4577 end
4578- ax_pos(:,3:4) = ax_pos(:,3:4) + ax_pos(:,1:2);
4579- leg_pos = get(lh, 'OuterPosition');
4580- if nLeg > 1;
4581- leg_pos = cell2mat(leg_pos);
4582+ set(ah, 'Tag', 'ObjectToCopy');
4583+ % Create a new figure exactly the same as the old one
4584+ fh = copyfig(fh); %copyobj(fh, 0);
4585+ if nargin < 2 || ~vis
4586+ set(fh, 'Visible', 'off');
4587 end
4588- leg_pos(:,3:4) = leg_pos(:,3:4) + leg_pos(:,1:2);
4589- ax_pos = shiftdim(ax_pos, -1);
4590- % Overlap test
4591- M = bsxfun(@lt, leg_pos(:,1), ax_pos(:,:,3)) & ...
4592- bsxfun(@lt, leg_pos(:,2), ax_pos(:,:,4)) & ...
4593- bsxfun(@gt, leg_pos(:,3), ax_pos(:,:,1)) & ...
4594- bsxfun(@gt, leg_pos(:,4), ax_pos(:,:,2));
4595- ah = [ah; lh(any(M, 2))];
4596+ % Reset the object tags
4597+ for a = 1:nAx
4598+ set(ah(a), 'Tag', old_tag{a});
4599+ end
4600+ % Find the objects to save
4601+ ah = findall(fh, 'Tag', 'ObjectToCopy');
4602+ if numel(ah) ~= nAx
4603+ close(fh);
4604+ error('Incorrect number of objects found.');
4605+ end
4606+ % Set the axes tags to what they should be
4607+ for a = 1:nAx
4608+ set(ah(a), 'Tag', old_tag{a});
4609+ end
4610+ % Keep any legends and colorbars which overlap the subplots
4611+ % Note: in HG1 these are axes objects; in HG2 they are separate objects, therefore we
4612+ % don't test for the type, only the tag (hopefully nobody but Matlab uses them!)
4613+ lh = findall(fh, 'Tag', 'legend', '-or', 'Tag', 'Colorbar');
4614+ nLeg = numel(lh);
4615+ if nLeg > 0
4616+ set([ah(:); lh(:)], 'Units', 'normalized');
4617+ try
4618+ ax_pos = get(ah, 'OuterPosition'); % axes and figures have the OuterPosition property
4619+ catch
4620+ ax_pos = get(ah, 'Position'); % uipanels only have Position, not OuterPosition
4621+ end
4622+ if nAx > 1
4623+ ax_pos = cell2mat(ax_pos(:));
4624+ end
4625+ ax_pos(:,3:4) = ax_pos(:,3:4) + ax_pos(:,1:2);
4626+ try
4627+ leg_pos = get(lh, 'OuterPosition');
4628+ catch
4629+ leg_pos = get(lh, 'Position'); % No OuterPosition in HG2, only in HG1
4630+ end
4631+ if nLeg > 1;
4632+ leg_pos = cell2mat(leg_pos);
4633+ end
4634+ leg_pos(:,3:4) = leg_pos(:,3:4) + leg_pos(:,1:2);
4635+ ax_pos = shiftdim(ax_pos, -1);
4636+ % Overlap test
4637+ M = bsxfun(@lt, leg_pos(:,1), ax_pos(:,:,3)) & ...
4638+ bsxfun(@lt, leg_pos(:,2), ax_pos(:,:,4)) & ...
4639+ bsxfun(@gt, leg_pos(:,3), ax_pos(:,:,1)) & ...
4640+ bsxfun(@gt, leg_pos(:,4), ax_pos(:,:,2));
4641+ ah = [ah; lh(any(M, 2))];
4642+ end
4643+ % Get all the objects in the figure
4644+ axs = findall(fh);
4645+ % Delete everything except for the input objects and associated items
4646+ delete(axs(~ismember(axs, [ah; allchildren(ah); allancestors(ah)])));
4647 end
4648-% Get all the objects in the figure
4649-axs = findall(fh);
4650-% Delete everything except for the input objects and associated items
4651-delete(axs(~ismember(axs, [ah; allchildren(ah); allancestors(ah)])));
4652-end
4653
4654 function ah = allchildren(ah)
4655-ah = findall(ah);
4656-if iscell(ah)
4657- ah = cell2mat(ah);
4658+ ah = findall(ah);
4659+ if iscell(ah)
4660+ ah = cell2mat(ah);
4661+ end
4662+ ah = ah(:);
4663 end
4664-ah = ah(:);
4665-end
4666
4667 function ph = allancestors(ah)
4668-ph = [];
4669-for a = 1:numel(ah)
4670- h = get(ah(a), 'parent');
4671- while h ~= 0
4672- ph = [ph; h];
4673- h = get(h, 'parent');
4674+ ph = [];
4675+ for a = 1:numel(ah)
4676+ h = get(ah(a), 'parent');
4677+ while h ~= 0
4678+ ph = [ph; h];
4679+ h = get(h, 'parent');
4680+ end
4681 end
4682 end
4683-end
Note: See TracBrowser for help on using the repository browser.