Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/dvi/mdvi-lib/fontmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'dvi/mdvi-lib/fontmap.c')
-rw-r--r--dvi/mdvi-lib/fontmap.c1172
1 files changed, 0 insertions, 1172 deletions
diff --git a/dvi/mdvi-lib/fontmap.c b/dvi/mdvi-lib/fontmap.c
deleted file mode 100644
index cc61064..0000000
--- a/dvi/mdvi-lib/fontmap.c
+++ /dev/null
@@ -1,1172 +0,0 @@
-/* encoding.c - functions to manipulate encodings and fontmaps */
-/*
- * 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 <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <sys/stat.h>
-
-#include "mdvi.h"
-#include "private.h"
-
-#include <kpathsea/expand.h>
-#include <kpathsea/pathsearch.h>
-
-typedef struct _DviFontMap DviFontMap;
-
-struct _DviFontMap {
- ListHead entries;
- DviHashTable fonts;
-};
-
-typedef struct _PSFontMap {
- struct _PSFontMap *next;
- struct _PSFontMap *prev;
- char *psname;
- char *mapname;
- char *fullname;
-} PSFontMap;
-
-/* these variables control PS font maps */
-static char *pslibdir = NULL; /* path where we look for PS font maps */
-static char *psfontdir = NULL; /* PS font search path */
-static int psinitialized = 0; /* did we expand the path already? */
-
-static ListHead psfonts = MDVI_EMPTY_LIST_HEAD;
-static DviHashTable pstable = MDVI_EMPTY_HASH_TABLE;
-
-static ListHead fontmaps;
-static DviHashTable maptable;
-static int fontmaps_loaded = 0;
-
-#define MAP_HASH_SIZE 57
-#define ENC_HASH_SIZE 31
-#define PSMAP_HASH_SIZE 57
-
-/* this hash table should be big enough to
- * hold (ideally) one glyph name per bucket */
-#define ENCNAME_HASH_SIZE 131 /* most TeX fonts have 128 glyphs */
-
-static ListHead encodings = MDVI_EMPTY_LIST_HEAD;
-static DviEncoding *tex_text_encoding = NULL;
-static DviEncoding *default_encoding = NULL;
-
-/* we keep two hash tables for encodings: one for their base files (e.g.
- * "8r.enc"), and another one for their names (e.g. "TeXBase1Encoding") */
-static DviHashTable enctable = MDVI_EMPTY_HASH_TABLE;
-static DviHashTable enctable_file = MDVI_EMPTY_HASH_TABLE;
-
-/* the TeX text encoding, from dvips */
-static char *tex_text_vector[256] = {
- "Gamma", "Delta", "Theta", "Lambda", "Xi", "Pi", "Sigma", "Upsilon",
- "Phi", "Psi", "Omega", "arrowup", "arrowdown", "quotesingle",
- "exclamdown", "questiondown", "dotlessi", "dotlessj", "grave",
- "acute", "caron", "breve", "macron", "ring", "cedilla",
- "germandbls", "ae", "oe", "oslash", "AE", "OE", "Oslash", "space",
- "exclam", "quotedbl", "numbersign", "dollar", "percent",
- "ampersand", "quoteright", "parenleft", "parenright", "asterisk",
- "plus", "comma", "hyphen", "period", "slash", "zero", "one", "two",
- "three", "four", "five", "six", "seven", "eight", "nine", "colon",
- "semicolon", "less", "equal", "greater", "question", "at", "A", "B",
- "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O",
- "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z",
- "bracketleft", "backslash", "bracketright", "circumflex",
- "underscore", "quoteleft", "a", "b", "c", "d", "e", "f", "g", "h",
- "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u",
- "v", "w", "x", "y", "z", "braceleft", "bar", "braceright", "tilde",
- "dieresis", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-static void ps_init_default_paths __PROTO((void));
-static int mdvi_set_default_encoding __PROTO((const char *name));
-static int mdvi_init_fontmaps __PROTO((void));
-
-/*
- * What we do here is allocate one block large enough to hold the entire
- * file (these files are small) minus the leading comments. This is much
- * better than allocating up to 256 tiny strings per encoding vector. */
-static int read_encoding(DviEncoding *enc)
-{
- FILE *in;
- int curr;
- char *line;
- char *name;
- char *next;
- struct stat st;
-
- ASSERT(enc->private == NULL);
-
- in = fopen(enc->filename, "r");
- if(in == NULL) {
- DEBUG((DBG_FMAP, "%s: could not read `%s' (%s)\n",
- enc->name, enc->filename, strerror(errno)));
- return -1;
- }
- if(fstat(fileno(in), &st) < 0) {
- /* should not happen */
- fclose(in);
- return -1;
- }
- st.st_size -= enc->offset;
-
- /* this will be one big string */
- enc->private = (char *)malloc(st.st_size + 1);
- /* setup the hash table */
- mdvi_hash_create(&enc->nametab, ENCNAME_HASH_SIZE);
- /* setup the encoding vector */
- enc->vector = (char **)mdvi_malloc(256 * sizeof(char *));
-
- /* jump to the beginning of the interesting part */
- fseek(in, enc->offset, SEEK_SET);
- /* and read everything */
- if(fread(enc->private, st.st_size, 1, in) != 1) {
- fclose(in);
- mdvi_free(enc->private);
- enc->private = NULL;
- return -1;
- }
- /* we don't need this anymore */
- fclose(in);
- curr = 0;
-
- next = name = NULL;
- DEBUG((DBG_FMAP, "%s: reading encoding vector\n", enc->name));
- for(line = enc->private; *line && curr < 256; line = next) {
- SKIPSP(line);
- if(*line == ']') {
- line++; SKIPSP(line);
- if(STRNEQ(line, "def", 3))
- break;
- }
- name = getword(line, " \t\n", &next);
- if(name == NULL)
- break;
- /* next > line */
- if(*name < ' ')
- continue;
- if(*name == '%') {
- while(*next && *next != '\n')
- next++;
- if(*next) next++; /* skip \n */
- continue;
- }
-
- /* got a name */
- if(*next) *next++ = 0;
-
- if(*name == '/')
- name++;
- enc->vector[curr] = name;
- /* add it to the hash table */
- if(!STREQ(name, ".notdef")) {
- mdvi_hash_add(&enc->nametab, MDVI_KEY(name),
- Int2Ptr(curr + 1), MDVI_HASH_REPLACE);
- }
- curr++;
- }
- if(curr == 0) {
- mdvi_hash_reset(&enc->nametab, 0);
- mdvi_free(enc->private);
- mdvi_free(enc);
- return -1;
- }
- while(curr < 256)
- enc->vector[curr++] = NULL;
- return 0;
-}
-
-static DviEncoding *find_encoding(const char *name)
-{
- return (DviEncoding *)(encodings.count ?
- mdvi_hash_lookup(&enctable, MDVI_KEY(name)) : NULL);
-}
-
-static void destroy_encoding(DviEncoding *enc)
-{
- if(enc == default_encoding) {
- default_encoding = tex_text_encoding;
- /* now we use reference counts again */
- mdvi_release_encoding(enc, 1);
- }
- if(enc != tex_text_encoding) {
- mdvi_hash_reset(&enc->nametab, 0);
- if(enc->private) {
- mdvi_free(enc->private);
- mdvi_free(enc->vector);
- }
- if(enc->name)
- mdvi_free(enc->name);
- if(enc->filename)
- mdvi_free(enc->filename);
- mdvi_free(enc);
- }
-}
-
-/* this is used for the `enctable_file' hash table */
-static void file_hash_free(DviHashKey key, void *data)
-{
- mdvi_free(key);
-}
-
-static DviEncoding *register_encoding(const char *basefile, int replace)
-{
- DviEncoding *enc;
- FILE *in;
- char *filename;
- char *name;
- Dstring input;
- char *line;
- long offset;
-
- DEBUG((DBG_FMAP, "register_encoding(%s)\n", basefile));
-
- if(encodings.count) {
- enc = mdvi_hash_lookup(&enctable_file, MDVI_KEY(basefile));
- if(enc != NULL) {
- DEBUG((DBG_FMAP, "%s: already there\n", basefile));
- return enc; /* no error */
- }
- }
-
- /* try our own files first */
- filename = kpse_find_file(basefile,
- kpse_program_text_format, 0);
-
- /* then try the system-wide ones */
- if(filename == NULL)
- filename = kpse_find_file(basefile,
- kpse_tex_ps_header_format, 0);
- if(filename == NULL)
- filename = kpse_find_file(basefile,
- kpse_dvips_config_format, 0);
-
- /* finally try the given name */
- if(filename == NULL)
- filename = mdvi_strdup(basefile);
-
- in = fopen(filename, "r");
- if(in == NULL) {
- mdvi_free(filename);
- return NULL;
- }
-
- /* just lookup the name of the encoding */
- name = NULL;
- dstring_init(&input);
- while((line = dgets(&input, in)) != NULL) {
- if(STRNEQ(line, "Encoding=", 9)) {
- name = getword(line + 9, " \t", &line);
- if(*line) *line++ = 0;
- break;
- } else if(*line == '/') {
- char *label = getword(line + 1, " \t", &line);
- if(*line) {
- *line++ = 0;
- SKIPSP(line);
- if(*line == '[') {
- *line = 0;
- name = label;
- break;
- }
- }
- }
- }
- offset = ftell(in);
- fclose(in);
- if(name == NULL || *name == 0) {
- DEBUG((DBG_FMAP,
- "%s: could not determine name of encoding\n",
- basefile));
- mdvi_free(filename);
- return NULL;
- }
-
- /* check if the encoding is already there */
- enc = find_encoding(name);
- if(enc == tex_text_encoding) {
- /* A special case: if the vector we found is the static one,
- * allow the user to override it with an external file */
- listh_remove(&encodings, LIST(enc));
- mdvi_hash_remove(&enctable, MDVI_KEY(enc->name));
- if(enc == default_encoding)
- default_encoding = NULL;
- } else if(enc) {
- /* if the encoding is being used, refuse to remove it */
- if(enc->links) {
- mdvi_free(filename);
- dstring_reset(&input);
- return NULL;
- }
- if(replace) {
- mdvi_hash_remove(&enctable, MDVI_KEY(name));
- mdvi_hash_remove(&enctable_file, MDVI_KEY(basefile));
- listh_remove(&encodings, LIST(enc));
- if(enc == default_encoding) {
- default_encoding = NULL;
- mdvi_release_encoding(enc, 1);
- }
- DEBUG((DBG_FMAP, "%s: overriding encoding\n", name));
- destroy_encoding(enc);
- } else {
- mdvi_free(filename);
- dstring_reset(&input);
- return enc; /* no error */
- }
- }
- enc = xalloc(DviEncoding);
- enc->name = mdvi_strdup(name);
- enc->filename = filename;
- enc->links = 0;
- enc->offset = offset;
- enc->private = NULL;
- enc->vector = NULL;
- mdvi_hash_init(&enc->nametab);
- dstring_reset(&input);
- if(default_encoding == NULL)
- default_encoding = enc;
- mdvi_hash_add(&enctable, MDVI_KEY(enc->name),
- enc, MDVI_HASH_UNCHECKED);
- mdvi_hash_add(&enctable_file, MDVI_KEY(mdvi_strdup(basefile)),
- enc, MDVI_HASH_REPLACE);
- listh_prepend(&encodings, LIST(enc));
- DEBUG((DBG_FMAP, "%s: encoding `%s' registered\n",
- basefile, enc->name));
- return enc;
-}
-
-DviEncoding *mdvi_request_encoding(const char *name)
-{
- DviEncoding *enc = find_encoding(name);
-
- if(enc == NULL) {
- DEBUG((DBG_FMAP, "%s: encoding not found, returning default `%s'\n",
- name, default_encoding->name));
- return default_encoding;
- }
- /* we don't keep reference counts for this */
- if(enc == tex_text_encoding)
- return enc;
- if(!enc->private && read_encoding(enc) < 0)
- return NULL;
- enc->links++;
-
- /* if the hash table is empty, rebuild it */
- if(enc->nametab.nkeys == 0) {
- int i;
-
- DEBUG((DBG_FMAP, "%s: rehashing\n", enc->name));
- for(i = 0; i < 256; i++) {
- if(enc->vector[i] == NULL)
- continue;
- mdvi_hash_add(&enc->nametab,
- MDVI_KEY(enc->vector[i]),
- (DviHashKey)Int2Ptr(i),
- MDVI_HASH_REPLACE);
- }
- }
- return enc;
-}
-
-void mdvi_release_encoding(DviEncoding *enc, int should_free)
-{
- /* ignore our static encoding */
- if(enc == tex_text_encoding)
- return;
- if(!enc->links || --enc->links > 0 || !should_free)
- return;
- DEBUG((DBG_FMAP, "%s: resetting encoding vector\n", enc->name));
- mdvi_hash_reset(&enc->nametab, 1); /* we'll reuse it */
-}
-
-int mdvi_encode_glyph(DviEncoding *enc, const char *name)
-{
- void *data;
-
- data = mdvi_hash_lookup(&enc->nametab, MDVI_KEY(name));
- if(data == NULL)
- return -1;
- /* we added +1 to the hashed index just to distinguish
- * a failed lookup from a zero index. Adjust it now. */
- return (Ptr2Int(data) - 1);
-}
-
-/****************
- * Fontmaps *
- ****************/
-
-static void parse_spec(DviFontMapEnt *ent, char *spec)
-{
- char *arg, *command;
-
- /* this is a ridiculously simple parser, and recognizes only
- * things of the form <argument> <command>. Of these, only
- * command=SlantFont, ExtendFont and ReEncodeFont are handled */
- while(*spec) {
- arg = getword(spec, " \t", &spec);
- if(*spec) *spec++ = 0;
- command = getword(spec, " \t", &spec);
- if(*spec) *spec++ = 0;
- if(!arg || !command)
- continue;
- if(STREQ(command, "SlantFont")) {
- double x = 10000 * strtod(arg, 0);
-
- /* SFROUND evaluates arguments twice */
- ent->slant = SFROUND(x);
- } else if(STREQ(command, "ExtendFont")) {
- double x = 10000 * strtod(arg, 0);
-
- ent->extend = SFROUND(x);
- } else if(STREQ(command, "ReEncodeFont")) {
- if(ent->encoding)
- mdvi_free(ent->encoding);
- ent->encoding = mdvi_strdup(arg);
- }
- }
-}
-
-#if 0
-static void print_ent(DviFontMapEnt *ent)
-{
- printf("Entry for `%s':\n", ent->fontname);
- printf(" PS name: %s\n", ent->psname ? ent->psname : "(none)");
- printf(" Encoding: %s\n", ent->encoding ? ent->encoding : "(default)");
- printf(" EncFile: %s\n", ent->encfile ? ent->encfile : "(none)");
- printf(" FontFile: %s\n", ent->fontfile ? ent->fontfile : "(same)");
- printf(" Extend: %ld\n", ent->extend);
- printf(" Slant: %ld\n", ent->slant);
-}
-#endif
-
-DviFontMapEnt *mdvi_load_fontmap(const char *file)
-{
- char *ptr;
- FILE *in;
- int lineno = 1;
- Dstring input;
- ListHead list;
- DviFontMapEnt *ent;
- DviEncoding *last_encoding;
- char *last_encfile;
-
- ptr = kpse_find_file(file, kpse_program_text_format, 0);
- if(ptr == NULL)
- ptr = kpse_find_file(file, kpse_tex_ps_header_format, 0);
- if(ptr == NULL)
- ptr = kpse_find_file(file, kpse_dvips_config_format, 0);
- if(ptr == NULL)
- in = fopen(file, "r");
- else {
- in = fopen(ptr, "r");
- mdvi_free(ptr);
- }
- if(in == NULL)
- return NULL;
-
- ent = NULL;
- listh_init(&list);
- dstring_init(&input);
- last_encoding = NULL;
- last_encfile = NULL;
-
- while((ptr = dgets(&input, in)) != NULL) {
- char *font_file;
- char *tex_name;
- char *ps_name;
- char *vec_name;
- int is_encoding;
- DviEncoding *enc;
-
- lineno++;
- SKIPSP(ptr);
-
- /* we skip what dvips does */
- if(*ptr <= ' ' || *ptr == '*' || *ptr == '#' ||
- *ptr == ';' || *ptr == '%')
- continue;
-
- font_file = NULL;
- tex_name = NULL;
- ps_name = NULL;
- vec_name = NULL;
- is_encoding = 0;
-
- if(ent == NULL) {
- ent = xalloc(DviFontMapEnt);
- ent->encoding = NULL;
- ent->slant = 0;
- ent->extend = 0;
- }
- while(*ptr) {
- char *hdr_name = NULL;
-
- while(*ptr && *ptr <= ' ')
- ptr++;
- if(*ptr == 0)
- break;
- if(*ptr == '"') {
- char *str;
-
- str = getstring(ptr, " \t", &ptr);
- if(*ptr) *ptr++ = 0;
- parse_spec(ent, str);
- continue;
- } else if(*ptr == '<') {
- ptr++;
- if(*ptr == '<')
- ptr++;
- else if(*ptr == '[') {
- is_encoding = 1;
- ptr++;
- }
- SKIPSP(ptr);
- hdr_name = ptr;
- } else if(!tex_name)
- tex_name = ptr;
- else if(!ps_name)
- ps_name = ptr;
- else
- hdr_name = ptr;
-
- /* get next word */
- getword(ptr, " \t", &ptr);
- if(*ptr) *ptr++ = 0;
-
- if(hdr_name) {
- const char *ext = file_extension(hdr_name);
-
- if(is_encoding || (ext && STRCEQ(ext, "enc")))
- vec_name = hdr_name;
- else
- font_file = hdr_name;
- }
- }
-
- if(tex_name == NULL)
- continue;
- ent->fontname = mdvi_strdup(tex_name);
- ent->psname = ps_name ? mdvi_strdup(ps_name) : NULL;
- ent->fontfile = font_file ? mdvi_strdup(font_file) : NULL;
- ent->encfile = vec_name ? mdvi_strdup(vec_name) : NULL;
- ent->fullfile = NULL;
- enc = NULL; /* we don't have this yet */
-
- /* if we have an encoding file, register it */
- if(ent->encfile) {
- /* register_encoding is smart enough not to load the
- * same file twice */
- if(!last_encfile || !STREQ(last_encfile, ent->encfile)) {
- last_encfile = ent->encfile;
- last_encoding = register_encoding(ent->encfile, 1);
- }
- enc = last_encoding;
- }
- if(ent->encfile && enc){
- if(ent->encoding && !STREQ(ent->encoding, enc->name)) {
- warning(
- _("%s: %d: [%s] requested encoding `%s' does not match vector `%s'\n"),
- file, lineno);
- } else if(!ent->encoding)
- ent->encoding = mdvi_strdup(enc->name);
- }
-
- /* add it to the list */
- /*print_ent(ent);*/
- listh_append(&list, LIST(ent));
- ent = NULL;
- }
- dstring_reset(&input);
- fclose(in);
-
- return (DviFontMapEnt *)list.head;
-}
-
-static void free_ent(DviFontMapEnt *ent)
-{
- ASSERT(ent->fontname != NULL);
- mdvi_free(ent->fontname);
- if(ent->psname)
- mdvi_free(ent->psname);
- if(ent->fontfile)
- mdvi_free(ent->fontfile);
- if(ent->encoding)
- mdvi_free(ent->encoding);
- if(ent->encfile)
- mdvi_free(ent->encfile);
- if(ent->fullfile)
- mdvi_free(ent->fullfile);
- mdvi_free(ent);
-}
-
-void mdvi_install_fontmap(DviFontMapEnt *head)
-{
- DviFontMapEnt *ent, *next;
-
- for(ent = head; ent; ent = next) {
- /* add all the entries, overriding old ones */
- DviFontMapEnt *old;
-
- old = (DviFontMapEnt *)
- mdvi_hash_remove(&maptable, MDVI_KEY(ent->fontname));
- if(old != NULL) {
- DEBUG((DBG_FMAP, "%s: overriding fontmap entry\n",
- old->fontname));
- listh_remove(&fontmaps, LIST(old));
- free_ent(old);
- }
- next = ent->next;
- mdvi_hash_add(&maptable, MDVI_KEY(ent->fontname),
- ent, MDVI_HASH_UNCHECKED);
- listh_append(&fontmaps, LIST(ent));
- }
-}
-
-static void init_static_encoding()
-{
- DviEncoding *encoding;
- int i;
-
- DEBUG((DBG_FMAP, "installing static TeX text encoding\n"));
- encoding = xalloc(DviEncoding);
- encoding->private = "";
- encoding->filename = "";
- encoding->name = "TeXTextEncoding";
- encoding->vector = tex_text_vector;
- encoding->links = 1;
- encoding->offset = 0;
- mdvi_hash_create(&encoding->nametab, ENCNAME_HASH_SIZE);
- for(i = 0; i < 256; i++) {
- if(encoding->vector[i]) {
- mdvi_hash_add(&encoding->nametab,
- MDVI_KEY(encoding->vector[i]),
- (DviHashKey)Int2Ptr(i),
- MDVI_HASH_UNCHECKED);
- }
- }
- ASSERT_VALUE(encodings.count, 0);
- mdvi_hash_create(&enctable, ENC_HASH_SIZE);
- mdvi_hash_create(&enctable_file, ENC_HASH_SIZE);
- enctable_file.hash_free = file_hash_free;
- mdvi_hash_add(&enctable, MDVI_KEY(encoding->name),
- encoding, MDVI_HASH_UNCHECKED);
- listh_prepend(&encodings, LIST(encoding));
- tex_text_encoding = encoding;
- default_encoding = tex_text_encoding;
-}
-
-static int mdvi_set_default_encoding(const char *name)
-{
- DviEncoding *enc, *old;
-
- enc = find_encoding(name);
- if(enc == NULL)
- return -1;
- if(enc == default_encoding)
- return 0;
- /* this will read it from file if necessary,
- * but it can fail if the file is corrupted */
- enc = mdvi_request_encoding(name);
- if(enc == NULL)
- return -1;
- old = default_encoding;
- default_encoding = enc;
- if(old != tex_text_encoding)
- mdvi_release_encoding(old, 1);
- return 0;
-}
-
-static int mdvi_init_fontmaps(void)
-{
- char *file;
- char *line;
- FILE *in;
- Dstring input;
- int count = 0;
- char *config;
-
- if(fontmaps_loaded)
- return 0;
- /* we will only try this once */
- fontmaps_loaded = 1;
-
- DEBUG((DBG_FMAP, "reading fontmaps\n"));
-
- /* make sure the static encoding is there */
- init_static_encoding();
-
- /* create the fontmap hash table */
- mdvi_hash_create(&maptable, MAP_HASH_SIZE);
-
- /* get the name of our configuration file */
- config = kpse_cnf_get("mdvi-config");
- if(config == NULL)
- config = MDVI_DEFAULT_CONFIG;
- /* let's ask kpathsea for the file first */
- file = kpse_find_file(config, kpse_program_text_format, 0);
- if(file == NULL)
- in = fopen(config, "r");
- else {
- in = fopen(file, "r");
- mdvi_free(file);
- }
- if(in == NULL)
- return -1;
- dstring_init(&input);
- while((line = dgets(&input, in)) != NULL) {
- char *arg;
-
- SKIPSP(line);
- if(*line < ' ' || *line == '#' || *line == '%')
- continue;
- if(STRNEQ(line, "fontmap", 7)) {
- DviFontMapEnt *ent;
-
- arg = getstring(line + 7, " \t", &line); *line = 0;
- DEBUG((DBG_FMAP, "%s: loading fontmap\n", arg));
- ent = mdvi_load_fontmap(arg);
- if(ent == NULL)
- warning(_("%s: could not load fontmap\n"), arg);
- else {
- DEBUG((DBG_FMAP,
- "%s: installing fontmap\n", arg));
- mdvi_install_fontmap(ent);
- count++;
- }
- } else if(STRNEQ(line, "encoding", 8)) {
- arg = getstring(line + 8, " \t", &line); *line = 0;
- if(arg && *arg)
- register_encoding(arg, 1);
- } else if(STRNEQ(line, "default-encoding", 16)) {
- arg = getstring(line + 16, " \t", &line); *line = 0;
- if(mdvi_set_default_encoding(arg) < 0)
- warning(_("%s: could not set as default encoding\n"),
- arg);
- } else if(STRNEQ(line, "psfontpath", 10)) {
- arg = getstring(line + 11, " \t", &line); *line = 0;
- if(!psinitialized)
- ps_init_default_paths();
- if(psfontdir)
- mdvi_free(psfontdir);
- psfontdir = kpse_path_expand(arg);
- } else if(STRNEQ(line, "pslibpath", 9)) {
- arg = getstring(line + 10, " \t", &line); *line = 0;
- if(!psinitialized)
- ps_init_default_paths();
- if(pslibdir)
- mdvi_free(pslibdir);
- pslibdir = kpse_path_expand(arg);
- } else if(STRNEQ(line, "psfontmap", 9)) {
- arg = getstring(line + 9, " \t", &line); *line = 0;
- if(mdvi_ps_read_fontmap(arg) < 0)
- warning("%s: %s: could not read PS fontmap\n",
- config, arg);
- }
- }
- fclose(in);
- dstring_reset(&input);
- fontmaps_loaded = 1;
- DEBUG((DBG_FMAP, "%d files installed, %d fontmaps\n",
- count, fontmaps.count));
- return count;
-}
-
-int mdvi_query_fontmap(DviFontMapInfo *info, const char *fontname)
-{
- DviFontMapEnt *ent;
-
- if(!fontmaps_loaded && mdvi_init_fontmaps() < 0)
- return -1;
- ent = (DviFontMapEnt *)mdvi_hash_lookup(&maptable, MDVI_KEY(fontname));
-
- if(ent == NULL)
- return -1;
- info->psname = ent->psname;
- info->encoding = ent->encoding;
- info->fontfile = ent->fontfile;
- info->extend = ent->extend;
- info->slant = ent->slant;
- info->fullfile = ent->fullfile;
-
- return 0;
-}
-
-int mdvi_add_fontmap_file(const char *name, const char *fullpath)
-{
- DviFontMapEnt *ent;
-
- if(!fontmaps_loaded && mdvi_init_fontmaps() < 0)
- return -1;
- ent = (DviFontMapEnt *)mdvi_hash_lookup(&maptable, MDVI_KEY(name));
- if(ent == NULL)
- return -1;
- if(ent->fullfile)
- mdvi_free(ent->fullfile);
- ent->fullfile = mdvi_strdup(fullpath);
- return 0;
-}
-
-
-void mdvi_flush_encodings(void)
-{
- DviEncoding *enc;
-
- if(enctable.nbucks == 0)
- return;
-
- DEBUG((DBG_FMAP, "flushing %d encodings\n", encodings.count));
- /* asked to remove all encodings */
- for(; (enc = (DviEncoding *)encodings.head); ) {
- encodings.head = LIST(enc->next);
- if((enc != tex_text_encoding && enc->links) || enc->links > 1) {
- warning(_("encoding vector `%s' is in use\n"),
- enc->name);
- }
- destroy_encoding(enc);
- }
- /* destroy the static encoding */
- if(tex_text_encoding->nametab.buckets)
- mdvi_hash_reset(&tex_text_encoding->nametab, 0);
- mdvi_hash_reset(&enctable, 0);
- mdvi_hash_reset(&enctable_file, 0);
-}
-
-void mdvi_flush_fontmaps(void)
-{
- DviFontMapEnt *ent;
-
- if(!fontmaps_loaded)
- return;
-
- DEBUG((DBG_FMAP, "flushing %d fontmaps\n", fontmaps.count));
- for(; (ent = (DviFontMapEnt *)fontmaps.head); ) {
- fontmaps.head = LIST(ent->next);
- free_ent(ent);
- }
- mdvi_hash_reset(&maptable, 0);
- fontmaps_loaded = 0;
-}
-
-/* reading of PS fontmaps */
-
-void ps_init_default_paths(void)
-{
- char *kppath;
- char *kfpath;
-
- ASSERT(psinitialized == 0);
-
- kppath = getenv("GS_LIB");
- kfpath = getenv("GS_FONTPATH");
-
- if(kppath != NULL)
- pslibdir = kpse_path_expand(kppath);
- if(kfpath != NULL)
- psfontdir = kpse_path_expand(kfpath);
-
- listh_init(&psfonts);
- mdvi_hash_create(&pstable, PSMAP_HASH_SIZE);
- psinitialized = 1;
-}
-
-int mdvi_ps_read_fontmap(const char *name)
-{
- char *fullname;
- FILE *in;
- Dstring dstr;
- char *line;
- int count = 0;
-
- if(!psinitialized)
- ps_init_default_paths();
- if(pslibdir)
- fullname = kpse_path_search(pslibdir, name, 1);
- else
- fullname = (char *)name;
- in = fopen(fullname, "r");
- if(in == NULL) {
- if(fullname != name)
- mdvi_free(fullname);
- return -1;
- }
- dstring_init(&dstr);
-
- while((line = dgets(&dstr, in)) != NULL) {
- char *name;
- char *mapname;
- const char *ext;
- PSFontMap *ps;
-
- SKIPSP(line);
- /* we're looking for lines of the form
- * /FONT-NAME (fontfile)
- * /FONT-NAME /FONT-ALIAS
- */
- if(*line != '/')
- continue;
- name = getword(line + 1, " \t", &line);
- if(*line) *line++ = 0;
- mapname = getword(line, " \t", &line);
- if(*line) *line++ = 0;
-
- if(!name || !mapname || !*name)
- continue;
- if(*mapname == '(') {
- char *end;
-
- mapname++;
- for(end = mapname; *end && *end != ')'; end++);
- *end = 0;
- }
- if(!*mapname)
- continue;
- /* dont add `.gsf' fonts, which require a full blown
- * PostScript interpreter */
- ext = file_extension(mapname);
- if(ext && STREQ(ext, "gsf")) {
- DEBUG((DBG_FMAP, "(ps) %s: font `%s' ignored\n",
- name, mapname));
- continue;
- }
- ps = (PSFontMap *)mdvi_hash_lookup(&pstable, MDVI_KEY(name));
- if(ps != NULL) {
- if(STREQ(ps->mapname, mapname))
- continue;
- DEBUG((DBG_FMAP,
- "(ps) replacing font `%s' (%s) by `%s'\n",
- name, ps->mapname, mapname));
- mdvi_free(ps->mapname);
- ps->mapname = mdvi_strdup(mapname);
- if(ps->fullname) {
- mdvi_free(ps->fullname);
- ps->fullname = NULL;
- }
- } else {
- DEBUG((DBG_FMAP, "(ps) adding font `%s' as `%s'\n",
- name, mapname));
- ps = xalloc(PSFontMap);
- ps->psname = mdvi_strdup(name);
- ps->mapname = mdvi_strdup(mapname);
- ps->fullname = NULL;
- listh_append(&psfonts, LIST(ps));
- mdvi_hash_add(&pstable, MDVI_KEY(ps->psname),
- ps, MDVI_HASH_UNCHECKED);
- count++;
- }
- }
- fclose(in);
- dstring_reset(&dstr);
-
- DEBUG((DBG_FMAP, "(ps) %s: %d PostScript fonts registered\n",
- fullname, count));
- return 0;
-}
-
-void mdvi_ps_flush_fonts(void)
-{
- PSFontMap *map;
-
- if(!psinitialized)
- return;
- DEBUG((DBG_FMAP, "(ps) flushing PS font map (%d) entries\n",
- psfonts.count));
- mdvi_hash_reset(&pstable, 0);
- for(; (map = (PSFontMap *)psfonts.head); ) {
- psfonts.head = LIST(map->next);
- mdvi_free(map->psname);
- mdvi_free(map->mapname);
- if(map->fullname)
- mdvi_free(map->fullname);
- mdvi_free(map);
- }
- listh_init(&psfonts);
- if(pslibdir) {
- mdvi_free(pslibdir);
- pslibdir = NULL;
- }
- if(psfontdir) {
- mdvi_free(psfontdir);
- psfontdir = NULL;
- }
- psinitialized = 0;
-}
-
-char *mdvi_ps_find_font(const char *psname)
-{
- PSFontMap *map, *smap;
- char *filename;
- int recursion_limit = 32;
-
- DEBUG((DBG_FMAP, "(ps) resolving PS font `%s'\n", psname));
- if(!psinitialized)
- return NULL;
- map = (PSFontMap *)mdvi_hash_lookup(&pstable, MDVI_KEY(psname));
- if(map == NULL)
- return NULL;
- if(map->fullname)
- return mdvi_strdup(map->fullname);
-
- /* is it an alias? */
- smap = map;
- while(recursion_limit-- > 0 && smap && *smap->mapname == '/')
- smap = (PSFontMap *)mdvi_hash_lookup(&pstable,
- MDVI_KEY(smap->mapname + 1));
- if(smap == NULL) {
- if(recursion_limit == 0)
- DEBUG((DBG_FMAP,
- "(ps) %s: possible loop in PS font map\n",
- psname));
- return NULL;
- }
-
- if(psfontdir)
- filename = kpse_path_search(psfontdir, smap->mapname, 1);
- else if(file_exists(map->mapname))
- filename = mdvi_strdup(map->mapname);
- else
- filename = NULL;
- if(filename)
- map->fullname = mdvi_strdup(filename);
-
- return filename;
-}
-
-/*
- * To get metric info for a font, we proceed as follows:
- * - We try to find NAME.<tfm,ofm,afm>.
- * - We query the fontmap for NAME.
- * - We get back a PSNAME, and use to find the file in the PS font map.
- * - We get the PSFONT file name, replace its extension by "afm" and
- * lookup the file in GS's font search path.
- * - We finally read the data, transform it as specified in our font map,
- * and return it to the caller. The new data is left in the font metrics
- * cache, so the next time it will be found at the first step (when we look
- * up NAME.afm).
- *
- * The name `_ps_' in this function is not meant to imply that it can be
- * used for Type1 fonts only. It should be usable for TrueType fonts as well.
- *
- * The returned metric info is subjected to the same caching mechanism as
- * all the other metric data, as returned by get_font_metrics(). One should
- * not modify the returned data at all, and it should be disposed with
- * free_font_metrics().
- */
-TFMInfo *mdvi_ps_get_metrics(const char *fontname)
-{
- TFMInfo *info;
- DviFontMapInfo map;
- char buffer[64]; /* to avoid mallocs */
- char *psfont;
- char *basefile;
- char *afmfile;
- char *ext;
- int baselen;
- int nc;
- TFMChar *ch;
- double efactor;
- double sfactor;
-
- DEBUG((DBG_FMAP, "(ps) %s: looking for metric data\n", fontname));
- info = get_font_metrics(fontname, DviFontAny, NULL);
- if(info != NULL)
- return info;
-
- /* query the fontmap */
- if(mdvi_query_fontmap(&map, fontname) < 0 || !map.psname)
- return NULL;
-
- /* get the PS font */
- psfont = mdvi_ps_find_font(map.psname);
- if(psfont == NULL)
- return NULL;
- DEBUG((DBG_FMAP, "(ps) %s: found as PS font `%s'\n",
- fontname, psfont));
- /* replace its extension */
- basefile = strrchr(psfont, '/');
- if(basefile == NULL)
- basefile = psfont;
- baselen = strlen(basefile);
- ext = strrchr(basefile, '.');
- if(ext != NULL)
- *ext = 0;
- if(baselen + 4 < 64)
- afmfile = &buffer[0];
- else
- afmfile = mdvi_malloc(baselen + 5);
- strcpy(afmfile, basefile);
- strcpy(afmfile + baselen, ".afm");
- /* we don't need this anymore */
- mdvi_free(psfont);
- DEBUG((DBG_FMAP, "(ps) %s: looking for `%s'\n",
- fontname, afmfile));
- /* lookup the file */
- psfont = kpse_path_search(psfontdir, afmfile, 1);
- /* don't need this anymore */
- if(afmfile != &buffer[0])
- mdvi_free(afmfile);
- if(psfont != NULL) {
- info = get_font_metrics(fontname, DviFontAFM, psfont);
- mdvi_free(psfont);
- } else
- info = NULL;
- if(info == NULL || (!map.extend && !map.slant))
- return info;
-
- /*
- * transform the data as prescribed -- keep in mind that `info'
- * points to CACHED data, so we're modifying the metric cache
- * in place.
- */
-
-#define DROUND(x) ((x) >= 0 ? floor((x) + 0.5) : ceil((x) - 0.5))
-#define TRANSFORM(x,y) DROUND(efactor * (x) + sfactor * (y))
-
- efactor = (double)map.extend / 10000.0;
- sfactor = (double)map.slant / 10000.0;
- DEBUG((DBG_FMAP, "(ps) %s: applying extend=%f, slant=%f\n",
- efactor, sfactor));
-
- nc = info->hic - info->loc + 1;
- for(ch = info->chars; ch < info->chars + nc; ch++) {
- /* the AFM bounding box is:
- * wx = ch->advance
- * llx = ch->left
- * lly = -ch->depth
- * urx = ch->right
- * ury = ch->height
- * what we do here is transform wx, llx, and urx by
- * newX = efactor * oldX + sfactor * oldY
- * where for `wx' oldY = 0. Also, these numbers are all in
- * TFM units (i.e. TFM's fix-words, which is just the actual
- * number times 2^20, no need to do anything to it).
- */
- if(ch->present) {
- ch->advance = TRANSFORM(ch->advance, 0);
- ch->left = TRANSFORM(ch->left, -ch->depth);
- ch->right = TRANSFORM(ch->right, ch->height);
- }
- }
-
- return info;
-}