Back to index

wims  3.65+svn20090927
dvi.c
Go to the documentation of this file.
00001 /*    Copyright (C) 2002-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
00002  *
00003  *  This program is free software; you can redistribute it and/or modify
00004  *  it under the terms of the GNU General Public License as published by
00005  *  the Free Software Foundation; either version 2 of the License, or
00006  *  (at your option) any later version.
00007  *
00008  *  This program is distributed in the hope that it will be useful,
00009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *  GNU General Public License for more details.
00012  *
00013  *  You should have received a copy of the GNU General Public License
00014  *  along with this program; if not, write to the Free Software
00015  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00016  */
00017 
00018 /* dvi 2 gif driver, dvi interpreter */
00019 
00020 unsigned char *dvibuf, *dviptr;
00021 int dvilen;
00022 int pass, passstop;
00023 int num, den, mag;
00024 int minx, maxx,miny, maxy;
00025 double dviratio;
00026 int dvix, dviy;
00027 int d_h,d_v,d_w,d_x,d_y,d_z;
00028 int d_f;
00029 int pageptr;
00030 struct {
00031     int minx, maxx, miny, maxy;
00032 } pagedata[MAX_PAGES];
00033 
00034 struct {
00035     int h,v,w,x,y,z;
00036 } dvistack[DVI_STACK_LIMIT];
00037 int dvistackptr;
00038 
00039 #define DVI_post_post       DVI_post
00040 void DVI_post(void)
00041 {
00042     passstop=-1; dviptr=dvibuf+dvilen;
00043 }
00044 
00045 void DVI_eop(void)
00046 {
00047     if(pass==1) {
00048        pagedata[pageptr].minx=minx;
00049        pagedata[pageptr].maxx=maxx;
00050        pagedata[pageptr].miny=miny;
00051        pagedata[pageptr].maxy=maxy;
00052     }
00053     else saveimage();
00054     pageptr++;
00055     if(*outfile==0 || pageptr>=MAX_PAGES) {
00056        passstop=-1; dviptr=dvibuf+dvilen;
00057     }
00058     else passstop=0;
00059 }
00060 
00061 void DVI_bop(void)
00062 {
00063     passstop=1; dvistackptr=0;
00064     d_h=d_v=d_w=d_x=d_y=d_z=0; d_f=-1;
00065     dviptr+=44;
00066     if(pass==1) {
00067        minx=miny=65536;
00068        maxx=maxy=-1;
00069     }
00070     else {
00071        char *p;
00072        maxx=pagedata[pageptr].maxx;
00073        minx=pagedata[pageptr].minx;
00074        maxy=pagedata[pageptr].maxy;
00075        miny=pagedata[pageptr].miny;
00076        if(maxx<=minx || maxy<=miny) error("Empty page.");
00077        createimage(maxx-minx,maxy-miny);
00078        currentcolor=color_black;
00079        p=getenv("w_instex_color");
00080        if(p!=NULL && *p!=0) makecolor(p);
00081     }
00082 }
00083 
00084 void DVI_nop(void) {}
00085 
00086 int DVI_put(int p)
00087 {
00088     int cc, ct, x1, x2, y1, y2;
00089     if(d_f<0) error("Bad dvi: trying to put non-existing font.");
00090     if(p==0) cc=*dviptr; else cc=texint(dviptr+1,p);
00091     dviptr+=p;
00092     if(cc<wfont[d_f].bc || cc>wfont[d_f].ec) return -1;
00093     dvix=rint(dviratio*d_h); dviy=rint(dviratio*d_v);
00094     if(pass==1) {
00095        ct=cc-wfont[d_f].bc;
00096        x1=dvix+wfont[d_f].fh[ct].xstart; y1=dviy+wfont[d_f].fh[ct].ystart;
00097        x2=x1+wfont[d_f].fh[ct].xmax; y2=y1+wfont[d_f].fh[ct].ymax;
00098        if(minx>x1) minx=x1; if(miny>y1) miny=y1;
00099        if(maxx<x2) maxx=x2; if(maxy<y2) maxy=y2;
00100     }
00101     else {
00102        paintfont(wfont+d_f,cc,dvix-minx,dviy-miny,currentcolor);
00103     }
00104     return cc;
00105 }
00106 
00107 void DVI_set(int p)
00108 {
00109     int cc;
00110     cc=DVI_put(p);
00111     if(cc<0) return;
00112     d_h+=wfont[d_f].fh[cc-wfont[d_f].bc].w;
00113 }
00114 
00115 int DVI_put_rule(void)
00116 {
00117     int xxx, xx, yy, x1, y1, x2, y2, xx1, xx2, yy1, yy2;
00118     yy=texint(dviptr+1,4); xx=texint(dviptr+5,4); dviptr+=8;
00119     if(xx<=0 || yy<=0) return xx;
00120     xxx=xx;
00121     if(xx>=0) {xx=rint(dviratio*xx+blacker); if(xx>0) xx--;}
00122     else {xx=rint(dviratio*xx-blacker); if(xx<0) xx--;}
00123     if(yy>=0) {yy=rint(dviratio*yy+blacker); if(yy>0) yy--;}
00124     else {yy=rint(dviratio*yy-blacker); if(yy<0) yy--;}
00125     if(pass==1) {
00126        x1=rint(dviratio*d_h); y2=rint(dviratio*d_v);
00127        x2=x1+xx; y1=y2-yy;
00128        if(x1<x2) {xx1=x1; xx2=x2;} else {xx1=x2; xx2=x1;}
00129        if(y1<y2) {yy1=y1; yy2=y2;} else {yy1=y2; yy2=y1;}
00130        if(minx>x1) minx=x1; if(miny>y1) miny=y1;
00131        if(maxx<x2) maxx=x2; if(maxy<y2) maxy=y2;
00132     }
00133     else {
00134        x1=rint(dviratio*d_h)-minx; y1=rint(dviratio*d_v)-miny;
00135        x2=x1+xx; y2=y1-yy;
00136        if(x1<x2) {xx1=x1; xx2=x2;} else {xx1=x2; xx2=x1;}
00137        if(y1<y2) {yy1=y1; yy2=y2;} else {yy1=y2; yy2=y1;}
00138        gdImageFilledRectangle(image,xx1,yy1,xx2,yy2,currentcolor);
00139     }
00140     return xxx;
00141 }
00142 
00143 void DVI_set_rule(void)
00144 {
00145     d_h+=DVI_put_rule();
00146 }
00147 
00148 void DVI_fnt_num(int p)
00149 {
00150     int fnum;
00151     if(p==0) fnum=*dviptr-171; else fnum=texint(dviptr+1,p);
00152     dviptr+=p;
00153     for(d_f=0; d_f<fontcnt && wfont[d_f].num!=fnum; d_f++);
00154     if(d_f>=fontcnt) error("Bad dvi: using font before defining it.");
00155 }
00156 
00157 void DVI_fnt_def(int p)
00158 {
00159     int i, fnum, fdensity;
00160     char fname[1024];
00161     unsigned long int c,s,d,a,l;
00162     double fratio;
00163     union { unsigned long c; char C[4]; } U;
00164 
00165     if(fontcnt>=FONT_NUMBER_LIMIT) error("Font number exceeded design capacity.");
00166     fnum=texint(++dviptr,p); dviptr+=p;
00167     for (i = 0; i <= 3; i++) U.C[i] = dviptr[i];
00168     c=U.c; dviptr+=4;
00169     s=texint(dviptr,4); dviptr+=4;
00170     d=texint(dviptr,4); dviptr+=4;
00171     a=*dviptr++; l=*dviptr++;
00172     if(a+l>1000 || a+l<1) error("Bad dvi: bad font name.");
00173     memmove(fname,dviptr,a+l); fname[a+l]=0; dviptr+=a+l-1;
00174     if(pass==1) {
00175        fdensity=(double) density*((double) s/d);
00176        if(loadfont(fname, c, fdensity, wfont+fontcnt)==NULL) {
00177            if(loadfont("cmr10",0,fdensity,wfont+fontcnt)==NULL) 
00178              error("Font panick: even cmr10 cannot be found.");
00179            else fprintf(stderr,"Font %s not found; replace by cmr10.\n",fname);
00180        }
00181        wfont[fontcnt].num=fnum;
00182        fratio=(double) s/wfont[fontcnt].designsize*d/65536;
00183        for(i=0;i<wfont[fontcnt].cnt; i++)
00184          wfont[fontcnt].fh[i].w=fratio*wfont[fontcnt].fh[i].w;
00185        fontcnt++;
00186     }
00187 }
00188 
00189 void DVI_push(void)
00190 {
00191     if(dvistackptr>=DVI_STACK_LIMIT) error("dvi stack overflow.");
00192     dvistack[dvistackptr].h=d_h;
00193     dvistack[dvistackptr].v=d_v;
00194     dvistack[dvistackptr].w=d_w;
00195     dvistack[dvistackptr].x=d_x;
00196     dvistack[dvistackptr].y=d_y;
00197     dvistack[dvistackptr].z=d_z;
00198     dvistackptr++;
00199 }
00200 
00201 void DVI_pop(void)
00202 {
00203     if(dvistackptr<=0) error("Bad dvi file: dvi stack underflow.");
00204     dvistackptr--;
00205     d_h=dvistack[dvistackptr].h;
00206     d_v=dvistack[dvistackptr].v;
00207     d_w=dvistack[dvistackptr].w;
00208     d_x=dvistack[dvistackptr].x;
00209     d_y=dvistack[dvistackptr].y;
00210     d_z=dvistack[dvistackptr].z;
00211 }
00212 
00213 void DVI_move(int *hv, int p)
00214 {
00215     int t;
00216     t=texintsigned(dviptr+1,p); dviptr+=p;
00217     *hv+=t;
00218 }
00219 
00220 void DVI_move2(int *hv, int *xyz, int p)
00221 {
00222     if(p>0) *xyz=texintsigned(dviptr+1,p);
00223     *hv+=*xyz;
00224     dviptr+=p;
00225 }
00226 
00227 void DVI_xxx(int p)
00228 {
00229     int i, t;
00230     char *pp, buf[1024];
00231     
00232     t=texint(dviptr+1,p);
00233     if(pass<2 || t>1000) {dviptr+=t+p; return;}
00234     memmove(buf,dviptr+1+1,t); buf[t]=0;
00235     dviptr+=t+p;
00236     for(i=0;i<t;i++) buf[i]=tolower(buf[i]);
00237     if(strncmp(buf,"color",5)!=0) return;
00238     pp=find_word_start(buf+5); if(*pp!='=') return;
00239     makecolor(pp+1);
00240 }
00241 
00242 #include "dvicmd.c"
00243 
00244        /* load and interprete dvi file */
00245 void dvi(void)
00246 {
00247     unsigned char cc, *startpoint;
00248     char namebuf[1024];
00249     
00250     snprintf(namebuf,sizeof(namebuf),"%s/texgif.dvi",tmpdir);
00251     dvilen=getfile(namebuf,&dvibuf);
00252     if(dvilen<=0) error("dvi file not found.");
00253     dviptr=dvibuf; fontcnt=0;
00254     if(*dviptr++!=dvi_pre || *dviptr++!=2) {
00255        /* baddvi: */ error("Bad dvi file header.");
00256     }
00257     num=texint(dviptr,4); dviptr+=4;
00258     den=texint(dviptr,4); dviptr+=4;
00259     mag=texint(dviptr,4); dviptr+=4;
00260     cc=*dviptr++; dviptr+=cc; startpoint=dviptr;
00261     density=rint((double) compressratio*mag*basedensity/1000);
00262     dviratio=(double) num/den*density/254000;
00263 printf("dvi file: num=%d, den=%d, ratio=%f, mag=%d, density=%d\n",
00264        num,den,dviratio, mag, density);
00265     for(pass=1; pass<=2; pass++) {
00266        passstop=0; d_f=-1; pageptr=0;
00267        for(dviptr=startpoint; dviptr<dvibuf+dvilen && passstop>=0; dviptr++) {
00268            if(*dviptr<128) {
00269               DVI_set(0); continue;
00270            }
00271            if(*dviptr>=171 && *dviptr<=234) {
00272               DVI_fnt_num(0); continue;
00273            }
00274            switch(*dviptr) {
00275               case dvi_set1: case dvi_set2: case dvi_set3:
00276               case dvi_set4: DVI_set(*dviptr-dvi_set1+1); break;
00277               case dvi_set_rule: DVI_set_rule(); break;
00278               
00279               case dvi_put1: case dvi_put2: case dvi_put3:
00280               case dvi_put4: DVI_put(*dviptr-dvi_put1+1); break;
00281               case dvi_put_rule: DVI_put_rule(); break;
00282               
00283               case dvi_nop: DVI_nop(); break;
00284               case dvi_bop: DVI_bop(); break;
00285               case dvi_eop: DVI_eop(); break;
00286               case dvi_push: DVI_push(); break;
00287               case dvi_pop: DVI_pop(); break;
00288               
00289               case dvi_right1: case dvi_right2: case dvi_right3:
00290               case dvi_right4: DVI_move(&d_h, *dviptr-dvi_right1+1); break;
00291               
00292               case dvi_w0: case dvi_w1: case dvi_w2: case dvi_w3:
00293               case dvi_w4: DVI_move2(&d_h, &d_w, *dviptr-dvi_w0); break;
00294               case dvi_x0: case dvi_x1: case dvi_x2: case dvi_x3:
00295               case dvi_x4: DVI_move2(&d_h, &d_x, *dviptr-dvi_x0); break;
00296        
00297               case dvi_down1: case dvi_down2: case dvi_down3:
00298               case dvi_down4: DVI_move(&d_v, *dviptr-dvi_down1+1); break;
00299               
00300               case dvi_y0: case dvi_y1: case dvi_y2: case dvi_y3:
00301               case dvi_y4: DVI_move2(&d_v, &d_y, *dviptr-dvi_y0); break;
00302               case dvi_z0: case dvi_z1: case dvi_z2: case dvi_z3:
00303               case dvi_z4: DVI_move2(&d_v, &d_z, *dviptr-dvi_z0); break;
00304               
00305               case dvi_fnt1: case dvi_fnt2: case dvi_fnt3:
00306               case dvi_fnt4: DVI_fnt_num(*dviptr-dvi_fnt1+1); break;
00307               
00308               case dvi_xxx1: case dvi_xxx2: case dvi_xxx3:
00309               case dvi_xxx4: DVI_xxx(*dviptr-dvi_xxx1+1); break;
00310               
00311               case dvi_fnt_def1: case dvi_fnt_def2: case dvi_fnt_def3:
00312               case dvi_fnt_def4: DVI_fnt_def(*dviptr-dvi_fnt_def1+1); break;
00313               
00314               case dvi_pre: error("Bad dvi file: pre within file.");
00315               case dvi_post: DVI_post(); break;
00316               case dvi_post_post: DVI_post_post(); break;
00317               
00318               default: error("Bad dvi file: unknown command.");
00319            }
00320        }
00321     }
00322     free(dvibuf);
00323 }
00324