src/tfm.c
/* [<][>][^][v][top][bottom][index][help] */
FUNCTIONS
This source file includes following functions.
- RDS2PT
- vf_tfm_init
- vf_tfm_open
- vf_tfm_jfm_chartype
- vf_tfm_metric
- read_tfm
- vf_tfm_free
1 /*
2 * tfm.c - TFM files interface
3 *
4 * 28 Sep 1996
5 * 25 Mar 1997 Added setting a program name for kpathsea by variable.
6 * 02 Apr 1997 Added support for .ofm files (Omega metrics file) (WL)
7 * 3 Jul 1997 Added Virtual Font support.
8 * 8 Aug 1997 for VFlib 3.3
9 * 1 Feb 1998 for VFlib 3.4
10 */
11 /*
12 * Copyright (C) 1996-1998 by Hirotsugu Kakugawa.
13 * All rights reserved.
14 *
15 * This file is part of the VFlib Library. This library is free
16 * software; you can redistribute it and/or modify it under the terms of
17 * the GNU Library General Public License as published by the Free
18 * Software Foundation; either version 2 of the License, or (at your
19 * option) any later version. This library is distributed in the hope
20 * that it will be useful, but WITHOUT ANY WARRANTY; without even the
21 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
22 * PURPOSE. See the GNU Library General Public License for more details.
23 * You should have received a copy of the GNU Library General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #include "config.h"
29 #include "with.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #ifdef HAVE_UNISTD_H
35 # include <unistd.h>
36 #endif
37 #include "VFlib-3_6.h"
38 #include "VFsys.h"
39 #include "vflibcap.h"
40 #include "consts.h"
41 #include "metric.h"
42 #include "cache.h"
43 #include "sexp.h"
44 #include "texfonts.h"
45 #include "tfm.h"
46
47
48 #define RDS2PT(rds) (tfm->design_size * ((double)(rds)/(double)(1<<20)))
/* [<][>][^][v][top][bottom][index][help] */
49
50
51 Glocal SEXP_LIST vf_tex_tfm_fontdirs;
52 Glocal SEXP_LIST vf_tex_tfm_extensions;
53
54 Private VF_TABLE tfm_table = NULL;
55
56
57
58 Glocal int
59 vf_tfm_init(void)
/* [<][>][^][v][top][bottom][index][help] */
60 {
61 static int inited = 0;
62
63 if (inited == 0){
64 inited = 1;
65 if ((tfm_table = vf_table_create()) == NULL){
66 vf_error = VF_ERR_NO_MEMORY;
67 return -1;
68 }
69 }
70
71 return 0;
72 }
73
74
75 Private TFM read_tfm(FILE* fp);
76
77
78 Glocal TFM
79 vf_tfm_open(char *tfm_path)
/* [<][>][^][v][top][bottom][index][help] */
80 {
81 int tfm_id;
82 TFM tfm;
83 FILE *fp;
84
85 if ((tfm_id = (tfm_table->get_id_by_key)(tfm_table, tfm_path,
86 strlen(tfm_path)+1)) >= 0){
87 (tfm_table->link_by_id)(tfm_table, tfm_id);
88 return (tfm_table->get_obj_by_id)(tfm_table, tfm_id);
89 }
90
91 #if 0
92 printf("* TFM Open: %s\n", tfm_path);
93 #endif
94
95 if ((fp = vf_fm_OpenBinaryFileStream(tfm_path)) == NULL)
96 goto Error;
97
98 if ((tfm = read_tfm(fp)) == NULL)
99 goto Error;
100
101 if ((tfm_table->put)(tfm_table, tfm, tfm_path, strlen(tfm_path)+1) < 0)
102 return NULL;
103
104 return tfm;
105
106
107 Error:
108 vf_error = VF_ERR_NO_METRIC_FILE;
109 return NULL;
110 }
111
112
113
114
115 Glocal int
116 vf_tfm_jfm_chartype(TFM tfm, UINT4 code)
/* [<][>][^][v][top][bottom][index][help] */
117 {
118 int i;
119
120 tfm->ct_kcode[tfm->nt] = code;
121 i = 0;
122 while (tfm->ct_kcode[i] != code)
123 i++;
124 if (i == tfm->nt)
125 return 0;
126 return tfm->ct_ctype[i];
127 }
128
129
130 Glocal VF_METRIC1
131 vf_tfm_metric(TFM tfm, UINT4 code, VF_METRIC1 metric)
/* [<][>][^][v][top][bottom][index][help] */
132 {
133 int dir_h, index;
134 double w, h, d;
135
136 if (metric == NULL)
137 if ((metric = vf_alloc_metric1()) == NULL)
138 return NULL;
139
140 if ((tfm->type == METRIC_TYPE_TFM) || (tfm->type == METRIC_TYPE_OFM)){
141 dir_h = 1;
142 index = (int)code;
143 } else { /* == METRIC_TYPE_JFM */
144 dir_h = (tfm->type_aux == METRIC_TYPE_JFM_AUX_H) ? 1 : 0;
145 if (code == 0)
146 index = 0;
147 else
148 index = vf_tfm_jfm_chartype(tfm, code);
149 }
150 if ((index < tfm->begin_char) || (tfm->end_char < index)){
151 vf_error = VF_ERR_ILL_CODE_POINT;
152 return NULL;
153 }
154
155 w = RDS2PT(tfm->width[index - tfm->begin_char]);
156 h = RDS2PT(tfm->height[index - tfm->begin_char]);
157 d = RDS2PT(tfm->depth[index - tfm->begin_char]);
158 #if 0
159 printf("* %d: W=%f H=%f D=%f\n", index, w, h, d);
160 #endif
161
162 if (dir_h == 1){
163 metric->bbx_width = w;
164 metric->bbx_height = h + d;
165 metric->off_x = 0;
166 metric->off_y = h;
167 metric->mv_x = w;
168 metric->mv_y = 0;
169 } else {
170 metric->bbx_width = h + d;
171 metric->bbx_height = w;
172 metric->off_x = -d;
173 metric->off_y = 0;
174 metric->mv_x = 0;
175 metric->mv_y = -w;
176 }
177 return metric;
178 }
179
180
181 Private TFM
182 read_tfm(FILE* fp)
/* [<][>][^][v][top][bottom][index][help] */
183 {
184 TFM tfm;
185 UINT4 lf, lh, nc, nci, err;
186 UINT4 offset_header, offset_char_info, offset_param;
187 UINT4 nw, nh, nd, ni, nl, nk, neng, np, dir;
188 INT4 *w, *h, *d;
189 UINT4 *ci, v;
190 UINT4 i;
191 INT4 bbxw, bbxh, xoff, yoff;
192
193 ALLOC_IF_ERR(tfm, struct s_tfm){
194 vf_error = VF_ERR_NO_MEMORY;
195 return NULL;
196 }
197
198 tfm->width = NULL;
199 tfm->height = NULL;
200 tfm->depth = NULL;
201 tfm->ct_kcode = NULL;
202 tfm->ct_ctype = NULL;
203
204 tfm->font_bbx_w = 0.0;
205 tfm->font_bbx_h = 0.0;
206 tfm->font_bbx_xoff = 0.0;
207 tfm->font_bbx_yoff = 0.0;
208
209 err = 0;
210 rewind(fp);
211 lf = (UINT4)READ_UINT2(fp);
212 if ((lf == 11) || (lf == 9)){
213 /* JFM file of Japanese TeX by ASCII Coop. */
214 tfm->type = METRIC_TYPE_JFM;
215 tfm->type_aux = (lf == 11)?METRIC_TYPE_JFM_AUX_H:METRIC_TYPE_JFM_AUX_V;
216 tfm->nt = (UINT4)READ_UINT2(fp);
217 lf = (UINT4)READ_UINT2(fp);
218 lh = (UINT4)READ_UINT2(fp);
219 offset_header = 4*7;
220 offset_char_info = 4*(7+tfm->nt+lh);
221 } else if (lf == 0){
222 /* Omega Metric File */
223 tfm->type = METRIC_TYPE_OFM;
224 tfm->type_aux = READ_INT2(fp); /* ofm_level */
225 if ((tfm->type_aux < 0) || (1 < tfm->type_aux))
226 tfm->type_aux = 0; /* broken, maybe */
227 lf = READ_UINT4(fp);
228 lh = READ_UINT4(fp);
229 if (tfm->type_aux == 0){ /* level 0 OFM */
230 offset_header = 4*14;
231 offset_char_info = 4*(14+lh);
232 } else { /* level 1 OFM: *** NOT SUPPORTED YET *** */
233 offset_header = 4*29;
234 offset_char_info = 4*(29+lh);
235 }
236 } else {
237 /* Traditional TeX Metric File */
238 tfm->type = METRIC_TYPE_TFM;
239 tfm->type_aux = 0;
240 lh = (int)READ_UINT2(fp);
241 offset_header = 4*6;
242 offset_char_info = 4*(6+lh);
243 }
244
245 if (tfm->type == METRIC_TYPE_OFM){
246 tfm->begin_char = READ_UINT4(fp);
247 tfm->end_char = READ_UINT4(fp);
248 nw = READ_UINT4(fp);
249 nh = READ_UINT4(fp);
250 nd = READ_UINT4(fp);
251
252 ni = READ_UINT4(fp);
253 nl = READ_UINT4(fp);
254 nk = READ_UINT4(fp);
255 neng = READ_UINT4(fp);
256 np = READ_UINT4(fp);
257 dir = READ_UINT4(fp);
258
259 if (((signed)(tfm->begin_char-1) > (signed)tfm->end_char) ||
260 (tfm->end_char > 65535)){
261 vf_error = VF_ERR_INVALID_METRIC;
262 return NULL;
263 }
264 } else {
265 tfm->begin_char = (int)READ_UINT2(fp);
266 tfm->end_char = (int)READ_UINT2(fp);
267 nw = (UINT4)READ_UINT2(fp);
268 nh = (UINT4)READ_UINT2(fp);
269 nd = (UINT4)READ_UINT2(fp);
270
271 ni = (UINT4)READ_UINT2(fp);
272 nl = (UINT4)READ_UINT2(fp);
273 nk = (UINT4)READ_UINT2(fp);
274 neng = (UINT4)READ_UINT2(fp);
275 np = (UINT4)READ_UINT2(fp);
276
277 if (tfm->type == METRIC_TYPE_TFM){
278 if (((signed)(tfm->begin_char-1) > (signed)tfm->end_char) ||
279 (tfm->end_char > 255)){
280 vf_error = VF_ERR_INVALID_METRIC;
281 return NULL;
282 }
283 }
284 }
285
286 fseek(fp, offset_header, SEEK_SET);
287 tfm->cs = READ_UINT4(fp);
288 tfm->ds = READ_UINT4(fp);
289 tfm->design_size = (double)(tfm->ds)/(double)(1<<20);
290
291 nc = tfm->end_char - tfm->begin_char + 1;
292 nci = nc;
293 if (tfm->type == METRIC_TYPE_OFM)
294 nci *= 2;
295 ci = (UINT4*)calloc(nci, sizeof(UINT4));
296 w = (INT4*)calloc(nw, sizeof(UINT4));
297 h = (INT4*)calloc(nh, sizeof(UINT4));
298 d = (INT4*)calloc(nd, sizeof(UINT4));
299 if ((ci == NULL) || (w == NULL) || (h == NULL) || (d == NULL)){
300 err = VF_ERR_NO_MEMORY;
301 goto Exit;
302 }
303 fseek(fp, offset_char_info, SEEK_SET);
304 for (i = 0; i < nci; i++)
305 ci[i] = READ_UINT4(fp);
306 offset_param = ftell(fp) + 4*(nw + nh + nd + ni + nl + nk + neng);
307 for (i = 0; i < nw; i++)
308 w[i] = READ_INT4(fp);
309 for (i = 0; i < nh; i++)
310 h[i] = READ_INT4(fp);
311 for (i = 0; i < nd; i++)
312 d[i] = READ_INT4(fp);
313
314 tfm->width = (INT4*)calloc(nc, sizeof(INT4));
315 tfm->height = (INT4*)calloc(nc, sizeof(INT4));
316 tfm->depth = (INT4*)calloc(nc, sizeof(INT4));
317 if ((tfm->width == NULL) || (tfm->height == NULL) || (tfm->depth == NULL)){
318 err = VF_ERR_NO_MEMORY;
319 goto Exit;
320 }
321 bbxw = 0;
322 bbxh = 0;
323 xoff = 0;
324 yoff = 0;
325 if (tfm->type == METRIC_TYPE_OFM){
326 for (i = 0; i < nc; i++){
327 v = ci[2*i];
328 tfm->depth[i] = d[v & 0xff]; v >>= 8;
329 tfm->height[i] = h[v & 0xff]; v >>= 8;
330 tfm->width[i] = w[v & 0xffff];
331 if (bbxw < tfm->width[i])
332 bbxw = tfm->width[i];
333 if (bbxh < (tfm->height[i] + tfm->depth[i]))
334 bbxh = tfm->height[i] + tfm->depth[i];
335 if (yoff > -tfm->depth[i])
336 yoff = -tfm->depth[i];
337 #if 0
338 printf("** %.3f %.3f %.3f\n",
339 (double)tfm->width[i]/(double)(1<<20),
340 (double)tfm->height[i]/(double)(1<<20),
341 (double)tfm->depth[i]/(double)(1<<20));
342 #endif
343 }
344 } else {
345 for (i = 0; i < nc; i++){
346 v = ci[i] / 0x10000L;
347 tfm->depth[i] = d[v & 0xf]; v >>= 4;
348 tfm->height[i] = h[v & 0xf]; v >>= 4;
349 tfm->width[i] = w[v & 0xff];
350 if (bbxw < tfm->width[i])
351 bbxw = tfm->width[i];
352 if (bbxh < (tfm->height[i] + tfm->depth[i]))
353 bbxh = tfm->height[i] + tfm->depth[i];
354 if (yoff > -tfm->depth[i])
355 yoff = -tfm->depth[i];
356 #if 0
357 printf("** %.3f %.3f\n",
358 (double)tfm->height[i]/(double)(1<<20),
359 (double)tfm->depth[i]/(double)(1<<20));
360 #endif
361 }
362 }
363 tfm->font_bbx_w = tfm->design_size * ((double)bbxw / (double)(1<<20));
364 tfm->font_bbx_h = tfm->design_size * ((double)bbxh / (double)(1<<20));
365 tfm->font_bbx_xoff = tfm->design_size * ((double)xoff / (double)(1<<20));
366 tfm->font_bbx_yoff = tfm->design_size * ((double)yoff / (double)(1<<20));
367
368 if (tfm->type == METRIC_TYPE_JFM){
369 fseek(fp, 4*(7+lh), SEEK_SET);
370 tfm->ct_kcode = (unsigned int*)calloc(tfm->nt+1, sizeof(unsigned int));
371 tfm->ct_ctype = (unsigned int*)calloc(tfm->nt+1, sizeof(unsigned int));
372 if ((tfm->ct_kcode == NULL) || (tfm->ct_ctype == NULL)){
373 err = VF_ERR_NO_MEMORY;
374 goto Exit;
375 }
376 for (i = 0; i < tfm->nt; i++){
377 v = READ_UINT4(fp);
378 tfm->ct_kcode[i] = v/0x10000L;
379 tfm->ct_ctype[i] = v%0x10000L;
380 }
381 tfm->ct_kcode[tfm->nt] = 0; /* sentinel */
382 tfm->ct_ctype[tfm->nt] = 0;
383 }
384
385 fseek(fp, offset_param, SEEK_SET);
386 tfm->slant = (double)READ_INT4(fp)/(double)(1<<20);
387
388 Exit:
389 vf_free(ci);
390 vf_free(w);
391 vf_free(h);
392 vf_free(d);
393
394 if (err != 0){
395 vf_tfm_free(tfm);
396 vf_error = err;
397 return NULL;
398 }
399 return tfm;
400 }
401
402
403 Glocal void
404 vf_tfm_free(TFM tfm)
/* [<][>][^][v][top][bottom][index][help] */
405 {
406 int tfm_id;
407
408 if (tfm == NULL)
409 return;
410
411 tfm_id = (tfm_table->get_id_by_obj)(tfm_table, tfm);
412 if (tfm_id < 0)
413 return;
414
415 if ((tfm_table->unlink_by_id)(tfm_table, tfm_id) <= 0){
416 vf_free(tfm->width);
417 vf_free(tfm->height);
418 vf_free(tfm->depth);
419 vf_free(tfm->ct_kcode);
420 vf_free(tfm->ct_ctype);
421 vf_free(tfm);
422 }
423 }
424
425
426 /*EOF*/