/**************************************************************************** * * Copyright(c) 2002-2008, John Forkosh Associates, Inc. All rights reserved. * http://www.forkosh.com mailto: john@forkosh.com * -------------------------------------------------------------------------- * This file is part of mimeTeX, which is free software. You may redistribute * and/or modify it under the terms of the GNU General Public License, * version 3 or later, as published by the Free Software Foundation. * MimeTeX is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY, not even the implied warranty of MERCHANTABILITY. * See the GNU General Public License for specific details. * By using mimeTeX, you warrant that you have read, understood and * agreed to these terms and conditions, and that you possess the legal * right and ability to enter into this agreement and to use mimeTeX * in accordance with it. * Your mimetex.zip distribution file should contain the file COPYING, * an ascii text copy of the GNU General Public License, version 3. * If not, point your browser to http://www.gnu.org/licenses/ * or write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * -------------------------------------------------------------------------- * * Program: gfuntype [-g gformat] [-u isnoname] [-m msglevel] * [-n fontname] [infile [outfile]] * * Purpose: Parses output from gftype -i * and writes pixel bitmap data of the characters * in a format suitable for a C header file, etc. * * -------------------------------------------------------------------------- * * Command-line Arguments: * --- args can be in any order --- * infile name of input file * (defaults to stdin if no filenames given) * outfile name of output file * (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) * -n fontname string used for fontname * (defaults to noname) * * Exits: 0=success, 1=some error * * Notes: o To compile * cc gfuntype.c mimetex.c -lm -o gfuntype * needs mimetex.c and mimetex.h * * Source: gfuntype.c * * -------------------------------------------------------------------------- * Revision History: * 09/22/02 J.Forkosh Installation. * 10/11/05 J.Forkosh .gf-style format options added. * 09/06/08 J.Forkosh mimeTeX version 1.70 released. * ****************************************************************************/ /* -------------------------------------------------------------------------- standard headers, program parameters, global data and macros -------------------------------------------------------------------------- */ /* --- standard headers --- */ #include #include #include #include /* --- application headers --- */ /* #define SIGNEDCHAR */ #include "mimetex.h" /* --- parameters either -D defined on cc line, or defaulted here --- */ #ifndef MSGLEVEL #define MSGLEVEL 0 #endif #ifndef GFORMAT #define GFORMAT 1 #endif #ifndef ISREPEAT #define ISREPEAT 1 #endif /* --- message level (verbose test) --- */ static int msglevel = MSGLEVEL; /* verbose if msglevel >= 9 */ 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 --- */ #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 */ /* ========================================================================== * Function: main() for gfuntype.c * Purpose: interprets command-line args, etc * -------------------------------------------------------------------------- * Command-Line Arguments: * See above * -------------------------------------------------------------------------- * Returns: 0=success, 1=some error * -------------------------------------------------------------------------- * Notes: o * ======================================================================= */ /* --- entry point --- */ int main ( int argc, char *argv[] ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ int argnum = 0; /* argv[] index for command-line args */ int inarg=0, outarg=0; /* argv[] indexes for infile, outfile */ int iserror = 1; /* error signal */ int charnum, /* character number (nextchar->charnum) */ nchars = 0; /* #chars in font */ char fontname[99] = "noname", /* font name */ *getcharname(); /* get character name from its number */ FILE /* *fopen(),*/ *infp=stdin, *outfp=stdout; /* init file pointers */ chardef *getnextchar(), *nextchar, /* read and parse next char in infp */ *fontdef[256]; /* chars stored using charnum as index */ int cstruct_chardef(); /* emit C struct for a character map */ int type_raster(); /* display debugging output */ char *copyright = /* copyright, gnu/gpl notice */ "+-----------------------------------------------------------------------+\n" "|gfuntype ver 1.00, Copyright(c) 2002-2003, John Forkosh Associates, Inc|\n" "+-----------------------------------------------------------------------+\n" "| gfuntype is free software licensed to you under terms of the GNU/GPL, |\n" "| and comes with absolutely no warranty whatsoever. |\n" "+-----------------------------------------------------------------------+"; /* -------------------------------------------------------------------------- interpret command-line arguments -------------------------------------------------------------------------- */ while ( argc > ++argnum ) /* check for flags and filenames */ if ( *argv[argnum] == '-' ) /* got some '-' flag */ { char flag = tolower(*(argv[argnum]+1)); /* char following '-' */ argnum++; /* arg following flag is usually its value */ switch ( flag ) /* see what user wants to tell us */ { /* --- no usage for clueless users yet --- */ default: exit(iserror); /* exit quietly for unrecognized input */ /* --- adjustable program parameters (not checking input) --- */ 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; } /* --- end-of-switch() --- */ } /* --- end-of-if(*argv[]=='-') --- */ else /* this arg not a -flag, so it must be... */ if ( inarg == 0 ) /* no infile arg yet */ inarg = argnum; /* so use this one */ else /* we already have an infile arg */ if ( outarg == 0 ) /* but no outfile arg yet */ outarg = argnum; /* so use this one */ /* --- set verbose file ptr --- */ msgfp = (outarg>0? stdout : stderr); /* use stdout or stderr */ /* --- emit copyright, gnu/gpl notice --- */ fprintf(msgfp,"%s\n",copyright); /* display copyright, gnu/gpl info */ /* --- display input args if verbose output --- */ if ( msglevel >= 9 ) /* verbose output requested */ fprintf(msgfp,"gfuntype> infile=%s outfile=%s, fontname=%s format=%d.%d\n", (inarg>0?argv[inarg]:"stdin"), (outarg>0?argv[outarg]:"stdout"), fontname, gformat,isrepeat); /* -------------------------------------------------------------------------- initialization -------------------------------------------------------------------------- */ /* --- initialize font[] array --- */ for ( charnum=0; charnum<256; charnum++ ) /*for each possible char in font*/ fontdef[charnum] = (chardef *)NULL; /* char doesn't exist yet */ /* --- open input file (if necessary) --- */ if ( inarg > 0 ) /* input from file, not from stdin */ if ( (infp = fopen(argv[inarg],"r")) == NULL ) /*try to open input file*/ { fprintf(msgfp,"gfuntype> can't open %s for read\n",argv[inarg]); 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 -------------------------------------------------------------------------- */ while ( (nextchar=getnextchar(infp)) != NULL ) /* get each char in file */ { /* --- display character info --- */ if ( msglevel >= 9 ) /* verbose output requested */ fprintf(msgfp,"gfuntype> Char#%3d, loc %4d: ul=(%d,%d) ll=(%d,%d)\n", nextchar->charnum, nextchar->location, nextchar->topleftcol,nextchar->toprow, nextchar->botleftcol,nextchar->botrow); if ( msglevel >= 19 ) /* if a bit more verbose */ type_raster(&(nextchar->image),msgfp); /*display ascii image of raster*/ /* --- store character in font */ charnum = nextchar->charnum; /* get char number of char in font */ if ( charnum>=0 && charnum<=255 ) /* check for valid range */ fontdef[charnum] = nextchar; /* store char in font */ } /* --- end-of-while(charnum>0) --- */ /* -------------------------------------------------------------------------- generate output file -------------------------------------------------------------------------- */ /* --- open output file (if necessary) --- */ if ( outarg > 0 ) /* output to a file, not to stdout */ if ( (outfp = fopen(argv[outarg],"w")) == NULL ) /*try to open output file*/ { fprintf(msgfp,"gfuntype> can't open %s for write\n",argv[outarg]); goto end_of_job; } /* report error and quit */ /* --- header lines --- */ fprintf(outfp,"/%c --- fontdef for %s --- %c/\n", '*',fontname,'*'); fprintf(outfp,"static\tchardef %c%s[] =\n {\n", ' ',fontname); /* --- write characters comprising font --- */ for ( charnum=0; charnum<256; charnum++ ) /*for each possible char in font*/ if ( fontdef[charnum] != (chardef *)NULL ) /*check if char exists in font*/ { char *charname = getcharname(fontname,charnum); if ( charname!=NULL || isnoname ) { /* char defined or want undefined */ if ( ++nchars > 1 ) /* bump count */ fprintf(outfp,",\n"); /* and terminate preceding chardef */ fprintf(outfp," /%c --- pixel bitmap for %s char#%d %s --- %c/\n", '*',fontname,charnum,(charname==NULL?noname:charname),'*'); 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 --- */ fprintf(outfp,",\n"); /* finish up last map from loop */ fprintf(outfp," /%c --- trailer --- %c/\n",'*','*'); /* trailer... */ fprintf(outfp," { -99, -999, 0,0,0,0, { 0,0,0,0, %s\"\\0\" } }\n", TYPECAST); fprintf(outfp," } ;\n"); /* terminating }; for fontdef */ /* -------------------------------------------------------------------------- end-of-job -------------------------------------------------------------------------- */ /* --- reset error status for okay exit --- */ iserror = 0; /* --- close files (if they're open and not stdin/out) --- */ end_of_job: if ( infp!=NULL && infp!=stdin ) fclose( infp); if ( outfp!=NULL && outfp!=stdout ) fclose(outfp); exit ( iserror ); } /* --- end-of-function main() --- */ /* ========================================================================== * Function: getnextchar ( fp ) * Purpose: Reads and parses the next character definition on fp, * and returns a new chardef struct describing that character. * -------------------------------------------------------------------------- * Arguments: fp (I) FILE * to input file * (containing output from gftype -i) * Returns: ( chardef * ) ptr to chardef struct describing character, * or NULL for eof or any error * -------------------------------------------------------------------------- * Notes: o fp is left so the next line read from it will be * the one following the final .<-- line. * ======================================================================= */ /* --- entry point --- */ chardef *getnextchar ( FILE *fp ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ chardef *new_chardef(), *nextchar=(chardef *)NULL; /*ptr returned to caller*/ int delete_chardef(); /* free allocated memory if error */ int findnextchar(), charnum,location; /* get header line for next char */ int rasterizechar(); /* ascii image --> raster pixmap */ int parsestat=(-999), parsecorner(); /* get col,row from ".<--" line */ char *readaline(); /* read next line from fp */ /* -------------------------------------------------------------------------- initialization -------------------------------------------------------------------------- */ while ( parsestat == (-999) ) { /* flush entirely blank characters */ /* --- find and interpret header line for next character --- */ charnum = findnextchar(fp,&location); /* read and parse header line */ if ( charnum < 0 ) goto error; /* eof or error, no more chars */ /* --- allocate a new chardef struct and begin populating it --- */ if ( nextchar == (chardef *)NULL ) /* haven't allocated chardef yet */ if ( (nextchar=new_chardef()) /* allocate a new chardef */ == (chardef *)NULL ) goto error; /* and quit if we failed */ nextchar->charnum = charnum; /* store charnum in struct */ nextchar->location = location; /* and location */ /* --- get upper-left corner line --- */ 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) -------------------------------------------------------------------------- */ /* --- read ascii character image and interpret as integer bitmap --- */ if ( rasterizechar(fp,&nextchar->image) != 1 ) /* parse image of char */ goto error; /* and quit if failed */ /* --- get lower-left corner line --- */ if ( !parsecorner(readaline(NULL), /* reread and parse corner line */ &(nextchar->botrow),&(nextchar->botleftcol)) ) /* row and col from line */ goto error; /* and quit if failed */ /* -------------------------------------------------------------------------- done -------------------------------------------------------------------------- */ goto end_of_job; /* skip error return if successful */ error: if ( nextchar != (chardef *)NULL ) /* have an allocated chardef */ delete_chardef(nextchar); /* so deallocate it */ nextchar = (chardef *)NULL; /* and reset ptr to null for error */ end_of_job: return ( nextchar ); /* back with chardef or null */ } /* --- end-of-function getnextchar() --- */ /* ========================================================================== * Function: getcharname ( fontname, charnum ) * Purpose: Looks up charnum for the family specified by fontname * and returns the corresponding charname. * -------------------------------------------------------------------------- * Arguments: fontname (I) char * containing fontname for font family * (from -n switch on command line) * charnum (I) int containing the character number * whose corresponding name is wanted. * Returns: ( char * ) ptr to character name * or NULL if charnum not found in table * -------------------------------------------------------------------------- * Notes: o * ======================================================================= */ /* --- entry point --- */ char *getcharname ( char *fontname, int charnum ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ /* --- recognized font family names and our corresponding numbers --- */ static char *fnames[] = /*font name from -n switch on command line*/ { "cmr","cmmib","cmmi","cmsy","cmex","bbold","rsfs", "stmary","cyr", NULL }; static int fnums[] = /* corresponding mimetex fontfamily number*/ { CMR10,CMMIB10,CMMI10,CMSY10,CMEX10,BBOLD10,RSFS10, STMARY10, CYR10, -1 }; static int offsets[] = /* symtable[ichar].charnum = charnum-offset*/ { 0, 0, 0, 0, 0, 0, 65, 0, 0, -1 }; /* --- other local declarations --- */ char *charname = NULL; /* character name returned to caller */ char flower[99] = "noname"; /* lowercase caller's fontname */ int ifamily = 0, /* fnames[] (and fnums[],offsets[]) index */ offset = 0, /* offsets[ifamily] */ ichar = 0; /* loop index */ /* -------------------------------------------------------------------------- lowercase caller's fontname and look it up in fnames[] -------------------------------------------------------------------------- */ /* --- lowercase caller's fontname --- */ for ( ichar=0; *fontname!='\000'; ichar++,fontname++ )/*lowercase each char*/ flower[ichar] = (isalpha(*fontname)? tolower(*fontname) : *fontname); flower[ichar] = '\000'; /* null-terminate lowercase fontname */ if ( strlen(flower) < 2 ) goto end_of_job; /* no lookup match possible */ /* --- look up lowercase fontname in our fnames[] table --- */ for ( ifamily=0; ;ifamily++ ) /* check fnames[] for flower */ if ( fnames[ifamily] == NULL ) goto end_of_job; /* quit at end-of-table */ 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 */ /* -------------------------------------------------------------------------- now look up name for caller's charnum in ifamily, and return it to caller -------------------------------------------------------------------------- */ /* --- search symtable[] for charnum in ifamily --- */ for ( ichar=0; ;ichar++ ) /*search symtable[] for charnum in ifamily*/ if ( symtable[ichar].symbol == NULL ) goto end_of_job; /* end-of-table */ else if ( symtable[ichar].family == ifamily /* found desired family */ && symtable[ichar].handler == NULL ) /* and char isn't a "dummy" */ if ( symtable[ichar].charnum == charnum-offset ) break; /*got charnum*/ /* --- return corresponding charname to caller --- */ charname = symtable[ichar].symbol; /* pointer to symbol name in table */ end_of_job: if ( charname==NULL && isnoname ) /* want unnamed/undefined chars */ charname = noname; /* so replace null return with noname */ return ( charname ); } /* --- end-of-function getcharname() --- */ /* ========================================================================== * Function: findnextchar ( fp, location ) * Purpose: Finds next "beginning of char" line in fp * and returns the character number, * and (optionally) location if arg provided. * -------------------------------------------------------------------------- * Arguments: fp (I) FILE * to input file * (containing output from gftype -i) * location (O) int * returning "location" of character * (or pass NULL and it won't be returned) * Returns: ( int ) character number, * or -1 for eof or any error * -------------------------------------------------------------------------- * Notes: o fp is left so the next line read from it will be * the one following the "beginning of char" line * ======================================================================= */ /* --- entry point --- */ int findnextchar ( FILE *fp, int *location ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ static char keyword[99]="beginning of char "; /*signals start of next char*/ char *readaline(), *line; /* read next line from fp */ char *strstr(), *strchr(), *delim; /* search line for substring, char */ char token[99]; /* token extracted from line */ int charnum = (-1); /* character number returned to caller */ /* -------------------------------------------------------------------------- keep reading lines until eof or keyword found -------------------------------------------------------------------------- */ while ( (line=readaline(fp)) != NULL ) /* read lines until eof */ { if ( msglevel >= 999 ) /* very, very verbose output requested */ fprintf(msgfp,"nextchar> line = %s\n",line); if ( (delim=strstr(line,keyword)) != NULL ) /* found keyword on line */ { /* --- get character number from line --- */ strcpy(token,delim+strlen(keyword)); /* char num follows keyword */ charnum = atoi(token); /* interpret token as integer charnum */ /* --- get location at beginning of line --- */ if ( location != (int *)NULL ) /* caller wants location returned */ if ( (delim=strchr(line,':')) != NULL ) /* location precedes colon */ { *delim = '\000'; /* terminate line after location */ *location = atoi(line); } /* interpret location as integer */ break; /* back to caller with charnum */ } /* --- end-of-if(delim!=NULL) --- */ } /* --- end-of-while(line!=NULL) --- */ return ( charnum ); /* back to caller with char number or -1 */ } /* --- end-of-function findnextchar() --- */ /* ========================================================================== * Function: rasterizechar ( fp, rp ) * Purpose: Reads and parses subsequent lines from fp * (until a terminating ".<--" line), * representing the ascii image of the character in fp, * and returns the results in raster struct rp * -------------------------------------------------------------------------- * Arguments: fp (I) FILE * to input file * (containing output from gftype -i) * positioned immediately after top .<-- line, * ready to read first line of ascii image * rp (O) raster * returning the rasterized * character represented on fp as an ascii image * Returns: ( int ) 1=okay, or 0=eof or any error * -------------------------------------------------------------------------- * Notes: o fp is left so the last line (already) read from it * contains the terminating .<-- corner information * (readaline(NULL) will reread this last line) * o char images on fp can be no wider than 31 pixels * ======================================================================= */ /* --- entry point --- */ int rasterizechar ( FILE *fp, raster *image ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ char *readaline(), *line; /* read next scan line for char from fp */ 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 */ width = 0; /* #chars on longest scan line */ int iscan, /* bitvec[] index */ ibit; /* bit along scan (i.e., 0...width-1) */ 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 -------------------------------------------------------------------------- */ memset(bitvec,0,128*1024); /* zero-fill bitvec[] */ while ( (line=readaline(fp)) != NULL ) /* read lines until eof */ { /* --- allocations and declarations --- */ int icol, ncols=strlen(line); /* line[] column index, #cols in line[] */ /* --- check for end-of-char (when we encounter corner line) --- */ if ( memcmp(line,CORNER_STUB,strlen(CORNER_STUB)) == 0 ) /* corner line */ break; /* so done with loop */ /* --- parse line (encode asterisks comprising character image) --- */ memset(bitvec[height],0,128); /* first zero out all bits */ for ( icol=0; icol= width ) width=icol+1; } /* and check for new width */ height++; /* bump character height */ } /* --- end-of-while(line!=NULL) --- */ if ( height<1 || width<1 ) /* some problem parsing character */ goto end_of_job; /* so quit */ /* -------------------------------------------------------------------------- init image values -------------------------------------------------------------------------- */ if ( image->pixmap != NULL ) /* hmm, somebody already allocated memory */ free((void *)image->pixmap); /* so just free it */ image->width = width; /* set image width within raster struct */ image->height = height; /* and height */ image->format = gformat; /* set format (will be reset below) */ image->pixsz = 1; /* #bits per pixel (or #counts in .gf fmt) */ 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 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= 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 = (nbytes2pixmap = (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 -------------------------------------------------------------------------- */ if ( iformat == 1 ) /* bit-by-bit representation of image */ { 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; iscanpixmap,ipixel); } else /*turn off corresponding raster bit*/ { unsetlongbit(image->pixmap,ipixel); } ipixel++; /* bump image raster pixel */ } /* --- end-of-for(iscan,ibit) --- */ } /* --- end-of-if(gformat==1) --- */ /* -------------------------------------------------------------------------- done -------------------------------------------------------------------------- */ isokay = 1; /* reset flag for success */ end_of_job: return ( isokay ); /* back with 1=success, 0=failure */ } /* --- end-of-function rasterizechar() --- */ /* ========================================================================== * Function: parsecorner ( line, row, col ) * Purpose: Parses a "pixel corner" line (upper left or lower left) * and returns the (col,row) information on it as integers. * -------------------------------------------------------------------------- * Arguments: line (I) char * to input line containing * ".<--This pixel's..." to be parsed * row (O) int * returning the (,row) * col (O) int * returning the (col,) * Returns: ( int ) 1 if successful, or 0 for any error * -------------------------------------------------------------------------- * Notes: o * ======================================================================= */ /* --- entry point --- */ int parsecorner ( char *line, int *row, int *col ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ int isokay = 0; /* success/fail flag, init for failure */ char field[99], *delim; /*(col,row) field and ptr to various delims*/ /* -------------------------------------------------------------------------- extract (col,row) field from line, and interpret col and row as integers -------------------------------------------------------------------------- */ /* --- first, check beginning of line --- */ 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*/ goto end_of_job; /* so quit */ /* --- extract col,row field from line --- */ if ( (delim=strchr(line,'(')) == NULL ) goto end_of_job; /*find open paren*/ strncpy(field,delim+1,10); /* extract next 10 chars */ field[10] = '\000'; /* and null-terminate field */ if ( (delim=strchr(field,')')) == NULL ) goto end_of_job; /*find close paren*/ *delim = '\000'; /* terminate field at close paren */ /* --- interpret col,row as integers --- */ if ( (delim=strchr(field,',')) == NULL ) goto end_of_job; /* find comma */ *delim = '\000'; /* break field into col and row */ if ( col != (int *)NULL ) /* caller gave us ptr for col */ *col = atoi(field); /* so return it to him */ if ( row != (int *)NULL ) /* caller gave us ptr for row */ *row = atoi(delim+1); /* so return it to him */ /* -------------------------------------------------------------------------- done -------------------------------------------------------------------------- */ isokay = 1; /* reset flag for success */ end_of_job: return ( isokay ); /* back with success/fail flag */ } /* --- end-of-function parsecorner() --- */ /* ========================================================================== * Function: readaline ( fp ) * Purpose: Reads a line from fp, strips terminating newline, * and returns ptr to internal buffer * -------------------------------------------------------------------------- * Arguments: fp (I) FILE * to input file to be read. * If null, returns line previously read. * Returns: ( char * ) internal buffer containing line read, * or NULL for eof or error. * -------------------------------------------------------------------------- * Notes: o fp is left on the line following the returned line * ======================================================================= */ /* --- entry point --- */ char *readaline ( FILE *fp ) { /* -------------------------------------------------------------------------- Allocations and Declarations -------------------------------------------------------------------------- */ static char buffer[2048]; /* static buffer returned to caller */ char *fgets(), *bufptr=buffer; /* read line from fp */ char *strchr(), *delim; /* remove terminating newline */ /* -------------------------------------------------------------------------- Read line and strip trailing newline -------------------------------------------------------------------------- */ if ( fp != NULL ) /*if null, return previous line read*/ if ( (bufptr=fgets(buffer,2047,fp)) /* read next line from fp */ != NULL ) /* and check that we succeeded */ { if ( (delim=strchr(bufptr,'\n')) /* look for terminating newline */ != NULL ) /* and check that we found it */ *delim = '\000'; /* truncate line at newline */ } /* --- end-of-if(fgets()!=NULL) --- */ return ( bufptr ); /*back to caller with buffer or null*/ } /* --- 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