diff options
Diffstat (limited to 'dvi/mdvi-lib/t1.c')
-rw-r--r-- | dvi/mdvi-lib/t1.c | 638 |
1 files changed, 0 insertions, 638 deletions
diff --git a/dvi/mdvi-lib/t1.c b/dvi/mdvi-lib/t1.c deleted file mode 100644 index acbfa23..0000000 --- a/dvi/mdvi-lib/t1.c +++ /dev/null @@ -1,638 +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 - */ - -/* - * Type1 font support for MDVI - * - * We use T1lib only as a rasterizer, not to draw glyphs. - */ - -#include "mdvi.h" - -#ifdef WITH_TYPE1_FONTS - -#include <stdio.h> -#include <t1lib.h> -#include "private.h" - -static int t1lib_initialized = 0; - -typedef struct t1info { - struct t1info *next; - struct t1info *prev; - char *fontname; /* (short) name of this font */ - int t1id; /* T1lib's id for this font */ - int hasmetrics; /* have we processed this font? */ - TFMInfo *tfminfo; /* TFM data is shared */ - DviFontMapInfo mapinfo; - DviEncoding *encoding; -} T1Info; - -static void t1_font_remove __PROTO((T1Info *)); -static int t1_load_font __PROTO((DviParams *, DviFont *)); -static int t1_font_get_glyph __PROTO((DviParams *, DviFont *, int)); -static void t1_font_shrink_glyph - __PROTO((DviContext *, DviFont *, DviFontChar *, DviGlyph *)); -static void t1_free_data __PROTO((DviFont *)); -static void t1_reset_font __PROTO((DviFont *)); -static char *t1_lookup_font __PROTO((const char *, Ushort *, Ushort *)); - -/* only symbol exported by this file */ -DviFontInfo t1_font_info = { - "Type1", - 1, /* scaling supported by format */ - t1_load_font, - t1_font_get_glyph, - t1_font_shrink_glyph, - mdvi_shrink_glyph_grey, - t1_free_data, - t1_reset_font, - t1_lookup_font, /* lookup */ - kpse_type1_format, - NULL -}; - -/* this seems good enough for most DVI files */ -#define T1_HASH_SIZE 31 - -/* If these parameters change, we must delete all size information - * in all fonts, and reset the device resolutions in T1lib */ -static int t1lib_xdpi = -1; -static int t1lib_ydpi = -1; - -static ListHead t1fonts = {NULL, NULL, 0}; -static DviHashTable t1hash; - -/* Type1 fonts need their own `lookup' function. Here is how it works: - * First we try to find the font by its given name. If that fails, we - * query the font maps. A typical font map entry may contain the line - * - * ptmr8rn Times-Roman ".82 ExtendFont TeXBase1Encoding ReEncodeFont" <8r.enc <ptmr - * - * which means: If you're looking for the font `ptmr8rn' load `Times-Roman' - * which is in `ptmr' instead, and extend it by 0.82 points, then reencode - * it with the vector TeXBase1Encoding from the file `8r.enc'. This will - * fail if the entry looks like this: - * - * ptmr8rn Times-Roman ".82 ExtendFont TeXBase1Encoding ReEncodeFont" <8r.enc - * - * because to deal with this we would need to be able to locate the font file - * for the `Times-Roman' font ourselves, and that's beyond the scope of mdvi. - * But hey, we tried hard. - */ -char *t1_lookup_font(const char *name, Ushort *hdpi, Ushort *vdpi) -{ - char *filename; - char *newname; - const char *ext; - DviFontMapInfo info; - - DEBUG((DBG_TYPE1, "(t1) looking for `%s'\n", name)); - - /* first let's try the font we were asked for */ - filename = kpse_find_file(name, kpse_type1_format, 1); - if(filename != NULL) { - /* we got it */ - return filename; - } - - DEBUG((DBG_TYPE1, "(t1) %s: not found, querying font maps\n", name)); - /* now query the fontmap */ - if(mdvi_query_fontmap(&info, name) < 0) { - /* it's not there either */ - return NULL; - } - - /* check what we got */ - if(info.fullfile) { - DEBUG((DBG_TYPE1, "(t1) %s: found `%s' (cached)\n", - name, info.fullfile)); - /* this is a cached lookup */ - return mdvi_strdup(info.fullfile); - } - - /* no file associated to this font? */ - if(info.fontfile == NULL) - return info.psname ? mdvi_ps_find_font(info.psname) : NULL; - - /* let's extract the extension */ - ext = file_extension(info.fontfile); - if(ext && !STREQ(ext, "pfa") && !STREQ(ext, "pfb")) { - DEBUG((DBG_TYPE1, - "(t1) %s: associated name `%s' is not Type1\n", - name, info.fontfile)); - /* it's not a Type1 font */ - return NULL; - } - - /* get the `base' name */ - if(ext) { - newname = mdvi_strdup(name); - newname[ext - info.fontfile - 1] = 0; - } else - newname = (char *)name; /* we don't modify this */ - - /* look it up */ - DEBUG((DBG_TYPE1, "(t1) looking for `%s' on behalf of `%s'\n", - newname, name)); - filename = kpse_find_file(newname, kpse_type1_format, 1); - - /* we don't need this anymore */ - if(newname != name) - mdvi_free(newname); - if(filename == NULL) { - DEBUG((DBG_TYPE1, "(t1) %s: not found\n", name)); - return NULL; - } - - DEBUG((DBG_TYPE1, "(t1) %s: found as `%s'\n", name, filename)); - /* got it! let's remember this */ - mdvi_add_fontmap_file(name, filename); - return filename; -} - -static void t1_reset_resolution(int xdpi, int ydpi) -{ - int i; - int nfonts; - - DEBUG((DBG_TYPE1, "(t1) resetting device resolution (current: (%d,%d))\n", - t1lib_xdpi, t1lib_ydpi)); -#if T1LIB_VERSION < 5 - nfonts = T1_Get_no_fonts(); -#else - nfonts = T1_GetNoFonts(); -#endif - - for(i = 0; i < nfonts; i++) - T1_DeleteAllSizes(i); - /* reset device resolutions */ - if(T1_SetDeviceResolutions((float)xdpi, (float)ydpi) < 0) - warning(_("(t1) failed to reset device resolution\n")); - else - DEBUG((DBG_TYPE1, - "(t1) reset successful, new resolution is (%d, %d)\n", - xdpi, ydpi)); - t1lib_xdpi = xdpi; - t1lib_ydpi = ydpi; -} - -static void t1_reset_font(DviFont *font) -{ - T1Info *info = (T1Info *)font->private; - - if(info == NULL) - return; - DEBUG((DBG_FONTS, "(t1) resetting font `%s'\n", font->fontname)); - /* just mark the font as not having metric info. It will be reset - * automatically later */ - info->hasmetrics = 0; -} - -static void t1_transform_font(T1Info *info) -{ - if(!info->hasmetrics && info->encoding != NULL) { - DEBUG((DBG_TYPE1, "(t1) %s: encoding with vector `%s'\n", - info->fontname, info->encoding->name)); - T1_DeleteAllSizes(info->t1id); - if(T1_ReencodeFont(info->t1id, info->encoding->vector) < 0) - warning(_("%s: could not encode font\n"), info->fontname); - } - if(info->mapinfo.slant) { - DEBUG((DBG_TYPE1, "(t1) %s: slanting by %.3f\n", - info->fontname, - MDVI_FMAP_SLANT(&info->mapinfo))); - T1_SlantFont(info->t1id, - MDVI_FMAP_SLANT(&info->mapinfo)); - } - if(info->mapinfo.extend) { - DEBUG((DBG_TYPE1, "(t1) %s: extending by %.3f\n", - info->fontname, - MDVI_FMAP_EXTEND(&info->mapinfo))); - T1_ExtendFont(info->t1id, - MDVI_FMAP_EXTEND(&info->mapinfo)); - } -} - -/* if this function is called, we really need this font */ -static int t1_really_load_font(DviParams *params, DviFont *font, T1Info *info) -{ - int i; - T1Info *old; - int t1id; - int copied; - int status; - - DEBUG((DBG_TYPE1, "(t1) really_load_font(%s)\n", info->fontname)); - - /* if the parameters changed, reset T1lib */ - if(t1lib_xdpi != params->dpi || t1lib_ydpi != params->vdpi) - t1_reset_resolution(params->dpi, params->vdpi); - - /* if we already have a T1lib id, do nothing */ - if(info->t1id != -1) { - info->hasmetrics = 1; - /* apply slant and extend again */ - t1_transform_font(info); - return 0; - } - - /* before we even attempt to load the font, make sure we have metric - * data for it */ - info->tfminfo = mdvi_ps_get_metrics(info->fontname); - if(info->tfminfo == NULL) { - DEBUG((DBG_FONTS, - "(t1) %s: no metric data, font ignored\n", - info->fontname)); - goto t1_error; - } - /* fix this */ - font->design = info->tfminfo->design; - - /* check if we have a font with this name (maybe at a different size) */ - old = (T1Info *)mdvi_hash_lookup(&t1hash, (unsigned char *)info->fontname); - if(old == info) { - /* let's avoid confusion */ - old = NULL; - } - if(old && old->t1id != -1) { - /* let's take advantage of T1lib's font sharing */ - t1id = T1_CopyFont(old->t1id); - DEBUG((DBG_TYPE1, "(t1) %s -> %d (CopyFont)\n", - info->fontname, t1id)); - copied = 1; - } else { - t1id = T1_AddFont(font->filename); - DEBUG((DBG_TYPE1, "(t1) %s -> %d (AddFont)\n", - info->fontname, t1id)); - copied = 0; - } - if(t1id < 0) - goto t1_error; - info->t1id = t1id; - - /* - * a minor optimization: If the old font in the hash table has - * not been loaded yet, replace it by this one, so we can use - * CopyFont later. - */ - if(old && old->t1id == -1) { - DEBUG((DBG_TYPE1, "(t1) font `%s' exchanged in hash table\n", - info->fontname)); - mdvi_hash_remove(&t1hash, (unsigned char *)old->fontname); - mdvi_hash_add(&t1hash, (unsigned char *)info->fontname, - info, MDVI_HASH_UNCHECKED); - } - - /* now let T1lib load it */ - if(!copied && T1_LoadFont(info->t1id) < 0) { - DEBUG((DBG_TYPE1, "(t1) T1_LoadFont(%d) failed with error %d\n", - info->t1id, T1_errno)); - goto t1_error; - } - DEBUG((DBG_TYPE1, "(t1) T1_LoadFont(%d) -> Ok\n", info->t1id)); - - /* get information from the fontmap */ - status = mdvi_query_fontmap(&info->mapinfo, info->fontname); - if(!status && info->mapinfo.encoding) - info->encoding = mdvi_request_encoding(info->mapinfo.encoding); - t1_transform_font(info); - - i = info->tfminfo->hic - info->tfminfo->loc + 1; - if(i != font->hic - font->loc + 1) { - /* reset to optimal size */ - font->chars = mdvi_realloc(font->chars, i * sizeof(DviFontChar)); - } - - /* get the scaled characters metrics */ - get_tfm_chars(params, font, info->tfminfo, 0); - info->hasmetrics = 1; - - DEBUG((DBG_TYPE1, "(t1) font `%s' really-loaded\n", info->fontname)); - return 0; - -t1_error: - /* some error does not allows us to use this font. We need to reset - * the font structure, so the font system can try to read this - * font in a different class */ - - /* first destroy the private data */ - t1_font_remove(info); - /* now reset all chars -- this is the important part */ - mdvi_free(font->chars); - font->chars = NULL; - font->loc = font->hic = 0; - return -1; -} - -static int init_t1lib(DviParams *params) -{ - int t1flags; - -#ifdef WORD_LITTLE_ENDIAN - /* try making T1lib use bitmaps in our format, but if this - * fails we'll convert the bitmap ourselves */ - T1_SetBitmapPad(BITMAP_BITS); -#endif - T1_SetDeviceResolutions((float)params->dpi, (float)params->vdpi); - t1flags = IGNORE_CONFIGFILE|IGNORE_FONTDATABASE|T1_NO_AFM; - if(DEBUGGING(TYPE1)) - t1flags |= LOGFILE; - if(T1_InitLib(t1flags) == NULL) - return (t1lib_initialized = -1); - if(DEBUGGING(TYPE1)) { - DEBUG((DBG_TYPE1, "T1lib debugging output saved in t1lib.log\n")); - T1_SetLogLevel(T1LOG_DEBUG); - } - /* initialize our hash table, but don't allocate memory for it - * until we use it */ - mdvi_hash_init(&t1hash); - DEBUG((DBG_TYPE1, "(t1) t1lib %s initialized -- resolution is (%d, %d), pad is %d bits\n", - T1_GetLibIdent(), params->dpi, params->vdpi, T1_GetBitmapPad())); - t1lib_initialized = 1; - t1lib_xdpi = params->dpi; - t1lib_ydpi = params->vdpi; - return 0; -} - -static int t1_load_font(DviParams *params, DviFont *font) -{ - T1Info *info; - int i; - - if(t1lib_initialized < 0) - return -1; - else if(t1lib_initialized == 0 && init_t1lib(params) < 0) - return -1; - - if(font->in != NULL) { - /* we don't need this */ - fclose(font->in); - font->in = NULL; - } - - info = xalloc(T1Info); - - /* - * mark the font as `unregistered' with T1lib. It will - * be added when we actually use it - */ - info->t1id = -1; - - /* add the font to our list */ - info->fontname = font->fontname; - info->hasmetrics = 0; - info->encoding = NULL; - info->mapinfo.psname = NULL; - info->mapinfo.encoding = NULL; - info->mapinfo.fontfile = NULL; - info->mapinfo.extend = 0; - info->mapinfo.slant = 0; - info->encoding = NULL; - - /* create the hash table if we have not done so yet */ - if(t1hash.nbucks == 0) - mdvi_hash_create(&t1hash, T1_HASH_SIZE); - mdvi_hash_add(&t1hash, (unsigned char *) info->fontname, info, MDVI_HASH_UNIQUE); - listh_append(&t1fonts, LIST(info)); - - font->private = info; - - /* reset everything */ - font->chars = xnalloc(DviFontChar, 256); - font->loc = 0; - font->hic = 255; - for(i = 0; i < 256; i++) { - font->chars[i].code = i; - font->chars[i].offset = 1; - font->chars[i].loaded = 0; - font->chars[i].glyph.data = NULL; - font->chars[i].shrunk.data = NULL; - font->chars[i].grey.data = NULL; - } - - return 0; -} - -#define GLYPH_WIDTH(g) \ - ((g)->metrics.rightSideBearing - (g)->metrics.leftSideBearing) -#define GLYPH_HEIGHT(g) \ - ((g)->metrics.ascent - (g)->metrics.descent) - -static inline BITMAP *t1_glyph_bitmap(GLYPH *glyph) -{ - BITMAP *bm; - int w, h; - - w = GLYPH_WIDTH(glyph); - h = GLYPH_HEIGHT(glyph); - - if(!w || !h) - return MDVI_GLYPH_EMPTY; - switch(glyph->bpp << 3) { - case 8: - bm = bitmap_convert_lsb8((unsigned char *)glyph->bits, w, h); - break; - default: - warning(_("(t1) unsupported bitmap pad size %d\n"), - glyph->bpp); - bm = MDVI_GLYPH_EMPTY; - break; - } - return bm; -} - -static void t1_font_shrink_glyph(DviContext *dvi, DviFont *font, DviFontChar *ch, DviGlyph *dest) -{ - double size; - GLYPH *glyph; - T1Info *info; - T1_TMATRIX matrix; - - info = (T1Info *)font->private; - ASSERT(info != NULL); - - DEBUG((DBG_TYPE1, "(t1) shrinking glyph for character %d in `%s' (%d,%d)\n", - ch->code, font->fontname, ch->width, ch->height)); - size = (double)font->scale / (dvi->params.tfm_conv * 0x100000); - size = 72.0 * size / 72.27; - matrix.cxx = 1.0/(double)dvi->params.hshrink; - matrix.cyy = 1.0/(double)dvi->params.vshrink; - matrix.cxy = 0.0; - matrix.cyx = 0.0; - glyph = T1_SetChar(info->t1id, ch->code, (float)size, &matrix); - - dest->data = t1_glyph_bitmap(glyph); - dest->x = -glyph->metrics.leftSideBearing; - dest->y = glyph->metrics.ascent; - dest->w = GLYPH_WIDTH(glyph); - dest->h = GLYPH_HEIGHT(glyph); - -#ifndef NODEBUG - if(DEBUGGING(BITMAP_DATA)) { - DEBUG((DBG_BITMAP_DATA, - "(t1) %s: t1_shrink_glyph(%d): (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n", - ch->glyph.w, ch->glyph.h, ch->glyph.x, ch->glyph.y, - dest->w, dest->h, dest->x, dest->y)); - bitmap_print(stderr, (BITMAP *)dest->data); - } -#endif - /* transform the glyph - we could do this with t1lib, but we do - * it ourselves for now */ - font_transform_glyph(dvi->params.orientation, dest); -} - -static int t1_font_get_glyph(DviParams *params, DviFont *font, int code) -{ - T1Info *info = (T1Info *)font->private; - GLYPH *glyph; - DviFontChar *ch; - double size; - T1_TMATRIX matrix; - int dpi; - - ASSERT(info != NULL); - if(!info->hasmetrics && t1_really_load_font(params, font, info) < 0) - return -1; - ch = FONTCHAR(font, code); - if(!ch || !glyph_present(ch)) - return -1; - ch->loaded = 1; - if(!ch->width || !ch->height) { - 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; - } - - /* load the glyph with T1lib (this is done only once for each glyph) */ - - /* get size in TeX points (tfm_conv includes dpi and magnification) */ - size = (double)font->scale / (params->tfm_conv * 0x100000); - /* and transform into PostScript points */ - size = 72.0 * size / 72.27; - - dpi = Max(font->hdpi, font->vdpi); - /* we don't want the glyph to be cached twice (once by us, another by - * T1lib), so we use an identity matrix to tell T1lib not to keep the - * glyph around */ - matrix.cxx = (double)font->hdpi / dpi; - matrix.cyy = (double)font->vdpi / dpi; - matrix.cxy = matrix.cyx = 0.0; - glyph = T1_SetChar(info->t1id, ch->code, (float)size, &matrix); - if(glyph == NULL) { - ch->glyph.x = ch->x; - ch->glyph.y = ch->y; - ch->glyph.w = ch->width; - ch->glyph.h = ch->height; - ch->glyph.data = NULL; - ch->missing = 1; - return 0; - } - /* and make it a bitmap */ - ch->glyph.data = t1_glyph_bitmap(glyph); - ch->glyph.x = -glyph->metrics.leftSideBearing; - ch->glyph.y = glyph->metrics.ascent; - ch->glyph.w = GLYPH_WIDTH(glyph); - ch->glyph.h = GLYPH_HEIGHT(glyph); - - /* let's also fix the glyph's origin - * (which is not contained in the TFM) */ - ch->x = ch->glyph.x; - ch->y = ch->glyph.y; - /* let's fix these too */ - ch->width = ch->glyph.w; - ch->height = ch->glyph.h; - - return 0; -} - -static void t1_font_remove(T1Info *info) -{ - T1Info *old; - - /* first remove it from our list */ - listh_remove(&t1fonts, LIST(info)); - - /* it it's in the hash table, we may need to replace this by another font */ - old = (T1Info *)mdvi_hash_lookup(&t1hash, (unsigned char *)info->fontname); - if(old == info) { - mdvi_hash_remove(&t1hash, (unsigned char *) info->fontname); - /* go through the list and see if there is another - * font with this name */ - for(old = (T1Info *)t1fonts.head; old; old = old->next) - if(STREQ(old->fontname, info->fontname)) - break; - if(old != NULL) - mdvi_hash_add(&t1hash, (unsigned char *) old->fontname, old, - MDVI_HASH_UNCHECKED); - } - /* release our encoding vector */ - if(info->encoding) { - DEBUG((DBG_TYPE1, "(t1) %s: releasing vector `%s'\n", - info->fontname, info->encoding->name)); - mdvi_release_encoding(info->encoding, 1); - } - - /* now get rid of it */ - if(info->t1id != -1) { - DEBUG((DBG_TYPE1, "(t1) %s: T1_DeleteFont(%d)\n", - info->fontname, info->t1id)); - T1_DeleteFont(info->t1id); - } else - DEBUG((DBG_TYPE1, "(t1) %s: not loaded yet, DeleteFont skipped\n", - info->fontname)); - - if(info->tfminfo) - free_font_metrics(info->tfminfo); - /*mdvi_free(info->fontname);*/ - mdvi_free(info); -} - -static void t1_free_data(DviFont *font) -{ - /* called after all the glyphs are destroyed */ - - if(font->private == NULL) { - /* this is perfectly normal, it just means the font has - * not been requested by MDVI yet */ - return; - } - - /* destroy this data */ - - t1_font_remove((T1Info *)font->private); - font->private = NULL; - - /* - * if this is the last T1 font, reset the T1 library - * It is important that we do this, because this is will be called - * when the resolution or the magnification changes. - */ - if(t1fonts.count == 0) { - DEBUG((DBG_TYPE1, "(t1) last font removed -- closing T1lib\n")); - T1_CloseLib(); - t1lib_initialized = 0; - t1lib_xdpi = -1; - t1lib_ydpi = -1; - } -} - -#endif /* WITH_TYPE1_FONTS */ |