#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "efaxmsg.h"
#include "efaxlib.h"
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
#define DEFXRES 204.145
#define DEFYRES 195.58
#define DEFWIDTH 1728
#define DEFHEIGHT 2287
extern t4tab wtab [ ( 64 + 27 + 13 ) + 1 ] ;
extern t4tab btab [ ( 64 + 27 + 13 ) + 1 ] ;
short short256 = 256 ;
uchar reversebits [ 256 ], normalbits [ 256 ] ;
int ckfmt ( char *p, int n )
{
for ( ; *p ; p++ ) {
if ( p[0] == '%' ) {
if ( p[1] == 'd' ) n-- ;
else if ( p[1] == '%' ) p++ ;
else n=-1 ;
}
}
return n < 0 ;
}
void newENCODER ( ENCODER *e )
{
e->x = 0 ;
e->shift = -8 ;
}
uchar *putcode ( ENCODER *e, short code, short bits, uchar *buf )
{
e->x = ( e->x << bits ) | code ;
e->shift += bits ? bits : -e->shift ;
while ( e->shift >= 0 ) {
*buf++ = e->x >> e->shift ;
e->shift -= 8 ;
}
return buf ;
}
uchar *runtocode ( ENCODER *e, short *runs, int nr, uchar *codes )
{
uchar col = 0, *maxcodes = codes + MAXCODES ;
t4tab *ctab = wtab, *p ;
short rlen ;
long x ;
short shift ;
#define PUTCODE(p) { x = ( x << p->bits ) | p->code ; shift += p->bits ; \
while ( shift >= 0 ) { *codes++ = x >> shift ; shift -= 8 ; } }
x = e->x ; shift = e->shift ;
while ( nr-- > 0 ) {
rlen = *runs++ ;
if ( rlen > 63 ) {
if ( rlen > MAXRUNLEN ) rlen = MAXRUNLEN ;
p = ctab + 63 + ( rlen >> 6 ) ;
if ( codes < maxcodes ) PUTCODE(p) ;
}
p = ctab + ( rlen & 0x3f ) ;
if ( codes < maxcodes ) PUTCODE(p) ;
ctab = ( col ^= 1 ) ? btab : wtab ;
}
e->x = x ; e->shift = shift ;
return codes ;
}
int xpad ( short *runs, int nr, int pad )
{
if ( pad < 0 ) {
while ( pad < 0 ) pad += ( nr <= 0 ? -pad : runs [ --nr ] ) ;
runs [ nr++ ] = pad ;
} else {
if ( nr & 1 ) runs [ nr - 1 ] += pad ;
else runs [ nr++ ] = pad ;
}
return nr ;
}
int xshift ( short *runs, int nr, int s )
{
int i=0, n=0 ;
if ( s < 0 ) {
for ( i = 0 ; s < 0 && i < nr ; i++ ) {
s += runs [ i ] ;
n -= runs [ i ] ;
runs [ i ] = 0 ;
}
i-- ;
}
if ( i < nr ) {
runs [ i ] += s ;
n += s ;
}
return n ;
}
int xscale ( short *p, int nr, int xs )
{
int inlen=0, outlen=0 ;
for ( ; nr-- > 0 ; p++ ) {
inlen += *p ;
*p = ( ( inlen * xs + 128 ) >> 8 ) - outlen ;
outlen += *p ;
}
return outlen ;
}
int xinvert ( short *p, int nr )
{
int i ;
if ( ! *p ) {
for ( i=0 ; i<nr-1 ; i++ ) {
p[i] = p[i+1] ;
}
nr-- ;
} else {
for ( i=nr ; i>0 ; i-- ) {
p[i] = p[i-1] ;
}
p[0] = 0 ;
nr++ ;
}
return nr ;
}
uchar byteruns [ 1408 + 1 ] =
"8071061106205120511105210530413041210411110411204220421104310440"
"3140313103121103122031112031111103112103113032303221032111032120"
"3320331103410350215021410213110213202121202121110212210212302111"
"3021112102111111021111202112202112110211310211402240223102221102"
"2220221120221111022121022130233023210231110231202420241102510260"
"1160115101141101142011312011311101132101133011213011212101121111"
"0112112011222011221101123101124011114011113101111211011112201111"
"1120111111110111112101111130111230111221011121110111212011132011"
"1311011141011150125012410123110123201221201221110122210122301211"
"3012112101211111012111201212201212110121310121401340133101321101"
"3220131120131111013121013130143014210141110141201520151101610170"
"1701610151101520141201411101421014301313013121013111101311201322"
"0132110133101340121401213101212110121220121112012111110121121012"
"1130122301222101221110122120123201231101241012501115011141011131"
"1011132011121201112111011122101112301111130111112101111111101111"
"1120111122011112110111131011114011240112310112211011222011211201"
"1211110112121011213011330113210113111011312011420114110115101160"
"2602510241102420231202311102321023302213022121022111102211202222"
"0222110223102240211402113102112110211220211112021111110211121021"
"1130212302122102121110212120213202131102141021503503410331103320"
"3212032111032210323031130311210311111031112031220312110313103140"
"4404310421104220411204111104121041305305210511105120620611071080" ;
int bittorun ( uchar *bits, int n, short *runs )
{
static uchar init=0, *rltab [ 256 ] ;
register uchar *p, c, lastc = 0x00 ;
short *runs0 = runs ;
if ( ! init ) {
int i = 0 ;
for ( rltab[ 0 ] = p = byteruns ; *p ; p++ )
if ( ! ( *p -= '0' ) && i < 255 )
rltab [ ++i ] = p+1 ;
init = 1 ;
}
*runs = 0 ;
for ( ; n > 0 ; n-- ) {
p = rltab [ c = *bits++ ] ;
if ( ( lastc & 0x01 ) ? ! ( c & 0x80 ) : ( c & 0x80 ) )
*(++runs) = *p++ ;
else
*runs += *p++ ;
while ( *p )
*(++runs) = *p++ ;
lastc = c ;
}
return runs - runs0 + 1 ;
}
int runor ( short *a, int na, short *b, int nb, short *c, int *pels )
{
register short la, lb ;
int ia, ib, ic, np=0 ;
short tmp [ MAXRUNS ] ;
if ( ! c ) c = tmp ;
la = a [ ia = 0 ] ;
lb = b [ ib = 0 ] ;
c [ ic = 0 ] = 0 ;
while ( 1 ) {
if ( la <= lb ) {
if ( ( ( ia | ib ) ^ ic ) & 1 )
c [ ++ic ] = la ;
else
c [ ic ] += la ;
lb -= la ;
if ( ++ia >= na ) break ;
la = a [ ia ] ;
} else {
if ( ( ( ia | ib ) ^ ic ) & 1 )
c [ ++ic ] = lb ;
else
c [ ic ] += lb ;
la -= lb ;
if ( ++ib >= nb ) break ;
lb = b [ ib ] ;
}
}
if ( ia < na )
while ( 1 ) {
if ( ( ia ^ ic ) & 1 )
c [ ++ic ] = la ;
else
c [ ic ] += la ;
if ( ++ia >= na ) break ;
la = a [ ia ] ;
}
else
while ( 1 ) {
if ( ( ib ^ ic ) & 1 )
c [ ++ic ] = lb ;
else
c [ ic ] += lb ;
if ( ++ib >= nb ) break ;
lb = b [ ib ] ;
}
if ( c == tmp ) for ( ia=0 ; ia <= ic ; ia++ ) np += a[ia] = c[ia] ;
if ( pels ) *pels = np ;
return ic + 1 ;
}
int pbmdim ( IFILE *f )
{
int c, n=0 ;
while ( ! isdigit ( c = fgetc ( f->f ) ) && c >= 0 )
if ( c == '#' )
while ( ( c = fgetc ( f->f ) ) != '\n' && c >= 0 ) ;
if ( c >= 0 && isdigit( c ) ) {
n = c - '0' ;
while ( isdigit ( c = fgetc ( f->f ) ) && c >= 0 )
n = n * 10 + c - '0' ;
}
return n ;
}
#define putbits( c, b ) { x = ( x << (b) ) | (c) ; shift += (b) ; \
if ( shift >= 0 ) { *out++ = x >> shift ; shift -= 8 ; } }
void copybits ( uchar *in, int from, short nb )
{
uchar *f ;
short bits ;
static uchar *out ;
static short x, shift ;
static unsigned char right [ 9 ] = {
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff } ;
if ( ! nb ) {
if ( in ) out = in ;
else putbits ( 0, -shift ) ;
x = 0 ;
shift = -8 ;
} else {
f = in + ( from >> 3 ) ;
bits = 8 - ( from & 7 ) ;
if ( nb >= bits ) {
putbits ( *f++ & right [ bits ], bits ) ;
nb -= bits ;
} else {
putbits ( ( *f >> ( bits - nb ) ) & right [ bits ], nb ) ;
nb = 0 ;
}
while ( nb >= 8 ) { putbits ( *f++, 8 ) ; nb -= 8 ; }
if ( nb > 0 ) putbits ( *f >> ( 8 - nb ), nb );
}
}
int texttorun ( uchar *txt, faxfont *font, short line,
int w, int h, int lmargin,
short *runs, int *ppels )
{
uchar *in, out [ MAXLINELEN * MAXFONTW / 8 + 1 ] ;
int i, nc = 0, cw, nr, pels ;
line = ( line * font->h + h/2 ) / h ;
cw = font->w ;
if ( line >= font->h ) line = font->h - 1 ;
in = font->buf + 256/8 * cw * line ;
copybits ( out, 0, 0 ) ;
for ( i=0 ; txt[i] && i < MAXLINELEN ; i++ ) {
copybits ( in, font->offset [ txt[i] ], cw ) ;
nc++ ;
while ( ( txt[i] == HT ) && ( nc & 7 ) ) {
copybits ( in, font->offset [ ' ' ], cw ) ;
nc++ ;
}
}
copybits ( 0, 0, 0 ) ;
nr = bittorun ( out, ( nc*cw + 7 )/8, runs ) ;
if ( font->w == w )
pels = nc*cw ;
else
pels = xscale ( runs, nr, ( w * 256 ) / font->w ) ;
pels += xshift ( runs, nr, lmargin ) ;
if ( ppels ) *ppels = pels ;
return nr ;
}
char *iformatname [ NIFORMATS ] = IFORMATS ;
char *oformatname [ NOFORMATS ] = OFORMATS ;
char *pformatname [ NPFORMATS ] = PFORMATS ;
void logifnames ( IFILE *f, char *s )
{
PAGE *p ;
char *fn ;
if ( f && f->page )
for ( p = f->page ; p <= f->lastpage ; p++ ) {
fn = p->fname ;
if ( fn ) msg ( s, fn ) ;
}
}
int readruns ( IFILE *f, short *runs, int *pels )
{
int err=0, c=EOF, n ;
register int x ;
dtab *tab, *t ;
short shift ;
short *p, *maxp, *q, len=0, npad=0 ;
DECODER *d ;
uchar reverse=f->page->revbits ;
maxp = ( p = runs ) + MAXRUNS ;
d = &f->d ;
x = d->x ; shift = d->shift ; tab = d->tab ;
do {
do {
while ( shift < 0 ) {
if ( ( c = fgetc ( f->f ) ) == EOF ) {
x = ( x << 15 ) | 1 ; shift += 15 ;
npad++ ;
} else {
if ( reverse ) c = normalbits [ c & 0xff ] ;
x = ( x << 8 ) | c ; shift += 8 ;
}
}
t = tab + ( ( x >> shift ) & 0x1ff ) ;
tab = t->next ;
shift -= t->bits ;
} while ( ! t->code ) ;
if ( p < maxp ) *p++ = t->code ;
} while ( t->code != -1 ) ;
d->x = x ; d->shift = shift ; d->tab = tab ;
if ( npad > 1 ) msg ("W EOF before RTC" ) ;
if ( p >= maxp ) msg ( "W run length buffer overflow" ) ;
n = p - runs - 1 ;
for ( p = q = runs ; n-- > 0 ; )
if ( *p > 64 && n-- > 0 ) {
len += *q++ = p[0] + p[1] - 2 ;
p+=2 ;
} else {
len += *q++ = *p++ - 1 ;
}
n = q - runs ;
if ( len )
d->eolcnt = 0 ;
else
if ( ++(d->eolcnt) >= RTCEOL ) err = EOF ;
if ( c == EOF ) {
if ( ferror ( f->f ) ) {
err = -msg ("ES2error reading fax file:") ;
} else {
err = -2 ;
}
}
if ( pels ) *pels = len ;
return err ? err : n ;
}
int readpcx ( char *p, int len, IFILE *f )
{
int err=0, n, c ;
while ( !err && len > 0 ) {
if ( ( c = fgetc ( f->f ) ) < 0 ) {
err = msg ( "ES2 PCX read failed" ) ;
} else {
if ( ( c & 0xc0 ) == 0xc0 ) {
n = c & 0x3f ;
c = fgetc ( f->f ) ;
if ( ( c = fgetc ( f->f ) ) < 0 ) {
err = msg ( "ES2 PCX read failed" ) ;
} else {
memset ( p, c, n <= len ? n : len ) ;
p += n ;
len -= n ;
}
} else {
*p++ = c ;
len-- ;
}
}
}
if ( len != 0 )
msg ( "W PCX run-length coding error" ) ;
return err ;
}
int readline ( IFILE *f, short *runs, int *pels )
{
int nr = 0, nb ;
uchar bits [ MAXBITS ] ;
if ( f->lines != 0 ) {
switch ( f->page->format ) {
case P_TEXT :
if ( f->txtlines <= 0 ) {
if ( fgets ( f->text, MAXLINELEN, f->f ) ) {
f->txtlines = f->charh ;
if ( strchr ( f->text, FF ) ) {
f->lines = 0 ;
nr = EOF ;
}
} else {
nr = EOF ;
}
}
if ( nr != EOF ) {
nr = texttorun ( (uchar*) f->text, f->font, f->charh - f->txtlines,
f->charw, f->charh, f->lmargin,
runs, pels ) ;
f->txtlines-- ;
}
break ;
case P_RAW:
case P_PBM:
if ( fread ( bits, 1, f->page->w/8, f->f ) != f->page->w/8 ) {
nr = EOF ;
} else {
nr = bittorun ( bits, f->page->w/8, runs ) ;
if ( pels ) *pels = f->page->w ;
}
break ;
case P_FAX:
nr = readruns ( f, runs, pels ) ;
break ;
case P_PCX:
nb = ( ( f->page->w + 15 ) / 16 ) * 2 ;
if ( readpcx ( bits, nb, f ) != 0 ) {
nr = EOF ;
} else {
nr = bittorun ( bits, nb, runs ) ;
if ( pels ) *pels = f->page->w ;
}
break ;
}
} else {
nr = EOF ;
}
if ( nr >= 0 && f->page->black_is_zero ) {
nr = xinvert ( runs, nr ) ;
}
if ( nr >= 0 && f->lines > 0 ) f->lines-- ;
return nr ;
}
int getformat ( uchar *p, int n )
{
int format = 0 ;
if ( ! format && n < 2 ) {
format = I_TEXT ;
msg ( "W only read %d byte(s) from input file, assuming text", n ) ;
}
if ( ! format && ! p[0] && ! ( p[1] & 0xe0 ) ) {
format = I_FAX ;
}
if ( ! format && ! strncmp ( p, "P4", 2 ) ) {
format = I_PBM ;
}
if ( ! format && n >= 128 && p[0] == 0x0a &&
strchr ("\02\03\05", p[1] ) && p[2] <= 1 ) {
if ( p[65] != 1 ) {
msg ( "E can't read colour PCX" ) ;
} else {
format = p[2] ? I_PCX : I_PCX ;
}
}
if ( ! format && ! strncmp ( p, "%!", 2 ) ) {
msg ( "W Postscript input file will be treated as text" ) ;
}
if ( ! format && ( p[0] == 'M' || p[1] == 'I' ) && ( p[1] == p[0] ) ) {
format = I_TIFF ;
}
if ( ! format &&
( p[0] == 0x3a && p[1] == 0xde &&
p[2] == 0x68 && p[3] == 0xb1) ) {
format = I_DCX ;
}
if ( ! format && n ) {
int i, nprint = 0 ;
for ( i=0 ; i<n ; i++ ) {
if ( isspace ( p[i] ) || isprint ( p[i] ) ) {
nprint++ ;
}
}
if ( ( nprint / (float) n ) > 0.90 ) {
format = I_TEXT ;
}
}
return format ;
}
void page_init ( PAGE *p, char *fn )
{
p->fname = fn ;
p->offset = 0 ;
p->w = DEFWIDTH ;
p->h = DEFHEIGHT ;
p->xres = DEFXRES ;
p->yres = DEFYRES ;
p->format = P_FAX ;
p->revbits = 0 ;
p->black_is_zero = 0 ;
}
void page_report ( PAGE *p, int fmt, int n )
{
msg ( "F page %d : %s + %ld : %dx%d @ %.fx%.f dpi %s/%s",
n,
p->fname, p->offset, p->w, p->h,
p->xres, p->yres,
iformatname [fmt], pformatname [p->format] ) ;
}
#define auto_first 0
#define auto_next 0
#define tiff_reset 0
char *tagname ( int tag )
{
static struct tagnamestruct { int code ; char *name ; }
tagnames [] = {
{ 256, "width" },
{ 257, "length" },
{ 258, "bits/sample" },
{ 259, "compresssion(g3=3)" },
{ 262, "photometric(0-min=white)" },
{ 266, "fill order(msb2lsb=1)" },
{ 273, "strip offsets" },
{ 274, "orientation(1=normal)" },
{ 277, "samples/pixel" },
{ 278, "rows/strip" },
{ 279, "strip byte counts" },
{ 282, "xresolution" },
{ 283, "yresolution" },
{ 284, "storage(1=single plane)" },
{ 292, "g3options" },
{ 296, "resolution units(2=in,3=cm)" },
{ 297, "page number" },
{ 327, "clean fax(0=clean/1=regen/2=errors)" },
{0,0} },
*p ;
for ( p=tagnames ; p->code ; p++ )
if ( tag == p->code ) break ;
return p->code ? p->name : "unknown tag" ;
}
int fread2 ( unsigned short *p, IFILE *f )
{
int err=0 ;
uchar c[2] ;
err = fread ( c, 1, 2, f->f ) == 2 ? 0 : 1 ;
*p = f->bigend ?
c[0] << 8 | c[1] << 0 :
c[1] << 8 | c[0] << 0 ;
return err ;
}
int fread4 ( unsigned long *p, IFILE *f )
{
int err=0 ;
uchar c[4] ;
err = fread ( c, 1, 4, f->f ) == 4 ? 0 : 1 ;
*p = f->bigend ?
c[0] << 24 | c[1] << 16 | c[2] << 8 | c[3] << 0 :
c[3] << 24 | c[2] << 16 | c[1] << 8 | c[0] << 0 ;
return err ;
}
int tiff_next ( IFILE *f )
{
int err=0 ;
unsigned short ntag, tag, type ;
unsigned long count, tv ;
double ftv ;
msg ( "F+ TIFF directory at %ld", ftell ( f->f ) ) ;
if ( fread2 ( &ntag, f ) ) {
err = msg ( "E2can't read TIFF tag count" ) ;
} else {
msg ( "F+ with %d tags", (int) ntag ) ;
}
for ( ; ! err && ntag > 0 ; ntag-- ) {
err = err || fread2 ( &tag, f ) ;
err = err || fread2 ( &type, f ) ;
err = err || fread4 ( &count, f ) ;
if ( type == 3 ) {
unsigned short a, b ;
err = err || fread2 ( &a, f ) ;
err = err || fread2 ( &b, f ) ;
tv = a ;
} else {
err = err || fread4 ( &tv, f ) ;
}
if ( type == 5 ) {
long a, b, where=0 ;
err = err || ( ( where = ftell ( f->f ) ) < 0 ) ;
err = err || fseek ( f->f, tv, SEEK_SET ) ;
err = err || fread4 ( &a, f ) ;
err = err || fread4 ( &b, f ) ;
err = err || fseek ( f->f, where, SEEK_SET ) ;
ftv = (float) a / ( b ? b : 1 ) ;
} else {
ftv = 0.0 ;
}
if ( err ) {
err = msg ( "ES2can't read TIFF tag" ) ;
continue ;
}
#ifdef TIFF_DEBUG
{
char *tagtype[] = { "none", "byte", "ascii", "short", "long", "ratio" } ;
msg ( "F %3d %-5s tag %s %5ld (%3d:%s)",
count,
type <= 5 ? tagtype[type] : "other",
count > 1 ? "@" : "=",
type == 5 ? (long) ftv : tv, tag, tagname(tag) ) ;
}
#endif
switch ( tag ) {
case 256 :
f->page->w = tv ;
break ;
case 257 :
f->page->h = tv ;
break ;
case 259 :
if ( tv == 1 ) {
f->page->format = P_RAW ;
} else if ( tv == 3 ) {
f->page->format = P_FAX ;
} else {
err = msg ( "E2can only read TIFF/G3 or TIFF/uncompressed" ) ;
}
break ;
case 262 :
f->page->black_is_zero = tv ;
break ;
case 266 :
f->page->revbits = ( tv == 2 ? 1 : 0 ) ;
break ;
case 273 :
if ( count != 1 )
err = msg ( "E2can't read multi-strip TIFF files" ) ;
else
f->page->offset = tv ;
break ;
case 282 :
f->page->xres = ftv ;
break ;
case 283 :
f->page->yres = ftv ;
break ;
case 292 :
if ( tv & 0x1 )
err = msg ( "E2can't read 2D compressed TIFF-F file" ) ;
if ( tv & 0x2 )
err = msg ( "E2can't read uncompressed TIFF-F file" ) ;
break ;
case 296 :
if ( tv == 3 ) {
f->page->xres *= 2.54 ;
f->page->yres *= 2.54 ;
}
break ;
}
}
if ( f->page->format == I_AUTO ) {
msg ( "W missing TIFF compression format, set to raw" ) ;
f->page->format = P_RAW ;
}
if ( ! err ) {
if ( fread4 ( &(f->next), f ) ) {
err = msg ( "E2can't read offset to next TIFF directory" ) ;
} else {
if ( f->next ) {
msg ( "F , next directory at %ld.", f->next ) ;
if ( fseek ( f->f, f->next, SEEK_SET ) )
err = msg ( "ES2 seek to next TIFF directory failed" ) ;
} else {
msg ( "F , last image." ) ;
}
}
}
if ( ! f->page->offset )
err = msg ( "E2 missing offset to TIFF data" ) ;
return err ;
}
int tiff_first ( IFILE *f )
{
short magic, version ;
fread ( (uchar*) &magic, 1, 2, f->f ) ;
f->bigend = ( *(uchar*) &magic == 'M' ) ? 1 : 0 ;
fread2 ( &version, f ) ;
fread4 ( &(f->next), f ) ;
msg ( "F TIFF version %d.%d file (%s-endian)",
version/10, version%10, f->bigend ? "big" : "little" ) ;
fseek ( f->f, f->next, SEEK_SET ) ;
return tiff_next ( f ) ;
}
int text_next ( IFILE *f )
{
int err = 0, i, nc ;
char buf [ MAXLINELEN ] ;
f->page->offset = ftell ( f->f ) ;
f->page->format = P_TEXT ;
nc = ( f->page->w - f->lmargin ) / f->charw ;
if ( nc > MAXLINELEN )
nc = MAXLINELEN ;
for ( i = 0 ; i < f->pglines && fgets ( buf, nc, f->f ) ; i++ ) ;
f->next = ! feof(f->f) ? ftell ( f->f ) : 0 ;
err = ferror(f->f) ? 2 : 0 ;
return err ;
}
int text_first ( IFILE *f )
{
static faxfont defaultfont ;
if ( ! f->font ) {
f->font = &defaultfont ;
readfont ( 0, f->font ) ;
if ( ! f->charw ) f->charw = 2 * f->font->w ;
if ( ! f->charh ) f->charh = 2 * f->font->h ;
if ( ! f->lmargin ) f->lmargin = 204 ;
if ( ! f->pglines ) f->pglines = DEFPGLINES ;
}
if ( ! f->charw ) f->charw = f->font->w ;
if ( ! f->charh ) f->charh = f->font->h ;
if ( ! f->lmargin ) f->lmargin = 0 ;
if ( ! f->pglines ) f->pglines = f->page->h / f->charh - 6 ;
return text_next ( f ) ;
}
int pbm_first ( IFILE *f )
{
int err=0 ;
fseek ( f->f, 2, SEEK_SET ) ;
if ( ! ( f->page->w = pbmdim ( f ) ) || ! ( f->page->h = pbmdim ( f ) ) ) {
err = msg ( "E2 EOF or 0 dimension in PBM header" ) ;
} else if ( f->page->w % 8 ) {
err = msg ( "E2 PBM width must be multiple of 8" ) ;
} else {
msg ( "F read %dx%d PBM header", f->page->w, f->page->h ) ;
}
f->page->offset = ftell ( f->f ) ;
f->page->format = P_PBM ;
f->next = 0 ;
return err ;
}
#define pbm_next 0
#define fax_first 0
#define fax_next 0
int fgeti ( IFILE *f )
{
return fgetc ( f->f ) + fgetc ( f->f ) * 256 ;
}
int pcx_first ( IFILE *f )
{
int err=0, xmin, xmax, ymin, ymax, nc, nb ;
long start ;
start = ftell ( f->f ) ;
fseek ( f->f, start+4, SEEK_SET ) ;
xmin = fgeti ( f ) ;
ymin = fgeti ( f ) ;
xmax = fgeti ( f ) ;
ymax = fgeti ( f ) ;
f->page->w = xmax - xmin + 1 ;
f->page->h = ymax - ymin + 1 ;
f->page->xres = fgeti ( f ) ;
f->page->yres = fgeti ( f ) ;
fseek ( f->f, start+0x41, SEEK_SET ) ;
nc = fgetc ( f->f ) ;
nb = fgeti ( f ) ;
if ( nc != 1 )
msg ( "W mono PCX file has %d colour planes", nc ) ;
if ( nb != ( f->page->w + 15 ) / 16 * 2 )
msg ( "W PCX file has %d bytes per scan line for %d pels",
nb, f->page->w ) ;
f->page->offset = start + 128 ;
f->page->format = P_PCX ;
return err ;
}
#define pcx_next 0
int dcx_next ( IFILE *f )
{
int err=0 ;
long thisp, nextp ;
fseek ( f->f, f->next, SEEK_SET ) ;
fread4 ( &thisp, f ) ;
fread4 ( &nextp, f ) ;
f->next = nextp ? f->next + 4 : 0 ;
if ( ! thisp )
err = msg ( "E2 can't happen (dcx_next)" ) ;
else
fseek ( f->f, thisp, SEEK_SET ) ;
return err ? err : pcx_first ( f ) ;
}
int dcx_first ( IFILE *f )
{
f->bigend = 0 ;
f->next = 4 ;
return dcx_next ( f ) ;
}
#define raw_reset 0
#define raw_first 0
#define raw_next 0
#define pcx_reset 0
#define pbm_reset 0
int text_reset ( IFILE *f )
{
int err=0 ;
f->lines = ( ( f->pglines * f->charh ) / f->charh ) * f->charh ;
f->txtlines = 0 ;
f->page->yres = f->lines > 1078 ? 196 : 98 ;
return err ;
}
int fax_reset ( IFILE *f )
{
int pels ;
short runs [ MAXRUNS ] ;
newDECODER ( &f->d ) ;
if ( readruns ( f, runs, &pels ) < 0 || pels )
msg ( "W first line has %d pixels: probably not fax data", pels ) ;
switch ( f->fileformat ) {
case I_TIFF:
break ;
case I_FAX:
default:
f->lines = -1 ;
}
return 0 ;
}
int nextipage ( IFILE *f, int dp )
{
int err=0 ;
int ( *reset [NPFORMATS] ) ( IFILE * ) = {
raw_reset, fax_reset, pbm_reset, text_reset, pcx_reset
}, (*pf)(IFILE*) ;
if ( f->f ) {
fclose ( f->f ) ;
f->f = 0 ;
}
if ( dp ) {
f->page++ ;
}
if ( f->page > f->lastpage ) {
err = 1 ;
}
if ( ! err ) {
f->f = fopen ( f->page->fname, (f->page->format == P_TEXT) ? "r" : "rb" ) ;
if ( ! f->f )
err = msg ( "ES2can't open %s:", f->page->fname ) ;
}
if ( ! err && fseek ( f->f, f->page->offset, SEEK_SET ) )
err = msg ( "ES2 seek failed" ) ;
f->lines = f->page->h ;
if ( ! err ) {
pf = reset[f->page->format] ;
if ( pf )
err = (*pf)(f) ;
}
return err ;
}
int lastpage ( IFILE *f )
{
return f->page >= f->lastpage ;
}
#define dfax_first 0
#define dfax_next 0
int newIFILE ( IFILE *f, char **fnames )
{
int err=0, i, n;
char **p ;
uchar buf[128] ;
int ( *fun ) ( IFILE * ) ;
int ( *first [NIFORMATS] ) ( IFILE * ) = {
auto_first, pbm_first, fax_first, text_first, tiff_first,
dfax_first, pcx_first, raw_first, dcx_first
} ;
int ( *next [NIFORMATS] ) ( IFILE * ) = {
auto_next, pbm_next, fax_next, text_next, tiff_next,
dfax_next, pcx_next, raw_next, dcx_next
} ;
f->fileformat = 0;
f->page = f->pages ;
for ( p=fnames ; ! err && *p ; p++ ) {
if ( ! ( f->f = fopen ( *p, "rb" ) ) )
err = msg ( "ES2 can't open %s:", *p ) ;
if ( ! err ) {
n = fread ( buf, 1, 128, f->f ) ;
if ( ferror ( f->f ) )
err = msg ( "ES2 can't open %s:", *p ) ;
}
if ( ! err ) {
f->fileformat = getformat ( buf, n ) ;
if ( ! f->fileformat )
err = msg ( "E2 can't get format of %s", *p ) ;
}
if ( ! err && fseek ( f->f, 0, SEEK_SET ) )
err = msg ( "ES2 can't rewind %s:", *p ) ;
for ( i=0 ; ! err ; i++ ) {
page_init ( f->page, *p ) ;
if ( ( fun = i ? next[f->fileformat] : first[f->fileformat] ) )
err = (*fun)(f) ;
if ( ! err ) {
page_report ( f->page, f->fileformat, f->page - f->pages + 1 ) ;
f->page++ ;
if ( f->page >= f->pages + MAXPAGE )
err = msg ( "E2 too many pages (max is %d)", MAXPAGE ) ;
}
if ( ! f->next ) break ;
}
if ( f->f ) {
fclose ( f->f ) ;
f->f = 0 ;
}
}
f->lastpage = f->page - 1 ;
f->page = f->pages ;
if ( ! normalbits[1] ) initbittab() ;
return err ;
}
char *PCLBEGIN =
"\033E"
"\033&l0E"
"\033&a0L"
"\033*t%dR"
"\033*r1A" ;
char *PCLEND =
"\033*rB"
"\014"
"\033E" ;
void pclwrite ( OFILE *f, unsigned char *buf, int n )
{
while ( n > 0 && buf [ n-1 ] == 0 ) n-- ;
fprintf( f->f, "\033*b%dW", n ) ;
fwrite ( buf, n, 1, f->f ) ;
}
void pgmwrite ( OFILE *f, uchar *buf, int n )
{
static uchar gval [ MAXBITS * 8 / 4 ] ;
static int init=0, lines=0 ;
static uchar hbits [ 256 ], lbits [ 256 ] ;
static int nybblecnt [ 16 ] = { 0,1,1,2, 1,2,2,3, 1,2,2,3, 2,3,3,4 } ;
static uchar corr [ 17 ] = { 255, 239, 223, 207, 191, 175, 159, 143, 127,
111, 95, 79, 63, 47, 31, 15, 0 } ;
int m ;
uchar *p, *q ;
if ( ! init ) {
short i ;
for ( i=0 ; i<256 ; i++ ) {
hbits [ i ] = nybblecnt [ i >> 4 & 0x0f ] ;
lbits [ i ] = nybblecnt [ i & 0x0f ] ;
}
init = 1 ;
}
for ( m=n, p=gval, q=buf ; m-- > 0 ; q++ ) {
*p++ += hbits [ *q ] ;
*p++ += lbits [ *q ] ;
}
if ( ( lines++ & 0x03 ) == 0x03 ) {
for ( p=gval, m=2*n ; m-- > 0 ; p++ ) *p = corr [ *p ] ;
fwrite ( gval, 1, 2*n, f->f ) ;
memset ( gval, 0, 2*n ) ;
}
}
const char PSBEGIN [] =
"%%!PS-Adobe-2.0 EPSF-2.0 \n"
"%%%%Creator: efax (Copyright 1995 Ed Casas) \n"
"%%%%Title: efix output\n"
"%%%%Pages: (atend) \n"
"%%%%BoundingBox: 0 0 %d %d \n"
"%%%%BeginComments \n"
"%%%%EndComments \n"
"/val 1 string def \n"
"/buf %d string def \n"
"/getval { \n"
" currentfile val readhexstring pop 0 get \n"
"} bind def \n"
"/readbuf { \n"
" 0 %% => index \n"
" { \n"
" dup buf length ge { exit } if \n"
" getval %% => index run_length \n"
" dup 127 le { \n"
" dup 0 eq { \n"
" pop buf length \n"
" } { \n"
" currentfile buf 3 index 3 index getinterval readhexstring pop pop\n"
" } ifelse \n"
" } { \n"
" dup 255 eq { \n"
" pop getval getval %% => index run_length value \n"
" 2 index 1 3 index 2 index add 1 sub %% => ... start 1 end \n"
" { buf exch 2 index put } for \n"
" pop \n"
" } { \n"
" 127 sub \n"
" } ifelse \n"
" } ifelse \n"
" add %% => index \n"
" } loop \n"
" pop \n"
" buf \n"
"} bind def \n"
"%%%%EndProlog \n" ;
const char PSPAGE [] =
"%%%%Page: %d %d \n"
"gsave \n"
"%f %f translate \n"
"%f %f scale \n"
"%d %d %d [ %d %d %d %d %d %d ] { readbuf } image \n" ;
const char PSPAGEEND [] =
"\n"
"grestore \n"
"showpage \n" ;
const char PSEND [] =
"%%Trailer \n"
"%%%%Pages: %d \n" ;
void psinit ( OFILE *f, int newfile, int page, int w, int h, int n )
{
float ptw, pth ;
if ( ! f ) {
msg ( "E2 can't happen (psinit)" ) ;
return ;
}
ptw = w/f->xres * 72.0 ;
pth = h/f->yres * 72.0 ;
if ( newfile )
fprintf ( f->f, PSBEGIN,
(int) ptw, (int) pth,
n ) ;
fprintf ( f->f, PSPAGE,
page, page,
0.0, 0.0,
ptw, pth,
w, h, 1,
w, 0, 0, -h, 0, h ) ;
f->pslines = 0 ;
f->lastpageno = page ;
}
char nhexout = 0, hexchars [ 16 ] = "0123456789abcdef" ;
#define hexputc( f, c ) ( \
putc ( hexchars [ (c) >> 4 ], f ), \
putc ( hexchars [ (c) & 0x0f ], f ), \
( ( ( nhexout++ & 31 ) == 31 ) ? putc ( '\n', f ) : 0 ) )
void hexputs ( FILE *f, uchar *p, int n )
{
uchar c ;
if ( n > 0 ) {
hexputc ( f, n ) ;
while ( n-- ) { c = *p++ ^ 0xff ; hexputc ( f, c ) ; }
}
}
void pswrite ( OFILE *f, unsigned char *buf, int n )
{
int i, j, l ;
static unsigned char last [ MAXBITS ] ;
l=i=0 ;
if ( ! f || ! buf || n<0 ) {
msg ( "E2 can't happen (pswrite)" ) ;
return ;
}
for ( j=0 ; j<n && buf[j]==last[j] && f->pslines ; j++ ) ;
if ( j == n ) {
hexputc ( f->f, 0 ) ;
l=i=n ;
}
while ( i<n ) {
for ( j=i ; j<n && buf[j]==last[j] && j-i<127 && f->pslines ; j++ ) ;
if ( j-i > 2 ) {
hexputs ( f->f, buf+l, i-l ) ;
hexputc ( f->f, j-i + 127 ) ;
l=i=j ;
} else {
for ( j=i ; j<n && buf[j]==buf[i] && j-i<255 ; j++ ) ;
if ( j-i > 4 ) {
hexputs ( f->f, buf+l, i-l ) ;
hexputc ( f->f, 255 ) ;
hexputc ( f->f, j-i ) ;
hexputc ( f->f, buf[i] ^ 0xff ) ;
l=i=j ;
} else {
if ( i-l >= 127 ) {
hexputs ( f->f, buf+l, i-l ) ;
l=i ;
} else {
i++ ;
}
}
}
}
hexputs ( f->f, buf+l, i-l ) ;
if ( n >= 0 )
memcpy ( last, buf, n ) ;
f->pslines++ ;
}
int fwrite2 ( short s, OFILE *f )
{
uchar *p = (void*) &s ;
return fwrite ( bigendian ? p + sizeof(short) - 2 : p, 2, 1, f->f ) ;
}
int fwrite4 ( long l, OFILE *f )
{
uchar *p = (void*) &l ;
return fwrite ( bigendian ? p + sizeof(long ) - 4 : p, 4, 1, f->f ) ;
}
int wtag ( OFILE *f, int lng, short tag, short type, long count, long offset )
{
int err=0 ;
err = err || ! fwrite2 ( tag, f ) ;
err = err || ! fwrite2 ( type, f ) ;
err = err || ! fwrite4 ( count, f ) ;
if ( lng ) {
err = err || ! fwrite4 ( offset, f ) ;
} else {
err = err || ! fwrite2 ( offset, f ) ;
err = err || ! fwrite2 ( 0, f ) ;
}
if ( err ) msg ( "ES2 can't write TIFF tag" ) ;
return err ;
}
#define NTAGS 17
#define NRATIO 2
int tiffinit ( OFILE *f )
{
int err=0, compr=1 ;
long tdoff, doff ;
fseek ( f->f, 0, SEEK_SET ) ;
fwrite2 ( bigendian ? 0x4d4d : 0x4949, f ) ;
fwrite2 ( 42, f ) ;
fwrite4 ( 8, f ) ;
fwrite2 ( NTAGS, f ) ;
tdoff = 8 + 2 + NTAGS*12 + 4 ;
doff = tdoff + NRATIO*8 ;
switch ( f->format ) {
case O_TIFF_RAW: compr = 1 ; break ;
case O_TIFF_FAX: compr = 3 ; break ;
default: err = msg ( "E2can't happen(tiffinit)" ) ; break ;
}
wtag( f, 1, 256, 4, 1, f->w ) ;
wtag( f, 1, 257, 4, 1, f->h ) ;
wtag( f, 0, 258, 3, 1, 1 ) ;
wtag( f, 0, 259, 3, 1, compr ) ;
wtag( f, 0, 262, 3, 1, 0 ) ;
wtag( f, 0, 266, 3, 1, 1 ) ;
wtag( f, 1, 273, 4, 1, doff ) ;
wtag( f, 0, 274, 3, 1, 1 ) ;
wtag( f, 0, 277, 3, 1, 1 ) ;
wtag( f, 1, 278, 4, 1, f->h ) ;
wtag( f, 1, 279, 4, 1, f->bytes ) ;
wtag( f, 1, 282, 5, 1, tdoff+0 ) ;
wtag( f, 1, 283, 5, 1, tdoff+8 ) ;
wtag( f, 0, 284, 3, 1, 1 ) ;
wtag( f, 1, 292, 4, 1, 0 ) ;
wtag( f, 0, 296, 3, 1, 2 ) ;
wtag( f, 0, 327, 3, 1, 0 ) ;
fwrite4 ( 0, f ) ;
fwrite4 ( f->xres+0.5, f ) ;
fwrite4 ( 1, f ) ;
fwrite4 ( f->yres+0.5, f ) ;
fwrite4 ( 1, f ) ;
return err ;
}
int runtobit ( short *runs, int nr, uchar *buf )
{
static uchar zerofill [ 9 ] = {
0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00 } ;
static uchar onefill [ 9 ] = {
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff } ;
uchar col=0, *buf0 = buf ;
register short len, b=8, bytes ;
while ( nr-- > 0 ) {
len = *runs++ ;
if ( col ) *buf |= onefill [ b ] ;
else *buf &= zerofill [ b ] ;
if ( b > len ) {
b -= len ;
} else {
len -= b ;
buf++ ;
b = 8 ;
if ( ( bytes = len>>3 ) > 0 ) {
memset ( buf, col, bytes ) ;
len -= bytes*8;
buf += bytes ;
}
*buf = col ;
b -= len ;
}
col ^= 0xff ;
}
return buf - buf0 + ( b < 8 ) ;
}
int fputi ( int i, OFILE *f )
{
putc ( i & 0xff, f->f ) ;
putc ( ( i >> 8 ) & 0xff, f->f ) ;
return 0 ;
}
void pcxinit ( OFILE *f )
{
uchar buf [ 60 ] = { 0x0a, 3, 1, 1 } ;
fwrite ( buf, 1, 4, f->f ) ;
fputi ( 0, f ) ;
fputi ( 0, f ) ;
fputi ( f->w-1, f ) ;
fputi ( f->h-1, f ) ;
fputi ( f->xres, f ) ;
fputi ( f->yres, f ) ;
memset ( buf, 0, 48 ) ;
fwrite ( buf, 1, 48, f->f ) ;
putc ( 0, f->f ) ;
putc ( 1, f->f ) ;
fputi ( (f->w+15)/16*2, f ) ;
memset ( buf, 0, 60 ) ;
fwrite ( buf, 1, 60, f->f ) ;
}
void pcxwrite ( OFILE *of, uchar *p, int nb )
{
int c, n, runc ;
FILE *f = of->f ;
runc = *p++ ;
n = 1 ;
for ( nb-- ; nb > 0 ; nb-- ) {
c = *p++ ;
if ( c == runc && n < 63 ) {
n++ ;
} else {
if ( n > 1 || ( ( runc & 0xc0 ) == 0xc0 ) )
putc ( n | 0xc0, f ) ;
putc ( runc, f ) ;
runc = c ;
n = 1 ;
}
}
if ( n > 1 || ( ( runc & 0xc0 ) == 0xc0 ) )
putc ( n | 0xc0, f ) ;
putc ( runc, f ) ;
}
int nextopage ( OFILE *f, int page )
{
int err = 0 ;
int i, nb=0 ;
uchar *p, codes [ ( RTCEOL * EOLBITS ) / 8 + 3 ] ;
if ( f->f ) {
switch ( f->format ) {
case O_PBM:
break ;
case O_PGM:
break ;
case O_FAX:
case O_TIFF_FAX:
for ( p = codes, i=0 ; i<RTCEOL ; i++ )
p = putcode ( &f->e, EOLCODE, EOLBITS, p ) ;
nb = putcode ( &f->e, 0, 0, p ) - codes ;
fwrite ( codes, 1, nb, f->f ) ;
f->bytes += nb ;
if ( f->format == O_TIFF_FAX ) tiffinit ( f ) ;
break ;
case O_TIFF_RAW:
tiffinit(f) ;
break ;
case O_PCL:
fprintf ( f->f, PCLEND ) ;
break ;
case O_PS:
fprintf ( f->f, PSPAGEEND ) ;
if ( f->fname || page<0 ) fprintf ( f->f, PSEND, f->lastpageno ) ;
break ;
case O_PCX:
case O_PCX_RAW:
fseek ( f->f, 0, SEEK_SET ) ;
pcxinit ( f ) ;
break ;
}
if ( ferror ( f->f ) ) {
err = msg ("ES2output error:" ) ;
} else {
msg ( "F+ wrote %s as %dx%d pixel %.fx%.f dpi %s page",
f->cfname, f->w, f->h, f->xres, f->yres,
oformatname [f->format] ) ;
switch ( f->format ) {
case O_PS:
msg ( "F (%d lines)", f->pslines ) ;
break ;
case O_TIFF_RAW:
case O_TIFF_FAX:
msg ( "F (%d bytes)", f->bytes ) ;
break ;
default:
msg ( "F " ) ;
break ;
}
}
}
if ( ! err && page >= 0 ) {
if ( f->fname ) {
sprintf ( f->cfname, f->fname, page+1, page+1, page+1 ) ;
if ( ! f->f )
f->f = fopen ( f->cfname, ( f->format == O_PS ) ? "w" : "wb+" ) ;
else
f->f = freopen ( f->cfname, ( f->format == O_PS ) ? "w" : "wb+", f->f ) ;
if ( ! f->f ) {
err = msg ("ES2can't open output file %s:", f->cfname ) ;
}
} else {
f->f = stdout ;
strcpy ( f->cfname, "standard output" ) ;
}
}
if ( ! err && page >= 0 ) {
switch ( f->format ) {
case O_PBM:
fprintf ( f->f, "P4 %d %d\n", f->w, f->h ) ;
break ;
case O_PGM:
fprintf ( f->f, "P5 %d %d %d\n", f->w/4, f->h/4, 255 ) ;
break ;
case O_FAX:
case O_TIFF_FAX:
if ( f->format == O_TIFF_FAX ) tiffinit ( f ) ;
p = putcode ( &f->e, EOLCODE, EOLBITS, codes ) ;
nb = p - codes ;
fwrite ( codes, 1, nb, f->f ) ;
break ;
case O_TIFF_RAW:
tiffinit ( f ) ;
break ;
case O_PCL:
fprintf ( f->f, PCLBEGIN, (int) f->xres ) ;
break ;
case O_PS:
psinit ( f, ( f->fname || page==0 ), page+1, f->w, f->h, f->w/8 ) ;
break ;
case O_PCX:
case O_PCX_RAW:
fseek ( f->f, 0, SEEK_SET ) ;
pcxinit ( f ) ;
break ;
}
if ( ferror ( f->f ) ) err = msg ("ES2output error:" ) ;
}
switch ( f->format ) {
case O_FAX:
case O_TIFF_FAX:
case O_PCX:
case O_PCX_RAW:
f->h = 0 ;
f->bytes = nb ;
break ;
}
return err ;
}
void writeline ( OFILE *f, short *runs, int nr, int no )
{
int nb = 0 ;
uchar *p, buf [ MAXCODES ] ;
if ( no > 0 )
switch ( f->format ) {
case O_PBM:
case O_PGM:
case O_PCL:
case O_PS:
case O_TIFF_RAW:
case O_PCX:
case O_PCX_RAW:
nb = runtobit ( runs, nr, buf ) ;
break ;
case O_FAX:
case O_TIFF_FAX:
break ;
}
while ( no-- > 0 ) {
switch ( f->format ) {
case O_PCX_RAW:
case O_TIFF_RAW:
case O_PBM:
fwrite ( buf, 1, nb, f->f ) ;
break ;
case O_PGM:
pgmwrite ( f, buf, nb ) ;
break ;
case O_TIFF_FAX:
case O_FAX:
p = runtocode ( &f->e, runs, nr, buf ) ;
p = putcode ( &f->e, EOLCODE, EOLBITS, p ) ;
nb = p - buf ;
fwrite ( buf, 1, nb, f->f ) ;
break ;
case O_PCL:
pclwrite ( f, buf, nb ) ;
break ;
case O_PS:
pswrite ( f, buf, nb ) ;
break ;
case O_PCX:
pcxwrite ( f, buf, nb ) ;
break ;
}
switch ( f->format ) {
case O_FAX:
case O_TIFF_FAX:
case O_TIFF_RAW:
case O_PCX:
case O_PCX_RAW:
f->h++ ;
f->bytes += nb ;
break ;
}
}
}
void newOFILE ( OFILE *f, int format, char *fname,
float xres, float yres, int w, int h )
{
f->f = 0 ;
f->format = format ;
f->fname = fname ;
f->xres = xres ;
f->yres = yres ;
f->w = w ;
f->h = h ;
f->bytes = 0 ;
newENCODER ( &f->e ) ;
}
int readfont ( char *fname, faxfont *font )
{
int err=0, i, j, n=0, nr, nb, fontok=0, pels ;
char *fnames [2] = { 0, 0 } ;
short runs [ MAXRUNS ] ;
IFILE f;
if ( fname && *fname ) {
fnames[0] = fname ;
newIFILE ( &f, fnames ) ;
if ( nextipage ( &f, 0 ) ) {
err = msg ( "E2 can't open font file %s", fnames[0] ) ;
}
nb = 0 ;
while ( ! err && ( nr = readline ( &f, runs, &pels ) ) >= 0 ) {
if ( nb+pels/8 < MAXFONTBUF ) {
nb += runtobit ( runs, nr, font->buf+nb ) ;
} else {
err = msg ("E2font file %s too large (max %d bytes)",
fnames[0], MAXFONTBUF ) ;
}
}
if ( ! err && nb != f.page->w * f.page->h / 8 )
err = msg ( "E2 read %d bytes of font data for %dx%d bitmap",
nb, f.page->w, f.page->h ) ;
if ( ! err && ( f.page->w / 256 > MAXFONTW || f.page->h > MAXFONTH ) ) {
err = msg ( "E2font size (%dx%d) too large", f.page->w, f.page->h ) ;
}
if ( err ) {
font->w = font->h = 0 ;
} else {
font->w = f.page->w / 256 ;
font->h = f.page->h ;
for ( i=0 ; i<256 ; i++ ) font->offset[i] = i*font->w ;
msg ("Iread %dx%d font %s (%d bytes)", font->w, font->h, fname, nb ) ;
fontok = 1 ;
}
if ( f.f ) {
fclose ( f.f ) ;
f.f = 0 ;
}
}
if ( ! fontok ) {
font->w = STDFONTW ;
font->h = STDFONTH ;
for ( i=j=0 ; j<STDFONTBUF ; i++ )
if ( stdfont [ i ] == 0 )
for ( n = stdfont [ ++i ] ; n > 0 ; n-- )
font->buf [ j++ ] = 0 ;
else
font->buf [ j++ ] = stdfont [ i ] ;
if ( i != 1980 ) err = msg ( "E2can't happen(readfont)" ) ;
for ( i=0 ; i<256 ; i++ ) font->offset[i] = i*font->w ;
}
return err ;
}
void initbittab ( void )
{
int i ;
for ( i=0 ; i<256 ; i++ )
normalbits [ reversebits [ i ] = i ] =
( i& 1 ? 128:0 ) | ( i& 2 ? 64:0 ) | ( i& 4 ? 32:0 ) | ( i& 8 ? 16:0 ) |
( i&16 ? 8:0 ) | ( i&32 ? 4:0 ) | ( i&64 ? 2:0 ) | ( i&128 ? 1:0 ) ;
}
dtab tw1 [ 512 ], tw2 [ 512 ], tb1 [ 512 ], tb2 [ 512 ], fill [ 512 ] ;
char tabinit=0 ;
void addcode ( dtab *tab, int cword, int shift,
short code, short bits, dtab *next )
{
int i, n = 1 << shift ;
for ( i = cword << shift ; n-- > 0 ; i++ ) {
tab[i].code = code ;
tab[i].bits = bits ;
tab[i].next = next ;
}
}
void init1dtab ( t4tab *p0, dtab *t1, dtab *t2, dtab *ot )
{
t4tab *p ;
for ( p = p0 ; p->code ; p++ )
if ( p->bits <= 9 ) {
addcode ( t1, p->code, 9 - p->bits, p->rlen + 1, p->bits,
( p - p0 ) > 63 ? t1 : ot ) ;
} else {
addcode ( t1, p->code >> ( p->bits - 9 ), 0, 0, 4, t2 ) ;
addcode ( t2, p->code, 13 - p->bits, p->rlen + 1, p->bits - 4,
( p - p0 ) > 63 ? t1 : ot ) ;
}
}
void newDECODER ( DECODER *d )
{
int i ;
if ( ! tabinit ) {
addcode ( tw1, 0, 9, 0, 1, tw1 ) ;
addcode ( tw2, 0, 9, 0, 1, tw1 ) ;
addcode ( tb1, 0, 9, 0, 1, tw1 ) ;
addcode ( tb2, 0, 9, 0, 1, tw1 ) ;
addcode ( fill, 0, 9, 0, 1, tw1 ) ;
addcode ( tw1, 0, 0, 0, 4, tw2 ) ;
addcode ( tw2, 0, 2, 0, 7, fill ) ;
addcode ( tb1, 0, 0, 0, 4, tb2 ) ;
addcode ( tb2, 0, 2, 0, 7, fill ) ;
addcode ( fill, 0, 0, 0, 9, fill ) ;
for ( i=0 ; i<=8 ; i++ )
addcode ( fill, 1, i, -1, 9-i, tw1 ) ;
init1dtab ( wtab, tw1, tw2, tb1 ) ;
init1dtab ( btab, tb1, tb2, tw1 ) ;
tabinit=1 ;
}
d->x = 0 ;
d->shift = -9 ;
d->tab = tw1 ;
d->eolcnt = 0 ;
}
t4tab wtab [ ( 64 + 27 + 13 ) + 1 ] = {
{53,8,0}, {7,6,1}, {7,4,2}, {8,4,3}, {11,4,4}, {12,4,5},
{14,4,6}, {15,4,7}, {19,5,8}, {20,5,9}, {7,5,10}, {8,5,11},
{8,6,12}, {3,6,13}, {52,6,14}, {53,6,15}, {42,6,16}, {43,6,17},
{39,7,18}, {12,7,19}, {8,7,20}, {23,7,21}, {3,7,22}, {4,7,23},
{40,7,24}, {43,7,25}, {19,7,26}, {36,7,27}, {24,7,28}, {2,8,29},
{3,8,30}, {26,8,31}, {27,8,32}, {18,8,33}, {19,8,34}, {20,8,35},
{21,8,36}, {22,8,37}, {23,8,38}, {40,8,39}, {41,8,40}, {42,8,41},
{43,8,42}, {44,8,43}, {45,8,44}, {4,8,45}, {5,8,46}, {10,8,47},
{11,8,48}, {82,8,49}, {83,8,50}, {84,8,51}, {85,8,52}, {36,8,53},
{37,8,54}, {88,8,55}, {89,8,56}, {90,8,57}, {91,8,58}, {74,8,59},
{75,8,60}, {50,8,61}, {51,8,62}, {52,8,63},
{27,5,64}, {18,5,128}, {23,6,192}, {55,7,256}, {54,8,320}, {55,8,384},
{100,8,448}, {101,8,512}, {104,8,576}, {103,8,640}, {204,9,704}, {205,9,768},
{210,9,832}, {211,9,896}, {212,9,960}, {213,9,1024},{214,9,1088},{215,9,1152},
{216,9,1216},{217,9,1280},{218,9,1344},{219,9,1408},{152,9,1472},{153,9,1536},
{154,9,1600},{24,6,1664}, {155,9,1728},
{8,11,1792}, {12,11,1856},{13,11,1920},{18,12,1984},{19,12,2048},{20,12,2112},
{21,12,2176},{22,12,2240},{23,12,2304},{28,12,2368},{29,12,2432},{30,12,2496},
{31,12,2560},
{0,0,0} } ;
t4tab btab [ ( 64 + 27 + 13 ) + 1 ] = {
{55,10,0}, {2,3,1}, {3,2,2}, {2,2,3}, {3,3,4}, {3,4,5},
{2,4,6}, {3,5,7}, {5,6,8}, {4,6,9}, {4,7,10}, {5,7,11},
{7,7,12}, {4,8,13}, {7,8,14}, {24,9,15}, {23,10,16}, {24,10,17},
{8,10,18}, {103,11,19}, {104,11,20}, {108,11,21}, {55,11,22}, {40,11,23},
{23,11,24}, {24,11,25}, {202,12,26}, {203,12,27}, {204,12,28}, {205,12,29},
{104,12,30}, {105,12,31}, {106,12,32}, {107,12,33}, {210,12,34}, {211,12,35},
{212,12,36}, {213,12,37}, {214,12,38}, {215,12,39}, {108,12,40}, {109,12,41},
{218,12,42}, {219,12,43}, {84,12,44}, {85,12,45}, {86,12,46}, {87,12,47},
{100,12,48}, {101,12,49}, {82,12,50}, {83,12,51}, {36,12,52}, {55,12,53},
{56,12,54}, {39,12,55}, {40,12,56}, {88,12,57}, {89,12,58}, {43,12,59},
{44,12,60}, {90,12,61}, {102,12,62}, {103,12,63},
{15,10,64}, {200,12,128},{201,12,192},{91,12,256}, {51,12,320}, {52,12,384},
{53,12,448}, {108,13,512},{109,13,576},{74,13,640}, {75,13,704}, {76,13,768},
{77,13,832}, {114,13,896},{115,13,960},{116,13,1024},{117,13,1088},
{118,13,1152},
{119,13,1216},{82,13,1280},{83,13,1344},{84,13,1408},{85,13,1472},{90,13,1536},
{91,13,1600},{100,13,1664},{101,13,1728},
{8,11,1792}, {12,11,1856},{13,11,1920},{18,12,1984},{19,12,2048},{20,12,2112},
{21,12,2176},{22,12,2240},{23,12,2304},{28,12,2368},{29,12,2432},{30,12,2496},
{31,12,2560},
{0,0,0} } ;
uchar stdfont [ 1980 ] = {
0,255,0,255,0,194,8,4,12,10,18,0,3,16,4,8,20,8,4,8,20,0,1,10,8,4,
4,10,18,0,2,16,4,8,20,4,0,68,20,0,1,8,0,2,12,6,48,0,5,2,0,43,14,32,
56,0,2,12,0,1,32,0,1,2,0,1,14,0,1,32,8,4,32,56,0,14,6,8,48,0,40,8,
0,1,18,0,6,30,0,4,4,0,11,4,8,18,20,18,12,0,2,8,8,20,20,4,8,20,20,
0,1,20,4,8,10,20,18,0,2,8,8,20,20,8,0,1,24,8,4,8,10,20,12,0,2,8,4,
8,20,16,8,8,20,54,10,8,4,8,10,20,0,2,16,4,8,20,4,0,1,20,0,33,12,20,
18,28,48,12,12,8,8,8,0,4,2,28,8,28,28,4,62,28,62,28,28,0,5,60,28,
12,60,14,56,62,30,14,34,62,62,33,16,33,34,12,60,12,60,30,127,34,33,
65,34,34,62,8,32,8,8,0,1,24,0,1,32,0,1,2,0,1,16,0,1,32,8,4,32,8,0,
7,16,0,6,8,8,8,0,36,4,14,0,1,34,8,12,18,28,24,0,3,28,0,1,24,0,1,28,
28,8,0,1,30,0,2,8,28,0,1,100,100,98,0,6,18,31,14,0,8,56,0,7,13,0,
5,32,36,4,8,20,20,20,18,0,2,4,8,20,20,8,16,20,20,8,20,4,8,20,20,20,
0,2,8,8,20,20,8,32,20,0,33,12,20,18,42,73,18,24,8,8,42,8,0,3,4,34,
24,34,34,12,32,34,2,34,34,0,2,2,0,1,16,2,34,12,34,18,36,32,16,18,
34,8,8,34,16,51,50,18,34,18,34,32,8,34,33,73,34,34,2,8,16,8,8,0,1,
24,0,1,32,0,1,2,0,1,16,0,1,32,0,2,32,8,0,7,16,0,6,8,8,8,0,36,15,16,
65,34,8,18,0,1,34,4,0,3,34,0,1,36,8,2,2,0,2,58,0,2,56,34,0,1,36,36,
18,0,1,12,12,12,12,12,12,24,18,62,62,62,62,62,62,62,62,36,34,12,12,
12,12,12,0,1,18,34,34,34,34,34,32,36,0,5,12,0,10,52,0,6,8,0,6,32,
0,34,12,0,1,63,40,74,18,0,1,16,4,20,8,0,3,4,34,40,2,2,20,32,32,2,
34,34,24,24,4,0,1,8,2,78,18,34,32,34,32,16,32,34,8,8,36,16,51,50,
33,34,33,34,32,8,34,33,73,20,34,4,8,16,8,20,0,2,28,44,14,30,28,62,
30,44,56,60,34,8,82,44,28,44,30,22,30,62,34,34,65,34,34,62,8,8,8,
0,35,12,20,16,62,34,8,16,0,1,77,4,0,3,93,0,1,24,8,2,12,0,1,34,58,
0,2,8,34,0,1,40,40,100,4,12,12,12,12,12,12,40,32,32,32,32,32,8,8,
8,8,34,50,18,18,18,18,18,34,35,34,34,34,34,34,60,40,28,28,28,28,28,
28,54,14,28,28,28,28,56,56,56,56,2,44,28,28,28,28,28,8,29,34,34,34,
34,34,44,34,0,33,12,0,1,18,24,52,12,0,1,16,4,42,8,0,3,8,34,8,2,2,
36,60,32,4,34,34,24,24,8,127,4,2,82,18,34,32,34,32,16,32,34,8,8,40,
16,45,42,33,34,33,34,48,8,34,33,73,20,20,4,8,8,8,20,0,2,34,50,16,
34,34,16,34,50,8,4,36,8,109,50,34,50,34,24,32,16,34,34,73,34,34,2,
4,8,16,57,0,34,12,36,16,34,20,0,1,40,0,1,81,28,18,127,0,1,89,0,2,
127,12,2,0,1,34,58,28,0,1,8,34,36,40,40,24,4,18,18,18,18,18,18,40,
32,32,32,32,32,8,8,8,8,34,50,33,33,33,33,33,20,37,34,34,34,34,20,
34,40,34,34,34,34,34,34,9,16,34,34,34,34,8,8,8,8,30,50,34,34,34,34,
34,0,1,34,34,34,34,34,34,50,34,0,33,12,0,1,18,12,8,25,0,1,16,4,8,
127,0,1,127,0,1,8,34,8,4,12,68,2,60,8,28,30,0,2,16,0,1,2,28,82,18,
60,32,34,60,30,32,62,8,8,56,16,45,42,33,34,33,60,28,8,34,18,85,8,
20,8,8,8,8,34,0,2,2,34,32,34,34,16,34,34,8,4,40,8,73,34,34,34,34,
16,32,16,34,34,73,20,34,4,24,8,12,78,0,35,36,60,34,62,0,1,36,0,1,
81,36,36,1,28,85,0,2,8,16,2,0,1,34,26,28,0,1,8,34,18,18,22,106,0,
1,18,18,18,18,18,18,47,32,60,60,60,60,8,8,8,8,122,42,33,33,33,33,
33,8,45,34,34,34,34,20,34,36,2,2,2,2,2,2,9,32,34,34,34,34,8,8,8,8,
34,34,34,34,34,34,34,127,38,34,34,34,34,34,34,34,0,33,8,0,1,63,10,
22,37,0,1,16,4,0,1,8,0,3,8,34,8,8,2,126,2,34,8,34,2,0,2,8,127,4,16,
86,63,34,32,34,32,16,34,34,8,8,36,16,45,38,33,60,33,36,6,8,34,18,
54,20,8,16,8,8,8,34,0,2,30,34,32,34,62,16,34,34,8,4,56,8,73,34,34,
34,34,16,28,16,34,20,85,8,20,8,4,8,16,0,35,8,36,16,34,8,8,18,0,1,
81,26,72,1,0,1,34,0,2,8,30,28,0,1,34,10,28,0,1,8,28,9,22,17,22,4,
63,63,63,63,63,63,120,32,32,32,32,32,8,8,8,8,34,42,33,33,33,33,33,
20,41,34,34,34,34,8,34,34,30,30,30,30,30,30,63,32,62,62,62,62,8,8,
8,8,34,34,34,34,34,34,34,0,1,42,34,34,34,34,20,34,20,0,35,18,10,41,
34,0,1,16,4,0,1,8,0,3,16,34,8,16,2,4,2,34,16,34,2,0,2,4,0,1,8,0,1,
73,33,34,32,34,32,16,34,34,8,8,34,16,33,38,33,32,33,34,2,8,34,18,
34,20,8,16,8,4,8,0,3,34,34,32,34,32,16,38,34,8,4,36,8,73,34,34,34,
34,16,2,16,34,20,34,20,20,16,8,8,8,0,35,12,20,16,62,62,8,10,0,1,77,
0,1,36,1,0,1,28,0,6,34,10,0,4,18,42,34,42,28,33,33,33,33,33,33,72,
32,32,32,32,32,8,8,8,8,34,38,33,33,33,33,33,34,49,34,34,34,34,8,60,
34,34,34,34,34,34,34,72,32,32,32,32,32,8,8,8,8,34,34,34,34,34,34,
34,8,50,34,34,34,34,20,34,20,0,33,12,0,1,18,42,73,34,0,1,8,8,0,1,
8,12,0,1,24,16,34,8,32,34,4,34,34,16,34,34,24,24,2,0,1,16,16,32,33,
34,16,36,32,16,18,34,8,8,33,16,33,34,18,32,18,34,2,8,34,12,34,34,
8,32,8,4,8,0,3,34,34,16,38,34,16,26,34,8,4,34,8,73,34,34,34,38,16,
2,16,38,8,34,34,8,32,8,8,8,0,35,12,15,16,65,8,8,4,0,1,34,0,1,18,0,
5,127,0,3,54,10,0,4,36,79,68,79,32,33,33,33,33,33,33,72,16,32,32,
32,32,8,8,8,8,36,38,18,18,18,18,18,0,1,18,34,34,34,34,8,32,34,34,
34,34,34,34,34,72,16,34,34,34,34,8,8,8,8,34,34,34,34,34,34,34,8,34,
38,38,38,38,8,34,8,0,33,12,0,1,18,28,6,29,0,1,8,8,0,2,12,0,1,24,32,
28,8,62,28,4,28,28,16,28,28,24,24,0,3,16,28,33,60,14,56,62,16,14,
34,62,112,33,30,33,34,12,32,12,34,60,8,28,12,34,34,8,62,8,2,8,0,3,
29,60,14,26,28,16,2,34,8,4,33,8,73,34,28,60,26,16,60,14,26,8,34,34,
8,62,8,8,8,0,35,12,4,62,0,1,8,8,36,0,1,28,0,11,42,10,0,5,66,71,66,
32,33,33,33,33,33,33,79,14,62,62,62,62,62,62,62,62,56,34,12,12,12,
12,12,0,1,44,28,28,28,28,8,32,36,29,29,29,29,29,29,55,14,28,28,28,
28,8,8,8,8,28,34,28,28,28,28,28,0,1,92,26,26,26,26,8,60,8,0,36,8,
0,3,6,48,0,2,24,0,2,32,0,11,48,0,21,6,0,9,14,2,56,0,1,127,0,7,2,0,
2,4,0,5,32,2,0,7,16,0,1,6,8,48,0,35,12,0,4,8,24,0,13,32,10,0,1,4,
0,6,32,0,7,4,0,31,4,0,21,16,32,16,0,81,3,0,21,28,0,2,56,0,5,32,2,
0,7,48,0,39,12,0,19,32,0,2,24,0,6,30,0,7,24,0,31,24,0,21,48,32,48,
0,255,0,1
} ;