home *** CD-ROM | disk | FTP | other *** search
- /*
- * JET PAK - HP DeskJet and LaserJet series printer utilities
- *
- * JETFONT module - soft font utility functions
- *
- * Version 1.1 (Public Domain)
- */
-
- /* system include files */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
-
- /* application include files */
- #include "jetfont.h"
- #include "jetutil.h"
-
- /*
- * LOCAL DEFINITIONS
- */
-
- /* macros for byte/word i/o */
- #define byte_read(nb,fp,dst) \
- if (do_byte_read(&nb, fp, &dst) == ERROR) \
- return(ERROR);
-
- #define int_read(nb,fp,dst) \
- if (do_int_read(&nb, fp, &dst) == ERROR) \
- return(ERROR);
-
- #define byte_write(fp,src) \
- if (do_byte_write(fp, src) == ERROR) \
- return(ERROR);
-
- #define int_write(fp,src) \
- if (do_int_write(fp, src) == ERROR) \
- return(ERROR);
-
- /* Descriptor readers and writers */
- static int font_descriptor_read();
- static int character_code_read();
- static int character_descriptor_read();
- static int font_descriptor_write();
- static int character_code_write();
- static int character_descriptor_write();
-
- /* Low level readers and writers */
- static int do_byte_read();
- static int do_int_read();
- static int do_byte_write();
- static int do_int_write();
-
- /* Command -> handler function mapping table */
- static struct {
- int type;
- char *start;
- char *end;
- int (*reader)();
- int (*writer)();
- } command_table[] = {
- { FDC,FDC_S,FDC_E,font_descriptor_read,font_descriptor_write },
- { CCC,CCC_S,CCC_E,character_code_read,character_code_write },
- { CDC,CDC_S,CDC_E,character_descriptor_read,character_descriptor_write },
- };
-
- /*
- * FONT COMMAND I/O
- */
-
- int font_command_read(infp, fcp)
- FILE *infp;
- FONT_COMMAND *fcp;
- {
- /*
- * Read an arbitrary font command from infp. Any characters up to
- * the first ESC are silently consumed. If a command is recognised
- * a lower level handler is called to read in the descriptor. If
- * an unrecognised command is encountered, a warning is given.
- */
- int r, i;
- char esc_start[11], esc_end[2];
- int (*reader)(); /* for brain-damaged compilers */
-
- do
- {
- /* skip junk between escape sequences (eg NULs are occasionally
- found in badly constructed fonts) */
- do
- {
- if ((r = getc(infp)) == EOF)
- return(EOF);
- } while (r != '\033');
-
- /* read a PCL style escape sequence */
- if ((r = fscanf(infp, "%10[^+-0123456789]%d%1s",
- esc_start, &fcp->number, esc_end)) == 3)
- {
- for (i = 0; i < sizeofarray(command_table); i++)
- {
- if ( (strcmp(esc_start, command_table[i].start) == 0)
- && (strcmp(esc_end , command_table[i].end ) == 0) )
- {
- fcp->command_type = command_table[i].type;
- reader = command_table[i].reader;
- r = (*reader)(infp, fcp);
-
- /* normal return point */
- return(r);
- }
- }
-
- /* this is needed because a few soft fonts include arbitrary
- printer escape sequences that aren't really part of the soft
- font (eg OE18R#US.SFP and SC18R#US.SFP) */
- fprintf(stderr, WARNING_COMMAND_SKIPPED, os_dir, os_file,
- esc_start, fcp->number, esc_end);
- }
- } while (r == 3);
-
- /* EOF (normally) or unexpected printer escape sequence structure */
- if (r != EOF)
- r = ERROR;
-
- return(r);
- }
- int font_command_write(outfp, fcp)
- FILE *outfp;
- FONT_COMMAND *fcp;
- {
- /*
- * Write an arbitrary font command to outfp. The generic part of
- * the escape sequence is output first. Then a lower level handler
- * is called to output the remainder of the escape sequence, which
- * is specific to the actual command.
- */
- int r, i;
- int (*writer)(); /* for brain-damaged compilers */
-
- for (i = 0; i < sizeofarray(command_table); i++)
- {
- if (fcp->command_type == command_table[i].type)
- {
- if ((r = fprintf(outfp, "\033%s%d%1s", command_table[i].start,
- fcp->number, command_table[i].end)) > 0)
- {
- writer = command_table[i].writer;
- r = (*writer)(outfp, fcp);
- }
- else
- {
- r = ERROR;
- }
-
- break;
- }
- }
-
- return(r);
- }
-
- static int font_descriptor_read(infp, fcp)
- FILE *infp;
- FONT_COMMAND *fcp;
- {
- /*
- * Read a font descriptor. This is a fairly complicated as there
- * are several data sizes to deal with: the routine is passed an
- * overall data size read in as part of the command. The
- * descriptor(s) themselves include another data size.
- *
- * The difference between the command data size(s) and the sum of
- * the descriptor sizes is accounted for by comment bytes.
- * Although the kosher descriptor size for an LJ soft font is 64,
- * many fonts put in a lower value.
- */
- int i, nc = 0, nd = fcp->number;
- UNSIGNEDBYTE temp_byte;
- char junk;
-
- int_read(nd, infp, fcp->data.font.size);
-
- /* split byte count into data bytes and other bytes */
- if (fcp->data.font.size < 2)
- {
- /* this should never occur in practice */
- nc = nd;
- nd = 0;
- }
- else if (fcp->data.font.size < (nd + 2))
- {
- nc = (nd + 2) - fcp->data.font.size;
- nd -= nc;
- }
-
- byte_read(nd, infp, fcp->data.font.header_format);
- byte_read(nd, infp, fcp->data.font.type);
-
- int_read(nd, infp, fcp->data.font.reserved1);
- int_read(nd, infp, fcp->data.font.baseline_distance);
- int_read(nd, infp, fcp->data.font.cell_width);
- int_read(nd, infp, fcp->data.font.cell_height);
-
- byte_read(nd, infp, fcp->data.font.orientation);
- byte_read(nd, infp, fcp->data.font.spacing);
-
- int_read(nd, infp, fcp->data.font.symbol_set);
- int_read(nd, infp, fcp->data.font.pitch);
- int_read(nd, infp, fcp->data.font.height);
- int_read(nd, infp, fcp->data.font.x_height);
-
- byte_read(nd, infp, fcp->data.font.width_type);
- if (fcp->data.font.header_format == DJ500FONTFORMAT)
- {
- int_read(nd, infp, fcp->data.font.style);
- }
- else
- {
- byte_read(nd, infp, temp_byte);
- fcp->data.font.style = (UNSIGNEDINT)temp_byte;
- }
- byte_read(nd, infp, fcp->data.font.stroke_weight);
- if (fcp->data.font.header_format == DJ500FONTFORMAT)
- {
- int_read(nd, infp, fcp->data.font.typeface);
- }
- else
- {
- byte_read(nd, infp, temp_byte);
- fcp->data.font.typeface = (UNSIGNEDINT)temp_byte;
- }
- byte_read(nd, infp, fcp->data.font.slant);
- byte_read(nd, infp, fcp->data.font.serif_style);
- byte_read(nd, infp, fcp->data.font.quality);
- byte_read(nd, infp, fcp->data.font.placement);
- byte_read(nd, infp, fcp->data.font.underline_distance);
- byte_read(nd, infp, fcp->data.font.underline_height);
-
- int_read(nd, infp, fcp->data.font.text_height);
- int_read(nd, infp, fcp->data.font.text_width);
- int_read(nd, infp, fcp->data.font.first_code);
- int_read(nd, infp, fcp->data.font.last_code);
-
- byte_read(nd, infp, fcp->data.font.pitch_extended);
- byte_read(nd, infp, fcp->data.font.height_extended);
-
- int_read(nd, infp, fcp->data.font.reserved2);
- int_read(nd, infp, fcp->data.font.font_number_top);
- int_read(nd, infp, fcp->data.font.font_number_bot);
-
- for (i = 0; i < sizeof(fcp->data.font.name); i++)
- {
- byte_read(nd, infp, fcp->data.font.name[i]);
- if (fcp->data.font.name[i] == '\0')
- fcp->data.font.name[i] = ' ';
- }
-
- /* this is the DJ specific stuff in the standard header */
- int_read(nd, infp, fcp->data.font.h_pixel_resolution);
- int_read(nd, infp, fcp->data.font.v_pixel_resolution);
-
- byte_read(nd, infp, fcp->data.font.tdu_distance);
- byte_read(nd, infp, fcp->data.font.tdu_height);
- byte_read(nd, infp, fcp->data.font.bdu_distance);
- byte_read(nd, infp, fcp->data.font.bdu_height);
-
- /* read a printer specific block: this is usually present in
- DJ soft fonts but not in any of the LJ soft fonts I have seen.
- This test gets around the problem that many LJ fonts will often
- have a garbage value (ie comment stuff) where you should get a
- descriptor size. If all the data up to the printer specific
- block is present, chances are it's OK to go ahead and
- try to read a printer specific block */
- if (fcp->data.font.size >= DJFDSIZE)
- {
- /* lump byte counts together again */
- nd += nc;
- nc = 0;
-
- int_read(nd, infp, fcp->data.font.specific_size);
-
- /* split byte count into data bytes and other bytes */
- if (fcp->data.font.specific_size < 2)
- {
- /* this does occur - the fonts in Elfring Soft Fonts'
- DJETFONT.ZIP package have a printer specific block
- size of 0 */
- nc = nd;
- nd = 0;
- }
- else if (fcp->data.font.specific_size < (nd + 2))
- {
- nc = (nd + 2) - fcp->data.font.specific_size;
- nd -= nc;
- }
-
- int_read(nd, infp, fcp->data.font.data_size);
-
- byte_read(nd, infp, fcp->data.font.unidirection);
- byte_read(nd, infp, fcp->data.font.compressed);
- byte_read(nd, infp, fcp->data.font.hold_time_factor);
- byte_read(nd, infp, fcp->data.font.no_half_pitch);
- byte_read(nd, infp, fcp->data.font.no_double_pitch);
- byte_read(nd, infp, fcp->data.font.no_half_height);
- byte_read(nd, infp, fcp->data.font.no_bold);
- byte_read(nd, infp, fcp->data.font.no_draft);
- byte_read(nd, infp, fcp->data.font.bold_method);
- byte_read(nd, infp, fcp->data.font.reserved3);
-
- int_read(nd, infp, fcp->data.font.baseline_offset_2);
- int_read(nd, infp, fcp->data.font.baseline_offset_3);
- int_read(nd, infp, fcp->data.font.baseline_offset_4);
-
- if (fcp->data.font.specific_size >= DJ500SSIZE)
- {
- for (i = 0; i < sizeof(fcp->data.font.name_extension); i++)
- {
- byte_read(nd, infp, fcp->data.font.name_extension[i]);
- if (fcp->data.font.name_extension[i] == '\0')
- fcp->data.font.name_extension[i] = ' ';
- }
- }
- }
-
- /* any remaining bytes are comments */
- for (i = 0; i < COMMENT_SIZE_MAX-1 && nc > 0; i++)
- {
- byte_read(nc, infp, fcp->data.font.comment[i]);
- if (fcp->data.font.comment[i] == '\0')
- fcp->data.font.comment[i] = ' ';
- }
- fcp->data.font.comment[i] = '\0';
-
- /* if nc > 0 here, you ran out of space in the comment string */
- while (nc > 0)
- byte_read(nc, infp, junk);
-
- return(OK);
- }
- static int font_descriptor_write(outfp, fcp)
- FILE *outfp;
- FONT_COMMAND *fcp;
- {
- /*
- * Write a font descriptor. Compared to reading one, this is a
- * cinch.
- */
- int i, len;
-
- int_write(outfp, fcp->data.font.size);
-
- byte_write(outfp, fcp->data.font.header_format);
- byte_write(outfp, fcp->data.font.type);
-
- int_write(outfp, fcp->data.font.reserved1);
- int_write(outfp, fcp->data.font.baseline_distance);
- int_write(outfp, fcp->data.font.cell_width);
- int_write(outfp, fcp->data.font.cell_height);
-
- byte_write(outfp, fcp->data.font.orientation);
- byte_write(outfp, fcp->data.font.spacing);
-
- int_write(outfp, fcp->data.font.symbol_set);
- int_write(outfp, fcp->data.font.pitch);
- int_write(outfp, fcp->data.font.height);
- int_write(outfp, fcp->data.font.x_height);
-
- byte_write(outfp, fcp->data.font.width_type);
- if (fcp->data.font.header_format == DJ500FONTFORMAT)
- {
- int_write(outfp, fcp->data.font.style);
- }
- else
- {
- byte_write(outfp, (UNSIGNEDBYTE)fcp->data.font.style);
- }
- byte_write(outfp, fcp->data.font.stroke_weight);
- if (fcp->data.font.header_format == DJ500FONTFORMAT)
- {
- int_write(outfp, fcp->data.font.typeface);
- }
- else
- {
- byte_write(outfp, (UNSIGNEDBYTE)fcp->data.font.typeface);
- }
- byte_write(outfp, fcp->data.font.slant);
- byte_write(outfp, fcp->data.font.serif_style);
- byte_write(outfp, fcp->data.font.quality);
- byte_write(outfp, fcp->data.font.placement);
- byte_write(outfp, fcp->data.font.underline_distance);
- byte_write(outfp, fcp->data.font.underline_height);
-
- int_write(outfp, fcp->data.font.text_height);
- int_write(outfp, fcp->data.font.text_width);
- int_write(outfp, fcp->data.font.first_code);
- int_write(outfp, fcp->data.font.last_code);
-
- byte_write(outfp, fcp->data.font.pitch_extended);
- byte_write(outfp, fcp->data.font.height_extended);
-
- int_write(outfp, fcp->data.font.reserved2);
- int_write(outfp, fcp->data.font.font_number_top);
- int_write(outfp, fcp->data.font.font_number_bot);
-
- for (i = 0; i < sizeof(fcp->data.font.name); i++)
- byte_write(outfp, fcp->data.font.name[i]);
-
- if (fcp->data.font.size >= DJFDSIZE)
- {
- int_write(outfp, fcp->data.font.h_pixel_resolution);
- int_write(outfp, fcp->data.font.v_pixel_resolution);
-
- byte_write(outfp, fcp->data.font.tdu_distance);
- byte_write(outfp, fcp->data.font.tdu_height);
- byte_write(outfp, fcp->data.font.bdu_distance);
- byte_write(outfp, fcp->data.font.bdu_height);
-
- int_write(outfp, fcp->data.font.specific_size);
- int_write(outfp, fcp->data.font.data_size);
-
- byte_write(outfp, fcp->data.font.unidirection);
- byte_write(outfp, fcp->data.font.compressed);
- byte_write(outfp, fcp->data.font.hold_time_factor);
- byte_write(outfp, fcp->data.font.no_half_pitch);
- byte_write(outfp, fcp->data.font.no_double_pitch);
- byte_write(outfp, fcp->data.font.no_half_height);
- byte_write(outfp, fcp->data.font.no_bold);
- byte_write(outfp, fcp->data.font.no_draft);
- byte_write(outfp, fcp->data.font.bold_method);
- byte_write(outfp, fcp->data.font.reserved3);
-
- int_write(outfp, fcp->data.font.baseline_offset_2);
- int_write(outfp, fcp->data.font.baseline_offset_3);
- int_write(outfp, fcp->data.font.baseline_offset_4);
-
- if (fcp->data.font.specific_size >= DJ500SSIZE)
- {
- for (i = 0; i < sizeof(fcp->data.font.name_extension); i++)
- byte_write(outfp, fcp->data.font.name_extension[i]);
- }
- }
-
- if ((len = strlen(fcp->data.font.comment)) > 0)
- if (fwrite(fcp->data.font.comment, 1, len, outfp) != len)
- return(ERROR);
-
- return(OK);
- }
-
- static int character_code_read(infp, fcp)
- FILE *infp;
- FONT_COMMAND *fcp;
- {
- /*
- * Nothing to do here as the character code command doesn't have
- * an associated descriptor
- */
- return(OK);
- }
- static int character_code_write(outfp, fcp)
- FILE *outfp;
- FONT_COMMAND *fcp;
- {
- /*
- * Nothing to do here as the character code command doesn't have
- * an associated descriptor
- */
- return(OK);
- }
-
- static int character_descriptor_read(infp, fcp)
- FILE *infp;
- FONT_COMMAND *fcp;
- {
- /*
- * Read a character descriptor. Fortunately character descriptors
- * don't seem to have comments. Half-way through reading the
- * descriptor you discover which kind you're dealing with and
- * switch to different code for each.
- */
- int nd = fcp->number;
- struct ljchar_struct *ljcp;
- struct djchar_struct *djcp;
-
- byte_read(nd, infp, fcp->data.character.format);
- byte_read(nd, infp, fcp->data.character.continuation);
-
- switch(fcp->data.character.format)
- {
- default:
- case LJCHARFORMAT:
- ljcp = &fcp->data.character.data.ljchar;
-
- byte_read(nd, infp, ljcp->descriptor_size);
- byte_read(nd, infp, ljcp->class);
- byte_read(nd, infp, ljcp->orientation);
- byte_read(nd, infp, ljcp->reserved);
-
- int_read(nd, infp, ljcp->left_offset);
- int_read(nd, infp, ljcp->top_offset);
- int_read(nd, infp, ljcp->character_width);
- int_read(nd, infp, ljcp->character_height);
- int_read(nd, infp, ljcp->delta_x);
-
- if (nd > BITMAP_SIZE_MAX)
- return(ERROR);
-
- if (fread(ljcp->bitmap, 1, nd, infp) != nd)
- return(ERROR);
- break;
- case DJCHARFORMAT:
- case DJPCHARFORMAT:
- case DJ500CHARFORMAT:
- djcp = &fcp->data.character.data.djchar;
-
- byte_read(nd, infp, djcp->descriptor_size);
- byte_read(nd, infp, djcp->char_type);
- byte_read(nd, infp, djcp->character_width);
- byte_read(nd, infp, djcp->comp_width);
- byte_read(nd, infp, djcp->left_offset);
- byte_read(nd, infp, djcp->right_offset);
-
- if (nd > BITMAP_SIZE_MAX)
- return(ERROR);
-
- if (fread(djcp->bitmap, 1, nd, infp) != nd)
- return(ERROR);
- break;
- }
-
- return(OK);
- }
- static int character_descriptor_write(outfp, fcp)
- FILE *outfp;
- FONT_COMMAND *fcp;
- {
- /*
- * Write a character descriptor.
- */
- int nd = fcp->number;
- struct ljchar_struct *ljcp;
- struct djchar_struct *djcp;
-
- byte_write(outfp, fcp->data.character.format);
- byte_write(outfp, fcp->data.character.continuation);
-
- switch(fcp->data.character.format)
- {
- default:
- case LJCHARFORMAT:
- ljcp = &fcp->data.character.data.ljchar;
-
- byte_write(outfp, ljcp->descriptor_size);
- byte_write(outfp, ljcp->class);
- byte_write(outfp, ljcp->orientation);
- byte_write(outfp, ljcp->reserved);
-
- int_write(outfp, ljcp->left_offset);
- int_write(outfp, ljcp->top_offset);
- int_write(outfp, ljcp->character_width);
- int_write(outfp, ljcp->character_height);
- int_write(outfp, ljcp->delta_x);
-
- nd -= (2 + ljcp->descriptor_size);
-
- if (fwrite(ljcp->bitmap, 1, nd, outfp) != nd)
- return(ERROR);
- break;
- case DJCHARFORMAT:
- case DJPCHARFORMAT:
- case DJ500CHARFORMAT:
- djcp = &fcp->data.character.data.djchar;
-
- byte_write(outfp, djcp->descriptor_size);
- byte_write(outfp, djcp->char_type);
- byte_write(outfp, djcp->character_width);
- byte_write(outfp, djcp->comp_width);
- byte_write(outfp, djcp->left_offset);
- byte_write(outfp, djcp->right_offset);
-
- nd -= (2 + djcp->descriptor_size);
-
- if (fwrite(djcp->bitmap, 1, nd, outfp) != nd)
- return(ERROR);
- break;
- }
-
- return(OK);
- }
-
- /*
- * LOW LEVEL I/O
- */
-
- static int do_byte_read(nbp, fp, dp)
- int *nbp;
- FILE *fp;
- UNSIGNEDBYTE *dp;
- {
- /*
- * If there's enough data available, read a byte, checking for
- * errors.
- */
- int wrk;
-
- if ((*nbp -=1) < 0)
- *dp = 0;
- else if ((wrk = getc(fp)) == EOF)
- return(ERROR);
- else
- *dp = wrk;
-
- return(OK);
- }
-
- static int do_int_read(nbp, fp, dp)
- int *nbp;
- FILE *fp;
- UNSIGNEDINT *dp;
- {
- /*
- * If there's enough data available, read a word, checking for
- * errors.
- */
- int wrk;
-
- if ((*nbp -= 2) < 0)
- *dp = 0;
- else
- {
- if ((wrk = getc(fp)) == EOF)
- return(ERROR);
-
- *dp = (wrk << 8);
-
- if ((wrk = getc(fp)) == EOF)
- return(ERROR);
-
- *dp |= wrk;
- }
-
- return(OK);
- }
-
- static int do_byte_write(fp, src)
- FILE *fp;
- UNSIGNEDBYTE src;
- {
- /*
- * Write a byte, checking for errors
- */
-
- if (putc(src, fp) == EOF)
- return(ERROR);
-
- return(OK);
- }
-
- static int do_int_write(fp, src)
- FILE *fp;
- UNSIGNEDINT src;
- {
- /*
- * Write a word, checking for errors
- */
-
- if (putc(src>>8,fp) == EOF)
- return(ERROR);
-
- if (putc(src&0xff,fp) == EOF)
- return(ERROR);
-
- return(OK);
- }
-