1 /************************************************************************/
2 /*									*/
3 /*  Utility routines to build font configuration.			*/
4 /*									*/
5 /************************************************************************/
6 
7 #   include	"utilPsConfig.h"
8 
9 #   include	<stdio.h>
10 #   include	<stdlib.h>
11 #   include	<string.h>
12 #   include	<ctype.h>
13 
14 #   include	<locale.h>
15 
16 #   include	<reg.h>
17 
18 #   include	<sioFileio.h>
19 #   include	<sioPfb.h>
20 #   include	<sioPipe.h>
21 #   include	<appSystem.h>
22 #   include	<utilMemoryBuffer.h>
23 #   include	<utilMemoryBufferPrintf.h>
24 #   include	"psTtf.h"
25 #   include	"psBuildConfigFiles.h"
26 #   include	"psReadWriteFontInfo.h"
27 
28 #   include	<appDebugon.h>
29 
30 #   ifdef __VMS
31     static const char * const		afmExtension= "AFM";
32     static const char * const		pfbExtension= "PFB";
33     static const char * const		pfaExtension= "PFA";
34 #   else
35     static const char * const		afmExtension= "afm";
36     static const char * const		pfbExtension= "pfb";
37     static const char * const		pfaExtension= "pfa";
38 #   endif
39     static const char * const		ttfExtension= "ttf";
40     static const char * const		TTFExtension= "TTF";
41 
42 static const char * PS_FontNamePattern=
43 			"^/FontName[ \t]*/([^ \t]*)[ \t][ \t]*def";
44 
45 static const char * PS_LocalAfmDir= "localfonts";
46 
47 /************************************************************************/
48 
49 typedef struct AfmDirBuilder
50     {
51     MemoryBuffer		adbAfmDirectory;
52     MemoryBuffer		adbAfmCommand;
53     MemoryBuffer		adbCwd;
54     regProg *			adbFontNameProg;
55 				/**
56 				 *  Owned by the caller. To be
57 				 *  augmented here.
58 				 */
59     PostScriptFontList *	adbPostScriptFontList;
60     int				adbAfmFlags;
61     } AfmDirBuilder;
62 
psInitAfmDirBuilder(AfmDirBuilder * adb)63 static void psInitAfmDirBuilder(	AfmDirBuilder *	adb )
64     {
65     utilInitMemoryBuffer( &(adb->adbAfmDirectory) );
66     utilInitMemoryBuffer( &(adb->adbAfmCommand) );
67     utilInitMemoryBuffer( &(adb->adbCwd) );
68     adb->adbFontNameProg= (regProg *)0;
69     adb->adbPostScriptFontList= (PostScriptFontList *)0;
70     adb->adbAfmFlags= 0;
71     }
72 
psCleanAfmDirBuilder(AfmDirBuilder * adb)73 static void psCleanAfmDirBuilder(	AfmDirBuilder *	adb )
74     {
75     utilCleanMemoryBuffer( &(adb->adbAfmDirectory) );
76     utilCleanMemoryBuffer( &(adb->adbAfmCommand) );
77     utilCleanMemoryBuffer( &(adb->adbCwd) );
78 
79     if  ( adb->adbFontNameProg )
80 	{ regFree( adb->adbFontNameProg );	}
81     }
82 
psStartAfmDirBuilder(AfmDirBuilder * adb,PostScriptFontList * psfl,int ignoreKerning,const MemoryBuffer * afmDirectory,const MemoryBuffer * psDirectory)83 static int psStartAfmDirBuilder(	AfmDirBuilder *		adb,
84 					PostScriptFontList *	psfl,
85 					int			ignoreKerning,
86 					const MemoryBuffer *	afmDirectory,
87 					const MemoryBuffer *	psDirectory )
88     {
89     int			rval= 0;
90     const int		relativeIsFile= 0;
91     const int		options= 0;
92 
93     const char *	afmBase= "gs -sthefont=%s -q %s/gsfontmetrics.ps -c quit";
94 
95     MemoryBuffer	local;
96 
97     utilInitMemoryBuffer( &local );
98 
99     adb->adbPostScriptFontList= psfl;
100 
101     if  ( ignoreKerning )
102 	{ adb->adbAfmFlags |= PSflagIGNORE_KERNING;	}
103 
104     if  ( utilMemoryBufferSetString( &local, PS_LocalAfmDir ) )
105 	{ LDEB(1); rval= -1; goto ready;	}
106 
107     if  ( afmDirectory )
108 	{
109 	if  ( appAbsoluteName( &(adb->adbAfmDirectory),
110 				&local, relativeIsFile, afmDirectory ) < 0 )
111 	    { SDEB(PS_LocalAfmDir); rval= -1; goto ready;	}
112 	}
113 
114     adb->adbFontNameProg= regCompile( PS_FontNamePattern, options );
115     if  ( ! adb->adbFontNameProg )
116 	{ XDEB(adb->adbFontNameProg); rval= -1; goto ready;	}
117 
118     if  ( psDirectory )
119 	{
120 	utilMemoryBufferPrintf( &(adb->adbAfmCommand), afmBase, "%s",
121 				utilMemoryBufferGetString( psDirectory ) );
122 	}
123 
124     if  ( appCurrentDirectory( &(adb->adbCwd) ) < 0 )
125 	{ LDEB(1); rval= -1; goto ready;	}
126 
127   ready:
128 
129     utilCleanMemoryBuffer( &local );
130 
131     return rval;
132     }
133 
psGetNameExt(MemoryBuffer * file,MemoryBuffer * extension,const AfmDirBuilder * adb,const char * fontFileName)134 static int psGetNameExt(	MemoryBuffer *		file,
135 				MemoryBuffer *		extension,
136 				const AfmDirBuilder *	adb,
137 				const char *		fontFileName )
138     {
139     int				rval= 0;
140     MemoryBuffer		filename;
141 
142     utilInitMemoryBuffer( &filename );
143 
144     if  ( utilMemoryBufferSetString( &filename, fontFileName ) )
145 	{ SDEB(fontFileName); rval= -1; goto ready;	}
146 
147     if  ( appFileGetFileExtension( extension, &filename ) < 0 )
148 	{ LDEB(1); rval= -1; goto ready;	}
149     if  ( utilMemoryBufferIsEmpty( extension ) )
150 	{ rval= -1; rval= 1; goto ready;	}
151 
152     if  ( ! appFileNameIsAbsolute( fontFileName ) )
153 	{
154 	int		l;
155 	const int	relativeIsFile= 0;
156 
157 	l= appAbsoluteName( file, &filename, relativeIsFile, &(adb->adbCwd) );
158 	if  ( l < 0 )
159 	    { LDEB(l); rval= -1; rval= 1; goto ready;	}
160 	}
161     else{
162 	if  ( utilCopyMemoryBuffer( file, &filename ) )
163 	    { LDEB(1);	}
164 	}
165 
166   ready:
167 
168     utilCleanMemoryBuffer( &filename );
169 
170     return rval;
171     }
172 
173 /************************************************************************/
174 /*									*/
175 /*  Find the font name for a Postcript type 1 font.			*/
176 /*									*/
177 /************************************************************************/
178 
psFontNameFromPf(MemoryBuffer * fontname,SimpleInputStream * sisFont,regProg * prog)179 static int psFontNameFromPf(	MemoryBuffer *		fontname,
180 				SimpleInputStream *	sisFont,
181 				regProg *		prog )
182     {
183     int			rval= 1;
184     char		scratch[550+1];
185 
186     while( sioInGetString( scratch, sizeof(scratch)-1, sisFont ) )
187 	{
188 	ExpressionMatch		em;
189 
190 	scratch[sizeof(scratch)-1]= '\0';
191 
192 	if  ( regFindLeftToRight( &em, prog, scratch, 0, strlen( scratch ) ) )
193 	    {
194 	    int		from;
195 	    int		past;
196 
197 	    regGetMatch( &from, &past, &em, 0 );
198 
199 	    if  ( utilMemoryBufferSetBytes( fontname,
200 				(unsigned char *)scratch+ from, past- from ) )
201 		{ LLDEB(past,from); rval= -1; break;	}
202 
203 	    rval= 0; break;
204 	    }
205 	}
206 
207     if  ( rval )
208 	{ LDEB(rval);	}
209 
210     return rval;
211     }
212 
psFillAfiForPf(SimpleInputStream * sisFont,const AfmDirBuilder * adb,const MemoryBuffer * filename)213 static AfmFontInfo * psFillAfiForPf(
214 				SimpleInputStream *	sisFont,
215 				const AfmDirBuilder *	adb,
216 				const MemoryBuffer *	filename )
217     {
218     int			rval= 0;
219 
220     MemoryBuffer	fontname;
221     MemoryBuffer	command;
222 
223     SimpleInputStream *	sisCmd= (SimpleInputStream *)0;
224     AfmFontInfo *	afi= (AfmFontInfo *)0;
225 
226     utilInitMemoryBuffer( &fontname );
227     utilInitMemoryBuffer( &command );
228 
229     afi= (AfmFontInfo *)malloc( sizeof(AfmFontInfo) );
230     if  ( ! afi )
231 	{ XDEB(afi); rval= -1; goto ready;	}
232     psInitAfmFontInfo( afi );
233 
234     if  ( psFontNameFromPf( &fontname, sisFont, adb->adbFontNameProg ) )
235 	{ LDEB(1); rval= -1; goto ready;	}
236 
237     utilMemoryBufferPrintf( &command,
238 		    utilMemoryBufferGetString( &(adb->adbAfmCommand) ),
239 		    utilMemoryBufferGetString( &fontname ) );
240 
241     sisCmd= sioInPipeOpen( &command );
242     if  ( ! sisCmd )
243 	{
244 	SXDEB(utilMemoryBufferGetString(&command),sisCmd);
245 	rval= -1; goto ready;
246 	}
247 
248     rval= psAfmReadAfm( sisCmd, afi, adb->adbAfmFlags );
249     if  ( rval  )
250 	{
251 	SLDEB(utilMemoryBufferGetString(&command),rval); rval= -1;
252 	rval= -1; goto ready;
253 	}
254 
255     if  ( utilCopyMemoryBuffer( &(afi->afiFontFileName), filename ) )
256 	{ LDEB(1); rval= -1; goto ready;	}
257 
258     if  ( psGetUnicodesFromGlyphNames( afi ) )
259 	{ SDEB(afi->afiFullName);	}
260     if  ( psGetAlternateGlyphs( afi ) )
261 	{ SDEB(afi->afiFullName);	}
262     if  ( psResolveFallbackGlyph( afi ) )
263 	{ SDEB(afi->afiFullName);	}
264 
265   ready:
266 
267     if  ( rval && afi )
268 	{
269 	psFreeAfmFontInfo( afi );
270 	afi= (AfmFontInfo *)0;
271 	}
272 
273     utilCleanMemoryBuffer( &fontname );
274     utilCleanMemoryBuffer( &command );
275 
276     if  ( sisCmd )
277 	{ sioInClose( sisCmd );	}
278 
279     return afi;
280     }
281 
psFontNameFromPfa(MemoryBuffer * fontname,regProg * prog,const MemoryBuffer * filename)282 static int psFontNameFromPfa(	MemoryBuffer *		fontname,
283 				regProg *		prog,
284 				const MemoryBuffer *	filename )
285     {
286     int			rval= 0;
287     SimpleInputStream *	sisFile= (SimpleInputStream *)0;
288 
289     sisFile= sioInFileioOpen( filename );
290     if  ( ! sisFile )
291 	{ XDEB(sisFile); rval= -1; goto ready;	}
292 
293     rval= psFontNameFromPf( fontname, sisFile, prog );
294     if  ( rval )
295 	{ LDEB(rval);	}
296 
297   ready:
298 
299     if  ( sisFile )
300 	{ sioInClose( sisFile );	}
301 
302     return rval;
303     }
304 
psFillAfiForPfa(const AfmDirBuilder * adb,const MemoryBuffer * filename)305 static AfmFontInfo * psFillAfiForPfa(	const AfmDirBuilder *	adb,
306 					const MemoryBuffer *	filename )
307     {
308     AfmFontInfo *	afi= (AfmFontInfo *)0;
309     SimpleInputStream *	sisFile= (SimpleInputStream *)0;
310 
311     sisFile= sioInFileioOpen( filename );
312     if  ( ! sisFile )
313 	{ XDEB(sisFile); goto ready;	}
314 
315     afi= psFillAfiForPf( sisFile, adb, filename );
316     if  ( ! afi )
317 	{ XDEB(afi);	}
318 
319   ready:
320 
321     if  ( sisFile )
322 	{ sioInClose( sisFile );	}
323 
324     return afi;
325     }
326 
psFontNameFromPfb(MemoryBuffer * fontname,regProg * prog,const MemoryBuffer * filename)327 static int psFontNameFromPfb(	MemoryBuffer *		fontname,
328 				regProg *		prog,
329 				const MemoryBuffer *	filename )
330     {
331     int			rval= 0;
332     SimpleInputStream *	sisFile= (SimpleInputStream *)0;
333     SimpleInputStream *	sisFont= (SimpleInputStream *)0;
334 
335     sisFile= sioInFileioOpen( filename );
336     if  ( ! sisFile )
337 	{ XDEB(sisFile); goto ready;	}
338 
339     sisFont= sioInPfbOpen( sisFile );
340     if  ( ! sisFont )
341 	{ XDEB(sisFont); goto ready;	}
342 
343     rval= psFontNameFromPf( fontname, sisFont, prog );
344     if  ( rval )
345 	{ LDEB(rval);	}
346 
347   ready:
348 
349     if  ( sisFont )
350 	{ sioInClose( sisFont );	}
351     if  ( sisFile )
352 	{ sioInClose( sisFile );	}
353 
354     return rval;
355     }
356 
psFillAfiForPfb(const AfmDirBuilder * adb,const MemoryBuffer * filename)357 static AfmFontInfo * psFillAfiForPfb(	const AfmDirBuilder *	adb,
358 					const MemoryBuffer *	filename )
359     {
360     AfmFontInfo *	afi= (AfmFontInfo *)0;
361     SimpleInputStream *	sisFile= (SimpleInputStream *)0;
362     SimpleInputStream *	sisFont= (SimpleInputStream *)0;
363 
364     sisFile= sioInFileioOpen( filename );
365     if  ( ! sisFile )
366 	{ XDEB(sisFile); goto ready;	}
367 
368     sisFont= sioInPfbOpen( sisFile );
369     if  ( ! sisFont )
370 	{ XDEB(sisFont); goto ready;	}
371 
372     afi= psFillAfiForPf( sisFont, adb, filename );
373     if  ( ! afi )
374 	{ XDEB(afi);	}
375 
376   ready:
377     if  ( sisFont )
378 	{ sioInClose( sisFont );	}
379     if  ( sisFile )
380 	{ sioInClose( sisFile );	}
381 
382     return afi;
383     }
384 
385 /************************************************************************/
386 /*									*/
387 /*  Find the font name for a TTF file. This is an expensive way. That	*/
388 /*  is not a problem as we rarely do this.				*/
389 /*									*/
390 /************************************************************************/
391 
psFillAfiForTtf(const MemoryBuffer * filename)392 static AfmFontInfo * psFillAfiForTtf(	const MemoryBuffer *	filename )
393     {
394     int			rval= 0;
395     AfmFontInfo *	afi= (AfmFontInfo *)0;
396     SimpleInputStream *	sisFile= (SimpleInputStream *)0;
397 
398     afi= (AfmFontInfo *)malloc( sizeof(AfmFontInfo) );
399     if  ( ! afi )
400 	{ XDEB(afi); rval= -1; goto ready;	}
401     psInitAfmFontInfo( afi );
402 
403     sisFile= sioInFileioOpen( filename );
404     if  ( ! sisFile )
405 	{ XDEB(sisFile); rval= -1; goto ready;	}
406 
407     if  ( psTtfToAfi( afi, filename, sisFile ) )
408 	{ LDEB(1); rval= -1; goto ready;	}
409 
410   ready:
411 
412     if  ( rval && afi )
413 	{
414 	psFreeAfmFontInfo( afi );
415 	afi= (AfmFontInfo *)0;
416 	}
417 
418     if  ( sisFile )
419 	{ sioInClose( sisFile );	}
420 
421     return afi;
422     }
423 
psFillAfiForAfm(int afmFlags,const MemoryBuffer * filename)424 static AfmFontInfo * psFillAfiForAfm(	int			afmFlags,
425 					const MemoryBuffer *	filename )
426     {
427     int			rval= 0;
428     AfmFontInfo *	afi= (AfmFontInfo *)0;
429     SimpleInputStream *	sisAfm= (SimpleInputStream *)0;
430 
431     afi= (AfmFontInfo *)malloc( sizeof(AfmFontInfo) );
432     if  ( ! afi )
433 	{ XDEB(afi); rval= -1; goto ready;	}
434     psInitAfmFontInfo( afi );
435 
436     sisAfm= sioInFileioOpen( filename );
437     if  ( ! sisAfm )
438 	{ XDEB(sisAfm); rval= -1; goto ready;	}
439 
440     if  ( psAfmReadAfm( sisAfm, afi, afmFlags ) )
441 	{ SDEB(utilMemoryBufferGetString(filename)); rval= -1; goto ready; }
442 
443   ready:
444 
445     if  ( rval && afi )
446 	{
447 	psFreeAfmFontInfo( afi );
448 	afi= (AfmFontInfo *)0;
449 	}
450 
451     if  ( sisAfm )
452 	{ sioInClose( sisAfm );	}
453 
454     return afi;
455     }
456 
psFontNameFromTtf(MemoryBuffer * fontname,const MemoryBuffer * filename)457 static int psFontNameFromTtf(	MemoryBuffer *		fontname,
458 				const MemoryBuffer *	filename )
459     {
460     int			rval= 0;
461     AfmFontInfo *	afi= (AfmFontInfo*)0;
462 
463     afi= psFillAfiForTtf( filename );
464     if  ( ! afi )
465 	{ XDEB(afi); goto ready;	}
466 
467     if  ( utilMemoryBufferSetString( fontname, afi->afiFontName ) )
468 	{ LDEB(1); rval= -1;	}
469 
470   ready:
471 
472     if  ( afi )
473 	{ psFreeAfmFontInfo( afi );	}
474 
475     return rval;
476     }
477 
psFontNameFromAfm(MemoryBuffer * fontname,MemoryBuffer * filename)478 static int psFontNameFromAfm(	MemoryBuffer *		fontname,
479 				MemoryBuffer *		filename )
480     {
481     int			rval= 0;
482     AfmFontInfo *	afi= (AfmFontInfo*)0;
483 
484     const int		afmFlags= PSflagDEFER_METRICS | PSflagIGNORE_KERNING;
485 
486     afi= psFillAfiForAfm( afmFlags, filename );
487     if  ( ! afi )
488 	{ SDEB(utilMemoryBufferGetString(filename)); rval= -1; goto ready; }
489 
490     if  ( utilMemoryBufferSetString( fontname, afi->afiFontName ) )
491 	{ LDEB(1); rval= -1;	}
492 
493     if  ( utilCopyMemoryBuffer( filename, &(afi->afiFontFileName) ) )
494 	{ LDEB(1); rval= -1;	}
495 
496   ready:
497 
498     if  ( afi )
499 	{ psFreeAfmFontInfo( afi );	}
500 
501     return rval;
502     }
503 
504 /************************************************************************/
505 /*									*/
506 /*  Scan a list of files and issue GhostScript compatible Fontmap lines	*/
507 /*  that can be added to a GhostScript Fontmap file. The purpose of	*/
508 /*  this function is to make the fonts known to GhostScript. This means	*/
509 /*  that we cannot use GhostScript yet.					*/
510 /*									*/
511 /************************************************************************/
512 
psFontmapForFiles(SimpleOutputStream * sosOut,int fileCount,const char * const * fileNames)513 int psFontmapForFiles(		SimpleOutputStream *	sosOut,
514 				int			fileCount,
515 				const char * const *	fileNames )
516     {
517     int			rval= 0;
518     int			f;
519 
520     const int		ignoreKerning= 1;
521 
522     AfmDirBuilder	adb;
523     MemoryBuffer	file;
524     MemoryBuffer	extension;
525     MemoryBuffer	fontname;
526 
527     utilInitMemoryBuffer( &file );
528     utilInitMemoryBuffer( &extension );
529     utilInitMemoryBuffer( &fontname );
530 
531     psInitAfmDirBuilder( &adb );
532 
533     if  ( psStartAfmDirBuilder( &adb, (PostScriptFontList *)0, ignoreKerning,
534 						(const MemoryBuffer *)0,
535 						(const MemoryBuffer *)0 ) )
536 	{ LDEB(1); rval= -1; goto ready;	}
537 
538     for ( f= 0; f < fileCount; f++ )
539 	{
540 	int	ret;
541 
542 	utilEmptyMemoryBuffer( &fontname );
543 
544 	ret= psGetNameExt( &file, &extension, &adb, fileNames[f] );
545 	if  ( ret )
546 	    { LDEB(ret); rval= -1; goto ready;	}
547 
548 	if  ( appFileGetFileExtension( &extension, &file ) < 0 )
549 	    { LDEB(1); rval= -1; goto ready;	}
550 	if  ( utilMemoryBufferIsEmpty( &extension ) )
551 	    { SDEB(fileNames[f]); rval= -1; continue;	}
552 
553 	if  ( utilMemoryBufferEqualsString( &extension, pfaExtension ) )
554 	    {
555 	    if  ( psFontNameFromPfa( &fontname, adb.adbFontNameProg, &file ) )
556 		{ SDEB(fileNames[f]); rval= -1;	}
557 	    }
558 
559 	if  ( utilMemoryBufferEqualsString( &extension, pfbExtension ) )
560 	    {
561 	    if  ( psFontNameFromPfb( &fontname, adb.adbFontNameProg, &file ) )
562 		{ SDEB(fileNames[f]); rval= -1;	}
563 	    }
564 
565 	if  ( utilMemoryBufferEqualsString( &extension, afmExtension ) )
566 	    {
567 	    if  ( psFontNameFromAfm( &fontname, &file ) )
568 		{ SDEB(fileNames[f]); rval= -1;	}
569 	    }
570 
571 	if  ( utilMemoryBufferEqualsString( &extension, ttfExtension ) ||
572 	      utilMemoryBufferEqualsString( &extension, TTFExtension ) )
573 	    {
574 	    if  ( psFontNameFromTtf( &fontname, &file ) )
575 		{ SDEB(fileNames[f]); rval= -1;	}
576 	    }
577 
578 	/*  Note that the afm reader potentially modifies the file name */
579 
580 	if  ( ! utilMemoryBufferIsEmpty( &fontname )	&&
581 	      ! utilMemoryBufferIsEmpty( &file )	)
582 	    {
583 	    sioOutPrintf( sosOut, "/%s (%s) ;\n",
584 		    utilMemoryBufferGetString( &fontname ),
585 		    utilMemoryBufferGetString( &file ) );
586 	    }
587 	}
588 
589   ready:
590 
591     psCleanAfmDirBuilder( &adb );
592 
593     utilCleanMemoryBuffer( &file );
594     utilCleanMemoryBuffer( &extension );
595     utilCleanMemoryBuffer( &fontname );
596 
597     return rval;
598     }
599 
600 /************************************************************************/
601 
psSaveAfmFile(AfmFontInfo * afi,AfmDirBuilder * adb)602 static int psSaveAfmFile(	AfmFontInfo *		afi,
603 				AfmDirBuilder *		adb )
604     {
605     int				rval= 0;
606     const int			relativeIsFile= 0;
607     unsigned char *		s;
608 
609     MemoryBuffer		relative;
610 
611     utilInitMemoryBuffer( &relative );
612 
613     if  ( utilMemoryBufferSetString( &relative, afi->afiFontName ) )
614 	{ LDEB(1); rval= -1; goto ready;	}
615     if  ( utilMemoryBufferAppendBytes( &relative,
616 				    (const unsigned char *)".afm", 4 ) )
617 	{ LDEB(4); rval= -1; goto ready;	}
618 
619     s= relative.mbBytes;
620     while( *s )
621 	{
622 	if  ( isspace( *s ) )
623 	    { *s= '-';	}
624 	s++;
625 	}
626     if  ( appAbsoluteName( &(afi->afiAfmFileName), &relative,
627 				relativeIsFile, &(adb->adbAfmDirectory) ) < 0 )
628 	{ LDEB(1); rval= -1; goto ready;	}
629 
630     if  ( psPostScriptFontListAddInfo( adb->adbPostScriptFontList, afi ) )
631 	{ LDEB(1); rval= -1; goto ready;	}
632 
633   ready:
634 
635     utilCleanMemoryBuffer( &relative );
636 
637     return rval;
638     }
639 
psAfmFromPfaFile(const MemoryBuffer * filename,void * through)640 static int psAfmFromPfaFile(	const MemoryBuffer *	filename,
641 				void *			through )
642     {
643     int			rval= 0;
644     AfmDirBuilder *	adb= (AfmDirBuilder *)through;
645     AfmFontInfo *	afi= (AfmFontInfo *)0;
646 
647     /* Broken symlinks */
648     if  ( appTestFileExists( filename ) )
649 	{ goto ready;	}
650 
651     afi= psFillAfiForPfa( adb, filename );
652     if  ( ! afi )
653 	{ XDEB(afi); goto ready;	} /* do not fail */
654 
655     if  ( psSaveAfmFile( afi, adb ) )
656 	{ LDEB(1); rval= -1; goto ready;	}
657 
658     afi= (AfmFontInfo *)0; /* steal */
659 
660   ready:
661 
662     if  ( afi )
663 	{ psFreeAfmFontInfo( afi );	}
664 
665     return rval;
666     }
667 
psAfmFromPfbFile(const MemoryBuffer * filename,void * through)668 static int psAfmFromPfbFile(	const MemoryBuffer *	filename,
669 				void *			through )
670     {
671     int			rval= 0;
672     AfmDirBuilder *	adb= (AfmDirBuilder *)through;
673     AfmFontInfo *	afi= (AfmFontInfo *)0;
674 
675     /* Broken symlinks */
676     if  ( appTestFileExists( filename ) )
677 	{ goto ready;	}
678 
679     afi= psFillAfiForPfb( adb, filename );
680     if  ( ! afi )
681 	{ XDEB(afi); goto ready;	} /* do not fail */
682 
683     if  ( psSaveAfmFile( afi, adb ) )
684 	{ LDEB(1); rval= -1; goto ready;	}
685 
686     afi= (AfmFontInfo *)0; /* steal */
687 
688   ready:
689 
690     if  ( afi )
691 	{ psFreeAfmFontInfo( afi );	}
692 
693     return rval;
694     }
695 
psAfmFromTtfFile(const MemoryBuffer * filename,void * through)696 static int psAfmFromTtfFile(	const MemoryBuffer *	filename,
697 				void *			through )
698     {
699     int			rval= 0;
700     AfmDirBuilder *	adb= (AfmDirBuilder *)through;
701 
702     AfmFontInfo *	afi= (AfmFontInfo *)0;
703 
704     /* Broken symlinks */
705     if  ( appTestFileExists( filename ) )
706 	{ goto ready;	}
707 
708     afi= psFillAfiForTtf( filename );
709     if  ( ! afi )
710 	{ XDEB(afi); goto ready;	} /* do not fail */
711 
712     if  ( psSaveAfmFile( afi, adb ) )
713 	{ LDEB(1); rval= -1; goto ready;	}
714 
715     afi= (AfmFontInfo *)0;
716 
717   ready:
718 
719     if  ( afi )
720 	{ psFreeAfmFontInfo( afi );	}
721 
722     return rval;
723     }
724 
psAfmFromAfmFile(const MemoryBuffer * filename,void * through)725 static int psAfmFromAfmFile(	const MemoryBuffer *	filename,
726 				void *			through )
727     {
728     int			rval= 0;
729     AfmDirBuilder *	adb= (AfmDirBuilder *)through;
730 
731     AfmFontInfo *	afi= (AfmFontInfo *)0;
732 
733     /* Broken symlinks */
734     if  ( appTestFileExists( filename ) )
735 	{ goto ready;	}
736 
737     afi= psFillAfiForAfm( adb->adbAfmFlags, filename );
738     if  ( ! afi )
739 	{ LDEB(1); goto ready;	} /* do not fail */
740 
741     if  ( psSaveAfmFile( afi, adb ) )
742 	{ LDEB(1); rval= -1; goto ready;	}
743 
744     afi= (AfmFontInfo *)0;
745 
746   ready:
747 
748     if  ( afi )
749 	{ psFreeAfmFontInfo( afi );	}
750 
751     return rval;
752     }
753 
754 /************************************************************************/
755 /*									*/
756 /*  Build an afm directory: Include all fonts that are on the		*/
757 /*  GhostScript library path.						*/
758 /*									*/
759 /************************************************************************/
760 
psGSLibAfmDirectory(PostScriptFontList * psfl,int ignoreKerning,const MemoryBuffer * afmDirectory,const MemoryBuffer * psDirectory)761 int psGSLibAfmDirectory(	PostScriptFontList *	psfl,
762 				int			ignoreKerning,
763 				const MemoryBuffer *	afmDirectory,
764 				const MemoryBuffer *	psDirectory )
765     {
766     int				rval= 0;
767     SimpleInputStream *		sisCmd= (SimpleInputStream *)0;
768 
769     AfmDirBuilder		adb;
770     MemoryBuffer		dir;
771     MemoryBuffer		libCommand;
772 
773     char			scratch[500+1];
774 
775     const char *		libBase= "gs -q %s/gslibpath.ps -c quit";
776 
777     utilInitMemoryBuffer( &dir );
778     utilInitMemoryBuffer( &libCommand );
779 
780     psInitAfmDirBuilder( &adb );
781 
782     if  ( psStartAfmDirBuilder( &adb, psfl, ignoreKerning,
783 					    afmDirectory, psDirectory ) )
784 	{ LDEB(1); rval= -1; goto ready;	}
785 
786     utilMemoryBufferPrintf( &libCommand, libBase,
787 				utilMemoryBufferGetString( psDirectory ) );
788 
789     sisCmd= sioInPipeOpen( &libCommand );
790     if  ( ! sisCmd )
791 	{ SXDEB(libBase,sisCmd); rval= -1; goto ready;	}
792 
793     setlocale( LC_NUMERIC, "C" );
794 
795     while( sioInGetString( scratch, sizeof(scratch)- 1, sisCmd ) )
796 	{
797 	int		l;
798 
799 	scratch[sizeof(scratch)- 1]= '\0';
800 	l= strlen( scratch );
801 	if  ( l < 2 )
802 	    { LDEB(l); rval= -1; goto ready;	}
803 	if  ( scratch[l-1] != '\n' )
804 	    { SDEB(scratch); rval= -1; goto ready;	}
805 	scratch[l-1]= '\0';
806 
807 	if  ( utilMemoryBufferSetString( &dir, scratch ) )
808 	    { LDEB(1); rval= -1; goto ready;	}
809 
810 	if  ( ! appFileNameIsAbsolute( scratch ) )
811 	    { continue;	}
812 	if  ( appTestDirectory( &dir ) )
813 	    { continue;	}
814 
815 	l= appForAllFiles( &dir, pfaExtension, &adb, psAfmFromPfaFile );
816 	if  ( l )
817 	    { SDEB(scratch); rval= -1;	}
818 	l= appForAllFiles( &dir, pfbExtension, &adb, psAfmFromPfbFile );
819 	if  ( l )
820 	    { SDEB(scratch); rval= -1;	}
821 	l= appForAllFiles( &dir, ttfExtension, &adb, psAfmFromTtfFile );
822 	if  ( l )
823 	    { SDEB(scratch); rval= -1;	}
824 	l= appForAllFiles( &dir, TTFExtension, &adb, psAfmFromTtfFile );
825 	if  ( l )
826 	    { SDEB(scratch); rval= -1;	}
827 	}
828 
829   ready:
830 
831     setlocale( LC_NUMERIC, "" );
832 
833     if  ( sisCmd )
834 	{ sioInClose( sisCmd );	}
835 
836     psCleanAfmDirBuilder( &adb );
837 
838     utilCleanMemoryBuffer( &dir );
839     utilCleanMemoryBuffer( &libCommand );
840 
841     return rval;
842     }
843 
844 /************************************************************************/
845 /*									*/
846 /*  Build afm directory files for a list of font files.			*/
847 /*									*/
848 /************************************************************************/
849 
psAfmForFontFiles(PostScriptFontList * psfl,int ignoreKerning,int fileCount,char ** fileNames,const MemoryBuffer * afmDirectory,const MemoryBuffer * psDirectory)850 int psAfmForFontFiles(	PostScriptFontList *	psfl,
851 			int			ignoreKerning,
852 			int			fileCount,
853 			char **			fileNames,
854 			const MemoryBuffer *	afmDirectory,
855 			const MemoryBuffer *	psDirectory )
856     {
857     int				rval= 0;
858     int				f;
859 
860 
861     AfmDirBuilder		adb;
862     MemoryBuffer		file;
863     MemoryBuffer		extension;
864 
865     utilInitMemoryBuffer( &file );
866     utilInitMemoryBuffer( &extension );
867 
868     psInitAfmDirBuilder( &adb );
869 
870     if  ( psStartAfmDirBuilder( &adb, psfl, ignoreKerning,
871 						afmDirectory, psDirectory ) )
872 	{ LDEB(1); rval= -1; goto ready;	}
873 
874     setlocale( LC_NUMERIC, "C" );
875 
876     for ( f= 0; f < fileCount; f++ )
877 	{
878 	int	ret;
879 
880 	ret= psGetNameExt( &file, &extension, &adb, fileNames[f] );
881 	if  ( ret < 0 )
882 	    { LDEB(ret); rval= -1; goto ready;	}
883 	if  ( ret > 0 )
884 	    { LDEB(ret); rval= -1; continue;	}
885 
886 	if  ( utilMemoryBufferEqualsString( &extension, pfaExtension ) )
887 	    {
888 	    if  ( psAfmFromPfaFile( &file, &adb ) )
889 		{ SDEB(fileNames[f]); rval= -1;	}
890 
891 	    continue;
892 	    }
893 
894 	if  ( utilMemoryBufferEqualsString( &extension, pfbExtension ) )
895 	    {
896 	    if  ( psAfmFromPfbFile( &file, &adb ) )
897 		{ SDEB(fileNames[f]); rval= -1;	}
898 
899 	    continue;
900 	    }
901 
902 	if  ( utilMemoryBufferEqualsString( &extension, afmExtension ) )
903 	    {
904 	    if  ( psAfmFromAfmFile( &file, &adb ) )
905 		{ SDEB(fileNames[f]); rval= -1;	}
906 
907 	    continue;
908 	    }
909 
910 	if  ( utilMemoryBufferEqualsString( &extension, ttfExtension ) ||
911 	      utilMemoryBufferEqualsString( &extension, TTFExtension ) )
912 	    {
913 	    if  ( psAfmFromTtfFile( &file, &adb ) )
914 		{ SDEB(fileNames[f]); rval= -1;	}
915 
916 	    continue;
917 	    }
918 
919 	SDEB(fileNames[f]); rval= -1; continue;
920 	}
921 
922   ready:
923 
924     setlocale( LC_NUMERIC, "" );
925 
926     psCleanAfmDirBuilder( &adb );
927 
928     utilCleanMemoryBuffer( &file );
929     utilCleanMemoryBuffer( &extension );
930 
931     return rval;
932     }
933 
psAfmToGSFontmap(SimpleOutputStream * sosFontDir,const char * afmFileName)934 int psAfmToGSFontmap(	SimpleOutputStream *	sosFontDir,
935 			const char *		afmFileName )
936     {
937     return psFontmapForFiles( sosFontDir, 1, &(afmFileName) );
938     }
939 
psFontFileToAfm(SimpleOutputStream * sosAfm,int omitKernPairs,const char * fontFileName,const MemoryBuffer * psDirectory)940 int psFontFileToAfm(	SimpleOutputStream *	sosAfm,
941 			int			omitKernPairs,
942 			const char *		fontFileName,
943 			const MemoryBuffer *	psDirectory )
944     {
945     int			rval= 0;
946     int			ret;
947     AfmFontInfo *	afi= (AfmFontInfo *)0;
948 
949     AfmDirBuilder	adb;
950     MemoryBuffer	file;
951     MemoryBuffer	extension;
952 
953     utilInitMemoryBuffer( &file );
954     utilInitMemoryBuffer( &extension );
955 
956     psInitAfmDirBuilder( &adb );
957 
958     if  ( psStartAfmDirBuilder( &adb, (PostScriptFontList *)0, omitKernPairs,
959 				    (const MemoryBuffer *)0, psDirectory ) )
960 	{ LDEB(1); rval= -1; goto ready;	}
961 
962     setlocale( LC_NUMERIC, "C" );
963 
964     ret= psGetNameExt( &file, &extension, &adb, fontFileName );
965     if  ( ret < 0 )
966 	{ LDEB(ret); rval= -1; goto ready;	}
967     if  ( ret > 0 )
968 	{ LDEB(ret); rval= -1; goto ready;	}
969 
970     if  ( utilMemoryBufferEqualsString( &extension, pfaExtension ) )
971 	{
972 	afi= psFillAfiForPfa( &adb, &file );
973 	if  ( ! afi )
974 	    { SXDEB(fontFileName,afi); rval= -1; goto ready;	}
975 	}
976 
977     if  ( utilMemoryBufferEqualsString( &extension, pfbExtension ) )
978 	{
979 	afi= psFillAfiForPfb( &adb, &file );
980 	if  ( ! afi )
981 	    { SXDEB(fontFileName,afi); rval= -1; goto ready;	}
982 	}
983 
984     if  ( utilMemoryBufferEqualsString( &extension, afmExtension ) )
985 	{
986 	afi= psFillAfiForAfm( adb.adbAfmFlags, &file );
987 	if  ( ! afi )
988 	    { SXDEB(fontFileName,afi); rval= -1; goto ready;	}
989 	}
990 
991     if  ( utilMemoryBufferEqualsString( &extension, ttfExtension ) ||
992 	  utilMemoryBufferEqualsString( &extension, TTFExtension ) )
993 	{
994 	afi= psFillAfiForTtf( &file );
995 	if  ( ! afi )
996 	    { SXDEB(fontFileName,afi); rval= -1; goto ready;	}
997 	}
998 
999     if  ( ! afi )
1000 	{ XDEB(afi); rval= -1; goto ready;	}
1001 
1002     if  ( psWriteAfmFile( sosAfm, adb.adbAfmFlags, afi ) )
1003 	{ LDEB(1); rval= -1; goto ready;	}
1004 
1005   ready:
1006 
1007     setlocale( LC_NUMERIC, "" );
1008 
1009     psCleanAfmDirBuilder( &adb );
1010 
1011     utilCleanMemoryBuffer( &file );
1012     utilCleanMemoryBuffer( &extension );
1013 
1014     if  ( afi )
1015 	{ psFreeAfmFontInfo( afi );	}
1016 
1017     return rval;
1018     }
1019