contrib/OWB: add correct SDL dependency, fix compilers used
[AROS-Contrib.git] / freetype1 / contrib / ttf2pk / ttfaux.c
blobdc969175d81a174aab44bb4e6a2306c09972188f
1 /*
2 * ttfaux.c
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>
9 */
11 #include <math.h>
12 #include <string.h>
13 #include <stdlib.h>
15 #include "freetype.h"
16 #include "extend/ftxkern.h" /* we are in the FreeType package tree */
17 #include "extend/ftxpost.h"
18 #include "extend/ftxopen.h"
20 #include "ttf2tfm.h"
21 #include "newobj.h"
22 #include "ligkern.h"
23 #include "ttfenc.h"
24 #include "tfmaux.h"
25 #include "errormsg.h"
26 #include "ttfaux.h"
27 #include "filesrch.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[];
49 char *real_ttfname;
51 TT_Engine engine;
52 TT_Face face;
53 TT_Instance instance;
54 TT_Glyph glyph;
55 TT_Outline outline;
56 TT_CharMap char_map;
57 TT_Matrix matrix1, matrix2;
59 TT_Big_Glyph_Metrics metrics;
60 TT_Face_Properties properties;
61 TT_BBox bbox;
63 TT_Kerning directory;
64 TT_Post post;
66 TTO_GSUBHeader gsub_;
67 TTO_GSUBHeader *gsub;
69 Boolean has_gsub;
73 static void
74 readttf_kern(Font *fnt)
76 register kern *nk;
77 register ttfinfo *ti;
78 TT_Kern_0_Pair* pairs0;
79 TT_Error error;
80 unsigned int i, j;
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)
87 return;
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)
96 case 0:
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);
101 if (ti == NULL)
102 warning("kern char not found");
103 else
105 nk = newkern();
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;
110 ti->kerns = nk;
113 return; /* we stop after the first format 0 kerning table */
115 default:
116 break;
119 return;
123 void
124 readttf(Font *fnt, Boolean quiet, Boolean only_range)
126 TT_Error error;
127 ttfinfo *ti, *Ti;
128 long Num, index;
129 unsigned int i, j;
130 long k, max_k;
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.
148 if (!only_range)
150 ti = newchar(fnt);
151 ti->charcode = -1;
152 ti->adobename = ".notdef";
154 ti = newchar(fnt);
155 ti->charcode = -1;
156 ti->adobename = "||"; /* boundary character name */
160 * Initialize FreeType engine.
163 if (!initialized)
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);
171 if (fnt->PSnames)
172 if ((error = TT_Init_Post_Extension(engine)))
173 oops("Cannot initialize PS name support (error code = 0x%x).", error);
175 if (fnt->rotate)
176 if ((error = TT_Init_GSUB_Extension(engine)))
177 oops("Cannot initialize GSUB support (error code = 0x%x).", error);
180 * Load face.
183 real_ttfname = TeX_search_ttf_file(&(fnt->ttfname));
184 if (!real_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.");
206 fnt->fontindex = 0;
207 fnt->fontindexparam = NULL;
209 else
211 TT_Close_Face(face);
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);
220 * Create instance.
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);
239 if (fnt->rotate)
241 matrix2.xx = 0;
242 matrix2.yx = 1L << 16;
243 matrix2.xy = -matrix2.yx;
244 matrix2.yy = matrix2.xx;
247 if ((error = TT_Set_Instance_Transform_Flags(
248 instance,
249 fnt->rotate ? 1 : 0,
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)
272 break;
274 if (i == num_cmap)
276 fprintf(stderr, "%s: ERROR: Invalid platform and/or encoding ID.\n",
277 progname);
278 if (num_cmap == 1)
279 fprintf(stderr, " The only valid PID/EID pair is");
280 else
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");
288 exit(1);
291 if ((error = TT_Get_CharMap(face, i, &char_map)))
292 oops("Cannot load cmap (error code = 0x%x).", error);
295 if (fnt->PSnames)
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);
306 else
307 set_encoding_scheme(encFontSpecific, fnt);
309 if (fnt->rotate)
311 gsub = &gsub_;
313 error = TT_Load_GSUB_Table(face, gsub, NULL);
314 if (!error)
315 has_gsub = True;
316 else if (error != TT_Err_Table_Missing)
317 warning("Cannot load GSUB table (error code = 0x%x).", error);
318 else
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,
325 SCRIPT_kana,
326 &script_index);
327 if (error)
328 goto check_hani;
329 error = TT_GSUB_Select_Feature(gsub,
330 FEATURE_vert,
331 script_index,
332 0xFFFF,
333 &feature_index);
334 if (error)
336 error = TT_GSUB_Select_Language(gsub,
337 LANGUAGE_JAN,
338 script_index,
339 &language_index,
340 &req_feature_index);
341 if (error)
342 goto check_hani;
343 error = TT_GSUB_Select_Feature(gsub,
344 FEATURE_vert,
345 script_index,
346 language_index,
347 &feature_index);
348 if (error)
349 goto check_hani;
350 else
351 goto Done;
353 else
354 goto Done;
356 check_hani:
357 error = TT_GSUB_Select_Script(gsub,
358 SCRIPT_hani,
359 &script_index);
360 if (error)
361 goto check_hang;
362 error = TT_GSUB_Select_Feature(gsub,
363 FEATURE_vert,
364 script_index,
365 0xFFFF,
366 &feature_index);
367 if (error)
369 error = TT_GSUB_Select_Language(gsub,
370 LANGUAGE_CHN,
371 script_index,
372 &language_index,
373 &req_feature_index);
374 if (error)
375 goto check_hang;
376 error = TT_GSUB_Select_Feature(gsub,
377 FEATURE_vert,
378 script_index,
379 language_index,
380 &feature_index);
381 if (error)
382 goto check_hang;
383 else
384 goto Done;
386 else
387 goto Done;
389 check_hang:
390 error = TT_GSUB_Select_Script(gsub,
391 SCRIPT_hang,
392 &script_index);
393 if (error)
394 goto Done;
395 error = TT_GSUB_Select_Feature(gsub,
396 FEATURE_vert,
397 script_index,
398 0xFFFF,
399 &feature_index);
400 if (error)
402 error = TT_GSUB_Select_Language(gsub,
403 LANGUAGE_KOR,
404 script_index,
405 &language_index,
406 &req_feature_index);
407 if (error)
408 goto Done;
409 error = TT_GSUB_Select_Feature(gsub,
410 FEATURE_vert,
411 script_index,
412 language_index,
413 &feature_index);
416 Done:
417 if (error)
419 warning("There is no data for vertical typesetting in GSUB table.");
420 has_gsub = False;
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);
427 in.length = 1;
428 in.pos = 0;
429 in.string = in_string;
430 in.properties = NULL;
432 out.pos = 0;
433 out.allocated = 0;
434 out.string = NULL;
435 out.properties = NULL;
438 initialized = True;
441 if (!quiet)
443 if (only_range)
444 printf("\n\n%s:\n", fnt->fullname);
445 printf("\n");
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
462 * mapping.
465 if (!only_range)
466 for (i = 0; i < 257; i++)
467 index_array[i] = 0;
468 else
469 for (i = 0; i < 256; i++)
470 fnt->inencptrs[i] = 0;
472 j = 0;
473 if (fnt->PSnames == Only)
474 max_k = properties.num_Glyphs - 1;
475 else
476 max_k = only_range ? 0xFF : 0xFFFF;
478 for (k = 0; k <= max_k; k++)
480 char *an;
483 if (fnt->PSnames != Only)
485 if (only_range)
487 index = fnt->sf_code[k];
488 if (index < 0)
489 continue;
490 j = k;
492 else
493 index = k;
495 Num = TT_Char_Index(char_map, index);
497 /* now we try to get a vertical glyph form */
499 if (has_gsub)
501 in_string[0] = Num;
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.",
505 Num);
506 else
507 Num = out.string[0];
510 if (Num < 0)
511 oops("Failure on cmap mapping from %s.", fnt->ttfname);
512 if (Num == 0)
513 continue;
514 if (!only_range)
515 if (Num <= 256)
516 index_array[Num] = 1;
518 else
520 Num = k;
521 index = 0;
524 error = TT_Load_Glyph(instance, glyph, Num, 0);
525 if (!error)
526 error = TT_Get_Glyph_Big_Metrics(glyph, &metrics);
527 if (!error)
528 error = TT_Get_Glyph_Outline(glyph, &outline);
529 if (!error)
531 if (fnt->efactor != 1.0 || fnt->slant != 0.0 )
532 TT_Transform_Outline(&outline, &matrix1);
533 if (fnt->rotate)
534 TT_Transform_Outline(&outline, &matrix2);
536 if (!error)
537 error = TT_Get_Outline_BBox(&outline, &bbox); /* we need the non-
538 grid-fitted bbox */
539 if (!error)
541 if (fnt->PSnames)
542 (void)TT_Get_PS_Name(face, Num, &an);
543 else
544 an = code_to_adobename(index);
546 /* ignore characters not usable for typesetting with TeX */
548 if (strcmp(an, ".notdef") == 0)
549 continue;
550 if (strcmp(an, ".null") == 0)
551 continue;
552 if (strcmp(an, "nonmarkingreturn") == 0)
553 continue;
555 ti = newchar(fnt);
556 ti->charcode = index;
557 ti->glyphindex = Num;
558 ti->adobename = an;
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.
569 if (fnt->rotate)
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.
584 if (ti->lly > 0)
585 ti->lly = 0;
586 if (ti->ury < 0)
587 ti->ury = 0;
588 if (fnt->rotate)
589 ti->width = metrics.vertAdvance * 1000 / fnt->units_per_em;
590 else
591 ti->width = transform(metrics.horiAdvance * 1000 / fnt->units_per_em,
592 0, fnt->efactor, fnt->slant);
594 if (!quiet)
595 printf("%5ld %04lx %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
596 Num, index, ti->adobename,
597 ti->width,
598 ti->llx, ti->lly, ti->urx, ti->ury);
600 if (j < 256)
602 fnt->inencptrs[j] = ti;
603 ti->incode = j;
605 j++;
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
612 * PS names.
615 if (!only_range && !fnt->PSnames)
617 for (i = 1; i <= properties.num_Glyphs; i++)
619 char *an;
622 if (index_array[i] == 0)
624 error = TT_Load_Glyph(instance, glyph, i, 0);
625 if (!error)
626 error = TT_Get_Glyph_Big_Metrics(glyph, &metrics);
627 if (!error)
628 error = TT_Get_Glyph_Outline(glyph, &outline);
629 if (!error)
630 error = TT_Get_Outline_BBox(&outline, &bbox);
631 if (!error)
633 an = code_to_adobename(i | 0x10000);
635 ti = newchar(fnt);
636 ti->charcode = i | 0x10000;
637 ti->glyphindex = i;
638 ti->adobename = an;
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;
644 if (ti->lly > 0)
645 ti->lly = 0;
646 if (ti->ury < 0)
647 ti->ury = 0;
648 ti->width = transform(metrics.horiAdvance*1000 / fnt->units_per_em,
649 0, fnt->efactor, fnt->slant);
651 if (!quiet)
652 printf("%5d %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
653 i, ti->adobename,
654 ti->width,
655 ti->llx, ti->lly, ti->urx, ti->ury);
657 if (j < 256)
659 fnt->inencptrs[j] = ti;
660 ti->incode = j;
662 else
663 break;
664 j++;
670 /* Finally, we construct a `Germandbls' glyph if necessary */
672 if (!only_range)
674 if (NULL == findadobe("Germandbls", fnt->charlist) &&
675 NULL != (Ti = findadobe("S", fnt->charlist)))
677 pcc *np, *nq;
680 ti = newchar(fnt);
681 ti->charcode = properties.num_Glyphs | 0x10000;
682 ti->glyphindex = properties.num_Glyphs;
683 ti->adobename = "Germandbls";
684 ti->width = Ti->width << 1;
685 ti->llx = Ti->llx;
686 ti->lly = Ti->lly;
687 ti->urx = Ti->width + Ti->urx;
688 ti->ury = Ti->ury;
689 ti->kerns = Ti->kerns;
691 np = newpcc();
692 np->partname = "S";
693 nq = newpcc();
694 nq->partname = "S";
695 nq->xoffset = Ti->width;
696 np->next = nq;
697 ti->pccs = np;
698 ti->constructed = True;
700 if (!quiet)
701 printf("* %-25s %5d % 5d,% 5d -- % 5d,% 5d\n",
702 ti->adobename,
703 ti->width,
704 ti->llx, ti->lly, ti->urx, ti->ury);
708 /* kerning between subfonts isn't available */
709 if (!only_range)
710 readttf_kern(fnt);
714 /* end */