]> www.fi.muni.cz Git - evince.git/blob - backend/dvi/mdvi-lib/t1.c
acbfa23eac7c45fd6019cd2b75166d22523d903b
[evince.git] / backend / dvi / mdvi-lib / t1.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 /* 
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 */