/* create a color table */ Ulong *get_color_table(DviDevice *dev, int nlevels, Ulong fg, Ulong bg, double gamma, int density) { ColorCache *cc, *tofree; int lohits; Ulong *pixels; int status; lohits = color_cache[0].hits; tofree = &color_cache[0]; /* look in the cache and see if we have one that matches this request */ for(cc = &color_cache[0]; cc < &color_cache[cc_entries]; cc++) { if(cc->hits < lohits) { lohits = cc->hits; tofree = cc; } if(cc->fg == fg && cc->bg == bg && cc->density == density && cc->nlevels == nlevels && fabs(cc->gamma - gamma) <= GAMMA_DIFF) break; } if(cc < &color_cache[cc_entries]) { cc->hits++; return cc->pixels; } DEBUG((DBG_DEVICE, "Adding color table to cache (fg=%lu, bg=%lu, n=%d)\n", fg, bg, nlevels)); /* no entry was found in the cache, create a new one */ if(cc_entries < CCSIZE) { cc = &color_cache[cc_entries++]; cc->pixels = NULL; } else { cc = tofree; mdvi_free(cc->pixels); } pixels = xnalloc(Ulong, nlevels); status = dev->alloc_colors(dev->device_data, pixels, nlevels, fg, bg, gamma, density); if(status < 0) { mdvi_free(pixels); return NULL; } cc->fg = fg; cc->bg = bg; cc->gamma = gamma; cc->density = density; cc->nlevels = nlevels; cc->pixels = pixels; cc->hits = 1; return pixels; }
int mdvi_unregister_special(const char *prefix) { DviSpecial *sp; sp = find_special_prefix(prefix); if(sp == NULL) return -1; mdvi_free(sp->prefix); #ifdef WITH_REGEX_SPECIALS if(sp->has_reg) regfree(&sp->reg); #endif listh_remove(&specials, LIST(sp)); mdvi_free(sp); return 0; }
void font_drop_one(DviFontRef *ref) { DviFont *font; font = ref->ref; mdvi_free(ref); /* drop all children */ for(ref = font->subfonts; ref; ref = ref->next) { /* just adjust the reference counts */ ref->ref->links--; } if(--font->links == 0) { /* * this font doesn't have any more references, but * we still keep it around in case a virtual font * requests it. */ if(font->in) { fclose(font->in); font->in = NULL; } if(LIST(font) != fontlist.tail) { /* move it to the end of the list */ listh_remove(&fontlist, LIST(font)); listh_append(&fontlist, LIST(font)); } } DEBUG((DBG_FONTS, "%s: reference dropped, %d more left\n", font->fontname, font->links)); }
int mdvi_register_special(const char *label, const char *prefix, const char *regex, DviSpecialHandler handler, int replace) { DviSpecial *sp; int newsp = 0; if(!registered_builtins) register_builtin_specials(); sp = find_special_prefix(prefix); if(sp == NULL) { sp = xalloc(DviSpecial); sp->prefix = mdvi_strdup(prefix); newsp = 1; } else if(!replace) return -1; else { mdvi_free(sp->label); sp->label = NULL; } #ifdef WITH_REGEX_SPECIALS if(!newsp && sp->has_reg) { regfree(&sp->reg); sp->has_reg = 0; } if(regex && regcomp(&sp->reg, regex, REG_NOSUB) != 0) { if(newsp) { mdvi_free(sp->prefix); mdvi_free(sp); } return -1; } sp->has_reg = (regex != NULL); #endif sp->handler = handler; sp->label = mdvi_strdup(label); sp->plen = strlen(prefix); if(newsp) listh_prepend(&specials, LIST(sp)); DEBUG((DBG_SPECIAL, "New \\special handler `%s' with prefix `%s'\n", label, prefix)); return 0; }
void mdvi_flush_specials(void) { DviSpecial *sp, *list; for(list = (DviSpecial *)specials.head; (sp = list); ) { list = sp->next; if(sp->prefix) mdvi_free(sp->prefix); if(sp->label) mdvi_free(sp->label); #ifdef WITH_REGEX_SPECIALS if(sp->has_reg) regfree(&sp->reg); #endif mdvi_free(sp); } specials.head = NULL; specials.tail = NULL; specials.count = 0; }
void bitmap_flip_rotate_counter_clockwise(BITMAP *bm) { BITMAP nb; BmUnit *fptr, *tptr; BmUnit fmask, tmask; int w, h; nb.width = bm->height; nb.height = bm->width; nb.stride = BM_BYTES_PER_LINE(&nb); nb.data = mdvi_calloc(nb.height, nb.stride); fptr = bm->data; tptr = nb.data; tmask = FIRSTMASK; for(h = 0; h < bm->height; h++) { BmUnit *fline, *tline; fmask = FIRSTMASK; fline = fptr; tline = tptr; for(w = 0; w < bm->width; w++) { if(*fline & fmask) *tline |= tmask; if(fmask == LASTMASK) { fmask = FIRSTMASK; fline++; } else NEXTMASK(fmask); /* go to next line */ tline = bm_offset(tline, nb.stride); } fptr = bm_offset(fptr, bm->stride); if(tmask == LASTMASK) { tmask = FIRSTMASK; tptr++; } else NEXTMASK(tmask); } DEBUG((DBG_BITMAP_OPS, "flip_rotate_counter_clockwise (%d,%d) -> (%d,%d)\n", bm->width, bm->height, nb.width, nb.height)); mdvi_free(bm->data); bm->data = nb.data; bm->width = nb.width; bm->height = nb.height; bm->stride = nb.stride; if(SHOW_OP_DATA) bitmap_print(stderr, bm); }
int font_free_unused(DviDevice *dev) { DviFont *font, *next; int count = 0; DEBUG((DBG_FONTS, "destroying unused fonts\n")); for(font = (DviFont *)fontlist.head; font; font = next) { DviFontRef *ref; next = font->next; if(font->links) continue; count++; DEBUG((DBG_FONTS, "removing unused %s font `%s'\n", TYPENAME(font), font->fontname)); listh_remove(&fontlist, LIST(font)); if(font->in) fclose(font->in); /* get rid of subfonts (but can't use `drop_chain' here) */ for(; (ref = font->subfonts); ) { font->subfonts = ref->next; mdvi_free(ref); } /* remove this font */ font_reset_font_glyphs(dev, font, MDVI_FONTSEL_GLYPH); /* let the font destroy its private data */ if(font->finfo->freedata) font->finfo->freedata(font); /* destroy characters */ if(font->chars) mdvi_free(font->chars); mdvi_free(font->fontname); mdvi_free(font->filename); mdvi_free(font); } DEBUG((DBG_FONTS, "%d unused fonts removed\n", count)); return count; }
char *read_string(FILE *in, int s, char *buffer, size_t len) { int n; char *str; n = fugetn(in, s ? s : 1); if((str = buffer) == NULL || n + 1 > len) str = mdvi_malloc(n + 1); if(fread(str, 1, n, in) != n) { if(str != buffer) mdvi_free(str); return NULL; } str[n] = 0; return str; }
void bitmap_flip_diagonally(BITMAP *bm) { BITMAP nb; BmUnit *fptr, *tptr; BmUnit fmask, tmask; int w, h; nb.width = bm->width; nb.height = bm->height; nb.stride = bm->stride; nb.data = mdvi_calloc(bm->height, bm->stride); fptr = bm->data; tptr = __bm_unit_ptr(&nb, nb.width-1, nb.height-1); for(h = 0; h < bm->height; h++) { BmUnit *fline, *tline; fline = fptr; tline = tptr; fmask = FIRSTMASK; tmask = FIRSTMASKAT(nb.width-1); for(w = 0; w < bm->width; w++) { if(*fline & fmask) *tline |= tmask; if(fmask == LASTMASK) { fmask = FIRSTMASK; fline++; } else NEXTMASK(fmask); if(tmask == FIRSTMASK) { tmask = LASTMASK; tline--; } else PREVMASK(tmask); } fptr = bm_offset(fptr, bm->stride); tptr = bm_offset(tptr, -nb.stride); } DEBUG((DBG_BITMAP_OPS, "flip_diagonally (%d,%d) -> (%d,%d)\n", bm->width, bm->height, nb.width, nb.height)); mdvi_free(bm->data); bm->data = nb.data; if(SHOW_OP_DATA) bitmap_print(stderr, bm); }
void buff_free(Buffer *buf) { if(buf->data) mdvi_free(buf->data); buff_init(buf); }
void epsf_special(DviContext *dvi, char *prefix, char *arg) { char *file; char *special; char *psfile; char *tmp; EpsfBox box = {0, 0, 0, 0}; int x, y; int w, h; double xf, vf; struct stat buf; file = parse_epsf_special(&box, &special, prefix, arg); if (file != NULL) mdvi_free (special); xf = dvi->params.dpi * dvi->params.mag / (72.0 * dvi->params.hshrink); vf = dvi->params.vdpi * dvi->params.mag / (72.0 * dvi->params.vshrink); w = FROUND(box.bw * xf); h = FROUND(box.bh * vf); x = FROUND(box.ox * xf) + dvi->pos.hh; y = FROUND(box.oy * vf) + dvi->pos.vv - h + 1; if (!file || !dvi->device.draw_ps) { dvi->device.draw_rule (dvi, x, y, w, h, 0); return; } if (file[0] == '/') { /* Absolute path */ if (stat (file, &buf) == 0) dvi->device.draw_ps (dvi, file, x, y, w, h); else dvi->device.draw_rule (dvi, x, y, w, h, 0); return; } tmp = mdvi_strrstr (dvi->filename, "/"); if (tmp) { /* Document directory */ int path_len = strlen (dvi->filename) - strlen (tmp + 1); int file_len = strlen (file); psfile = mdvi_malloc (path_len + file_len + 1); psfile[0] = '\0'; strncat (psfile, dvi->filename, path_len); strncat (psfile, file, file_len); if (stat (psfile, &buf) == 0) { dvi->device.draw_ps (dvi, psfile, x, y, w, h); mdvi_free (psfile); return; } mdvi_free (psfile); } psfile = mdvi_build_path_from_cwd (file); if (stat (psfile, &buf) == 0) { /* Current working dir */ dvi->device.draw_ps (dvi, psfile, x, y, w, h); mdvi_free (psfile); return; } mdvi_free (psfile); psfile = kpse_find_pict (file); if (psfile) { /* kpse */ dvi->device.draw_ps (dvi, psfile, x, y, w, h); } else { dvi->device.draw_rule(dvi, x, y, w, h, 0); } free (psfile); }
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 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; }