-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathnr_ps2pdf.m
393 lines (358 loc) · 16 KB
/
nr_ps2pdf.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
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
function ps2pdf(varargin)
%PS2PDF Function to convert a PostScript file to PDF using Ghostscript
%
% Converts a postscript file into PDF. The resulting PDF file will contain
% one page for each page defined in the postscript files, so a multi-page
% postscript file, like those generated by using the '-append' option of
% MATLAB's print command, can be used to generate a multi-page PDF file.
%
% Ghostscript is a third-party application currently supplied with
% MATLAB. The caller may also specify a different version of Ghostscript
% to use.
%
% PS2PDF expects to be called with a set of parameter-value pairs. The
% order of these is unimportant, but required parameters MUST be
% specified
%
% In the list below, required parameters are marked with an asterisk *
% NOTE: ps2pdf can not use MATLAB's version of Ghostscript
% in a deployed application; you MUST provide a
% the path to a separate instance of Ghostscript. This
% parameter is marked with a double asterisk **
%
% Parameter: Value:
% * psfile full or relative path to the postscript file to convert
%
% * pdffile full or relative path to the pdf file to create
%
% ** gscommand path to Ghostscript executable to use; this will try
% to default to the version of Ghostscript shipped with
% MATLAB, if any. If this value is specified you should
% also specify the gsfontpath and gslibpath values.
%
% ** See note on deployed applications, above.
%
% gsfontpath full path to the Ghostscript font files
% If a gscommand is specified then this path should
% also be specified and reference the same Ghostscript
% version
%
% gslibpath full path to the Ghostscript library (.ps) files.
% If a gscommand is specified then this path should
% also be specified and reference the same Ghostscript
% version
%
% If gscommand is NOT specified and we can determine
% the version of Ghostscript, if any, shipped with
% MATLAB, then this value will be overridden to use the
% path that references MATLAB's version of Ghostscript
%
% gspapersize paper size to use in the created .pdf file. If not
% specified or the specified value is not recognized
% it will use whatever default paper size is
% built into the version of Ghostscript being run
%
% NOTE: no scaling of the input occurs - it's simply
% placed on a page with the specified paper size.
%
% Valid values for gspapersize are:
% 'letter', 'ledger', 'legal', '11x17',
% 'archA', 'archB', 'archC', 'archD', 'archE',
% 'a0', 'a1', 'a2', 'a3','a4', 'a5',
% 'a6', 'a7', 'a8', 'a9', 'a10'
%
% deletepsfile 0 to keep the input ps file after creating pdf
% non-zero to delete the input ps file after creating pdf
% Default is 0: keep the input ps file (do NOT delete it)
% NOTE: if the pdf creation process fails, the input
% PS file will be kept regardless of this setting
%
% verbose 0 to suppress display of status/progress info;
% non-zero to allow display of status/progress info
% Default is 0 (no display)
%
% Example usage:
% use MATLAB's version of Ghostscript to generate an A4 pdf file
% ps2pdf('psfile', 'input.ps', 'pdffile', 'output.pdf', 'gspapersize', 'a4')
%
% use a local copy of Ghostcript to generate a file, and display some
% status/progress info while doing so.
% ps2pdf('psfile', '../reports/input.ps', 'pdffile', 'c:\temp\output3.pdf', ...
% 'gspapersize', 'a4', 'verbose', 1, ...
% 'gscommand', 'C:\Program Files\GhostScript\bin\gswin32c.exe', ...
% 'gsfontpath', 'C:\Program Files\GhostScript\fonts', ...
% 'gslibpath', 'C:\Program Files\GhostScript\lib')
%
% use MATLAB's version of Ghostscript to generate a pdf file and delete
% the input.ps file when done
% ps2pdf('psfile', 'input.ps', 'pdffile', 'output.pdf', 'gspapersize', 'a4', 'deletepsfile', 1)
% Update log:
% Jun 16, 2010: added check for deployed application
% May 19, 2010: wrapped filenames sent to Ghostscript in quotes
% May 06, 2010: updated how Ghostscript is found, don't rely on MATLAB version #
% Aug 15, 2008: fixed bug where embedded space in location of
% MATLAB's version of Ghostscript caused ps2pdf to fail.
% Apr 16, 2008: added deletepsfile option
% Copyright 2008-2010 The MathWorks, Inc.
if nargin < 1
error('ps2pdf:parameters', 'No parameters specified. Type ''help ps2pdf'' for details on how to use this function.');
end
% parse input args
gsData = LocalParseArgs(varargin{:});
% setup the file that tells GS what we want it to do
gsData = LocalCreateResponseFile(gsData);
gsDebug = 0;
if gsData.verbose
fprintf('ps2pdf: input settings are:\n');
if isfield(gsData, 'paperSizes')
gsData = rmfield(gsData, 'paperSizes');
end
gsData %#ok<NOPRT>
fprintf('ps2pdf: response file for Ghostscript is:\n');
type(gsData.responseFile);
gsDebug = 1;
end
%to hold results/status from system call
s = 0; %#ok<NASGU>
r = ''; %#ok<NASGU>
% run Ghostscript to convert the file
if gsData.useBuiltin
[s, r] = gsData.cmd(['@' gsData.responseFile], gsData.psFile, gsDebug);
else
[s, r] = system([gsData.cmd ' @"' gsData.responseFile '" "' gsData.psFile '"']);
end
if gsData.verbose
disp( ['Ghostscript STDOUT: ' num2str(s) ] );
disp( ['Ghostscript STDERR: ' r ] );
else
delete(gsData.responseFile)
end
if s && ~isempty(r)
error('ps2pdf:ghostscript', ['Problem converting PostScript. System returned error: ' num2str(s) '.' r])
elseif s
error('ps2pdf:ghostscript', ['Problem calling GhostScript. System returned error: ' num2str(s)])
end
%if after all this we still couldn't create the file, report the error
fid = fopen( gsData.pdfFile, 'r');
if ( fid == -1 )
error('ps2pdf:ghostscript', '%s', [ 'Ghostscript could not create ''' gsData.pfdFile '''.' ])
else
fclose( fid );
end
% if we get here, we successfully created pdf file; delete ps file if
% requested to do so
if gsData.deletePSFile
delete(gsData.psFile);
end
end
%local function to parse arguments and fill in the gsData structure
% .psFile - postscript file to convert
% .pdfFile - pdf file to create
% .cmd - path/name of Ghostscript command to run or handle to gscript
% builtin
% .useBuiltin - 1 if using builtin gs command
% .fontPath - path to the Ghostscript fonts, if any
% .libPath - path to the Ghostscript libs (Ghostscript .ps files), if any)
% .paperSize - paper size to set for resulting .pdf file
% .deletePSFile - 0 to keep (not delete) the input ps file if pdf created ok
% .verbose - if non-zero, display some status/progress info to command window
function gsData = LocalParseArgs(varargin)
gsData.paperSizes = {'letter', 'ledger', 'legal', '11x17', 'archA', 'archB', ...
'archC', 'archD', 'archE', 'a0', 'a1', 'a2', 'a3','a4', 'a5', ...
'a6', 'a7', 'a8', 'a9', 'a10'};
%default values for some settings
gsData.verbose = 0;
gsData.useBuiltin = 0;
gsData.deletePSFile = 0;
for i = 1 : 2 : length(varargin)-1
param_arg = varargin{i};
param_value = varargin{i+1};
switch(lower(param_arg))
% path to ps file to conver
case 'psfile'
if ~exist(param_value, 'file')
error('print:ghostscript', ...
'Can not find postscript file <%s> to convert', ...
param_value)
end
gsData.psFile = param_value;
% path to pdf file to create
case 'pdffile'
%verify we can create file at that location
pdf_fid = fopen(param_value,'w');
if pdf_fid < 0
error('ps2pdf:invalidPDFFIle', ...
'Can not open <%s> for writing', ...
param_value);
end
fclose(pdf_fid);
%delete temp file we created
delete(param_value);
gsData.pdfFile = param_value;
% full path to gs executable
case 'gscommand'
if ~exist(param_value, 'file')
error('ps2pdf:ghostscriptCommand', ...
'Can not find Ghostscript executable (''gscommand'') <%s>',...
param_value)
end
if ispc && ~isempty(findstr(param_value, ' '))
param_value = ['"' param_value '"']; %#ok<AGROW>
end
gsData.cmd = param_value;
% full path to gs font dir
case 'gsfontpath'
if ~exist(param_value, 'dir')
error('ps2pdf:ghostscriptFontPath', ...
'Can not find the directory <%s> for Ghostscript fonts (''gsfontpath'')', ...
param_value)
end
gsData.fontPath = param_value;
% full path to gs lib dir
case 'gslibpath'
if ~exist(param_value, 'dir')
error('ps2pdf:ghostscriptLibPath', ...
'Can not find the directory <%s> for Ghostscript library files (''gslibpath'')', ...
param_value)
end
gsData.libPath = param_value;
% paper size
case 'gspapersize'
idx = strcmpi(param_value, gsData.paperSizes);
if ~any(idx)
warning('ps2pdf:papersize', ...
'''gspapersize'' value <%s> not found in the list of known sizes, ignoring it.', param_value);
else
gsData.paperSize = gsData.paperSizes{idx};
end
% deletePSFile
case 'deletepsfile'
if isnumeric(param_value)
gsData.deletePSFile = param_value;
else
warning('ps2pdf:deletepsfile', ...
'''deletepsfile'' value <%s> class <%s> should be numeric, defaulting to 0', ...
param_value, class(param_value));
end
% verbose
case 'verbose'
if isnumeric(param_value)
gsData.verbose = param_value;
else
warning('ps2pdf:verbose', ...
'''verbose'' value <%s> class <%s> should be numeric, defaulting to 0', ...
param_value, class(param_value));
end
otherwise
if isnumeric(param_value)
param_value = num2str(param_value);
end
warning('ps2pdf:unknown', ...
'ignoring unknown parameter <%s> with value <%s>.', param_arg, param_value);
end
end
if ~isfield(gsData, 'psFile')
error('ps2pdf:noInputFile', ...
'No input (psfile) file specified');
end
if ~isfield(gsData, 'pdfFile')
error('ps2pdf:noOutputFile', ...
'No output (pdffile) file specified');
end
if ~isfield(gsData, 'cmd')
if isdeployed
error('ps2pdf:deployedNeedsGhostscript', ...
'In order to use ''ps2pdf'' in a deployed application you must provide the path to a separate instance of Ghostscript.');
end
% updated code to find ghostscript - look for gs8x first,
% then try old location. Don't depend on MATLAB version #
ghostDir = fullfile( matlabroot, 'sys', 'gs8x' );
if ~exist(ghostDir, 'dir')
[gsCmd, ghostDir] = Local_GetOldGhostscript();
gsData.cmd = gsCmd;
else
gsData.cmd = Local_GetGscriptFcnHandle;
if ~isempty(gsData.cmd)
gsData.useBuiltin = 1; % use builtin Ghostscript
end
end
if ~exist(ghostDir, 'dir')
error('ps2pdf:ghostscriptCommand', ...
'Can not find Ghostscript installed with MATLAB in <%s>',...
ghostDir);
end
if ~isempty(gsData.cmd)
% if using MATLAB's version of GhostScript, use same set of fonts and library files
if isfield(gsData, 'fontPath') || isfield(gsData, 'libPath')
warning('ps2pdf:ghostscriptPathOverride', ...
'Using MATLAB''s version of Ghostscript; overriding ''gsfontpath'' and ''gslibpath'' to use builtin MATLAB version');
end
gsData.fontPath = fullfile( ghostDir, 'fonts', '');
gsData.libPath = fullfile( ghostDir, 'ps_files', '');
else
error('ps2pdf:noGhostscriptCommand', ...
'Can not find Ghostscript program in MATLAB');
end
else
% if gscommandpath was specified,
if ~isfield(gsData, 'fontPath') || ~isfield(gsData, 'libPath')
warning('ps2pdf:ghostscriptCommandSuggestion', ...
['When specifying a Ghostscript executable (''gscommand'') you should also '...
'specify both the ''gsfontpath'' and ''gslibpath'' locations']);
end
end
end
%local function to create the input file needed for Ghostscript
function gsData = LocalCreateResponseFile(gsData)
% open a response file to write out Ghostscript commands
rsp_file = [tempname '.rsp'];
rsp_fid = fopen (rsp_file, 'w');
if (rsp_fid < 0)
error('ps2pdf:responseFileCreate', 'Unable to create response file')
end
fprintf(rsp_fid, '-dBATCH -dNOPAUSE\n');
if ~gsData.verbose
fprintf(rsp_fid, '-q\n');
end
if isfield(gsData, 'libPath')
fprintf(rsp_fid, '-I"%s"\n', gsData.libPath);
end
if isfield(gsData, 'fontPath')
fprintf(rsp_fid, '-I"%s"\n', gsData.fontPath);
end
if isfield(gsData, 'paperSize')
fprintf( rsp_fid, '-sPAPERSIZE=%s\n', gsData.paperSize );
end
fprintf(rsp_fid, '-sOutputFile="%s"\n', gsData.pdfFile);
fprintf(rsp_fid, '-sDEVICE=%s\n', 'pdfwrite');
fclose(rsp_fid);
gsData.responseFile = rsp_file;
end
%local function to get a handle to MATLAB's Ghostscript implementation
%NOTE: this may change or be removed in future releases
function gs = Local_GetGscriptFcnHandle()
gs = '';
p = which('-all', 'gscript');
if ~isempty(p)
p = p{1};
fpath = fileparts(p);
olddir = cd(fpath);
gs = @gscript;
cd(olddir);
end
end
% local function to try and get location of Ghostscript in older MATLAB
function [gsCmd, ghostDir] = Local_GetOldGhostscript
ghostDir = fullfile( matlabroot, 'sys', 'ghostscript' );
gsCmd = '';
if ispc
if exist(fullfile(ghostDir,'bin','win32','gs.exe'), 'file')
gsCmd = fullfile(ghostDir,'bin','win32','gs.exe');
end
else
if exist(fullfile(ghostDir,'bin',lower(computer),'gs'), 'file')
gsCmd = fullfile(ghostDir,'bin',lower(computer), 'gs');
end
end
gsCmd = ['"' gsCmd '"'];
end