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 --- */ |
|
|