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