diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/pbm/pbmtopk.c | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/pbm/pbmtopk.c')
-rw-r--r-- | converter/pbm/pbmtopk.c | 976 |
1 files changed, 976 insertions, 0 deletions
diff --git a/converter/pbm/pbmtopk.c b/converter/pbm/pbmtopk.c new file mode 100644 index 00000000..b84818b1 --- /dev/null +++ b/converter/pbm/pbmtopk.c @@ -0,0 +1,976 @@ +/* + pbmtopk, adapted from "pxtopk.c by tomas rokicki" by AJCD 1/8/90 + + compile with: cc -o pbmtopk pbmtopk.c -lm -lpbm +*/ + +#define _BSD_SOURCE 1 /* Make sure strdup() is in string.h */ +#define _XOPEN_SOURCE 500 /* Make sure strdup() is in string.h */ + +#include <stdio.h> +#include <math.h> +#include <ctype.h> +#include <string.h> + +#include "pm_c_util.h" +#include "pbm.h" +#include "nstring.h" +#include "mallocvar.h" + +#define MAXPKCHAR 256 +#define MAXOPTLINE 200 +#define MAXWIDTHTAB 256 +#define MAXHEIGHTTAB 16 +#define MAXDEPTHTAB 16 +#define MAXITALICTAB 64 +#define MAXPARAMS 30 +#define NAMELENGTH 80 + +#define fixword(d) ((int)((double)(d)*1048576)) +#define unfixword(f) ((double)(f) / 1048576) +#define fixrange(f) ((f) < 16777216 && (f) > -16777216) +#define designunits(p) ((p)*72.27/(double)resolution/unfixword(designsize)) + +/* character flags: in order of appearance in option files. */ +#define XOFFSET 1 +#define YOFFSET 2 +#define HORZESC 4 +#define VERTESC 8 +#define TFMWIDTH 16 +#define TFMHEIGHT 32 +#define TFMDEPTH 64 +#define TFMITALIC 128 + +typedef int integer ; +typedef char quarterword ; +typedef char boolean ; +typedef quarterword ASCIIcode ; +typedef quarterword eightbits ; +typedef unsigned char byte ; + +static integer resolution, designsize ; +static char *filename[MAXPKCHAR] ; + +static integer xoffset[MAXPKCHAR] ; +static integer yoffset[MAXPKCHAR] ; +static integer horzesc[MAXPKCHAR] ; +static integer vertesc[MAXPKCHAR] ; + +static byte tfmindex[MAXPKCHAR] ; +static byte hgtindex[MAXPKCHAR] ; +static byte depindex[MAXPKCHAR] ; +static byte italindex[MAXPKCHAR] ; +static byte charflags[MAXPKCHAR] ; + +static bit **bitmap ; +static integer smallestch = MAXPKCHAR ; +static integer largestch = -1; +static integer emwidth = 0; +static integer checksum ; +static const char *codingscheme = "GRAPHIC" ; +static const char *familyname = "PBM" ; + +static integer widthtab[MAXWIDTHTAB] = {0}; /* TFM widths */ +static integer numwidth = 1; /* number of entries in width table */ +static integer heighttab[MAXHEIGHTTAB] = {0}; +static integer numheight = 1; +static integer depthtab[MAXDEPTHTAB] = {0}; +static integer numdepth = 1; +static integer italictab[MAXITALICTAB] = {0}; +static integer numitalic = 1; +static integer parameters[MAXPARAMS] = {0}; +static integer numparam = 0; + +static ASCIIcode xord[128] ; +static char xchr[256] = { + '?', '?', '?', '?', '?', '?', '?', '?', + '?', '?', '?', '?', '?', '?', '?', '?', + '?', '?', '?', '?', '?', '?', '?', '?', + '?', '?', '?', '?', '?', '?', '?', '?', + ' ', '!', '"', '#', '$', '%', '&', '\'', + '(', ')', '*', '+', ',', '-', '.', '/', + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', ':', ';', '<', '=', '>', '?', + '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', + 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', + 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', + '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', + 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', + 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', + 'x', 'y', 'z', '{', '|', '}', '~', '?' }; + +static FILE *tfmfile, *pkfile ; +static char tfmname[NAMELENGTH+1], pkname[NAMELENGTH+1] ; +static integer pbmtopk_pkloc = 0 ; +static integer bitweight ; +static integer outputbyte ; +static integer car ; +static integer hppp ; +static integer width ; +static integer height ; + +/* check sum algorithm (in Pascal): + +compute_checksum() + begin + c0:=bc; c1:=ec; c2:=bc; c3:=ec; + for c:=bc to ec do if char_wd[c]>0 then begin + temp_width:=memory[char_wd[c]]; + if design_units<>unity then + temp_width:=round((temp_width/design_units)*1048576.0); + temp_width:=temp_width + (c+4)*@'20000000; + {this should be positive} + c0:=(c0+c0+temp_width) mod 255; + c1:=(c1+c1+temp_width) mod 253; + c2:=(c2+c2+temp_width) mod 251; + c3:=(c3+c3+temp_width) mod 247; + end; + header_bytes[check_sum_loc]:=c0; + header_bytes[check_sum_loc+1]:=c1; + header_bytes[check_sum_loc+2]:=c2; + header_bytes[check_sum_loc+3]:=c3; + end +*/ + +#define add_tfmwidth(v) (add_tfmtable(widthtab, &numwidth, v, MAXWIDTHTAB,\ + "TFM width")) +#define add_tfmheight(v) (add_tfmtable(heighttab, &numheight, v, MAXHEIGHTTAB,\ + "TFM height")) +#define add_tfmdepth(v) (add_tfmtable(depthtab, &numdepth, v, MAXDEPTHTAB,\ + "TFM depth")) +#define add_tfmitalic(v) (add_tfmtable(italictab, &numitalic, v, MAXITALICTAB,\ + "Italic correction")) + + +static byte +add_tfmtable(int * const table, + int * const count, + int const value, + int const max_count, + const char * const name) { + + integer i; + for (i = 0; i < *count; i++) /* search for value in tfm table */ + if (table[i] == value) return (byte)i; + if (*count >= max_count) + pm_error("too many values in %s table", name) ; + if (!fixrange(value)) + pm_error("%s %f for char %d out of range", + name, unfixword(value), car); + table[*count] = value ; + return (*count)++ ; +} + + + +/* add a suffix to a filename in an allocated space */ +static void +pbmtopk_add_suffix(char * const name, + const char * const suffix) { + + char *slash = strrchr(name, '/'); + char *dot = strrchr(name, '.'); + + if ((dot && slash ? dot < slash : !dot) && !STREQ(name, "-")) + strcat(name, suffix); +} + + + +/* initialize the PK parameters */ +static void +initialize_pk(void) { + integer i ; + pm_message("This is PBMtoPK, version 2.4") ; + for (i = 127 ; i <= 255 ; i ++) xchr[i] = '?' ; + for (i = 0 ; i <= 127 ; i ++) xord[i] = 32 ; + for (i = 32 ; i < 127 ; i ++) xord[(int)xchr[i]] = i ; + for (i = 0; i < MAXPKCHAR; i++) { + filename[i] = NULL; + charflags[i] = 0; + } + designsize = fixword(1.0) ; +} + + + +/* write a single byte to the PK file */ +static void +pbmtopk_pkbyte(integer const b_in) { + integer b; + + b = b_in; /* initial value */ + + if (b < 0) + b += 256 ; + putc(b, pkfile) ; + pbmtopk_pkloc++ ; +} + + + +/* write two bytes to the PK file */ +static void +pkhalfword(integer const a_in) { + integer a; + + a = a_in; + + if (a < 0) + a += 65536 ; + pbmtopk_pkbyte(a >> 8) ; + pbmtopk_pkbyte(a & 255) ; +} + + + +/* write three bytes to the PK file */ +static void +pkthreebytes(integer const a) { + + pbmtopk_pkbyte((a>>16) & 255) ; + pbmtopk_pkbyte((a>>8) & 255) ; + pbmtopk_pkbyte(a & 255) ; +} + + + +/* write four bytes to the PK file */ +static void +pkword(integer const a) { + pbmtopk_pkbyte((a>>24) & 255) ; + pbmtopk_pkbyte((a>>16) & 255) ; + pbmtopk_pkbyte((a>>8) & 255) ; + pbmtopk_pkbyte(a & 255) ; +} + + + +/* write a nibble to the PK file */ +static void +pknyb(integer const a) { + + if (bitweight == 16) { + outputbyte = (a<<4) ; + bitweight = 1 ; + } else { + pbmtopk_pkbyte(outputbyte + a) ; + bitweight = 16 ; + } +} + + + +/* write preamble to PK file */ +static void +writepreamble(void) { + integer i ; + const char * const comment = "PBMtoPK 2.4 output" ; + + pbmtopk_pkbyte(247) ; /* PRE command */ + pbmtopk_pkbyte(89) ; /* PK file type */ + pbmtopk_pkbyte(strlen(comment)) ; /* output comment */ + for (i = 0 ; i < strlen(comment); i++) + pbmtopk_pkbyte(xord[(int)comment[i]]) ; + pkword(designsize) ; /* write designsize */ + pkword(checksum) ; /* write checksum; calculate if possible */ + pkword(hppp) ; /* write H pixels per point */ + pkword(hppp) ; /* write V pixels per point */ +} + + + +/* write postamble to PK file, padded to word length */ +static void +writepostamble(void) { + pbmtopk_pkbyte(245) ; /* POST command */ + while (pbmtopk_pkloc % 4) + pbmtopk_pkbyte(246) ; /* pad with no-ops */ + pm_message("%d bytes written to packed file.", pbmtopk_pkloc) ; +} + + + +/* write a byte to the TFM file */ +static void +tfmbyte(integer const b_in) { + integer b; + + b = b_in; + + if (b < 0) b += 256 ; + putc(b, tfmfile) ; +} + + + +/* write a half word to the TFM file */ +static void +tfmhalfword(integer const a_in) { + + integer a; + + a = a_in; + + if (a < 0) a += 65536 ; + tfmbyte(a >> 8) ; + tfmbyte(a & 255) ; +} + + + +/* write a word to the TFM file */ +static void +tfmword(integer const a) { + tfmbyte((a>>24) & 255) ; + tfmbyte((a>>16) & 255) ; + tfmbyte((a>>8) & 255) ; + tfmbyte(a & 255) ; +} + + + +/* write the whole TFM file for the font */ +static void +writetfmfile(void) { + integer totallength ; + integer headersize = 17; + integer i ; + + if (largestch - smallestch < 0) { + largestch = 0; + smallestch = 1; + } + if (numparam < 7) /* set default parameters */ + switch (numparam) { + case 0: /* slant */ + parameters[numparam++] = 0 ; + case 1: /* space */ + parameters[numparam++] = fixword(designunits(emwidth/3.0)); + case 2: /* space_stretch */ + parameters[numparam++] = fixword(unfixword(parameters[1])/2.0) ; + case 3: /* space_shrink */ + parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ; + case 4: /* x_height */ + parameters[numparam++] = fixword(0.45); + case 5: /* quad */ + parameters[numparam++] = fixword(designunits(emwidth)) ; + case 6: /* extra_space */ + parameters[numparam++] = fixword(unfixword(parameters[1])/3.0) ; + } + totallength = 6 + headersize + (largestch+1-smallestch) + + numwidth + numheight + numdepth + numitalic + numparam ; + /* lengths */ + tfmhalfword(totallength) ; /* write file TFM length */ + tfmhalfword(headersize) ; /* write TFM header length */ + tfmhalfword(smallestch) ; /* write lowest char index */ + tfmhalfword(largestch) ; /* write highest char index */ + tfmhalfword(numwidth) ; /* write number of widths */ + tfmhalfword(numheight) ; /* write number of heights */ + tfmhalfword(numdepth) ; /* write number of depths */ + tfmhalfword(numitalic) ; /* write number of italcorrs */ + tfmhalfword(0) ; /* lig/kern table */ + tfmhalfword(0) ; /* kern table */ + tfmhalfword(0) ; /* extensible char table */ + tfmhalfword(numparam) ; /* number of fontdimens */ + /* header */ + tfmword(checksum) ; /* write checksum */ + tfmword(designsize) ; /* write designsize */ + if (strlen(codingscheme) > 39) + tfmbyte(39) ; /* write coding scheme len */ + else + tfmbyte(strlen(codingscheme)) ; + for (i = 0; i < 39; i++) /* write coding scheme */ + if + (*codingscheme) tfmbyte(xord[(int)(*codingscheme++)]) ; + else + tfmbyte(0) ; + if (strlen(familyname) > 19) + tfmbyte(19) ; /* write family length */ + else + tfmbyte(strlen(familyname)) ; + for (i = 0; i < 19; i++) /* write family */ + if (*familyname) + tfmbyte(xord[(int)(*familyname++)]) ; + else + tfmbyte(0) ; + /* char_info */ + for (car = smallestch; car <= largestch; car++) + if (filename[car]) { /* write character info */ + tfmbyte(tfmindex[car]) ; + tfmbyte((hgtindex[car]<<4) + depindex[car]) ; + tfmbyte(italindex[car]<<2) ; + tfmbyte(0) ; + } else + tfmword(0) ; + /* width table */ + for (i = 0; i < numwidth; i++) tfmword(widthtab[i]) ; + /* height table */ + for (i = 0; i < numheight; i++) tfmword(heighttab[i]) ; + /* depth table */ + for (i = 0; i < numdepth; i++) tfmword(depthtab[i]) ; + /* italic correction table */ + for (i = 0; i < numitalic; i++) tfmword(italictab[i]) ; + /* no lig_kern, kern, or exten tables */ + /* fontdimen table */ + for (i = 0; i < numparam; i++) + if (i && !fixrange(parameters[i])) + pm_error("parameter %d out of range (-p)", i); + else + tfmword(parameters[i]) ; + pm_message("%d bytes written to tfm file.", totallength*4) ; +} + + + +/* read a character from a PBM file */ +static void readcharacter(void) { + FILE *fp; + + fp = pm_openr(filename[car]); + bitmap = pbm_readpbm(fp, &width, &height) ; + pm_close(fp) ; + + if ((charflags[car] & HORZESC) == 0) horzesc[car] = width ; + if ((charflags[car] & VERTESC) == 0) vertesc[car] = 0; + if ((charflags[car] & XOFFSET) == 0) xoffset[car] = 0; + if ((charflags[car] & YOFFSET) == 0) yoffset[car] = height-1; + if ((charflags[car] & TFMWIDTH) == 0) + tfmindex[car] = add_tfmwidth(fixword(designunits(width))); + if ((charflags[car] & TFMHEIGHT) == 0) + hgtindex[car] = add_tfmheight(fixword(designunits(yoffset[car]+1))); + if ((charflags[car] & TFMDEPTH) == 0) + depindex[car] = + add_tfmdepth(fixword(designunits(height-1-yoffset[car]))); + if ((charflags[car] & TFMITALIC) == 0) italindex[car] = 0; + + if (car < smallestch) smallestch = car; + if (car > largestch) largestch = car; + if (width > emwidth) emwidth = width ; +} + + + +/* test if two rows of the PBM are the same */ +static int +equal(const bit * const row1, + const bit * const row2) { + + integer i ; + + for (i = 0; i < width; i++) + if (row1[i] != row2[i]) + return (0) ; + + return(1) ; +} + + + +static void +shipcharacter(void) { + + integer compsize ; + integer i, j, k ; + bit *zerorow, *onesrow ; + integer *repeatptr, *bitcounts ; + integer count ; + integer test ; + integer curptr, rowptr ; + integer bitval ; + integer repeatflag ; + integer colptr ; + integer currepeat ; + integer dynf ; + integer deriv[14] ; + integer bcompsize ; + boolean firston ; + integer flagbyte ; + boolean state ; + boolean on ; + integer hbit ; + integer pbit ; + boolean ron, son ; + integer rcount, scount ; + integer ri, si ; + integer max2 ; + integer predpkloc ; + integer buff ; + + integer tfwid = widthtab[tfmindex[car]] ; + integer hesc = horzesc[car] ; + integer vesc = vertesc[car] ; + integer xoff = xoffset[car] ; + integer yoff = yoffset[car] ; + + MALLOCARRAY(repeatptr, height + 1); + MALLOCARRAY(bitcounts, height * width); + if (repeatptr == NULL || bitcounts == NULL) + pm_error("out of memory while allocating bit counts"); + zerorow = pbm_allocrow(width) ; /* initialize plain rows */ + onesrow = pbm_allocrow(width) ; + for (i = 0 ; i < width ; i++) { + zerorow[i] = PBM_WHITE ; + onesrow[i] = PBM_BLACK ; + } + for (i=0; i < height; i = k) { /* set repeat pointers */ + k = i + 1; + if (!equal(bitmap[i], zerorow) && !equal(bitmap[i], onesrow)) { + while (k < height && equal(bitmap[i], bitmap[k])) + k++; + repeatptr[i] = k - i - 1; + } else { + repeatptr[i] = 0; + } + } + repeatptr[height] = 0 ; + colptr = width - 1 ; + repeatflag = currepeat = curptr = count = rowptr = 0 ; + test = PBM_WHITE ; + do { + colptr++ ; + if (colptr == width) { /* end of row, get next row */ + colptr = 0 ; + rowptr = currepeat ; + if (repeatptr[currepeat] > 0) { + repeatflag = repeatptr[currepeat] ; + currepeat += repeatflag ; + rowptr += repeatflag ; + } + currepeat++ ; + } + if (rowptr >= height) bitval = -1 ; + else bitval = bitmap[rowptr][colptr] ; + if (bitval == test) count++ ; /* count repeated pixels */ + else { /* end of pixel run */ + bitcounts[curptr++] = count ; + if (curptr+3 >= height*width) + pm_error("out of memory while saving character counts"); + count = 1 ; + test = bitval ; + if (repeatflag > 0) { + bitcounts[curptr++] = -repeatflag ; + repeatflag = 0 ; + } + } + } while (test != -1) ; + bitcounts[curptr] = 0 ; + bitcounts[curptr + 1] = 0 ; + for (i = 1 ; i <= 13 ; i ++) deriv[i] = 0 ; + i = firston = (bitcounts[0] == 0) ; + compsize = 0 ; + while (bitcounts[i] != 0) { /* calculate dyn_f */ + j = bitcounts[i] ; + if (j == -1) compsize++ ; + else { + if (j < 0) { + compsize++ ; + j = -j ; + } + if (j < 209) compsize += 2 ; + else { + k = j - 193 ; + while (k >= 16) { + k >>= 4 ; + compsize += 2 ; + } + compsize++ ; + } + if (j < 14) (deriv[j])-- ; + else if (j < 209) (deriv[(223 - j) / 15])++ ; + else { + k = 16 ; + while (((k<<4) < j + 3)) k <<= 4 ; + if (j - k <= 192) + deriv[(207 - j + k) / 15] += 2 ; + } + } + i++ ; + } + bcompsize = compsize ; + dynf = 0 ; + for (i = 1 ; i <= 13 ; i ++) { + compsize += deriv[i] ; + if (compsize <= bcompsize) { + bcompsize = compsize ; + dynf = i ; + } + } + compsize = ((bcompsize + 1)>>1) ; + if ((compsize > ((height*width+7)>>3)) || (height*width == 0)) { + compsize = ((height*width+7)>>3) ; + dynf = 14 ; + } + flagbyte = (dynf<<4) ; + if (firston) flagbyte |= 8 ; + if (tfwid > 16777215 || tfwid < 0 || hesc < 0 || vesc != 0 || + compsize > 196579 || width > 65535 || height > 65535 || + xoff > 32767 || yoff > 32767 || xoff < -32768 || yoff < -32768) { + flagbyte |= 7 ; /* long form preamble */ + pbmtopk_pkbyte(flagbyte) ; + compsize += 28 ; + pkword(compsize) ; /* char packet size */ + pkword(car) ; /* character number */ + predpkloc = pbmtopk_pkloc + compsize ; + pkword(tfwid) ; /* TFM width */ + pkword(hesc<<16) ; /* horiz escapement */ + pkword(vesc<<16) ; /* vert escapement */ + pkword(width) ; /* bounding box width */ + pkword(height) ; /* bounding box height */ + pkword(xoff) ; /* horiz offset */ + pkword(yoff) ; /* vert offset */ + } else if (hesc > 255 || width > 255 || height > 255 || + xoff > 127 || yoff > 127 || xoff < -128 || + yoff < -128 || compsize > 1016) { + compsize += 13 ; /* extended short preamble */ + flagbyte += (compsize>>16) + 4 ; + pbmtopk_pkbyte(flagbyte) ; + pkhalfword(compsize & 65535) ; /* char packet size */ + pbmtopk_pkbyte(car) ; /* character number */ + predpkloc = pbmtopk_pkloc + compsize ; + pkthreebytes(tfwid) ; /* TFM width */ + pkhalfword(hesc) ; /* horiz escapement */ + pkhalfword(width) ; /* bounding box width */ + pkhalfword(height) ; /* bounding box height */ + pkhalfword(xoff) ; /* horiz offset */ + pkhalfword(yoff) ; /* vert offset */ + } else { + compsize += 8 ; /* short form preamble */ + flagbyte = flagbyte + (compsize>>8) ; + pbmtopk_pkbyte(flagbyte) ; + pbmtopk_pkbyte(compsize & 255) ; /* char packet size */ + pbmtopk_pkbyte(car) ; /* character number */ + predpkloc = pbmtopk_pkloc + compsize ; + pkthreebytes(tfwid) ; /* TFM width */ + pbmtopk_pkbyte(hesc) ; /* horiz escapement */ + pbmtopk_pkbyte(width) ; /* bounding box width */ + pbmtopk_pkbyte(height) ; /* bounding box height */ + pbmtopk_pkbyte(xoff) ; /* horiz offset */ + pbmtopk_pkbyte(yoff) ; /* vert offset */ + } + if (dynf != 14) { /* write packed character */ + bitweight = 16 ; + max2 = 208 - 15 * dynf ; + i = firston ; + while (bitcounts[i] != 0) { + j = bitcounts[i] ; + if (j == - 1) pknyb(15) ; + else { + if (j < 0) { + pknyb(14) ; + j = -j ; + } + if (j <= dynf) pknyb(j) ; + else if (j <= max2) { + j -= dynf + 1 ; + pknyb((j >> 4) + dynf + 1) ; + pknyb((j & 15)) ; + } else { + j -= max2 - 15 ; + k = 16 ; + while (k <= j) { + k <<= 4 ; + pknyb(0) ; + } + while (k > 1) { + k >>= 4 ; + pknyb(j / k) ; + j = j % k ; + } + } + } + i++ ; + } + if (bitweight != 16) pbmtopk_pkbyte(outputbyte) ; + } else { /* write bitmap character */ + buff = 0 ; + pbit = 8 ; + i = firston ; + hbit = width ; + on = ! firston ; + state = 0 ; + count = repeatflag = 0 ; + while ((bitcounts[i] != 0) || state || (count > 0)) { + if (state) { + count = rcount ; + i = ri ; + on = ron ; + repeatflag-- ; + } else { + rcount = count ; + ri = i ; + ron = on ; + } + do { + if (count == 0) { + if (bitcounts[i] < 0) { + if (! state) repeatflag = -bitcounts[i] ; + i++ ; + } + count = bitcounts[i] ; + i++ ; + on = !on ; + } + if ((count >= pbit) && (pbit < hbit)) { + if (on) buff += (1 << pbit) - 1 ; + pbmtopk_pkbyte(buff) ; + buff = 0 ; + hbit -= pbit ; + count -= pbit ; + pbit = 8 ; + } else if ((count < pbit) && (count < hbit)) { + if (on) buff += (1 << pbit) - (1 << (pbit - count)) ; + pbit -= count ; + hbit -= count ; + count = 0 ; + } else { + if (on) buff += (1 << pbit) - (1 << (pbit - hbit)) ; + count -= hbit ; + pbit -= hbit ; + hbit = width ; + if (pbit == 0) { + pbmtopk_pkbyte(buff) ; + buff = 0 ; + pbit = 8 ; + } + } + } while (hbit != width) ; + if (state && (repeatflag == 0)) { + count = scount ; + i = si ; + on = son ; + state = 0 ; + } else if (! state && (repeatflag > 0)) { + scount = count ; + si = i ; + son = on ; + state = 1 ; + } + } + if (pbit != 8) pbmtopk_pkbyte(buff) ; + } + if (predpkloc != pbmtopk_pkloc) + pm_error("bad predicted character length: character %d", car); + pbm_freerow(zerorow); + pbm_freerow(onesrow); + free((char *)repeatptr); + free((char *)bitcounts); +} + + + +/* check that character is in valid range */ +static void +checkchar(void) { + if (car < 0 || car >= MAXPKCHAR) + pm_error("character must be in range 0 to %d", MAXPKCHAR-1) ; +} + + + +/* read character information from an option file */ +static void +optionfile(const char * const name) { + + FILE *fp ; + char buffer[MAXOPTLINE] ; + + fp = pm_openr(name); + while (!feof(fp)) { + char *here = buffer; + + if (fgets(buffer, MAXOPTLINE, fp) == NULL) break ; + while (ISSPACE(*here)) here++ ; + if (*here && *here == '=') { + if (sscanf(here+1, "%d", &car) != 1) + pm_error("bad option file line %s", buffer) ; + } else if (*here && *here != '%' && *here != '#') { + char str[NAMELENGTH] ; + integer i, n; + + checkchar() ; + if (sscanf(here, "%s%n", str, &n) != 1) + pm_error("bad option file line %s", buffer) ; + filename[car] = strdup(str); + if (filename[car] == NULL) + pm_error("out of memory allocating filename %s", str); + for (i = 1; i < 256; i<<=1) { + here += n; + if (sscanf(here, "%s%n", str, &n) != 1) break ; + if (strcmp(str, "*")) { + charflags[car] |= i ; + switch (i) { + case XOFFSET: + xoffset[car] = atoi(str) ; + break ; + case YOFFSET: + yoffset[car] = atoi(str) ; + break ; + case HORZESC: + horzesc[car] = atoi(str) ; + break ; + case VERTESC: + vertesc[car] = atoi(str) ; + break ; + case TFMWIDTH: + tfmindex[car] = add_tfmwidth(fixword(atof(str))) ; + break ; + case TFMHEIGHT: + hgtindex[car] = add_tfmheight(fixword(atof(str))) ; + break ; + case TFMDEPTH: + depindex[car] = add_tfmdepth(fixword(atof(str))) ; + break ; + case TFMITALIC: + italindex[car] = add_tfmitalic(fixword(atof(str))) ; + break ; + } + } + } + car++ ; + } + } + pm_close(fp) ; +} + + + +int +main(int argc, char *argv[]) { + integer i, hesc, vesc, xoff, yoff, tfwid, tfdep, tfhgt, tfital ; + byte flags ; + const char * const usage = "pkfile[.pk] tfmfile[.tfm] dpi " + "[-s designsize] [-p num param...]\n" + "[-C codingscheme ] [-F family] [-c num | <char>]...\n" + "<char> is:\n" + "[-W tfmwidth] [-H tfmheight] [-D tfmdepth] [-I ital_corr] " + "[-h horiz]\n" + "[-v vert] [-x xoffset] [-y yoffset] file\n" + "or:\n" + "-f optfile\n" ; + + pbm_init(&argc, argv); + initialize_pk() ; + + if (--argc < 1) pm_usage(usage) ; + strcpy(pkname, *++argv) ; + pbmtopk_add_suffix(pkname, ".pk") ; + + if (--argc < 1) pm_usage(usage) ; + strcpy(tfmname, *++argv) ; + pbmtopk_add_suffix(tfmname, ".tfm") ; + + if (--argc < 1) pm_usage(usage) ; + resolution = atoi(*++argv) ; + if (resolution < 1 || resolution > 32767) + pm_error("unlikely resolution %d dpi", resolution); + + car = flags = hesc = vesc = xoff = yoff = tfwid = 0; + while (++argv, --argc) { + if (argv[0][0] == '-' && argv[0][1]) { + char c, *p; + c = argv[0][1] ; + if (argv[0][2]) p = *argv + 2 ; /* set argument pointer */ + else if (++argv, --argc) p = *argv ; + else pm_usage(usage) ; + switch (c) { + case 'C': + codingscheme = p; + break ; + case 'F': + familyname = p; + break ; + case 'c': + car = atoi(p) ; + break ; + case 's': + designsize = fixword(atof(p)); + if (designsize < 1048576) + pm_error("design size %f out of range", + unfixword(designsize)); + case 'h': + hesc = atoi(p) ; + flags |= HORZESC ; + break ; + case 'v': + vesc = atoi(p) ; + flags |= VERTESC ; + break ; + case 'x': + xoff = atoi(p) ; + flags |= XOFFSET ; + break ; + case 'y': + yoff = atoi(p) ; + flags |= YOFFSET ; + break ; + case 'W': + tfwid = fixword(atof(p)) ; + flags |= TFMWIDTH ; + break ; + case 'H': + tfhgt = fixword(atof(p)) ; + flags |= TFMHEIGHT ; + break ; + case 'D': + tfdep = fixword(atof(p)) ; + flags |= TFMDEPTH ; + break ; + case 'I': + tfital = fixword(atof(p)) ; + flags |= TFMITALIC ; + break ; + case 'f': + optionfile(p) ; + break ; + case 'p': + numparam = atoi(p); + if (numparam < 1 || numparam > MAXPARAMS) + pm_error("parameter count %d out of range", numparam); + for (i=0; i<numparam; i++) + if (++argv,--argc) + parameters[i] = fixword(atof(*argv)) ; + else + pm_error("not enough parameters (-p)"); + break ; + default: + pm_usage(usage) ; + } + } else { + checkchar() ; + if (flags & TFMWIDTH) + tfmindex[car] = add_tfmwidth(tfwid); + if (flags & TFMDEPTH) + depindex[car] = add_tfmdepth(tfdep); + if (flags & TFMHEIGHT) + hgtindex[car] = add_tfmheight(tfhgt); + if (flags & TFMITALIC) + italindex[car] = add_tfmitalic(tfital); + horzesc[car] = hesc ; + vertesc[car] = vesc ; + xoffset[car] = xoff ; + yoffset[car] = yoff ; + filename[car] = *argv ; + charflags[car] = flags ; + car++ ; + flags = 0; + } + } + hppp = ROUND((resolution<<16) / 72.27) ; + pkfile = pm_openw(pkname); + tfmfile = pm_openw(tfmname); + writepreamble() ; + for (car = 0 ; car < MAXPKCHAR ; car++) + if (filename[car]) { + readcharacter() ; + shipcharacter() ; + } + writepostamble() ; + writetfmfile() ; + pm_close(pkfile) ; + pm_close(tfmfile) ; + + return 0; +} + |