diff options
Diffstat (limited to 'dvi/mdvi-lib/font.c')
-rw-r--r-- | dvi/mdvi-lib/font.c | 516 |
1 files changed, 0 insertions, 516 deletions
diff --git a/dvi/mdvi-lib/font.c b/dvi/mdvi-lib/font.c deleted file mode 100644 index fedb7e7..0000000 --- a/dvi/mdvi-lib/font.c +++ /dev/null @@ -1,516 +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 - */ - -#include <stdlib.h> - -#include "mdvi.h" -#include "private.h" - -static ListHead fontlist; - -extern char *_mdvi_fallback_font; - -extern void vf_free_macros(DviFont *); - -#define finfo search.info -#define TYPENAME(font) \ - ((font)->finfo ? (font)->finfo->name : "none") - -int font_reopen(DviFont *font) -{ - if(font->in) - fseek(font->in, (long)0, SEEK_SET); - else if((font->in = fopen(font->filename, "r")) == NULL) { - DEBUG((DBG_FILES, "reopen(%s) -> Error\n", font->filename)); - return -1; - } - DEBUG((DBG_FILES, "reopen(%s) -> Ok.\n", font->filename)); - return 0; -} - -/* used from context: params and device */ -static int load_font_file(DviParams *params, DviFont *font) -{ - int status; - - if(SEARCH_DONE(font->search)) - return -1; - if(font->in == NULL && font_reopen(font) < 0) - return -1; - DEBUG((DBG_FONTS, "%s: loading %s font from `%s'\n", - font->fontname, - font->finfo->name, font->filename)); - do { - status = font->finfo->load(params, font); - } while(status < 0 && mdvi_font_retry(params, font) == 0); - if(status < 0) - return -1; - if(font->in) { - fclose(font->in); - font->in = NULL; - } - DEBUG((DBG_FONTS, "reload_font(%s) -> %s\n", - font->fontname, status < 0 ? "Error" : "Ok")); - 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)); -} - -void font_drop_chain(DviFontRef *head) -{ - DviFontRef *ptr; - - for(; (ptr = head); ) { - head = ptr->next; - font_drop_one(ptr); - } -} - -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; -} - -/* used from context: params and device */ -DviFontRef * -font_reference( - DviParams *params, /* rendering parameters */ - Int32 id, /* external id number */ - const char *name, /* font name */ - Int32 sum, /* checksum (from DVI of VF) */ - int hdpi, /* resolution */ - int vdpi, - Int32 scale) /* scaling factor (from DVI or VF) */ -{ - DviFont *font; - DviFontRef *ref; - DviFontRef *subfont_ref; - - /* see if there is a font with the same characteristics */ - for(font = (DviFont *)fontlist.head; font; font = font->next) { - if(strcmp(name, font->fontname) == 0 - && (!sum || !font->checksum || font->checksum == sum) - && font->hdpi == hdpi - && font->vdpi == vdpi - && font->scale == scale) - break; - } - /* try to load the font */ - if(font == NULL) { - font = mdvi_add_font(name, sum, hdpi, vdpi, scale); - if(font == NULL) - return NULL; - listh_append(&fontlist, LIST(font)); - } - if(!font->links && !font->chars && load_font_file(params, font) < 0) { - DEBUG((DBG_FONTS, "font_reference(%s) -> Error\n", name)); - return NULL; - } - ref = xalloc(DviFontRef); - ref->ref = font; - - font->links++; - for(subfont_ref = font->subfonts; subfont_ref; subfont_ref = subfont_ref->next) { - /* just adjust the reference counts */ - subfont_ref->ref->links++; - } - - ref->fontid = id; - - if(LIST(font) != fontlist.head) { - listh_remove(&fontlist, LIST(font)); - listh_prepend(&fontlist, LIST(font)); - } - - DEBUG((DBG_FONTS, "font_reference(%s) -> %d links\n", - font->fontname, font->links)); - return ref; -} - -void font_transform_glyph(DviOrientation orient, DviGlyph *g) -{ - BITMAP *map; - int x, y; - - map = (BITMAP *)g->data; - if(MDVI_GLYPH_ISEMPTY(map)) - map = NULL; - - /* put the glyph in the right orientation */ - switch(orient) { - case MDVI_ORIENT_TBLR: - break; - case MDVI_ORIENT_TBRL: - g->x = g->w - g->x; - if(map) bitmap_flip_horizontally(map); - break; - case MDVI_ORIENT_BTLR: - g->y = g->h - g->y; - if(map) bitmap_flip_vertically(map); - break; - case MDVI_ORIENT_BTRL: - g->x = g->w - g->x; - g->y = g->h - g->y; - if(map) bitmap_flip_diagonally(map); - break; - case MDVI_ORIENT_RP90: - if(map) bitmap_rotate_counter_clockwise(map); - y = g->y; - x = g->w - g->x; - g->x = y; - g->y = x; - SWAPINT(g->w, g->h); - break; - case MDVI_ORIENT_RM90: - if(map) bitmap_rotate_clockwise(map); - y = g->h - g->y; - x = g->x; - g->x = y; - g->y = x; - SWAPINT(g->w, g->h); - break; - case MDVI_ORIENT_IRP90: - if(map) bitmap_flip_rotate_counter_clockwise(map); - y = g->y; - x = g->x; - g->x = y; - g->y = x; - SWAPINT(g->w, g->h); - break; - case MDVI_ORIENT_IRM90: - if(map) bitmap_flip_rotate_clockwise(map); - y = g->h - g->y; - x = g->w - g->x; - g->x = y; - g->y = x; - SWAPINT(g->w, g->h); - break; - } -} - -static int load_one_glyph(DviContext *dvi, DviFont *font, int code) -{ - BITMAP *map; - DviFontChar *ch; - int status; - -#ifndef NODEBUG - ch = FONTCHAR(font, code); - DEBUG((DBG_GLYPHS, "loading glyph code %d in %s (at %u)\n", - code, font->fontname, ch->offset)); -#endif - if(font->finfo->getglyph == NULL) { - /* font type does not need to load glyphs (e.g. vf) */ - return 0; - } - - status = font->finfo->getglyph(&dvi->params, font, code); - if(status < 0) - return -1; - /* get the glyph again (font->chars may have changed) */ - ch = FONTCHAR(font, code); -#ifndef NODEBUG - map = (BITMAP *)ch->glyph.data; - if(DEBUGGING(BITMAP_DATA)) { - DEBUG((DBG_BITMAP_DATA, - "%s: new %s bitmap for character %d:\n", - font->fontname, TYPENAME(font), code)); - if(MDVI_GLYPH_ISEMPTY(map)) - DEBUG((DBG_BITMAP_DATA, "blank bitmap\n")); - else - bitmap_print(stderr, map); - } -#endif - /* check if we have to scale it */ - if(!font->finfo->scalable && font->hdpi != font->vdpi) { - int hs, vs, d; - - /* we scale it ourselves */ - d = Max(font->hdpi, font->vdpi); - hs = d / font->hdpi; - vs = d / font->vdpi; - if(ch->width && ch->height && (hs > 1 || vs > 1)) { - int h, v; - DviGlyph glyph; - - DEBUG((DBG_FONTS, - "%s: scaling glyph %d to resolution %dx%d\n", - font->fontname, code, font->hdpi, font->vdpi)); - h = dvi->params.hshrink; - v = dvi->params.vshrink; - d = dvi->params.density; - dvi->params.hshrink = hs; - dvi->params.vshrink = vs; - dvi->params.density = 50; - /* shrink it */ - font->finfo->shrink0(dvi, font, ch, &glyph); - /* restore parameters */ - dvi->params.hshrink = h; - dvi->params.vshrink = v; - dvi->params.density = d; - /* update glyph data */ - if(!MDVI_GLYPH_ISEMPTY(ch->glyph.data)) - bitmap_destroy((BITMAP *)ch->glyph.data); - ch->glyph.data = glyph.data; - ch->glyph.x = glyph.x; - ch->glyph.y = glyph.y; - ch->glyph.w = glyph.w; - ch->glyph.h = glyph.h; - } - - } - font_transform_glyph(dvi->params.orientation, &ch->glyph); - - return 0; -} - -DviFontChar *font_get_glyph(DviContext *dvi, DviFont *font, int code) -{ - DviFontChar *ch; - -again: - /* if we have not loaded the font yet, do so now */ - if(!font->chars && load_font_file(&dvi->params, font) < 0) - return NULL; - - /* get the unscaled glyph, maybe loading it from disk */ - ch = FONTCHAR(font, code); - if(!ch || !glyph_present(ch)) - return NULL; - if(!ch->loaded && load_one_glyph(dvi, font, code) == -1) { - if(font->chars == NULL) { - /* we need to try another font class */ - goto again; - } - return NULL; - } - /* yes, we have to do this again */ - ch = FONTCHAR(font, code); - - /* Got the glyph. If we also have the right scaled glyph, do no more */ - if(!ch->width || !ch->height || - font->finfo->getglyph == NULL || - (dvi->params.hshrink == 1 && dvi->params.vshrink == 1)) - return ch; - - /* If the glyph is empty, we just need to shrink the box */ - if(ch->missing || MDVI_GLYPH_ISEMPTY(ch->glyph.data)) { - if(MDVI_GLYPH_UNSET(ch->shrunk.data)) - mdvi_shrink_box(dvi, font, ch, &ch->shrunk); - return ch; - } else if(MDVI_ENABLED(dvi, MDVI_PARAM_ANTIALIASED)) { - if(ch->grey.data && - ch->fg == dvi->curr_fg && - ch->bg == dvi->curr_bg) - return ch; - if(ch->grey.data) { - if(dvi->device.free_image) - dvi->device.free_image(ch->grey.data); - ch->grey.data = NULL; - } - font->finfo->shrink1(dvi, font, ch, &ch->grey); - } else if(!ch->shrunk.data) - font->finfo->shrink0(dvi, font, ch, &ch->shrunk); - - return ch; -} - -void font_reset_one_glyph(DviDevice *dev, DviFontChar *ch, int what) -{ - if(!glyph_present(ch)) - return; - if(what & MDVI_FONTSEL_BITMAP) { - if(MDVI_GLYPH_NONEMPTY(ch->shrunk.data)) - bitmap_destroy((BITMAP *)ch->shrunk.data); - ch->shrunk.data = NULL; - } - if(what & MDVI_FONTSEL_GREY) { - if(MDVI_GLYPH_NONEMPTY(ch->grey.data)) { - if(dev->free_image) - dev->free_image(ch->grey.data); - } - ch->grey.data = NULL; - } - if(what & MDVI_FONTSEL_GLYPH) { - if(MDVI_GLYPH_NONEMPTY(ch->glyph.data)) - bitmap_destroy((BITMAP *)ch->glyph.data); - ch->glyph.data = NULL; - ch->loaded = 0; - } -} - -void font_reset_font_glyphs(DviDevice *dev, DviFont *font, int what) -{ - int i; - DviFontChar *ch; - - if(what & MDVI_FONTSEL_GLYPH) - what |= MDVI_FONTSEL_BITMAP|MDVI_FONTSEL_GREY; - if(font->subfonts) { - DviFontRef *ref; - - for(ref = font->subfonts; ref; ref = ref->next) - font_reset_font_glyphs(dev, ref->ref, what); - } - if(font->in) { - DEBUG((DBG_FILES, "close(%s)\n", font->filename)); - fclose(font->in); - font->in = NULL; - } - if(font->finfo->getglyph == NULL) - return; - DEBUG((DBG_FONTS, "resetting glyphs in font `%s'\n", font->fontname)); - for(ch = font->chars, i = font->loc; i <= font->hic; ch++, i++) { - if(glyph_present(ch)) - font_reset_one_glyph(dev, ch, what); - } - if((what & MDVI_FONTSEL_GLYPH) && font->finfo->reset) - font->finfo->reset(font); -} - -void font_reset_chain_glyphs(DviDevice *dev, DviFontRef *head, int what) -{ - DviFontRef *ref; - - for(ref = head; ref; ref = ref->next) - font_reset_font_glyphs(dev, ref->ref, what); -} - -static int compare_refs(const void *p1, const void *p2) -{ - return ((*(DviFontRef **)p1)->fontid - (*(DviFontRef **)p2)->fontid); -} - -void font_finish_definitions(DviContext *dvi) -{ - int count; - DviFontRef **map, *ref; - - /* first get rid of unused fonts */ - font_free_unused(&dvi->device); - - if(dvi->fonts == NULL) { - warning(_("%s: no fonts defined\n"), dvi->filename); - return; - } - map = xnalloc(DviFontRef *, dvi->nfonts); - for(count = 0, ref = dvi->fonts; ref; ref = ref->next) - map[count++] = ref; - /* sort the array by font id */ - qsort(map, dvi->nfonts, sizeof(DviFontRef *), compare_refs); - dvi->fontmap = map; -} - -DviFontRef *font_find_flat(DviContext *dvi, Int32 id) -{ - DviFontRef *ref; - - for(ref = dvi->fonts; ref; ref = ref->next) - if(ref->fontid == id) - break; - return ref; -} - -DviFontRef *font_find_mapped(DviContext *dvi, Int32 id) -{ - int lo, hi, n; - DviFontRef **map; - - /* do a binary search */ - lo = 0; hi = dvi->nfonts; - map = dvi->fontmap; - while(lo < hi) { - int sign; - - n = (hi + lo) >> 1; - sign = (map[n]->fontid - id); - if(sign == 0) - break; - else if(sign < 0) - lo = n; - else - hi = n; - } - if(lo >= hi) - return NULL; - return map[n]; -} - |