contrib/OWB: add correct SDL dependency, fix compilers used
[AROS-Contrib.git] / freetype1 / contrib / ttf2pk / ttflib.c
blob3cadaa240297ae5f79623150b3ef6857ea89340f
1 /*
2 * ttflib.c
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>
9 */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <math.h> /* libc ANSI */
15 #include <ctype.h>
17 #include "pklib.h" /* for the `byte' type */
18 #include "freetype.h"
19 #include "ttfenc.h"
20 #include "ttflib.h"
21 #include "errormsg.h"
22 #include "newobj.h"
23 #include "ttf2tfm.h"
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')
47 TT_Engine engine;
48 TT_Face face;
49 TT_Instance instance;
50 TT_Glyph glyph;
51 TT_CharMap char_map;
53 TT_Outline outline;
54 TT_Face_Properties properties;
55 TT_BBox bbox;
57 TT_Post post;
59 TT_Raster_Map Bit, Bit2;
60 void *Bitp, *Bit2p;
62 int dpi;
63 int ptsize;
65 int x_offset, y_offset;
66 int ppem;
68 TT_Big_Glyph_Metrics metrics;
70 TT_Matrix matrix1, matrix2;
72 TTO_GSUBHeader gsub_;
73 TTO_GSUBHeader *gsub;
75 TT_UShort in_string[2];
76 TTO_GSUB_String in, out;
78 Boolean has_gsub;
81 static void
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;
95 if (!quiet)
96 printf(" off = (%d, %d)", x_offset, y_offset);
98 #if 0
99 x_offset = y_offset = 0;
100 #endif
102 if (!quiet)
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.
118 if (Bitp)
119 free(Bitp);
120 Bitp = mymalloc(Bit.size + Bit.cols);
121 Bit.bitmap = Bitp;
123 Bit2 = Bit;
125 if (Bit2p)
126 free(Bit2p);
127 Bit2p = mymalloc(Bit.size + Bit.cols);
128 Bit2.bitmap = Bit2p;
132 static void
133 FlipBit(void)
135 int y;
136 char *p1, *p2;
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);
144 p1 += Bit.cols;
145 p2 -= Bit.cols;
150 #if 0
152 static void
153 Output(TT_Raster_Map Bit)
155 int x;
156 int y;
157 int i;
159 char *p, b;
162 p = Bit.bitmap;
163 printf("====\n");
165 for (y = 0; y < Bit.rows; y++)
167 printf("%3d:", y);
168 for (x = 0; x < Bit.cols; x++)
170 b = *p++;
171 for(i = 0x80; i; i >>= 1)
172 printf((b & i) ? "x" : ".");
174 printf("\n");
178 #endif /* 0 */
181 void
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;
187 TT_Error error;
189 TT_UShort script_index, language_index, feature_index;
190 TT_UShort req_feature_index = 0xFFFF;
193 dpi = new_dpi;
194 ptsize = new_ptsize;
196 if ((error = TT_Init_FreeType(&engine)))
197 oops("Cannot initialize FreeType engine (error code = 0x%x).", error);
199 if (fnt->PSnames)
200 if ((error = TT_Init_Post_Extension(engine)))
201 oops("Cannot initialize PS name support (error code = 0x%x).", error);
203 if (fnt->rotate)
204 if ((error = TT_Init_GSUB_Extension(engine)))
205 oops("Cannot initialize GSUB support (error code = 0x%x).", error);
208 * Load face.
211 error = TT_Open_Face(engine, filename, &face);
212 if (error)
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.");
230 else
232 TT_Close_Face(face);
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);
241 * Create instance.
244 if ((error = TT_New_Instance(face, &instance)))
245 oops("Cannot create instance for `%s' (error code = 0x%x).",
246 filename, error);
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;
256 if (!quiet)
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);
264 if (fnt->rotate)
266 matrix2.xx = 0;
267 matrix2.yx = 1L << 16;
268 matrix2.xy = -matrix2.yx;
269 matrix2.yy = matrix2.xx;
272 if ((error = TT_Set_Instance_Transform_Flags(
273 instance,
274 fnt->rotate ? 1 : 0,
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)
293 break;
295 if (i == num_cmap)
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);
302 if (fnt->PSnames)
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);
313 else
314 set_encoding_scheme(encFontSpecific, fnt);
316 if (fnt->rotate)
318 gsub = &gsub_;
320 error = TT_Load_GSUB_Table(face, gsub, NULL);
321 if (!error)
322 has_gsub = True;
323 else if (error != TT_Err_Table_Missing)
324 warning("Cannot load GSUB table (error code = 0x%x).", error);
325 else
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,
332 SCRIPT_kana,
333 &script_index);
334 if (error)
335 goto check_hani;
336 error = TT_GSUB_Select_Feature(gsub,
337 FEATURE_vert,
338 script_index,
339 0xFFFF,
340 &feature_index);
341 if (error)
343 error = TT_GSUB_Select_Language(gsub,
344 LANGUAGE_JAN,
345 script_index,
346 &language_index,
347 &req_feature_index);
348 if (error)
349 goto check_hani;
350 error = TT_GSUB_Select_Feature(gsub,
351 FEATURE_vert,
352 script_index,
353 language_index,
354 &feature_index);
355 if (error)
356 goto check_hani;
357 else
358 goto Done;
360 else
361 goto Done;
363 check_hani:
364 error = TT_GSUB_Select_Script(gsub,
365 SCRIPT_hani,
366 &script_index);
367 if (error)
368 goto check_hang;
369 error = TT_GSUB_Select_Feature(gsub,
370 FEATURE_vert,
371 script_index,
372 0xFFFF,
373 &feature_index);
374 if (error)
376 error = TT_GSUB_Select_Language(gsub,
377 LANGUAGE_CHN,
378 script_index,
379 &language_index,
380 &req_feature_index);
381 if (error)
382 goto check_hang;
383 error = TT_GSUB_Select_Feature(gsub,
384 FEATURE_vert,
385 script_index,
386 language_index,
387 &feature_index);
388 if (error)
389 goto check_hang;
390 else
391 goto Done;
393 else
394 goto Done;
396 check_hang:
397 error = TT_GSUB_Select_Script(gsub,
398 SCRIPT_hang,
399 &script_index);
400 if (error)
401 goto Done;
402 error = TT_GSUB_Select_Feature(gsub,
403 FEATURE_vert,
404 script_index,
405 0xFFFF,
406 &feature_index);
407 if (error)
409 error = TT_GSUB_Select_Language(gsub,
410 LANGUAGE_KOR,
411 script_index,
412 &language_index,
413 &req_feature_index);
414 if (error)
415 goto Done;
416 error = TT_GSUB_Select_Feature(gsub,
417 FEATURE_vert,
418 script_index,
419 language_index,
420 &feature_index);
423 Done:
424 if (error)
426 warning("There is no data for vertical typesetting in GSUB table.");
427 has_gsub = False;
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);
434 in.length = 1;
435 in.pos = 0;
436 in.string = in_string;
437 in.properties = NULL;
439 out.pos = 0;
440 out.allocated = 0;
441 out.string = NULL;
442 out.properties = NULL;
447 static TT_Error
448 LoadTrueTypeChar(Font *fnt,
449 int idx,
450 Boolean hint,
451 Boolean quiet)
453 TT_Error error;
454 int flags;
457 flags = TTLOAD_SCALE_GLYPH;
458 if (hint)
459 flags |= TTLOAD_HINT_GLYPH;
461 error = TT_Load_Glyph(instance, glyph, idx, flags);
462 if (!error)
463 error = TT_Get_Glyph_Big_Metrics(glyph, &metrics);
464 if (!error)
465 error = TT_Get_Glyph_Outline(glyph, &outline);
466 if (!error)
468 if (fnt->efactor != 1.0 || fnt->slant != 0.0 )
469 TT_Transform_Outline(&outline, &matrix1);
470 if (fnt->rotate)
471 TT_Transform_Outline(&outline, &matrix2);
473 if (!error)
474 error = TT_Get_Outline_BBox(&outline, &bbox); /* we need the non-
475 grid-fitted bbox */
476 if (fnt->rotate)
477 TT_Translate_Outline(&outline,
478 metrics.vertBearingY - bbox.xMin,
479 -fnt->y_offset * ppem * 64);
480 if (!error)
481 error = TT_Get_Outline_BBox(&outline, &bbox);
482 if (!error)
483 SetRasterArea(quiet);
484 return error;
488 Boolean
489 TTFprocess(Font *fnt,
490 long Code,
491 byte **bitmap,
492 int *width, int *height,
493 int *hoff, int *voff,
494 Boolean hinting,
495 Boolean quiet)
497 int Num;
498 TT_Error error;
501 if (!bitmap || !width || !height || !hoff || !voff)
502 oops("Invalid parameter in call to TTFprocess()");
504 if (Code >= 0x10000)
505 Num = Code & 0xFFFF;
506 else
508 Num = TT_Char_Index(char_map, Code);
509 if (has_gsub)
511 in_string[0] = Num;
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.",
515 Num);
516 else
517 Num = out.string[0];
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);
526 FlipBit();
527 *bitmap = Bit2.bitmap;
528 *width = Bit2.width;
529 *height = Bit2.rows;
530 *hoff = x_offset;
531 *voff = y_offset;
532 /* *voff = Bit2.rows - y_offset; */
533 /* printf("%D %d\n", *hoff, *voff); */
534 /* Output(Bit2); */
535 return True;
537 else
538 return False;
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.
552 encoding *
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 */
557 char *n;
558 encoding *e = (encoding *)mymalloc(sizeof (encoding));
561 if (!array)
562 oops("Invalid parameter in call to TTFget_first_glyphs()");
564 for (i = 0; i < 257; i++)
565 index_array[i] = 0;
567 j = 0;
568 if (fnt->PSnames != Only)
570 for (i = 0; i <= 0xFFFF; i++)
572 Num = TT_Char_Index(char_map, i);
573 if (Num < 0)
574 oops("cmap mapping failure.");
575 if (Num == 0)
576 continue;
577 if (Num <= 256)
578 index_array[Num] = 1;
580 if (fnt->PSnames)
581 (void)TT_Get_PS_Name(face, Num, &n);
582 else
583 n = code_to_adobename(i);
584 if (strcmp(n, ".notdef") == 0)
585 continue;
586 if (strcmp(n, ".null") == 0)
587 continue;
588 if (strcmp(n, "nonmarkingreturn") == 0)
589 continue;
591 if (j < 256)
593 array[j] = i;
594 e->vec[j] = n;
596 else
597 return e;
598 j++;
601 if (!fnt->PSnames)
603 for (i = 1; i < properties.num_Glyphs; i++)
605 if (index_array[i] == 0)
607 if (j < 256)
609 array[j] = i | 0x10000;
610 e->vec[j] = code_to_adobename(i | 0x10000);
612 else
613 return e;
614 j++;
619 else
621 for (i = 0; i < properties.num_Glyphs; i++)
623 char *n;
626 (void)TT_Get_PS_Name(face, i, &n);
628 if (strcmp(n, ".notdef") == 0)
629 continue;
630 if (strcmp(n, ".null") == 0)
631 continue;
632 if (strcmp(n, "nonmarkingreturn") == 0)
633 continue;
635 if (j < 256)
637 array[j] = i | 0x10000;
638 e->vec[j] = n;
640 else
641 return e;
642 j++;
646 return NULL; /* never reached */
651 * This routine fills `array' with the subfont character codes;
652 * additionally, it tests for valid glyph indices.
655 void
656 TTFget_subfont(Font *fnt, long *array)
658 int i, j, Num;
661 if (!fnt || !array)
662 oops("Invalid parameter in call to TTFget_subfont()");
664 for (i = 0; i <= 0xFF; i++)
666 j = fnt->sf_code[i];
668 if (j < 0)
669 array[i] = j;
670 else
672 Num = TT_Char_Index(char_map, j);
673 if (Num < 0)
674 oops("cmap mapping failure.");
675 else
676 array[i] = j;
682 long
683 TTFsearch_PS_name(char *name)
685 unsigned int i;
686 char *n;
689 for (i = 0; i < properties.num_Glyphs; i++)
691 TT_Get_PS_Name(face, i, &n);
692 if (strcmp(name, n) == 0)
693 break;
696 if (i == properties.num_Glyphs)
697 return -1L;
698 else
699 return (long)i;
703 /* end */