]> www.fi.muni.cz Git - evince.git/blob - backend/dvi/mdvi-lib/sp-epsf.c
1aa9fa553f2f005b0a287c420110212ac983520b
[evince.git] / backend / dvi / mdvi-lib / sp-epsf.c
1 /*
2  * Copyright (C) 2000, Matias Atria
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 /* postscript specials */
20
21 #include <config.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include "mdvi.h"
28 #include "private.h"
29
30 typedef struct {
31         double  ox;
32         double  oy;
33         double  bw;
34         double  bh;
35         double  angle;
36 } EpsfBox;
37
38 #define LLX     0
39 #define LLY     1
40 #define URX     2
41 #define URY     3
42 #define RWI     4
43 #define RHI     5
44 #define HOFF    6
45 #define VOFF    7
46 #define HSIZE   8
47 #define VSIZE   9
48 #define HSCALE  10
49 #define VSCALE  11
50 #define ANGLE   12
51 #define CLIP    13
52
53 void    epsf_special __PROTO((DviContext *dvi, char *prefix, char *arg));
54
55 /* Note: the given strings are modified in place */
56 static char *parse_epsf_special(EpsfBox *box, char **ret, 
57         char *prefix, char *arg)
58 {
59         static struct {
60                 char *name;
61                 int  has_arg;
62                 char *value;
63         } keys[] = {
64                 {"llx", 1, "0"},
65                 {"lly", 1, "0"},
66                 {"urx", 1, "0"},
67                 {"ury", 1, "0"},
68                 {"rwi", 1, "0"},
69                 {"rhi", 1, "0"},
70                 {"hoffset", 1, "0"},
71                 {"voffset", 1, "0"},
72                 {"hsize", 1, "612"},
73                 {"vsize", 1, "792"},
74                 {"hscale", 1, "100"},
75                 {"vscale", 1, "100"},
76                 {"angle", 1, "0"},
77                 {"clip", 0, "0"}
78         };
79 #define NKEYS   (sizeof(keys) / sizeof(keys[0]))
80         char    *ptr;
81         char    *filename;
82         int     quoted;
83         double  value[NKEYS];
84         Uchar   present[NKEYS];
85         Buffer  buffer;
86         char    *name;
87         int     i;
88         double  originx;
89         double  originy;
90         double  hsize;
91         double  vsize;
92         double  hscale;
93         double  vscale;
94                 
95         /* this special has the form
96          *   ["]file.ps["] [key=valye]*
97          */
98         
99         /* scan the filename */
100         while(*arg == ' ' || *arg == '\t')
101                 arg++;
102
103         /* make a copy of the string */
104         ptr = arg;
105
106         if(*ptr == '"')
107                 for(name = ++ptr; *ptr && *ptr != '"'; ptr++);
108         else
109                 for(name = ptr; *ptr && *ptr != ' ' && *ptr != '\t'; ptr++);
110         if(ptr == name)
111                 return NULL;
112         *ptr++ = 0;
113         filename = name;
114
115         /* reset values to defaults */
116         for(i = 0; i < NKEYS; i++) {
117                 value[i] = atof(keys[i].value);
118                 present[i] = 0;
119         }
120         
121         buff_init(&buffer);
122         buff_add(&buffer, "@beginspecial ", 0);
123
124         quoted = 0;
125         while(*ptr) {
126                 const char *keyname;
127                 char    *val;
128                 char    *p;
129
130                 while(*ptr == ' ' || *ptr == '\t')
131                         ptr++;
132                 keyname = ptr;
133                 
134                 /* get the whole key=value pair */
135                 for(; *ptr && *ptr != ' ' && *ptr != '\t'; ptr++);
136                 
137                 if(*ptr) *ptr++ = 0;
138                 /* now we shouldn't touch `ptr' anymore */
139                 
140                 /* now work on this pair */
141                 p = strchr(keyname, '=');
142                 if(p == NULL)
143                         val = NULL;
144                 else {
145                         *p++ = 0;
146                         if(*p == '"') {
147                                 val = ++p;
148                                 /* skip until closing quote */
149                                 while(*p && *p != '"')
150                                         p++;
151                                 if(*p != '"')
152                                         mdvi_warning(
153                                         _("%s: malformed value for key `%s'\n"),
154                                                 filename, keyname);
155                         } else
156                                 val = p;
157                 }
158
159                 /* lookup the key */
160                 for(i = 0; i < NKEYS; i++)
161                         if(STRCEQ(keys[i].name, keyname))
162                                 break;
163                 if(i == NKEYS) {
164                         mdvi_warning(_("%s: unknown key `%s' ignored\n"),
165                                      filename, keyname);
166                         continue;
167                 }
168                 if(keys[i].has_arg && val == NULL) {
169                         mdvi_warning(_("%s: no argument for key `%s', using defaults\n"),
170                                      filename, keyname);
171                         val = keys[i].value;
172                 } else if(!keys[i].has_arg && val) {
173                         mdvi_warning(_("%s: argument `%s' ignored for key `%s'\n"),
174                                      filename, val, keyname);
175                         val = NULL;
176                 }
177                 if(val)
178                         value[i] = atof(val);
179                 
180                 /* put the argument */
181                 buff_add(&buffer, val, 0);
182                 buff_add(&buffer, " @", 2);
183                 buff_add(&buffer, keyname, 0);
184                 buff_add(&buffer, " ", 1);
185                 
186                 /* remember that this option was given */
187                 present[i] = 0xff;
188         }
189         buff_add(&buffer, " @setspecial", 0);
190         
191         /* now compute the bounding box (code comes from dvips) */
192         originx = 0;
193         originy = 0;
194         hscale = 1;
195         vscale = 1;
196         hsize = 0;
197         vsize = 0;
198         
199         if(present[HSIZE])
200                 hsize = value[HSIZE];
201         if(present[VSIZE])
202                 vsize = value[VSIZE];
203         if(present[HOFF])
204                 originx = value[HOFF];
205         if(present[VOFF])
206                 originy = value[VOFF];
207         if(present[HSCALE])
208                 hscale = value[HSCALE] / 100.0;
209         if(present[VSCALE])
210                 vscale = value[VSCALE] / 100.0;
211         if(present[URX] && present[LLX])
212                 hsize = value[URX] - value[LLX];
213         if(present[URY] && present[LLY])
214                 vsize = value[URY] - value[LLY];
215         if(present[RWI] || present[RHI]) {
216                 if(present[RWI] && !present[RHI])
217                         hscale = vscale = value[RWI] / (10.0 * hsize);
218                 else if(present[RHI] && !present[RWI])
219                         hscale = vscale = value[RHI] / (10.0 * vsize);
220                 else {
221                         hscale = value[RWI] / (10.0 * hsize);
222                         vscale = value[RHI] / (10.0 * vsize);
223                 }
224         }
225         
226         box->ox = originx;
227         box->oy = originy;
228         box->bw = hsize * hscale;
229         box->bh = vsize * vscale;
230         box->angle = value[ANGLE];
231
232         *ret = buffer.data;
233         
234         return filename;
235 }
236
237 void    epsf_special(DviContext *dvi, char *prefix, char *arg)
238 {
239         char    *file;
240         char    *special;
241         char    *psfile;
242         char    *tmp;
243         EpsfBox box = {0, 0, 0, 0};
244         int     x, y;
245         int     w, h;
246         double  xf, vf;
247         struct stat buf;
248         
249         file = parse_epsf_special(&box, &special, prefix, arg);
250         if (file != NULL)
251                 mdvi_free (special);
252
253         xf = dvi->params.dpi * dvi->params.mag / (72.0 * dvi->params.hshrink);
254         vf = dvi->params.vdpi * dvi->params.mag / (72.0 * dvi->params.vshrink);
255         w = FROUND(box.bw * xf);
256         h = FROUND(box.bh * vf);
257         x = FROUND(box.ox * xf) + dvi->pos.hh;
258         y = FROUND(box.oy * vf) + dvi->pos.vv - h + 1;
259
260         if (!file || !dvi->device.draw_ps) {
261                 dvi->device.draw_rule (dvi, x, y, w, h, 0);
262                 return;
263         }
264
265         if (file[0] == '/') { /* Absolute path */
266                 if (stat (file, &buf) == 0)
267                         dvi->device.draw_ps (dvi, file, x, y, w, h);
268                 else
269                         dvi->device.draw_rule (dvi, x, y, w, h, 0);
270                 return;
271         }
272
273         tmp = mdvi_strrstr (dvi->filename, "/");
274         if (tmp) { /* Document directory */
275                 int path_len = strlen (dvi->filename) - strlen (tmp + 1);
276                 int file_len = strlen (file);
277                 
278                 psfile = mdvi_malloc (path_len + file_len + 1);
279                 psfile[0] = '\0';
280                 strncat (psfile, dvi->filename, path_len);
281                 strncat (psfile, file, file_len);
282
283                 if (stat (psfile, &buf) == 0) {
284                         dvi->device.draw_ps (dvi, psfile, x, y, w, h);
285                         mdvi_free (psfile);
286
287                         return;
288                 }
289
290                 mdvi_free (psfile);
291         }
292                         
293         psfile = mdvi_build_path_from_cwd (file);
294         if (stat (psfile, &buf) == 0) { /* Current working dir */
295                 dvi->device.draw_ps (dvi, psfile, x, y, w, h);
296                 mdvi_free (psfile);
297
298                 return;
299         }
300
301         mdvi_free (psfile);
302         
303         psfile = kpse_find_pict (file);
304         if (psfile) { /* kpse */
305                 dvi->device.draw_ps (dvi, psfile, x, y, w, h);
306         } else {
307                 dvi->device.draw_rule(dvi, x, y, w, h, 0);
308         }
309
310         free (psfile);
311 }