~ubuntu-branches/ubuntu/oneiric/evince/oneiric-updates

« back to all changes in this revision

Viewing changes to dvi/mdvi-lib/t1.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-01-10 19:35:11 UTC
  • mto: (1.3.1 experimental) (52.1.1 hardy-proposed)
  • mto: This revision was merged to the branch mainline in revision 20.
  • Revision ID: james.westby@ubuntu.com-20070110193511-yjrnndv8e8wv03yy
Tags: upstream-0.7.1
ImportĀ upstreamĀ versionĀ 0.7.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
/* 
20
 
 * Type1 font support for MDVI
21
 
 *
22
 
 * We use T1lib only as a rasterizer, not to draw glyphs.
23
 
 */
24
 
 
25
 
#include "mdvi.h"
26
 
 
27
 
#ifdef WITH_TYPE1_FONTS
28
 
 
29
 
#include <stdio.h>
30
 
#include <t1lib.h>
31
 
#include "private.h"
32
 
 
33
 
static int      t1lib_initialized = 0;
34
 
 
35
 
typedef struct t1info {
36
 
        struct t1info *next;
37
 
        struct t1info *prev;
38
 
        char    *fontname;      /* (short) name of this font */
39
 
        int     t1id;           /* T1lib's id for this font */  
40
 
        int     hasmetrics;     /* have we processed this font? */
41
 
        TFMInfo *tfminfo;       /* TFM data is shared */
42
 
        DviFontMapInfo mapinfo;
43
 
        DviEncoding *encoding;
44
 
} T1Info;
45
 
 
46
 
static void  t1_font_remove __PROTO((T1Info *));
47
 
static int   t1_load_font __PROTO((DviParams *, DviFont *));
48
 
static int   t1_font_get_glyph __PROTO((DviParams *, DviFont *, int));
49
 
static void  t1_font_shrink_glyph 
50
 
                __PROTO((DviContext *, DviFont *, DviFontChar *, DviGlyph *));
51
 
static void  t1_free_data __PROTO((DviFont *));
52
 
static void  t1_reset_font __PROTO((DviFont *));
53
 
static char *t1_lookup_font __PROTO((const char *, Ushort *, Ushort *));
54
 
 
55
 
/* only symbol exported by this file */
56
 
DviFontInfo t1_font_info = {
57
 
        "Type1",
58
 
        1, /* scaling supported by format */
59
 
        t1_load_font,
60
 
        t1_font_get_glyph,
61
 
        t1_font_shrink_glyph,
62
 
        mdvi_shrink_glyph_grey,
63
 
        t1_free_data,
64
 
        t1_reset_font,
65
 
        t1_lookup_font, /* lookup */
66
 
        kpse_type1_format,
67
 
        NULL
68
 
};
69
 
 
70
 
/* this seems good enough for most DVI files */
71
 
#define T1_HASH_SIZE    31
72
 
 
73
 
/* If these parameters change, we must delete all size information
74
 
 * in all fonts, and reset the device resolutions in T1lib */
75
 
static int t1lib_xdpi = -1;
76
 
static int t1lib_ydpi = -1;
77
 
 
78
 
static ListHead t1fonts = {NULL, NULL, 0};
79
 
static DviHashTable t1hash;
80
 
 
81
 
/* Type1 fonts need their own `lookup' function. Here is how it works: 
82
 
 * First we try to find the font by its given name. If that fails, we
83
 
 * query the font maps. A typical font map entry may contain the line
84
 
 * 
85
 
 * ptmr8rn Times-Roman ".82 ExtendFont TeXBase1Encoding ReEncodeFont" <8r.enc <ptmr
86
 
 *
87
 
 * which means: If you're looking for the font `ptmr8rn' load `Times-Roman'
88
 
 * which is in `ptmr' instead, and extend it by 0.82 points, then reencode
89
 
 * it with the vector TeXBase1Encoding from the file `8r.enc'. This will
90
 
 * fail if the entry looks like this:
91
 
 *
92
 
 * ptmr8rn Times-Roman ".82 ExtendFont TeXBase1Encoding ReEncodeFont" <8r.enc
93
 
 *
94
 
 * because to deal with this we would need to be able to locate the font file
95
 
 * for the `Times-Roman' font ourselves, and that's beyond the scope of mdvi.
96
 
 * But hey, we tried hard.
97
 
 */
98
 
char    *t1_lookup_font(const char *name, Ushort *hdpi, Ushort *vdpi)
99
 
{
100
 
        char    *filename;
101
 
        char    *newname;
102
 
        const char *ext;
103
 
        DviFontMapInfo info;
104
 
 
105
 
        DEBUG((DBG_TYPE1, "(t1) looking for `%s'\n", name));
106
 
 
107
 
        /* first let's try the font we were asked for */
108
 
        filename = kpse_find_file(name, kpse_type1_format, 1);
109
 
        if(filename != NULL) {
110
 
                /* we got it */
111
 
                return filename;
112
 
        }
113
 
 
114
 
        DEBUG((DBG_TYPE1, "(t1) %s: not found, querying font maps\n", name));   
115
 
        /* now query the fontmap */
116
 
        if(mdvi_query_fontmap(&info, name) < 0) {
117
 
                /* it's not there either */
118
 
                return NULL;
119
 
        }
120
 
        
121
 
        /* check what we got */
122
 
        if(info.fullfile) {
123
 
                DEBUG((DBG_TYPE1, "(t1) %s: found `%s' (cached)\n",
124
 
                        name, info.fullfile));
125
 
                /* this is a cached lookup */
126
 
                return mdvi_strdup(info.fullfile);
127
 
        }
128
 
        
129
 
        /* no file associated to this font? */
130
 
        if(info.fontfile == NULL)
131
 
                return info.psname ? mdvi_ps_find_font(info.psname) : NULL;
132
 
                
133
 
        /* let's extract the extension */
134
 
        ext = file_extension(info.fontfile);
135
 
        if(ext && !STREQ(ext, "pfa") && !STREQ(ext, "pfb")) {
136
 
                DEBUG((DBG_TYPE1, 
137
 
                        "(t1) %s: associated name `%s' is not Type1\n",
138
 
                        name, info.fontfile));
139
 
                /* it's not a Type1 font */
140
 
                return NULL;
141
 
        }
142
 
 
143
 
        /* get the `base' name */
144
 
        if(ext) {
145
 
                newname = mdvi_strdup(name);
146
 
                newname[ext - info.fontfile - 1] = 0;
147
 
        } else
148
 
                newname = (char *)name; /* we don't modify this */
149
 
 
150
 
        /* look it up */
151
 
        DEBUG((DBG_TYPE1, "(t1) looking for `%s' on behalf of `%s'\n",
152
 
                newname, name));
153
 
        filename = kpse_find_file(newname, kpse_type1_format, 1);
154
 
 
155
 
        /* we don't need this anymore */
156
 
        if(newname != name)
157
 
                mdvi_free(newname);
158
 
        if(filename == NULL) {
159
 
                DEBUG((DBG_TYPE1, "(t1) %s: not found\n", name));
160
 
                return NULL;
161
 
        }
162
 
        
163
 
        DEBUG((DBG_TYPE1, "(t1) %s: found as `%s'\n", name, filename));
164
 
        /* got it! let's remember this */
165
 
        mdvi_add_fontmap_file(name, filename);
166
 
        return filename;
167
 
}
168
 
 
169
 
static void t1_reset_resolution(int xdpi, int ydpi)
170
 
{
171
 
        int     i;
172
 
        int     nfonts;
173
 
 
174
 
        DEBUG((DBG_TYPE1, "(t1) resetting device resolution (current: (%d,%d))\n",
175
 
                t1lib_xdpi, t1lib_ydpi));
176
 
#if T1LIB_VERSION < 5
177
 
        nfonts = T1_Get_no_fonts();
178
 
#else
179
 
        nfonts = T1_GetNoFonts();
180
 
#endif  
181
 
 
182
 
        for(i = 0; i < nfonts; i++)
183
 
                T1_DeleteAllSizes(i);
184
 
        /* reset device resolutions */
185
 
        if(T1_SetDeviceResolutions((float)xdpi, (float)ydpi) < 0)
186
 
                warning(_("(t1) failed to reset device resolution\n"));
187
 
        else
188
 
                DEBUG((DBG_TYPE1, 
189
 
                        "(t1) reset successful, new resolution is (%d, %d)\n",
190
 
                        xdpi, ydpi));
191
 
        t1lib_xdpi = xdpi;
192
 
        t1lib_ydpi = ydpi;
193
 
}
194
 
 
195
 
static void t1_reset_font(DviFont *font)
196
 
{
197
 
        T1Info *info = (T1Info *)font->private;
198
 
        
199
 
        if(info == NULL)
200
 
                return;
201
 
        DEBUG((DBG_FONTS, "(t1) resetting font `%s'\n", font->fontname));
202
 
        /* just mark the font as not having metric info. It will be reset
203
 
         * automatically later */
204
 
        info->hasmetrics = 0;
205
 
}
206
 
 
207
 
static void t1_transform_font(T1Info *info)
208
 
{
209
 
        if(!info->hasmetrics && info->encoding != NULL) {
210
 
                DEBUG((DBG_TYPE1, "(t1) %s: encoding with vector `%s'\n",
211
 
                        info->fontname, info->encoding->name));
212
 
                T1_DeleteAllSizes(info->t1id);
213
 
                if(T1_ReencodeFont(info->t1id, info->encoding->vector) < 0)
214
 
                        warning(_("%s: could not encode font\n"), info->fontname);
215
 
        }
216
 
        if(info->mapinfo.slant) {
217
 
                DEBUG((DBG_TYPE1, "(t1) %s: slanting by %.3f\n", 
218
 
                        info->fontname,
219
 
                        MDVI_FMAP_SLANT(&info->mapinfo)));
220
 
                T1_SlantFont(info->t1id, 
221
 
                        MDVI_FMAP_SLANT(&info->mapinfo));
222
 
        }
223
 
        if(info->mapinfo.extend) {
224
 
                DEBUG((DBG_TYPE1, "(t1) %s: extending by %.3f\n",
225
 
                        info->fontname,
226
 
                        MDVI_FMAP_EXTEND(&info->mapinfo)));
227
 
                T1_ExtendFont(info->t1id, 
228
 
                        MDVI_FMAP_EXTEND(&info->mapinfo));
229
 
        }               
230
 
}
231
 
 
232
 
/* if this function is called, we really need this font */
233
 
static int t1_really_load_font(DviParams *params, DviFont *font, T1Info *info)
234
 
{
235
 
        int     i;
236
 
        T1Info  *old;
237
 
        int     t1id;
238
 
        int     copied;
239
 
        int     status;
240
 
 
241
 
        DEBUG((DBG_TYPE1, "(t1) really_load_font(%s)\n", info->fontname));
242
 
 
243
 
        /* if the parameters changed, reset T1lib */
244
 
        if(t1lib_xdpi != params->dpi || t1lib_ydpi != params->vdpi)
245
 
                t1_reset_resolution(params->dpi, params->vdpi);
246
 
 
247
 
        /* if we already have a T1lib id, do nothing */
248
 
        if(info->t1id != -1) {
249
 
                info->hasmetrics = 1;
250
 
                /* apply slant and extend again */
251
 
                t1_transform_font(info);
252
 
                return 0;
253
 
        }
254
 
 
255
 
        /* before we even attempt to load the font, make sure we have metric
256
 
         * data for it */
257
 
        info->tfminfo = mdvi_ps_get_metrics(info->fontname);
258
 
        if(info->tfminfo == NULL) {
259
 
                DEBUG((DBG_FONTS, 
260
 
                        "(t1) %s: no metric data, font ignored\n",
261
 
                        info->fontname));
262
 
                goto t1_error;
263
 
        }
264
 
        /* fix this */
265
 
        font->design = info->tfminfo->design;
266
 
 
267
 
        /* check if we have a font with this name (maybe at a different size) */
268
 
        old = (T1Info *)mdvi_hash_lookup(&t1hash, (unsigned char *)info->fontname);
269
 
        if(old == info) {
270
 
                /* let's avoid confusion */
271
 
                old = NULL;
272
 
        }
273
 
        if(old && old->t1id != -1) {
274
 
                /* let's take advantage of T1lib's font sharing */
275
 
                t1id = T1_CopyFont(old->t1id);
276
 
                DEBUG((DBG_TYPE1, "(t1) %s -> %d (CopyFont)\n", 
277
 
                        info->fontname, t1id));
278
 
                copied = 1;
279
 
        } else {
280
 
                t1id = T1_AddFont(font->filename);
281
 
                DEBUG((DBG_TYPE1, "(t1) %s -> %d (AddFont)\n",
282
 
                        info->fontname, t1id));
283
 
                copied = 0;
284
 
        }
285
 
        if(t1id < 0)
286
 
                goto t1_error;
287
 
        info->t1id = t1id;
288
 
 
289
 
        /* 
290
 
         * a minor optimization: If the old font in the hash table has
291
 
         * not been loaded yet, replace it by this one, so we can use
292
 
         * CopyFont later.
293
 
         */
294
 
        if(old && old->t1id == -1) {
295
 
                DEBUG((DBG_TYPE1, "(t1) font `%s' exchanged in hash table\n",
296
 
                        info->fontname));
297
 
                mdvi_hash_remove(&t1hash, (unsigned char *)old->fontname);
298
 
                mdvi_hash_add(&t1hash, (unsigned char *)info->fontname, 
299
 
                        info, MDVI_HASH_UNCHECKED);
300
 
        }
301
 
 
302
 
        /* now let T1lib load it */
303
 
        if(!copied && T1_LoadFont(info->t1id) < 0) {
304
 
                DEBUG((DBG_TYPE1, "(t1) T1_LoadFont(%d) failed with error %d\n",
305
 
                        info->t1id, T1_errno));
306
 
                goto t1_error;
307
 
        }
308
 
        DEBUG((DBG_TYPE1, "(t1) T1_LoadFont(%d) -> Ok\n", info->t1id));
309
 
 
310
 
        /* get information from the fontmap */
311
 
        status = mdvi_query_fontmap(&info->mapinfo, info->fontname);
312
 
        if(!status && info->mapinfo.encoding)
313
 
                info->encoding = mdvi_request_encoding(info->mapinfo.encoding);
314
 
        t1_transform_font(info);
315
 
 
316
 
        i = info->tfminfo->hic - info->tfminfo->loc + 1;
317
 
        if(i != font->hic - font->loc + 1) {
318
 
                /* reset to optimal size */
319
 
                font->chars = mdvi_realloc(font->chars, i * sizeof(DviFontChar));
320
 
        }
321
 
 
322
 
        /* get the scaled characters metrics */
323
 
        get_tfm_chars(params, font, info->tfminfo, 0);
324
 
        info->hasmetrics = 1;
325
 
        
326
 
        DEBUG((DBG_TYPE1, "(t1) font `%s' really-loaded\n", info->fontname));
327
 
        return 0;
328
 
 
329
 
t1_error:
330
 
        /* some error does not allows us to use this font. We need to reset
331
 
         * the font structure, so the font system can try to read this
332
 
         * font in a different class */
333
 
        
334
 
        /* first destroy the private data */
335
 
        t1_font_remove(info);
336
 
        /* now reset all chars -- this is the important part */
337
 
        mdvi_free(font->chars);
338
 
        font->chars = NULL;
339
 
        font->loc = font->hic = 0;
340
 
        return -1;
341
 
}
342
 
 
343
 
static int init_t1lib(DviParams *params)
344
 
{
345
 
        int     t1flags;
346
 
 
347
 
#ifdef WORD_LITTLE_ENDIAN
348
 
        /* try making T1lib use bitmaps in our format, but if this
349
 
         * fails we'll convert the bitmap ourselves */
350
 
        T1_SetBitmapPad(BITMAP_BITS);
351
 
#endif
352
 
        T1_SetDeviceResolutions((float)params->dpi, (float)params->vdpi);
353
 
        t1flags = IGNORE_CONFIGFILE|IGNORE_FONTDATABASE|T1_NO_AFM;
354
 
        if(DEBUGGING(TYPE1))
355
 
                t1flags |= LOGFILE;
356
 
        if(T1_InitLib(t1flags) == NULL)
357
 
                return (t1lib_initialized = -1);
358
 
        if(DEBUGGING(TYPE1)) {
359
 
                DEBUG((DBG_TYPE1, "T1lib debugging output saved in t1lib.log\n"));
360
 
                T1_SetLogLevel(T1LOG_DEBUG);
361
 
        }
362
 
        /* initialize our hash table, but don't allocate memory for it
363
 
         * until we use it */
364
 
        mdvi_hash_init(&t1hash);
365
 
        DEBUG((DBG_TYPE1, "(t1) t1lib %s initialized -- resolution is (%d, %d), pad is %d bits\n",
366
 
                T1_GetLibIdent(), params->dpi, params->vdpi, T1_GetBitmapPad()));
367
 
        t1lib_initialized = 1;  
368
 
        t1lib_xdpi = params->dpi;
369
 
        t1lib_ydpi = params->vdpi;
370
 
        return 0;
371
 
}
372
 
 
373
 
static int t1_load_font(DviParams *params, DviFont *font)
374
 
{
375
 
        T1Info  *info;
376
 
        int     i;
377
 
                                
378
 
        if(t1lib_initialized < 0)
379
 
                return -1;
380
 
        else if(t1lib_initialized == 0 && init_t1lib(params) < 0)
381
 
                return -1;
382
 
 
383
 
        if(font->in != NULL) {
384
 
                /* we don't need this */
385
 
                fclose(font->in);
386
 
                font->in = NULL;
387
 
        }
388
 
 
389
 
        info = xalloc(T1Info);
390
 
 
391
 
        /* 
392
 
         * mark the font as `unregistered' with T1lib. It will
393
 
         * be added when we actually use it
394
 
         */
395
 
        info->t1id = -1;
396
 
 
397
 
        /* add the font to our list */
398
 
        info->fontname = font->fontname;
399
 
        info->hasmetrics = 0;
400
 
        info->encoding = NULL;
401
 
        info->mapinfo.psname = NULL;
402
 
        info->mapinfo.encoding = NULL;
403
 
        info->mapinfo.fontfile = NULL;
404
 
        info->mapinfo.extend = 0;
405
 
        info->mapinfo.slant = 0;
406
 
        info->encoding = NULL;
407
 
        
408
 
        /* create the hash table if we have not done so yet */
409
 
        if(t1hash.nbucks == 0)
410
 
                mdvi_hash_create(&t1hash, T1_HASH_SIZE);
411
 
        mdvi_hash_add(&t1hash, (unsigned char *) info->fontname, info, MDVI_HASH_UNIQUE);               
412
 
        listh_append(&t1fonts, LIST(info));
413
 
 
414
 
        font->private = info;
415
 
                
416
 
        /* reset everything */
417
 
        font->chars = xnalloc(DviFontChar, 256);
418
 
        font->loc = 0;
419
 
        font->hic = 255;
420
 
        for(i = 0; i < 256; i++) {
421
 
                font->chars[i].code = i;
422
 
                font->chars[i].offset = 1;
423
 
                font->chars[i].loaded = 0;
424
 
                font->chars[i].glyph.data = NULL;
425
 
                font->chars[i].shrunk.data = NULL;
426
 
                font->chars[i].grey.data = NULL;
427
 
        }
428
 
        
429
 
        return 0;
430
 
}
431
 
 
432
 
#define GLYPH_WIDTH(g) \
433
 
        ((g)->metrics.rightSideBearing - (g)->metrics.leftSideBearing)
434
 
#define GLYPH_HEIGHT(g) \
435
 
        ((g)->metrics.ascent - (g)->metrics.descent)
436
 
 
437
 
static inline BITMAP *t1_glyph_bitmap(GLYPH *glyph)
438
 
{
439
 
        BITMAP  *bm;
440
 
        int     w, h;
441
 
        
442
 
        w = GLYPH_WIDTH(glyph);
443
 
        h = GLYPH_HEIGHT(glyph);
444
 
 
445
 
        if(!w || !h)
446
 
                return MDVI_GLYPH_EMPTY;
447
 
        switch(glyph->bpp << 3) {
448
 
                case 8: 
449
 
                        bm = bitmap_convert_lsb8((unsigned char *)glyph->bits, w, h);
450
 
                        break;
451
 
                default:
452
 
                        warning(_("(t1) unsupported bitmap pad size %d\n"),
453
 
                                glyph->bpp);
454
 
                        bm = MDVI_GLYPH_EMPTY;
455
 
                        break;
456
 
        }
457
 
        return bm;
458
 
}
459
 
 
460
 
static void t1_font_shrink_glyph(DviContext *dvi, DviFont *font, DviFontChar *ch, DviGlyph *dest)
461
 
{
462
 
        double  size;
463
 
        GLYPH   *glyph;
464
 
        T1Info  *info;
465
 
        T1_TMATRIX matrix;
466
 
        
467
 
        info = (T1Info *)font->private;
468
 
        ASSERT(info != NULL);
469
 
 
470
 
        DEBUG((DBG_TYPE1, "(t1) shrinking glyph for character %d in `%s' (%d,%d)\n",
471
 
                ch->code, font->fontname, ch->width, ch->height));      
472
 
        size = (double)font->scale / (dvi->params.tfm_conv * 0x100000);
473
 
        size = 72.0 * size / 72.27;
474
 
        matrix.cxx = 1.0/(double)dvi->params.hshrink;
475
 
        matrix.cyy = 1.0/(double)dvi->params.vshrink;
476
 
        matrix.cxy = 0.0;
477
 
        matrix.cyx = 0.0;
478
 
        glyph = T1_SetChar(info->t1id, ch->code, (float)size, &matrix);
479
 
 
480
 
        dest->data = t1_glyph_bitmap(glyph);
481
 
        dest->x = -glyph->metrics.leftSideBearing;
482
 
        dest->y = glyph->metrics.ascent;
483
 
        dest->w = GLYPH_WIDTH(glyph);
484
 
        dest->h = GLYPH_HEIGHT(glyph);
485
 
 
486
 
#ifndef NODEBUG
487
 
        if(DEBUGGING(BITMAP_DATA)) {
488
 
                DEBUG((DBG_BITMAP_DATA, 
489
 
                        "(t1) %s: t1_shrink_glyph(%d): (%dw,%dh,%dx,%dy) -> (%dw,%dh,%dx,%dy)\n",
490
 
                        ch->glyph.w, ch->glyph.h, ch->glyph.x, ch->glyph.y,
491
 
                        dest->w, dest->h, dest->x, dest->y));
492
 
                bitmap_print(stderr, (BITMAP *)dest->data);
493
 
        }
494
 
#endif
495
 
        /* transform the glyph - we could do this with t1lib, but we do
496
 
         * it ourselves for now */
497
 
        font_transform_glyph(dvi->params.orientation, dest);
498
 
}
499
 
 
500
 
static int t1_font_get_glyph(DviParams *params, DviFont *font, int code)
501
 
{
502
 
        T1Info  *info = (T1Info *)font->private;
503
 
        GLYPH   *glyph;
504
 
        DviFontChar *ch;
505
 
        double  size;
506
 
        T1_TMATRIX matrix;
507
 
        int     dpi;
508
 
        
509
 
        ASSERT(info != NULL);
510
 
        if(!info->hasmetrics && t1_really_load_font(params, font, info) < 0)
511
 
                return -1;
512
 
        ch = FONTCHAR(font, code);      
513
 
        if(!ch || !glyph_present(ch))
514
 
                return -1;
515
 
        ch->loaded = 1;
516
 
        if(!ch->width || !ch->height) {
517
 
                ch->glyph.x = ch->x;
518
 
                ch->glyph.y = ch->y;
519
 
                ch->glyph.w = ch->width;
520
 
                ch->glyph.h = ch->height;
521
 
                ch->glyph.data = NULL;
522
 
                return 0;
523
 
        }
524
 
 
525
 
        /* load the glyph with T1lib (this is done only once for each glyph) */
526
 
 
527
 
        /* get size in TeX points (tfm_conv includes dpi and magnification) */
528
 
        size = (double)font->scale / (params->tfm_conv * 0x100000);
529
 
        /* and transform into PostScript points */
530
 
        size = 72.0 * size / 72.27;
531
 
 
532
 
        dpi = Max(font->hdpi, font->vdpi);
533
 
        /* we don't want the glyph to be cached twice (once by us, another by 
534
 
         * T1lib), so we use an identity matrix to tell T1lib not to keep the
535
 
         * glyph around */
536
 
        matrix.cxx = (double)font->hdpi / dpi;
537
 
        matrix.cyy = (double)font->vdpi / dpi;
538
 
        matrix.cxy = matrix.cyx = 0.0;
539
 
        glyph = T1_SetChar(info->t1id, ch->code, (float)size, &matrix);
540
 
        if(glyph == NULL) {
541
 
                ch->glyph.x = ch->x;
542
 
                ch->glyph.y = ch->y;
543
 
                ch->glyph.w = ch->width;
544
 
                ch->glyph.h = ch->height;
545
 
                ch->glyph.data = NULL;
546
 
                ch->missing = 1;
547
 
                return 0;
548
 
        }
549
 
        /* and make it a bitmap */
550
 
        ch->glyph.data = t1_glyph_bitmap(glyph);
551
 
        ch->glyph.x = -glyph->metrics.leftSideBearing;
552
 
        ch->glyph.y = glyph->metrics.ascent;
553
 
        ch->glyph.w = GLYPH_WIDTH(glyph);
554
 
        ch->glyph.h = GLYPH_HEIGHT(glyph);
555
 
 
556
 
        /* let's also fix the glyph's origin 
557
 
         * (which is not contained in the TFM) */
558
 
        ch->x = ch->glyph.x;
559
 
        ch->y = ch->glyph.y;
560
 
        /* let's fix these too */
561
 
        ch->width = ch->glyph.w;
562
 
        ch->height = ch->glyph.h;
563
 
                
564
 
        return 0;
565
 
}
566
 
 
567
 
static void t1_font_remove(T1Info *info)
568
 
{
569
 
        T1Info  *old;
570
 
        
571
 
        /* first remove it from our list */
572
 
        listh_remove(&t1fonts, LIST(info));
573
 
 
574
 
        /* it it's in the hash table, we may need to replace this by another font */
575
 
        old = (T1Info *)mdvi_hash_lookup(&t1hash, (unsigned char *)info->fontname);
576
 
        if(old == info) {
577
 
                mdvi_hash_remove(&t1hash, (unsigned char *) info->fontname);
578
 
                /* go through the list and see if there is another 
579
 
                 * font with this name */
580
 
                for(old = (T1Info *)t1fonts.head; old; old = old->next)
581
 
                        if(STREQ(old->fontname, info->fontname))
582
 
                                break;
583
 
                if(old != NULL)
584
 
                        mdvi_hash_add(&t1hash, (unsigned char *) old->fontname, old, 
585
 
                                MDVI_HASH_UNCHECKED);
586
 
        }
587
 
        /* release our encoding vector */
588
 
        if(info->encoding) {
589
 
                DEBUG((DBG_TYPE1, "(t1) %s: releasing vector `%s'\n",
590
 
                        info->fontname, info->encoding->name));
591
 
                mdvi_release_encoding(info->encoding, 1);
592
 
        }
593
 
 
594
 
        /* now get rid of it */
595
 
        if(info->t1id != -1) {
596
 
                DEBUG((DBG_TYPE1, "(t1) %s: T1_DeleteFont(%d)\n",
597
 
                        info->fontname, info->t1id));
598
 
                T1_DeleteFont(info->t1id);
599
 
        } else
600
 
                DEBUG((DBG_TYPE1, "(t1) %s: not loaded yet, DeleteFont skipped\n",
601
 
                        info->fontname));
602
 
 
603
 
        if(info->tfminfo)
604
 
                free_font_metrics(info->tfminfo);
605
 
        /*mdvi_free(info->fontname);*/
606
 
        mdvi_free(info);
607
 
}
608
 
 
609
 
static void t1_free_data(DviFont *font)
610
 
{
611
 
        /* called after all the glyphs are destroyed */
612
 
 
613
 
        if(font->private == NULL) {
614
 
                /* this is perfectly normal, it just means the font has 
615
 
                 * not been requested by MDVI yet */
616
 
                return;
617
 
        }
618
 
        
619
 
        /* destroy this data */
620
 
 
621
 
        t1_font_remove((T1Info *)font->private);
622
 
        font->private = NULL;
623
 
 
624
 
        /* 
625
 
         * if this is the last T1 font, reset the T1 library
626
 
         * It is important that we do this, because this is will be called
627
 
         * when the resolution or the magnification changes.
628
 
         */
629
 
        if(t1fonts.count == 0) {
630
 
                DEBUG((DBG_TYPE1, "(t1) last font removed -- closing T1lib\n"));
631
 
                T1_CloseLib();
632
 
                t1lib_initialized = 0;
633
 
                t1lib_xdpi = -1;
634
 
                t1lib_ydpi = -1;
635
 
        }
636
 
}
637
 
 
638
 
#endif /* WITH_TYPE1_FONTS */