/* * Get any character by its code. */ static int gf_get_char (gf_font_t *font, gf_char_t *sym, unsigned char charcode) { gf_locator_t *loc; unsigned char c, col_delta, row_delta; long lcode, back_pointer; loc = &font->char_loc [charcode]; if (loc->char_pointer == -1) return 0; sym->font = font; sym->h_escapement = loc->h_escapement; sym->tfm_width = loc->tfm_width; if (fseek (font->input_file, loc->char_pointer, SEEK_SET) < 0) { fprintf (stderr, "%s: seek error\n", font->input_filename); return 0; } /* This reads the character starting from the current position * (but some specials might come first). */ skip_specials (font); c = get_byte (font); switch (c) { case BOC: /* If the back pointer actually points somewhere, * this character is a ``residue'', and the font * is probably too big. */ lcode = (long) get_four (font); if (lcode < 0 || lcode > 255) { /* Someone is trying to use a font with character codes * that are out of our range. */ fprintf (stderr, "%s: invalid character code %ld (expected %d)\n", font->input_filename, lcode, charcode); return 0; } sym->charcode = lcode; back_pointer = (long) get_four (font); if (back_pointer != -1) fprintf (stderr, "%s: warning: character %u has a non-null back pointer (to %#lx)\n", font->input_filename, sym->charcode, back_pointer); sym->bbox_min_col = (long) get_four (font); sym->bbox_max_col = (long) get_four (font); sym->bbox_min_row = (long) get_four (font); sym->bbox_max_row = (long) get_four (font); break; case BOC1: sym->charcode = get_byte (font); col_delta = get_byte (font); sym->bbox_max_col = get_byte (font); sym->bbox_min_col = sym->bbox_max_col - col_delta; row_delta = get_byte (font); sym->bbox_max_row = get_byte (font); sym->bbox_min_row = sym->bbox_max_row - row_delta; break; case POST: return 0; default: fprintf (stderr, "%s: error reading character (found %u)\n", font->input_filename, c); return 0; } if (sym->charcode != charcode) { fprintf (stderr, "%s: warning: character code mismatch, %d != %d\n", font->input_filename, sym->charcode, charcode); } get_character_bitmap (sym); deblank (sym); return 1; }
void InitPK(struct font_entry * tfontp) { unsigned char* position; struct char_entry *tcharptr; /* temporary char_entry pointer */ uint32_t hppp, vppp, packet_length; uint32_t c; DEBUG_PRINT((DEBUG_DVI|DEBUG_PK),("\n OPEN FONT:\t'%s'", tfontp->name)); Message(BE_VERBOSE,"<%s>", tfontp->name); if (MmapFile(tfontp->name,&(tfontp->fmmap))) Fatal("font file %s unusable", tfontp->name); position=(unsigned char*)tfontp->fmmap.data; if (tfontp->fmmap.size < 2 || tfontp->fmmap.size < 3+*(position+2)+16) Fatal("PK file %s ends prematurely",tfontp->name); if (*position++ != PK_PRE) Fatal("unknown font format in file %s",tfontp->name); if (*position++ != PK_ID) Fatal( "wrong version %d of PK file %s (should be 89)", (int)*(position-1),tfontp->name); DEBUG_PRINT(DEBUG_PK,("\n PK_PRE:\t'%.*s'",(int)*position, position+1)); position += *position + 1; tfontp->designsize = UNumRead(position, 4); DEBUG_PRINT(DEBUG_PK,(" %d", tfontp->designsize)); tfontp->type = FONT_TYPE_PK; c = UNumRead(position+4, 4); DEBUG_PRINT(DEBUG_PK,(" %d", c)); CheckChecksum (tfontp->c, c, tfontp->name); hppp = UNumRead(position+8, 4); vppp = UNumRead(position+12, 4); DEBUG_PRINT(DEBUG_PK,(" %d %d", hppp,vppp)); if (hppp != vppp) Warning("aspect ratio is %d:%d (should be 1:1)", hppp, vppp); tfontp->magnification = (uint32_t)((uint64_t)hppp * 7227 * 5 / 65536l + 50)/100; position+=16; /* Read char definitions */ position = skip_specials(position); while (*position != PK_POST) { DEBUG_PRINT(DEBUG_PK,("\n @%ld PK CHAR:\t%d", (long)((char *)position - tfontp->fmmap.data), *position)); if ((tcharptr = malloc(sizeof(struct char_entry))) == NULL) Fatal("cannot allocate space for char_entry"); tcharptr->flag_byte = *position; tcharptr->data = NULL; tcharptr->tfmw = 0; if ((*position & 7) == 7) { packet_length = UNumRead(position+1,4); c = UNumRead(position+5, 4); position += 9; } else if (*position & 4) { packet_length = (*position & 3) * 65536l + UNumRead(position+1, 2); c = UNumRead(position+3, 1); position += 4; } else { packet_length = (*position & 3) * 256 + UNumRead(position+1, 1); c = UNumRead(position+2, 1); position += 3; } DEBUG_PRINT(DEBUG_PK,(" %d %d",packet_length,c)); if (c > (LASTFNTCHAR)) Fatal("PK font %s exceeds char numbering limit",tfontp->name); tcharptr->length = packet_length; tcharptr->pkdata = position; tfontp->chr[c]=tcharptr; position += packet_length; position = skip_specials(position); } }
/* * The ``bitmap'' is a sequence of commands that describe it in terms of * run-length encoding. * * GF's row and column numbers are the lower left corner of a pixel. * GF (0,0) is the Cartesian unit square: 0 <= x (col) <= 1, * 0 <= y (row) <= 1. Yes, it's <=, not <. What does this mean for * the maxes and mins? Let's take the height first: if a character has * min_row = 0 and max_row = 10, we start the ``current'' y at 10, * (possibly) paint some pixels on that row, ..., and end up with it at * zero, (possibly) painting some pixels on that row. Thus, there are * 11 (10 - 0 + 1) rows in which we might paint pixels. Now the width: * if a character has min_row = 0 and max_row = 4, the current x starts * at zero, we paint four pixels (let's say), and now the current x is * four (the max possible), so we cannot paint any more. Thus there are * four (4 - 0) columns in which we might paint pixels. * * Weird, huh? */ static void get_character_bitmap (gf_char_t *sym) { unsigned char c; /* We expect these to be >= 0, but if the GF file is improper, * they might turn to be negative. */ int height, width, painting_black = 0; int cur_x, cur_y; /* This will be the GF position. */ cur_x = sym->bbox_min_col; cur_y = sym->bbox_max_row; width = sym->bbox_max_col - sym->bbox_min_col; height = sym->bbox_max_row - sym->bbox_min_row + 1; /* If the character has zero or negative extent in either dimension, * it's not going to have a bitmap. (If this happens, the GF file is * incorrect; but the discrepancy isn't serious, so we may as well not * bomb out when it happens, especially since PKtoGF has a bug that * produces such a bounding box when the character is all blank.) */ if (width <= 0 || height <= 0) { sym->height = 0; sym->width = 0; sym->bitmap = 0; /* The next non-NO_OP byte should be EOC. */ while ((c = get_byte (sym->font)) == NO_OP) continue; /* do nothing */ if (c != EOC) { fprintf (stderr, "%s: expected eoc (for a blank character), found %u\n", sym->font->input_filename, c); exit (-1); } return; } sym->height = height; sym->width = width; sym->bitmap = calloc (width, height); if (! sym->bitmap) { fprintf (stderr, "%s: out of memory\n", sym->font->input_filename); exit (-1); } for (;;) { c = get_byte (sym->font); if (c == EOC) break; if (/* PAINT_0 <= c && */ c <= PAINT3) { /* No need to test if `PAINT_0 <= c'; it must be, * since PAINT_0 is zero and `c' is unsigned. */ /* The paint commands come in two varieties -- either * with the length implicitly part of the command, * or where it is specified as a separate parameter. */ unsigned length; if (/* PAINT_0 <= c && */ c <= PAINT_63) length = c - PAINT_0; else { switch (c) { case PAINT1: length = get_byte (sym->font); break; case PAINT2: length = get_two (sym->font); break; case PAINT3: length = get_three (sym->font); break; default: fprintf (stderr, "%s: invalid painting command %u\n", sym->font->input_filename, c); exit (-1); } } /* We have to translate from Cartesian to * C coordinates. That means the x's are the same, * but the y's are flipped. */ if (painting_black) { unsigned matrix_x, matrix_y; matrix_y = sym->bbox_max_row - cur_y; for (; length != 0; length--) { matrix_x = cur_x - sym->bbox_min_col; PIXEL (sym, matrix_y, matrix_x) = 255; cur_x++; } } else { cur_x += length; } painting_black = ! painting_black; } else if (SKIP0 <= c && c <= SKIP3) { /* Skip commands move down in the GF character, * leaving blank rows. */ unsigned rows_to_skip; switch (c) { case SKIP0: rows_to_skip = 0; break; case SKIP1: rows_to_skip = get_byte (sym->font); break; case SKIP2: rows_to_skip = get_two (sym->font); break; case SKIP3: rows_to_skip = get_three (sym->font); break; default: fprintf (stderr, "%s: invalid skip command %u\n", sym->font->input_filename, c); exit (-1); } cur_y -= rows_to_skip + 1; cur_x = sym->bbox_min_col; painting_black = 0; } else if (NEW_ROW_0 <= c && c <= NEW_ROW_164) { /* `new_row' commands move to the next line down * and then over. */ cur_y--; cur_x = sym->bbox_min_col + c - NEW_ROW_0; painting_black = 1; } else if (c == NO_OP) { /* do nothing */ } else if ((XXX1 <= c && c <= XXX4) || c == YYY) { skip_specials (sym->font); } else { fprintf (stderr, "%s: expected paint or skip or new_row, found %u\n", sym->font->input_filename, c); exit (-1); } } }