static int gf_read_bitmap(FILE *p, DviFontChar *ch) { int op; int min_n, max_n; int min_m, max_m; int paint_switch; int x, y; int bpl; Int32 par; BmUnit *line; BITMAP *map; fseek(p, (long)ch->offset, SEEK_SET); op = fuget1(p); if(op == GF_BOC) { /* skip character code */ fuget4(p); /* skip pointer */ fuget4(p); min_m = fsget4(p); max_m = fsget4(p); min_n = fsget4(p); max_n = fsget4(p); } else if(op == GF_BOC1) { /* skip character code */ fuget1(p); min_m = fuget1(p); /* this is max_m - min_m */ max_m = fuget1(p); min_n = fuget1(p); /* this is max_n - min_n */ max_n = fuget1(p); min_m = max_m - min_m; min_n = max_n - min_n; } else { mdvi_error(_("GF: invalid opcode %d in character %d\n"), op, ch->code); return -1; } ch->x = -min_m; ch->y = max_n; ch->width = max_m - min_m + 1; ch->height = max_n - min_n + 1; map = bitmap_alloc(ch->width, ch->height); ch->glyph.data = map; ch->glyph.x = ch->x; ch->glyph.y = ch->y; ch->glyph.w = ch->width; ch->glyph.h = ch->height; #define COLOR(x) ((x) ? "BLACK" : "WHITE") paint_switch = WHITE; x = y = 0; line = map->data; bpl = map->stride; DEBUG((DBG_BITMAPS, "(gf) reading character %d\n", ch->code)); while((op = fuget1(p)) != GF_EOC) { Int32 n; if(feof(p)) break; if(op == GF_PAINT0) { DEBUG((DBG_BITMAPS, "(gf) Paint0 %s -> %s\n", COLOR(paint_switch), COLOR(!paint_switch))); paint_switch = !paint_switch; } else if(op <= GF_PAINT3) { if(op < GF_PAINT1) par = op; else par = fugetn(p, op - GF_PAINT1 + 1); if(y >= ch->height || x + par >= ch->width) goto toobig; /* paint everything between columns x and x + par - 1 */ DEBUG((DBG_BITMAPS, "(gf) Paint %d %s from (%d,%d)\n", par, COLOR(paint_switch), x, y)); if(paint_switch == BLACK) bitmap_paint_bits(line + (x / BITMAP_BITS), x % BITMAP_BITS, par); paint_switch = !paint_switch; x += par; } else if(op >= GF_NEW_ROW_0 && op <= GF_NEW_ROW_MAX) { y++; line = bm_offset(line, bpl); x = op - GF_NEW_ROW_0; paint_switch = BLACK; DEBUG((DBG_BITMAPS, "(gf) new_row_%d\n", x)); } else switch(op) { case GF_SKIP0: y++; line = bm_offset(line, bpl); x = 0; paint_switch = WHITE; DEBUG((DBG_BITMAPS, "(gf) skip_0\n")); break; case GF_SKIP1: case GF_SKIP2: case GF_SKIP3: par = fugetn(p, op - GF_SKIP1 + 1); y += par + 1; line = bm_offset(line, (par + 1) * bpl); x = 0; paint_switch = WHITE; DEBUG((DBG_BITMAPS, "(gf) skip_%d\n", op - GF_SKIP1)); break; case GF_XXX1: case GF_XXX2: case GF_XXX3: case GF_XXX4: { #ifndef NODEBUG char *s; s = read_string(p, op - GF_XXX1 + 1, NULL, 0); DEBUG((DBG_SPECIAL, "(gf) Character %d: Special \"%s\"\n", ch->code, s)); mdvi_free(s); #else n = fugetn(p, op - GF_XXX1 + 1); fseek(p, (long)n, SEEK_CUR); #endif break; } case GF_YYY: n = fuget4(p); DEBUG((DBG_SPECIAL, "(gf) Character %d: MF special %u\n", ch->code, n)); break; case GF_NOOP: DEBUG((DBG_BITMAPS, "(gf) no_op\n")); break; default: mdvi_error(_("(gf) Character %d: invalid opcode %d\n"), ch->code, op); goto error; } /* chech that we're still inside the bitmap */ if(x > ch->width || y > ch->height) goto toobig; DEBUG((DBG_BITMAPS, "(gf) curr_loc @ (%d,%d)\n", x, y)); } if(op != GF_EOC) goto error; DEBUG((DBG_BITMAPS, "(gf) end of character %d\n", ch->code)); return 0; toobig: mdvi_error(_("(gf) character %d has an incorrect bounding box\n"), ch->code); error: bitmap_destroy(map); ch->glyph.data = NULL; return -1; }
static DviContext * mdvi_init_context (const char *file) { FILE *p; gint32 arg; int op; int n; DviContext *dvi; char *filename; /* * 1. Open the file and initialize the DVI context */ filename = opendvi (file); if (filename == NULL) { return NULL; } p = fopen (filename, "rb"); if (p == NULL) { g_free (filename); return NULL; } dvi = g_new0 (DviContext, 1); dvi->filename = filename; dvi->in = p; /* * 2. Read the preamble, extract scaling information */ if (fuget1 (p) != DVI_PRE) { goto error; } if ((arg = fuget1 (p)) != DVI_ID) { g_message ("Unsupported DVI format (version %u)", arg); goto error; } /* get dimensions */ dvi->num = fuget4 (p); dvi->den = fuget4 (p); dvi->dvimag = fuget4 (p); /* check that these numbers make sense */ if (!dvi->num || !dvi->den || !dvi->dvimag) { goto error; } /* get the comment from the preamble */ n = fuget1 (p); dvi->fileid = g_malloc (n + 1); fread (dvi->fileid, 1, n, p); dvi->fileid[n] = 0; g_debug ("Preamble Comment: '%s'", dvi->fileid); /* * 3. Read postamble, extract page information (number of * pages, dimensions) and stack depth. */ /* jump to the end of the file */ if (fseek (p, (long) - 1, SEEK_END) == -1) { goto error; } for (n = 0; (op = fuget1 (p)) == DVI_TRAILER; n++) { if (fseek (p, (long) - 2, SEEK_CUR) < 0) { break; } } if (op != arg || n < 4) { goto error; } /* get the pointer to postamble */ fseek (p, (long) - 5, SEEK_CUR); arg = fuget4 (p); /* jump to it */ fseek (p, (long) arg, SEEK_SET); if (fuget1 (p) != DVI_POST) { goto error; } fuget4 (p); /* offset */ if (dvi->num != fuget4 (p) || dvi->den != fuget4 (p) || dvi->dvimag != fuget4 (p)) { goto error; } dvi->dvi_page_h = fuget4 (p); dvi->dvi_page_w = fuget4 (p); dvi->stacksize = fuget2 (p); dvi->npages = fuget2 (p); g_debug ("Postamble: %d pages", dvi->npages); return dvi; error: mdvi_destroy_context (dvi); return NULL; }
static int gf_load_font(DviParams *unused, DviFont *font) { int i; int n; int loc; int hic; FILE *p; Int32 word; int op; long alpha, beta, z; #ifndef NODEBUG char s[256]; #endif p = font->in; /* check preamble */ loc = fuget1(p); hic = fuget1(p); if(loc != GF_PRE || hic != GF_ID) goto badgf; loc = fuget1(p); #ifndef NODEBUG for(i = 0; i < loc; i++) s[i] = fuget1(p); s[i] = 0; DEBUG((DBG_FONTS, "(gf) %s: %s\n", font->fontname, s)); #else fseek(p, (long)loc, SEEK_CUR); #endif /* now read character locators in postamble */ if(fseek(p, (long)-1, SEEK_END) == -1) return -1; n = 0; while((op = fuget1(p)) == GF_TRAILER) { if(fseek(p, (long)-2, SEEK_CUR) < 0) break; n++; } if(op != GF_ID || n < 4) goto badgf; /* get the pointer to the postamble */ fseek(p, (long)-5, SEEK_CUR); op = fuget4(p); /* jump to it */ fseek(p, (long)op, SEEK_SET); if(fuget1(p) != GF_POST) goto badgf; /* skip pointer to last EOC */ fuget4(p); /* get the design size */ font->design = fuget4(p); /* the checksum */ word = fuget4(p); if(word && font->checksum && font->checksum != word) { mdvi_warning(_("%s: bad checksum (expected %u, found %u)\n"), font->fontname, font->checksum, word); } else if(!font->checksum) font->checksum = word; /* skip pixels per point ratio */ fuget4(p); fuget4(p); font->chars = xnalloc(DviFontChar, 256); for(loc = 0; loc < 256; loc++) font->chars[loc].offset = 0; /* skip glyph "bounding box" */ fseek(p, (long)16, SEEK_CUR); loc = 256; hic = -1; TFMPREPARE(font->scale, z, alpha, beta); while((op = fuget1(p)) != GF_POST_POST) { DviFontChar *ch; int cc; /* get the character code */ cc = fuget1(p); if(cc < loc) loc = cc; if(cc > hic) hic = cc; ch = &font->chars[cc]; switch(op) { case GF_LOC: fsget4(p); /* skip dx */ fsget4(p); /* skip dy */ break; case GF_LOC0: fuget1(p); /* skip dx */ /* dy assumed 0 */ break; default: mdvi_error(_("%s: junk in postamble\n"), font->fontname); goto error; } ch->code = cc; ch->tfmwidth = fuget4(p); ch->tfmwidth = TFMSCALE(ch->tfmwidth, z, alpha, beta); ch->offset = fuget4(p); if(ch->offset == -1) ch->offset = 0; /* initialize the rest of the glyph information */ ch->x = 0; ch->y = 0; ch->width = 0; ch->height = 0; ch->glyph.data = NULL; ch->shrunk.data = NULL; ch->grey.data = NULL; ch->flags = 0; ch->loaded = 0; } if(op != GF_POST_POST) goto badgf; if(loc > 0 || hic < 255) { /* shrink to optimal size */ 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; badgf: mdvi_error(_("%s: File corrupted, or not a GF file\n"), font->fontname); error: if(font->chars) { mdvi_free(font->chars); font->chars = NULL; } font->loc = font->hic = 0; return -1; }