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