Rev 8195 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
10 | reyssat | 1 | /* Copyright (C) 2002-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis |
2 | * |
||
3 | * This program is free software; you can redistribute it and/or modify |
||
4 | * it under the terms of the GNU General Public License as published by |
||
5 | * the Free Software Foundation; either version 2 of the License, or |
||
6 | * (at your option) any later version. |
||
7 | * |
||
8 | * This program is distributed in the hope that it will be useful, |
||
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
11 | * GNU General Public License for more details. |
||
12 | * |
||
13 | * You should have received a copy of the GNU General Public License |
||
14 | * along with this program; if not, write to the Free Software |
||
15 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
||
16 | */ |
||
8103 | bpr | 17 | #include "texgif.h" |
10 | reyssat | 18 | |
19 | /* dvi 2 gif driver, dvi interpreter */ |
||
8103 | bpr | 20 | #define dvi_set1 128 |
21 | #define dvi_set2 129 |
||
22 | #define dvi_set3 130 |
||
23 | #define dvi_set4 131 |
||
24 | #define dvi_set_rule 132 |
||
25 | #define dvi_put1 133 |
||
26 | #define dvi_put2 134 |
||
27 | #define dvi_put3 135 |
||
28 | #define dvi_put4 136 |
||
29 | #define dvi_put_rule 137 |
||
30 | #define dvi_nop 138 |
||
31 | #define dvi_bop 139 |
||
32 | #define dvi_eop 140 |
||
33 | #define dvi_push 141 |
||
34 | #define dvi_pop 142 |
||
35 | #define dvi_right1 143 |
||
36 | #define dvi_right2 144 |
||
37 | #define dvi_right3 145 |
||
38 | #define dvi_right4 146 |
||
39 | #define dvi_w0 147 |
||
40 | #define dvi_w1 148 |
||
41 | #define dvi_w2 149 |
||
42 | #define dvi_w3 150 |
||
43 | #define dvi_w4 151 |
||
44 | #define dvi_x0 152 |
||
45 | #define dvi_x1 153 |
||
46 | #define dvi_x2 154 |
||
47 | #define dvi_x3 155 |
||
48 | #define dvi_x4 156 |
||
49 | #define dvi_down1 157 |
||
50 | #define dvi_down2 158 |
||
51 | #define dvi_down3 159 |
||
52 | #define dvi_down4 160 |
||
53 | #define dvi_y0 161 |
||
54 | #define dvi_y1 162 |
||
55 | #define dvi_y2 163 |
||
56 | #define dvi_y3 164 |
||
57 | #define dvi_y4 165 |
||
58 | #define dvi_z0 166 |
||
59 | #define dvi_z1 167 |
||
60 | #define dvi_z2 168 |
||
61 | #define dvi_z3 169 |
||
62 | #define dvi_z4 170 |
||
63 | #define dvi_fnt1 235 |
||
64 | #define dvi_fnt2 236 |
||
65 | #define dvi_fnt3 237 |
||
66 | #define dvi_fnt4 238 |
||
67 | #define dvi_xxx1 239 |
||
68 | #define dvi_xxx2 240 |
||
69 | #define dvi_xxx3 241 |
||
70 | #define dvi_xxx4 242 |
||
71 | #define dvi_fnt_def1 243 |
||
72 | #define dvi_fnt_def2 244 |
||
73 | #define dvi_fnt_def3 245 |
||
74 | #define dvi_fnt_def4 246 |
||
75 | #define dvi_pre 247 |
||
76 | #define dvi_post 248 |
||
77 | #define dvi_post_post 249 |
||
10 | reyssat | 78 | |
79 | unsigned char *dvibuf, *dviptr; |
||
80 | int dvilen; |
||
81 | int pass, passstop; |
||
82 | int num, den, mag; |
||
83 | int minx, maxx,miny, maxy; |
||
84 | double dviratio; |
||
85 | int dvix, dviy; |
||
86 | int d_h,d_v,d_w,d_x,d_y,d_z; |
||
87 | int d_f; |
||
88 | int pageptr; |
||
89 | struct { |
||
90 | int minx, maxx, miny, maxy; |
||
91 | } pagedata[MAX_PAGES]; |
||
92 | |||
93 | struct { |
||
94 | int h,v,w,x,y,z; |
||
95 | } dvistack[DVI_STACK_LIMIT]; |
||
96 | int dvistackptr; |
||
97 | |||
98 | #define DVI_post_post DVI_post |
||
99 | void DVI_post(void) |
||
100 | { |
||
101 | passstop=-1; dviptr=dvibuf+dvilen; |
||
102 | } |
||
103 | |||
104 | void DVI_eop(void) |
||
105 | { |
||
106 | if(pass==1) { |
||
107 | pagedata[pageptr].minx=minx; |
||
108 | pagedata[pageptr].maxx=maxx; |
||
109 | pagedata[pageptr].miny=miny; |
||
110 | pagedata[pageptr].maxy=maxy; |
||
111 | } |
||
112 | else saveimage(); |
||
113 | pageptr++; |
||
114 | if(*outfile==0 || pageptr>=MAX_PAGES) { |
||
115 | passstop=-1; dviptr=dvibuf+dvilen; |
||
116 | } |
||
117 | else passstop=0; |
||
118 | } |
||
119 | |||
120 | void DVI_bop(void) |
||
121 | { |
||
122 | passstop=1; dvistackptr=0; |
||
123 | d_h=d_v=d_w=d_x=d_y=d_z=0; d_f=-1; |
||
124 | dviptr+=44; |
||
125 | if(pass==1) { |
||
126 | minx=miny=65536; |
||
127 | maxx=maxy=-1; |
||
128 | } |
||
129 | else { |
||
130 | char *p; |
||
131 | maxx=pagedata[pageptr].maxx; |
||
132 | minx=pagedata[pageptr].minx; |
||
133 | maxy=pagedata[pageptr].maxy; |
||
134 | miny=pagedata[pageptr].miny; |
||
8195 | bpr | 135 | if(maxx<=minx || maxy<=miny) texgif_error("Empty page."); |
10 | reyssat | 136 | createimage(maxx-minx,maxy-miny); |
137 | currentcolor=color_black; |
||
138 | p=getenv("w_instex_color"); |
||
139 | if(p!=NULL && *p!=0) makecolor(p); |
||
140 | } |
||
141 | } |
||
142 | |||
143 | void DVI_nop(void) {} |
||
144 | |||
145 | int DVI_put(int p) |
||
146 | { |
||
147 | int cc, ct, x1, x2, y1, y2; |
||
8195 | bpr | 148 | if(d_f<0) texgif_error("Bad dvi: trying to put non-existing font."); |
10 | reyssat | 149 | if(p==0) cc=*dviptr; else cc=texint(dviptr+1,p); |
150 | dviptr+=p; |
||
151 | if(cc<wfont[d_f].bc || cc>wfont[d_f].ec) return -1; |
||
152 | dvix=rint(dviratio*d_h); dviy=rint(dviratio*d_v); |
||
153 | if(pass==1) { |
||
154 | ct=cc-wfont[d_f].bc; |
||
155 | x1=dvix+wfont[d_f].fh[ct].xstart; y1=dviy+wfont[d_f].fh[ct].ystart; |
||
156 | x2=x1+wfont[d_f].fh[ct].xmax; y2=y1+wfont[d_f].fh[ct].ymax; |
||
11121 | georgesk | 157 | if(minx>x1) minx=x1; |
158 | if(miny>y1) miny=y1; |
||
159 | if(maxx<x2) maxx=x2; |
||
160 | if(maxy<y2) maxy=y2; |
||
10 | reyssat | 161 | } |
162 | else { |
||
163 | paintfont(wfont+d_f,cc,dvix-minx,dviy-miny,currentcolor); |
||
164 | } |
||
165 | return cc; |
||
166 | } |
||
167 | |||
168 | void DVI_set(int p) |
||
169 | { |
||
170 | int cc; |
||
171 | cc=DVI_put(p); |
||
172 | if(cc<0) return; |
||
173 | d_h+=wfont[d_f].fh[cc-wfont[d_f].bc].w; |
||
174 | } |
||
175 | |||
176 | int DVI_put_rule(void) |
||
177 | { |
||
178 | int xxx, xx, yy, x1, y1, x2, y2, xx1, xx2, yy1, yy2; |
||
179 | yy=texint(dviptr+1,4); xx=texint(dviptr+5,4); dviptr+=8; |
||
180 | if(xx<=0 || yy<=0) return xx; |
||
181 | xxx=xx; |
||
182 | if(xx>=0) {xx=rint(dviratio*xx+blacker); if(xx>0) xx--;} |
||
183 | else {xx=rint(dviratio*xx-blacker); if(xx<0) xx--;} |
||
184 | if(yy>=0) {yy=rint(dviratio*yy+blacker); if(yy>0) yy--;} |
||
185 | else {yy=rint(dviratio*yy-blacker); if(yy<0) yy--;} |
||
186 | if(pass==1) { |
||
187 | x1=rint(dviratio*d_h); y2=rint(dviratio*d_v); |
||
188 | x2=x1+xx; y1=y2-yy; |
||
189 | if(x1<x2) {xx1=x1; xx2=x2;} else {xx1=x2; xx2=x1;} |
||
190 | if(y1<y2) {yy1=y1; yy2=y2;} else {yy1=y2; yy2=y1;} |
||
11121 | georgesk | 191 | if(minx>x1) minx=x1; |
192 | if(miny>y1) miny=y1; |
||
193 | if(maxx<x2) maxx=x2; |
||
194 | if(maxy<y2) maxy=y2; |
||
10 | reyssat | 195 | } |
196 | else { |
||
197 | x1=rint(dviratio*d_h)-minx; y1=rint(dviratio*d_v)-miny; |
||
198 | x2=x1+xx; y2=y1-yy; |
||
199 | if(x1<x2) {xx1=x1; xx2=x2;} else {xx1=x2; xx2=x1;} |
||
200 | if(y1<y2) {yy1=y1; yy2=y2;} else {yy1=y2; yy2=y1;} |
||
201 | gdImageFilledRectangle(image,xx1,yy1,xx2,yy2,currentcolor); |
||
202 | } |
||
203 | return xxx; |
||
204 | } |
||
205 | |||
206 | void DVI_set_rule(void) |
||
207 | { |
||
208 | d_h+=DVI_put_rule(); |
||
209 | } |
||
210 | |||
211 | void DVI_fnt_num(int p) |
||
212 | { |
||
213 | int fnum; |
||
214 | if(p==0) fnum=*dviptr-171; else fnum=texint(dviptr+1,p); |
||
215 | dviptr+=p; |
||
216 | for(d_f=0; d_f<fontcnt && wfont[d_f].num!=fnum; d_f++); |
||
8195 | bpr | 217 | if(d_f>=fontcnt) texgif_error("Bad dvi: using font before defining it."); |
10 | reyssat | 218 | } |
219 | |||
220 | void DVI_fnt_def(int p) |
||
221 | { |
||
222 | int i, fnum, fdensity; |
||
223 | char fname[1024]; |
||
224 | unsigned long int c,s,d,a,l; |
||
225 | double fratio; |
||
226 | union { unsigned long c; char C[4]; } U; |
||
227 | |||
8195 | bpr | 228 | if(fontcnt>=FONT_NUMBER_LIMIT) texgif_error("Font number exceeded design capacity."); |
10 | reyssat | 229 | fnum=texint(++dviptr,p); dviptr+=p; |
230 | for (i = 0; i <= 3; i++) U.C[i] = dviptr[i]; |
||
231 | c=U.c; dviptr+=4; |
||
232 | s=texint(dviptr,4); dviptr+=4; |
||
233 | d=texint(dviptr,4); dviptr+=4; |
||
234 | a=*dviptr++; l=*dviptr++; |
||
8195 | bpr | 235 | if(a+l>1000 || a+l<1) texgif_error("Bad dvi: bad font name."); |
10 | reyssat | 236 | memmove(fname,dviptr,a+l); fname[a+l]=0; dviptr+=a+l-1; |
237 | if(pass==1) { |
||
238 | fdensity=(double) density*((double) s/d); |
||
239 | if(loadfont(fname, c, fdensity, wfont+fontcnt)==NULL) { |
||
8100 | bpr | 240 | if(loadfont("cmr10",0,fdensity,wfont+fontcnt)==NULL) |
8195 | bpr | 241 | texgif_error("Font panick: even cmr10 cannot be found."); |
10 | reyssat | 242 | else fprintf(stderr,"Font %s not found; replace by cmr10.\n",fname); |
243 | } |
||
244 | wfont[fontcnt].num=fnum; |
||
245 | fratio=(double) s/wfont[fontcnt].designsize*d/65536; |
||
246 | for(i=0;i<wfont[fontcnt].cnt; i++) |
||
247 | wfont[fontcnt].fh[i].w=fratio*wfont[fontcnt].fh[i].w; |
||
248 | fontcnt++; |
||
249 | } |
||
250 | } |
||
251 | |||
252 | void DVI_push(void) |
||
253 | { |
||
8195 | bpr | 254 | if(dvistackptr>=DVI_STACK_LIMIT) texgif_error("dvi stack overflow."); |
10 | reyssat | 255 | dvistack[dvistackptr].h=d_h; |
256 | dvistack[dvistackptr].v=d_v; |
||
257 | dvistack[dvistackptr].w=d_w; |
||
258 | dvistack[dvistackptr].x=d_x; |
||
259 | dvistack[dvistackptr].y=d_y; |
||
260 | dvistack[dvistackptr].z=d_z; |
||
261 | dvistackptr++; |
||
262 | } |
||
263 | |||
264 | void DVI_pop(void) |
||
265 | { |
||
8195 | bpr | 266 | if(dvistackptr<=0) texgif_error("Bad dvi file: dvi stack underflow."); |
10 | reyssat | 267 | dvistackptr--; |
268 | d_h=dvistack[dvistackptr].h; |
||
269 | d_v=dvistack[dvistackptr].v; |
||
270 | d_w=dvistack[dvistackptr].w; |
||
271 | d_x=dvistack[dvistackptr].x; |
||
272 | d_y=dvistack[dvistackptr].y; |
||
273 | d_z=dvistack[dvistackptr].z; |
||
274 | } |
||
275 | |||
276 | void DVI_move(int *hv, int p) |
||
277 | { |
||
278 | int t; |
||
279 | t=texintsigned(dviptr+1,p); dviptr+=p; |
||
280 | *hv+=t; |
||
281 | } |
||
282 | |||
283 | void DVI_move2(int *hv, int *xyz, int p) |
||
284 | { |
||
285 | if(p>0) *xyz=texintsigned(dviptr+1,p); |
||
286 | *hv+=*xyz; |
||
287 | dviptr+=p; |
||
288 | } |
||
289 | |||
290 | void DVI_xxx(int p) |
||
291 | { |
||
292 | int i, t; |
||
293 | char *pp, buf[1024]; |
||
8100 | bpr | 294 | |
10 | reyssat | 295 | t=texint(dviptr+1,p); |
296 | if(pass<2 || t>1000) {dviptr+=t+p; return;} |
||
297 | memmove(buf,dviptr+1+1,t); buf[t]=0; |
||
298 | dviptr+=t+p; |
||
299 | for(i=0;i<t;i++) buf[i]=tolower(buf[i]); |
||
300 | if(strncmp(buf,"color",5)!=0) return; |
||
301 | pp=find_word_start(buf+5); if(*pp!='=') return; |
||
302 | makecolor(pp+1); |
||
303 | } |
||
304 | |||
305 | /* load and interprete dvi file */ |
||
306 | void dvi(void) |
||
307 | { |
||
308 | unsigned char cc, *startpoint; |
||
309 | char namebuf[1024]; |
||
8100 | bpr | 310 | |
10 | reyssat | 311 | snprintf(namebuf,sizeof(namebuf),"%s/texgif.dvi",tmpdir); |
312 | dvilen=getfile(namebuf,&dvibuf); |
||
8195 | bpr | 313 | if(dvilen<=0) texgif_error("dvi file not found."); |
10 | reyssat | 314 | dviptr=dvibuf; fontcnt=0; |
315 | if(*dviptr++!=dvi_pre || *dviptr++!=2) { |
||
8195 | bpr | 316 | /* baddvi: */ texgif_error("Bad dvi file header."); |
10 | reyssat | 317 | } |
318 | num=texint(dviptr,4); dviptr+=4; |
||
319 | den=texint(dviptr,4); dviptr+=4; |
||
320 | mag=texint(dviptr,4); dviptr+=4; |
||
321 | cc=*dviptr++; dviptr+=cc; startpoint=dviptr; |
||
322 | density=rint((double) compressratio*mag*basedensity/1000); |
||
323 | dviratio=(double) num/den*density/254000; |
||
324 | printf("dvi file: num=%d, den=%d, ratio=%f, mag=%d, density=%d\n", |
||
325 | num,den,dviratio, mag, density); |
||
326 | for(pass=1; pass<=2; pass++) { |
||
327 | passstop=0; d_f=-1; pageptr=0; |
||
328 | for(dviptr=startpoint; dviptr<dvibuf+dvilen && passstop>=0; dviptr++) { |
||
329 | if(*dviptr<128) { |
||
330 | DVI_set(0); continue; |
||
331 | } |
||
332 | if(*dviptr>=171 && *dviptr<=234) { |
||
333 | DVI_fnt_num(0); continue; |
||
334 | } |
||
335 | switch(*dviptr) { |
||
336 | case dvi_set1: case dvi_set2: case dvi_set3: |
||
337 | case dvi_set4: DVI_set(*dviptr-dvi_set1+1); break; |
||
338 | case dvi_set_rule: DVI_set_rule(); break; |
||
8100 | bpr | 339 | |
10 | reyssat | 340 | case dvi_put1: case dvi_put2: case dvi_put3: |
341 | case dvi_put4: DVI_put(*dviptr-dvi_put1+1); break; |
||
342 | case dvi_put_rule: DVI_put_rule(); break; |
||
8100 | bpr | 343 | |
10 | reyssat | 344 | case dvi_nop: DVI_nop(); break; |
345 | case dvi_bop: DVI_bop(); break; |
||
346 | case dvi_eop: DVI_eop(); break; |
||
347 | case dvi_push: DVI_push(); break; |
||
348 | case dvi_pop: DVI_pop(); break; |
||
8100 | bpr | 349 | |
10 | reyssat | 350 | case dvi_right1: case dvi_right2: case dvi_right3: |
351 | case dvi_right4: DVI_move(&d_h, *dviptr-dvi_right1+1); break; |
||
8100 | bpr | 352 | |
10 | reyssat | 353 | case dvi_w0: case dvi_w1: case dvi_w2: case dvi_w3: |
354 | case dvi_w4: DVI_move2(&d_h, &d_w, *dviptr-dvi_w0); break; |
||
355 | case dvi_x0: case dvi_x1: case dvi_x2: case dvi_x3: |
||
356 | case dvi_x4: DVI_move2(&d_h, &d_x, *dviptr-dvi_x0); break; |
||
8100 | bpr | 357 | |
10 | reyssat | 358 | case dvi_down1: case dvi_down2: case dvi_down3: |
359 | case dvi_down4: DVI_move(&d_v, *dviptr-dvi_down1+1); break; |
||
8100 | bpr | 360 | |
10 | reyssat | 361 | case dvi_y0: case dvi_y1: case dvi_y2: case dvi_y3: |
362 | case dvi_y4: DVI_move2(&d_v, &d_y, *dviptr-dvi_y0); break; |
||
363 | case dvi_z0: case dvi_z1: case dvi_z2: case dvi_z3: |
||
364 | case dvi_z4: DVI_move2(&d_v, &d_z, *dviptr-dvi_z0); break; |
||
8100 | bpr | 365 | |
10 | reyssat | 366 | case dvi_fnt1: case dvi_fnt2: case dvi_fnt3: |
367 | case dvi_fnt4: DVI_fnt_num(*dviptr-dvi_fnt1+1); break; |
||
8100 | bpr | 368 | |
10 | reyssat | 369 | case dvi_xxx1: case dvi_xxx2: case dvi_xxx3: |
370 | case dvi_xxx4: DVI_xxx(*dviptr-dvi_xxx1+1); break; |
||
8100 | bpr | 371 | |
10 | reyssat | 372 | case dvi_fnt_def1: case dvi_fnt_def2: case dvi_fnt_def3: |
373 | case dvi_fnt_def4: DVI_fnt_def(*dviptr-dvi_fnt_def1+1); break; |
||
8100 | bpr | 374 | |
8195 | bpr | 375 | case dvi_pre: texgif_error("Bad dvi file: pre within file."); |
10 | reyssat | 376 | case dvi_post: DVI_post(); break; |
377 | case dvi_post_post: DVI_post_post(); break; |
||
8100 | bpr | 378 | |
8195 | bpr | 379 | default: texgif_error("Bad dvi file: unknown command."); |
10 | reyssat | 380 | } |
381 | } |
||
382 | } |
||
383 | free(dvibuf); |
||
384 | } |
||
385 |