1 /*
2  *  ttf2pfb.c -- TrueType to PostScript Type 1 Font converter.
3  *
4  * Author: Chun-Yu Lee <d791013@ce.ntu.edu.tw>
5  * Maintainer: Werner Lemberg <wl@gnu.org>
6  *
7  * The generated output is in a raw Type 1 Font format. An encoder
8  * (e.g. t1asm or t1binary) is needed to convert it into PFA or PFB format.
9  *
10  * This program was adapted from the ntu2cjk package (which was part of the
11  * LaTeX2e CJK package (by Werner Lemberg <wl@gnu.org>)).
12  *
13  *
14  * Modified by Joachim H. Kaiser <jhk@cmpnetmail.com> to include real glyph
15  * names and other font infos (see PS_Head function).
16  * The test programs of the FreeType distribution have been heavily used as
17  * templates.
18  *
19  */
20 
21 /*
22  * Requirements:
23  *   - the FreeType library.
24  *   - t1asm or a similar converter if PFA or PFB format is required.
25  *   - getafm or a similar program if AFM font metrics are required.
26  *   - afm2tfm or a similar program if TFM font metrics are required.
27  *   - for compact fonts: the CJK package for typesetting LaTeX documents.
28  *   - dvips 5.66 or higher if self-contained PostScript document
29  *     outputs with partially downloaded fonts are required. Note that
30  *     the partial download code in dvips is still buggy, causing strange
31  *     error messages during loading of the created PS fonts.
32  *   - Ghostscript 3.33 or newer (this is optional).
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <stdarg.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <time.h>
41 #ifdef TM_IN_SYS_TIME
42 #include <sys/time.h>
43 #endif
44 #include <ctype.h>
45 
46 #include "freetype.h"
47 #include "extend/ftxpost.h"     /* we are in the FreeType package tree */
48 
49 char rcsid[] = "$Id: ttf2pfb.c,v 1.13 1999/08/20 13:14:26 werner Exp $";
50 
51 
52 #define PID_UNICODE 3
53 #define EID_UNICODE 1
54 #define PID_SJIS    3
55 #define EID_SJIS    2
56 #define PID_GB      3
57 #define EID_GB      3
58 #define PID_BIG5    3
59 #define EID_BIG5    4
60 #define PID_KS      3                     /* KS is also called Wansung */
61 #define EID_KS      5
62 #define PID_JOHAB   3
63 #define EID_JOHAB   6
64 
65 /* Set default values */
66 #ifndef DEFAULT_PLATFORM_ID
67 #define DEFAULT_PLATFORM_ID PID_UNICODE   /* MS platform */
68 #endif
69 
70 #ifndef DEFAULT_ENCODING_ID
71 #define DEFAULT_ENCODING_ID EID_UNICODE
72 #endif
73 
74 /* The possible values for the `force_enc' variable. */
75 typedef enum enc_type_
76 {
77   GB = 1, Big5, JIS, KS, Johab, SJIS, X
78 } enc_type;
79 
80 /* A variable to enforce a certain font encoding (if > 0). */
81 enc_type force_enc = 0;
82 
83 
84 #ifndef TRUE
85 #define TRUE  1
86 #endif
87 
88 #ifndef FALSE
89 #define FALSE 0
90 #endif
91 
92 #ifndef FAILURE
93 #define FAILURE -1
94 #endif
95 
96 
97 #define LINELEN 40  /* max # of columns of code range file */
98 #define NAMELEN 80  /* max length of name used from LookUp */
99 
100 
101 /*
102  * Flags and globals
103  */
104 
105 int   verbose   = FALSE;  /* messages should be printed or not. */
106 int   compact   = FALSE;  /* generate compact font? */
107 int   keep      = FALSE;  /* keep output font in case of error? */
108 int   mapping   = FALSE;  /* use encoding file as mapping? */
109 float fontShift = 0;
110 
111 #ifndef UShort
112 typedef unsigned short UShort;
113 #endif
114 #ifndef UChar
115 typedef unsigned char  UChar;
116 #endif
117 
118 #define TT_Flag_On_Curve 1
119 
120 /* default platform and encoding ID's. */
121 int pid = DEFAULT_PLATFORM_ID;
122 int eid = DEFAULT_ENCODING_ID;
123 
124 
125 char* prog;             /* program name */
126 
127 
128 /* for orthogonality with fprintf */
129 #define Fputs(_string_) fprintf(out, "%s\n", _string_)
130 
131 
132 /* Postscript font related defines and functions */
133 TT_F26Dot6 lastpsx, lastpsy;
134 
135 #define Coord(x) (int)(x)
136 #define PS_LastPt(x, y) lastpsx = x; lastpsy = y
137 #define PS_Moveto(x, y) \
138           fprintf(out, "%d %d rmoveto\n", \
139                   Coord(x - lastpsx), Coord(y - lastpsy)); \
140           PS_LastPt(x, y)
141 #define PS_Lineto(x, y) \
142           fprintf(out, "%d %d rlineto\n", \
143                   Coord(x - lastpsx), Coord(y - lastpsy)); \
144           PS_LastPt(x, y)
145 
146 
147 /*
148  * Freetype globals.
149  */
150 
151 TT_Engine   engine;
152 TT_Face     face;
153 TT_Instance instance;
154 TT_Glyph    glyph;
155 TT_CharMap  cmap;
156 TT_Error    error;
157 TT_Post     post;
158 
159 TT_Outline         outline;
160 TT_Glyph_Metrics   metrics;
161 TT_Face_Properties properties;
162 
163 
164 /*
165  * Data structures defined for encoding vectors
166  */
167 
168 /*
169  * A code range file for the encoding vector of a font contains code
170  * range pairs, each pair a line. The values for the begin and end of the
171  * ranges are separated by ` - '. Note that the spaces before and after the
172  * minus sign are significant. The possible syntax is as follows:
173  *
174  * (Note that code ranges must appear in ascending order.)
175  *
176  * 1. Absolute range, i.e., the code is at least a two-byte number, e.g.:
177  *
178  *    0xA140 - 0xA17E
179  *    41280  - 41342
180  *    0xE00000 - 0xE000FF
181  *
182  * The first two lines represent the same range.
183  *
184  * 2. Relative range, i.e., the code is a one-byte number. If the line ends
185  * with a colon `:', it designates the high byte(s) range, otherwise the
186  * low byte range. If there is no high byte(s) range declared before the low
187  * byte range, the last defined high byte(s) range or `0x00 - 0x00:' will be
188  * used. e.g.:
189  *
190  *    0xA1 - 0xFE:
191  *      0x40 - 0x7E
192  *      0xA1 - 0xFE
193  *
194  * which is Big-5 Encoding.
195  *
196  * 3. Single code. Similar to absolute or relative range but the second
197  * number of the range is the same as the first number. E.g.:
198  *
199  *    0xA141  ==  0xA141 - 0xA141
200  *    0xA1:   ==  0xA1 - 0xA1:
201  *    0xA1    ==  0xA1 - 0xA1
202  *
203  * 4. If the high byte range is declared and there is no low byte range
204  * declared consecutively, the assumed low byte range is `0x00 - 0xFF'.
205  *
206  * 5. Comment line. A line starting with a hash mark `#' followed by any
207  * characters up to the end of the line is ignored. Blank lines are also
208  * discarded.
209  */
210 
211 typedef struct _EVHigh
212 {
213   UShort start, end;
214 } EVHigh;
215 
216 typedef struct _EVLow
217 {
218   UChar start, end;
219 } EVLow;
220 
221 typedef struct _EVcRange
222 {
223   EVHigh high;
224   UShort numLowRanges;
225   EVLow* low;
226 } EVcRange;
227 
228 typedef struct _EncVec
229 {
230   UShort    numCodeRanges;
231   EVcRange* codeRange;
232 } EncVec;
233 
234 /* Select encoding vector with respect to pid and eid */
235 EncVec* eVecMap[5][10];
236 
237 /* Select encoding vector with respect to force_enc */
238 EncVec* eVecMap_force[10];
239 
240 
241 /*************/
242 /* Functions */
243 /*************/
244 
245 
246 void
mesg(const char * msg,...)247 mesg(const char *msg, ...)
248 {
249   va_list ap;
250 
251   va_start(ap, msg);
252   vfprintf(stderr, msg, ap);
253   va_end(ap);
254 }
255 
256 
257 /*
258  * Usage.
259  */
260 
261 void
Usage(int eval)262 Usage(int eval)
263 {
264 #ifdef DEBUG
265   mesg("Usage: %s [-h][-v][-c][-k][-m][-d charcode][-l][-ng][-nc]\n", prog);
266 #else
267   mesg("Usage: %s [-h][-v][-c][-k][-m]\n", prog);
268 #endif
269   mesg("\t[-pid id] [-eid id] [-force enc] [-enc file]\n");
270   mesg("\t[-plane pl] [-f fname] [-uid id] [-s shift]\n");
271   mesg("\t[-o output] [-ttf font.ttf | font.ttf]\n");
272   mesg("-h\t\tThis message.\n");
273   mesg("-v\t\tPrint messages during conversion.\n");
274   mesg("-c\t\tCompact font");
275   mesg(" (256 chars per font; useful for the CJK package).\n");
276   mesg("-k\t\tKeep output file in case of error.\n");
277   mesg("-m\t\tUse encoding file as mapping file.\n");
278 #ifdef DEBUG
279   mesg("-d charcode\tDebug CharString for the given character code.\n");
280   mesg("-l\t\tDisplay point labels.\n");
281   mesg("-ng\t\tDo not show glyph outline.\n");
282   mesg("-nc\t\tDo not show control paths.\n");
283 #endif
284   mesg("-pid id\t\tSet the platform ID [%d].\n", DEFAULT_PLATFORM_ID);
285   mesg("-eid id\t\tSet the encoding ID [%d].\n", DEFAULT_ENCODING_ID);
286   mesg("\t\t(Use a strange pid,eid pair to list all possible pid,eid)\n");
287   mesg("-force enc\tForce a certain encoding [none].\n");
288   mesg("\t\t(Possible values are `GB', `JIS', `KS', `SJIS', and `X').\n");
289   mesg("-enc file\tFile contains code ranges [none].\n");
290   mesg("-plane pl\tA single font plane [0x0].\n");
291   mesg("-f fname\tFont name [UNKNOWN].\n");
292   mesg("-uid id\t\tUnique font ID, for private fonts 4000000-4999999 [4999999].\n");
293   mesg("-s shift\tY-offset factor [%5.3f].\n", fontShift);
294   mesg("-o outfile\tSet the output filename [stdout].\n");
295   mesg("-ttf ttfpath\tThe TTF font pathname.\n");
296 
297   exit(eval);
298 }
299 
300 
301 void
fatal(const char * msg,...)302 fatal(const char *msg,
303       ...)
304 {
305   va_list ap;
306 
307   va_start(ap, msg);
308   fprintf(stderr, "%s: ", prog);
309   vfprintf(stderr, msg, ap);
310   fprintf(stderr, "\n");
311   va_end(ap);
312   exit(FAILURE);
313 }
314 
315 
316 void
fatal_error(const char * msg,...)317 fatal_error(const char *msg,
318             ...)
319 {
320   va_list ap;
321 
322   va_start(ap, msg);
323   fprintf(stderr, "%s: Error code 0x%04lx: ", prog, error);
324   vfprintf(stderr, msg, ap);
325   fprintf(stderr, "\n");
326   va_end(ap);
327   exit(FAILURE);
328 }
329 
330 
331 /*
332  * Reallocate a pointer.
333  */
334 
335 void *
re_alloc(void * ptr,size_t size,char * sub)336 re_alloc(void* ptr,
337          size_t size,
338          char* sub)
339 {
340   register void* value = realloc(ptr, size);
341 
342   if (value == NULL)
343     fatal("%s: Virtual memory exhausted", sub);
344   return value;
345 }
346 
347 
348 /*
349  * We have to introduce the `dummy' integer to assure correct handling of
350  * the stack.  Using `UShort' as the first parameter may fail in case
351  * this type is promoted to a different type (as happens e.g. under
352  * emx for DOS).
353  */
354 
355 EncVec*
Alloc_EncVec(int dummy,...)356 Alloc_EncVec(int dummy,
357              ...)
358 {
359   va_list   vp;
360   EncVec*   encVec = NULL;
361   EVcRange* cRange = NULL;
362   EVLow*    evLow  = NULL;
363   UShort    numCR, numLows;
364   int       i, j;
365 
366   va_start(vp, dummy);
367   numCR = va_arg(vp, UShort);
368 
369   encVec = re_alloc(encVec, 1 * sizeof (EncVec), "Alloc_EncVec");
370   encVec->numCodeRanges = numCR;
371 
372   cRange = re_alloc(cRange, numCR * sizeof (EVcRange), "Alloc_EncVec");
373   for (i = 0; i < numCR; i++)
374   {
375     (cRange + i)->high.start   = va_arg(vp, UShort);
376     (cRange + i)->high.end     = va_arg(vp, UShort);
377     (cRange + i)->numLowRanges = numLows = va_arg(vp, UShort);
378     evLow = NULL;
379     evLow = re_alloc(evLow, numLows * sizeof (EVLow), "Alloc_EncVec");
380     for (j = 0; j < numLows; j++)
381     {
382       (evLow + j)->start = va_arg(vp, UChar);
383       (evLow + j)->end   = va_arg(vp, UChar);
384     }
385     (cRange + i)->low = evLow;
386   }
387   encVec->codeRange = cRange;
388 
389   va_end(vp);
390   return encVec;
391 }
392 
393 
394 void
Known_Encodings(void)395 Known_Encodings(void)
396 {
397   EncVec* encVec;
398 
399   /* Big-5 encoding */
400   encVec = Alloc_EncVec(1,
401                         1, 0xA1, 0xFE,
402                              2, 0x40, 0x7E, 0xA1, 0xFE);
403   eVecMap[PID_BIG5][EID_BIG5] = encVec;
404   eVecMap_force[Big5] = encVec;
405 
406   /* GB encoding */
407   encVec = Alloc_EncVec(2,
408                         1, 0xA1, 0xF7,
409                              1, 0xA1, 0xFE);
410   eVecMap[PID_GB][EID_GB] = encVec;
411   eVecMap_force[GB] = encVec;
412 
413   /* KS encoding */
414   encVec = Alloc_EncVec(3,
415                         1, 0xA1, 0xFE,
416                              1, 0xA1, 0xFE);
417   eVecMap[PID_KS][EID_KS] = encVec;
418   eVecMap_force[KS] = encVec;
419 
420   /* Johab encoding */
421   encVec = Alloc_EncVec(4,
422                         3, 0x84, 0xD3,
423                              2, 0x41, 0x7E,
424                                 0x81, 0xFE,
425                            0xD8, 0xDE,
426                              2, 0x31, 0x7E,
427                                 0x91, 0xFE,
428                            0xE0, 0xF9,
429                              2, 0x31, 0x7E,
430                                 0x91, 0xFE);
431   eVecMap[PID_JOHAB][EID_JOHAB] = encVec;
432   eVecMap_force[Johab] = encVec;
433 
434   /* JIS encoding */
435   encVec = Alloc_EncVec(5,
436                         1, 0xA1, 0xF4,
437                              1, 0xA1, 0xFE);
438   eVecMap_force[JIS] = encVec;
439   eVecMap_force[X] = encVec;     /* will be internally translated to SJIS */
440 
441   /* Unicode encoding */
442   encVec = Alloc_EncVec(6,
443                         1, 0x00, 0xFF,
444                              1, 0x00, 0xFF);
445   eVecMap[PID_UNICODE][EID_UNICODE] = encVec;
446 
447   /* SJIS encoding */
448   encVec = Alloc_EncVec(7,
449                         3, 0x0, 0x0,
450                              1, 0xA1, 0xDF,
451                            0x81, 0x9F,
452                              2, 0x40, 0x7E,
453                                 0x80, 0xFC,
454                            0xE0, 0xEF,
455                              2, 0x40, 0x7E,
456                                 0x80, 0xFC);
457   eVecMap[PID_SJIS][EID_SJIS] = encVec;
458   eVecMap_force[SJIS] = encVec;
459 }
460 
461 
462 /*
463  * Convert JIS to SJIS encoding.
464  */
465 
466 UShort
JIS_to_SJIS(UShort code)467 JIS_to_SJIS(UShort code)
468 {
469   UShort index;
470   UShort cc0 = (code >> 8) & 0xFF;
471   UShort cc1 = code & 0xFF;
472 
473   index = (cc0 - 0xa1) * (0xfe - 0xa1 + 1) + (cc1 - 0xa1);
474   cc0 = index / ((0x7e - 0x40 + 1) + (0xfc - 0x80 + 1));
475   cc1 = index % ((0x7e - 0x40 + 1) + (0xfc - 0x80 + 1));
476   if (cc0 < (0x9f - 0x81 + 1))
477     cc0 += 0x81;
478   else
479     cc0 += 0xe0 - (0x9f - 0x81 + 1);
480   if (cc1 < (0x7e - 0x40 + 1))
481     cc1 += 0x40;
482   else
483     cc1 += 0x80 - (0x7E - 0x40 + 1);
484 
485   return (cc0 << 8) + cc1;
486 }
487 
488 
489 /*
490  * Open TTF file and select cmap.
491  */
492 
493 int
Init_Font_Engine(char * infile)494 Init_Font_Engine(char* infile)
495 {
496   UShort cmapindex, platformID, encodingID, num_cmap;
497 
498   if (verbose)
499     printf("Initializing TrueType font engine...\n");
500 
501   /* initialization of the FreeType engine */
502   error = TT_Init_FreeType(&engine);
503   if (error)
504     fatal_error("Couldn't initialize FreeType engine");
505 
506   /* initialization of the post extension */
507   error = TT_Init_Post_Extension(engine);
508   if (error)
509     fatal_error("Couldn't initialize the post extension");
510 
511   /* open the input file */
512   error = TT_Open_Face(engine, infile, &face);
513   if (error)
514     fatal_error("Unable to open input file `%s'", infile);
515 
516   /* load full post table */
517   error = TT_Load_PS_Names(face, &post);
518   if (error)
519     fatal_error("Unable to load post table");
520 
521   /* get face properties */
522   TT_Get_Face_Properties(face, &properties);
523 
524   /* Load the instance. */
525   error = TT_New_Instance(face, &instance);
526   if (error)
527     fatal_error("Couldn't create instance");
528 
529   error = TT_Set_Instance_Resolutions(instance, 600, 600);
530   if (error)
531     fatal_error("Error setting resolutions");
532 
533   error = TT_Set_Instance_CharSize(instance, 120 * 64);
534   if (error)
535     fatal_error("Error setting character size");
536 
537   error = TT_New_Glyph(face, &glyph);
538   if (error)
539     fatal_error("Couldn't create new glyph");
540 
541   /* Get the requested cmap. */
542   num_cmap = TT_Get_CharMap_Count(face);
543   for (cmapindex = 0; cmapindex < num_cmap; cmapindex++)
544   {
545     TT_Get_CharMap_ID(face, cmapindex, &platformID, &encodingID);
546     if (platformID == pid && encodingID == eid)
547       break;
548   }
549   if (cmapindex == num_cmap)
550   {
551     mesg("Possible platform and encoding ID pairs:");
552     for (cmapindex = 0; cmapindex < num_cmap; cmapindex++)
553     {
554       TT_Get_CharMap_ID(face, cmapindex, &platformID, &encodingID);
555       mesg("  (%d, %d)", platformID, encodingID);
556     }
557     mesg ("\n");
558     fatal("No character map for given platform %d, encoding %d", pid, eid);
559   }
560 
561   /* malloc for glyph data */
562   error = TT_Get_CharMap(face, cmapindex, &cmap);
563   if (error)
564     fatal_error("Cannot load cmap");
565 
566   return TRUE;
567 }
568 
569 
570 /*
571  * Get font infos: name, version, copyright.
572  */
573 
574 char*
LookUp_Name(int index)575 LookUp_Name(int index)
576 {
577   UShort platform, encoding, language, id;
578   char*  string;
579   UShort string_len;
580   UShort i, n;
581 
582   n = properties.num_Names;
583 
584   for (i = 0; i < n; i++)
585   {
586     TT_Get_Name_ID(face, i, &platform, &encoding, &language, &id);
587     TT_Get_Name_String(face, i, &string, &string_len);
588 
589     if (id == index)
590       break;
591   }
592   i = (string_len > NAMELEN) ? NAMELEN : string_len;
593   string[i] = '\0';
594   return string;
595 }
596 
597 
598 /*
599  * Load a glyph's outline and metrics.
600  */
601 
602 int
LoadTrueTypeChar(int idx)603 LoadTrueTypeChar(int idx)
604 {
605   TT_Matrix scale = {(1 << 16) / 64, 0, 0, (1 << 16) / 64};
606 
607   error = TT_Load_Glyph(instance, glyph, idx, TTLOAD_DEFAULT);
608   if (error)
609     fatal_error("Load glyph");
610 
611   error = TT_Get_Glyph_Outline(glyph, &outline);
612   if (error)
613     fatal_error("Get glyph outlines");
614 
615   TT_Transform_Outline(&outline, &scale);
616 
617   error = TT_Get_Glyph_Metrics(glyph, &metrics);
618   if (error)
619     fatal_error("Get glyph_metrics");
620 
621   return TRUE;
622 }
623 
624 
625 /*
626  * Get PS name of a glyph.
627  */
628 
629 char*
PS_GlyphName(UShort idx,UShort code)630 PS_GlyphName(UShort idx,
631              UShort code)
632 {
633   char *glyphname = ".notdef";
634   static char CJK_glyphname[8];
635 
636   if (compact)
637   {
638     sprintf(CJK_glyphname, "cjk%04X", code);
639     glyphname = CJK_glyphname;
640   }
641   else
642   {
643     if (idx)
644       TT_Get_PS_Name(face, idx, &glyphname);
645   }
646 
647   return glyphname;
648 }
649 
650 
651 /*
652  * Header of Type 1 font.
653  */
654 
655 void
PS_Head(FILE * out,int plane,EncVec * planeEV,char * font,int UID)656 PS_Head(FILE *out,
657         int plane,
658         EncVec* planeEV,
659         char* font,
660         int UID)
661 {
662   EVcRange* cRange = planeEV->codeRange;
663   UShort    numCR  = planeEV->numCodeRanges;
664   int       cjk = 0, nGlyph = 0, irange;
665   EVLow*    pLow = cRange->low;
666   UShort    nLow = cRange->numLowRanges;
667   int       ipl, ilow, ich;
668   int       idx;
669   UShort    code;
670   time_t    curtime;
671   struct tm *loctime;
672   char      text[NAMELEN];
673   char      fam_name[NAMELEN];
674   char*     version;
675   char      fullname[NAMELEN];
676   char      copyright[NAMELEN];
677 
678   /* Get the current time with local representation */
679   curtime = time(NULL);
680   loctime = localtime(&curtime);
681 
682   /* Get font infos: family name, version, notice */
683   strcpy(fullname, LookUp_Name(6));
684   strcpy(fam_name, LookUp_Name(1));
685   strcpy(text, LookUp_Name(5));
686   version = &text[strcspn(text, "1234567890.")];
687   version[strspn(version, "1234567890.")] = '\0';
688   strcpy(copyright, LookUp_Name(0));
689 
690   fprintf(out, "%%!FontType1-1.0: %s %s\n", font, version);
691   fprintf(out, "%%%%Creator: %s, ", prog);
692   fprintf(out, "%s\n", rcsid);
693   fprintf(out, "%%%%CreationDate: %s", asctime(loctime));
694 
695   Fputs("%%VMusage: 030000 030000");
696   Fputs("11 dict begin");
697   Fputs("/FontInfo 8 dict dup begin");
698   fprintf(out, "/version (%s) readonly def\n", version);
699   fprintf(out, "/Copyright (%s) readonly def\n", copyright);
700   fprintf(out, "/Notice (Plane %d) readonly def\n", plane);
701   fprintf(out, "/FullName (%s) readonly def\n", fullname);
702   fprintf(out, "/FamilyName (%s) readonly def\n", fam_name);
703   Fputs("/Weight (Regular) readonly def");
704   Fputs("/ItalicAngle 0 def");
705   Fputs("/isFixedPitch false def");
706   /* Fputs("/UnderlineThickness 50 def"); */
707   Fputs("end readonly def");
708   fprintf(out, "/FontName /%s def\n", font);
709   Fputs("/PaintType 0 def");
710   Fputs("/FontType 1 def");
711 
712   if (fontShift == 0)
713     Fputs("/FontMatrix [0.001 0 0 0.001 0 0] readonly def");
714   else
715     fprintf(out, "/FontMatrix [0.001 0 0 0.001 0 %5.3f] readonly def\n",
716             fontShift);
717 
718   Fputs("/Encoding 256 array");
719   Fputs("0 1 255 {1 index exch /.notdef put} for");
720   /* encoding vector */
721   for (irange = 0; irange < numCR; irange++, cRange++)
722   {
723     pLow = cRange->low;
724     nLow = cRange->numLowRanges;
725     for (ipl = cRange->high.start; ipl <= cRange->high.end; ipl++)
726     {
727       if (nLow == 0)
728       {
729         nGlyph = 0x100;
730         for (ich = 0; ich <= 0xff; ich++)
731         {
732           code = ipl<<8 | ich;
733           idx = TT_Char_Index(cmap, code);
734           fprintf(out, "dup %d /%s put\n", ich, PS_GlyphName(idx, code));
735         }
736       }
737       else
738       {
739         for (ilow = 0; ilow < nLow; ilow++, pLow++)
740         {
741           if (!compact && !mapping)
742             cjk = pLow->start;
743           nGlyph += pLow->end - pLow->start + 1;
744           for (ich = pLow->start; ich <= pLow->end; ich++, cjk++)
745           {
746             code = ipl<<8 | ich;
747             idx = TT_Char_Index(cmap, code);
748             fprintf(out, "dup %d /%s put\n", cjk, PS_GlyphName(idx, code));
749             if (mapping && cjk == 0xFF)
750               goto done;
751           }
752         }
753       }
754     }
755   }
756 
757 done:
758 
759   Fputs("readonly def");
760   Fputs("/FontBBox [0 -300 1000 1000] readonly def");
761   fprintf(out, "/UniqueID %d def\n",UID);
762   Fputs("currentdict end");
763   Fputs("currentfile eexec");
764 
765   Fputs("dup /Private 8 dict dup begin");
766   Fputs("/-| { string currentfile exch readstring pop } executeonly def");
767   Fputs("/|- { noaccess def } executeonly def");
768   Fputs("/| { noaccess put } executeonly def");
769   Fputs("/BlueValues [ ] |-");
770   Fputs("/ForceBold true def");
771   Fputs("/LanguageGroup 1 def");
772   Fputs("/RndStemUp false def");
773   Fputs("/MinFeature{16 16} |-");
774   /* Fputs("/password 5839 def"); */
775   fprintf(out, "/UniqueID %d def\n",UID);
776 
777   Fputs("/Subrs 4 array");
778   Fputs("dup 0 { 3 0 callothersubr pop pop setcurrentpoint return } |");
779   Fputs("dup 1 { 0 1 callothersubr return } |");
780   Fputs("dup 2 { 0 2 callothersubr return } |");
781   Fputs("dup 3 { return } |");
782   Fputs("|-");
783 
784   fprintf(out, "2 index /CharStrings %d dict dup begin\n", nGlyph + 1);
785 }
786 
787 
788 /*
789  * Tail of Type 1 font.
790  */
791 
792 void
PS_Tail(FILE * out)793 PS_Tail(FILE *out)
794 {
795   Fputs("/.notdef { 0 250 hsbw endchar } |-");
796   Fputs("end end readonly put noaccess put");
797   Fputs("dup /FontName get exch definefont pop");
798   Fputs("mark currentfile closefile");
799 }
800 
801 
802 /*
803  * Use the `rrcurveto' command on more than one `off' points.
804  */
805 
806 void
PS_Curveto(FILE * out,TT_F26Dot6 x,TT_F26Dot6 y,int s,int e)807 PS_Curveto(FILE *out,
808            TT_F26Dot6 x,
809            TT_F26Dot6 y,
810            int s,
811            int e)
812 {
813   int  N, i;
814   TT_F26Dot6 sx[3], sy[3], cx[4], cy[4];
815 
816   N = e - s + 1;
817   cx[0] = lastpsx; cy[0] = lastpsy;
818   if (s == e)
819   {
820     cx[1] = (2 * outline.points[s].x + outline.points[s - 1].x) / 3;
821     cy[1] = (2 * outline.points[s].y + outline.points[s - 1].y) / 3;
822     cx[2] = (2 * outline.points[s].x + x) / 3;
823     cy[2] = (2 * outline.points[s].y + y) / 3;
824     cx[3] = x;
825     cy[3] = y;
826 
827     fprintf(out, "%d %d %d %d %d %d rrcurveto\n",
828             Coord(cx[1] - cx[0]), Coord(cy[1] - cy[0]),
829             Coord(cx[2] - cx[1]), Coord(cy[2] - cy[1]),
830             Coord(cx[3] - cx[2]), Coord(cy[3] - cy[2]));
831   }
832   else
833   {
834     for(i = 0; i < N; i++)
835     {
836       sx[0] = (i == 0) ?
837                 outline.points[s - 1].x :
838                 (outline.points[i + s].x + outline.points[i + s - 1].x) / 2;
839       sy[0] = (i == 0) ?
840                 outline.points[s - 1].y :
841                 (outline.points[i + s].y + outline.points[i + s - 1].y) / 2;
842       sx[1] = outline.points[s + i].x;
843       sy[1] = outline.points[s + i].y;
844       sx[2] = (i == N - 1) ?
845                 x :
846                 (outline.points[s + i].x + outline.points[s + i + 1].x) / 2;
847       sy[2] = (i == N - 1) ?
848                 y :
849                 (outline.points[s + i].y + outline.points[s + i + 1].y) / 2;
850 
851       cx[1] = (2 * sx[1] + sx[0]) / 3;
852       cy[1] = (2 * sy[1] + sy[0]) / 3;
853       cx[2] = (2 * sx[1] + sx[2]) / 3;
854       cy[2] = (2 * sy[1] + sy[2]) / 3;
855       cx[3] = sx[2];
856       cy[3] = sy[2];
857 
858       fprintf(out, "%d %d %d %d %d %d rrcurveto\n",
859               Coord(cx[1] - cx[0]), Coord(cy[1] - cy[0]),
860               Coord(cx[2] - cx[1]), Coord(cy[2] - cy[1]),
861               Coord(cx[3] - cx[2]), Coord(cy[3] - cy[2]));
862 
863       cx[0] = cx[3];
864       cy[0] = cy[3];
865     }
866   }
867   PS_LastPt(x, y);
868 }
869 
870 
871 #ifdef DEBUG
872 int   debug_Char_Code = 0xFFFF;
873 FILE* tmpout;
874 int   showlabel = FALSE;
875 int   no_glyph  = FALSE;
876 int   no_control= FALSE;
877 
878 #define Fputps(_msg_) fprintf(tmpout, "%s\n", _msg_)
879 
880 
881 void
tmp_out(FILE * tmpout)882 tmp_out(FILE* tmpout)
883 {
884   int i, j;
885 
886   Fputps("%!PS");
887   Fputps("%%% CharString debugging program.");
888   Fputps("%%% Generated by: ttf2pfb $Revision: 1.13 $");
889   Fputps("%%% plot char-string (pathes defined in /cjkxxxx)");
890   Fputps("");
891   Fputps("%%% user-defined parameter");
892   Fputps("/scalefactor .6 def");
893   Fputps("%% 0 black, 1 white");
894   Fputps("/glyph-outline-gray 0 def");
895   Fputps("/control-point-gray 0.7 def");
896   Fputps("");
897   Fputps("%%% calculate shifts and scale factor");
898   Fputps("currentpagedevice /PageSize get dup");
899   Fputps("0 get /pagewidth exch def");
900   Fputps("1 get /pageheight exch def");
901   Fputps("");
902   fprintf(tmpout,
903           "/llx %d.0 def /lly %d.0 def /urx %d.0 def /ury %d.0 def\n",
904           Coord(metrics.bbox.xMin / 64), Coord(metrics.bbox.yMin / 64),
905           Coord(metrics.bbox.xMax / 64), Coord(metrics.bbox.yMax / 64));
906   Fputps("/olwidth urx llx sub def");
907   Fputps("/olheight ury lly sub def");
908   Fputps("");
909   Fputps("/scale scalefactor pagewidth mul olwidth div def");
910   Fputps("/xshift pagewidth 1 scalefactor sub mul 2 div def");
911   Fputps("/yshift pageheight olheight scale mul sub 2 div def");
912   Fputps("");
913   Fputps("%% save old gray-scale value");
914   Fputps("/oldgray currentgray def");
915   Fputps("");
916   Fputps("%%% for point sequence label");
917   Fputps("/TimesRoman 8 selectfont");
918   Fputps("/i++ {i /i i 1 add def} def");
919   Fputps("/itos {4 string cvs} def");
920   Fputps("/point {2 copy i++ 3 1 roll 5 3 roll} def");
921   Fputps("/drawlabel");
922   Fputps("  {{moveto dup 0 eq {exit}");
923   Fputps("    {itos show} ifelse} loop pop} def");
924   Fputps("/nodrawlabel {clear} def");
925   Fputps("/i 0 def");
926   Fputps("");
927   Fputps("%%% for drawing glyph paths, redefine commands used in CharString");
928   Fputps("%% scaled to proper size");
929   Fputps("/addr {scale mul 3 -1 roll add 3 1 roll");
930   Fputps("       scale mul add exch 2 copy} def");
931   if (no_glyph)
932   {
933     Fputps("/rmoveto {addr pop pop point} def");
934     Fputps("/rlineto {addr pop pop point} def");
935     Fputps("/rrcurveto {8 4 roll addr 8 -2 roll addr 8 -2 roll addr");
936     Fputps("            8 2 roll 6 {pop} repeat point} def");
937   }
938   else
939   {
940     Fputps("/rmoveto {addr moveto point} def");
941     Fputps("/rlineto {addr lineto point} def");
942     Fputps("/rrcurveto {8 4 roll addr 8 -2 roll addr 8 -2 roll addr");
943     Fputps("            8 2 roll curveto point} def");
944   }
945   Fputps("/hsbw {pop pop");
946   Fputps("  xshift llx scale mul sub");
947   Fputps("  yshift lly scale mul sub} def");
948   Fputps("/endchar {stroke pop pop} def");
949   Fputps("");
950   Fputps("%%% for drawing control paths");
951   Fputps("/T {pop lly sub scale mul yshift add exch");
952   Fputps("        llx sub scale mul xshift add exch } def");
953   Fputps("/mt {T 2 copy moveto} def");
954   if (no_control)
955     Fputps("/lt {T} def");
956   else
957     Fputps("/lt {T 2 copy lineto} def");
958   Fputps("");
959   Fputps("1 setlinecap 1 setlinejoin");
960   Fputps("%%% draw control points and paths");
961   Fputps("control-point-gray setgray");
962 
963   for (i = 0, j = 0; i < outline.n_contours; i++)
964   {
965     Fputps("");
966     fprintf(tmpout,
967             "%d %d %d %d mt\n",
968             j,
969             Coord(outline.points[j].x), Coord(outline.points[j].y),
970             outline.flags[j]);
971     j++;
972     for (; j <= outline.contours[i]; j++)
973       fprintf(tmpout,
974               "%d %d %d %d lt\n",
975               j,
976               Coord(outline.points[j].x), Coord(outline.points[j].y),
977               outline.flags[j]);
978     Fputps("closepath");
979   }
980   Fputps("stroke");
981   if (showlabel && !no_control)
982     Fputps("drawlabel");
983   else
984     Fputps("nodrawlabel");
985   Fputps("");
986   Fputps("%%% draw glyph outlines");
987   Fputps("glyph-outline-gray setgray");
988   Fputps("");
989 }
990 #endif
991 
992 
993 /*
994  * Construct CharString of a glyph.
995  */
996 
997 short
PS_CharString(FILE * out,UShort char_Code)998 PS_CharString(FILE *out,
999               UShort char_Code)
1000 {
1001   int    idx, i, j;
1002   UShort start_offpt, end_offpt = 0, fst;
1003 #if DEBUG
1004   FILE*  oldout = out;
1005   int    loop   = 1;
1006 #endif
1007 
1008   if (force_enc == X)
1009     char_Code = JIS_to_SJIS(char_Code);
1010 
1011   idx = TT_Char_Index(cmap, char_Code);
1012   if (idx == 0)
1013     return FALSE;
1014 
1015   if (!LoadTrueTypeChar(idx))
1016     fatal("Couldn't load character with index %d (code %d)", idx, char_Code);
1017 
1018   if (verbose)
1019     printf("0x%04x (%05d):  %s\n",
1020            char_Code, idx, PS_GlyphName(idx, char_Code));
1021 
1022   /* Begin string */
1023   fprintf(out, "/%s {\n", PS_GlyphName(idx, char_Code));
1024 
1025 #ifdef DEBUG
1026   if (char_Code == debug_Char_Code)
1027   {
1028     tmp_out(tmpout);
1029     out  = tmpout;
1030     loop = 0;
1031   }
1032   for (; loop < 2; loop++)
1033   {
1034 #endif
1035 
1036   /* coordinates are all relative to (0,0) in FreeType */
1037   fprintf(out, "0 %d hsbw\n", (int)(metrics.advance / 64));
1038 
1039   /* Initialize ending contour point, relative coordinates */
1040   lastpsx = lastpsy = 0;
1041 
1042   for (i = 0, j = 0; i < outline.n_contours; i++)
1043   {
1044     fst = j;
1045     PS_Moveto(outline.points[j].x, outline.points[j].y);
1046     j++;
1047 
1048     start_offpt = 0; /* start at least 1 */
1049 
1050     /*
1051      * data pts for all contours stored in one array.
1052      * each round j init at last j + 1
1053      */
1054 
1055     /*
1056      * start_offpt means start of off points.
1057      * 0 means no off points in record.
1058      * N means the position of the off point.
1059      * end_offpt means the ending off point.
1060      * lastx, lasty is the last ON point from which Curve and Line
1061      * shall start.
1062      */
1063 
1064     /*
1065      * start with j=0. into loop, j=1.
1066      * if pt[1] off, if start_offpt == 0, toggle start_offpt
1067      * next j=2. if on, now start_off != 0, run Curveto.
1068      * if pt[1] on, start_off == 0, will run Lineto.
1069      */
1070 
1071     for (; j <= outline.contours[i]; j++)
1072     {
1073       if (!(outline.flags[j] & TT_Flag_On_Curve))
1074       {
1075         if (!start_offpt)
1076           start_offpt = end_offpt = j;
1077         else
1078           end_offpt++;
1079       }
1080       else
1081       {                    /* On Curve */
1082         if (start_offpt)
1083         {
1084           /*
1085            * start_offpt stuck at j, end_offpt++.
1086            * end_offpt - start_offpt gives no of off pts.
1087            * start_offpt gives start of sequence.
1088            * why need outline.xCoord[j] outline.yCoord[j]?
1089            */
1090 
1091           PS_Curveto(out,
1092                      outline.points[j].x, outline.points[j].y,
1093                      start_offpt, end_offpt);
1094           start_offpt = 0;
1095 
1096           /*
1097            * also use start_offpt as indicator to save one variable!!
1098            * after curveto, reset condition.
1099            */
1100         }
1101         else
1102           PS_Lineto(outline.points[j].x, outline.points[j].y);
1103       }
1104     }
1105 
1106     /*
1107      * looks like closepath fst = first, i.e. go back to first
1108      */
1109 
1110     if (start_offpt)
1111       PS_Curveto(out,
1112                  outline.points[fst].x, outline.points[fst].y,
1113                  start_offpt, end_offpt);
1114     else
1115       Fputs("closepath");
1116   }
1117 
1118   Fputs("endchar");
1119 
1120 #if DEBUG
1121     out = oldout;
1122   }
1123   if (char_Code == debug_Char_Code)
1124   {
1125     if (showlabel && !no_glyph)
1126       Fputps("drawlabel");
1127     else
1128       Fputps("nodrawlabel");
1129     Fputps("");
1130     Fputps("%%% end of drawing");
1131     Fputps("oldgray setgray");
1132     Fputps("showpage");
1133     fclose(tmpout);
1134   }
1135 #endif
1136 
1137   Fputs(" } |-");
1138   return TRUE;
1139 }
1140 
1141 
1142 /*
1143  * Get code ranges of an encoding scheme either from
1144  * the eVecMap or a code range file.
1145  */
1146 
1147 EncVec*
Get_EncVec(FILE * enc)1148 Get_EncVec(FILE *enc)
1149 {
1150   EncVec*   encVec = NULL;
1151   EVcRange* cRange = NULL;
1152   EVLow*    lByte  = NULL;
1153   UShort    numCR = 0, numLow = 0;
1154   int       start, end;
1155   int       buflen = LINELEN, numAssigned;
1156   char      buf[LINELEN];
1157 
1158   if (force_enc != 0)
1159     return eVecMap_force[force_enc];
1160 
1161   if (enc == NULL && eVecMap[pid][eid] != NULL)
1162     return eVecMap[pid][eid];
1163 
1164   /* parse each code range line */
1165   while (fgets(buf, buflen, enc) != NULL)
1166   {
1167     if (buf[0] != '#' && buf[0] != '\n')
1168     {
1169       if (strrchr(buf,':') != NULL)
1170       {
1171         /* if there is no high value declared before low value */
1172         if (lByte != NULL)
1173         {
1174           if (cRange == NULL)
1175           {
1176             /* default code range `0x00-0x00:' */
1177             cRange = re_alloc(cRange, ++numCR * sizeof (EVcRange),
1178                               "Get_EncVec");
1179             cRange->high.start = cRange->high.end = 0;
1180           }
1181           /* Assign the last low value */
1182           (cRange + numCR - 1)->low          = lByte;
1183           (cRange + numCR - 1)->numLowRanges = numLow;
1184         }
1185 
1186         /* New high byte range */
1187         cRange = re_alloc(cRange, ++numCR * sizeof (EVcRange), "Get_EncVec");
1188         (cRange + numCR - 1)->numLowRanges = numLow = 0;
1189         lByte = NULL;
1190 
1191         /* Parse code range */
1192         numAssigned = sscanf(buf, "%i %*40s %i", &start, &end);
1193         if (numAssigned <= 0 || numAssigned > 2)
1194         {
1195           mesg("%s: Get_EncVec: Invalid high code range.\n", prog);
1196           return NULL;
1197         }
1198         else
1199         {
1200           (cRange + numCR - 1)->high.start = start;
1201           if (numAssigned == 1)
1202             (cRange + numCR - 1)->high.end = start;
1203           else
1204             (cRange + numCR - 1)->high.end = end;
1205         }
1206       }
1207       else
1208       {
1209         lByte = re_alloc(lByte, ++numLow * sizeof (EVLow), "Get_EncVec");
1210         numAssigned = sscanf(buf, "%i %*40s %i", &start, &end);
1211         if (numAssigned <= 0 || numAssigned > 2)
1212         {
1213           mesg("%s: Get_EncVec: Invalid long code range.\n", prog);
1214           return NULL;
1215         }
1216         else
1217         {
1218           (lByte + numLow - 1)->start = start;
1219           if (numAssigned == 1)
1220             (lByte + numLow - 1)->end = start;
1221           else
1222             (lByte + numLow - 1)->end = end;
1223         }
1224       }
1225     }
1226   }
1227 
1228   if (cRange == NULL)
1229   {
1230     cRange = re_alloc(cRange, ++numCR * sizeof (EVcRange), "Get_EncVec");
1231     cRange->high.start = cRange->high.end = 0;
1232     cRange->numLowRanges = 0;
1233   }
1234 
1235   if (lByte != NULL)
1236   {
1237     (cRange + numCR - 1)->low          = lByte;
1238     (cRange + numCR - 1)->numLowRanges = numLow;
1239   }
1240 
1241   encVec = re_alloc(encVec, 1 * sizeof (EncVec), "Get_EncVec");
1242   encVec->numCodeRanges = numCR;
1243   encVec->codeRange = cRange;
1244   return encVec;
1245 }
1246 
1247 
1248 /*
1249  * Match code ranges by a font plane.
1250  */
1251 
1252 EncVec*
Get_PlaneEV(EncVec * encVec,int plane)1253 Get_PlaneEV(EncVec* encVec,
1254             int plane)
1255 {
1256   UShort    numCR  = encVec->numCodeRanges;
1257   EVcRange* cRange = encVec->codeRange;
1258 
1259   EncVec*   encV = NULL;
1260   EVcRange* planeCR = NULL;
1261   EVLow*    planeLow = NULL;
1262   UShort    nCR = 0, nLow = 0;
1263 
1264   int       icr;
1265 
1266   if (compact)
1267   {
1268     int iChar = 0;               /* summed # of chars */
1269     int nChar = (plane-1) * 256; /* the first char code ranges recorded */
1270     int recording = 0;
1271 
1272     /* if compact, plane starts from 1 to be */
1273     /* compatible with the CJK package */
1274     if (plane < 1 || plane > 99)
1275       fatal("Get_PlaneEV: Given plane out of range");
1276 
1277     for (icr = 0; icr < numCR; icr++, cRange++)
1278     {
1279       UShort numLow = cRange->numLowRanges;
1280       int    ipl;
1281 
1282       for (ipl = cRange->high.start; ipl <= cRange->high.end; ipl++)
1283       {
1284         EVLow* pLow = cRange->low;
1285         int ilow;
1286 
1287         if (recording)
1288         { /* if we have made a hit */
1289           if (planeLow != NULL)
1290           { /* if low byte range has not been saved */
1291             (planeCR + nCR - 1)->low = planeLow;
1292             (planeCR + nCR - 1)->numLowRanges = nLow;
1293             planeLow = NULL;
1294           }
1295 
1296           /* each new plane starts a EVcRange if */
1297           /* iChar is still less than nChar */
1298           if (iChar <= nChar)
1299           {
1300             planeCR = re_alloc(planeCR, ++nCR * sizeof (EVcRange),
1301                                "Get_PlaneEV");
1302             (planeCR + nCR - 1)->high.start =
1303               (planeCR + nCR - 1)->high.end = ipl;
1304             (planeCR + nCR - 1)->numLowRanges = nLow = 0;
1305           }
1306         }
1307 
1308         /* scan each low byte range */
1309         for (ilow = 0; ilow < (numLow == 0 ? 1 : numLow); ilow++, pLow++)
1310         {
1311           int start, end, nLowChar;
1312 
1313           if (numLow == 0)
1314           { /* default range */
1315             start = 0x0;
1316             end   = 0xff;
1317           }
1318           else
1319           {
1320             start = pLow->start;
1321             end   = pLow->end;
1322           }
1323           nLowChar = end - start + 1;
1324           if (iChar + nLowChar > nChar)
1325           { /* a hit! */
1326             int bchar = start + nChar - iChar;
1327             if (planeCR == NULL)
1328             {
1329               /* the first time code range is recorded */
1330               planeCR = re_alloc(planeCR, ++nCR * sizeof (EVcRange),
1331                                  "Get_PlaneEV");
1332               (planeCR + nCR - 1)->high.start = ipl;
1333               (planeCR + nCR - 1)->high.end   = ipl;
1334             }
1335 
1336             /* adjust range boundary */
1337             if (recording == 0)
1338               start = bchar;
1339             else
1340               end = bchar;
1341             nChar += 0xff;
1342 
1343             /* recording starts */
1344             recording++;
1345           }
1346 
1347           iChar += nLowChar;    /* next range */
1348 
1349           if (recording)
1350           {
1351             /* a new low range */
1352             if (iChar <= nChar)
1353             {
1354               planeLow = re_alloc(planeLow, ++nLow * sizeof (EVLow),
1355                                   "Get_PlaneEV");
1356               (planeLow + nLow - 1)->start = start;
1357               (planeLow + nLow - 1)->end   = end;
1358             }
1359             if (recording > 1 || iChar > nChar)
1360             {
1361               /* beyond recording range */
1362               (planeCR + nCR - 1)->numLowRanges = nLow;
1363               (planeCR + nCR - 1)->low = planeLow;
1364               encV = re_alloc(encV, 1 * sizeof (EncVec), "Get_PlaneEV");
1365               encV->numCodeRanges = nCR;
1366               encV->codeRange = planeCR;
1367               return encV;
1368             }
1369           }
1370         }
1371       }
1372     }
1373     /* we must finalize the ranges */
1374     if (recording)
1375     {
1376       (planeCR + nCR - 1)->numLowRanges = nLow;
1377       (planeCR + nCR - 1)->low = planeLow;
1378       encV = re_alloc(encV, 1 * sizeof (EncVec), "Get_PlaneEV");
1379       encV->numCodeRanges = nCR;
1380       encV->codeRange = planeCR;
1381       return encV;
1382     }
1383   }
1384   else
1385   {
1386     for (icr = 0; icr < numCR; icr++, cRange++)
1387     {
1388       if (plane >= cRange->high.start && plane <= cRange->high.end)
1389       {
1390         encV = re_alloc(encV, 1 * sizeof (EncVec), "Get_PlaneEV");
1391         planeCR = re_alloc(planeCR, 1 * sizeof (EVcRange), "Get_PlaneEV");
1392 
1393         planeCR->high.start = planeCR->high.end = plane;
1394         planeCR->numLowRanges = cRange->numLowRanges;
1395         planeCR->low = cRange->low;
1396         encV->numCodeRanges = 1;
1397         encV->codeRange = planeCR;
1398         return encV;
1399       }
1400     }
1401   }
1402   return NULL;
1403 }
1404 
1405 
1406 /*
1407  * The main subroutine for generating Type 1 fonts.
1408  * One subfont per call.
1409  */
1410 
1411 short
Generate_Font(FILE * out,int plane,FILE * enc,char * fname,int UID)1412 Generate_Font(FILE *out,
1413               int plane,
1414               FILE *enc,
1415               char *fname,
1416               int UID)
1417 {
1418   EncVec*   encVec = Get_EncVec(enc);
1419   EncVec*   planeEncVec;
1420   EVcRange* cRange;
1421   UShort    numCR;
1422   UShort    code;
1423   int       ilow, iplan, ichar, irange;
1424 
1425   if (verbose)
1426     printf("Generating fonts...\n\n");
1427 
1428   if (encVec == NULL)
1429     return FALSE;
1430   if (mapping)
1431     planeEncVec = encVec;
1432   else
1433     if ((planeEncVec = Get_PlaneEV(encVec, plane)) == NULL)
1434     {
1435       mesg("%s: Can't find encoding vector for the font plane 0x%X.\n",
1436            prog, plane);
1437       return FALSE;
1438     }
1439 
1440   /* Header of Type1 font */
1441   PS_Head(out, plane, planeEncVec, fname, UID);
1442 
1443   numCR  = planeEncVec->numCodeRanges;
1444   cRange = planeEncVec->codeRange;
1445 
1446   for (irange = 0; irange < numCR; irange++, cRange++)
1447   {
1448     EVLow* pLow = cRange->low;
1449     UShort nLow = cRange->numLowRanges;
1450 
1451     for (iplan = cRange->high.start; iplan <= cRange->high.end; iplan++)
1452     {
1453       if (nLow == 0)
1454       {
1455         for (ichar = 0; ichar <= 0xff; ichar++)
1456         {
1457           code = iplan << 8 | ichar;
1458           PS_CharString(out, code);
1459         }
1460       }
1461       else
1462       {
1463         for (ilow = 0; ilow < nLow; ilow++, pLow++)
1464         {
1465           for (ichar = pLow->start; ichar <= pLow->end; ichar++)
1466           {
1467             code = iplan << 8 | ichar;
1468             PS_CharString(out, code);
1469           }
1470         }
1471       }
1472     }
1473   }
1474   PS_Tail(out);
1475 
1476   return TRUE;
1477 }
1478 
1479 
1480 /*
1481  * Main: process options, file I/O, etc.
1482  */
1483 
1484 int
main(int argc,char * argv[])1485 main(int argc,
1486      char *argv[])
1487 {
1488   char *infile, *outfile, *encFile, *fname = "UNKNOWN";
1489   FILE *out, *enc;
1490   int  result, plane = 0, UID = 4999999;
1491 
1492   if ((prog = strrchr(argv[0], '/')))
1493     prog++;
1494   else
1495     prog = argv[0];
1496 
1497   /* set up known encoding vectors */
1498   Known_Encodings();
1499 
1500   out    = stdout;
1501   enc    = NULL;
1502   infile = outfile = encFile = NULL;
1503 
1504   argc--;
1505   argv++;
1506 
1507   while (argc > 0)
1508   {
1509     if (argv[0][0] == '-')
1510     {
1511       switch (argv[0][1])
1512       {
1513       case 'v':
1514       case 'V':
1515         verbose = TRUE;
1516         break;
1517       case 'c':
1518       case 'C':
1519         compact = TRUE;
1520         break;
1521       case 'k':
1522       case 'K':
1523         keep = TRUE;
1524         break;
1525       case 'm':
1526       case 'M':
1527         mapping = TRUE;
1528         break;
1529       case 'p':
1530       case 'P':
1531         result = argv[0][2];
1532         argc--;
1533         argv++;
1534         if (result == 'i' || result == 'I')
1535         {
1536           /* Set the platform ID. Assumed upper bound is 64 */
1537           if ((pid = atoi(argv[0])) < 0 || pid > 64)
1538             /* Check the platform and encoding IDs. */
1539             fatal("Invalid platform ID %d", pid);
1540         }
1541         else if (result == 'l' || result == 'L')
1542         {
1543           result = 0;
1544           while (argv[0][result] == '0' &&
1545                  toupper(argv[0][result + 1]) != 'X')
1546             result++; /* no octal number */
1547           sscanf(&argv[0][result], "%i", &plane);
1548         }
1549         break;
1550       case 'e':
1551       case 'E':
1552         result = argv[0][2];
1553         argc--;
1554         argv++;
1555         if (result == 'i' || result == 'I')
1556         {
1557           /* Set the encoding ID. */
1558           if ((eid = atoi(argv[0])) < 0 || eid > 64)
1559             fatal("Invalid encoding ID %d", eid);
1560         }
1561         else if (result == 'n' || result == 'N')
1562           encFile = argv[0];
1563         break;
1564       case 'u':
1565       case 'U':
1566         argc--;
1567         argv++;
1568         UID = atoi(argv[0]);
1569         break;
1570       case 'f':
1571       case 'F':
1572         result = argv[0][2];
1573         argc--;
1574         argv++;
1575         if (result == '\0')
1576           fname = argv[0];
1577         else if (result == 'o' || result == 'O')
1578         {
1579           switch (argv[0][0])
1580           {
1581           case 'g':
1582           case 'G':
1583             force_enc = GB;
1584             break;
1585           case 'k':
1586           case 'K':
1587             force_enc = KS;
1588             break;
1589           case 'b':
1590           case 'B':
1591             force_enc = Big5;
1592             break;
1593           case 'j':
1594           case 'J':
1595             result = argv[0][1];
1596             if (result == 'o' || result == 'O')
1597               force_enc = Johab;
1598             else
1599               force_enc = JIS;
1600             break;
1601           case 's':
1602           case 'S':
1603             force_enc = SJIS;
1604             break;
1605           case 'x':
1606           case 'X':
1607             force_enc = X;
1608           }
1609         }
1610         break;
1611       case 't':                 /* Get the TTF file name. */
1612       case 'T':
1613         argc--;
1614         argv++;
1615         infile = argv[0];
1616         break;
1617       case 'o':                 /* Set the output file name. */
1618       case 'O':
1619         argc--;
1620         argv++;
1621         outfile = argv[0];
1622         break;
1623       case 's':                 /* shift font bbox up or down */
1624       case 'S':
1625         argc--;
1626         argv++;
1627         sscanf(argv[0], "%f", &fontShift);
1628         break;
1629 #ifdef DEBUG
1630       case 'd':                 /* character code for debugging */
1631       case 'D':
1632         argc--;
1633         argv++;
1634         sscanf(argv[0], "%i", &debug_Char_Code);
1635         tmpout = fopen("ch-debug.ps", "wt");
1636         mesg("You have specified the character code 0x%04x for debugging.\n",
1637              debug_Char_Code);
1638         mesg("A PostScript program named `ch-debug.ps' will be created.\n");
1639         break;
1640       case 'l':
1641       case 'L':
1642         showlabel = TRUE;
1643         break;
1644       case 'n':
1645       case 'N':
1646         result = argv[0][2];
1647         if (result == 'g' || result == 'G')
1648           no_glyph = TRUE;
1649         else if (result == 'c' || result == 'C')
1650           no_control = TRUE;
1651         break;
1652 #endif
1653       default:
1654         Usage(1);
1655       }
1656     }
1657     else
1658       /* Set the input file name. */
1659       infile = argv[0];
1660 
1661     argc--;
1662     argv++;
1663   }
1664 
1665   /* Open the output file if specified. */
1666   if (outfile != NULL)
1667     /* Attempt to open the output file. */
1668     if ((out = fopen(outfile, "wt")) == 0)
1669     {
1670       fatal("Unable to open the output file `%s'", outfile);
1671       exit(FAILURE);
1672     }
1673 
1674   /* Validate the values passed on the command line. */
1675   if (infile == NULL)
1676   {
1677     mesg("%s: No input TTF file provided\n", prog);
1678     Usage(1);
1679   }
1680 
1681   if (encFile != NULL)
1682   {
1683     if ((enc = fopen(encFile, "rt")) == 0)
1684       fatal("No input code range file");
1685   }
1686 
1687   /* Initialize font engine */
1688   if (!Init_Font_Engine(infile))
1689   {
1690     if (out != stdout)
1691     {
1692       fclose(out);
1693       if (!keep)
1694         (void)unlink(outfile);
1695     }
1696     exit(FAILURE);
1697   }
1698 
1699   /* Generate the disassembled PFB font from the TrueType font */
1700   if (Generate_Font(out, plane, enc, fname, UID))
1701     result = 0;
1702   else
1703     result = 2;
1704 
1705   if (out != stdout)
1706   {
1707     fclose(out);
1708     if (result != 0)
1709     {
1710       mesg("%s: An error occurred while generating the font", prog);
1711       if (!keep)
1712         (void)unlink(outfile);
1713     }
1714   }
1715 
1716   TT_Close_Face(face);
1717   TT_Done_FreeType(engine);
1718 
1719   exit(result);
1720 
1721   return 0; /* never reached */
1722 }
1723 
1724 
1725 /* end of ttf2pfb.c */
1726