]> www.fi.muni.cz Git - evince.git/blob - backend/dvi/mdvi-lib/tfm.c
3779c6b4a03ab222f0cb1f9c360e5125364509f4
[evince.git] / backend / dvi / mdvi-lib / tfm.c
1 /*
2  * Copyright (C) 2000, Matias Atria
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <string.h>
22 #include <sys/stat.h>
23 #include <unistd.h>
24
25 #include "mdvi.h"
26 #include "private.h"
27
28 static int tfm_load_font __PROTO((DviParams *, DviFont *));
29 static int tfm_font_get_glyph __PROTO((DviParams *, DviFont *, int));
30
31 DviFontInfo tfm_font_info = {
32         "TFM",
33         0, /* scaling not supported by format */
34         tfm_load_font,
35         tfm_font_get_glyph,
36         mdvi_shrink_box,
37         mdvi_shrink_box,
38         NULL,   /* free */
39         NULL,   /* reset */
40         NULL,   /* lookup */
41         kpse_tfm_format,
42         NULL
43 };
44
45 DviFontInfo ofm_font_info = {
46         "OFM",
47         0, /* scaling not supported by format */
48         tfm_load_font,
49         tfm_font_get_glyph,
50         mdvi_shrink_box,
51         mdvi_shrink_box,
52         NULL,   /* free */
53         NULL,   /* reset */
54         NULL,   /* lookup */
55         kpse_ofm_format,
56         NULL
57 };
58
59 DviFontInfo afm_font_info = {
60         "AFM",
61         0, /* scaling not supported by format */
62         tfm_load_font,
63         tfm_font_get_glyph,
64         mdvi_shrink_box,
65         mdvi_shrink_box,
66         NULL,   /* free */
67         NULL,   /* reset */
68         NULL,   /* lookup */
69         kpse_afm_format,
70         NULL
71 };
72
73 #define TYPENAME(font)  \
74         ((font)->search.info ? (font)->search.info : "none")
75
76 /* 
77  * Although it does not seem that way, this conversion is independent of the
78  * shrinking factors, within roundoff (that's because `conv' and `vconv'
79  * have already been scaled by hshrink and vshrink, repsectively). We
80  * should really use `dviconv' and `dvivconv', but I'm not so sure those
81  * should be moved to the DviParams structure.
82  */
83 #define XCONV(x)        FROUND(params->conv * (x) * params->hshrink)
84 #define YCONV(y)        FROUND(params->vconv * (y) * params->vshrink)
85
86 /* this is used quite often in several places, so I made it standalone */
87 int     get_tfm_chars(DviParams *params, DviFont *font, TFMInfo *info, int loaded)
88 {
89         Int32   z, alpha, beta;
90         int     n;
91         DviFontChar *ch;
92         TFMChar *ptr;
93         
94         n = info->hic - info->loc + 1;
95         if(n != FONT_GLYPH_COUNT(font)) {
96                 font->chars = mdvi_realloc(font->chars,
97                         n * sizeof(DviFontChar));
98         }
99         font->loc = info->loc;
100         font->hic = info->hic;  
101         ch = font->chars;
102         ptr = info->chars;
103
104         /* Prepare z, alpha and beta for TFM width computation */
105         TFMPREPARE(font->scale, z, alpha, beta);
106
107         /* get the character metrics */
108         for(n = info->loc; n <= info->hic; ch++, ptr++, n++) {
109                 int     a, b, c, d;
110
111                 ch->offset = ptr->present;
112                 if(ch->offset == 0)
113                         continue;
114                 /* this is what we came here for */
115                 ch->tfmwidth    = TFMSCALE(z, ptr->advance, alpha, beta);
116                 /* scale all other TFM units (so they are in DVI units) */
117                 a = TFMSCALE(z, ptr->left, alpha, beta);
118                 b = TFMSCALE(z, ptr->right, alpha, beta);
119                 c = TFMSCALE(z, ptr->height, alpha, beta);
120                 d = TFMSCALE(z, ptr->depth, alpha, beta);
121
122                 /* now convert to unscaled pixels */            
123                 ch->width = XCONV(b - a);
124                 ch->height = YCONV(c - d);
125                 if(ch->height < 0) ch->height = -ch->height;
126                 ch->x = XCONV(a);
127                 ch->y = YCONV(c);
128                 /*
129                  * the offset is not used, but we might as well set it to 
130                  * something meaningful (and it MUST be non-zero)
131                  */
132                 ch->flags       = 0;
133                 ch->code        = n;
134                 ch->glyph.data  = NULL;
135                 ch->grey.data   = NULL;
136                 ch->shrunk.data = NULL;
137                 ch->loaded      = loaded;
138         }
139
140         return 0;
141 }
142
143 /*
144  * We use this function as a last resort to find the character widths in a
145  * font The DVI rendering code can correctly skip over a glyph if it knows
146  * its TFM width, which is what we try to find here.
147  */
148 static int tfm_load_font(DviParams *params, DviFont *font)
149 {
150         TFMInfo *tfm;
151         int     type;
152
153         switch(font->search.info->kpse_type) {
154         case kpse_tfm_format:
155                 type = DviFontTFM;
156                 break;
157         case kpse_afm_format:
158                 type = DviFontAFM;
159                 break;
160         case kpse_ofm_format:
161                 type = DviFontOFM;
162                 break;
163         default:
164                 return -1;
165         }
166
167         /* we don't need this */
168         if(font->in) {
169                 fclose(font->in);
170                 font->in = NULL;
171         }
172         tfm = get_font_metrics(font->fontname, type, font->filename);
173         if(tfm == NULL)
174                 return -1;
175                         
176         if(tfm->checksum && font->checksum && tfm->checksum != font->checksum) {
177                 warning(_("%s: Checksum mismatch (got %u, expected %u)\n"),
178                         font->fontname, (unsigned)tfm->checksum, 
179                         (unsigned)font->checksum);
180         }
181         font->checksum = tfm->checksum;
182         font->design = tfm->design;
183         font->loc = 0;
184         font->hic = 0;
185         font->chars = NULL;
186         get_tfm_chars(params, font, tfm, 1);
187         
188         /* free everything */
189         free_font_metrics(tfm);
190         
191         return 0;
192 }
193
194 static int tfm_font_get_glyph(DviParams *params, DviFont *font, int code)
195 {
196         DviFontChar *ch;
197         
198         ch = FONTCHAR(font, code);
199         if(!glyph_present(ch))
200                 return -1;
201         ch->glyph.x = ch->x;
202         ch->glyph.y = ch->y;
203         ch->glyph.w = ch->width;
204         ch->glyph.h = ch->height;
205         /* 
206          * This has two purposes: (1) avoid unnecessary calls to this function,
207          * and (2) detect when the glyph data for a TFM font is actually used 
208          * (we'll get a SEGV). Any occurrence of that is a bug.
209          */
210         ch->glyph.data = MDVI_GLYPH_EMPTY;
211
212         return 0;
213 }