Diff for /loncom/cgi/mimeTeX/gfuntype.c between versions 1.1 and 1.2

version 1.1, 2005/02/28 19:08:11 version 1.2, 2006/03/24 23:08:33
Line 17 Line 17
  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  * --------------------------------------------------------------------------   * --------------------------------------------------------------------------
  *   *
  * Program: gfuntype  [-n fontname]  [-m msglevel]  [infile [outfile]]   * Program: gfuntype  [-g gformat]  [-u isnoname] [-m msglevel]
    * [-n fontname]  [infile [outfile]]
  *   *
  * Purpose: Parses output from  gftype -i   * Purpose: Parses output from  gftype -i
  * and writes pixel bitmap data of the characters   * and writes pixel bitmap data of the characters
Line 31 Line 32
  * (defaults to stdin if no filenames given)   * (defaults to stdin if no filenames given)
  * outfile name of output file   * outfile name of output file
  * (defaults to stdout if <2 filenames given)   * (defaults to stdout if <2 filenames given)
    * -g gformat gformat=1(default) for bitmap representation,
    * or 2,3 for 8-bit,4-bit .gf-like compression,
    * or 0 to choose smallest format.
    * Add 10 (gformat=10,12,13,14) to embed scan
    * line repeat counts in format.
    * -u isnoname isnoname=1(default) to output symbols not
    * defined/named in mimetex.h, or 0 to omit them
  * -m msglevel verbose if msglevel>=9 (vv if >=99)   * -m msglevel verbose if msglevel>=9 (vv if >=99)
  * -n fontname string used for fontname   * -n fontname string used for fontname
  * (defaults to noname)   * (defaults to noname)
Line 46 Line 54
  * --------------------------------------------------------------------------   * --------------------------------------------------------------------------
  * Revision History:   * Revision History:
  * 09/22/02 J.Forkosh Installation.   * 09/22/02 J.Forkosh Installation.
    * 10/11/05 J.Forkosh .gf-style format options added.
  *   *
  ****************************************************************************/   ****************************************************************************/
   
Line 62  standard headers, program parameters, gl Line 71  standard headers, program parameters, gl
 #include "mimetex.h"  #include "mimetex.h"
 /* --- parameters either -D defined on cc line, or defaulted here --- */  /* --- parameters either -D defined on cc line, or defaulted here --- */
 #ifndef MSGLEVEL  #ifndef MSGLEVEL
 #define MSGLEVEL 0    #define MSGLEVEL 0
   #endif
   #ifndef GFORMAT
     #define GFORMAT 1
   #endif
   #ifndef ISREPEAT
     #define ISREPEAT 1
 #endif  #endif
 /* --- message level (verbose test) --- */  /* --- message level (verbose test) --- */
 static int msglevel = MSGLEVEL; /* verbose if msglevel >= 9 */  static int msglevel = MSGLEVEL; /* verbose if msglevel >= 9 */
 static FILE *msgfp; /* verbose output goes here */  static FILE *msgfp; /* verbose output goes here */
   /* --- output file format --- */
   static int isnoname = 1; /* true to output unnamed symbols */
   static char *noname = "(noname)"; /* char name used if lookup fails */
   static int gformat = GFORMAT; /* 1=bitmap, 2=.gf-like */
   static int isrepeat = ISREPEAT; /* true to store line repeat counts*/
   /* extern int imageformat; */ /* as per gformat, 1=bitmap,2=.gf */
 /* --- miscellaneous other data --- */  /* --- miscellaneous other data --- */
 #define CORNER_STUB ".<--" /* start of upper,lower-left line */  #define CORNER_STUB ".<--" /* start of upper,lower-left line */
   #define BLANKCHAR_STUB "character is entirely blank" /* signals blank char */
 #define TYPECAST    "(pixbyte *)" /* typecast for pixmap string */  #define TYPECAST    "(pixbyte *)" /* typecast for pixmap string */
   
 /* ==========================================================================  /* ==========================================================================
Line 120  while ( argc > ++argnum ) /* check for f Line 142  while ( argc > ++argnum ) /* check for f
  /* --- no usage for clueless users yet --- */   /* --- no usage for clueless users yet --- */
  default:  exit(iserror); /* exit quietly for unrecognized input */   default:  exit(iserror); /* exit quietly for unrecognized input */
  /* --- adjustable program parameters (not checking input) --- */   /* --- adjustable program parameters (not checking input) --- */
  case 'm': msglevel   = atoi(argv[argnum]); break;   case 'g': gformat  = atoi(argv[argnum]);
     isrepeat = (gformat>=10?1:0);
     gformat  = gformat%10;         break;
    case 'u': isnoname = atoi(argv[argnum]); break;
    case 'm': msglevel = atoi(argv[argnum]); break;
  case 'n': strcpy(fontname,argv[argnum]); break;   case 'n': strcpy(fontname,argv[argnum]); break;
  } /* --- end-of-switch() --- */   } /* --- end-of-switch() --- */
       } /* --- end-of-if(*argv[]=='-') --- */        } /* --- end-of-if(*argv[]=='-') --- */
Line 136  msgfp = (outarg>0? stdout : stderr); /* Line 162  msgfp = (outarg>0? stdout : stderr); /*
 fprintf(msgfp,"%s\n",copyright); /* display copyright, gnu/gpl info */  fprintf(msgfp,"%s\n",copyright); /* display copyright, gnu/gpl info */
 /* --- display input args if verbose output --- */  /* --- display input args if verbose output --- */
 if ( msglevel >= 9 ) /* verbose output requested */  if ( msglevel >= 9 ) /* verbose output requested */
   fprintf(msgfp,"gfuntype> infile=%s, outfile=%s, fontname=%s\n",    fprintf(msgfp,"gfuntype> infile=%s outfile=%s, fontname=%s format=%d.%d\n",
   (inarg>0?argv[inarg]:"stdin"), (outarg>0?argv[outarg]:"stdout"), fontname);    (inarg>0?argv[inarg]:"stdin"), (outarg>0?argv[outarg]:"stdout"),
     fontname, gformat,isrepeat);
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 initialization  initialization
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
Line 149  if ( inarg > 0 )  /* input from file, no Line 176  if ( inarg > 0 )  /* input from file, no
   if ( (infp = fopen(argv[inarg],"r")) == NULL ) /*try to open input file*/    if ( (infp = fopen(argv[inarg],"r")) == NULL ) /*try to open input file*/
     { fprintf(msgfp,"gfuntype> can't open %s for read\n",argv[inarg]);      { fprintf(msgfp,"gfuntype> can't open %s for read\n",argv[inarg]);
       goto end_of_job; } /* report error and quit */        goto end_of_job; } /* report error and quit */
   /* --- set format for mimetex.c functions --- */
   if ( gformat<0 || gformat>3 ) gformat=1; /* sanity check */
   /* if ( gformat == 1 ) imageformat = 1; */ /* force bitmap format */
   /* else gformat = imageformat = 2; */ /* or force .gf format */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 process input file  process input file
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
Line 180  fprintf(outfp,"/%c --- fontdef for %s -- Line 211  fprintf(outfp,"/%c --- fontdef for %s --
 fprintf(outfp,"static\tchardef %c%s[] =\n   {\n", ' ',fontname);  fprintf(outfp,"static\tchardef %c%s[] =\n   {\n", ' ',fontname);
 /* --- write characters comprising font --- */  /* --- write characters comprising font --- */
 for ( charnum=0; charnum<256; charnum++ ) /*for each possible char in font*/  for ( charnum=0; charnum<256; charnum++ ) /*for each possible char in font*/
   if ( fontdef[charnum] != (chardef *)NULL ) /*check if char exists in font*/   if ( fontdef[charnum] != (chardef *)NULL ) /*check if char exists in font*/
     { if ( ++nchars > 1 ) /* bump count */    { char *charname = getcharname(fontname,charnum);
  fprintf(outfp,",\n"); /* and terminate preceding chardef */      if ( charname!=NULL || isnoname ) { /* char defined or want undefined */
       fprintf(outfp,"      /%c --- pixel bitmap for %s char#%d %s --- %c/\n",       if ( ++nchars > 1 ) /* bump count */
  '*',fontname,charnum,getcharname(fontname,charnum),'*');        fprintf(outfp,",\n"); /* and terminate preceding chardef */
       cstruct_chardef(fontdef[charnum],outfp,6); } /*emit chardef as struct*/       fprintf(outfp,"      /%c --- pixel bitmap for %s char#%d %s --- %c/\n",
   else        '*',fontname,charnum,(charname==NULL?noname:charname),'*');
       if(0)fprintf(outfp,"NULL"); /* no character in this position */       cstruct_chardef(fontdef[charnum],outfp,6); } /*emit chardef struct*/
       else
        if(0)fprintf(outfp,"NULL"); /* no character in this position */
     } /* --- end-of-if(fontdef[]!=NULL) --- */
    else
     if(0)fprintf(outfp,"NULL"); /* no character in this position */
 /* --- write trailer chardef and closing brace --- */  /* --- write trailer chardef and closing brace --- */
 fprintf(outfp,",\n"); /* finish up last map from loop */  fprintf(outfp,",\n"); /* finish up last map from loop */
 fprintf(outfp,"      /%c --- trailer  --- %c/\n",'*','*'); /* trailer... */  fprintf(outfp,"      /%c --- trailer  --- %c/\n",'*','*'); /* trailer... */
 fprintf(outfp,"      { -99, -999,  0,0,0,0, { 0,0,0, %s\"\\0\" }  }\n",  fprintf(outfp,"      { -99, -999,  0,0,0,0, { 0,0,0,0, %s\"\\0\" }  }\n",
      TYPECAST);       TYPECAST);
 fprintf(outfp,"   } ;\n"); /* terminating }; for fontdef */  fprintf(outfp,"   } ;\n"); /* terminating }; for fontdef */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
Line 230  chardef *new_chardef(), *nextchar=(chard Line 266  chardef *new_chardef(), *nextchar=(chard
 int delete_chardef(); /* free allocated memory if error */  int delete_chardef(); /* free allocated memory if error */
 int findnextchar(), charnum,location; /* get header line for next char */  int findnextchar(), charnum,location; /* get header line for next char */
 int rasterizechar(); /* ascii image --> raster pixmap */  int rasterizechar(); /* ascii image --> raster pixmap */
 int parsecorner(); /* get col,row from ".<--" line */  int parsestat=(-999), parsecorner(); /* get col,row from ".<--" line */
 char *readaline(); /* read next line from fp */  char *readaline(); /* read next line from fp */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 initialization  initialization
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 /* --- find and interpret header line for next character --- */  while ( parsestat == (-999) ) { /* flush entirely blank characters */
 charnum = findnextchar(fp,&location); /* read and parse header line */    /* --- find and interpret header line for next character --- */
 if ( charnum < 0 ) goto error; /* eof or error, no more chars */    charnum = findnextchar(fp,&location); /* read and parse header line */
 /* --- allocate a new chardef struct and begin populating it --- */    if ( charnum < 0 ) goto error; /* eof or error, no more chars */
 if ( (nextchar=new_chardef()) /* allocate a new chardef */    /* --- allocate a new chardef struct and begin populating it --- */
 ==   (chardef *)NULL ) goto error; /* and quit if we failed */    if ( nextchar == (chardef *)NULL ) /* haven't allocated chardef yet */
 nextchar->charnum = charnum; /* store charnum in struct */      if ( (nextchar=new_chardef()) /* allocate a new chardef */
 nextchar->location = location; /* and location */      ==   (chardef *)NULL ) goto error; /* and quit if we failed */
 /* --- get upper-left corner line --- */    nextchar->charnum = charnum; /* store charnum in struct */
 if ( !parsecorner(readaline(fp), /* parse corner line */    nextchar->location = location; /* and location */
 &(nextchar->toprow),&(nextchar->topleftcol)) ) /* row and col from line */    /* --- get upper-left corner line --- */
   goto error; /* and quit if failed */    parsestat = parsecorner(readaline(fp), /* parse corner line */
       &(nextchar->toprow),&(nextchar->topleftcol)); /* row and col from line */
     } /* --- end-of-while(parsestat)  --- */
   if ( !parsestat ) goto error; /* quit if parsecorner() failed */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 interpret character image (and parse terminating corner line)  interpret character image (and parse terminating corner line)
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
Line 276  end_of_job: Line 315  end_of_job:
  * and returns the corresponding charname.   * and returns the corresponding charname.
  * --------------------------------------------------------------------------   * --------------------------------------------------------------------------
  * Arguments: fontname (I) char * containing fontname for font family   * Arguments: fontname (I) char * containing fontname for font family
    * (from -n switch on command line)
  * charnum (I) int containing the character number   * charnum (I) int containing the character number
  * whose corresponding name is wanted.   * whose corresponding name is wanted.
  * Returns: ( char * ) ptr to character name   * Returns: ( char * ) ptr to character name
Line 290  char *getcharname ( char *fontname, int Line 330  char *getcharname ( char *fontname, int
 Allocations and Declarations  Allocations and Declarations
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 /* --- recognized font family names and our corresponding numbers --- */  /* --- recognized font family names and our corresponding numbers --- */
 static char *fnames[] = { "cmr","cmmi","cmsy","cmex",NULL };  static char *fnames[] = /*font name from -n switch on command line*/
 static int    fnums[] = { CMR10,CMMI10,CMSY10,CMEX10,  -1 };   { "cmr","cmmib","cmmi","cmsy","cmex","bbold","rsfs","stmary", NULL };
 static char *noname = "(noname)";  /* char name returned if lookup fails */  static int    fnums[] = /* corresponding mimetex fontfamily number*/
    { CMR10,CMMIB10,CMMI10,CMSY10,CMEX10,BBOLD10,RSFS10,STMARY10,  -1 };
   static int    offsets[] = /* symtable[ichar].charnum = charnum-offset*/
    {     0,      0,     0,     0,     0,      0,    65,       0,  -1 };
 /* --- other local declarations --- */  /* --- other local declarations --- */
 char *charname = noname; /* character name returned to caller */  char *charname = NULL; /* character name returned to caller */
 char flower[99] = "noname"; /* lowercase caller's fontname */  char flower[99] = "noname"; /* lowercase caller's fontname */
 int ifamily = 0, /* fnames[] (and fnums[]) index */  int ifamily = 0, /* fnames[] (and fnums[],offsets[]) index */
  ichar = 0;   offset = 0, /* offsets[ifamily] */
    ichar = 0; /* loop index */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 lowercase caller's fontname and look it up in fnames[]  lowercase caller's fontname and look it up in fnames[]
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
Line 310  if ( strlen(flower) < 2 ) goto end_of_jo Line 354  if ( strlen(flower) < 2 ) goto end_of_jo
 for ( ifamily=0; ;ifamily++ ) /* check fnames[] for flower */  for ( ifamily=0; ;ifamily++ ) /* check fnames[] for flower */
   if ( fnames[ifamily] == NULL ) goto end_of_job; /* quit at end-of-table */    if ( fnames[ifamily] == NULL ) goto end_of_job; /* quit at end-of-table */
   else if ( strstr(flower,fnames[ifamily]) != NULL ) break; /* found it */    else if ( strstr(flower,fnames[ifamily]) != NULL ) break; /* found it */
   offset = offsets[ifamily]; /* symtable[ichar].charnum = charnum-offset*/
 ifamily = fnums[ifamily]; /* xlate index to font family number */  ifamily = fnums[ifamily]; /* xlate index to font family number */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 now look up name for caller's charnum in ifamily, and return it to caller  now look up name for caller's charnum in ifamily, and return it to caller
Line 320  for ( ichar=0; ;ichar++ ) /*search symta Line 365  for ( ichar=0; ;ichar++ ) /*search symta
   else    else
     if ( symtable[ichar].family == ifamily /* found desired family */      if ( symtable[ichar].family == ifamily /* found desired family */
     &&   symtable[ichar].handler == NULL ) /* and char isn't a "dummy" */      &&   symtable[ichar].handler == NULL ) /* and char isn't a "dummy" */
       if ( symtable[ichar].charnum == charnum ) break; /* found charnum */        if ( symtable[ichar].charnum == charnum-offset ) break; /*got charnum*/
 /* --- return corresponding charname to caller --- */  /* --- return corresponding charname to caller --- */
 charname = symtable[ichar].symbol; /* pointer to symbol name in table */  charname = symtable[ichar].symbol; /* pointer to symbol name in table */
 end_of_job:  end_of_job:
     if ( charname==NULL && isnoname ) /* want unnamed/undefined chars */
       charname = noname; /* so replace null return with noname */
   return ( charname );    return ( charname );
 } /* --- end-of-function getcharname() --- */  } /* --- end-of-function getcharname() --- */
   
Line 406  int rasterizechar ( FILE *fp, raster *im Line 453  int rasterizechar ( FILE *fp, raster *im
 Allocations and Declarations  Allocations and Declarations
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 char *readaline(), *line; /* read next scan line for char from fp */  char *readaline(), *line; /* read next scan line for char from fp */
 unsigned char bitvec[512][64]; /* scan lines parsed (up to 512x512 bits) */  unsigned char bitvec[1024][128]; /* scan lines parsed up to 1024x1024 bits */
   int bitcmp(); /* compare bit strings */
 int height = 0, /* #scan lines in fp comprising char */  int height = 0, /* #scan lines in fp comprising char */
  width = 0, /* #chars on longest scan line */   width = 0; /* #chars on longest scan line */
  pixsz = 1; /* default #bits per pixel, 1=bitmap */  int iscan, /* bitvec[] index */
 int iscan, ipixel=0, /* bitvec[] index, raster pixel map index */  
  ibit; /* bit along scan (i.e., 0...width-1) */   ibit; /* bit along scan (i.e., 0...width-1) */
 int isokay = 0; /* returned status, init for failure */  int isokay = 0; /* returned status, init for failure */
   /* --- bitmap and .gf-formatted image info (we'll choose smallest) --- */
   int iformat = gformat; /*0=best, 1=bitmap, 2=8-bit.gf, 3=4-bit.gf*/
   unsigned char gfpixcount[2][65536]; /* .gf black/white flips (max=64K) */
   int npixcounts[2] = {9999999,9999999}; /* #counts for 8-bit,4-bit .gf */
   int nbytes1=9999999,nbytes2=9999999,nbytes3=9999999;/*#bytes for format*/
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 read lines till ".<--" terminator, and construct one vector[] int per line  read lines till ".<--" terminator, and construct one vector[] int per line
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
   memset(bitvec,0,128*1024); /* zero-fill bitvec[] */
 while ( (line=readaline(fp)) != NULL ) /* read lines until eof */  while ( (line=readaline(fp)) != NULL ) /* read lines until eof */
   {    {
   /* --- allocations and declarations --- */    /* --- allocations and declarations --- */
Line 424  while ( (line=readaline(fp)) != NULL ) / Line 477  while ( (line=readaline(fp)) != NULL ) /
   if ( memcmp(line,CORNER_STUB,strlen(CORNER_STUB)) == 0 ) /* corner line */    if ( memcmp(line,CORNER_STUB,strlen(CORNER_STUB)) == 0 ) /* corner line */
     break; /* so done with loop */      break; /* so done with loop */
   /* --- parse line (encode asterisks comprising character image) --- */    /* --- parse line (encode asterisks comprising character image) --- */
   memset(bitvec[height],0,64); /* first zero out all bits */    memset(bitvec[height],0,128); /* first zero out all bits */
   for ( icol=0; icol<ncols; icol++ ) /* now check line[] for asterisks */    for ( icol=0; icol<ncols; icol++ ) /* now check line[] for asterisks */
     if ( line[icol] == '*' ) /* we want to set this bit */      if ( line[icol] == '*' ) /* we want to set this bit */
       { setlongbit(bitvec[height],icol); /* set bit */        { setlongbit(bitvec[height],icol); /* set bit */
Line 434  while ( (line=readaline(fp)) != NULL ) / Line 487  while ( (line=readaline(fp)) != NULL ) /
 if ( height<1 || width<1 ) /* some problem parsing character */  if ( height<1 || width<1 ) /* some problem parsing character */
   goto end_of_job; /* so quit */    goto end_of_job; /* so quit */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 allocate image raster pixmap for character  init image values
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 if ( image->pixmap != NULL ) /* hmm, somebody already allocated memory */  if ( image->pixmap != NULL ) /* hmm, somebody already allocated memory */
   free((void *)image->pixmap); /* just free it */    free((void *)image->pixmap); /* so just free it */
 image->width = width; /* set image width within raster struct */  image->width = width; /* set image width within raster struct */
 image->height = height; /* and height */  image->height = height; /* and height */
 image->pixsz = pixsz; /* #bits per pixel, 1=bitmap or 8=bytemap */  image->format = gformat; /* set format (will be reset below) */
 if ( (image->pixmap = (unsigned char *)malloc(pixmapsz(image)))  image->pixsz = 1; /* #bits per pixel (or #counts in .gf fmt) */
 == NULL ) goto end_of_job; /* quit if failed to allocate pixmap */  if ( gformat==0 || gformat==1 ) /* bitmap representation allowed */
     { nbytes1 = pixmapsz(image); /* #bytes needed for bitmap */
       iformat = 1; } /* default to bitmap format */
   /* --------------------------------------------------------------------------
   perform .gf-like compression on image in bitvec
   -------------------------------------------------------------------------- */
   if ( gformat == 0 /* choose optimal/smallest respresentation */
   ||   gformat==2 || gformat==3 ) /* .gf-like compressed representation */
    {
    /* --- try both 8-bits/count and 4-bits/count for best compression --- */
    int maxbitcount[2] = {254,14}; /* don't count too much in one byte */
    int repeatcmds[2]  = {255,15}; /* opcode for repeat/duplicate count */
    int minbytes = 0; /* #bytes needed for smallest format */
    for ( iformat=2; iformat<=3; iformat++ ) { /* 2=8-bit packing, 3=4-bit */
     int gfbitcount = 0, /* count of consecutive gfbitval's */
    gfbitval = 0, /* begin with count of leading 0's */
    pixcount = 0; /* #packed bytes (#black/white flips) */
     unsigned char *gfcount = gfpixcount[iformat-2]; /*counts for this format*/
     if ( gformat!=0 && gformat!=iformat ) /* this format not allowed */
       continue; /* so just skip it */
     for ( iscan=0; iscan<height; iscan++ ) /* for each integer in bitvec[] */
      {
      int bitval = 0; /* current actual pixel value */
      int nrepeats=0, nextreps=0; /* #duplicate lines below current,next line*/
      /* --- check for repeated/duplicate scan lines --- */
      if ( isrepeat /* we're storing scan line repeat counts */
      &&   iscan < height-1 ) { /* current scan line isn't the last line */
       /* --- count repeats --- */
       int jscan = iscan; /* compare current scan with lines below it*/
       while ( ++jscan < height ) { /* until last scan line */
        if (nrepeats == jscan-iscan-1) /*no intervening non-identical lines*/
         if ( bitcmp(bitvec[iscan],bitvec[jscan],width) == 0 ) /* identical */
          nrepeats++; /* so bump repeat count */
        if ( jscan > iscan+1 ) /* we're below next line */
         if (nextreps == jscan-iscan-2) /*no intervening non-identical lines*/
          if ( bitcmp(bitvec[iscan+1],bitvec[jscan],width) == 0 )/*identical*/
    nextreps++; } /* so bump next lline repeat count */
       /* --- set repeat command and count --- */
       if ( nrepeats > 0 ) { /* found repeated lines below current */
        int maxrepeats = maxbitcount[iformat-2]; /*max count/repeats per byte*/
        if ( nrepeats > maxrepeats ) nrepeats=maxrepeats; /* don't exceed max */
        {setbyfmt(iformat,gfcount,pixcount,repeatcmds[iformat-2]);} /*set cmd*/
        {setbyfmt(iformat,gfcount,pixcount+1,nrepeats);} /* set #repeats */
        pixcount += 2; } /* don't bump pixcount within macros */
       } /* --- end-of-if(isrepeat) --- */
      /* --- set bit counts for current scan line --- */
      for ( ibit=0; ibit<width; ibit++ ) /* for all bits in this scanline */
       {
       bitval = getlongbit(bitvec[iscan],ibit); /* check actual pixel value */
       if ( bitval != gfbitval ) { /* black-to-white edge (or vice versa) */
         {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
         pixcount++; /* don't bump pixcount within macro */
         gfbitcount = 0; /* reset consecutive bit count */
         gfbitval = 1-gfbitval; } /* flip bit to be counted */
       else /* check count if continuing with same val */
        if ( gfbitcount >= maxbitcount[iformat-2] ) { /* max count per byte */
         {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
         clearbyfmt(iformat,gfcount,pixcount+1); /*followed by dummy 0 count*/
         pixcount += 2; /* don't bump pixcount within macros */
         gfbitcount = 0; } /* reset consecutive bit count */
       if ( bitval == gfbitval ) /* same bit val as preceding, or first new */
         gfbitcount++; /* so just count another pixel */
       } /* --- end-of-for(ibit) --- */
      /* --- adjust for repeated scan lines --- */
      iscan += nrepeats; /* skip repeated/duplicate scan lines */
      if ( nrepeats>0 || nextreps>0 ) /* emit count to align on full scan */
       if ( iscan < height-1 ) /* have another scan line below this one */
        if ( gfbitcount > 0 ) { /* should always have some final count */
         {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
         pixcount++; /* don't bump pixcount within macro */
         gfbitcount = 0; /* reset consecutive bit count */
         if ( bitval == getlongbit(bitvec[iscan+1],0) ) { /* same bit value */
          clearbyfmt(iformat,gfcount,pixcount); /*so we need a dummy 0 count*/
          pixcount++; } /* don't bump pixcount within macros */
         else /* bitval flips at start of next line */
          gfbitval = 1-gfbitval; /* so flip bit to be counted */
         } /* --- end-of-if(nrepeats...gfbitcount>0) --- */
      } /* --- end-of-for(iscan) --- */
      /* --- store final count --- */
      if ( gfbitcount > 0 ) { /* have a final count */
        {setbyfmt(iformat,gfcount,pixcount,gfbitcount);} /*set byte or nibble*/
        pixcount++; } /* don't bump pixcount within macro */
      else /* ended exactly after maxbitcount? */
       if ( getbyfmt(iformat,gfcount,pixcount-1) == 0 )/*have dummy 0 trailer?*/
        pixcount--; /* remove unneeded dummy trailer */
      /* --- save count to choose smallest --- */
      npixcounts[iformat-2] = pixcount; /* save count */
      } /* --- end-of-for(iformat) --- */
    /* --- check for optimal/smallest format --- */
    nbytes2=npixcounts[0];  nbytes3=(1+npixcounts[1])/2; /* #bytes for count */
    iformat = (nbytes2<nbytes3? 2:3); /* choose smallest format */
    minbytes = (iformat==2?nbytes2:nbytes3); /* #bytes for smallest format */
    if ( gformat == 0 ) /* bitmap representation also permitted */
     if ( nbytes1 <= minbytes ) /* and it's the optimal/smallest format */
      iformat = 1; /* so flip format */
    /* --- move results to returned image --- */
    if ( iformat != 1 ) { /* using a .gf format */
     if ( (image->pixmap = (unsigned char *)malloc(minbytes)) /* alloc pixmap */
     == NULL ) goto end_of_job; /* quit if failed to allocate pixmap */
     memcpy(image->pixmap,gfpixcount[iformat-2],minbytes); /*copy local counts*/
     image->format = iformat; /* signal byte counts or nibble counts */
     image->pixsz = npixcounts[iformat-2]; /*#counts in pixmap for gformat=2,3*/
     } /* --- end-of-if(iformat!=1) --- */
    } /* --- end-of-if(gformat==2) --- */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 copy each integer in bitvec[] to raster pixmap, bit by bit  copy each integer in bitvec[] to raster pixmap, bit by bit
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 for ( iscan=0; iscan<height; iscan++ ) /* for each integer in vector[] */  if ( iformat == 1 ) /* bit-by-bit representation of image */
   for ( ibit=0; ibit<width; ibit++ ) /* for all bits in this scan */   {
    int ipixel = 0; /* pixmap index */
    /* --- first allocate image raster pixmap for character --- */
    if ( (image->pixmap = (unsigned char *)malloc(pixmapsz(image)))
    == NULL ) goto end_of_job; /* quit if failed to allocate pixmap */
    image->format = iformat; /* reset format */
    /* --- now store bit image in allocated raster --- */
    for ( iscan=0; iscan<height; iscan++ ) /* for each integer in bitvec[] */
     for ( ibit=0; ibit<width; ibit++ ) /* for all bits in this scanline */
     {      {
     if ( getlongbit(bitvec[iscan],ibit) != 0 ) /* check current scan pixel */      if ( getlongbit(bitvec[iscan],ibit) != 0 ) /* check current scan pixel */
       { setlongbit(image->pixmap,ipixel); }        { setlongbit(image->pixmap,ipixel); }
Line 455  for ( iscan=0; iscan<height; iscan++ ) / Line 619  for ( iscan=0; iscan<height; iscan++ ) /
       { unsetlongbit(image->pixmap,ipixel); }        { unsetlongbit(image->pixmap,ipixel); }
     ipixel++; /* bump image raster pixel */      ipixel++; /* bump image raster pixel */
     } /* --- end-of-for(iscan,ibit) --- */      } /* --- end-of-for(iscan,ibit) --- */
    } /* --- end-of-if(gformat==1) --- */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 done  done
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
Line 490  extract (col,row) field from line, and i Line 655  extract (col,row) field from line, and i
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 /* --- first, check beginning of line --- */  /* --- first, check beginning of line --- */
 if ( line == (char *)NULL ) goto end_of_job; /* no line supplied by caller */  if ( line == (char *)NULL ) goto end_of_job; /* no line supplied by caller */
   /* --- check for blank line --- */
   if ( strstr(line,BLANKCHAR_STUB) != NULL ) /* got entirely blank character */
     return ( -999 ); /* so return special -999 signal */
   /* --- check for corner --- */
 if ( memcmp(line,CORNER_STUB,strlen(CORNER_STUB)) != 0 ) /*not valid corner*/  if ( memcmp(line,CORNER_STUB,strlen(CORNER_STUB)) != 0 ) /*not valid corner*/
   goto end_of_job; /* so quit */    goto end_of_job; /* so quit */
 /* --- extract  col,row  field from line --- */  /* --- extract  col,row  field from line --- */
Line 532  char *readaline ( FILE *fp ) Line 701  char *readaline ( FILE *fp )
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 Allocations and Declarations  Allocations and Declarations
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 static char buffer[1024]; /* static buffer if caller supplies none */  static char buffer[2048]; /* static buffer returned to caller */
 char *fgets(), *bufptr=buffer; /* read line from fp */  char *fgets(), *bufptr=buffer; /* read line from fp */
 char *strchr(), *delim; /* remove terminating newline */  char *strchr(), *delim; /* remove terminating newline */
 /* --------------------------------------------------------------------------  /* --------------------------------------------------------------------------
 Read line and strip trailing newline  Read line and strip trailing newline
 -------------------------------------------------------------------------- */  -------------------------------------------------------------------------- */
 if ( fp != NULL ) /*if null, return previous line read*/  if ( fp != NULL ) /*if null, return previous line read*/
   if ( (bufptr=fgets(buffer,1023,fp)) /* read next line from fp */    if ( (bufptr=fgets(buffer,2047,fp)) /* read next line from fp */
   != NULL ) /* and check that we succeeded */    != NULL ) /* and check that we succeeded */
     {      {
     if ( (delim=strchr(bufptr,'\n')) /* look for terminating newline */      if ( (delim=strchr(bufptr,'\n')) /* look for terminating newline */
Line 548  if ( fp != NULL )   /*if null, return pr Line 717  if ( fp != NULL )   /*if null, return pr
     } /* --- end-of-if(fgets()!=NULL) --- */      } /* --- end-of-if(fgets()!=NULL) --- */
 return ( bufptr ); /*back to caller with buffer or null*/  return ( bufptr ); /*back to caller with buffer or null*/
 } /* --- end-of-function readaline() --- */  } /* --- end-of-function readaline() --- */
   
   
   /* ==========================================================================
    * Function: bitcmp ( bs1, bs2, n )
    * Purpose: compares the first n bits of two strings
    * --------------------------------------------------------------------------
    * Arguments: bs1 (I) unsigned char * to first bit string
    * bs2 (I) unsigned char * to second bit string
    * n (I) int containing #bits to compare
    * Returns: ( int ) 0 if first n bits are identical
    * -1 if first unmatching bit of bs1 is 0
    * +1 if first unmatching bit of bs2 id 0
    * --------------------------------------------------------------------------
    * Notes:     o
    * ======================================================================= */
   /* --- entry point --- */
   int bitcmp ( unsigned char *bs1, unsigned char *bs2, int n )
   {
   /* --------------------------------------------------------------------------
   Allocations and Declarations
   -------------------------------------------------------------------------- */
   int icmp = 0; /* returned to caller */
   int nbytes = n/8, /* #full bytes we can compare with memcmp()*/
    nbits  = n%8,  ibit=0; /* #trailing bits in last byte, index */
   /* --------------------------------------------------------------------------
   compare leading bytes, then trailing bits
   -------------------------------------------------------------------------- */
   if ( nbytes > 0 ) icmp = memcmp(bs1,bs2,nbytes); /* compare leading bytes */
   if ( icmp == 0 ) /* leading bytes identical */
    if ( nbits > 0 ) /* and we have trailing bits */
     for ( ibit=0; ibit<nbits; ibit++ ) /* check each bit */
      { icmp = (int)get1bit(bs1[nbytes],ibit) - (int)get1bit(bs2[nbytes],ibit);
        if ( icmp != 0 ) break; } /* done at first unmatched bit */
   return ( icmp ); /* back to caller with -1,0,+1 */
   } /* --- end-of-function bitcmp() --- */
 /* --- end-of-file gfuntype.c --- */  /* --- end-of-file gfuntype.c --- */
   

Removed from v.1.1  
changed lines
  Added in v.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>