diff options
Diffstat (limited to 'dvi/mdvi-lib/pk.c')
-rw-r--r-- | dvi/mdvi-lib/pk.c | 569 |
1 files changed, 0 insertions, 569 deletions
diff --git a/dvi/mdvi-lib/pk.c b/dvi/mdvi-lib/pk.c deleted file mode 100644 index 48da008..0000000 --- a/dvi/mdvi-lib/pk.c +++ /dev/null @@ -1,569 +0,0 @@ - -/* Copyright (C) 2000, Matias Atria - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * History: - * - * 11/3/2000: - * - First working version - * 11/4/2000: - * - FIXED: entirely white/black rows were missed. - * 11/8/2000: - * - TESTED: Glyphs are rendered correctly in different byte orders. - * - Made bitmap code much more efficient and compact. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <math.h> - -#include "mdvi.h" -#include "private.h" - -#define PK_ID 89 -#define PK_CMD_START 240 -#define PK_X1 240 -#define PK_X2 241 -#define PK_X3 242 -#define PK_X4 243 -#define PK_Y 244 -#define PK_POST 245 -#define PK_NOOP 246 -#define PK_PRE 247 - -#define PK_DYN_F(x) (((x) >> 4) & 0xf) -#define PK_PACKED(x) (PK_DYN_F(x) != 14) - -static int pk_load_font __PROTO((DviParams *, DviFont *)); -static int pk_font_get_glyph __PROTO((DviParams *, DviFont *, int)); - -static int pk_auto_generate = 1; /* this is ON by default */ - -typedef struct { - char currbyte; - char nybpos; - int dyn_f; -} pkread; - -static char *pk_lookup __PROTO((const char *, Ushort *, Ushort *)); -static char *pk_lookupn __PROTO((const char *, Ushort *, Ushort *)); - -/* only symbols exported by this file */ -DviFontInfo pk_font_info = { - "PK", - 0, /* scaling not supported natively */ - pk_load_font, - pk_font_get_glyph, - mdvi_shrink_glyph, - mdvi_shrink_glyph_grey, - NULL, /* free */ - NULL, /* reset */ - pk_lookup, /* lookup */ - kpse_pk_format, - NULL -}; - -DviFontInfo pkn_font_info = { - "PKN", - 0, /* scaling not supported natively */ - pk_load_font, - pk_font_get_glyph, - mdvi_shrink_glyph, - mdvi_shrink_glyph_grey, - NULL, /* free */ - NULL, /* reset */ - pk_lookupn, /* lookup */ - kpse_pk_format, - NULL -}; - -static char *pk_lookup(const char *name, Ushort *hdpi, Ushort *vdpi) -{ - kpse_glyph_file_type type; - char *filename; - - if(pk_auto_generate == 0) { - kpse_set_program_enabled(kpse_pk_format, 1, kpse_src_cmdline); - pk_auto_generate = 1; - } - filename = kpse_find_glyph(name, Max(*hdpi, *vdpi), - kpse_pk_format, &type); - if(filename && type.source == kpse_glyph_source_fallback) { - mdvi_free(filename); - filename = NULL; - } else if(filename) { - *hdpi = *vdpi = type.dpi; - } - return filename; -} - -static char *pk_lookupn(const char *name, Ushort *hdpi, Ushort *vdpi) -{ - kpse_glyph_file_type type; - char *filename; - - if(pk_auto_generate) { - kpse_set_program_enabled(kpse_pk_format, 0, kpse_src_cmdline); - pk_auto_generate = 0; - } - filename = kpse_find_glyph(name, Max(*hdpi, *vdpi), - kpse_pk_format, &type); - if(filename && type.source == kpse_glyph_source_fallback) { - mdvi_free(filename); - filename = NULL; - } else if(filename) { - *hdpi = *vdpi = type.dpi; - } - return filename; -} - -static inline int pk_get_nyb(FILE *p, pkread *pk) -{ - unsigned t; - int nb; - char c; - - t = c = pk->currbyte; - nb = pk->nybpos; - - switch(nb) { - case 0: - c = pk->currbyte = fuget1(p); - t = (c >> 4); - break; - case 1: - t = c; - break; - } - pk->nybpos = !nb; - return (t & 0xf); -} - -/* - * this is a bit cumbersome because we have to pass around - * the `pkread' data... - */ -static int pk_packed_num(FILE *p, pkread *pkr, int *repeat) -{ - int i, j; - int dyn_f = pkr->dyn_f; - - i = pk_get_nyb(p, pkr); - if(i == 0) { - do { - j = pk_get_nyb(p, pkr); - i++; - } while(j == 0); - while(i-- > 0) - j = (j << 4) + pk_get_nyb(p, pkr); - return (j - 15 + ((13 - dyn_f) << 4) + - dyn_f); - } else if(i <= dyn_f) - return i; - else if(i < 14) - return ((i - dyn_f - 1) << 4) + - pk_get_nyb(p, pkr) + dyn_f + 1; - else { - *repeat = 1; - if(i == 14) - *repeat = pk_packed_num(p, pkr, repeat); - return pk_packed_num(p, pkr, repeat); - } -} - -#define ROUND(x,y) (((x) + (y) - 1) / (y)) - -static BITMAP *get_bitmap(FILE *p, int w, int h, int flags) -{ - int i, j; - BmUnit *ptr; - BITMAP *bm; - int bitpos; - int currch; - - flags = 0; /* shut up that compiler */ - bitpos = -1; - if((bm = bitmap_alloc(w, h)) == NULL) - return NULL; - DEBUG((DBG_BITMAPS, "get_bitmap(%d,%d,%d): reading raw bitmap\n", - w, h, flags)); - ptr = bm->data; - currch = 0; - for(i = 0; i < h; i++) { - BmUnit mask; - - mask = FIRSTMASK; - for(j = 0; j < w; j++) { - if(bitpos < 0) { - currch = fuget1(p); - bitpos = 7; - } - if(currch & (1 << bitpos)) - *ptr |= mask; - bitpos--; - if(mask == LASTMASK) { - ptr++; - mask = FIRSTMASK; - } else - NEXTMASK(mask); - } - ptr = bm_offset(ptr, bm->stride); - } - return bm; -} - -static BITMAP *get_packed(FILE *p, int w, int h, int flags) -{ - int inrow, count; - int row; - BITMAP *bm; - int repeat_count; - int paint; - pkread pkr; - - pkr.nybpos = 0; - pkr.currbyte = 0; - pkr.dyn_f = PK_DYN_F(flags); - paint = !!(flags & 0x8); - - repeat_count = 0; - row = 0; - inrow = w; - if((bm = bitmap_alloc(w, h)) == NULL) - return NULL; - DEBUG((DBG_BITMAPS, "get_packed(%d,%d,%d): reading packed glyph\n", - w, h, flags)); - while(row < h) { - int i = 0; - - count = pk_packed_num(p, &pkr, &i); - if(i > 0) { - if(repeat_count) - fprintf(stderr, "second repeat count for this row (had %d and got %d)\n", - repeat_count, i); - repeat_count = i; - } - - if(count >= inrow) { - Uchar *r, *t; - BmUnit *a, mask; - - /* first finish current row */ - if(paint) - bitmap_set_row(bm, row, w - inrow, inrow, paint); - /* now copy it as many times as required */ - r = (Uchar *)bm->data + row * bm->stride; - while(repeat_count-- > 0) { - t = r + bm->stride; - /* copy entire lines */ - memcpy(t, r, bm->stride); - r = t; - row++; - } - repeat_count = 0; - /* count first row we drew */ - row++; - /* update run count */ - count -= inrow; - /* now r points to the beginning of the last row we finished */ - if(paint) - mask = ~((BmUnit)0); - else - mask = 0; - /* goto next row */ - a = (BmUnit *)(r + bm->stride); - /* deal with entirely with/black rows */ - while(count >= w) { - /* count number of atoms in a row */ - i = ROUND(w, BITMAP_BITS); - while(i-- > 0) - *a++ = mask; - count -= w; - row++; - } - inrow = w; - } - if(count > 0) - bitmap_set_row(bm, row, w - inrow, count, paint); - inrow -= count; - paint = !paint; - } - if(row != h || inrow != w) { - error(_("Bad PK file: More bits than required\n")); - bitmap_destroy(bm); - return NULL; - } - return bm; -} - -static BITMAP *get_char(FILE *p, int w, int h, int flags) -{ - /* check if dyn_f == 14 */ - if(((flags >> 4) & 0xf) == 14) - return get_bitmap(p, w, h, flags); - else - return get_packed(p, w, h, flags); -} - -/* supports any number of characters in a font */ -static int pk_load_font(DviParams *unused, DviFont *font) -{ - int i; - int flag_byte; - int loc, hic, maxch; - Int32 checksum; - FILE *p; -#ifndef NODEBUG - char s[256]; -#endif - long alpha, beta, z; - - font->chars = xnalloc(DviFontChar, 256); - p = font->in; - memzero(font->chars, 256 * sizeof(DviFontChar)); - for(i = 0; i < 256; i++) - font->chars[i].offset = 0; - - /* check the preamble */ - loc = fuget1(p); hic = fuget1(p); - if(loc != PK_PRE || hic != PK_ID) - goto badpk; - i = fuget1(p); -#ifndef NODEBUG - for(loc = 0; loc < i; loc++) - s[loc] = fuget1(p); - s[loc] = 0; - DEBUG((DBG_FONTS, "(pk) %s: %s\n", font->fontname, s)); -#else - fseek(in, (long)i, SEEK_CUR); -#endif - /* get the design size */ - font->design = fuget4(p); - /* get the checksum */ - checksum = fuget4(p); - if(checksum && font->checksum && font->checksum != checksum) { - warning(_("%s: checksum mismatch (expected %u, got %u)\n"), - font->fontname, font->checksum, checksum); - } else if(!font->checksum) - font->checksum = checksum; - /* skip pixel per point ratios */ - fuget4(p); - fuget4(p); - if(feof(p)) - goto badpk; - - /* now start reading the font */ - loc = 256; hic = -1; maxch = 256; - - /* initialize alpha and beta for TFM width computation */ - TFMPREPARE(font->scale, z, alpha, beta); - - while((flag_byte = fuget1(p)) != PK_POST) { - if(feof(p)) - break; - if(flag_byte >= PK_CMD_START) { - switch(flag_byte) { - case PK_X1: - case PK_X2: - case PK_X3: - case PK_X4: { -#ifndef NODEBUG - char *t; - int n; - - i = fugetn(p, flag_byte - PK_X1 + 1); - if(i < 256) - t = &s[0]; - else - t = mdvi_malloc(i + 1); - for(n = 0; n < i; n++) - t[n] = fuget1(p); - t[n] = 0; - DEBUG((DBG_SPECIAL, "(pk) %s: Special \"%s\"\n", - font->fontname, t)); - if(t != &s[0]) - mdvi_free(t); -#else - i = fugetn(p, flag_byte - PK_X1 + 1); - while(i-- > 0) - fuget1(p); -#endif - break; - } - case PK_Y: - i = fuget4(p); - DEBUG((DBG_SPECIAL, "(pk) %s: MF special %u\n", - font->fontname, (unsigned)i)); - break; - case PK_POST: - case PK_NOOP: - break; - case PK_PRE: - error(_("%s: unexpected preamble\n"), font->fontname); - goto error; - } - } else { - int pl; - int cc; - int w, h; - int x, y; - int offset; - long tfm; - - switch(flag_byte & 0x7) { - case 7: - pl = fuget4(p); - cc = fuget4(p); - offset = ftell(p) + pl; - tfm = fuget4(p); - fsget4(p); /* skip dx */ - fsget4(p); /* skip dy */ - w = fuget4(p); - h = fuget4(p); - x = fsget4(p); - y = fsget4(p); - break; - case 4: - case 5: - case 6: - pl = (flag_byte % 4) * 65536 + fuget2(p); - cc = fuget1(p); - offset = ftell(p) + pl; - tfm = fuget3(p); - fsget2(p); /* skip dx */ - /* dy assumed 0 */ - w = fuget2(p); - h = fuget2(p); - x = fsget2(p); - y = fsget2(p); - break; - default: - pl = (flag_byte % 4) * 256 + fuget1(p); - cc = fuget1(p); - offset = ftell(p) + pl; - tfm = fuget3(p); - fsget1(p); /* skip dx */ - /* dy assumed 0 */ - w = fuget1(p); - h = fuget1(p); - x = fsget1(p); - y = fsget1(p); - } - if(feof(p)) - break; - if(cc < loc) - loc = cc; - if(cc > hic) - hic = cc; - if(cc > maxch) { - font->chars = xresize(font->chars, - DviFontChar, cc + 16); - for(i = maxch; i < cc + 16; i++) - font->chars[i].offset = 0; - maxch = cc + 16; - } - font->chars[cc].code = cc; - font->chars[cc].flags = flag_byte; - font->chars[cc].offset = ftell(p); - font->chars[cc].width = w; - font->chars[cc].height = h; - font->chars[cc].glyph.data = NULL; - font->chars[cc].x = x; - font->chars[cc].y = y; - font->chars[cc].glyph.x = x; - font->chars[cc].glyph.y = y; - font->chars[cc].glyph.w = w; - font->chars[cc].glyph.h = h; - font->chars[cc].grey.data = NULL; - font->chars[cc].shrunk.data = NULL; - font->chars[cc].tfmwidth = TFMSCALE(z, tfm, alpha, beta); - font->chars[cc].loaded = 0; - fseek(p, (long)offset, SEEK_SET); - } - } - if(flag_byte != PK_POST) { - error(_("%s: unexpected end of file (no postamble)\n"), - font->fontname); - goto error; - } - while((flag_byte = fuget1(p)) != EOF) { - if(flag_byte != PK_NOOP) { - error(_("invalid PK file! (junk in postamble)\n")); - goto error; - } - } - - /* resize font char data */ - if(loc > 0 || hic < maxch-1) { - memmove(font->chars, font->chars + loc, - (hic - loc + 1) * sizeof(DviFontChar)); - font->chars = xresize(font->chars, - DviFontChar, hic - loc + 1); - } - font->loc = loc; - font->hic = hic; - return 0; - -badpk: - error(_("%s: File corrupted, or not a PK file\n"), font->fontname); -error: - mdvi_free(font->chars); - font->chars = NULL; - font->loc = font->hic = 0; - return -1; -} - -static int pk_font_get_glyph(DviParams *params, DviFont *font, int code) -{ - DviFontChar *ch; - - if((ch = FONTCHAR(font, code)) == NULL) - return -1; - - if(ch->offset == 0) - return -1; - DEBUG((DBG_GLYPHS, "(pk) loading glyph for character %d (%dx%d) in font `%s'\n", - code, ch->width, ch->height, font->fontname)); - if(font->in == NULL && font_reopen(font) < 0) - return -1; - if(!ch->width || !ch->height) { - /* this happens for ` ' (ASCII 32) in some fonts */ - ch->glyph.x = ch->x; - ch->glyph.y = ch->y; - ch->glyph.w = ch->width; - ch->glyph.h = ch->height; - ch->glyph.data = NULL; - return 0; - } - if(fseek(font->in, ch->offset, SEEK_SET) == -1) - return -1; - ch->glyph.data = get_char(font->in, - ch->width, ch->height, ch->flags); - if(ch->glyph.data) { - /* restore original settings */ - ch->glyph.x = ch->x; - ch->glyph.y = ch->y; - ch->glyph.w = ch->width; - ch->glyph.h = ch->height; - } else - return -1; - ch->loaded = 1; - return 0; -} |