4 * This file is part of the ttf2pk package.
6 * Copyright 1997-1999 by
7 * Loyer Frederic <loyer@ensta.fr>
8 * Werner Lemberg <wl@gnu.org>
14 #include <math.h> /* libc ANSI */
17 #include "pklib.h" /* for the `byte' type */
25 #include "extend/ftxpost.h"
26 #include "extend/ftxopen.h"
29 #define Macintosh_platform 1
30 #define Macintosh_encoding 0
32 #define Microsoft_platform 3
33 #define Microsoft_Symbol_encoding 0
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')
54 TT_Face_Properties properties
;
59 TT_Raster_Map Bit
, Bit2
;
65 int x_offset
, y_offset
;
68 TT_Big_Glyph_Metrics metrics
;
70 TT_Matrix matrix1
, matrix2
;
75 TT_UShort in_string
[2];
76 TTO_GSUB_String in
, out
;
82 SetRasterArea(int quiet
)
84 int temp1_x
, temp1_y
, temp2_x
, temp2_y
;
87 temp1_x
= bbox
.xMin
/ 64; /* scaling F16.6 -> int */
88 temp1_y
= bbox
.yMin
/ 64;
89 temp2_x
= (bbox
.xMax
+ 63) / 64;
90 temp2_y
= (bbox
.yMax
+ 63) / 64;
92 x_offset
= 5 - temp1_x
;
93 y_offset
= 5 - temp1_y
;
96 printf(" off = (%d, %d)", x_offset
, y_offset
);
99 x_offset
= y_offset
= 0;
103 printf(" bbox = (%d, %d) <-> (%d, %d)\n",
104 temp1_x
, temp1_y
, temp2_x
, temp2_y
);
106 Bit
.rows
= temp2_y
- temp1_y
+ 10;
107 Bit
.width
= temp2_x
- temp1_x
+ 10;
109 Bit
.cols
= (Bit
.width
+ 7) / 8; /* convert to # of bytes */
110 Bit
.flow
= TT_Flow_Up
;
111 Bit
.size
= Bit
.rows
* Bit
.cols
; /* number of bytes in buffer */
114 * We allocate one more row to have valid pointers for comparison
115 * purposes in pklib.c, making `gcc -fbounds-checking' happy.
120 Bitp
= mymalloc(Bit
.size
+ Bit
.cols
);
127 Bit2p
= mymalloc(Bit
.size
+ Bit
.cols
);
138 p1
= (char *)Bit
.bitmap
;
139 p2
= (char *)Bit2
.bitmap
+ Bit2
.cols
* (Bit2
.rows
- 1);
141 for (y
= 0; y
< Bit
.rows
; y
++)
143 memcpy(p2
, p1
, Bit
.cols
);
153 Output(TT_Raster_Map Bit
)
165 for (y
= 0; y
< Bit
.rows
; y
++)
168 for (x
= 0; x
< Bit
.cols
; x
++)
171 for(i
= 0x80; i
; i
>>= 1)
172 printf((b
& i
) ? "x" : ".");
182 TTFopen(char *filename
, Font
*fnt
, int new_dpi
, int new_ptsize
, Boolean quiet
)
184 unsigned short i
, num_cmap
;
185 unsigned short cmap_plat
;
186 unsigned short cmap_enc
;
189 TT_UShort script_index
, language_index
, feature_index
;
190 TT_UShort req_feature_index
= 0xFFFF;
196 if ((error
= TT_Init_FreeType(&engine
)))
197 oops("Cannot initialize FreeType engine (error code = 0x%x).", error
);
200 if ((error
= TT_Init_Post_Extension(engine
)))
201 oops("Cannot initialize PS name support (error code = 0x%x).", error
);
204 if ((error
= TT_Init_GSUB_Extension(engine
)))
205 oops("Cannot initialize GSUB support (error code = 0x%x).", error
);
211 error
= TT_Open_Face(engine
, filename
, &face
);
213 oops("Cannot open `%s'.", filename
);
216 * Get face properties and allocate preloaded arrays.
219 TT_Get_Face_Properties(face
, &properties
);
222 * Now we try to open the proper font in a collection.
225 if (fnt
->fontindex
!= 0)
227 if (properties
.num_Faces
== 1)
228 warning("This isn't a TrueType collection.\n"
229 "Parameter `Fontindex' is ignored.");
233 if ((error
= TT_Open_Collection(engine
, filename
,
234 fnt
->fontindex
, &face
)))
235 oops("Cannot open font %lu in TrueType Collection `%s'.",
236 fnt
->fontindex
, filename
);
244 if ((error
= TT_New_Instance(face
, &instance
)))
245 oops("Cannot create instance for `%s' (error code = 0x%x).",
248 if ((error
= TT_Set_Instance_Resolutions(instance
, dpi
, dpi
)))
249 oops("Cannot set device resolutions (error code = 0x%x).");
251 if ((error
= TT_Set_Instance_CharSize(instance
, ptsize
* 64)))
252 oops("Cannot set character size (error code = 0x%x).", error
);
254 ppem
= (dpi
* ptsize
+ 36) / 72;
257 printf("dpi = %d, ptsize = %d, ppem = %d\n\n", dpi
, ptsize
, ppem
);
259 matrix1
.xx
= (TT_Fixed
)(floor(fnt
->efactor
* 1024) * (1<<16)/1024);
260 matrix1
.xy
= (TT_Fixed
)(floor(fnt
->slant
* 1024) * (1<<16)/1024);
261 matrix1
.yx
= (TT_Fixed
)0;
262 matrix1
.yy
= (TT_Fixed
)(1<<16);
267 matrix2
.yx
= 1L << 16;
268 matrix2
.xy
= -matrix2
.yx
;
269 matrix2
.yy
= matrix2
.xx
;
272 if ((error
= TT_Set_Instance_Transform_Flags(
275 fnt
->efactor
!= 1.0 ? 1 : 0)))
276 oops("Cannot set transform flags (error code = 0x%x).", error
);
279 * Create glyph container.
282 if ((error
= TT_New_Glyph(face
, &glyph
)))
283 oops("Cannot create glyph container (error code = 0x%x).");
285 if (fnt
->PSnames
!= Only
)
287 num_cmap
= properties
.num_CharMaps
;
288 for (i
= 0; i
< num_cmap
; i
++)
290 if ((error
= TT_Get_CharMap_ID(face
, i
, &cmap_plat
, &cmap_enc
)))
291 oops("Cannot query cmap (error code = 0x%x).", error
);
292 if (cmap_plat
== fnt
->pid
&& cmap_enc
== fnt
->eid
)
296 oops("Invalid platform and/or encoding ID.");
298 if ((error
= TT_Get_CharMap(face
, i
, &char_map
)))
299 oops("Cannot load cmap (error code = 0x%x).", error
);
304 if ((error
= TT_Load_PS_Names(face
, &post
)))
305 oops("Cannot load TrueType PS names (error code = 0x%x).", error
);
307 else if (cmap_plat
== Microsoft_platform
&&
308 cmap_enc
== Microsoft_Unicode_encoding
)
309 set_encoding_scheme(encUnicode
, fnt
);
310 else if (cmap_plat
== Macintosh_platform
&&
311 cmap_enc
== Macintosh_encoding
)
312 set_encoding_scheme(encMac
, fnt
);
314 set_encoding_scheme(encFontSpecific
, fnt
);
320 error
= TT_Load_GSUB_Table(face
, gsub
, NULL
);
323 else if (error
!= TT_Err_Table_Missing
)
324 warning("Cannot load GSUB table (error code = 0x%x).", error
);
326 warning("No GSUB data available "
327 "for vertical glyph presentation forms.");
329 /* we check for the `vert' feature in Chinese, Japanese, and Korean */
331 error
= TT_GSUB_Select_Script(gsub
,
336 error
= TT_GSUB_Select_Feature(gsub
,
343 error
= TT_GSUB_Select_Language(gsub
,
350 error
= TT_GSUB_Select_Feature(gsub
,
364 error
= TT_GSUB_Select_Script(gsub
,
369 error
= TT_GSUB_Select_Feature(gsub
,
376 error
= TT_GSUB_Select_Language(gsub
,
383 error
= TT_GSUB_Select_Feature(gsub
,
397 error
= TT_GSUB_Select_Script(gsub
,
402 error
= TT_GSUB_Select_Feature(gsub
,
409 error
= TT_GSUB_Select_Language(gsub
,
416 error
= TT_GSUB_Select_Feature(gsub
,
426 warning("There is no data for vertical typesetting in GSUB table.");
430 if (req_feature_index
!= 0xFFFF)
431 TT_GSUB_Add_Feature(gsub
, req_feature_index
, ALL_GLYPHS
);
432 TT_GSUB_Add_Feature(gsub
, feature_index
, ALL_GLYPHS
);
436 in
.string
= in_string
;
437 in
.properties
= NULL
;
442 out
.properties
= NULL
;
448 LoadTrueTypeChar(Font
*fnt
,
457 flags
= TTLOAD_SCALE_GLYPH
;
459 flags
|= TTLOAD_HINT_GLYPH
;
461 error
= TT_Load_Glyph(instance
, glyph
, idx
, flags
);
463 error
= TT_Get_Glyph_Big_Metrics(glyph
, &metrics
);
465 error
= TT_Get_Glyph_Outline(glyph
, &outline
);
468 if (fnt
->efactor
!= 1.0 || fnt
->slant
!= 0.0 )
469 TT_Transform_Outline(&outline
, &matrix1
);
471 TT_Transform_Outline(&outline
, &matrix2
);
474 error
= TT_Get_Outline_BBox(&outline
, &bbox
); /* we need the non-
477 TT_Translate_Outline(&outline
,
478 metrics
.vertBearingY
- bbox
.xMin
,
479 -fnt
->y_offset
* ppem
* 64);
481 error
= TT_Get_Outline_BBox(&outline
, &bbox
);
483 SetRasterArea(quiet
);
489 TTFprocess(Font
*fnt
,
492 int *width
, int *height
,
493 int *hoff
, int *voff
,
501 if (!bitmap
|| !width
|| !height
|| !hoff
|| !voff
)
502 oops("Invalid parameter in call to TTFprocess()");
508 Num
= TT_Char_Index(char_map
, Code
);
512 error
= TT_GSUB_Apply_String(gsub
, &in
, &out
);
513 if (error
&& error
!= TTO_Err_Not_Covered
)
514 warning("Cannot get the vertical glyph form for glyph index %d.",
521 if ((error
= LoadTrueTypeChar(fnt
, Num
, hinting
, quiet
)) == TT_Err_Ok
)
523 memset(Bit
.bitmap
, 0, Bit
.size
);
524 TT_Get_Glyph_Bitmap(glyph
, &Bit
, x_offset
* 64, y_offset
* 64);
527 *bitmap
= Bit2
.bitmap
;
532 /* *voff = Bit2.rows - y_offset; */
533 /* printf("%D %d\n", *hoff, *voff); */
543 * We collect first all glyphs addressed via the cmap. Then we fill the
544 * array up with glyphs not in the cmap.
546 * If PSnames is set to `Only', we get the first 256 glyphs which have
547 * names different from `.notdef', `.null', and `nonmarkingreturn'.
549 * For nicer output, we return the glyph names in an encoding array.
553 TTFget_first_glyphs(Font
*fnt
, long *array
)
555 unsigned int i
, j
, Num
;
556 unsigned int index_array
[257]; /* we ignore glyph index 0 */
558 encoding
*e
= (encoding
*)mymalloc(sizeof (encoding
));
562 oops("Invalid parameter in call to TTFget_first_glyphs()");
564 for (i
= 0; i
< 257; i
++)
568 if (fnt
->PSnames
!= Only
)
570 for (i
= 0; i
<= 0xFFFF; i
++)
572 Num
= TT_Char_Index(char_map
, i
);
574 oops("cmap mapping failure.");
578 index_array
[Num
] = 1;
581 (void)TT_Get_PS_Name(face
, Num
, &n
);
583 n
= code_to_adobename(i
);
584 if (strcmp(n
, ".notdef") == 0)
586 if (strcmp(n
, ".null") == 0)
588 if (strcmp(n
, "nonmarkingreturn") == 0)
603 for (i
= 1; i
< properties
.num_Glyphs
; i
++)
605 if (index_array
[i
] == 0)
609 array
[j
] = i
| 0x10000;
610 e
->vec
[j
] = code_to_adobename(i
| 0x10000);
621 for (i
= 0; i
< properties
.num_Glyphs
; i
++)
626 (void)TT_Get_PS_Name(face
, i
, &n
);
628 if (strcmp(n
, ".notdef") == 0)
630 if (strcmp(n
, ".null") == 0)
632 if (strcmp(n
, "nonmarkingreturn") == 0)
637 array
[j
] = i
| 0x10000;
646 return NULL
; /* never reached */
651 * This routine fills `array' with the subfont character codes;
652 * additionally, it tests for valid glyph indices.
656 TTFget_subfont(Font
*fnt
, long *array
)
662 oops("Invalid parameter in call to TTFget_subfont()");
664 for (i
= 0; i
<= 0xFF; i
++)
672 Num
= TT_Char_Index(char_map
, j
);
674 oops("cmap mapping failure.");
683 TTFsearch_PS_name(char *name
)
689 for (i
= 0; i
< properties
.num_Glyphs
; i
++)
691 TT_Get_PS_Name(face
, i
, &n
);
692 if (strcmp(name
, n
) == 0)
696 if (i
== properties
.num_Glyphs
)