OSDN Git Service

bf5f4e5051c15199e7038018014cc7f7b52a0d11
[putex/putex.git] / src / dvipdfmx-pu / src / spc_dvips.c
1 /*  
2     
3     This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
5     Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata,
6     the dvipdfmx project team.
7     
8     Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
9
10     This program is free software; you can redistribute it and/or modify
11     it under the terms of the GNU General Public License as published by
12     the Free Software Foundation; either version 2 of the License, or
13     (at your option) any later version.
14     
15     This program is distributed in the hope that it will be useful,
16     but WITHOUT ANY WARRANTY; without even the implied warranty of
17     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18     GNU General Public License for more details.
19     
20     You should have received a copy of the GNU General Public License
21     along with this program; if not, write to the Free Software
22     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23 */
24
25 #include <string.h>
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "system.h"
32 #include "mem.h"
33 #include "error.h"
34
35 #include "dpxfile.h"
36
37 #include "pdfparse.h"
38
39 #include "pdfdoc.h"
40
41 #include "mpost.h"
42
43 #include "pdfximage.h"
44 #include "pdfdraw.h"
45 #include "pdfcolor.h"
46 #include "pdfdev.h"
47
48 #include "specials.h"
49 #include "spc_util.h"
50
51 #include "spc_dvips.h"
52
53
54 static int    block_pending = 0;
55 static double pending_x     = 0.0;
56 static double pending_y     = 0.0;
57 static int    position_set  = 0;
58
59 static char *
60 parse_filename (const char **pp, const char *endptr)
61 {
62   char  *r;
63   const char *q = NULL, *p = *pp;
64   char   qchar;
65   int    n;
66
67   if (!p || p >= endptr)
68     return  NULL;
69   else if (*p == '\"' || *p == '\'')
70     qchar = *p++;
71   else {
72     qchar = ' ';
73   }
74   for (n = 0, q = p; p < endptr && *p != qchar; n++, p++);
75   if (qchar != ' ') {
76     if (*p != qchar)
77       return  NULL;
78     p++;
79   }
80   if (!q || n == 0)
81     return  NULL;
82
83 #if  0
84   {
85     int  i;
86     for (i = 0; i < n && isprint(q[i]); i++);
87     if (i != n) {
88       WARN("Non printable char in filename string...");
89     }
90   }
91 #endif
92
93   r = NEW(n + 1, char);
94   memcpy(r, q, n); r[n] = '\0';
95
96   *pp = p;
97   return  r;
98 }
99
100 /* =filename ... */
101 static int
102 spc_handler_ps_file (struct spc_env *spe, struct spc_arg *args)
103 {
104   int            form_id;
105   char          *filename;
106   transform_info ti;
107
108   ASSERT(spe && args);
109
110   skip_white(&args->curptr, args->endptr);
111   if (args->curptr + 1 >= args->endptr ||
112       args->curptr[0] != '=') {
113     spc_warn(spe, "No filename specified for PSfile special.");
114     return  -1;
115   }
116   args->curptr++;
117
118   filename = parse_filename(&args->curptr, args->endptr);
119   if (!filename) {
120     spc_warn(spe, "No filename specified for PSfile special.");
121     return  -1;
122   }
123
124   transform_info_clear(&ti);
125   if (spc_util_read_dimtrns(spe, &ti, args, NULL, 1) < 0) {
126     RELEASE(filename);
127     return  -1;
128   }
129
130   form_id = pdf_ximage_findresource(filename, 1, NULL);
131   if (form_id < 0) {
132     spc_warn(spe, "Failed to read image file: %s", filename);
133     RELEASE(filename);
134     return  -1;
135   }
136   RELEASE(filename);
137
138   pdf_dev_put_image(form_id, &ti, spe->x_user, spe->y_user);
139
140   return  0;
141 }
142
143 /* This isn't correct implementation but dvipdfm supports... */
144 static int
145 spc_handler_ps_plotfile (struct spc_env *spe, struct spc_arg *args)
146 {
147   int            error = 0;
148   int            form_id;
149   char          *filename;
150   transform_info p;
151
152   ASSERT(spe && args);
153
154   spc_warn(spe, "\"ps: plotfile\" found (not properly implemented)");
155
156   skip_white(&args->curptr, args->endptr);
157   filename = parse_filename(&args->curptr, args->endptr);
158   if (!filename) {
159     spc_warn(spe, "Expecting filename but not found...");
160     return -1;
161   }
162
163   form_id = pdf_ximage_findresource(filename, 1, NULL);
164   if (form_id < 0) {
165     spc_warn(spe, "Could not open PS file: %s", filename);
166     error = -1;
167   } else {
168     transform_info_clear(&p);
169     p.matrix.d = -1.0; /* xscale = 1.0, yscale = -1.0 */
170 #if 0
171     /* I don't know how to treat this... */
172     pdf_dev_put_image(form_id, &p,
173                       block_pending ? pending_x : spe->x_user,
174                       block_pending ? pending_y : spe->y_user);
175 #endif
176     pdf_dev_put_image(form_id, &p, 0, 0);
177   }
178   RELEASE(filename);
179
180   return  error;
181 }
182
183 static int
184 spc_handler_ps_literal (struct spc_env *spe, struct spc_arg *args)
185 {
186   int     error = 0;
187   int     st_depth, gs_depth;
188   double  x_user, y_user;
189
190   ASSERT(spe && args && args->curptr <= args->endptr);
191
192   if (args->curptr + strlen(":[begin]") <= args->endptr &&
193       !strncmp(args->curptr, ":[begin]", strlen(":[begin]"))) {
194     block_pending++;
195     position_set = 1;
196
197     x_user = pending_x = spe->x_user;
198     y_user = pending_y = spe->y_user;
199     args->curptr += strlen(":[begin]");
200   } else if (args->curptr + strlen(":[end]") <= args->endptr &&
201              !strncmp(args->curptr, ":[end]", strlen(":[end]"))) {
202     if (block_pending <= 0) {
203       spc_warn(spe, "No corresponding ::[begin] found.");
204       return -1;
205     }
206     block_pending--;
207
208     position_set = 0;
209
210     x_user = pending_x;
211     y_user = pending_y;
212     args->curptr += strlen(":[end]");
213   } else if (args->curptr < args->endptr &&
214              args->curptr[0] == ':') {
215     x_user = position_set ? pending_x : spe->x_user;
216     y_user = position_set ? pending_y : spe->y_user;
217     args->curptr++;
218   } else {
219     position_set = 1;
220     x_user = pending_x = spe->x_user;
221     y_user = pending_y = spe->y_user;
222   }
223
224   skip_white(&args->curptr, args->endptr);
225   if (args->curptr < args->endptr) {
226
227     st_depth = mps_stack_depth();
228     gs_depth = pdf_dev_current_depth();
229
230     error = mps_exec_inline(&args->curptr,
231                             args->endptr,
232                             x_user, y_user);
233     if (error) {
234       spc_warn(spe, "Interpreting PS code failed!!! Output might be broken!!!");
235       pdf_dev_grestore_to(gs_depth);
236     } else if (st_depth != mps_stack_depth()) {
237       spc_warn(spe, "Stack not empty after execution of inline PostScript code.");
238       spc_warn(spe, ">> Your macro package makes some assumption on internal behaviour of DVI drivers.");
239       spc_warn(spe, ">> It may not compatible with dvipdfmx.");
240     }
241   }
242
243   return  error;
244 }
245
246 static int
247 spc_handler_ps_default (struct spc_env *spe, struct spc_arg *args)
248 {
249   int  error;
250   int  st_depth, gs_depth;
251
252   ASSERT(spe && args);
253
254   pdf_dev_gsave();
255
256   st_depth = mps_stack_depth();
257   gs_depth = pdf_dev_current_depth();
258
259   {
260     pdf_tmatrix M;
261     M.a = M.d = 1.0; M.b = M.c = 0.0; M.e = spe->x_user; M.f = spe->y_user;
262     pdf_dev_concat(&M);
263   error = mps_exec_inline(&args->curptr,
264                           args->endptr,
265                           spe->x_user, spe->y_user);
266     M.e = -spe->x_user; M.f = -spe->y_user;
267     pdf_dev_concat(&M);
268   }
269   if (error)
270     spc_warn(spe, "Interpreting PS code failed!!! Output might be broken!!!");
271   else {
272     if (st_depth != mps_stack_depth()) {
273       spc_warn(spe, "Stack not empty after execution of inline PostScript code.");
274       spc_warn(spe, ">> Your macro package makes some assumption on internal behaviour of DVI drivers.");
275       spc_warn(spe, ">> It may not compatible with dvipdfmx.");
276     }
277   }
278
279   pdf_dev_grestore_to(gs_depth);
280   pdf_dev_grestore();
281
282   return  error;
283 }
284
285 static struct spc_handler dvips_handlers[] = {
286   {"PSfile",        spc_handler_ps_file},
287   {"psfile",        spc_handler_ps_file},
288   {"ps: plotfile ", spc_handler_ps_plotfile},
289   {"PS: plotfile ", spc_handler_ps_plotfile},
290   {"PS:",           spc_handler_ps_literal},
291   {"ps:",           spc_handler_ps_literal},
292   {"\" ",           spc_handler_ps_default}
293 };
294
295 int
296 spc_dvips_at_end_page (void)
297 {
298   mps_eop_cleanup();
299   return  0;
300 }
301
302 int
303 spc_dvips_check_special (const char *buf, long len)
304 {
305   const char *p, *endptr;
306   int   i;
307
308   p      = buf;
309   endptr = p + len;
310
311   skip_white(&p, endptr);
312   if (p >= endptr)
313     return  0;
314
315   len = (long) (endptr - p);
316   for (i = 0;
317        i < sizeof(dvips_handlers)/sizeof(struct spc_handler); i++) {
318     if (len >= strlen(dvips_handlers[i].key) &&
319         !memcmp(p, dvips_handlers[i].key,
320                 strlen(dvips_handlers[i].key))) {
321       return  1;
322     }
323   }
324
325   return  0;
326 }
327
328 int 
329 spc_dvips_setup_handler (struct spc_handler *handle,
330                          struct spc_env *spe, struct spc_arg *args)
331 {
332   const char *key;
333   int   i, keylen;
334
335   ASSERT(handle && spe && args);
336
337   skip_white(&args->curptr, args->endptr);
338
339   key = args->curptr;
340   while (args->curptr < args->endptr &&
341          isalpha(args->curptr[0])) {
342     args->curptr++;
343   }
344   /* Test for "ps:". The "ps::" special is subsumed under this case.  */
345   if (args->curptr < args->endptr &&
346       args->curptr[0] == ':') {
347     args->curptr++;
348     if (args->curptr+strlen(" plotfile ") <= args->endptr &&
349         !strncmp(args->curptr, " plotfile ", strlen(" plotfile "))) {
350       args->curptr += strlen(" plotfile ");
351       }
352   } else if (args->curptr+1 < args->endptr &&
353              args->curptr[0] == '"' && args->curptr[1] == ' ') {
354     args->curptr += 2;
355   }
356
357   keylen = (int) (args->curptr - key);
358   if (keylen < 1) {
359     spc_warn(spe, "Not ps: special???");
360     return  -1;
361   }
362
363   for (i = 0;
364        i < sizeof(dvips_handlers) / sizeof(struct spc_handler); i++) {
365     if (keylen == strlen(dvips_handlers[i].key) &&
366         !strncmp(key, dvips_handlers[i].key, keylen)) {
367
368       skip_white(&args->curptr, args->endptr);
369
370       args->command = dvips_handlers[i].key;
371
372       handle->key  = "ps:";
373       handle->exec = dvips_handlers[i].exec;
374
375       return  0;
376     }
377   }
378
379   return  -1;
380 }
381