forked from altmany/export_fig
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprint2eps.m
262 lines (252 loc) · 9.27 KB
/
print2eps.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
%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-2014
% 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
% Set paper size
old_pos_mode = get(fig, 'PaperPositionMode');
old_orientation = get(fig, 'PaperOrientation');
set(fig, 'PaperPositionMode', 'auto', 'PaperOrientation', 'portrait');
% 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
% 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]);
% Reset paper size
set(fig, 'PaperPositionMode', old_pos_mode, 'PaperOrientation', old_orientation);
% 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
if using_hg2(fig)
% Move the bounding box to the top of the file
try
move_bb(name);
catch
warning('move_bb() failed. This is usually because the figure contains a large number of patch objects. Consider exporting to a bitmap format in this case.');
end
else
% 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
end
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})));
fstrm = regexprep(fstrm, varargin{a}, 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);
function move_bb(fname)
% 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);
% Find the bounding box
[s, e] = regexp(fstrm, '%%BoundingBox: [\w\s()]*%%');
if numel(s) == 2
fstrm = fstrm([1:s(1)-1 s(2):e(2)-2 e(1)-1:s(2)-1 e(2)-1:end]);
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);