File: | backend/dvi/mdvi-lib/tfm.c |
Warning: | line 211, column 17 Using a fixed address is not portable because that address will probably not be valid in all environments or platforms |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 *))(DviParams *, DviFont *); | |||
30 | static int tfm_font_get_glyph __PROTO((DviParams *, DviFont *, int))(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((void*)0), /* free */ | |||
40 | NULL((void*)0), /* reset */ | |||
41 | NULL((void*)0), /* lookup */ | |||
42 | kpse_tfm_format, | |||
43 | NULL((void*)0) | |||
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((void*)0), /* free */ | |||
54 | NULL((void*)0), /* reset */ | |||
55 | NULL((void*)0), /* lookup */ | |||
56 | kpse_ofm_format, | |||
57 | NULL((void*)0) | |||
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((void*)0), /* free */ | |||
68 | NULL((void*)0), /* reset */ | |||
69 | NULL((void*)0), /* lookup */ | |||
70 | kpse_afm_format, | |||
71 | NULL((void*)0) | |||
72 | }; | |||
73 | ||||
74 | #define TYPENAME(font)((font)->search.info ? (font)->search.info : "none") \ | |||
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)(int)((params->conv * (x) * params->hshrink) + 0.5) FROUND(params->conv * (x) * params->hshrink)(int)((params->conv * (x) * params->hshrink) + 0.5) | |||
85 | #define YCONV(y)(int)((params->vconv * (y) * params->vshrink) + 0.5) FROUND(params->vconv * (y) * params->vshrink)(int)((params->vconv * (y) * params->vshrink) + 0.5) | |||
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)((font)->hic - (font)->loc + 1)) { | |||
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)do { alpha = 16; z = (font->scale); while(z > 040000000L ) { z >>= 1; alpha <<= 1; } beta = 256 / alpha; alpha *= z; } while(0); | |||
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)(((((ptr->advance) >> 24) & 0xff) == 255) ? (((( ((((ptr->advance)) & 0xff) * ((z))) >> 8) + (((( (ptr->advance)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->advance)) >> 16) & 0xff) * ((z))) / (beta) - (alpha) : ((((((((ptr->advance)) & 0xff) * ((z))) >> 8) + (((((ptr->advance)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->advance)) >> 16) & 0xff) * ((z))) / (beta)); | |||
117 | /* scale all other TFM units (so they are in DVI units) */ | |||
118 | a = TFMSCALE(z, ptr->left, alpha, beta)(((((ptr->left) >> 24) & 0xff) == 255) ? ((((((( (ptr->left)) & 0xff) * ((z))) >> 8) + (((((ptr-> left)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr ->left)) >> 16) & 0xff) * ((z))) / (beta) - (alpha ) : ((((((((ptr->left)) & 0xff) * ((z))) >> 8) + (((((ptr->left)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->left)) >> 16) & 0xff) * ((z))) / ( beta)); | |||
119 | b = TFMSCALE(z, ptr->right, alpha, beta)(((((ptr->right) >> 24) & 0xff) == 255) ? (((((( ((ptr->right)) & 0xff) * ((z))) >> 8) + (((((ptr ->right)) >> 8) & 0xff) * ((z)))) >> 8) + ( (((ptr->right)) >> 16) & 0xff) * ((z))) / (beta) - (alpha) : ((((((((ptr->right)) & 0xff) * ((z))) >> 8) + (((((ptr->right)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->right)) >> 16) & 0xff) * ((z))) / (beta)); | |||
120 | c = TFMSCALE(z, ptr->height, alpha, beta)(((((ptr->height) >> 24) & 0xff) == 255) ? ((((( (((ptr->height)) & 0xff) * ((z))) >> 8) + (((((ptr ->height)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->height)) >> 16) & 0xff) * ((z))) / (beta ) - (alpha) : ((((((((ptr->height)) & 0xff) * ((z))) >> 8) + (((((ptr->height)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->height)) >> 16) & 0xff) * ((z))) / (beta)); | |||
121 | d = TFMSCALE(z, ptr->depth, alpha, beta)(((((ptr->depth) >> 24) & 0xff) == 255) ? (((((( ((ptr->depth)) & 0xff) * ((z))) >> 8) + (((((ptr ->depth)) >> 8) & 0xff) * ((z)))) >> 8) + ( (((ptr->depth)) >> 16) & 0xff) * ((z))) / (beta) - (alpha) : ((((((((ptr->depth)) & 0xff) * ((z))) >> 8) + (((((ptr->depth)) >> 8) & 0xff) * ((z)))) >> 8) + ((((ptr->depth)) >> 16) & 0xff) * ((z))) / (beta)); | |||
122 | ||||
123 | /* now convert to unscaled pixels */ | |||
124 | ch->width = XCONV(b - a)(int)((params->conv * (b - a) * params->hshrink) + 0.5); | |||
125 | ch->height = YCONV(c - d)(int)((params->vconv * (c - d) * params->vshrink) + 0.5 ); | |||
126 | if(ch->height < 0) ch->height = -ch->height; | |||
127 | ch->x = XCONV(a)(int)((params->conv * (a) * params->hshrink) + 0.5); | |||
128 | ch->y = YCONV(c)(int)((params->vconv * (c) * params->vshrink) + 0.5); | |||
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((void*)0); | |||
136 | ch->grey.data = NULL((void*)0); | |||
137 | ch->shrunk.data = NULL((void*)0); | |||
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 | fclosekpse_fclose_trace(font->in); | |||
171 | font->in = NULL((void*)0); | |||
172 | } | |||
173 | tfm = get_font_metrics(font->fontname, type, font->filename); | |||
174 | if(tfm == NULL((void*)0)) | |||
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")gettext("%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((void*)0); | |||
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)(((code) < font->loc || (code) > font->hic || !(font )->chars) ? ((void*)0) : &font->chars[(code) - (font )->loc]); | |||
| ||||
200 | if(!glyph_present(ch)((ch) && (ch)->offset)) | |||
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((void *)1); | |||
| ||||
212 | ||||
213 | return 0; | |||
214 | } |