Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
tfm.c
Go to the documentation of this file.
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 
33  "TFM",
34  0, /* scaling not supported by format */
39  NULL, /* free */
40  NULL, /* reset */
41  NULL, /* lookup */
42  kpse_tfm_format,
43  NULL
44 };
45 
47  "OFM",
48  0, /* scaling not supported by format */
53  NULL, /* free */
54  NULL, /* reset */
55  NULL, /* lookup */
56  kpse_ofm_format,
57  NULL
58 };
59 
61  "AFM",
62  0, /* scaling not supported by format */
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  */
212 
213  return 0;
214 }