4 * This file is part of the ttf2pk package.
6 * Copyright 1997-1999 by
7 * Frederic Loyer <loyer@ensta.fr>
8 * Werner Lemberg <wl@gnu.org>
16 #include "extend/ftxkern.h" /* we are in the FreeType package tree */
17 #include "extend/ftxpost.h"
18 #include "extend/ftxopen.h"
30 #define Macintosh_platform 1
31 #define Macintosh_encoding 0
33 #define Microsoft_platform 3
34 #define Microsoft_Unicode_encoding 1
36 #define SCRIPT_kana MAKE_TT_TAG('k', 'a', 'n', 'a')
37 #define SCRIPT_hani MAKE_TT_TAG('h', 'a', 'n', 'i')
38 #define SCRIPT_hang MAKE_TT_TAG('h', 'a', 'n', 'g')
40 #define LANGUAGE_JAN MAKE_TT_TAG('J', 'A', 'N', ' ')
41 #define LANGUAGE_CHN MAKE_TT_TAG('C', 'H', 'N', ' ')
42 #define LANGUAGE_KOR MAKE_TT_TAG('K', 'O', 'R', ' ')
44 #define FEATURE_vert MAKE_TT_TAG('v', 'e', 'r', 't')
47 extern char progname
[];
57 TT_Matrix matrix1
, matrix2
;
59 TT_Big_Glyph_Metrics metrics
;
60 TT_Face_Properties properties
;
74 readttf_kern(Font
*fnt
)
78 TT_Kern_0_Pair
* pairs0
;
83 if ((error
= TT_Get_Kerning_Directory(face
, &directory
)))
84 oops("Cannot get kerning directory (error code = 0x%x).", error
);
86 if (directory
.nTables
== 0)
89 for (i
= 0; i
< directory
.nTables
; i
++)
91 if ((error
= TT_Load_Kerning_Table(face
, i
)))
92 oops("Cannot load kerning table (error code = 0x%x).", error
);
94 switch (directory
.tables
[i
].format
)
97 pairs0
= directory
.tables
[i
].t
.kern0
.pairs
;
98 for (j
= 0; j
< directory
.tables
[i
].t
.kern0
.nPairs
; j
++, pairs0
++)
100 ti
= findglyph(pairs0
->left
, fnt
->charlist
);
102 warning("kern char not found");
106 nk
->succ
= findglyph(pairs0
->right
, fnt
->charlist
)->adobename
;
107 nk
->delta
= transform(pairs0
->value
* 1000 / fnt
->units_per_em
, 0,
108 fnt
->efactor
, fnt
->slant
);
109 nk
->next
= ti
->kerns
;
113 return; /* we stop after the first format 0 kerning table */
124 readttf(Font
*fnt
, Boolean quiet
, Boolean only_range
)
131 unsigned short num_cmap
;
132 unsigned short cmap_plat
, cmap_enc
;
133 int index_array
[257];
135 static Boolean initialized
= False
;
137 TT_UShort in_string
[2];
138 TTO_GSUB_String in
, out
;
140 TT_UShort script_index
, language_index
, feature_index
;
141 TT_UShort req_feature_index
= 0xFFFF;
145 * We allocate a placeholder boundary and the `.notdef' character.
152 ti
->adobename
= ".notdef";
156 ti
->adobename
= "||"; /* boundary character name */
160 * Initialize FreeType engine.
165 if ((error
= TT_Init_FreeType(&engine
)))
166 oops("Cannot initialize engine (error code = 0x%x).", error
);
168 if ((error
= TT_Init_Kerning_Extension(engine
)))
169 oops("Cannot initialize kerning (error code = 0x%x).", error
);
172 if ((error
= TT_Init_Post_Extension(engine
)))
173 oops("Cannot initialize PS name support (error code = 0x%x).", error
);
176 if ((error
= TT_Init_GSUB_Extension(engine
)))
177 oops("Cannot initialize GSUB support (error code = 0x%x).", error
);
183 real_ttfname
= TeX_search_ttf_file(&(fnt
->ttfname
));
185 oops("Cannot find `%s'.", fnt
->ttfname
);
187 if ((error
= TT_Open_Face(engine
, real_ttfname
, &face
)))
188 oops("Cannot open `%s'.", real_ttfname
);
191 * Get face properties and allocate preload arrays.
194 TT_Get_Face_Properties(face
, &properties
);
197 * Now we try to open the proper font in a collection.
200 if (fnt
->fontindex
!= 0)
202 if (properties
.num_Faces
== 1)
204 warning("This isn't a TrueType collection.\n"
205 "Parameter `-f' is ignored.");
207 fnt
->fontindexparam
= NULL
;
212 if ((error
= TT_Open_Collection(engine
, real_ttfname
,
213 fnt
->fontindex
, &face
)))
214 oops("Cannot open font %lu in TrueType Collection `%s'.",
215 fnt
->fontindex
, real_ttfname
);
223 if ((error
= TT_New_Instance(face
, &instance
)))
224 oops("Cannot create instance for `%s' (error code = 0x%x).",
225 real_ttfname
, error
);
228 * We use a dummy glyph size of 10pt.
231 if ((error
= TT_Set_Instance_CharSize(instance
, 10 * 64)))
232 oops("Cannot set character size (error code = 0x%x).", error
);
234 matrix1
.xx
= (TT_Fixed
)(floor(fnt
->efactor
* 1024) * (1L<<16)/1024);
235 matrix1
.xy
= (TT_Fixed
)(floor(fnt
->slant
* 1024) * (1L<<16)/1024);
236 matrix1
.yx
= (TT_Fixed
)0;
237 matrix1
.yy
= (TT_Fixed
)(1L<<16);
242 matrix2
.yx
= 1L << 16;
243 matrix2
.xy
= -matrix2
.yx
;
244 matrix2
.yy
= matrix2
.xx
;
247 if ((error
= TT_Set_Instance_Transform_Flags(
250 fnt
->efactor
!= 1.0 ? 1 : 0)))
251 oops("Cannot set transform flags (error code = 0x%x).", error
);
254 * Create glyph container.
257 if ((error
= TT_New_Glyph(face
, &glyph
)))
258 oops("Cannot create glyph container (error code = 0x%x).", error
);
260 fnt
->units_per_em
= properties
.header
->Units_Per_EM
;
261 fnt
->fixedpitch
= properties
.postscript
->isFixedPitch
;
262 fnt
->italicangle
= properties
.postscript
->italicAngle
/ 65536.0;
264 if (fnt
->PSnames
!= Only
)
266 num_cmap
= properties
.num_CharMaps
;
267 for (i
= 0; i
< num_cmap
; i
++)
269 if ((error
= TT_Get_CharMap_ID(face
, i
, &cmap_plat
, &cmap_enc
)))
270 oops("Cannot query cmap (error code = 0x%x).", error
);
271 if (cmap_plat
== fnt
->pid
&& cmap_enc
== fnt
->eid
)
276 fprintf(stderr
, "%s: ERROR: Invalid platform and/or encoding ID.\n",
279 fprintf(stderr
, " The only valid PID/EID pair is");
281 fprintf(stderr
, " Valid PID/EID pairs are:\n");
282 for (i
= 0; i
< num_cmap
; i
++)
284 TT_Get_CharMap_ID(face
, i
, &cmap_plat
, &cmap_enc
);
285 fprintf(stderr
, " (%i,%i)\n", cmap_plat
, cmap_enc
);
287 fprintf(stderr
, "\n");
291 if ((error
= TT_Get_CharMap(face
, i
, &char_map
)))
292 oops("Cannot load cmap (error code = 0x%x).", error
);
297 if ((error
= TT_Load_PS_Names(face
, &post
)))
298 oops("Cannot load TrueType PS names (error code = 0x%x).", error
);
300 else if (cmap_plat
== Microsoft_platform
&&
301 cmap_enc
== Microsoft_Unicode_encoding
)
302 set_encoding_scheme(encUnicode
, fnt
);
303 else if (cmap_plat
== Macintosh_platform
&&
304 cmap_enc
== Macintosh_encoding
)
305 set_encoding_scheme(encMac
, fnt
);
307 set_encoding_scheme(encFontSpecific
, fnt
);
313 error
= TT_Load_GSUB_Table(face
, gsub
, NULL
);
316 else if (error
!= TT_Err_Table_Missing
)
317 warning("Cannot load GSUB table (error code = 0x%x).", error
);
319 warning("No GSUB data available "
320 "for vertical glyph presentation forms.");
322 /* we check for the `vert' feature in Chinese, Japanese, and Korean */
324 error
= TT_GSUB_Select_Script(gsub
,
329 error
= TT_GSUB_Select_Feature(gsub
,
336 error
= TT_GSUB_Select_Language(gsub
,
343 error
= TT_GSUB_Select_Feature(gsub
,
357 error
= TT_GSUB_Select_Script(gsub
,
362 error
= TT_GSUB_Select_Feature(gsub
,
369 error
= TT_GSUB_Select_Language(gsub
,
376 error
= TT_GSUB_Select_Feature(gsub
,
390 error
= TT_GSUB_Select_Script(gsub
,
395 error
= TT_GSUB_Select_Feature(gsub
,
402 error
= TT_GSUB_Select_Language(gsub
,
409 error
= TT_GSUB_Select_Feature(gsub
,
419 warning("There is no data for vertical typesetting in GSUB table.");
423 if (req_feature_index
!= 0xFFFF)
424 TT_GSUB_Add_Feature(gsub
, req_feature_index
, ALL_GLYPHS
);
425 TT_GSUB_Add_Feature(gsub
, feature_index
, ALL_GLYPHS
);
429 in
.string
= in_string
;
430 in
.properties
= NULL
;
435 out
.properties
= NULL
;
444 printf("\n\n%s:\n", fnt
->fullname
);
446 printf("Glyph Code Glyph Name ");
447 printf("Width llx lly urx ury\n");
448 printf("---------------------------------------");
449 printf("---------------------------------\n");
453 * We load only glyphs with a valid cmap entry. Nevertheless, for
454 * the default mapping, we use the first 256 glyphs addressed by
455 * ascending code points, followed by glyphs not in the cmap.
457 * If we compute a range, we take the character codes given in
458 * the fnt->sf_code array.
460 * If the -N flag is set, no cmap is used at all. Instead, the
461 * first 256 glyphs (with a valid PS name) are used for the default
466 for (i
= 0; i
< 257; i
++)
469 for (i
= 0; i
< 256; i
++)
470 fnt
->inencptrs
[i
] = 0;
473 if (fnt
->PSnames
== Only
)
474 max_k
= properties
.num_Glyphs
- 1;
476 max_k
= only_range
? 0xFF : 0xFFFF;
478 for (k
= 0; k
<= max_k
; k
++)
483 if (fnt
->PSnames
!= Only
)
487 index
= fnt
->sf_code
[k
];
495 Num
= TT_Char_Index(char_map
, index
);
497 /* now we try to get a vertical glyph form */
502 error
= TT_GSUB_Apply_String(gsub
, &in
, &out
);
503 if (error
&& error
!= TTO_Err_Not_Covered
)
504 warning("Cannot get the vertical glyph form for glyph index %d.",
511 oops("Failure on cmap mapping from %s.", fnt
->ttfname
);
516 index_array
[Num
] = 1;
524 error
= TT_Load_Glyph(instance
, glyph
, Num
, 0);
526 error
= TT_Get_Glyph_Big_Metrics(glyph
, &metrics
);
528 error
= TT_Get_Glyph_Outline(glyph
, &outline
);
531 if (fnt
->efactor
!= 1.0 || fnt
->slant
!= 0.0 )
532 TT_Transform_Outline(&outline
, &matrix1
);
534 TT_Transform_Outline(&outline
, &matrix2
);
537 error
= TT_Get_Outline_BBox(&outline
, &bbox
); /* we need the non-
542 (void)TT_Get_PS_Name(face
, Num
, &an
);
544 an
= code_to_adobename(index
);
546 /* ignore characters not usable for typesetting with TeX */
548 if (strcmp(an
, ".notdef") == 0)
550 if (strcmp(an
, ".null") == 0)
552 if (strcmp(an
, "nonmarkingreturn") == 0)
556 ti
->charcode
= index
;
557 ti
->glyphindex
= Num
;
559 ti
->llx
= bbox
.xMin
* 1000 / fnt
->units_per_em
;
560 ti
->lly
= bbox
.yMin
* 1000 / fnt
->units_per_em
;
561 ti
->urx
= bbox
.xMax
* 1000 / fnt
->units_per_em
;
562 ti
->ury
= bbox
.yMax
* 1000 / fnt
->units_per_em
;
565 * We must now shift the rotated character both horizontally
566 * and vertically. The vertical amount is 25% by default.
571 ti
->llx
+= (metrics
.vertBearingY
- bbox
.xMin
) *
572 1000 / fnt
->units_per_em
;
573 ti
->lly
-= 1000 * fnt
->y_offset
;
574 ti
->urx
+= (metrics
.vertBearingY
- bbox
.xMin
) *
575 1000 / fnt
->units_per_em
;
576 ti
->ury
-= 1000 * fnt
->y_offset
;
580 * We need to avoid negative heights or depths. They break accents
581 * in math mode, among other things.
589 ti
->width
= metrics
.vertAdvance
* 1000 / fnt
->units_per_em
;
591 ti
->width
= transform(metrics
.horiAdvance
* 1000 / fnt
->units_per_em
,
592 0, fnt
->efactor
, fnt
->slant
);
595 printf("%5ld %04lx %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
596 Num
, index
, ti
->adobename
,
598 ti
->llx
, ti
->lly
, ti
->urx
, ti
->ury
);
602 fnt
->inencptrs
[j
] = ti
;
610 * Now we load glyphs without a cmap entry, provided some slots are
611 * still free -- we skip this if we have to compute a range or use
615 if (!only_range
&& !fnt
->PSnames
)
617 for (i
= 1; i
<= properties
.num_Glyphs
; i
++)
622 if (index_array
[i
] == 0)
624 error
= TT_Load_Glyph(instance
, glyph
, i
, 0);
626 error
= TT_Get_Glyph_Big_Metrics(glyph
, &metrics
);
628 error
= TT_Get_Glyph_Outline(glyph
, &outline
);
630 error
= TT_Get_Outline_BBox(&outline
, &bbox
);
633 an
= code_to_adobename(i
| 0x10000);
636 ti
->charcode
= i
| 0x10000;
639 ti
->llx
= bbox
.xMin
* 1000 / fnt
->units_per_em
;
640 ti
->lly
= bbox
.yMin
* 1000 / fnt
->units_per_em
;
641 ti
->urx
= bbox
.xMax
* 1000 / fnt
->units_per_em
;
642 ti
->ury
= bbox
.yMax
* 1000 / fnt
->units_per_em
;
648 ti
->width
= transform(metrics
.horiAdvance
*1000 / fnt
->units_per_em
,
649 0, fnt
->efactor
, fnt
->slant
);
652 printf("%5d %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
655 ti
->llx
, ti
->lly
, ti
->urx
, ti
->ury
);
659 fnt
->inencptrs
[j
] = ti
;
670 /* Finally, we construct a `Germandbls' glyph if necessary */
674 if (NULL
== findadobe("Germandbls", fnt
->charlist
) &&
675 NULL
!= (Ti
= findadobe("S", fnt
->charlist
)))
681 ti
->charcode
= properties
.num_Glyphs
| 0x10000;
682 ti
->glyphindex
= properties
.num_Glyphs
;
683 ti
->adobename
= "Germandbls";
684 ti
->width
= Ti
->width
<< 1;
687 ti
->urx
= Ti
->width
+ Ti
->urx
;
689 ti
->kerns
= Ti
->kerns
;
695 nq
->xoffset
= Ti
->width
;
698 ti
->constructed
= True
;
701 printf("* %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
704 ti
->llx
, ti
->lly
, ti
->urx
, ti
->ury
);
708 /* kerning between subfonts isn't available */