diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dvipsk/repack.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipsk/repack.c')
-rw-r--r-- | Build/source/texk/dvipsk/repack.c | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/repack.c b/Build/source/texk/dvipsk/repack.c new file mode 100644 index 00000000000..f3d518ef63c --- /dev/null +++ b/Build/source/texk/dvipsk/repack.c @@ -0,0 +1,446 @@ +/* + * Compressed TeX fonts in PostScript. + * By Radical Eye Software. + * (Slight mods by Don Knuth in December 89.) + */ +#include "dvips.h" /* The copyright notice in that file is included too! */ +#ifdef DEBUG +extern integer debug_flag; +#endif /* DEBUG */ + +/* Given a raster that has been unpacked from PK format, + * we compress it by another scheme that is suitable for + * a PostScript-oriented unpacking. We write instructions for + * a little interpreter whose one-byte instructions have the form + * 18*opcode+parameter. The interpreter forms each row based + * on simple transformations to the previous row. */ + +#define MAXOUT (18) +#define CMD(n) (MAXOUT*(n)) +#define ADVXCHG1 CMD(0) +#define ADVXCHG1END CMD(1) +#define CHGX CMD(2)-1 +#define CHGXEND CMD(3)-1 +#define ADVXLSH CMD(4) +#define ADVXLSHEND CMD(5) +#define ADVXRSH CMD(6) +#define ADVXRSHEND CMD(7) +#define ADVX CMD(8)-1 +#define REPX CMD(9)-1 +#define SETX CMD(10)-1 +#define CLRX CMD(11)-1 +#define ADVXCHG2 CMD(12) +#define ADVXCHG2END CMD(13) +#define END CMD(14) + +#include "protos.h" + +static int rowlength = -1 ; +static unsigned char *specdata ; +static long tslen = 0 ; +static unsigned char *tempstore, *tsp, *tsend ; + +void putlong P2C(register char *, a, long, i) +{ + a[0] = i >> 24 ; + a[1] = i >> 16 ; + a[2] = i >> 8 ; + a[3] = i ; +} + +long getlong P1C(register unsigned char *, a) +{ + return ((((((a[0] << 8L) + a[1]) << 8L) + a[2]) << 8L) + a[3]) ; +} + +/* First, a routine that appends one byte to the compressed output. */ + +#define addtse(n) {lcm=tsp-tempstore;addts(n);} /* mark END option position */ + +static void addts P1C(register unsigned char, what) +{ + register unsigned char *p, *q ; + + if (tsp >= tsend) { + if (tempstore == NULL) { + tslen = 2020 ; + tempstore = (unsigned char *)mymalloc((integer)tslen) ; + tsp = tempstore ; + } else { + tslen = 2 * tslen ; + tsp = (unsigned char *)mymalloc((integer)tslen) ; + for (p=tempstore, q=tsp; p<tsend; p++, q++) + *q = *p ; + free((char *)tempstore) ; + tempstore = tsp ; + tsp = q ; + } + tsend = tempstore + tslen ; + } + *tsp++ = what ; +} + +/* Next, a routine that discovers how to do the compression. */ + +#define rsh(a,b) ( ((a)==0) ? ((b)==128) : ( ((a)==255) ? ((b)==127) :\ + ((b)==(((a)>>1)|((a)&128))) )) +#define lsh(a,b) ( ((a)==0) ? ((b)==1) : ( ((a)==255) ? ((b)==254) :\ + ((b)==((((a)<<1)&255)|((a)&1))) )) +#define DIFFERENT (1) +#define LSHPOSSIB (2) +#define RSHPOSSIB (4) +#define BLKPOSSIB (8) +#define WHTPOSSIB (16) +#define ENDROW (32) +#define NOPOSSIB(n) ((n&(LSHPOSSIB|RSHPOSSIB|BLKPOSSIB|WHTPOSSIB))==0) +#define NOSHIFT(n) ((n&(LSHPOSSIB|RSHPOSSIB))==0) +/* + * Our input bytes are packed to the 16-bit word. On output, + * they're packed to bytes. Thus, we may have to skip a byte at + * the end of each row. + */ +void dochar P3C(unsigned char *, from, short, width, short, height) +{ + register int i ; + register unsigned char *f, *t, *d ; + register unsigned char *e ; + register int accum ; + int j, k, kk ; + int diffrow ; + int repeatcount ; + int lit, pos, cmd = 0 ; + long lcm ; + int widthc ; + + widthc = width + (width & 1) ; /* halfword correction */ + lcm = -1 ; + if (widthc > rowlength) { + if (rowlength > 0) + free((char *)specdata) ; + rowlength = widthc + 30 ; + specdata = (unsigned char *)mymalloc((integer)(rowlength + 15)) ; + } + for (i= -15, t=specdata; i<=widthc; i++, t++) + *t = 0 ; + repeatcount = 0 ; + f = specdata + 2 ; + for (j=0; j<height; j++, f = from, from += widthc) { + diffrow = 0 ; + for (i=0, t=from, d=specdata; i<width; i++, f++, t++, d++) { + if (*f == *t) { + if (*t == 0) + *d = WHTPOSSIB ; + else if (*t == 255) + *d = BLKPOSSIB ; + else + *d = 0 ; + } else { + accum = DIFFERENT ; + if (rsh(*f, *t)) + accum |= RSHPOSSIB ; + else if (lsh(*f, *t)) + accum |= LSHPOSSIB ; + if (*t == 0) + accum |= WHTPOSSIB ; + else if (*t == 255) + accum |= BLKPOSSIB ; + *d = accum ; + diffrow++ ; + } + } /* end 'for i' */ + *d = ENDROW ; + if (diffrow == 0) { + repeatcount++ ; + } else { + if (repeatcount) { + while (repeatcount > MAXOUT) { + addts((unsigned char)(REPX+MAXOUT)) ; + repeatcount -= MAXOUT ; + } + addts((unsigned char)(REPX+repeatcount)) ; + repeatcount = 0 ; + } + pos = 0 ; + for (i=0, d=specdata, f=t-width; i<width;) { + if ((*d & DIFFERENT) == 0) { + i++ ; + d++ ; + f++ ; + } else { + accum = 0 ; + if (pos != i) + lit = NOSHIFT(*d) ; + else /* N.B.: 'lit' does not imply literate programming here */ + lit = NOPOSSIB(*d) ; + for (e=d; ;e++) { + if (NOPOSSIB(*e)) + lit = 1 ; + if ((*e & DIFFERENT) == 0) + break ; + if ((*e & WHTPOSSIB) && + (e[1] & WHTPOSSIB)) { + while (*e & WHTPOSSIB) { + e++ ; + accum++ ; + } + cmd = CLRX ; + e -= accum ; + break ; + } else if ((*e & BLKPOSSIB) && + (e[1] & BLKPOSSIB)) { + while (*e & BLKPOSSIB) { + e++ ; + accum++ ; + } + cmd = SETX ; + e -= accum ; + break ; + } + } /* end 'for e'; d pts to first bad byte, e to next good one */ + while (i - pos > MAXOUT) { + addts((unsigned char)(ADVX+MAXOUT)) ; + pos += MAXOUT ; + } + if (0 != (k = (e - d))) { + if (lit) { + if (k > 2) { + if (i > pos) { + addts((unsigned char)(ADVX + i - pos)) ; + pos = i ; + } + while (k > MAXOUT) { + addts((unsigned char)(CHGX + MAXOUT)) ; + for (kk=0; kk<MAXOUT; kk++) + addts((unsigned char)(*f++)) ; + d += MAXOUT ; + pos += MAXOUT ; + i += MAXOUT ; + k -= MAXOUT ; + } + addtse((unsigned char)(CHGX + k)) ; + pos += k ; + for (; d<e; d++, i++, f++) + addts((unsigned char)(*f)) ; + } else { + if (k == 1) { + if (i == pos+MAXOUT) { + addts((unsigned char)(ADVX + MAXOUT)) ; + pos = i ; + } + addtse((unsigned char)(ADVXCHG1 + i - pos)) ; + addts((unsigned char)(*f)) ; + i++ ; + pos = i ; + d++ ; + f++ ; + } else { + if (i == pos+MAXOUT) { + addts((unsigned char)(ADVX + MAXOUT)) ; + pos = i ; + } + addtse((unsigned char)(ADVXCHG2 + i - pos)) ; + addts((unsigned char)(*f)) ; + addts((unsigned char)(f[1])) ; + i += 2 ; + pos = i ; + d += 2 ; + f += 2 ; + } + } + } else { + while (e > d) { + if (*d & LSHPOSSIB) { + if (i == pos+MAXOUT) { + addts((unsigned char)(ADVX + MAXOUT)) ; + pos = i ; + } + addtse((unsigned char)(ADVXLSH + i - pos)) ; + } else if (*d & RSHPOSSIB) { + if (i == pos+MAXOUT) { + addts((unsigned char)(ADVX + MAXOUT)) ; + pos = i ; + } + addtse((unsigned char)(ADVXRSH + i - pos)) ; + } else if (*d & WHTPOSSIB) { /* i==pos */ + addts((unsigned char)(CLRX + 1)) ; lcm = -1 ; + } else if (*d & BLKPOSSIB) { /* i==pos */ + addts((unsigned char)(SETX + 1)) ; lcm = -1 ; + } else + error("! bug") ; /* why wasn't lit true? */ + d++ ; + f++ ; + i++ ; + pos = i ; + } /* end 'while e>d' */ + } + } /* end 'if e>d' */ + if (accum > 0) { + if (i > pos) { + addts((unsigned char)(ADVX + i - pos)) ; + pos = i ; + } + i += accum ; + d += accum ; + f += accum ; + while (accum > MAXOUT) { + addts((unsigned char)(cmd + MAXOUT)) ; + accum -= MAXOUT ; + pos += MAXOUT ; + } + lcm = -1 ; + addts((unsigned char)(cmd + accum)) ; + pos += accum ; + } + } /* end 'else DIFFERENT' */ + } /* end 'for i' */ + if (lcm != -1) { + tempstore[lcm] += MAXOUT ; /* append END */ + lcm = -1 ; + } else { + addts((unsigned char)(END)) ; + } + } /* end 'else rows different' */ +#ifdef DEBUG + if (d != specdata + width) + error("! internal inconsistency in repack") ; +#endif + } /* end 'for j' */ + if (repeatcount) { + while (repeatcount > MAXOUT) { + addts((unsigned char)(REPX+MAXOUT)) ; + repeatcount -= MAXOUT ; + } + addts((unsigned char)(REPX+repeatcount)) ; + repeatcount = 0 ; + } +} + +extern long bytesleft ; +extern quarterword *raster ; +long mbytesleft ; +quarterword *mraster ; + +char * +makecopy P3C(register unsigned char *, what, + register long, len, + register unsigned char *, p) +{ + register unsigned char *q ; + + if (p == NULL) { + if (len > MINCHUNK) + p = (unsigned char *)mymalloc((integer)len) ; + else { + if (bytesleft < len) { + raster = (quarterword *)mymalloc((integer)RASTERCHUNK) ; + bytesleft = RASTERCHUNK ; + } + p = (unsigned char *)raster ; + bytesleft -= len ; + raster += len ; + } + } + q = p ; + while (len > 0) { + *p++ = *what++ ; + len -- ; + } + return ((char *)q) ; +} + +/* Now the main routine, which is called when a character is used + for the very first time. */ +void repack P1C(register chardesctype *, cp) +{ + register long i, j ; + register unsigned char *p ; + register int width, height ; + register int wwidth ; + char startbytes ; + int smallchar ; + + p = cp->packptr ; + if (p == NULL) + error("! no raster?") ; + tsp = tempstore ; + tsend = tempstore + tslen ; + addts(*p) ; /* copy the PK flag byte */ + if (*p & 4) { + if ((*p & 7) == 7) { + startbytes = 17 ; + width = getlong(p + 1) ; + height = getlong(p + 5) ; + for (i=0; i<12; i++) + addts(*++p) ; + } else { + startbytes = 9 ; + width = p[1] * 256 + p[2] ; + height = p[3] * 256 + p[4] ; + addts(*++p) ; + addts(*++p) ; + addts(*++p) ; + addts(*++p) ; + } + } else { + startbytes = 5 ; + width = p[1] ; + height = p[2] ; + } + addts(*++p) ; + addts(*++p) ; + addts(*++p) ; + addts(*++p) ; + p++ ; /* OK, p now points to beginning of the nibbles */ + addts((unsigned char)0) ; + addts((unsigned char)0) ; + addts((unsigned char)0) ; + addts((unsigned char)0) ; /* leave room to stick in a new length field */ + wwidth = (width + 15) / 16 ; + i = 2 * height * (long)wwidth ; + if (i <= 0) + i = 2 ; + if ((cp->flags & BIGCHAR) == 0) + smallchar = 5 ; + else + smallchar = 0 ; + i += smallchar ; + if (mbytesleft < i) { + if (mbytesleft >= RASTERCHUNK) + (void) free((char *) mraster) ; + if (RASTERCHUNK > i) { + mraster = (quarterword *)mymalloc((integer)RASTERCHUNK) ; + mbytesleft = RASTERCHUNK ; + } else { + i += i / 4 ; + mraster = (quarterword *)mymalloc((integer)(i + 3)) ; + mbytesleft = i ; + } + } + while (i > 0) + mraster[--i] = 0 ; + i = startbytes + unpack(p, (halfword *)mraster, (halfword)width, + (halfword)height, *(cp->packptr)) ; + dochar(mraster, (width + 7) >> 3, height) ; + if (smallchar) { + addts((unsigned char)0) ; + addts((unsigned char)0) ; + addts((unsigned char)0) ; + addts((unsigned char)0) ; + addts((unsigned char)0) ; + } + j = tsp - tempstore ; +#ifdef DEBUG + if (dd(D_COMPRESS)) + (void)fprintf(stderr,"PK %ld bytes, unpacked %ld, compressed %ld\n", + i-(long)startbytes, (long)((width+7L)/8)*height, j-(long)startbytes-4) ; +#endif /* DEBUG */ + if ( i < j ) { + if (i > MINCHUNK) + free(cp->packptr) ; + cp->packptr = + (unsigned char *)makecopy(tempstore, j, (unsigned char *)0) ; + } else + makecopy(tempstore, j, (unsigned char *)cp->packptr) ; + putlong((char *)(cp->packptr+startbytes), j-startbytes-4-smallchar) ; + cp->flags |= REPACKED ; +} |