1 # include "utilPsConfig.h"
2
3 # include <stdlib.h>
4 # include <string.h>
5 # include <ctype.h>
6
7 # include "psFontInfo.h"
8 # include "psGlyphs.h"
9 # include <utilTree.h>
10 # include <uniAlternatives.h>
11
12 # include <appDebugon.h>
13
14 /************************************************************************/
15 /* */
16 /* Bookkeeping and management of AFM information. */
17 /* */
18 /************************************************************************/
19
psInitAfmCodeList(AfmCodeList * acl)20 static void psInitAfmCodeList( AfmCodeList * acl )
21 {
22 acl->aclCodes= (unsigned short int *)0;
23 acl->aclCodeCount= 0;
24 }
25
psInitAfmCharMetric(AfmCharMetric * acm)26 static void psInitAfmCharMetric( AfmCharMetric * acm )
27 {
28 psInitAfmCodeList( &(acm->acmDefaultCodeList) );
29 psInitAfmCodeList( &(acm->acmUnicodeCodeList) );
30
31 acm->acmWX= 0;;
32 geoInitRectangle ( &(acm->acmBBox) );
33 acm->acmN= (char *)0;
34 acm->acmKernPairs= (AfmKerningPair *)0;
35 acm->acmKernPairCount= 0;
36 acm->acmGlyphIndex= -1;
37 }
38
psCleanAfmCodeList(AfmCodeList * acl)39 static void psCleanAfmCodeList( AfmCodeList * acl )
40 {
41 if ( acl->aclCodes )
42 { free( acl->aclCodes ); }
43 }
44
psFreeAfmCharMetric(AfmCharMetric * acm)45 static void psFreeAfmCharMetric( AfmCharMetric * acm )
46 {
47 psCleanAfmCodeList( &(acm->acmDefaultCodeList) );
48 psCleanAfmCodeList( &(acm->acmUnicodeCodeList) );
49
50 if ( acm->acmN )
51 { free( acm->acmN ); }
52 if ( acm->acmKernPairs )
53 { free( acm->acmKernPairs ); }
54
55 free( acm );
56 }
57
psFontMetricAddCodeToList(AfmCodeList * acl,AfmFontInfo * afi,int C)58 static int psFontMetricAddCodeToList( AfmCodeList * acl,
59 AfmFontInfo * afi,
60 int C )
61 {
62 int i;
63 unsigned short * fresh;
64
65 if ( C < 0 )
66 { LDEB(C); return -1; }
67
68 for ( i= 0; i < acl->aclCodeCount; i++ )
69 {
70 if ( acl->aclCodes[i] == C )
71 { return 0; }
72 }
73
74 fresh= (unsigned short *)realloc( acl->aclCodes,
75 ( acl->aclCodeCount+ 1 )* sizeof(unsigned short) );
76 if ( ! fresh )
77 { LXDEB(acl->aclCodeCount,fresh); return -1; }
78 acl->aclCodes= fresh;
79
80 acl->aclCodes[acl->aclCodeCount++]= C;
81
82 return 0;
83 }
84
85 /************************************************************************/
86
psGetUnicodesFromGlyphNames(AfmFontInfo * afi)87 int psGetUnicodesFromGlyphNames( AfmFontInfo * afi )
88 {
89 int glyphIndex;
90 int rval= 0;
91
92 IndexMapping * tgm= &(afi->afiUnicodeToGlyphMapping);
93
94 for ( glyphIndex= 0; glyphIndex < afi->afiMetricCount; glyphIndex++ )
95 {
96 AfmCharMetric * acm= afi->afiMetrics[glyphIndex];
97 if ( acm && acm->acmN )
98 {
99 int code= psGlyphNameToUnicode( acm->acmN );
100
101 if ( code < 0 )
102 { /*SDEB(acm->acmN);*/ continue; }
103
104 if ( psFontMetricAddCodeToList( &(acm->acmUnicodeCodeList),
105 afi, code ) )
106 { LDEB(code); return -1; }
107
108 if ( utilIndexMappingGet( tgm, code ) < 0 )
109 {
110 utilIndexMappingPut( tgm, code, glyphIndex );
111
112 if ( utilIndexSetAdd( &(afi->afiUnicodesProvided), code ) )
113 { LDEB(code); }
114 }
115 }
116 }
117
118 return rval;
119 }
120
psGetAlternateGlyphs(AfmFontInfo * afi)121 int psGetAlternateGlyphs( AfmFontInfo * afi )
122 {
123 if ( uniMapToAlternatives( &(afi->afiUnicodeToGlyphMapping) ) )
124 { SDEB(afi->afiFullName); }
125
126 if ( uniIncludeWithAlternatives( &(afi->afiUnicodesProvided) ) )
127 { SDEB(afi->afiFullName); }
128
129 return 0;
130 }
131
psResolveFallbackGlyph(AfmFontInfo * afi)132 int psResolveFallbackGlyph( AfmFontInfo * afi )
133 {
134 IndexMapping * tgm= &(afi->afiUnicodeToGlyphMapping);
135 int space;
136
137 if ( afi->afiFallbackGlyph >= 0 )
138 { return 0; }
139
140 space= utilIndexMappingGet( tgm, ' ' );
141 if ( space >= 0 )
142 { afi->afiFallbackGlyph= space; return 0; }
143
144 SDEB(afi->afiFullName); return -1;
145 }
146
147 /************************************************************************/
148 /* */
149 /* Initialise an AfmFontInfo */
150 /* */
151 /************************************************************************/
152
psInitAfmFontInfo(AfmFontInfo * afi)153 void psInitAfmFontInfo( AfmFontInfo * afi )
154 {
155 afi->afiFaceNumber= -1;
156
157 afi->afiFontName= (char *)0;
158 afi->afiFullName= (char *)0;
159 afi->afiNotice= (char *)0;
160 afi->afiVersion= (char *)0;
161 afi->afiFamilyName= (char *)0;
162 afi->afiFamilyName_Orig= (char *)0;
163 afi->afiWeightStr= (char *)0;
164 afi->afiWeightInt= FONTweightREGULAR;
165 afi->afiWidthStr= (char *)0;
166 afi->afiWidthInt= FONTwidthNORMAL;
167
168 afi->afiItalicAngle= 0.0;
169 afi->afiTanItalicAngle= 0.0;
170
171 afi->afiIsFixedPitch= 0;
172 geoInitRectangle( &(afi->afiFontBBox) );
173 afi->afiUnderlinePosition= 0;
174 afi->afiUnderlineThickness= 0;
175 afi->afiEncodingScheme= (char *)0;
176 afi->afiCapHeight= 0;
177 afi->afiXHeight= 0;
178 afi->afiAscender= 0;
179 afi->afiDescender= 0;
180 afi->afiCharacterSet= (char *)0;
181 afi->afiVendor= (char *)0;
182
183 afi->afiResourceName= (char *)0;
184 utilInitMemoryBuffer( &(afi->afiFontFileName) );
185 afi->afiFontFileIndex= 0;
186
187 utilInitMemoryBuffer( &(afi->afiAfmFileName) );
188 afi->afiMetricsDeferred= 0;
189 afi->afiIgnoreKerning= 0;
190 afi->afiMetricCount= 0;
191 afi->afiMetrics= (AfmCharMetric **)0;
192 afi->afiNameToMetric= (void *)0;
193 afi->afiFallbackGlyph= 0;
194
195 afi->afiX11FontCount= 0;
196 afi->afiX11Fonts= (char **)0;
197
198 utilInitIndexMapping( &(afi->afiUnicodeToGlyphMapping) );
199 utilInitIndexSet( &(afi->afiUnicodesProvided) );
200
201 /**/
202 afi->afiStyle= (char *)0;
203
204 afi->afiResolveMetrics= (ResolveFontMetrics)0;
205
206 return;
207 }
208
psRemoveMetricsFromInfo(AfmFontInfo * afi)209 void psRemoveMetricsFromInfo( AfmFontInfo * afi )
210 {
211 int i;
212
213 for ( i= 0; i < afi->afiMetricCount; i++ )
214 {
215 if ( afi->afiMetrics[i] )
216 { psFreeAfmCharMetric( afi->afiMetrics[i] ); }
217 }
218
219 if ( afi->afiMetrics )
220 { free( afi->afiMetrics );}
221
222 afi->afiMetricCount= 0;
223 afi->afiMetrics= (AfmCharMetric **)0;
224
225 if ( afi->afiNameToMetric )
226 {
227 utilTreeFreeTree( afi->afiNameToMetric,
228 (UTIL_TREE_CALLBACK)0, (void *)0 );
229 afi->afiNameToMetric= (void *)0;
230 }
231
232 return;
233 }
234
psCleanAfmFontInfo(AfmFontInfo * afi)235 void psCleanAfmFontInfo( AfmFontInfo * afi )
236 {
237 int i;
238
239 if ( afi->afiFontName )
240 { free( afi->afiFontName ); }
241 if ( afi->afiFullName )
242 { free( afi->afiFullName ); }
243 if ( afi->afiNotice )
244 { free( afi->afiNotice ); }
245 if ( afi->afiVersion )
246 { free( afi->afiVersion ); }
247 if ( afi->afiFamilyName )
248 { free( afi->afiFamilyName ); }
249 if ( afi->afiFamilyName_Orig )
250 { free( afi->afiFamilyName_Orig ); }
251 if ( afi->afiWeightStr )
252 { free( afi->afiWeightStr ); }
253 if ( afi->afiWidthStr )
254 { free( afi->afiWidthStr ); }
255 if ( afi->afiEncodingScheme )
256 { free( afi->afiEncodingScheme );}
257 if ( afi->afiCharacterSet )
258 { free( afi->afiCharacterSet );}
259 if ( afi->afiVendor )
260 { free( afi->afiVendor );}
261 if ( afi->afiResourceName )
262 { free( afi->afiResourceName );}
263
264 utilCleanMemoryBuffer( &(afi->afiFontFileName) );
265 utilCleanMemoryBuffer( &(afi->afiAfmFileName) );
266
267 for ( i= 0; i < afi->afiX11FontCount; i++ )
268 {
269 if ( afi->afiX11Fonts[i] )
270 { free( afi->afiX11Fonts[i] ); }
271 }
272
273 if ( afi->afiX11Fonts )
274 { free( afi->afiX11Fonts );}
275
276 psRemoveMetricsFromInfo( afi );
277
278 /* afi->afiStyle is a reference to another string */
279
280 utilCleanIndexMapping( &(afi->afiUnicodeToGlyphMapping) );
281 utilCleanIndexSet( &(afi->afiUnicodesProvided) );
282
283 return;
284 }
285
psFreeAfmFontInfo(AfmFontInfo * afi)286 void psFreeAfmFontInfo( AfmFontInfo * afi )
287 {
288 psCleanAfmFontInfo( afi );
289 free( afi );
290 }
291
292 /************************************************************************/
293 /* */
294 /* Add one code for the default encoding to a char metric. */
295 /* */
296 /************************************************************************/
297
psFontMetricAddCode(AfmCharMetric * acm,AfmFontInfo * afi,int C)298 static int psFontMetricAddCode( AfmCharMetric * acm,
299 AfmFontInfo * afi,
300 int C )
301 {
302 if ( psFontMetricAddCodeToList( &(acm->acmDefaultCodeList), afi, C ) )
303 { LDEB(C); return -1; }
304
305 return 0;
306 }
307
308 /************************************************************************/
309 /* */
310 /* Add one metic to a font info. */
311 /* */
312 /************************************************************************/
313
psFontInfoAddMetric(AfmFontInfo * afi,int C,int WX,const char * N,const DocumentRectangle * abb)314 int psFontInfoAddMetric( AfmFontInfo * afi,
315 int C,
316 int WX,
317 const char * N,
318 const DocumentRectangle * abb )
319 {
320 AfmCharMetric ** fresh;
321 AfmCharMetric * acm;
322 int duplicate= 0;
323
324 if ( ! afi->afiNameToMetric )
325 {
326 const int ownKeys= 0;
327
328 afi->afiNameToMetric= utilTreeMakeTree( ownKeys );
329 if ( ! afi->afiNameToMetric )
330 { XDEB(afi->afiNameToMetric); return -1; }
331 }
332
333 if ( N && N[0] )
334 {
335 acm= (AfmCharMetric *)utilTreeGetEQ( afi->afiNameToMetric, (const char **)0, N );
336
337 if ( acm )
338 {
339 if ( C >= 0 && psFontMetricAddCode( acm, afi, C ) )
340 { LDEB(C); return -1; }
341
342 duplicate= 1;
343 }
344 }
345
346 fresh= (AfmCharMetric **)realloc( afi->afiMetrics,
347 ( afi->afiMetricCount+ 1 )* sizeof(AfmCharMetric *) );
348 if ( ! fresh )
349 { LXDEB(C,fresh); return -1; }
350 afi->afiMetrics= fresh;
351
352 fresh[afi->afiMetricCount]= acm= (AfmCharMetric *)malloc(
353 sizeof(AfmCharMetric) );
354 if ( ! acm )
355 { XDEB(acm); return -1; }
356
357 psInitAfmCharMetric( acm );
358
359 acm->acmWX= (int)WX;
360 if ( N && ! duplicate )
361 {
362 acm->acmN= strdup( N );
363
364 if ( utilTreeStoreValue( afi->afiNameToMetric,
365 (void **)0, (const char **)0,
366 acm->acmN, acm ) )
367 { LDEB(afi->afiMetricCount); }
368 }
369
370 acm->acmBBox= *abb;
371 acm->acmGlyphIndex= afi->afiMetricCount++;
372
373 if ( C >= 0 && psFontMetricAddCode( acm, afi, C ) )
374 { LDEB(C); return -1; }
375
376 return 0;
377 }
378
379 /************************************************************************/
380 /* */
381 /* Set/Add the default encoding for a glyph. */
382 /* As this is the wrong way round in the AFM file format, more than */
383 /* one code can map to the same glyph. */
384 /* */
385 /************************************************************************/
386
psFontInfoSetGlyphCode(AfmFontInfo * afi,int glyphIndex,int C)387 int psFontInfoSetGlyphCode( AfmFontInfo * afi,
388 int glyphIndex,
389 int C )
390 {
391 if ( glyphIndex < 0 ||
392 glyphIndex >= afi->afiMetricCount ||
393 ! afi->afiMetrics[glyphIndex] )
394 { LLDEB(glyphIndex,afi->afiMetricCount); return -1; }
395
396 if ( psFontMetricAddCode( afi->afiMetrics[glyphIndex], afi, C ) )
397 { LDEB(C); return -1; }
398
399 return 0;
400 }
401
psFontInfoSetGlyphUnicode(AfmFontInfo * afi,int glyphIndex,int code)402 int psFontInfoSetGlyphUnicode( AfmFontInfo * afi,
403 int glyphIndex,
404 int code )
405 {
406 AfmCharMetric * acm;
407 IndexMapping * tgm= &(afi->afiUnicodeToGlyphMapping);
408
409 if ( glyphIndex < 0 ||
410 glyphIndex >= afi->afiMetricCount ||
411 ! afi->afiMetrics[glyphIndex] )
412 { LLDEB(glyphIndex,afi->afiMetricCount); return -1; }
413
414 acm= afi->afiMetrics[glyphIndex];
415
416 if ( psFontMetricAddCodeToList( &(acm->acmUnicodeCodeList), afi, code ) )
417 { LDEB(code); return -1; }
418
419 if ( utilIndexMappingGet( tgm, code ) < 0 )
420 {
421 utilIndexMappingPut( tgm, code, glyphIndex );
422
423 if ( utilIndexSetAdd( &(afi->afiUnicodesProvided), code ) )
424 { LDEB(code); }
425 }
426
427 return 0;
428 }
429
430 /************************************************************************/
431 /* */
432 /* Remember the name of a glyph. */
433 /* */
434 /************************************************************************/
435
psFontInfoSetGlyphName(AfmFontInfo * afi,int glyphIndex,const char * glyphName)436 int psFontInfoSetGlyphName( AfmFontInfo * afi,
437 int glyphIndex,
438 const char * glyphName )
439 {
440 if ( glyphIndex < 0 ||
441 glyphIndex >= afi->afiMetricCount ||
442 ! afi->afiMetrics[glyphIndex] )
443 { LLDEB(glyphIndex,afi->afiMetricCount); return -1; }
444
445 if ( afi->afiMetrics[glyphIndex]->acmN )
446 {
447 utilTreeDeleteEQ( afi->afiNameToMetric,
448 afi->afiMetrics[glyphIndex]->acmN,
449 (UTIL_TREE_CALLBACK)0, (void *)0 );
450 free( afi->afiMetrics[glyphIndex]->acmN );
451 }
452
453 afi->afiMetrics[glyphIndex]->acmN= strdup( glyphName );
454 if ( ! afi->afiMetrics[glyphIndex]->acmN )
455 { XDEB(afi->afiMetrics[glyphIndex]->acmN); return -1; }
456
457 if ( utilTreeStoreValue( afi->afiNameToMetric,
458 (void **)0, (const char **)0,
459 afi->afiMetrics[glyphIndex]->acmN,
460 afi->afiMetrics[glyphIndex] ) )
461 { LDEB(afi->afiMetricCount); }
462
463 return 0;
464 }
465
psFontInfoGetGlyphName(const AfmFontInfo * afi,int glyphIndex)466 const char * psFontInfoGetGlyphName( const AfmFontInfo * afi,
467 int glyphIndex )
468 {
469 if ( glyphIndex < 0 ||
470 glyphIndex >= afi->afiMetricCount ||
471 ! afi->afiMetrics[glyphIndex] )
472 { LLDEB(glyphIndex,afi->afiMetricCount); return (const char *)0; }
473
474 return afi->afiMetrics[glyphIndex]->acmN;
475 }
476
psFontInfoGetGlyphIndex(const AfmFontInfo * afi,const char * glyphName)477 int psFontInfoGetGlyphIndex( const AfmFontInfo * afi,
478 const char * glyphName )
479 {
480 AfmCharMetric * acm;
481
482 if ( ! afi->afiNameToMetric )
483 {
484 if ( afi->afiMetricCount > 0 )
485 { LXDEB(afi->afiMetricCount,afi->afiNameToMetric); }
486
487 return -1;
488 }
489
490 acm= (AfmCharMetric *)utilTreeGetEQ( afi->afiNameToMetric,
491 (const char **)0, glyphName );
492 if ( ! acm )
493 { return -1; }
494
495 return acm->acmGlyphIndex;
496 }
497
498 /************************************************************************/
499 /* */
500 /* Add one metic to a font info. */
501 /* */
502 /************************************************************************/
503
psAddX11FontToInfo(AfmFontInfo * afi,const char * fontName)504 int psAddX11FontToInfo( AfmFontInfo * afi,
505 const char * fontName )
506 {
507 int i;
508 char ** fresh;
509
510 for ( i= 0; i < afi->afiX11FontCount; i++ )
511 {
512 if ( ! strcmp( afi->afiX11Fonts[i], fontName ) )
513 { return 0; }
514 }
515
516 fresh= (char **)realloc( afi->afiX11Fonts,
517 ( afi->afiX11FontCount+ 1 )* sizeof(char *) );
518 if ( ! fresh )
519 { XDEB(fresh); return -1; }
520 afi->afiX11Fonts= fresh;
521
522 fresh[afi->afiX11FontCount]= strdup( fontName );
523 if ( ! fresh[afi->afiX11FontCount] )
524 { XDEB(fresh[afi->afiX11FontCount]); return -1; }
525
526 afi->afiX11FontCount++;
527
528 return 0;
529 }
530
531