summaryrefslogtreecommitdiff
path: root/Build/source/texk/windvi/t1.c
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
committerKarl Berry <karl@freefriends.org>2006-01-17 21:41:51 +0000
commit487ca4806cc046076293cf6cc5fbba0db282bac7 (patch)
tree847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/windvi/t1.c
parenta3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff)
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/windvi/t1.c')
-rw-r--r--Build/source/texk/windvi/t1.c1051
1 files changed, 1051 insertions, 0 deletions
diff --git a/Build/source/texk/windvi/t1.c b/Build/source/texk/windvi/t1.c
new file mode 100644
index 00000000000..e49a4938e22
--- /dev/null
+++ b/Build/source/texk/windvi/t1.c
@@ -0,0 +1,1051 @@
+/*========================================================================*\
+
+Copyright (c) 1999 Nicolai Langfeldt
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL NICOLAI LANGFELDT, PAUL VOJTA, OR ANYONE ELSE BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Names:
+ janl: Nicolai Langfeldt (janl@math.uio.no)
+ rmz: Rainer Menzner (Rainer.Menzner@neuroinformatik.ruhr-uni-bochum.de)
+
+History:
+ 18/02/1999, janl: Initial version, first public alpha release of xdvi-t1.
+ 22/02/1999, rmz: Changes to make scaling and antialiasing work better.
+ 24/02/1999, janl: Read afm files to get alignments right. type1 char
+ widhts are to coarse.
+ 08/05/1999, janl: Update to t1lib-0.9, add code to read more generic
+ encoding maps (encoding.map, not *.enc)
+ 10/05/1999, janl: New font loading code and data struct for defered
+ font loading. Significant reduction in startup time realized.
+
+Bugs:
+ - Every kpse_find_file call presents a memory leak. The pathname
+ buffer is not freed.
+
+\*========================================================================*/
+
+#define HAVE_BOOLEAN 1
+
+#include "xdvi-config.h"
+
+#if T1
+
+#define PRIVATE static
+#define PUBLIC
+
+#if defined(HAVE_STRING_H)
+#include <string.h>
+#else
+extern char *strtok P2H(char *, const char *);
+#endif
+
+#include "dvi.h"
+#include <kpathsea/tex-file.h>
+
+#include <t1lib.h>
+#include <t1libw32.h>
+
+/* Datastructures:
+
+ encodings[n]: Loaded from map file
+ [0] = 8r, <vector>
+ [1] = 8c, <vector>
+
+ The vectors are demand-loaded in 'load_encoded_font'
+
+*/
+
+typedef struct encoding {
+ char *enc; /* This may be NULL. From dvips maps we get
+ encodings loaded by filename, and no name given */
+ char *file;
+ char **vector;
+} encoding;
+
+PRIVATE encoding *encodings; /* Dynamic array */
+#define ENCSTART 16 /* Start size. Normaly there will not
+ be even this many. */
+#define ENCGROW 16 /* Grow by, when full */
+PRIVATE int maxenc=ENCSTART-1; /* Current size of array */
+PRIVATE int enclidx=-1; /* Current last index in array */
+
+/*
+
+ t1fonts[n]: Built as xdvi loads t1 fonts
+ idx file short t1id loaded
+ [0] = /path/cmr10.pfb, cmr10 0 1
+ [1] = /path/prmr.pfa, prmr 1 0
+ [2] = /path/pcrr8a.pfa, pcrr8a 2 0
+
+ This array enumerates the loaded t1 fonts by full path name. The
+ refered to t1id is the t1lib font id. The font will not be
+ extended/slanted/encoded. The loaded field indicates if
+ T1_LoadFont has been called for the font yet. texfonts that need a
+ modified version of the t1 font must use T1_CopyFont to copy the
+ raw font and obtain the id of a new t1 font which can then be
+ modified. As described in the t1 docs a font must be loaded before
+ it can be copied.
+
+ Fonts that are copies of other fonts have NULL filenames. If any
+ font files are to be reused based on the file name the raw font
+ must be reused, not a copy.
+
+ The short field contains the font as it was identified in the
+ fontmap. This is used to save searching; if two fonts are
+ identified the same way in the fontmap they the same font.
+
+*/
+
+typedef struct t1font {
+ char *file;
+ char *shortname;
+ int t1id;
+ int loaded;
+} t1font;
+
+PRIVATE t1font *t1fonts; /* Dynamic array */
+#define T1START 2048 /* Japanese, Chineese, Korean and others
+ use a lot of fonts */
+#define T1GROW 1024
+PRIVATE int maxt1=T1START-1;
+PRIVATE int t1lidx=-1;
+
+/*
+ fontmaps[n]: Loaded from map file, and extended with 'implied'
+ fonts as needed.
+ idx texname enc exten. slant filena. t1libid pathn. tfmidx
+ [0] = pcrr8rn 0 750 0 pcrr8a 2 ... 2
+ [1] = putro8r 0 0 0 putro8r 3 ... 3
+
+ The first 5 fields of this table are loaded from the font map
+ files, or filled out with default values when implied fonts are
+ set-up. The t1libid is -1 until the font is loaded or copied as
+ described under t1fonts. Once the dvi file reveals that the font
+ is needed it is located on disk to ensure it exists, and the
+ pathname field is filled out. The t1 font is not loaded, or
+ copied, before it's needed because set_t1_char has been called to
+ draw a glyph from the font. The late loading is necessiated by the
+ high cost of loading fonts. If the font loading is concentrated at
+ startup of the program the startup-time becomes ecessively high due
+ to the high number of fonts used by any normaly LaTeX-document.
+
+ 0 extention and slant means no extention/slant. If the input
+ values are decimal (less than 10) they're multiplied by 1000 and
+ 10000 respectively to obtain fixed-point integer values. Integer
+ values have the advandage of being testable for exact match (== 0)
+ on all architectures (it's true! Not all architectures can do
+ (reliable) exact matching of floatingpoint values)
+
+*/
+
+typedef struct fontmap {
+ char *texname;
+ int enc; /* Index in encoding array */
+ int extention; /* Fixed point, *1000 */
+ int slant; /* Fixed point, *10000, some font slantings have 4
+ significant digits, all after the decimalpoint */
+ char *filename; /* Name of the t1 font file as given in map/dvi */
+
+ int t1libid; /* The t1lib id of this font, or -1 if not set up */
+ char *pathname; /* Full path of the font, once needed and located */
+ int tfmidx; /* Index in tfminfo array, or -1 */
+} fontmap;
+
+PRIVATE fontmap *fontmaps;
+#define FNTMAPSTART 2048
+#define FNTMAPGROW 1024
+PRIVATE int maxmap=FNTMAPSTART-1;
+PRIVATE int maplidx=-1;
+
+/*
+ widthinfo[n]: TFM widht info, demand loaded as the fonts are used.
+ idx texname widths
+ [0] = cmr10 ...
+ [1] = ptmr8r ...
+ [2] = pcrr8rn ...
+ [3] = putro8r ...
+
+ The widthinfo is loaded from the font tfm file since the type1
+ width information isn't precise enough to avoid accumulating
+ rounding errors that make things visibly unaligned. This is
+ esp. noticeable in tables; the vline column separators become
+ unaligned.
+
+ For other than "design" sizes the widths are scaled up or down.
+
+*/
+
+typedef struct tfminfos {
+ char *texname;
+ long designsize;
+ long widths[256];
+} tfminfos;
+
+PRIVATE tfminfos *tfminfo;
+#define TEXWSTART 2048
+#define TEXWGROW 1024
+PRIVATE int maxw=TEXWSTART-1;
+PRIVATE int wlidx=-1;
+
+PRIVATE int size_devisor;
+
+/* For file reading */
+#define BUFFER_SIZE 512
+
+/* This is the conversion factor from TeXs pt to TeXs bp (big point).
+ Maximum machine precision is needed to keep it accurate. */
+PRIVATE double bp_fac=72.0/72.27;
+
+/* Try to convert from PS charspace units to DVI units with minimal
+ loss of significant digits */
+#define t1_dvi_conv(x) ((((int) (x)) << 16)/1000)
+/* Convert from DVI units to TeX pt */
+#define dvi_pt_conv(x) (((long) (x)) >> 16)
+/* Experiment with preserving significant digits by using floating point.
+ No win observed. */
+#define dvi_pt_fconv(x) ((x) / 65536.0)
+
+/* Convert from TFM units to DVI units */
+#define tfm_dvi_conv(x) (((int) (x)) >> 1)
+
+/* ********************** FONT AND ENCODING LOADING ******************** */
+
+PRIVATE char **load_vector P1C(char *,enc)
+
+{
+ char *filename;
+ char **vector=NULL;
+
+ filename=kpse_find_file(enc,kpse_program_text_format,0);
+
+ if (filename!=NULL) {
+ vector=T1_LoadEncoding(filename);
+ if (vector==NULL) {
+ fprintf(stderr,"%s: Unable to load encoding vector %s from %s\n",
+ enc,filename);
+ perror("xdvi");
+ exit(1);
+ }
+ fprintf(stderr,"Encoding %s loaded from %s at 0x%lx\n",
+ enc,filename,vector);
+ } else
+ fprintf(stderr,"Unable to load encoding vector %s\n",enc);
+
+ return vector;
+}
+
+
+PRIVATE int add_tfm P1C(char *,texname)
+
+{
+ /* Load font metrics if not already loaded. Return index into
+ fontmetrics array, or -1 if it failed */
+
+ int i;
+
+ for (i=0;i<=wlidx;i++)
+ if (strcmp(tfminfo[i].texname,texname)==0)
+ return i;
+
+ if (wlidx==maxw) {
+ maxw += TEXWGROW;
+ tfminfo=realloc(tfminfo,sizeof(*tfminfo)*maxw);
+ if (tfminfo==NULL) {
+ fprintf(stderr,"%s: Error: Out of memory.\n");
+ exit(1);
+ }
+ }
+
+ wlidx++;
+
+ tfminfo[wlidx].texname=texname;
+
+ if (!tfmload(texname,&tfminfo[wlidx].designsize,tfminfo[wlidx].widths)) {
+ fprintf(stderr,"%s: Could not find/load tfm file for %s. "
+ "%s: Expect ugly output.\n",texname);
+
+ wlidx--;
+ return -1;
+ }
+
+ return wlidx;
+}
+
+
+PRIVATE int add_t1font P2C(char *,fontname, char *,filename)
+
+{
+ /* Add t1 font to list, or not if it's already there. Return the
+ t1lib font id. The filename argument is optional, but is assumed
+ to be a full path if it is given */
+
+ int id,i,free_it=0;
+ char *path;
+
+ /* Already set up by that name? */
+ for (i=0;i<=t1lidx;i++) {
+ if (strcmp(t1fonts[i].shortname,fontname)==0 ||
+ strcmp(t1fonts[i].file,fontname)==0) {
+#if debug
+ fprintf(stderr,"Type1 font %s already loaded from %s\n",
+ fontname, filename);
+#endif
+ return t1fonts[i].t1id;
+ }
+ }
+
+ /* Insert and set up new t1 font */
+
+ if (t1lidx==maxt1) {
+ /* Make room */
+ maxt1 += T1GROW;
+ t1fonts=realloc(t1fonts,sizeof(*t1fonts)*maxt1);
+ if (t1fonts==NULL) {
+ fprintf(stderr,"%s: Error: Out of memory\n");
+ exit(1);
+ }
+ fprintf(stderr,"Enlarged t1 table from %d to %d entries\n",
+ t1lidx, maxt1);
+ }
+
+ t1lidx++;
+
+ if (filename == NULL) {
+ /* We don't know the full path name yet, find it */
+ fprintf(stderr,"Looking for type1: %s\n",fontname);
+ path = kpse_find_file(fontname,kpse_type1_format,0);
+ if (path == NULL) return -1; /* xdvi will use substitution font */
+ free_it=1;
+ } else {
+ path=filename;
+ }
+
+ t1fonts[t1lidx].file=strdup(path);
+ t1fonts[t1lidx].t1id=id=T1_AddFont(path);
+ t1fonts[t1lidx].shortname=strdup(fontname);
+ t1fonts[t1lidx].loaded=0;
+
+ if (free_it)
+ free(path);
+
+ fprintf(stderr,"%s set-up as t1lib font %d\n", filename, id);
+
+#if USE_AFM
+ /* Set the afm filename. Always before loading. If no afm file
+ found t1lib will use fallback code */
+ path=kpse_find_file(fontname,kpse_afm_format,0);
+ if (path!=NULL) {
+ T1_SetAfmFileName(id,path);
+ free(path);
+ }
+#endif
+
+ return id;
+}
+
+
+PRIVATE int find_texfont P1C(char *,texname)
+
+{
+ /* Find fontmap index of texfont */
+ int i;
+
+ for (i=0;i<maplidx;i++) {
+ if (strcmp(fontmaps[i].texname,texname)==0) {
+#if debug
+ fprintf(stderr,"Type1 font already loaded: %s\n",texname);
+#endif
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+PRIVATE int setup_encoded_T1_font P6C(char *,texname, char *,alias,
+ char *,filename,
+ int, enc, int, ext, int, sl)
+
+
+{
+ /* xdvi T1 Font loading is done in two steps:
+
+ 1. At xdvi startup two things happen:
+
+ a. The fontmaps are read.
+
+ b. the dvi file is (partialy) scanned, and fonts are set up.
+ In the case of t1 fonts we only set up the data structures,
+ they are not actually loaded until they are used.
+
+ 2. At the time a T1 font is used it is loaded, encoded, extended
+ and slanted as prescribed.
+
+ This procedure takes care of step 1a. It locates the font and
+ sets up the data-structures so it may be assumed, by xdvi, to be
+ loaded. Return the fontmaps array index.
+
+ The 'texname' param should be the texname of the font, such as
+ ptmr8r or cmr10.
+
+ The 'alias' param should be the file name of the font if it is
+ different from the texname. This is often the case with fonts
+ defined in fontmaps.
+
+ If, for some reason, the full filename of the font has already
+ been looked up before we get here it is passed in the filename
+ param so we don't have to look it up again.
+
+ Implied encodings are not handled here.
+
+ REMEMBER: THIS PROC IS CALLED FOR EACH FONT IN THE FONTMAPS, WE
+ CANNOT DO ANY EXPENSIVE OPERATIONS HERE!!!
+
+ */
+
+ int idx=-1;
+
+ /* Already setup by that name? */
+ idx=find_texfont(texname);
+
+ if (idx!=-1) return idx;
+
+ /* Not set up. Do it. */
+
+ if (maplidx==maxmap) {
+ maxmap += FNTMAPGROW;
+ /* Hope realloc isn't destructive anywhere :-) */
+ fontmaps=realloc(fontmaps,sizeof(*fontmaps)*maxmap);
+ if (fontmaps==NULL) {
+ fprintf(stderr,"%s: Error: No memory for fontmap. Buy some RAM?\n");
+ exit(1);
+ }
+ fprintf(stderr,"Enlarged the fontmap from %d to %d entries\n",
+ maplidx,maxmap);
+ }
+
+ maplidx++;
+
+ if (alias==NULL)
+ alias=texname;
+
+ fontmaps[maplidx].texname=strdup(texname);
+ fontmaps[maplidx].enc=enc;
+ fontmaps[maplidx].extention=ext;
+ fontmaps[maplidx].slant=sl;
+
+ fontmaps[maplidx].filename=strdup(alias);
+ fontmaps[maplidx].t1libid=-1;
+ if (filename!=NULL) {
+ fontmaps[maplidx].pathname=strdup(filename);
+ } else {
+ fontmaps[maplidx].pathname=NULL;
+ }
+ fontmaps[maplidx].tfmidx=-1;
+
+ if (fontmaps[maplidx].texname==NULL || fontmaps[maplidx].filename==NULL) {
+ fprintf(stderr, "%s: Error: Dang, can't find any free memory!\n");
+ exit(1);
+ }
+
+ return maplidx;
+}
+
+
+PRIVATE void load_font_now P1C(int, idx)
+
+{
+ /* At this point xdvi needs to draw a glyph from this font. But
+ first it must be loaded/copied and modified if needed. */
+
+ int t1idx; /* The fontmap entry number */
+ int t1id; /* The id of the unmodified font */
+ int cid; /* The id of the copied font */
+ int enc,sl,ext;
+
+ t1idx=add_t1font(fontmaps[idx].filename,fontmaps[idx].pathname);
+
+ t1id=fontmaps[idx].t1libid=t1fonts[t1idx].t1id;
+
+ if (!t1fonts[t1idx].loaded && T1_LoadFont(t1id)==-1) {
+ fprintf(stderr,"Could not load T1 font %s from %s alias %s\n",
+ fontmaps[idx].texname, fontmaps[idx].filename,
+ fontmaps[idx].pathname);
+ exit(1);
+ }
+
+ fontmaps[idx].tfmidx=add_tfm(fontmaps[idx].texname);
+
+ t1fonts[t1idx].loaded=1;
+
+ /* If there is nothing further to do, just return */
+ enc=fontmaps[idx].enc;
+ ext=fontmaps[idx].extention;
+ sl=fontmaps[idx].slant;
+
+ if (enc==-1 && ext==0 && sl==0)
+ return;
+
+ /* The fontmap entry speaks of a modified font. Copy it first. */
+ cid = T1_CopyFont(t1id);
+
+ fprintf(stderr,"t1lib font %d copied to %d to be modified: enc: %d, sl: "
+ "%d ext: %d\n",t1id,cid,enc,sl,ext);
+
+ fontmaps[idx].t1libid=cid;
+
+ if (enc!=-1) {
+ /* Demand load vector */
+ if (encodings[enc].vector==NULL)
+ encodings[enc].vector=load_vector(encodings[enc].file);
+
+ if (encodings[enc].vector==NULL) {
+ fprintf(stderr,"xdvik: Could not load encoding file %s for vector %s.\n"
+ "The font '%s' is affected by this.\n",
+ encodings[enc].file,encodings[enc].enc,fontmaps[idx].texname);
+ } else {
+ if (T1_ReencodeFont(cid,encodings[enc].vector)!=0) {
+ fprintf(stderr,"%s: WARNING: Re-encoding of %s did not work.\n",
+ fontmaps[idx].texname);
+ }
+ }
+ }
+
+ if (ext)
+ T1_ExtendFont(cid,ext/1000.0);
+
+ if (sl)
+ T1_SlantFont(cid,sl/10000.0);
+
+ return;
+}
+
+
+PUBLIC int find_T1_font P1C(char *,texname)
+
+{
+ /* Step 1b in the scenario above. xdvi knows that this font is
+ needed. Check if it is available. But do not load yet.
+ Return the fontmap index at which the font was found */
+
+ int idx; /* Iterator, t1 font id */
+ char *filename;
+ int fl,el; /* Fontname length, encoding name length */
+ int encoded=-1;
+ char *mname; /* Modified font name */
+
+ encoded=0;
+
+ /* First: Check the maps */
+ idx=find_texfont(texname);
+
+ if (idx!=-1) {
+ if (fontmaps[idx].pathname==NULL) {
+ filename=kpse_find_file(fontmaps[idx].filename,kpse_type1_format,0);
+ /* It should have been on disk according to the map, but never
+ fear, xdvi will try to find it other ways. */
+ if (filename==NULL) {
+ fprintf(stderr,"%s: Warning: Font map calls for %s, but it was "
+ "not found\n",fontmaps[idx].filename);
+ return -1;
+ }
+ fontmaps[idx].pathname=filename;
+ }
+ return idx;
+ }
+
+ /* Second: the bare name */
+ filename=kpse_find_file(texname,kpse_type1_format,0);
+
+ if (filename!=NULL)
+ return setup_encoded_T1_font(texname, NULL, filename, -1, 0, 0);
+
+ /* Third: Implied encoding? */
+ fl=strlen(texname);
+
+ for (idx=0; idx<=enclidx; idx++) {
+
+ if (encodings[idx].enc==NULL)
+ continue;
+
+ el=strlen(encodings[idx].enc);
+
+ if (strcmp(texname+(fl-el),encodings[idx].enc)==0) {
+ /* Found a matching encoding */
+ fprintf(stderr,"Encoding match: %s - %s\n",texname,encodings[idx].enc);
+ mname=malloc(fl+2);
+ strcpy(mname,texname);
+ mname[fl-el]='\0';
+ /* If we had 'ptmr8r' the we now look for 'ptmr' */
+ filename=kpse_find_file(mname, kpse_type1_format,0);
+ if (filename==NULL) {
+ /* No? Look for ptmr8a. 8a postfix is oft used on raw fonts */
+ strcat(mname,"8a");
+ filename=kpse_find_file(mname,kpse_type1_format,0);
+ }
+ if (filename!=NULL)
+ return setup_encoded_T1_font(texname, mname, filename, idx, 0, 0);
+
+ free(mname);
+ /* Now we have tried everything. Time to give up. */
+ return -1;
+
+ } /* If (strcmp...) */
+ } /* for */
+
+ return -1;
+}
+
+/* ************************* CONFIG FILE READING ************************ */
+
+
+PRIVATE int new_encoding P2C(char *,enc, char *,file)
+
+{
+ /* (Possebly) new encoding entered from .cfg file, or from dvips
+ map. When entered from dvips map the enc is null/anonymous */
+
+ int i;
+
+ /* Shirley! You're jesting! */
+ if (file==NULL) return -1;
+
+ if (enc==NULL) {
+ /* Enter by file name. First check if the file has been entered
+ already. */
+ for (i=0; i<=enclidx; i++) {
+ if (strcmp(encodings[i].file,file)==0)
+ return i;
+ }
+ } else {
+ /* Enter by encoding name. Check if already loaded first. */
+ for (i=0; i<=enclidx; i++) {
+ if (encodings[i].enc!=NULL && strcmp(encodings[i].enc,enc)==0)
+ return i;
+ }
+ }
+
+ /* Bonafide new encoding */
+
+ /* Any space left? */
+ if (enclidx==maxenc) {
+ maxenc += ENCGROW;
+ encodings=realloc(encodings,sizeof(*encodings)*maxenc);
+ if (encodings==NULL) {
+ fprintf(stderr,"%s: Error: No memory for encoding map.?\n");
+ exit(1);
+ }
+ fprintf(stderr,"Enlarged encoding map from %d to %d entries\n",
+ enclidx,maxenc);
+ }
+
+ enclidx++;
+#if debug
+ fprintf(stderr,"New encoding #%d: '%s' -> '%s'\n",enclidx,enc,file);
+#endif
+ encodings[enclidx].enc=strdup(enc);
+ encodings[enclidx].file=strdup(file);
+ encodings[enclidx].vector=NULL; /* Demand load later */
+
+ if (encodings[enclidx].enc==NULL || encodings[enclidx].file==NULL) {
+ fprintf(stderr,"%s: Ran out memory\n");
+ exit(0);
+ }
+
+ return enclidx;
+}
+
+
+PUBLIC void add_T1_mapentry P4C(char *,name, char *,file, char *,vec,
+ char *,spec)
+
+{
+ /* This is called from getpsinfo, once for each fontmap line. We
+ will dutifully enter the information into our fontmap table */
+
+ static char delim[]="\t ";
+ char *last, *current;
+ float number;
+ int extend=0;
+ int slant=0;
+
+#if 0
+ fprintf(stderr,"Map entry: %s -> %s(%s) Spec: %s\n",name,file,vec,spec);
+#endif
+
+ if (spec!=NULL) {
+ /* Try to analyze the postscript string. We recognize two things:
+ "n ExtendFont" and "m SlantFont". n can be a decimal number in
+ which case it's an extention factor, or a integer, in which
+ case it's a charspace unit? In any case 850 = .85 */
+
+ last=strtok(spec,delim);
+ current=strtok(NULL,delim);
+ while (current!=NULL) {
+ if (strcmp(current,"ExtendFont")==0) {
+ sscanf(last,"%f",&number);
+ if (number<10.0)
+ extend = number * 1000.0;
+ else
+ extend = number;
+#if 0
+ fprintf(stderr,"EXTEND: %d\n",extend);
+#endif
+ } else if (strcmp(current,"SlantFont")==0) {
+ sscanf(last,"%f",&number);
+ slant = number * 10000.0;
+#if 0
+ fprintf(stderr,"SLANT: %d\n",slant);
+#endif
+ }
+ last=current;
+ current=strtok(NULL,delim);
+ }
+ }
+
+ setup_encoded_T1_font(name,file,NULL,new_encoding(NULL,vec),extend,slant);
+
+ if (fontmaps[maplidx].texname==NULL || fontmaps[maplidx].filename==NULL) {
+ fprintf(stderr, "%s: Error: Dang, can't find any free memory!\n");
+ exit(1);
+ }
+}
+
+
+PRIVATE void read_enc_map P1C(char *,file)
+
+ /* Read encoding map file */
+
+{
+ char *filename;
+ char *enc, *name, *f;
+ char *buffer;
+ FILE *mapfile;
+ int len;
+ int i;
+ static const char delim[]="\t \n\r";
+
+ filename=kpse_find_file(file,kpse_program_text_format,1);
+ if (filename==NULL) {
+ fprintf(stderr,"%s: Warning: Unable to find %s\n",file);
+ exit(1);
+ }
+
+ mapfile = fopen(filename,"r");
+
+ if (mapfile==NULL) {
+ fprintf(stderr,"%s: Unable to open %s for reading: ",filename);
+ perror("");
+ exit(1);
+ }
+
+#if debug
+ fprintf(stderr,"Reading encoding map file %s\n",filename);
+#endif
+
+ buffer=malloc(BUFFER_SIZE);
+ if (buffer==NULL) {
+ fprintf(stderr,"%s: Out of memory error.\n");
+ exit(1);
+ }
+
+ while (fgets(buffer, BUFFER_SIZE, mapfile)!=NULL) {
+ len=strlen(buffer);
+ if (buffer[len-1]!='\n') {
+ fprintf(stderr,"%s: Error: Line longer than %d in %s. %d\n",
+ BUFFER_SIZE,filename,(int)buffer[len]);
+ exit(1);
+ }
+
+ /* char *enc, *name, *f; */
+ enc=buffer;
+
+ while (enc[0]!='\0' && (enc[0]==' ' || enc[0]=='\t')) enc++;
+
+ /* % in first column is a correct comment */
+ if (enc[0]=='%' || enc[0]=='\0' || enc[0]=='\n')
+ continue;
+
+ enc=strtok(enc,delim);
+ name=strtok(NULL,delim);
+ f=strtok(NULL,delim);
+ i=new_encoding(enc,f);
+ fprintf(stderr,"Encoding[%d]: '%s' = '%s' -> '%s'\n", i,enc,name,f);
+ }
+
+ fclose(mapfile);
+
+ free(buffer);
+ free(filename);
+}
+
+
+PRIVATE void read_cfg_file P1C(char *,file)
+
+ /* Read config file. */
+
+{
+ char *filename;
+ FILE *mapfile;
+ int len;
+ char *keyword;
+ char *f;
+ char *buffer;
+ static const char delim[]="\t \n\r";
+
+ if (file==NULL)
+ file="xdvi.cfg";
+
+ filename=kpse_find_file(file,kpse_program_text_format,1);
+ if (filename==NULL) {
+ fprintf(stderr,"%s: Warning: unable to find %s\n",file);
+ return;
+ }
+
+ mapfile = fopen(filename,"r");
+
+ if (mapfile==NULL) {
+ fprintf(stderr,"%s: Error: Unable to open %s for reading: ",filename);
+ perror("");
+ exit(1);
+ }
+
+ fprintf(stderr,"Reading cfg file %s\n",filename);
+
+ buffer=malloc(BUFFER_SIZE);
+ if (buffer==NULL) {
+ fprintf(stderr,"%s: Out of memory error.\n");
+ exit(1);
+ }
+
+ while (fgets(buffer, BUFFER_SIZE, mapfile)!=NULL) {
+ len=strlen(buffer);
+ if (buffer[len-1]!='\n') {
+ fprintf(stderr, "%s: Error: Line longer than %d in %s. %d\n",
+ BUFFER_SIZE,filename,(int)buffer[len]);
+ exit(1);
+ }
+
+ keyword=buffer;
+
+ /* Skip leading whitespace */
+ while (keyword[0]!='\0' && (keyword[0]==' ' || keyword[0]=='\t'))
+ keyword++;
+
+ /* % in first column is a correct comment */
+ if (keyword[0]=='%' || keyword[0]=='\0' || keyword[0]=='\n')
+ continue;
+
+ keyword=strtok(keyword,delim);
+
+ if (strcmp(keyword,"dvipsmap")==0) {
+ f=strtok(NULL,delim);
+#if debug
+ fprintf(stderr,"DVIPSMAP: '%s'\n",f);
+#endif
+ if (!getpsinfo(f)) {
+ fprintf(stderr,"Could not load dvips map %s\n",f);
+ exit(1);
+ }
+ } else if (strcmp(keyword,"encmap")==0) {
+ f=strtok(NULL,delim);
+#if debug
+ fprintf(stderr,"Encoding map: '%s'\n",f);
+#endif
+ read_enc_map(f);
+ } else {
+ fprintf(stderr,"%s: Error: Unknown keyword: '%s' in %s\n",
+ keyword,filename);
+ exit(1);
+ }
+ }
+
+ fclose(mapfile);
+
+ free(buffer);
+ free(filename);
+
+ return;
+}
+
+
+/* **************************** GLYPH DRAWING *************************** */
+
+
+/* Set character# ch */
+
+#ifdef TEXXET
+PUBLIC void set_t1_char P2C(wide_ubyte, cmd, wide_ubyte, ch)
+#else
+PUBLIC long set_t1_char P1C(wide_ubyte, ch)
+#endif
+
+{
+ GC gc;
+ int xpos = PXL_H - currwin.base_x ;
+ /* + 1 here, seems t1lib and xdvi rounds the baseline differently */
+ int ypos = PXL_V - currwin.base_y + 1;
+ int t1libid;
+
+ /* Side by side comparison of cmr10 and ecrm1000 suggests that t1lib
+ renders the fonts a touch too large, and a factor of 0.96 was
+ arrived at as a reasonable correction for this.
+
+ Comparing the test file in gv at large sizes indicates that the
+ t1 cmr10 font is a hair taller than ecrm1000 also as seen by gv.
+ But, the size difference in xdvi was bigger.
+
+ Another related problem is that there are some gaps in math modes
+ tall braces '{', (see for example the amstex users guide). When
+ the factor is applied these gaps are more pronounced and there
+ are more of them, compared to when the factor is not applied.
+ The gaps does not show up in the fullsize window, and when the
+ 0.96 factor is not applied it only seems to show up in the main
+ window when the shrink factor is even.
+
+ Also, the size difference is in no way obvious unless you're
+ looking for it.
+
+ All in all the factor has been droped pending further experience
+ with t1 fonts in xdvi.
+
+ */
+
+ float size=
+ dvi_pt_conv(currinf.fontp->scale*(pixels_per_inch/size_devisor))/72.27;
+
+ int id=currinf.fontp->t1id;
+ int dvi_h_sav;
+
+ long gw ;
+
+ /* size=size*0.96; */
+
+ if (fontmaps[id].t1libid==-1)
+ load_font_now(id);
+
+ t1libid=fontmaps[id].t1libid;
+
+#if 0
+ fprintf(stderr,"Setting '%c' of %d, at %ld(%.2fpt), shrinkage is %d\n",
+ ch, t1libid, currinf.fontp->scale,
+ dvi_pt_fconv(currinf.fontp->scale),shrink_factor);
+#endif
+
+ if (fontmaps[id].tfmidx==-1)
+ /* Fallback when tfm data is missing. Not precise enough for
+ tables with vertical lines. */
+ gw = t1_dvi_conv(T1_GetCharWidth(t1libid, ch)*size)*
+ pixels_per_inch/72;
+ else
+ /* Use the widht from the tfm file */
+ gw = tfminfo[fontmaps[id].tfmidx].widths[ch] * currinf.fontp->dimconv;
+
+#ifdef HTEX
+ gc = HTeXreflevel > 0? highGC: foreGC;
+#else
+ gc = foreGC;
+#endif
+
+#ifdef TEXXET
+ dvi_h_sav = DVI_H;
+ if (currinf.dir < 0) DVI_H -= gw;
+
+ /* FIXME: There is something about scan_frame in set_char, I have no
+ idea what it does, and dvi-draw does not export it either. */
+#endif
+
+#ifdef GREY
+ if (use_grey && !(shrink_factor==1)) {
+ T1_AASetCharX(currwin.win, gc, T1_OPAQUE, xpos, ypos,
+ t1libid, ch, size/(double) shrink_factor, NULL);
+ } else
+#endif
+ {
+ T1_SetCharX(currwin.win, gc, T1_OPAQUE, xpos, ypos, t1libid,
+ ch, size/(double) shrink_factor, NULL);
+ }
+
+#ifndef TEXXET
+ return gw;
+#else
+# ifdef Omega
+ if ((cmd == PUT1) || (cmd == PUT2))
+# else
+ if (cmd == PUT1)
+# endif
+ DVI_H = dvi_h_sav;
+ else
+ if (currinf.dir > 0)
+ DVI_H += gw;
+#endif
+}
+
+
+PUBLIC void read_T1_char P2C(struct font *,fontp, ubyte, ch)
+
+{
+ /* Should never be called */
+ fprintf(stderr,"BUG: asked to load %c\n",ch);
+}
+
+
+PUBLIC void init_t1 P1C(void,)
+
+{
+ /* Initialize t1lib for drawing marks on screen */
+
+ if ((T1_InitLib(LOGFILE|
+ IGNORE_CONFIGFILE|
+ IGNORE_FONTDATABASE|
+ T1_NO_AFM)==NULL)) {
+ fprintf(stderr, "%s: Error: Initialization of t1lib failed\n");
+ exit(1);
+ }
+ T1_SetLogLevel(T1LOG_DEBUG);
+
+ T1_SetDeviceResolutions((float)pixels_per_inch,(float)pixels_per_inch);
+
+ /* Thanks to my wife for figuring this out. My mind was putty after
+ struggeling with too many kinds of units and factors for too
+ long: */
+ size_devisor=pixels_per_inch/75;
+
+ T1_SetX11Params(DISP, our_visual, our_depth, our_colormap);
+ /* T1_AA_LOW seems better than T1_AA_HIGH */
+ T1_AASetLevel(T1_AA_HIGH);
+ /* T1_AASetLevel(T1_AA_LOW);*/
+ T1_AASetBitsPerPixel(our_depth);
+
+ encodings=malloc(sizeof(*encodings)*ENCSTART);
+ fontmaps=malloc(sizeof(*fontmaps)*FNTMAPSTART);
+ t1fonts=malloc(sizeof(*t1fonts)*T1START);
+ tfminfo=malloc(sizeof(*tfminfo)*TEXWSTART);
+
+ if (encodings==NULL || fontmaps==NULL || t1fonts==NULL) {
+ fprintf(stderr,"%s: Error: No memory for datastructures.\n");
+ exit(1);
+ }
+
+ /* Malloc mem before reading config files! */
+ read_cfg_file(NULL);
+}
+
+#endif /* t1 */