%PRINT2EPS Prints figures to eps with improved line styles % % Examples: % print2eps filename % print2eps(filename, fig_handle) % print2eps(filename, fig_handle, options) % % This function saves a figure as an eps file, with two improvements over % MATLAB's print command. First, it improves the line style, making dashed % lines more like those on screen and giving grid lines their own dotted % style. Secondly, it substitutes original font names back into the eps % file, where these have been changed by MATLAB, for up to 11 different % fonts. % %IN: % filename - string containing the name (optionally including full or % relative path) of the file the figure is to be saved as. A % ".eps" extension is added if not there already. If a path is % not specified, the figure is saved in the current directory. % fig_handle - The handle of the figure to be saved. Default: gcf. % options - Additional parameter strings to be passed to print. % Copyright (C) Oliver Woodford 2008-2013 % The idea of editing the EPS file to change line styles comes from Jiro % Doke's FIXPSLINESTYLE (fex id: 17928) % The idea of changing dash length with line width came from comments on % fex id: 5743, but the implementation is mine :) % 14/11/2011: Fix a MATLAB bug rendering black or white text incorrectly. % Thanks to Mathieu Morlighem for reporting the issue and % obtaining a fix from TMW. % 08/12/11: Added ability to correct fonts. Several people have requested % this at one time or another, and also pointed me to printeps % (fex id: 7501), so thank you to them. My implementation (which % was not inspired by printeps - I'd already had the idea for my % approach) goes slightly further in that it allows multiple % fonts to be swapped. % 14/12/11: Fix bug affecting font names containing spaces. Thanks to David % Szwer for reporting the issue. % 25/01/12: Add a font not to be swapped. Thanks to Anna Rafferty and Adam % Jackson for reporting the issue. Also fix a bug whereby using a % font alias can lead to another font being swapped in. % 10/04/12: Make the font swapping case insensitive. % 26/10/12: Set PaperOrientation to portrait. Thanks to Michael Watts for % reporting the issue. % 26/10/12: Fix issue to do with swapping fonts changing other fonts and % sizes we don't want, due to listeners. Thanks to Malcolm Hudson % for reporting the issue. % 22/03/13: Extend font swapping to axes labels. Thanks to Rasmus Ischebeck % for reporting the issue. % 23/07/13: Bug fix to font swapping. Thank to George for reporting the % issue. % 13/08/13: Fix MATLAB feature of not exporting white lines correctly. % Thanks to Sebastian Heßlinger for reporting it. function print2eps(name, fig, varargin) options = {'-depsc2'}; if nargin < 2 fig = gcf; elseif nargin > 2 options = [options varargin]; end % Construct the filename if numel(name) < 5 || ~strcmpi(name(end-3:end), '.eps') name = [name '.eps']; % Add the missing extension end % Find all the used fonts in the figure font_handles = findall(fig, '-property', 'FontName'); fonts = get(font_handles, 'FontName'); if ~iscell(fonts) fonts = {fonts}; end % Map supported font aliases onto the correct name fontsl = lower(fonts); for a = 1:numel(fonts) f = fontsl{a}; f(f==' ') = []; switch f case {'times', 'timesnewroman', 'times-roman'} fontsl{a} = 'times-roman'; case {'arial', 'helvetica'} fontsl{a} = 'helvetica'; case {'newcenturyschoolbook', 'newcenturyschlbk'} fontsl{a} = 'newcenturyschlbk'; otherwise end end fontslu = unique(fontsl); % Determine the font swap table matlab_fonts = {'Helvetica', 'Times-Roman', 'Palatino', 'Bookman', 'Helvetica-Narrow', 'Symbol', ... 'AvantGarde', 'NewCenturySchlbk', 'Courier', 'ZapfChancery', 'ZapfDingbats'}; matlab_fontsl = lower(matlab_fonts); require_swap = find(~ismember(fontslu, matlab_fontsl)); unused_fonts = find(~ismember(matlab_fontsl, fontslu)); font_swap = cell(3, min(numel(require_swap), numel(unused_fonts))); fonts_new = fonts; for a = 1:size(font_swap, 2) font_swap{1,a} = find(strcmp(fontslu{require_swap(a)}, fontsl)); font_swap{2,a} = matlab_fonts{unused_fonts(a)}; font_swap{3,a} = fonts{font_swap{1,a}(1)}; fonts_new(font_swap{1,a}) = {font_swap{2,a}}; end % Swap the fonts if ~isempty(font_swap) fonts_size = get(font_handles, 'FontSize'); if iscell(fonts_size) fonts_size = cell2mat(fonts_size); end M = false(size(font_handles)); % Loop because some changes may not stick first time, due to listeners c = 0; update = zeros(1000, 1); for b = 1:10 % Limit number of loops to avoid infinite loop case for a = 1:numel(M) M(a) = ~isequal(get(font_handles(a), 'FontName'), fonts_new{a}) || ~isequal(get(font_handles(a), 'FontSize'), fonts_size(a)); if M(a) set(font_handles(a), 'FontName', fonts_new{a}, 'FontSize', fonts_size(a)); c = c + 1; update(c) = a; end end if ~any(M) break; end end % Compute the order to revert fonts later, without the need of a loop [update, M] = unique(update(1:c)); [M, M] = sort(M); update = reshape(update(M), 1, []); end % Set paper size bUseDesktop = usejava('desktop'); if(bUseDesktop) old_pos_mode = get(fig, 'PaperPositionMode'); old_orientation = get(fig, 'PaperOrientation'); set(fig, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait'); end % MATLAB bug fix - black and white text can come out inverted sometimes % Find the white and black text white_text_handles = findobj(fig, 'Type', 'text'); M = get(white_text_handles, 'Color'); if iscell(M) M = cell2mat(M); end M = sum(M, 2); black_text_handles = white_text_handles(M == 0); white_text_handles = white_text_handles(M == 3); % Set the font colors slightly off their correct values set(black_text_handles, 'Color', [0 0 0] + eps); set(white_text_handles, 'Color', [1 1 1] - eps); % MATLAB bug fix - white lines can come out funny sometimes % Find the white lines white_line_handles = findobj(fig, 'Type', 'line'); M = get(white_line_handles, 'Color'); if iscell(M) M = cell2mat(M); end white_line_handles = white_line_handles(sum(M, 2) == 3); % Set the line color slightly off white set(white_line_handles, 'Color', [1 1 1] - 0.00001); % Print to eps file print(fig, options{:}, name); % Reset the font and line colors set(black_text_handles, 'Color', [0 0 0]); set(white_text_handles, 'Color', [1 1 1]); set(white_line_handles, 'Color', [1 1 1]); if(bUseDesktop) % Reset paper size set(fig, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation); end % Correct the fonts if ~isempty(font_swap) % Reset the font names in the figure for a = update set(font_handles(a), 'FontName', fonts{a}, 'FontSize', fonts_size(a)); end % Replace the font names in the eps file font_swap = font_swap(2:3,:); try swap_fonts(name, font_swap{:}); catch warning('swap_fonts() failed. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.'); return end end % Fix the line styles try fix_lines(name); catch warning('fix_lines() failed. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.'); end return function swap_fonts(fname, varargin) % Read in the file fh = fopen(fname, 'r'); if fh == -1 error('File %s not found.', fname); end try fstrm = fread(fh, '*char')'; catch ex fclose(fh); rethrow(ex); end fclose(fh); % Replace the font names for a = 1:2:numel(varargin) fstrm = regexprep(fstrm, [varargin{a} '-?[a-zA-Z]*\>'], varargin{a+1}(~isspace(varargin{a+1}))); end % Write out the updated file fh = fopen(fname, 'w'); if fh == -1 error('Unable to open %s for writing.', fname2); end try fwrite(fh, fstrm, 'char*1'); catch ex fclose(fh); rethrow(ex); end fclose(fh); return