draw.c

0000#include <stdio.h>
0001#include <stdlib.h>
0002#include <string.h>
0003#include <math.h>
0004#include "draw.h"
0005#include "gcs1.h"
0006
0007/**************** basic draw information ***********/
0008unsigned char* pD; // bitmap buffer
0009int depthD; // Mac standard 256 colors
0010int widthD; // picture size
0011int heightD;
0012int coloD; // current color for drawing
0013int xD; // current pen position
0014int yD;
0015int cliplD; // clip rect left
0016int cliprD;
0017int cliptD;
0018int clipbD;
0019
0020/**************** for polygon ***************/
0021unsigned char* poD; // bitmap buffer
0022int polyWidthD; // number of chars for one line of poD
0023int firstPtxD; // x value of first point. saved for closure
0024int firstPtyD;
0025int vertXD; // left-upper line crossings
0026int horiXD; // upper-left line crossings
0027int polyD; // 1 if polygon mode
0028int pxminD,pxmaxD,pyminD,pymaxD; // bounding rect
0029
0030/***************** for font ********************/
0031unsigned char* pfD; // font bitmap
0032int fontD; // font id (11,16,22)
0033int direcD; // direction of string 0:horiz 1:vert
0034int modeD; // current pen position is 0:left 1:right 2:center of string
0035int widthBytesD;
0036int fontBytesD;
0037int ascentD;
0038int descentD;
0039int fontWidthD;
0040int fontHeightD;
0041#include "font.c"
0042
0043/***************** for graph ********************/
0044int lgD,tgD,rgD,bgD;
0045double ldgD,tdgD,rdgD,bdgD;
0046int htD,hlD,vlD;
0047
0048int lzw;
0049unsigned char sizeOfCTD; // depthD-1
0050unsigned char outBufD[260];
0051int bitPtrD;
0052int bitsD;
0053FILE *fpD;
0054
0055/**************** for CRC ********************/
0056unsigned long crc_table[256];
0057int crc_table_computed=0;
0058
0059int MakeView(int width,int height)
0060{
0061 int i,j;
0062 widthD=width;
0063 heightD=height;
0064 pD=(unsigned char *)malloc((widthD+1)*heightD*sizeof(char));
0065 j=widthD*heightD;
0066 for(i=0;i<j;i++) pD[i]=0;
0067 depthD=8;
0068 if(widthD%8==0) polyWidthD=widthD/8; // width for buffer
0069 else polyWidthD=width/8+1;
0070 poD=(unsigned char *)malloc(polyWidthD*heightD*sizeof(char));
0071 cliplD=0; // clip rect left
0072 cliprD=widthD;
0073 cliptD=0;
0074 clipbD=heightD;
0075 polyD=0; // not polygon mode initially
0076 lzw=0; // not compress
0077}
0078
0079int SetColor(int r1,int g1,int b1)
0080{
0081  int i;
0082  unsigned int r,g,b;
0083  
0084  r=r1*(0xffff/100);
0085  g=g1*(0xffff/100);
0086  b=b1*(0xffff/100);
0087
0088  if(r==0&&g==0&&b==0){
0089    coloD=255;
0090    return;
0091  }
0092  if(r==0xffff&&g==0xffff&&b==0xffff){
0093    coloD=0;
0094    return;
0095  }
0096  if(r==0&&g==0){
0097    i=(b+2185)/4369;
0098    if(i%3!=0){
0099      coloD=245-(i-i/3);
0100      return;
0101    }
0102  }
0103  if(g==0&&b==0){
0104    i=(r+2185)/4369;
0105    if(i%3!=0){
0106      coloD=225-(i-i/3);
0107      return;
0108    }
0109  }
0110  if(b==0&&r==0){
0111    i=(g+2185)/4369;
0112    if(i%3!=0){
0113      coloD=235-(i-i/3);
0114      return;
0115    }
0116  }
0117  if(b==g&&r==g){ // gray scale
0118    i=(g+2185)/4369;
0119    if(i!=0&&i%3!=0){
0120      coloD=255-(i-i/3);
0121      return;
0122    }
0123  }
0124  coloD=215-((r+6554)/13107)*36-((g+6554)/13107)*6-(b+6554)/13107;
0125  if(coloD==215) coloD=255;
0126}
0127
0128int MoveTo(int x,int y)
0129{
0130  if(polyD){
0131   firstPtxD=x;
0132   firstPtyD=y;
0133   if(x<pxminD) pxminD=x;
0134   if(x>pxmaxD) pxmaxD=x;
0135   if(y<pyminD) pyminD=y;
0136   if(y>pymaxD) pymaxD=y;
0137  }
0138  xD=x;
0139  yD=y;
0140}
0141
0142int LineTo(int x1,int y1)
0143{
0144  int a,dx,dy,b,two_a,two_b,xcrit,eps;
0145  unsigned char i;
0146  if(polyD){
0147   if(x1<pxminD) pxminD=x1;
0148   if(x1>pxmaxD) pxmaxD=x1;
0149   if(y1<pyminD) pyminD=y1;
0150   if(y1>pymaxD) pymaxD=y1;
0151   if(xD*x1<0){
0152    if((xD*y1-yD*x1)/(xD-x1)<0) vertXD++;
0153   }
0154   if(yD*y1<0){
0155    if((yD*x1-xD*y1)/(yD-y1)<0) horiXD++;
0156   }
0157  }
0158  dx=1;
0159  a=x1-xD;
0160  if(a<0){
0161   dx=-1;
0162   a=-a;
0163  }
0164
0165  dy=1;
0166  b=y1-yD;
0167  if(b<0){
0168   dy=-1;
0169   b=-b;
0170  }
0171  two_a = 2*a;
0172  two_b = 2*b;
0173  xcrit = -b+two_a;
0174  eps=0;
0175
0176  for(;;){
0177    if(cliplD<=xD && xD<cliprD && cliptD<=yD && yD<clipbD){
0178     if(polyD){
0179      i=1<<(xD%8);
0180      poD[yD*polyWidthD+xD/8]|=i;
0181     }
0182     else *(pD+yD*widthD+xD)=coloD;
0183    }
0184    if(xD==x1&&yD==y1) break;
0185    if(eps<=xcrit) xD += dx, eps+=two_b;
0186    if(eps>=a || a<=b) yD += dy, eps-=two_a;
0187  }
0188}
0189
0190int OpenPoly()
0191{
0192  int i,j;
0193  for(j=0;j<heightD;j++)
0194   for(i=0;i<polyWidthD;i++) poD[j*polyWidthD+i]=0;
0195  polyD=1; // polygon mode on
0196  vertXD=0; // left-upper line crossings
0197  horiXD=0;
0198  pxminD=10000;
0199  pxmaxD=-10000;
0200  pyminD=10000;
0201  pymaxD=-10000;
0202}
0203
0204int ClosePoly()
0205{
0206  int transitD[31][3]; // first black points and last black points
0207                       // for three lines
0208  int cornerBlack;
0209  int i,j,k,l,i1,i2,i3,i4,i5,i6,i7,i8;
0210  unsigned char m;
0211
0212  LineTo(firstPtxD,firstPtyD); // close polygon
0213  polyD=0; // polygon mode off
0214  if(pxminD>=widthD) return; // out of view
0215  if(pxmaxD<0) return;
0216  if(pyminD>=heightD) return;
0217  if(pymaxD<0) return;
0218
0219  pxmaxD++; // past-the-boundary value
0220  pymaxD++;
0221
0222  if(pxminD<0) pxminD=0; // crossing rect
0223  if(pxmaxD>widthD) pxmaxD=widthD;
0224  if(pyminD<0) pyminD=0;
0225  if(pymaxD>heightD) pymaxD=heightD;
0226
0227  if(pxminD==(pxmaxD-1)) return;
0228  if(pyminD==(pymaxD-1)) return;
0229  
0230  cornerBlack=0; // upper left corner is white
0231  if(pxminD==0&&pyminD==0){
0232   if(vertXD%2==1) cornerBlack=1;
0233  }
0234
0235  for(j=pyminD;j<pymaxD;j++){
0236   for(k=0;k<31;k++){
0237    transitD[k][0]=transitD[k][1];
0238    transitD[k][1]=transitD[k][2];
0239    transitD[k][2]=-1;
0240   }
0241   k=0; // point white
0242   for(i=pxminD;i<pxmaxD;i++){
0243    m=poD[j*polyWidthD+i/8];
0244    if(m&(1<<(i%8))){ // black
0245     if(k%3==0){
0246      transitD[k][2]=i; // first black
0247      k++;
0248     }
0249    }
0250    else{ // white
0251     if(k%3==1){
0252      transitD[k][2]=i-1; // last black
0253      k+=2;
0254     }
0255    }
0256   } /* for(i=pxminD;i<pxmaxD;i++) */
0257   if(k%3==1){
0258    transitD[k][2]=i-1; // last point is black
0259    k+=2;
0260   }
0261   transitD[30][2]=k/3; // number of islands
0262   if(j>pyminD){ // if line 1 and abobe , process line 0
0263    for(k=0;k<transitD[30][1];k++){
0264     i1=transitD[3*k][1];
0265     i2=transitD[3*k+1][1];
0266     i3=0;
0267     for(i4=0;i4<transitD[30][2];i4++){
0268      i5=transitD[3*i4][2];
0269      i6=transitD[3*i4+1][2];
0270      if(i6>=(i1-1)&&i5<=(i2+1)) i3++;
0271     }
0272     transitD[3*k+2][1]=i3;
0273    }
0274   } /* if(j>pyminD) */
0275   if(j>pyminD+1){ // re-evaluate 3-line data and fill first line
0276    i1=0;
0277    for(k=0;k<transitD[30][0];k++) i1+=transitD[3*k+2][0];
0278    i2=0;
0279    for(k=0;k<transitD[30][1];k++) i2+=transitD[3*k+2][1];
0280    if(i1==i2-1){ // change somewhere in transitD[3*k+2][0] to 2
0281     for(k=0;k<transitD[30][0];k++) transitD[3*k+2][0]=transitD[3*k+2][1];
0282    }
0283    else if(i2==i1-1){
0284     for(k=0;k<transitD[30][1];k++){
0285      i1=transitD[3*k][1];
0286      i2=transitD[3*k+1][1];
0287      i3=0;
0288      for(i4=0;i4<transitD[30][0];i4++){
0289       i5=transitD[3*i4][0];
0290       i6=transitD[3*i4+1][0];
0291       if(i6>=(i1-1)&&i5<=(i2+1)) i3++;
0292      }
0293      if(i3==2&&transitD[3*k+2][1]==1) transitD[3*k+2][1]=0;
0294     }
0295    } /* else if(i2==i1-1) */
0296    i8=cornerBlack; // starting color
0297    i7=pxminD;
0298    for(k=0;k<transitD[30][0];k++){
0299     i1=transitD[3*k][0];
0300     if(i8){ // if black, paint from i7 to i1
0301      for(l=i7;l<i1;l++)
0302      poD[(j-2)*polyWidthD+l/8]|=(1<<l%8);
0303     }
0304     if(transitD[3*k+2][0]==1){
0305      if(i8==1) i8=0;
0306      else i8=1;
0307     }
0308     i7=transitD[3*k+1][0]+1;
0309    }
0310    if(i8==1&&i7<pxmaxD){ // paint to the end of line
0311     for(l=i7;l<pxmaxD;l++)
0312      poD[(j-2)*polyWidthD+l/8]|=(1<<l%8);
0313    }
0314   } /* if(j>pymind+1) */      
0315  } /* for(j=pyminD;j<pymaxD,j++) */
0316/* now do for last two lines */
0317  for(k=0;k<transitD[30][2];k++){
0318   i1=transitD[3*k][2];
0319   i2=transitD[3*k+1][2];
0320   i3=0;
0321   for(i4=0;i4<transitD[30][1];i4++){
0322    i5=transitD[3*i4][1];
0323    i6=transitD[3*i4+1][1];
0324    if(i6>=(i1-1)&&i5<=(i2+1)) i3++;
0325   }
0326   transitD[3*k+2][2]=i3;
0327  }
0328  i1=0;
0329  for(k=0;k<transitD[30][1];k++) i1+=transitD[3*k+2][1];
0330  i2=0;
0331  for(k=0;k<transitD[30][2];k++) i2+=transitD[3*k+2][2];
0332  if(i1==i2-1){ // change somewhere in transitD[3*k+2][0] to 0
0333   for(k=0;k<transitD[30][2];k++) transitD[3*k+2][2]=transitD[3*k+2][1];
0334  }
0335  for(j=0;j<2;j++){
0336   i8=cornerBlack;
0337   i7=pxminD;
0338   for(k=0;k<transitD[30][j+1];k++){
0339    i1=transitD[3*k][j+1];
0340    if(i8){ // if black, paint from i7 to i1
0341     for(l=i7;l<i1;l++)
0342      poD[(pymaxD-2+j)*polyWidthD+l/8]|=(1<<l%8);
0343    }
0344    if(transitD[3*k+2][j+1]==1){
0345     if(i8==1) i8=0;
0346     else i8=1;
0347    }
0348    i7=transitD[3*k+1][j+1]+1;
0349   }
0350   if(i8==1&&i7<pxmaxD){ // paint to the end of line
0351    for(l=i7;l<pxmaxD;l++)
0352     poD[(pymaxD-2+j)*polyWidthD+l/8]|=(1<<l%8);
0353   }
0354  }
0355/* now poD has been painted, next we will paint pD in coloD */
0356  for(j=pyminD;j<pymaxD;j++){
0357   for(i=pxminD;i<pxmaxD;i++){
0358    m=poD[j*polyWidthD+i/8];
0359    if(m&(1<<(i%8)))
0360      *(pD+j*widthD+i)=coloD;
0361   }
0362  }
0363}
0364
0365int FontInfo(int font,int direc,int mode)
0366{
0367 fontD=font;
0368 switch(font){
0369  case 11: // 6x11
0370   pfD=fontdata_6x11;
0371   ascentD=8;
0372   descentD=3;
0373   fontWidthD=6;
0374   fontHeightD=11;
0375   widthBytesD=1;
0376   fontBytesD=11;
0377   break;
0378  case 16: // 8x16
0379   pfD=fontdata_8x16;
0380   ascentD=11;
0381   descentD=5;
0382   fontWidthD=8;
0383   fontHeightD=16;
0384   widthBytesD=1;
0385   fontBytesD=16;
0386   break;
0387  case 22: // 12x22
0388   pfD=fontdata_12x22;
0389   ascentD=16;
0390   descentD=6;
0391   fontWidthD=12;
0392   fontHeightD=22;
0393   widthBytesD=2;
0394   fontBytesD=44;
0395   break;
0396 }
0397 direcD=direc;
0398 modeD=mode;
0399}
0400
0401int DrawString(char *c)
0402{
0403  long int dots[1056]; // up to and including double size of 12x22
0404  int h,i,j,k,l,m,n,k0,x,y;
0405  unsigned char test,mask;
0406
0407  if(modeD==0);
0408  else{
0409   i=strlen(c);
0410   i=i*fontWidthD;
0411   if(modeD==2) i/=2; /* center */
0412   if(direcD==0) xD-=i;
0413   else yD+=i;
0414  }
0415  for(h=0;c[h]!='\0';h++){
0416   k0=fontBytesD*(int)c[h];
0417   n=0;
0418   for(i=0;i<fontHeightD;i++){
0419    k=k0+i*widthBytesD;
0420    m=0;
0421    for(j=0;j<widthBytesD;j++){
0422      test=pfD[k+j];
0423      mask=0x80;
0424      for(l=0;l<8;l++){
0425	if(test&mask){
0426         if(direcD==0){ // horizontal
0427          y=yD-ascentD+i;
0428          x=xD+j*8+l;
0429         }
0430         else{ // vertical
0431          x=xD-ascentD+i;
0432          y=yD-j*8-l;
0433         }
0434         if(x>=0&&x<widthD&&y>=0&&y<heightD)
0435          dots[n++]=y*widthD+x;
0436        }
0437	mask>>=1;
0438	m++;
0439	if(m==fontWidthD) break;
0440      }
0441    }
0442   } /* for(i=0;i<fontHeightD;i++) */
0443   for(j=0;j<n;j++) *(pD+dots[j])=coloD;
0444   if(direcD==0) xD+=fontWidthD;
0445   else yD-=fontWidthD;
0446  } /* for(h=0;c[h]!='\0';h++) */
0447}
0448
0449int DrawNum(int i)
0450{
0451 char c[15];
0452 sprintf(c,"%i",i);
0453 DrawString(c);
0454}
0455
0456int DrawFNum(char *f,double a)
0457{
0458 char c[30];
0459 sprintf(c,f,a);
0460 DrawString(c);
0461} 
0462
0463int MakeGraph(int left,int top,int right,int bottom)
0464{
0465 lgD=left;
0466 tgD=top;
0467 rgD=right;
0468 bgD=bottom;
0469 htD=0;
0470 hlD=0;
0471 vlD=0;
0472}
0473
0474int HorizTime()
0475{
0476 htD=1;
0477}
0478
0479int HorizLog()
0480{
0481 hlD=1;
0482}
0483
0484int VertLog()
0485{
0486 vlD=1;
0487}
0488
0489int format(int col,double num,char* fig)
0490{
0491 int i,j,colst,inte1,ncha;
0492 double a,frac;
0493 double inte;
0494 char c[10]={'0','1','2','3','4','5','6','7','8','9'};
0495
0496 ncha=0;
0497 i=0;
0498 if(num<0.){
0499  i++;
0500  fig[ncha++]='-';
0501  num=fabs(num);
0502 }
0503
0504 if(num!=0.){
0505  a=log10(num);
0506  frac=modf(a,&inte);
0507  colst=inte+0.1;
0508  if(colst<0) colst=0;
0509 }
0510 else colst=0;
0511        
0512 num+=pow(10,colst-6);
0513        
0514 frac=num/pow(10,colst);
0515 if(frac<1.&&frac>0.9999) frac=1.;
0516 for(j=colst;j>=0;j--){
0517  if(frac<1.&&frac>0.9999) frac=1.;
0518  frac=modf(frac,&inte)*10.;
0519  inte1=inte;
0520  i++;
0521  fig[ncha++]=c[inte1];
0522 }
0523
0524 if(col!=0){
0525  i++;
0526  fig[ncha++]='.';
0527  for(j=col;j>0;j--){
0528   if(frac<1.&&frac>0.9999) frac=1.;
0529   frac=modf(frac,&inte)*10.;
0530   inte1=inte;
0531   i++;
0532   fig[ncha++]=c[inte1];
0533  }
0534 }
0535 fig[ncha]='\0';
0536 return i;
0537}
0538
0539
0540int HorizScale(char *c,double left,double right)
0541{
0542 int i,j,ix,colx;
0543 double stepc,stepf,delta,intef,frac,num;
0544 char ar[12];
0545 double mdy,hms,scl;
0546 char *month[]={"Jan","Feb","Mar","Apr","May","Jun",
0547  "Jul","Aug","Sep","Oct","Nov","Dec"};
0548
0549 ldgD=left;
0550 rdgD=right;
0551 delta=right-left;
0552 MoveTo(lgD,bgD);
0553 LineTo(rgD,bgD);
0554if(htD==0){
0555 frac=modf(log10(delta),&intef);
0556 stepc=pow(10.,intef-1);
0557 stepf=stepc;
0558 if(frac<0.2) stepf*=0.5;
0559 else if(frac<0.8) stepc*=5.;
0560 else{
0561  stepc*=10.;
0562  stepf*=5.;
0563 }
0564 frac=modf(log10(stepc),&intef);
0565// if(log10(stepc)<0.) colx=-intef+1.;
0566 if(log10(stepc)<0.) colx=-log10(stepc)+0.8;
0567 else colx=0;
0568 frac=modf(left/stepc,&intef);
0569 frac=intef;
0570 if(hlD){
0571  stepc=1.;
0572  colx=0;
0573 }
0574 while(1){
0575  num=frac*stepc;                        // x value for grid
0576  if(num>rdgD) break;
0577  ix=(rgD-lgD)*((num-ldgD)/(rdgD-ldgD))+lgD;
0578  i=format(colx,num,ar);
0579  MoveTo(ix,tgD);
0580  LineTo(ix,bgD+2);
0581  FontInfo(11,0,0);
0582  for(i=0;ar[i]!='\0';i++);
0583  if(hlD){
0584   MoveTo(ix-i*3+4,bgD+12);
0585   DrawString(ar);
0586   MoveTo(ix-i*3-6,bgD+20);
0587   DrawString("10");
0588  }
0589  else{
0590   MoveTo(ix-i*3,bgD+12);
0591   DrawString(ar);
0592  }
0593  frac++;
0594 }
0595}
0596else{ /* horiz is time */
0597  mdy=mdyday(left);
0598  hms=hmsday(left);
0599  scl=(rgD-lgD)/delta;  /* dots per day */
0600  if(delta>700.){ /* yr */   
0601   frac=fmod(mdy*1000000.,10000.);
0602   while(1){
0603    num=refday(1.01+frac/1000000.,0.);     // x value for grid
0604    if(num>rdgD) break;
0605    ix=scl*(num-ldgD)+lgD;
0606    i=format(0,frac,ar);
0607    MoveTo(ix,tgD);
0608    LineTo(ix,bgD+2);
0609    if(num+182.>rdgD) break;
0610    FontInfo(11,0,2); /* center */
0611    ix=scl*(num+182.-ldgD)+lgD;
0612    MoveTo(ix,bgD+12);
0613    if(scl>0.07) DrawString(ar);
0614    else DrawString(&ar[2]);
0615    frac++; /* add a year */
0616   }
0617  }
0618  else if(delta>70.){ /* mo */
0619   stepc=fmod(mdy*1000000.,10000.); 
0620   stepf=floor(mdy);
0621   while(1){
0622    num=refday(stepf+0.01+stepc/1000000.,0.);     // x value for grid
0623    if(num>rdgD) break;
0624    if(num>ldgD){
0625     ix=scl*(num-ldgD)+lgD;
0626     MoveTo(ix,tgD);
0627     LineTo(ix,bgD+2);
0628    }
0629    if(num+15.>rdgD) break;
0630    FontInfo(11,0,2); /* center */
0631    ix=scl*(num+15.-ldgD)+lgD;
0632    MoveTo(ix,bgD+12);
0633    i=stepf;
0634    DrawString(month[i-1]);
0635    stepf++;
0636    if(stepf>12.1){
0637     stepf=1.;
0638     stepc++;
0639    }
0640   }
0641  }
0642  else if(delta>2.){ /* day */
0643   num=refday(mdy,0.);
0644   while(1){
0645    if(num>rdgD) break;
0646    stepf=mdyday(num);
0647    stepc=floor(stepf*100.);
0648    stepf=fmod(stepc,100.);
0649    i=1;
0650    if(scl<12.){
0651     if(fmod(num+0.001,7.)>1.) i=0;
0652    }
0653    if(num>ldgD){
0654     ix=scl*(num-ldgD)+lgD;
0655     MoveTo(ix,tgD);
0656     LineTo(ix,bgD+2*i);
0657    }
0658    if(i==1){
0659     if(num+0.5>rdgD) break;
0660     FontInfo(11,0,2); /* center */
0661     ix=scl*(num+0.5-ldgD)+lgD;
0662     MoveTo(ix,bgD+12);
0663     format(0,stepf,ar);
0664     DrawString(ar);
0665    }
0666    num++;
0667   }
0668  }
0669  else{ /* hour */
0670   stepc=floor(hms);
0671   num=refday(mdy,stepc);
0672   while(1){
0673    if(num>rdgD) break;
0674    if(num>ldgD){
0675     ix=scl*(num-ldgD)+lgD;
0676     MoveTo(ix,tgD);
0677     LineTo(ix,bgD+2);
0678    }
0679    if(num>rdgD) break;
0680    FontInfo(11,0,2); /* center */
0681    ix=scl*(num-ldgD)+lgD;
0682    MoveTo(ix,bgD+12);
0683    i=format(0,stepc,ar);
0684    DrawString(ar);
0685    stepc++;
0686    if(stepc>23.5) stepc=0;
0687    num+=0.041666666;
0688   }
0689  }
0690 }
0691 for(i=0;c[i]!='\0';i++);
0692 if(hlD) MoveTo((lgD+rgD-i*8)/2,bgD+33);
0693 else MoveTo((lgD+rgD-i*8)/2,bgD+22);
0694 FontInfo(16,0,0);
0695 DrawString(c);
0696}
0697
0698int VertScale(char *c,double bottom,double top)
0699{
0700 int i,j,iy,coly;
0701 double stepc,stepf,delta,intef,frac,num;
0702 char ar[12];
0703
0704 bdgD=bottom;
0705 tdgD=top;
0706 delta=top-bottom;
0707 frac=modf(log10(delta),&intef);
0708 stepc=pow(10.,intef-1);
0709 stepf=stepc;
0710 if(frac<0.2) stepf*=0.5;
0711 else if(frac<0.8) stepc*=5.;
0712 else{
0713  stepc*=10.;
0714  stepf*=5.;
0715 }
0716 MoveTo(lgD,tgD);
0717 LineTo(lgD,bgD);
0718
0719 frac=modf(log10(stepc),&intef);
0720// if(log10(stepc)<0.) coly=-intef+1.;
0721 if(log10(stepc)<0.) coly=-log10(stepc)+0.8;
0722 else coly=0;
0723 frac=modf(bottom/stepc,&intef);
0724 frac=intef;
0725 if(vlD){
0726  stepc=1.;
0727  coly=0;
0728 }
0729 j=0;
0730 while(1){
0731  num=frac*stepc;                        // y value for grid
0732  if(num>tdgD) break;
0733  iy=(tgD-bgD)*((num-bdgD)/(tdgD-bdgD))+bgD;
0734  i=format(coly,num,ar);
0735  if(i>j) j=i;
0736  MoveTo(lgD-2,iy);
0737  LineTo(rgD,iy);
0738  FontInfo(11,0,0);
0739  for(i=0;ar[i]!='\0';i++);
0740  if(vlD){
0741   MoveTo(lgD-i*6-3,iy-1);
0742   DrawString(ar);
0743   MoveTo(lgD-i*6-12,iy+6);
0744   DrawString("10");
0745  }
0746  else{
0747   MoveTo(lgD-i*6-3,iy+3);
0748   DrawString(ar);
0749  }
0750  frac++;
0751 }
0752 for(i=0;c[i]!='\0';i++);
0753 if(vlD) MoveTo(lgD-j*6-16,(bgD+tgD+i*8)/2);
0754 else MoveTo(lgD-j*6-8,(bgD+tgD+i*8)/2);
0755 FontInfo(16,1,0);
0756 DrawString(c);
0757}
0758
0759int MoveToG(double x,double y)
0760{
0761 int savel,saver,savet,saveb;
0762 int ix,iy;
0763 
0764 savel=cliplD;
0765 saver=cliprD;
0766 savet=cliptD;
0767 saveb=clipbD;
0768 cliplD=lgD;
0769 cliprD=rgD;
0770 cliptD=tgD;
0771 clipbD=bgD;
0772
0773 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0774 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
0775 MoveTo(ix,iy);
0776
0777 cliplD=savel;
0778 cliprD=saver;
0779 cliptD=savet;
0780 clipbD=saveb;
0781}
0782
0783int LineToG(double x,double y)
0784{
0785 int savel,saver,savet,saveb;
0786 int ix,iy;
0787 
0788 savel=cliplD;
0789 saver=cliprD;
0790 savet=cliptD;
0791 saveb=clipbD;
0792 cliplD=lgD;
0793 cliprD=rgD;
0794 cliptD=tgD;
0795 clipbD=bgD;
0796
0797 
0798 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0799 iy=(tgD-bgD)*((y-bdgD)/(tdgD-bdgD))+bgD;
0800 LineTo(ix,iy);
0801
0802 cliplD=savel;
0803 cliprD=saver;
0804 cliptD=savet;
0805 clipbD=saveb;
0806}
0807
0808int PlotG(int mark,double x,double y)
0809{
0810 int ix,iy;
0811
0812 ix=(rgD-lgD)*((x-ldgD)/(rdgD-ldgD))+lgD;
0813 iy=(tgD-bgD)*((x-bdgD)/(tdgD-bdgD))+bgD;
0814 MoveTo(ix-1,iy-1);
0815 LineTo(ix-1,iy+1);
0816 LineTo(ix+1,iy+1);
0817 LineTo(ix-1,iy+1);
0818 LineTo(ix,iy+1);
0819 LineTo(ix,iy);
0820}
0821 
0822
0823 
0824int GifOut()
0825{
0826  int i,j,k;
0827  unsigned char m;
0828  unsigned int step,red,green,blue;
0829
0830  int ctSize=256;
0831  int *prec;
0832  unsigned char *color;
0833  unsigned char pc[2000];
0834  int ipc,nn,n,nnstart,nstart;
0835  int bitsmin;
0836  int kstart;
0837  int clrcode;
0838
0839#ifdef CGI
0840  printf("Content-type: image/gif\n\n");
0841#else
0842  fpD=fopen("test.gif","wb");
0843#endif
0844
0845  prec=(int *)malloc(4097*sizeof(int));	// code up to 12 bits
0846  color=(unsigned char*)malloc(4097*sizeof(unsigned char));
0847  for(i=0;i<4097;i++) prec[i]=-1;
0848
0849#ifdef CGI
0850  printf("GIF89a");
0851#else
0852  fprintf(fpD,"GIF89a");
0853#endif
0854  
0855#ifdef CGI
0856  fwrite((char *)&widthD,sizeof(char),2,stdout);
0857  fwrite((char *)&heightD,sizeof(char),2,stdout);
0858#else
0859  fwrite((char *)&widthD,sizeof(char),2,fpD);
0860  fwrite((char *)&heightD,sizeof(char),2,fpD);
0861#endif
0862  sizeOfCTD=7; // class variable
0863  m=0xF0|sizeOfCTD;
0864#ifdef CGI
0865  fwrite(&m,sizeof(char),1,stdout);
0866#else
0867  fwrite(&m,sizeof(char),1,fpD);
0868#endif
0869  m=0; // Background Color Index
0870#ifdef CGI
0871  fwrite(&m,sizeof(char),1,stdout);
0872#else
0873  fwrite(&m,sizeof(char),1,fpD);
0874#endif
0875  m=0; // Pixel Aspect Ratio
0876#ifdef CGI
0877  fwrite(&m,sizeof(char),1,stdout);
0878#else
0879  fwrite(&m,sizeof(char),1,fpD);
0880#endif
0881  step=0xFFFF/5;
0882  for(i=5;i>=0;i--){
0883    red=i*step;
0884    for(j=5;j>=0;j--){
0885      green=j*step;
0886      for(k=5;k>=0;k--){
0887	blue=k*step;
0888	if(i!=0||j!=0||k!=0){
0889#ifdef CGI
0890          fwrite(&red,sizeof(char),1,stdout);
0891          fwrite(&green,sizeof(char),1,stdout);
0892          fwrite(&blue,sizeof(char),1,stdout);
0893#else
0894          fwrite(&red,sizeof(char),1,fpD);
0895          fwrite(&green,sizeof(char),1,fpD);
0896          fwrite(&blue,sizeof(char),1,fpD);
0897#endif
0898	}
0899      }
0900    }
0901  }
0902  step=0xFFFF/15;
0903  green=0;
0904  blue=0;
0905  for(i=14;i>0;i--){
0906    if(i%3!=0){
0907      red=i*step;
0908#ifdef CGI
0909          fwrite(&red,sizeof(char),1,stdout);
0910          fwrite(&green,sizeof(char),1,stdout);
0911          fwrite(&blue,sizeof(char),1,stdout);
0912#else
0913          fwrite(&red,sizeof(char),1,fpD);
0914          fwrite(&green,sizeof(char),1,fpD);
0915          fwrite(&blue,sizeof(char),1,fpD);
0916#endif
0917    }
0918  }
0919  red=0;
0920  blue=0;
0921  for(i=14;i>0;i--){
0922    if(i%3!=0){
0923      green=i*step;
0924#ifdef CGI
0925          fwrite(&red,sizeof(char),1,stdout);
0926          fwrite(&green,sizeof(char),1,stdout);
0927          fwrite(&blue,sizeof(char),1,stdout);
0928#else
0929          fwrite(&red,sizeof(char),1,fpD);
0930          fwrite(&green,sizeof(char),1,fpD);
0931          fwrite(&blue,sizeof(char),1,fpD);
0932#endif
0933    }
0934  }
0935  red=0;
0936  green=0;
0937  for(i=14;i>0;i--){
0938    if(i%3!=0){
0939      blue=i*step;
0940#ifdef CGI
0941          fwrite(&red,sizeof(char),1,stdout);
0942          fwrite(&green,sizeof(char),1,stdout);
0943          fwrite(&blue,sizeof(char),1,stdout);
0944#else
0945          fwrite(&red,sizeof(char),1,fpD);
0946          fwrite(&green,sizeof(char),1,fpD);
0947          fwrite(&blue,sizeof(char),1,fpD);
0948#endif
0949    }
0950  }
0951  for(i=14;i>0;i--){
0952    if(i%3!=0){
0953      red=green=blue=i*step;
0954#ifdef CGI
0955          fwrite(&red,sizeof(char),1,stdout);
0956          fwrite(&green,sizeof(char),1,stdout);
0957          fwrite(&blue,sizeof(char),1,stdout);
0958#else
0959          fwrite(&red,sizeof(char),1,fpD);
0960          fwrite(&green,sizeof(char),1,fpD);
0961          fwrite(&blue,sizeof(char),1,fpD);
0962#endif
0963    }
0964  }
0965  red=0;
0966  green=0;
0967  blue=0;
0968#ifdef CGI
0969          fwrite(&red,sizeof(char),1,stdout);
0970          fwrite(&green,sizeof(char),1,stdout);
0971          fwrite(&blue,sizeof(char),1,stdout);
0972#else
0973          fwrite(&red,sizeof(char),1,fpD);
0974          fwrite(&green,sizeof(char),1,fpD);
0975          fwrite(&blue,sizeof(char),1,fpD);
0976#endif
0977
0978  m=0x2c; // image separator
0979#ifdef CGI
0980  fwrite(&m,sizeof(char),1,stdout);
0981#else
0982  fwrite(&m,sizeof(char),1,fpD);
0983#endif
0984  
0985  i=0; // image left position
0986#ifdef CGI
0987  fwrite((char *)&i,sizeof(char),2,stdout);
0988#else
0989  fwrite((char *)&i,sizeof(char),2,fpD);
0990#endif
0991  i=0; // image top position
0992#ifdef CGI
0993  fwrite((char *)&i,sizeof(char),2,stdout);
0994  fwrite((char *)&widthD,sizeof(char),2,stdout);
0995  fwrite((char *)&heightD,sizeof(char),2,stdout);
0996#else
0997  fwrite((char *)&i,sizeof(char),2,fpD);
0998  fwrite((char *)&widthD,sizeof(char),2,fpD);
0999  fwrite((char *)&heightD,sizeof(char),2,fpD);
1000#endif
1001  m=0x00|sizeOfCTD;
1002#ifdef CGI
1003  fwrite(&m,sizeof(char),1,stdout);
1004#else
1005  fwrite(&m,sizeof(char),1,fpD);
1006#endif
1007
1008  m++; // LZW minimum code size 8
1009  if(m==1) m=2;
1010#ifdef CGI
1011  fwrite(&m,sizeof(char),1,stdout);
1012#else
1013  fwrite(&m,sizeof(char),1,fpD);
1014#endif
1015  clrcode=1<<m; // clear code 0x100
1016  bitsD=m+1; // output number of bits 9
1017  bitsmin=bitsD; // initial number of bits
1018  for(i=0;i<ctSize;i++) color[i]=i; // the first 256 of 4097 colors
1019  for(i=0;i<260;i++) outBufD[i]=0;
1020  bitPtrD=0; // initialize output buffer
1021  emit(clrcode);
1022  ipc=0; // index for already-seen-color-sequence pc[]
1023  nnstart=0; // initial index value for nn used for pc[]
1024  nstart=clrcode+2; // n is index for preceeding code, prec
1025  for(j=0;j<heightD;j++){
1026    for(i=0;i<widthD;i++){
1027      m=pD[widthD*j+i]; // CHARACTER
1028      pc[ipc++]=m; // STRING add to already-seen-sequence
1029      nn=nnstart; // index for pc[] used at comparing
1030      if(nn==0){ // first time and immediately after emit
1031	// for(k=0;k<ctSize;k++) if(color[k]==pc[nn]) break;
1032	k=pc[nn]; // equivalent to the above expression
1033	nn++;
1034      }
1035      else k=kstart; // code to be compared
1036     if(lzw){ // compress
1037      for(n=nstart;prec[n]!=-1;n++){ // matched upto and including nn-1 and n-1
1038	if(nn==ipc) break; // same as previously-seen-color-sequence
1039	if(prec[n]==k){
1040	  if(color[n]==pc[nn]){
1041	    nn++;
1042	    k=n;
1043	  }
1044	}
1045      }
1046      if(nn==ipc-1){ // if there is no previously-seen-color-sequence
1047	emit(k); // output code for hether-to matching sequence
1048	prec[n]=k; // add the code to dictionary
1049	color[n]=pc[ipc-1]; // add next-to-code-color in dictionary
1050	if(n>>bitsD) bitsD++;
1051	if(n==0xFFF){
1052	  emit(clrcode);
1053	  bitsD=bitsmin;
1054	  for(n=0;n<4097;n++) prec[n]=-1;
1055	}
1056	pc[0]=m; // lastly-read color comes first in color array
1057	ipc=1;
1058	nnstart=0; //position of color array to be compared
1059	nstart=clrcode+2; // position of dictionary to be compared
1060      }
1061      else{ // when there is a previous instance
1062	nnstart=nn; // position of color array to be compared
1063	nstart=n; // position of dictionary to be compared
1064	kstart=k; // code to be compared
1065      }
1066     }
1067     else{ // not compress
1068	emit(m); // output code for hether-to matching sequence
1069	emit(clrcode);
1070	pc[0]=m; // lastly-read color comes first in color array
1071	ipc=1;
1072	nnstart=0; //position of color array to be compared
1073     }
1074    }
1075  }
1076  if(ipc==1){
1077    for(k=0;k<ctSize;k++) if(color[k]==pc[0]) break;
1078  }
1079  if(lzw) emit(k);
1080  n++;
1081  if(n>>bitsD) bitsD++;
1082
1083  emit(clrcode);
1084  bitsD=bitsmin;
1085
1086  emit(clrcode+1);
1087  i=bitPtrD/8;
1088  if((bitPtrD%8)!=0) i++;
1089#ifdef CGI
1090  fwrite((char *)&i,sizeof(char),1,stdout);
1091  fwrite((char *)outBufD,sizeof(char),i,stdout);
1092#else
1093  fwrite((char *)&i,sizeof(char),1,fpD);
1094  fwrite((char *)outBufD,sizeof(char),i,fpD);
1095#endif
1096  m=0;
1097#ifdef CGI
1098  fwrite((char *)&m,sizeof(char),1,stdout);
1099#else
1100  fwrite((char *)&m,sizeof(char),1,fpD);
1101#endif
1102  m=0x3b;
1103#ifdef CGI
1104  fwrite((char *)&m,sizeof(char),1,stdout);
1105#else
1106  fwrite((char *)&m,sizeof(char),1,fpD);
1107  fclose(fpD);
1108#endif
1109
1110//  delete[] prec;
1111//  delete[] color;
1112
1113
1114}
1115
1116
1117void emit(int k)
1118{
1119  int i,j,m,n;
1120
1121  for(i=0;i<bitsD;i++){ // do for current number of bits
1122    m=bitPtrD/8; // put in n-th bit of m-th byte
1123    n=bitPtrD%8;
1124    j=k;
1125    j>>=i;
1126    j&=1;
1127    j<<=n;
1128    outBufD[m]|=j; // outBuf is char , j is int
1129    bitPtrD++;
1130  }
1131
1132  if(m>254){
1133    i=0xFF;
1134#ifdef CGI
1135  fwrite((char *)&i,sizeof(char),1,stdout);
1136  fwrite((char *)outBufD,sizeof(char),255,stdout);
1137#else
1138  fwrite((char *)&i,sizeof(char),1,fpD);
1139  fwrite((char *)outBufD,sizeof(char),255,fpD);
1140#endif
1141    bitPtrD-=255*8;
1142    outBufD[0]=outBufD[255];
1143    outBufD[1]=outBufD[256];
1144    for(i=2;i<257;i++) outBufD[i]=0;
1145  }
1146}
1147
1148int PngOut()
1149{
1150  unsigned char signa[]={137,80,78,71,13,10,26,10};
1151  unsigned char *chunk;
1152
1153  int i,j,k,l,m,n;
1154  int i1,j1,k1,l1,m1,n1;
1155  int i2,j2,k2,l2,m2,n2;
1156  unsigned int step,red,green,blue;
1157  int lmatch,dmatch;
1158  int wdopen;
1159  unsigned long adler=1L;
1160  unsigned long s1,s2;
1161
1162  i=widthD*heightD/10;
1163  chunk=(unsigned char *)calloc(i*sizeof(char),sizeof(char)); /* this size must be related to picture size */
1164#ifdef CGI
1165  printf("Content-type: image/png\n\n");
1166  fwrite((char *)signa,sizeof(char),8,stdout);
1167#else
1168  fpD=fopen("test.png","wb");
1169  fwrite((char *)signa,sizeof(char),8,fpD);
1170#endif
1171  *(int *)&chunk[0]=13; // excluding length, type or crc
1172  revPng(&chunk[0]);
1173  chunk[4]='I';
1174  chunk[5]='H';
1175  chunk[6]='D';
1176  chunk[7]='R';
1177  *(int *)&chunk[8]=widthD;
1178  revPng(&chunk[8]);
1179  *(int *)&chunk[12]=heightD;
1180  revPng(&chunk[12]);
1181  chunk[16]=8; /* bit depth */
1182  chunk[17]=3; /* color type - palette index */
1183  chunk[18]=0; /* compression method - deflate */
1184  chunk[19]=0; /* filter method */
1185  chunk[20]=0; /* interlace method */
1186  crcPng(&chunk[4],17); // including chunk type and chunk data
1187#ifdef CGI
1188  fwrite((char *)chunk,sizeof(char),25,stdout);
1189#else
1190  fwrite((char *)chunk,sizeof(char),25,fpD);
1191#endif
1192  *(int *)&chunk[0]=768; // 256*3
1193  revPng(&chunk[0]);
1194  chunk[4]='P';
1195  chunk[5]='L';
1196  chunk[6]='T';
1197  chunk[7]='E';
1198  l=8;
1199  step=0xFFFF/5;
1200  for(i=5;i>=0;i--){
1201    red=i*step;
1202    for(j=5;j>=0;j--){
1203      green=j*step;
1204      for(k=5;k>=0;k--){
1205	blue=k*step;
1206	if(i!=0||j!=0||k!=0){
1207          chunk[l++]=red;
1208          chunk[l++]=green;
1209          chunk[l++]=blue;
1210	}
1211      }
1212    }
1213  }
1214  step=0xFFFF/15;
1215  green=0;
1216  blue=0;
1217  for(i=14;i>0;i--){
1218    if(i%3!=0){
1219      red=i*step;
1220      chunk[l++]=red;
1221      chunk[l++]=green;
1222      chunk[l++]=blue;
1223    }
1224  }
1225  red=0;
1226  blue=0;
1227  for(i=14;i>0;i--){
1228    if(i%3!=0){
1229      green=i*step;
1230      chunk[l++]=red;
1231      chunk[l++]=green;
1232      chunk[l++]=blue;
1233    }
1234  }
1235  red=0;
1236  green=0;
1237  for(i=14;i>0;i--){
1238    if(i%3!=0){
1239      blue=i*step;
1240      chunk[l++]=red;
1241      chunk[l++]=green;
1242      chunk[l++]=blue;
1243    }
1244  }
1245  for(i=14;i>0;i--){
1246    if(i%3!=0){
1247      red=green=blue=i*step;
1248      chunk[l++]=red;
1249      chunk[l++]=green;
1250      chunk[l++]=blue;
1251    }
1252  }
1253  red=0;
1254  green=0;
1255  blue=0;
1256  chunk[l++]=red;
1257  chunk[l++]=green;
1258  chunk[l++]=blue;
1259  crcPng(&chunk[4],768+4);
1260#ifdef CGI
1261  fwrite((char *)chunk,sizeof(char),780,stdout);
1262#else
1263  fwrite((char *)chunk,sizeof(char),780,fpD);
1264#endif
1265  for(l=0;l<780;l++) chunk[l]=0;
1266/** LZ77 conpression **/
1267  chunk[4]='I';
1268  chunk[5]='D';
1269  chunk[6]='A';
1270  chunk[7]='T';
1271  chunk[8]=0x78; /* compression methodflag code */
1272  chunk[9]=0x9c; /* additional flagscheck bits */
1273  i1=10; // initial code byte
1274  j1=0; // initial bit position
1275  setPng(chunk,i1,j1,3,3,&i1,&j1); // three header bit for the block
1276                                   // final & fixed Huffman code
1277  l=heightD*widthD; /* insert filter type byte */
1278  for(n=heightD-1;n>=0;n--){
1279   k=n*(widthD+1);
1280   for(m=widthD;m>0;m--) pD[k+m]=pD[--l];
1281   pD[k]=0;
1282  }
1283  wdopen=0;
1284  l=heightD*(widthD+1);
1285  for(n=0;n<l;n++){
1286   lmatch=0;
1287   if(n<32768) wdopen=0;
1288   else wdopen=n-32768;
1289   for(m=n-1;m>=wdopen;m--){
1290    j=n;
1291    k=m;
1292    i=0;
1293    while(pD[j++]==pD[k++]){
1294     i++;
1295     if(i==258) break;
1296     if(j>=l) break;
1297    }
1298    if(i>lmatch){
1299     lmatch=i; /* length */
1300     dmatch=n-m; /* distance */
1301    }
1302    if(lmatch==258||j>=l) break;
1303   }
1304   l1=0; // number of extra bits
1305   m1=0; // value of extra bits
1306   if(lmatch<3) k1=pD[n];  // raw data
1307   else{
1308    if(lmatch<11) k1=254+lmatch;
1309    else if(lmatch<19){
1310     l1=1;
1311     k1=(lmatch-11)/2+265;
1312     m1=(lmatch-11)%2;
1313    }
1314    else if(lmatch<35){
1315     l1=2;
1316     k1=(lmatch-19)/4+269;
1317     m1=(lmatch-19)%4;
1318    }
1319    else if(lmatch<67){
1320     l1=3;
1321     k1=(lmatch-35)/8+273;
1322     m1=(lmatch-35)%8;
1323    }
1324    else if(lmatch<131){
1325     l1=4;
1326     k1=(lmatch-67)/16+277;
1327     m1=(lmatch-67)%16;
1328    }
1329    else if(lmatch<258){
1330     l1=5;
1331     k1=(lmatch-131)/32+281;
1332     m1=(lmatch-131)%32;
1333    }
1334    else k1=285;
1335   } /* else */
1336/* convert alphabet k1 to Huffman code */
1337   if(k1<144){
1338    n1=0x30+k1; // Huffman code
1339    i2=0x80; // mask for output
1340   }
1341   else if(k1<256){
1342    n1=0x190+k1-144;
1343    i2=0x100;
1344   }
1345   else if(k1<280){
1346    n1=0x0+k1-256;
1347    i2=0x40;
1348   }
1349   else{
1350    n1=0xc0+k1-280;
1351    i2=0x80;
1352   }
1353   for(;i2>0;i2/=2){
1354    if(n1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1355    else setPng(chunk,i1,j1,0,1,&i1,&j1);
1356   }
1357   if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for length */
1358   if(k1>256){ /* distance in dmatch */
1359    m2=1;
1360    for(l2=1;;l2++){
1361     m2*=2;
1362     if(m2>=dmatch) break;
1363    }
1364    k1=l2*2-1; // code 
1365               //     dmatch<= k1 l2 extra-bits
1366               //        2      1   1    0
1367               //        4      3   2    0
1368               //        8      5   3    1
1369               //       16      7   4    2
1370               //       32      9   5    3
1371    l1=l2-2;   // number of extra bits
1372    if(l1<0) l1=0;
1373               // m2       2   2   4   4   8   8   8   8  16  16  16
1374               // dmatch   1   2   3   4   5   6   7   8   9  10  11
1375               // l2       1   1   2   2   3   3   3   3   4   4   4
1376               // k1       1   1   3   3   5   5   5   5   7   7   7
1377               // l1       0   0   0   0   1   1   1   1   2   2   2 ->number of extra bits
1378               // n2       1   1   1   1   2   2   2   2   4   4   4
1379               // m2-n2    1   1   3   3   6   6   6   6  12  12  12
1380               // k1       0  (1)  2  (3)  4   4  (5) (5)  6   6   6 ->code
1381               // m2       1   2   3   4   6   6   8   8  12  12  12
1382               // m2-n2    0   1   2   3   4   4   6   6   8   8   8
1383               // m1       1   1   1   1   1   2   1   2   1   2   3
1384               // m1       0   0   0   0   0   1   0   1   0   1   2 ->extra bit value
1385    n2=pow(2,l1);
1386    if(dmatch<=m2-n2){
1387     k1--;
1388     m2=m2-n2;
1389    }
1390    m1=dmatch-(m2-n2);
1391    m1--;    // value of extra bits
1392
1393    i2=0x10; // 5 bits
1394    for(;i2>0;i2/=2){
1395     if(k1&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1396     else setPng(chunk,i1,j1,0,1,&i1,&j1);
1397    }
1398    if(l1>0) setPng(chunk,i1,j1,m1,l1,&i1,&j1); /* extra bits for distance */
1399    n+=lmatch-1; /* advance main loop counter - 1 incremented later */
1400   } /* if(k1>256) */
1401  } /* for(n=0;n<l;n++){ */
1402  i2=0x40; // 7 bits - end of block mark
1403  for(;i2>0;i2/=2){ // huffman code for 256 is 0
1404   if(0&i2) setPng(chunk,i1,j1,1,1,&i1,&j1);
1405   else setPng(chunk,i1,j1,0,1,&i1,&j1);
1406  }
1407/* Adler-32 : a check sum value of the uncompressed data */
1408  s1=adler&0xffff;
1409  s2=(adler>>16)&0xffff;
1410  for(n=0;n<l;n++){
1411   s1=(s1+pD[n])%65521;
1412   s2=(s2+s1)%65521;
1413  }
1414  if(j1!=0) i1++;
1415  *(unsigned long *)&chunk[i1]=(s2<<16)+s1;
1416  revPng(&chunk[i1]);
1417  i1+=4;  /* pointer index to crc */
1418  *(int *)&chunk[0]=i1-8; /* data length */
1419  revPng(&chunk[0]);
1420  crcPng(&chunk[4],i1-4);
1421  i1+=4; /* number of bytes including crc */
1422#ifdef CGI
1423  fwrite((char *)chunk,sizeof(char),i1,stdout);
1424#else
1425  fwrite((char *)chunk,sizeof(char),i1,fpD);
1426#endif
1427  *(int *)&chunk[0]=0; /* data length */
1428  revPng(&chunk[0]);
1429  chunk[4]='I';
1430  chunk[5]='E';
1431  chunk[6]='N';
1432  chunk[7]='D';
1433  crcPng(&chunk[4],4);
1434
1435#ifdef CGI
1436  fwrite((char *)chunk,sizeof(char),12,stdout);
1437#else
1438  fwrite((char *)chunk,sizeof(char),12,fpD);
1439  fclose(fpD);
1440#endif
1441
1442}
1443
1444void revPng(unsigned char *c)
1445{
1446 unsigned char a;
1447 a=c[0];
1448 c[0]=c[3];
1449 c[3]=a;
1450 a=c[1];
1451 c[1]=c[2];
1452 c[2]=a;
1453}
1454
1455/*********************************************
1456  Pad data into chunk
1457  chunk : chunk array
1458  byte : index into chunk array
1459  bit : bit position (0(lsb)-7(msb))
1460  val : data to be set
1461  nbit : number of bits of val
1462  *nxtbyte : next index to be returned
1463  *nxtbit : next bit position to be returned
1464********************************************/
1465void setPng(unsigned char *chunk,int byte,int bit,
1466        int val,int nbit,int *nxtbyte,int *nxtbit)
1467{
1468 unsigned char c1,c2;
1469 unsigned char cin[4];
1470 unsigned char mask,mask1;
1471 int sourcebyte,destbyte,sourcebit,destbit;
1472 int i;
1473
1474 sourcebyte=0;
1475 sourcebit=0;
1476 destbyte=byte;
1477 destbit=bit;
1478 *(unsigned long*)cin=val;
1479 for(i=0;i<nbit;i++){
1480  mask=1;
1481  mask<<=sourcebit;
1482  c1=cin[sourcebyte];
1483  if(c1&mask){
1484   mask=1;
1485   mask<<=destbit;
1486   chunk[destbyte]|=mask;
1487  }
1488  sourcebit++;
1489  if(sourcebit==8){
1490   sourcebyte++;
1491   sourcebit=0;
1492  }
1493  destbit++;
1494  if(destbit==8){
1495   destbyte++;
1496   destbit=0;
1497  }
1498 }
1499 *nxtbyte=destbyte;
1500 *nxtbit=destbit;
1501}
1502
1503
1504/**********************************************
1505  CRC - ported from W3C specification
1506  Return the CRC of the bytes buf[0]..[len-1]
1507  in buf[len]..[len+3] 
1508**********************************************/
1509void crcPng(unsigned char *buf,int len)
1510{
1511 unsigned long c;
1512 int n,k;
1513
1514 if(!crc_table_computed){
1515  for(n=0;n<256;n++){
1516   c=(unsigned long)n;
1517   for(k=0;k<8;k++){
1518    if(c&1) c=0xedb88320L^(c>>1);
1519    else c=c>>1;
1520   }
1521   crc_table[n]=c;
1522  }
1523  crc_table_computed=1;
1524 }
1525 c=0xffffffffL;
1526 for(n=0;n<len;n++){
1527  c=crc_table[(c^buf[n])&0xff]^(c>>8);
1528 }
1529 *(int *)&buf[len]=c^0xffffffffL;
1530 revPng(&buf[len]);
1531}
1532