1 /*--------------------------------------------------------------------------
2 ----- File: t1load.c
3 ----- Author: Rainer Menzner (Rainer.Menzner@web.de)
4 ----- Date: 2007-12-23
5 ----- Description: This file is part of the t1-library. It contains
6 functions for loading fonts and for managing size
7 dependent data.
8 ----- Copyright: t1lib is copyrighted (c) Rainer Menzner, 1996-2007.
9 As of version 0.5, t1lib is distributed under the
10 GNU General Public Library Lincense. The
11 conditions can be found in the files LICENSE and
12 LGPL, which should reside in the toplevel
13 directory of the distribution. Please note that
14 there are parts of t1lib that are subject to
15 other licenses:
16 The parseAFM-package is copyrighted by Adobe Systems
17 Inc.
18 The type1 rasterizer is copyrighted by IBM and the
19 X11-consortium.
20 ----- Warranties: Of course, there's NO WARRANTY OF ANY KIND :-)
21 ----- Credits: I want to thank IBM and the X11-consortium for making
22 their rasterizer freely available.
23 Also thanks to Piet Tutelaers for his ps2pk, from
24 which I took the rasterizer sources in a format
25 independent from X11.
26 Thanks to all people who make free software living!
27 --------------------------------------------------------------------------*/
28
29 #define T1LOAD_C
30
31 #define ANSI_REALLOC_VM
32
33 /* Note: On some systems, like e.g. my Linux box, realloc() frequently returns
34 the identical pointer, if the memory chunk is *decreased* in size. As
35 a consequence, pointer shifting (as implemented below) would never
36 actually appear. The following definition enforces pointer shifting,
37 and hence allows to check pointer shifting on every system. Do not
38 activate this, it is meant for testing only!
39 */
40 /* #define ANSI_REALLOC_ENFORCE_POINTERSHIFTING */
41
42 #include <stdio.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #if defined(_MSC_VER)
47 # include <io.h>
48 # include <sys/types.h>
49 # include <sys/stat.h>
50 #else
51 # include <unistd.h>
52 #endif
53 #include <stdlib.h>
54 #include <math.h>
55 #include <string.h>
56
57 #include "../type1/ffilest.h"
58 #include "../type1/types.h"
59 #include "parseAFM.h"
60 #include "../type1/objects.h"
61 #include "../type1/spaces.h"
62 #include "../type1/util.h"
63 #include "../type1/fontfcn.h"
64 #include "../type1/blues.h"
65 #include "../type1/paths.h"
66 #include "../type1/regions.h"
67
68
69 #include "t1types.h"
70 #include "t1extern.h"
71 #include "t1load.h"
72 #include "t1env.h"
73 #include "t1set.h"
74 #include "t1base.h"
75 #include "t1finfo.h"
76 #include "t1afmtool.h"
77
78
79
80 extern psobj *StdEncArrayP; /* For checking of a fonts encoding */
81 extern char not_def[]; /* for checking the ".notdef"-string */
82
83
84
85 /* T1_LoadFont(FontID): Loads a Type1 font into memory and allocates all
86 memory, necessary for this. */
87
T1_LoadFont(int FontID)88 int T1_LoadFont( int FontID)
89 {
90 int i, j, k, l, m, n;
91 char *FileName, *FileNamePath;
92 int mode; /* This is used by the type1-library for error reporting */
93 char *charname;
94
95 /* The following vars are used for reallocation of VM */
96 long tmp_size;
97 float ascender;
98 #ifdef ANSI_REALLOC_VM
99 unsigned long shift;
100 unsigned long ldummy;
101 char *tmp_ptr;
102 #endif
103
104 struct region *area;
105 struct XYspace *S;
106
107 /* These are for constructing the kerning lookup table: */
108 PairKernData *pkd;
109 METRICS_ENTRY *kern_tbl;
110 int char1, char2;
111
112
113 if (T1_CheckForInit()){
114 T1_errno=T1ERR_OP_NOT_PERMITTED;
115 return(-1);
116 }
117
118
119 i=T1_CheckForFontID(FontID);
120 if (i==1)
121 return(0); /* Font already loaded */
122 if (i==-1){
123 T1_errno=T1ERR_INVALID_FONTID;
124 return(-1); /* illegal FontID */
125 }
126
127 /* Allocate memory for ps_font structure: */
128 if ((pFontBase->pFontArray[FontID].pType1Data=(psfont *)malloc(sizeof(psfont)))==NULL){
129 T1_PrintLog( "T1_LoadFont()", "Failed to allocate memory for psfont-struct (FontID=%d)",
130 T1LOG_ERROR, FontID);
131 T1_errno=T1ERR_ALLOC_MEM;
132 return(-1);
133 }
134
135 /* Check for valid filename */
136 if ((FileName=T1_GetFontFileName(FontID))==NULL){
137 T1_PrintLog( "T1_LoadFont()", "No font file name for font %d", T1LOG_ERROR, FontID);
138 return(-1);
139 }
140
141 /* Fetch the full path of type1 font file */
142 if ((FileNamePath=intT1_Env_GetCompletePath( FileName,
143 T1_PFAB_ptr))==NULL){
144 T1_PrintLog( "T1_LoadFont()", "Couldn't locate font file for font %d in %s",
145 T1LOG_ERROR, FontID, T1_GetFileSearchPath(T1_PFAB_PATH));
146 T1_errno=T1ERR_FILE_OPEN_ERR;
147 return(-1);
148 }
149
150 /* And load all PostScript information into memory */
151 if (fontfcnA( FileNamePath, &mode,
152 pFontBase->pFontArray[FontID].pType1Data) == FALSE){
153 T1_PrintLog( "T1_LoadFont()", "Loading font with ID = %d failed! (mode = %d)",
154 T1LOG_ERROR, FontID, mode);
155 free(FileNamePath);
156 pFontBase->pFontArray[FontID].pType1Data=NULL;
157 T1_errno=mode;
158 return(-1);
159 }
160 free(FileNamePath);
161
162
163 /* Set some default for FontBBox and Encoding if the font does not provide
164 correct data. Strictly taken, these fonts do not adhere to the Type1
165 specification. However, it is easy to work around and find reasonable
166 defaults. This solution has been proposed by the Debian community (see
167 http://bugs.debian.org/313236). */
168 /* 1. FontBBox. We set default values of 0 which is recommended by Adobe
169 in cases where the font does not make use of the SEAC primitive. Later on,
170 if AFM fallback info is computed, these settings might be overwritten with
171 meaningful values. */
172 if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP == NULL) {
173 if ((pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP =
174 (psobj *)vm_alloc(4 * sizeof(psobj))) == NULL) {
175 T1_PrintLog( "T1_LoadFont()", "Error allocating memory for fontbbox objects (FontID=%d)",
176 T1LOG_ERROR, FontID);
177 T1_errno=T1ERR_ALLOC_MEM;
178 return(-1);
179 }
180 for (n = 0; n < 4; n++) {
181 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP[n].type = OBJ_INTEGER;
182 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP[n].len = 0;
183 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTBBOX].value.data.arrayP[n].data.integer = 0;
184 }
185 T1_PrintLog( "T1_LoadFont()", "Missing FontBBox, adding a trivial one in order to avoid crashes (FontID=%d)",
186 T1LOG_WARNING, FontID);
187 }
188 /* 2. Encoding. In this case, we simply fallback to Standard Encoding. */
189 if (pFontBase->pFontArray[FontID].pFontEnc == NULL &&
190 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP == NULL) {
191 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.valueP = (char *) StdEncArrayP;
192 T1_PrintLog( "T1_LoadFont()", "Missing, invalid or undefined Encoding, setting up Standard Encoding in order to avoid crashes (FontID=%d)",
193 T1LOG_WARNING, FontID);
194 }
195
196
197 /* Store the base address of virtual memory and realloc in order not
198 to waste too much memory: */
199 pFontBase->pFontArray[FontID].vm_base=vm_base;
200 #ifdef ANSI_REALLOC_VM
201 /* We first get the size of pointers on the current system */
202 /* Get size of VM, ... */
203 tmp_size=((unsigned long)vm_used - (unsigned long)vm_base);
204 /* ... realloc to that size ... */
205 #ifdef ANSI_REALLOC_ENFORCE_POINTERSHIFTING
206 tmp_ptr=(char *)malloc( tmp_size);
207 memcpy( tmp_ptr, vm_base, tmp_size);
208 #else
209 tmp_ptr=(char *)realloc(vm_base, tmp_size);
210 #endif
211 /* ... and shift all pointers refering to that area */
212 if (tmp_ptr > vm_base){
213 shift= (unsigned long)tmp_ptr - (unsigned long)vm_base;
214 sprintf( err_warn_msg_buf,
215 "Old VM at 0x%lX, new VM at 0x%lX, shifting up by %lu",
216 (unsigned long)vm_base, (unsigned long)tmp_ptr, tmp_size);
217 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
218
219 /* We start by shifting the topmost pointers: */
220 pFontBase->pFontArray[FontID].vm_base=tmp_ptr;
221
222 ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->vm_start);
223 ldummy +=shift;
224 pFontBase->pFontArray[FontID].pType1Data->vm_start=(char *)ldummy;
225
226 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP;
227 ldummy +=shift;
228 pFontBase->pFontArray[FontID].pType1Data->CharStringsP=(psdict *)ldummy;
229
230 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private;
231 ldummy +=shift;
232 pFontBase->pFontArray[FontID].pType1Data->Private=(psdict *)ldummy;
233
234 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP;
235 ldummy +=shift;
236 pFontBase->pFontArray[FontID].pType1Data->fontInfoP=(psdict *)ldummy;
237
238 ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->BluesP);
239 ldummy +=shift;
240 pFontBase->pFontArray[FontID].pType1Data->BluesP=(struct blues_struct *)ldummy;
241
242 /* We now have to care for correcting all pointers which are in the VM
243 and refer to some place in the VM! Note: Instead of selecting the
244 appropriate pointer-elements of the union we simply shift the
245 unspecified pointer "valueP".
246 Note: The filename entry does not need to be modified since it does not
247 need to be shifted since it points to memory managed by t1lib.
248 */
249 /* FontInfo-dictionary: All name-pointers and the pointers to all array
250 types have to be shifted: */
251 i=pFontBase->pFontArray[FontID].pType1Data->fontInfoP[0].key.len;
252 for (j=1; j<=i; j++){
253 if ((pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ARRAY) ||
254 (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_STRING) ||
255 (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_NAME) ||
256 (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_FILE)){
257 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP;
258 ldummy +=shift;
259 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy;
260 }
261 /* The encoding needs special treatment: */
262 if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ENCODING){
263 /* If builtin StandardEncoding is used, we do nothing here. Standard Encoding
264 is now located once for all fonts on the heap. For font-specific encodings
265 we have to move all pointers appropriately, because this is entirely located
266 in VM */
267 if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP
268 == StdEncArrayP){ /* Font uses builtin StandardEncoding */
269 ;
270 }
271 else{ /* Font-specific encoding */
272 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP;
273 ldummy +=shift;
274 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy;
275 for (k=0; k<256; k++){
276 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP;
277 /* The ".notdef" is also static and may not be shifted (Thanks, Derek ;) */
278 if (ldummy != (unsigned long)not_def) {
279 ldummy +=shift;
280 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP=(struct ps_obj *)ldummy;
281 }
282 }
283 }
284 } /* end of encoding-handling */
285 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP;
286 ldummy +=shift;
287 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP=(char *)ldummy;
288 } /* fontinfo-dict done */
289
290 /* Private-dictionary: All name-pointers and the pointers to all array
291 types have to be shifted: */
292 i=pFontBase->pFontArray[FontID].pType1Data->Private[0].key.len;
293 for (j=1; j<=i; j++){
294 if ((pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_ARRAY) ||
295 (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_STRING) ||
296 (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_NAME) ||
297 (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_FILE)){
298 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP;
299 ldummy +=shift;
300 pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP=(char *)ldummy;
301 }
302 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP;
303 ldummy +=shift;
304 pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP=(char *)ldummy;
305 }
306
307 /* BluesP: The entry "next" is the only pointer in blues_struct. Although it is
308 not used anywhere we should shift it for correctness reasons (in case its not
309 NULL)! */
310 if (pFontBase->pFontArray[FontID].pType1Data->BluesP->next != NULL){
311 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->BluesP->next;
312 ldummy +=shift;
313 pFontBase->pFontArray[FontID].pType1Data->BluesP->next=(struct blues_struct *)ldummy;
314 }
315
316 /* The CharStrings-dictionary: Every namepointer and its corresponding
317 charstring has to be shifted: */
318 i=pFontBase->pFontArray[FontID].pType1Data->CharStringsP[0].key.len;
319 for (j=1; j<=i; j++){
320 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP;
321 ldummy +=shift;
322 pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP=(char *)ldummy;
323 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP;
324 ldummy +=shift;
325 pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP=(char *)ldummy;
326 }
327
328 /* The Subroutines have also to be reorganized: */
329 i=pFontBase->pFontArray[FontID].pType1Data->Subrs.len;
330 /* First, shift pointer to array-start and after that the pointers to
331 each command string: */
332 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP;
333 ldummy +=shift;
334 pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP=(struct ps_obj *)ldummy;
335 for (j=0; j<i; j++) {
336 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP;
337 ldummy +=shift;
338 pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP=(char *)ldummy;
339 }
340 } /* end of if( tmp_ptr > vm_base ) */
341 else if ( vm_base > tmp_ptr){
342 shift= (unsigned long)vm_base - (unsigned long)tmp_ptr;
343 sprintf( err_warn_msg_buf,
344 "Old VM at 0x%lX, new VM at 0x%lX, shifting down by %lu",
345 (unsigned long)vm_base, (unsigned long)tmp_ptr, tmp_size);
346 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
347
348 /* We start by shifting the topmost pointers: */
349 pFontBase->pFontArray[FontID].vm_base=tmp_ptr;
350
351 ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->vm_start);
352 ldummy -=shift;
353 pFontBase->pFontArray[FontID].pType1Data->vm_start=(char *)ldummy;
354
355 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP;
356 ldummy -=shift;
357 pFontBase->pFontArray[FontID].pType1Data->CharStringsP=(psdict *)ldummy;
358
359 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private;
360 ldummy -=shift;
361 pFontBase->pFontArray[FontID].pType1Data->Private=(psdict *)ldummy;
362
363 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP;
364 ldummy -=shift;
365 pFontBase->pFontArray[FontID].pType1Data->fontInfoP=(psdict *)ldummy;
366
367 ldummy=(long)(pFontBase->pFontArray[FontID].pType1Data->BluesP);
368 ldummy -=shift;
369 pFontBase->pFontArray[FontID].pType1Data->BluesP=(struct blues_struct *)ldummy;
370
371 /* We now have to care for correcting all pointers which are in the VM
372 and refer to some place in the VM! Note: Instead of selecting the
373 appropriate pointer-elements of the union we simply shift the
374 unspecified pointer "valueP".
375 Note: The filename entry does not need to be modified since it does not
376 need to be shifted since it points to memory managed by t1lib.
377 */
378 /* FontInfo-dictionary: All name-pointers and the pointers to all array
379 types have to be shifted: */
380 i=pFontBase->pFontArray[FontID].pType1Data->fontInfoP[0].key.len;
381 for (j=1; j<=i; j++){
382 if ((pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ARRAY) ||
383 (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_STRING) ||
384 (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_NAME) ||
385 (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_FILE)){
386 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP;
387 ldummy -=shift;
388 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy;
389 }
390 /* The encoding needs special treatment: */
391 if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.type==OBJ_ENCODING){
392 /* If builtin StandardEncoding is used, we do nothing here. Standard Encoding
393 is now located once for all fonts on the heap. For font-specific encodings
394 we have to move all pointers appropriately, because this is entirely located
395 in VM */
396 if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP
397 == StdEncArrayP){ /* Font uses builtin StandardEncoding */
398 ;
399 }
400 else{ /* Font-specific encoding */
401 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP;
402 ldummy -=shift;
403 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.valueP=(char *)ldummy;
404 for (k=0; k<256; k++){
405 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP;
406 /* The ".notdef" is also static and may not be shifted (Thanks, Derek ;) */
407 if (ldummy != (unsigned long)not_def) {
408 ldummy -=shift;
409 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].value.data.arrayP[k].data.arrayP=(struct ps_obj *)ldummy;
410 }
411 }
412 }
413 } /* end of encoding-handling */
414 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP;
415 ldummy -=shift;
416 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[j].key.data.valueP=(char *)ldummy;
417 } /* fontinfo-dict done */
418
419 /* Private-dictionary: All name-pointers and the pointers to all array
420 types have to be shifted: */
421 i=pFontBase->pFontArray[FontID].pType1Data->Private[0].key.len;
422 for (j=1; j<=i; j++){
423 if ((pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_ARRAY) ||
424 (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_STRING) ||
425 (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_NAME) ||
426 (pFontBase->pFontArray[FontID].pType1Data->Private[j].value.type==OBJ_FILE)){
427 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP;
428 ldummy -=shift;
429 pFontBase->pFontArray[FontID].pType1Data->Private[j].value.data.valueP=(char *)ldummy;
430 }
431 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP;
432 ldummy -=shift;
433 pFontBase->pFontArray[FontID].pType1Data->Private[j].key.data.valueP=(char *)ldummy;
434 }
435
436 /* BluesP: The entry "next" is the only pointer in blues_struct. Although it is
437 not used anywhere we should shift it for correctness reasons (in case its not
438 NULL)! */
439 if (pFontBase->pFontArray[FontID].pType1Data->BluesP->next != NULL){
440 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->BluesP->next;
441 ldummy -=shift;
442 pFontBase->pFontArray[FontID].pType1Data->BluesP->next=(struct blues_struct *)ldummy;
443 }
444
445 /* The CharStrings-dictionary: Every namepointer and its corresponding
446 charstring has to be shifted: */
447 i=pFontBase->pFontArray[FontID].pType1Data->CharStringsP[0].key.len;
448 for (j=1; j<=i; j++){
449 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP;
450 ldummy -=shift;
451 pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].value.data.valueP=(char *)ldummy;
452 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP;
453 ldummy -=shift;
454 pFontBase->pFontArray[FontID].pType1Data->CharStringsP[j].key.data.valueP=(char *)ldummy;
455 }
456
457 /* The Subroutines have also to be reorganized: */
458 i=pFontBase->pFontArray[FontID].pType1Data->Subrs.len;
459 /* First, shift pointer to array-start and after that the pointers to
460 each command string: */
461 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP;
462 ldummy -=shift;
463 pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP=(struct ps_obj *)ldummy;
464 for (j=0; j<i; j++) {
465 ldummy=(long)pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP;
466 ldummy -=shift;
467 pFontBase->pFontArray[FontID].pType1Data->Subrs.data.arrayP[j].data.valueP=(char *)ldummy;
468 }
469 } /* end of if( vm_base > tmp_ptr ) */
470 else{ /* VM addess has not changed during reallocation */
471 sprintf( err_warn_msg_buf,
472 "Old VM and new VM at 0x%lX, no pointer-shifting",
473 (unsigned long)vm_base);
474 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
475 }
476 #ifdef ANSI_REALLOC_ENFORCE_POINTERSHIFTING
477 /* If pointer shifting had been enforced by allocating from
478 scratch using malloc() free the previous vm. */
479 free( vm_base);
480 #endif
481 #endif
482
483 /* Generate a message how much VM the current font consumes */
484 sprintf( err_warn_msg_buf,
485 "VM for Font %d: %d bytes", FontID, (int) tmp_size);
486 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_STATISTIC);
487
488
489 /* Set the matrix for common transformations to "no transformations" */
490 pFontBase->pFontArray[FontID].FontTransform[0]=1.0;
491 pFontBase->pFontArray[FontID].FontTransform[1]=0.0;
492 pFontBase->pFontArray[FontID].FontTransform[2]=0.0;
493 pFontBase->pFontArray[FontID].FontTransform[3]=1.0;
494
495 /* Now, that the font has been loaded into memory, try to find the
496 FontMatrix in the font info dictionary. If it exists, load it into
497 our local fontmatrix, otherwise use a default matrix which scales to
498 1/1000 (since font outlines are defined in a 1000 point space)
499 and does no further transformations. */
500 if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP == NULL){
501 pFontBase->pFontArray[FontID].FontMatrix[0]=0.001;
502 pFontBase->pFontArray[FontID].FontMatrix[1]=0.0;
503 pFontBase->pFontArray[FontID].FontMatrix[2]=0.0;
504 pFontBase->pFontArray[FontID].FontMatrix[3]=0.001;
505 }
506 else{
507 pFontBase->pFontArray[FontID].FontMatrix[0]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[0].data.real;
508 pFontBase->pFontArray[FontID].FontMatrix[1]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[1].data.real;
509 pFontBase->pFontArray[FontID].FontMatrix[2]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[2].data.real;
510 pFontBase->pFontArray[FontID].FontMatrix[3]= (double)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[FONTMATRIX].value.data.arrayP[3].data.real;
511 }
512
513 /* Set the default values for transformation: */
514 pFontBase->pFontArray[FontID].slant=0.0;
515 pFontBase->pFontArray[FontID].extend=1.0;
516
517
518 /* Now try to load afm-structures from corresponding .afm-file (if
519 not suppressed by the user). */
520 if ((pFontBase->t1lib_flags & T1_NO_AFM)!=0) {
521 pFontBase->pFontArray[FontID].pAFMData = NULL;
522 T1_PrintLog( "T1_LoadFont()",
523 "Suppressing AFM data handling on user request",
524 T1LOG_STATISTIC);
525 }
526 else {
527 if ((i=openFontMetricsFile( FontID, 0))){
528 /* Try a fallback, opening sloppy: */
529 if ((i=openFontMetricsFile( FontID, 1))) {
530 sprintf( err_warn_msg_buf,
531 "Alert: Error (%d) sloppy-processing afm-file for Font %d!",
532 i ,FontID);
533 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_STATISTIC);
534 if ((pFontBase->pFontArray[FontID].pAFMData=
535 T1_GenerateAFMFallbackInfo(FontID))==NULL){
536 sprintf( err_warn_msg_buf,
537 "Ultimately failed to generate metrics information Font %d!",
538 FontID);
539 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_WARNING);
540 }
541 else {
542 pFontBase->pFontArray[FontID].info_flags |=AFM_SELFGEN_SUCCESS;
543 T1_PrintLog( "T1_LoadFont()",
544 "Generating AFM-information from fontfile successful!",
545 T1LOG_STATISTIC);
546 }
547 }
548 else {
549 pFontBase->pFontArray[FontID].info_flags |=AFM_SLOPPY_SUCCESS;
550 sprintf( err_warn_msg_buf,
551 "Alert: Limited afm-information for Font %d",FontID);
552 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_STATISTIC);
553 }
554 }
555 else {
556 pFontBase->pFontArray[FontID].info_flags |=AFM_SUCCESS;
557 }
558 }
559
560
561 /* Now, set Encodingvector entry to default if the font's
562 internal encoding is "StandardEncoding".
563 */
564 if (pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP
565 == StdEncArrayP) {
566 pFontBase->pFontArray[FontID].info_flags |=USES_STANDARD_ENCODING;
567 pFontBase->pFontArray[FontID].pFontEnc=pFontBase->default_enc;
568 sprintf( err_warn_msg_buf,
569 "Font %d reencoded to default",FontID);
570 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
571 }
572 else {
573 sprintf( err_warn_msg_buf,
574 "Font %d not reencoded to default",FontID);
575 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
576 pFontBase->pFontArray[FontID].pFontEnc = NULL;
577 }
578
579
580 /* If AFM-Info available we try to speed up some things: */
581 if (pFontBase->pFontArray[FontID].pAFMData != NULL) {
582 /* We have to fill the array that maps the current encodings' indices to the
583 indices used in afm file. The interpretation has been changed in
584 in t1lib-1.2. We now use positive values for indexing into the charmetrics
585 array and negative values for indexing into the composite character array.
586 an index of zero indicates that no metrics are defined for this character.
587 This may happen because (a) not all AFM-files define metrics for the .notdef
588 character, and (b) because font and AFM-file do not match. */
589 if ((pFontBase->pFontArray[FontID].pEncMap=
590 (int *)calloc(256,sizeof(int)))==NULL) {
591 sprintf( err_warn_msg_buf, "Error allocating memory for encoding map (FontID=%d)",
592 FontID);
593 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf,
594 T1LOG_WARNING);
595 T1_errno=T1ERR_ALLOC_MEM;
596 return(-1);
597 }
598 for (i=0; i<256; i++) {
599 charname=T1_GetCharName( FontID, i);
600 /* in a first loop check for ordinary characters */
601 for ( j=0; j<pFontBase->pFontArray[FontID].pAFMData->numOfChars; j++) {
602 if (strcmp( charname,
603 pFontBase->pFontArray[FontID].pAFMData->cmi[j].name)==0) {
604 pFontBase->pFontArray[FontID].pEncMap[i]=j+1; /* index 0 is reserved! */
605 continue;
606 }
607 }
608 /* if nothing has been found, check for composite characters */
609 for ( j=0; j<pFontBase->pFontArray[FontID].pAFMData->numOfComps; j++) {
610 if (strcmp( charname,
611 pFontBase->pFontArray[FontID].pAFMData->ccd[j].ccName)==0) {
612 pFontBase->pFontArray[FontID].pEncMap[i]=-(j+1); /* index 0 is reserved! */
613 continue;
614 }
615 }
616 }
617
618 /* For composite characters, we still have to compute the width and bbox */
619 for ( j=0; j<pFontBase->pFontArray[FontID].pAFMData->numOfComps; j++) {
620 /*and bounding box by ourselves. First, set up an identity charspace
621 matrix and then generate an edgelist for the composite character at
622 size 1000bp using no transformation and current encoding. Note: This
623 action is only required when loading a font at first time, but not
624 when reencoding a font. */
625 S=(struct XYspace *)IDENTITY;
626 S=(struct XYspace *)Permanent
627 (Transform(S, pFontBase->pFontArray[FontID].FontTransform[0],
628 pFontBase->pFontArray[FontID].FontTransform[1],
629 pFontBase->pFontArray[FontID].FontTransform[2],
630 pFontBase->pFontArray[FontID].FontTransform[3]));
631
632 area=fontfcnB_ByName( FontID, 0, S,
633 pFontBase->pFontArray[FontID].pAFMData->ccd[j].ccName,
634 &mode, pFontBase->pFontArray[FontID].pType1Data,
635 DO_RASTER);
636 /* Store bounding box ... */
637 pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.llx=area->xmin;
638 pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.urx=area->xmax;
639 pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.lly=area->ymin;
640 pFontBase->pFontArray[FontID].pAFMData->ccd[j].charBBox.ury=area->ymax;
641 /* ... and character width. This should be the width of the base character
642 of the composite! */
643 pFontBase->pFontArray[FontID].pAFMData->ccd[j].wx=NEARESTPEL(area->ending.x);
644 /* clean up. */
645 KillRegion (area);
646 if (S!=NULL) {
647 KillSpace (S);
648 S=NULL;
649 }
650 }
651 /* We now create an encoding-specific kerning table which will speed up
652 looking for kerning pairs! */
653 pFontBase->pFontArray[FontID].KernMapSize=0;
654 /* First, get number of defined kerning pairs: */
655 k=pFontBase->pFontArray[FontID].pAFMData->numOfPairs;
656 if (k>0){ /* i.e., there are any pairs */
657 /* OK, it does not suffice to alloc numOfPairs METRICS_ENTRYs, because
658 a given character might be encoded at several locations and kerning
659 should still work. As a worst case estimation, we allocate 256^2
660 and realloc later. */
661 if ((pFontBase->pFontArray[FontID].pKernMap=
662 (METRICS_ENTRY *)malloc( (256*256) *sizeof( METRICS_ENTRY)))==NULL){
663 sprintf( err_warn_msg_buf, "Error allocating memory for metrics map (FontID=%d)",
664 FontID);
665 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf,
666 T1LOG_WARNING);
667 T1_errno=T1ERR_ALLOC_MEM;
668 return(-1);
669 }
670 kern_tbl=pFontBase->pFontArray[FontID].pKernMap;
671 pkd=pFontBase->pFontArray[FontID].pAFMData->pkd;
672 j=0;
673 for ( i=0; i<k; i++) {
674 /* We do not check T1_GetEncodingIndices() against the return value
675 NULL because we just loading the font in question: */
676 l=0;
677 while ((char1=(T1_GetEncodingIndices( FontID, pkd[i].name1))[l++])!=-1) {
678 /* pair could be relevant in current encoding */
679 m=0;
680 while ((char2=(T1_GetEncodingIndices( FontID, pkd[i].name2))[m++])!=-1) {
681 /* Since we get here we have a relevant pair -->
682 Put char1 in higher byte and char2 in LSB: */
683 kern_tbl[j].chars=(char1 << 8) | char2;
684 /* We only make use of horizontal kerning */
685 kern_tbl[j].hkern=pkd[i].xamt;
686 j++;
687 } /* while (char2) */
688 } /* while (char1) */
689 } /* for */
690 /* We are done, realloc memory: */
691 kern_tbl=(METRICS_ENTRY*) realloc( kern_tbl, j*sizeof(METRICS_ENTRY));
692 /* We now sort the kerning array with respect to char indices */
693 qsort( kern_tbl, (size_t) j, sizeof(METRICS_ENTRY),
694 &cmp_METRICS_ENTRY );
695 /* Finally write back pointer for the case that realloc changed the
696 pointer */
697 pFontBase->pFontArray[FontID].pKernMap=kern_tbl;
698 pFontBase->pFontArray[FontID].KernMapSize=j;
699 }
700 else
701 pFontBase->pFontArray[FontID].pKernMap=NULL;
702 }
703 else { /* no AFM data */
704 pFontBase->pFontArray[FontID].pKernMap=NULL;
705 pFontBase->pFontArray[FontID].pEncMap=NULL;
706 }
707 /* End of "if (AFM-info ..)" */
708
709
710 /* We have just loaded a physical font into memory, thus .... */
711 pFontBase->pFontArray[FontID].physical=1;
712
713 /* Set reference-counter to 1: */
714 pFontBase->pFontArray[FontID].refcount=1;
715
716 /* Get the index into encoding vector where the space character is
717 found. If not encoded, set space_position to -1. */
718 pFontBase->pFontArray[FontID].space_position=-1;
719 i=0;
720 if (pFontBase->pFontArray[FontID].pFontEnc) { /* external default encoding */
721 while (i<256) {
722 if (strcmp( (char *)pFontBase->pFontArray[FontID].pFontEnc[i],
723 "space")==0){
724 /* space found at position i: */
725 pFontBase->pFontArray[FontID].space_position=i;
726 break;
727 }
728 i++;
729 }
730 }
731 else { /* internal encoding */
732 while (i<256) {
733 if (strcmp( (char *)pFontBase->pFontArray[FontID].pType1Data->fontInfoP[ENCODING].value.data.arrayP[i].data.arrayP,
734 "space")==0){
735 /* space found at position i: */
736 pFontBase->pFontArray[FontID].space_position=i;
737 break;
738 }
739 i++;
740 }
741 }
742
743
744 /* Set the lining rule parameters to default values */
745 pFontBase->pFontArray[FontID].UndrLnPos=
746 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[UNDERLINEPOSITION].value.data.real;
747 pFontBase->pFontArray[FontID].UndrLnThick=
748 pFontBase->pFontArray[FontID].pType1Data->fontInfoP[UNDERLINETHICKNESS].value.data.real;
749
750 /* We have to set the value for the typographic ascender. If possible,
751 we get it from the afm-File. But be aware this value might be undefined!
752 This value should in any acse explicitly be set later by the user! */
753 if (pFontBase->pFontArray[FontID].pAFMData!=NULL &&
754 pFontBase->pFontArray[FontID].pAFMData->gfi!=NULL) {
755 ascender=(float) pFontBase->pFontArray[FontID].pAFMData->gfi->ascender;
756 }
757 else {
758 ascender=(float) T1_GetCharBBox( FontID, T1_GetEncodingIndex( FontID, "d")).ury;
759 }
760
761 pFontBase->pFontArray[FontID].OvrLnPos=ascender
762 + (float) abs( (double)pFontBase->pFontArray[FontID].UndrLnPos);
763 pFontBase->pFontArray[FontID].OvrStrkPos=ascender / 2.0;
764 pFontBase->pFontArray[FontID].OvrLnThick=pFontBase->pFontArray[FontID].UndrLnThick;
765 pFontBase->pFontArray[FontID].OvrStrkThick=pFontBase->pFontArray[FontID].UndrLnThick;
766
767
768 /* Finally, set the font size dependencies pointer to NULL since we can
769 assume, that at load time of a font, no size specific data of this
770 font is available.
771 */
772
773 pFontBase->pFontArray[FontID].pFontSizeDeps=NULL;
774
775 /* If wanted, some debugging information is put into logfile */
776 sprintf( err_warn_msg_buf, "Pointer vm_base: 0x%lX",
777 (long)pFontBase->pFontArray[FontID].vm_base);
778 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
779 sprintf( err_warn_msg_buf, "Pointer vm_start: 0x%lX",
780 (long)pFontBase->pFontArray[FontID].pType1Data->vm_start);
781 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
782 sprintf( err_warn_msg_buf, "Pointer CharStringsP: 0x%lX",
783 (long)pFontBase->pFontArray[FontID].pType1Data->CharStringsP);
784 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
785 sprintf( err_warn_msg_buf, "Pointer Private: 0x%lX",
786 (long)pFontBase->pFontArray[FontID].pType1Data->Private);
787 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
788 sprintf( err_warn_msg_buf, "Pointer fontInfoP: 0x%lX",
789 (long)pFontBase->pFontArray[FontID].pType1Data->fontInfoP);
790 T1_PrintLog( "T1_LoadFont()", err_warn_msg_buf, T1LOG_DEBUG);
791
792 return(0);
793 }
794
795
796 /* openFontMetricsFile( FontID, open_sloppy): Gets the fontfilename
797 corresponding to FontID, opens the corresponding afm-file and fills
798 the data structures. return-value is the value returned by the
799 T1lib_parseFile() function. If open_sloppy is set, the minimum
800 information needed is read from AFM file. This can be considered a
801 fallback for problematic AFM files. */
openFontMetricsFile(int FontID,int open_sloppy)802 static int openFontMetricsFile( int FontID, int open_sloppy)
803 {
804 char *FontFileName;
805 char *AFMFileName;
806 char *afm_name;
807 char *AFMFileNamePath;
808
809 int i, j;
810 FILE *metricsfile;
811
812
813 afm_name=T1_GetAfmFileName(FontID);
814
815 if (afm_name!=NULL) { /* We have name explicitly specified */
816 /* It needs to be freeable */
817 if ((AFMFileName=
818 (char *)malloc( (strlen(afm_name)+1)*sizeof( char)))==NULL) {
819 T1_errno=T1ERR_ALLOC_MEM;
820 return( -6);
821 }
822 strcpy( AFMFileName, afm_name);
823 }
824 else {
825 FontFileName=T1_GetFontFileName( FontID);
826 i=strlen(FontFileName);
827 j=i;
828 AFMFileName=(char *)malloc( i+5);
829 strcpy( AFMFileName, FontFileName);
830 while ( AFMFileName[i] != '.'){
831 if (i==0) break;
832 else i--;
833 }
834 if (i==0){
835 /* We have a filename without extension -> append extension */
836 AFMFileName[j]='.';
837 AFMFileName[j+1]='a';
838 AFMFileName[j+2]='f';
839 AFMFileName[j+3]='m';
840 AFMFileName[j+4]='\0';
841 }
842 else{
843 /* we found a '.' -> replace extension */
844 AFMFileName[i+1]='a';
845 AFMFileName[i+2]='f';
846 AFMFileName[i+3]='m';
847 AFMFileName[i+4]='\0';
848 }
849 }
850
851 /* Get full path of the afm file (The case of a full path name
852 name specification is valid */
853 AFMFileNamePath=intT1_Env_GetCompletePath( AFMFileName, T1_AFM_ptr);
854 free( AFMFileName);
855
856 /* open afm-file: */
857 if (AFMFileNamePath!=NULL){
858 if ((metricsfile=fopen(AFMFileNamePath,"rb"))==NULL){
859 free(AFMFileNamePath);
860 return(-4);
861 }
862 else {
863 free(AFMFileNamePath);
864 }
865 }
866 else{
867 return( -5);
868 }
869
870 /* Call procedure to read afm-file and store the data formatted.
871 Flags used here: P_M All Metrics Information
872 P_P Pair Kerning Information
873 P_C Composite Character Data (since t1lib V.1.2)
874 The P_G flag to get global font information should not be used
875 if not absolutely needed. When parsing an unknown keyword, which
876 may be harmless, the T1lib_parseFile function returns the error code
877 -1 (parseError). On the other hand, all other really relevant
878 data may habe been parsed and stored correctly. In such a case,
879 There's no way to make a serious decision whether an error has
880 occured or not.
881 */
882 if (open_sloppy!=0)
883 i=T1lib_parseFile( (FILE *) metricsfile,
884 (FontInfo **) &(FontBase.pFontArray[FontID].pAFMData),
885 P_M );
886 else
887 i=T1lib_parseFile( (FILE *) metricsfile,
888 (FontInfo **) &(FontBase.pFontArray[FontID].pAFMData),
889 P_G | P_M | P_P | P_C );
890 fclose(metricsfile);
891 return(i);
892 }
893
894
895
896 /* T1int_CreateNewFontSize( FontID, size): Create a new size "size" of font
897 "FontID" and allocate all data necessary for this. The data
898 structure is connected to the linked list of FontSizeDeps for this
899 font. Returns a pointer to the newly created FontSizeDeps-struct
900 if all went correct and NULL otherwise.
901 Since of version 0.3 a member antialias has been added to the
902 FONTSIZEDEPS structure! This can be:
903
904 0: bitmaps are stored in this struct
905 1: non-antialiased bytemaps are stored in this struct
906 2: low-antialiased bytemaps are stored in this struct
907 4: high-antialiased bytemaps are stored in this struct
908 */
T1int_CreateNewFontSize(int FontID,float size,int aa)909 FONTSIZEDEPS *T1int_CreateNewFontSize( int FontID, float size, int aa)
910 {
911
912 FONTSIZEDEPS *pFontSizeDeps, *pPrev;
913
914
915 /* First, get to the last font size in the linked list for this font.
916 The following routine returns the address of the last struct in the
917 linked list of FONTSIZEDEPS or NULL if none exists. */
918 pFontSizeDeps=T1int_GetLastFontSize( FontID);
919 pPrev=pFontSizeDeps;
920
921
922 if (pFontSizeDeps==NULL){
923 /* Allocate memory for first FontSizeDeps-structure: */
924 if ((pFontBase->pFontArray[FontID].pFontSizeDeps=(FONTSIZEDEPS *)malloc(sizeof(FONTSIZEDEPS)))==NULL){
925 T1_errno=T1ERR_ALLOC_MEM;
926 return(NULL);
927 }
928 pFontSizeDeps=pFontBase->pFontArray[FontID].pFontSizeDeps;
929 }
930 else{
931 /* A valid address of an existing structure was found */
932 if ((pFontSizeDeps->pNextFontSizeDeps=(FONTSIZEDEPS *)malloc(sizeof(FONTSIZEDEPS)))==NULL){
933 T1_errno=T1ERR_ALLOC_MEM;
934 return(NULL);
935 }
936 pFontSizeDeps=pFontSizeDeps->pNextFontSizeDeps;
937 }
938
939 /* The pointer to the previous struct */
940 pFontSizeDeps->pPrevFontSizeDeps=pPrev;
941 /* Put the size into this structure */
942 pFontSizeDeps->size=size;
943 /* Set the antialias mark: */
944 pFontSizeDeps->antialias=aa;
945
946 /* Just the current becomes now the last item in the linked list: */
947 pFontSizeDeps->pNextFontSizeDeps=NULL;
948 /* Setup CharSpaceMatrix for this font: */
949 pFontSizeDeps->pCharSpaceLocal=(struct XYspace *) IDENTITY;
950 /* Apply transformation with font matrix: */
951 pFontSizeDeps->pCharSpaceLocal=(struct XYspace *)
952 Transform(pFontSizeDeps->pCharSpaceLocal,
953 pFontBase->pFontArray[FontID].FontMatrix[0],
954 pFontBase->pFontArray[FontID].FontMatrix[1],
955 pFontBase->pFontArray[FontID].FontMatrix[2],
956 pFontBase->pFontArray[FontID].FontMatrix[3]);
957 /* Apply a further transformation (optionally): */
958 pFontSizeDeps->pCharSpaceLocal=(struct XYspace *)
959 Transform(pFontSizeDeps->pCharSpaceLocal,
960 pFontBase->pFontArray[FontID].FontTransform[0],
961 pFontBase->pFontArray[FontID].FontTransform[1],
962 pFontBase->pFontArray[FontID].FontTransform[2],
963 pFontBase->pFontArray[FontID].FontTransform[3]);
964 /* Apply desired scaling factor, and make it Permanent */
965 pFontSizeDeps->pCharSpaceLocal=(struct XYspace *) Permanent
966 (Scale(pFontSizeDeps->pCharSpaceLocal, size, size));
967
968 /* We should now allocate memory for the glyph area of the font
969 cache: */
970 if ((pFontSizeDeps->pFontCache=(GLYPH *)calloc(256,sizeof(GLYPH)))
971 ==NULL)
972 return(NULL);
973
974 sprintf( err_warn_msg_buf, "New Size %f created for FontID %d (antialias=%d)",
975 pFontSizeDeps->size, FontID, pFontSizeDeps->antialias);
976 T1_PrintLog( "CreateNewFontSize()", err_warn_msg_buf, T1LOG_STATISTIC);
977 /* We are done */
978 return(pFontSizeDeps);
979
980 }
981
982
983
984
985 /* T1_QueryFontSize( FontID, size, aa): Search if a requested size of font
986 FontID is already existing. If so, it returns a pointer to the
987 respective FontSizeDeps-structure, otherwise NULL is returned: */
T1int_QueryFontSize(int FontID,float size,int aa)988 FONTSIZEDEPS *T1int_QueryFontSize( int FontID, float size, int aa)
989 {
990
991 FONTSIZEDEPS *link_ptr;
992
993
994 /* There's not yet one size: */
995 if (pFontBase->pFontArray[FontID].pFontSizeDeps == NULL)
996 return(pFontBase->pFontArray[FontID].pFontSizeDeps);
997
998
999 /* There's already existing one or more size */
1000 link_ptr=pFontBase->pFontArray[FontID].pFontSizeDeps;
1001
1002 while (((link_ptr->size != size)||(link_ptr->antialias != aa))
1003 &&(link_ptr->pNextFontSizeDeps != NULL))
1004 link_ptr=link_ptr->pNextFontSizeDeps;
1005
1006 if ((link_ptr->size != size)||(link_ptr->antialias != aa))
1007 return( NULL); /* requested size/aa-combination was not found */
1008 else
1009 return(link_ptr); /* return pointer to requested struct */
1010
1011 }
1012
1013 /* FONTSIZEDEPS *T1int_GetLastFontSize( FontID): Get the address of the
1014 last struct in the linked list of FontSizeDeps or NULL if there is
1015 no existing size dependent data. */
T1int_GetLastFontSize(int FontID)1016 FONTSIZEDEPS *T1int_GetLastFontSize( int FontID)
1017 {
1018 FONTSIZEDEPS *link_ptr, *result_ptr;
1019
1020
1021 /* There's not yet one size: */
1022 if (pFontBase->pFontArray[FontID].pFontSizeDeps == NULL)
1023 return((FONTSIZEDEPS *) (pFontBase->pFontArray[FontID].pFontSizeDeps));
1024
1025
1026 /* There's already existing one or more size */
1027 link_ptr=pFontBase->pFontArray[FontID].pFontSizeDeps;
1028
1029 while (link_ptr != NULL){
1030 result_ptr=link_ptr;
1031 link_ptr=link_ptr->pNextFontSizeDeps;
1032 }
1033
1034 return((FONTSIZEDEPS *)(result_ptr));
1035 }
1036
1037
1038 /* A function for comparing METRICS_ENTRY structs */
cmp_METRICS_ENTRY(const void * entry1,const void * entry2)1039 static int cmp_METRICS_ENTRY( const void *entry1, const void *entry2)
1040 {
1041 if (((METRICS_ENTRY *)entry1)->chars <
1042 ((METRICS_ENTRY *)entry2)->chars)
1043 return(-1);
1044 if (((METRICS_ENTRY *)entry1)->chars >
1045 ((METRICS_ENTRY *)entry2)->chars)
1046 return(1);
1047 return(0); /* This should not happen */
1048 }
1049
1050
1051