beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / fontforge / fontforge / parsettf.c
blob5a3d3b58d20ef13ca58191fd85a5b0e731d151b8
1 /* Copyright (C) 2000-2008 by George Williams */
2 /*
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "pfaedit.h"
28 #include <chardata.h>
29 #include <utype.h>
30 #include <ustring.h>
31 #include <math.h>
32 #include <locale.h>
33 #include "ttf.h"
35 extern char *AdobeStandardEncoding[], *AdobeExpertEncoding[];
36 extern const char *ttfstandardnames[];
37 extern int ask_user_for_cmap;
38 extern char *SaveTablesPref;
40 #ifdef LUA_FF_LIB
41 SplineFont *_SFReadTTFInfo(FILE *ttf, int flags,enum openflags openflags, char *filename,struct fontdict *fd);
42 void THPatchSplineChar(SplineChar *sc);
43 #endif
45 int THtest_duplicate_glyph_names = 0;
46 int THread_ttf_glyph_data = 0;
48 char *SaveTablesPref;
49 int ask_user_for_cmap = false;
51 /* True Type is a really icky format. Nothing is together. It's badly described */
52 /* much of the description is misleading */
53 /* Apple's version: */
54 /* http://fonts.apple.com/TTRefMan/index.html */
55 /* MS's version: */
56 /* http://www.microsoft.com/typography/tt/tt.htm */
57 /* An helpful but incomplete description is given at */
58 /* http://www.truetype.demon.co.uk/ttoutln.htm */
59 /* For some things I looked at freetype's code to see how they did it */
60 /* (I think only for what happens if !ARGS_ARE_XY) */
61 /* http://freetype.sourceforge.net/ */
62 /* It grows on you though... now that I understand it better it seems better designed */
63 /* but the docs remain in conflict. Sometimes badly so */
65 int prefer_cjk_encodings=false;
67 /* ************************************************************************** */
68 static struct ms_2_locales { char *loc_name; int local_id; } ms_2_locals[] = {
69 { "af", 0x436 },
70 { "sq_AL", 0x41c },
71 { "am", 0x45e },
72 { "ar_SA", 0x401 },
73 { "ar_IQ", 0x801 },
74 { "ar_EG", 0xc01 },
75 { "ar_LY", 0x1001 },
76 { "ar_DZ", 0x1401 },
77 { "ar_MA", 0x1801 },
78 { "ar_TN", 0x1C01 },
79 { "ar_OM", 0x2001 },
80 { "ar_YE", 0x2401 },
81 { "ar_SY", 0x2801 },
82 { "ar_JO", 0x2c01 },
83 { "ar_LB", 0x3001 },
84 { "ar_KW", 0x3401 },
85 { "ar_AE", 0x3801 },
86 { "ar_BH", 0x3c01 },
87 { "ar_QA", 0x4001 },
88 { "hy", 0x42b },
89 { "as", 0x44d },
90 { "az", 0x42c },
91 { "az", 0x82c },
92 { "eu", 0x42d },
93 { "be_BY", 0x423 },
94 { "bn_IN", 0x445 },
95 { "bn_BD", 0x845 },
96 { "bg_BG", 0x402 },
97 { "my", 0x455 },
98 { "ca", 0x403 },
99 { "km", 0x453 },
100 { "zh_TW", 0x404 }, /* Trad */
101 { "zh_CN", 0x804 }, /* Simp */
102 { "zh_HK", 0xc04 }, /* Trad */
103 { "zh_SG", 0x1004 }, /* Simp */
104 { "zh_MO", 0x1404 }, /* Trad */
105 { "hr", 0x41a },
106 { "hr_BA", 0x101a },
107 { "cs_CZ", 0x405 },
108 { "da_DK", 0x406 },
109 { "div", 0x465 },
110 { "nl_NL", 0x413 },
111 { "nl_BE", 0x813 },
112 { "en_UK", 0x809 },
113 { "en_US", 0x409 },
114 { "en_CA", 0x1009 },
115 { "en_AU", 0xc09 },
116 { "en_NZ", 0x1409 },
117 { "en_IE", 0x1809 },
118 { "en_ZA", 0x1c09 },
119 { "en_JM", 0x2009 },
120 { "en", 0x2409 },
121 { "en_BZ", 0x2809 },
122 { "en_TT", 0x2c09 },
123 { "en_ZW", 0x3009 },
124 { "en_PH", 0x3409 },
125 { "en_ID", 0x3809 },
126 { "en_HK", 0x3c09 },
127 { "en_IN", 0x4009 },
128 { "en_MY", 0x4409 },
129 { "et_EE", 0x425 },
130 { "fo", 0x438 },
131 /* No language code for filipino */
132 { "fa", 0x429 },
133 { "fi_FI", 0x40b },
134 { "fr_FR", 0x40c },
135 { "fr_BE", 0x80c },
136 { "fr_CA", 0xc0c },
137 { "fr_CH", 0x100c },
138 { "fr_LU", 0x140c },
139 { "fr_MC", 0x180c },
140 { "fr", 0x1c0c }, /* West Indes */
141 { "fr_RE", 0x200c },
142 { "fr_CD", 0x240c },
143 { "fr_SN", 0x280c },
144 { "fr_CM", 0x2c0c },
145 { "fr_CI", 0x300c },
146 { "fr_ML", 0x340c },
147 { "fr_MA", 0x380c },
148 { "fr_HT", 0x3c0c },
149 { "fr_DZ", 0xe40c }, /* North African is most likely to be Algeria, possibly Tunisia */
150 { "fy", 0x462 },
151 { "gl", 0x456 },
152 { "ka", 0x437 },
153 { "de_DE", 0x407 },
154 { "de_CH", 0x807 },
155 { "de_AT", 0xc07 },
156 { "de_LU", 0x1007 },
157 { "de_LI", 0x1407 },
158 { "el_GR", 0x408 },
159 { "ga", 0x83c },
160 { "gd", 0x43c },
161 { "gn", 0x474 },
162 { "gu", 0x447 },
163 { "ha", 0x468 },
164 { "he_IL", 0x40d },
165 { "iw", 0x40d }, /* Obsolete name for Hebrew */
166 { "hi", 0x439 },
167 { "hu_HU", 0x40e },
168 { "is_IS", 0x40f },
169 { "id", 0x421 },
170 { "in", 0x421 }, /* Obsolete name for Indonesean */
171 { "iu", 0x45d },
172 { "it_IT", 0x410 },
173 { "it_CH", 0x810 },
174 { "ja_JP", 0x411 },
175 { "kn", 0x44b },
176 { "ks_IN", 0x860 },
177 { "kk", 0x43f },
178 { "ky", 0x440 },
179 { "km", 0x453 },
180 { "kok", 0x457 },
181 { "ko", 0x412 },
182 { "ko", 0x812 }, /*Johab */
183 { "lo", 0x454 },
184 { "la", 0x476 },
185 { "lv_LV", 0x426 },
186 { "lt_LT", 0x427 },
187 { "lt", 0x827 }, /* Classic */
188 { "mk", 0x42f },
189 { "ms", 0x43e },
190 { "ms", 0x83e },
191 { "ml", 0x44c },
192 { "mt", 0x43a },
193 { "mr", 0x44e },
194 { "mn", 0x450 },
195 { "ne_NP", 0x461 },
196 { "ne_IN", 0x861 },
197 { "no_NO", 0x414 }, /* Bokmal */
198 { "no_NO", 0x814 }, /* Nynorsk */
199 { "or", 0x448 },
200 { "om", 0x472 },
201 { "ps", 0x463 },
202 { "pl_PL", 0x415 },
203 { "pt_PT", 0x416 },
204 { "pt_BR", 0x816 },
205 { "pa_IN", 0x446 },
206 { "pa_PK", 0x846 },
207 { "qu_BO", 0x46b },
208 { "qu_EC", 0x86b },
209 { "qu_PE", 0xc6b },
210 { "rm", 0x417 },
211 { "ro_RO", 0x418 },
212 { "ro_MD", 0x818 },
213 { "ru_RU", 0x419 },
214 { "ru_MD", 0x819 },
215 { "smi", 0x43b },
216 { "sa", 0x43b },
217 /* No language code for Sepedi */
218 { "sr", 0xc1a }, /* Cyrillic */
219 { "sr", 0x81a }, /* Latin */
220 { "sd_IN", 0x459 },
221 { "sd_PK", 0x859 },
222 { "si", 0x45b },
223 { "sk_SK", 0x41b },
224 { "sl_SI", 0x424 },
225 { "wen", 0x42e },
226 { "es_ES", 0x40a }, /* traditional spanish */
227 { "es_MX", 0x80a },
228 { "es_ES", 0xc0a }, /* Modern spanish */
229 { "es_GT", 0x100a },
230 { "es_CR", 0x140a },
231 { "es_PA", 0x180a },
232 { "es_DO", 0x1c0a },
233 { "es_VE", 0x200a },
234 { "es_CO", 0x240a },
235 { "es_PE", 0x280a },
236 { "es_AR", 0x2c0a },
237 { "es_EC", 0x300a },
238 { "es_CL", 0x340a },
239 { "es_UY", 0x380a },
240 { "es_PY", 0x3c0a },
241 { "es_BO", 0x400a },
242 { "es_SV", 0x440a },
243 { "es_HN", 0x480a },
244 { "es_NI", 0x4c0a },
245 { "es_PR", 0x500a },
246 { "es_US", 0x540a },
247 { "sutu", 0x430 },
248 { "sw_KE", 0x441 },
249 { "sv_SE", 0x41d },
250 { "sv_FI", 0x81d },
251 { "tl", 0x464 },
252 { "tg", 0x464 },
253 { "ta", 0x449 },
254 { "tt", 0x444 },
255 { "te", 0x44a },
256 { "th", 0x41e },
257 { "bo_CN", 0x451 },
258 { "bo_BT", 0x451 },
259 { "ti_ET", 0x473 },
260 { "ti_ER", 0x873 },
261 { "ts", 0x431 },
262 { "tn", 0x432 },
263 { "tr_TR", 0x41f },
264 { "tk", 0x442 },
265 { "uk_UA", 0x422 },
266 { "ug", 0x480 },
267 { "ur_PK", 0x420 },
268 { "ur_IN", 0x820 },
269 { "uz", 0x443 }, /* Latin */
270 { "uz", 0x843 }, /* Cyrillic */
271 { "ven", 0x433 },
272 { "vi", 0x42a },
273 { "cy", 0x452 },
274 { "xh", 0x434 },
275 { "yi", 0x43d },
276 { "ji", 0x43d }, /* Obsolete Yiddish */
277 { "yo", 0x46a },
278 { "zu", 0x435 },
279 { NULL, 0 }};
281 int MSLanguageFromLocale(void) {
282 const char *lang=NULL;
283 int i, langlen;
284 static char *envs[] = { "LC_ALL", "LC_MESSAGES", "LANG", NULL };
285 char langcountry[8], language[4];
286 int langcode, langlocalecode;
288 for ( i=0; envs[i]!=NULL; ++i ) {
289 lang = getenv(envs[i]);
290 if ( lang!=NULL ) {
291 langlen = strlen(lang);
292 if (( langlen>5 && lang[5]=='.' && lang[2]=='_' ) ||
293 (langlen==5 && lang[2]=='_' ) ||
294 (langlen==2) ||
295 (langlen==3)) /* Some obscure languages have a 3 letter code */
296 /* I understand this language */
297 break;
300 if ( lang==NULL )
301 lang = "en_US";
302 strncpy(langcountry,lang,5); langcountry[5] = '\0';
303 strncpy(language,lang,3); language[3] = '\0';
304 if ( language[2]=='_' ) language[2] = '\0';
305 langlen = strlen(language);
307 langcode = langlocalecode = -1;
308 for ( i=0; ms_2_locals[i].loc_name!=NULL; ++i ) {
309 if ( strmatch(langcountry,ms_2_locals[i].loc_name)==0 ) {
310 langlocalecode = ms_2_locals[i].local_id;
311 langcode = langlocalecode&0x3ff;
312 break;
313 } else if ( strncmp(language,ms_2_locals[i].loc_name,langlen)==0 )
314 langcode = ms_2_locals[i].local_id&0x3ff;
316 if ( langcode==-1 ) /* Default to English */
317 langcode = 0x9;
318 return( langlocalecode==-1 ? (langcode|0x400) : langlocalecode );
320 /* ************************************************************************** */
322 int getushort(FILE *ttf) {
323 int ch1 = getc(ttf);
324 int ch2 = getc(ttf);
325 if ( ch2==EOF )
326 return( EOF );
327 return( (ch1<<8)|ch2 );
330 int get3byte(FILE *ttf) {
331 int ch1 = getc(ttf);
332 int ch2 = getc(ttf);
333 int ch3 = getc(ttf);
334 if ( ch3==EOF )
335 return( EOF );
336 return( (ch1<<16)|(ch2<<8)|ch3 );
339 int32 getlong(FILE *ttf) {
340 int ch1 = getc(ttf);
341 int ch2 = getc(ttf);
342 int ch3 = getc(ttf);
343 int ch4 = getc(ttf);
344 if ( ch4==EOF )
345 return( EOF );
346 return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
349 static int32 getoffset(FILE *ttf, int offsize) {
350 if ( offsize==1 )
351 return( getc(ttf));
352 else if ( offsize==2 )
353 return( getushort(ttf));
354 else if ( offsize==3 )
355 return( get3byte(ttf));
356 else
357 return( getlong(ttf));
360 real getfixed(FILE *ttf) {
361 int32 val = getlong(ttf);
362 int mant = val&0xffff;
363 /* This oddity may be needed to deal with the first 16 bits being signed */
364 /* and the low-order bits unsigned */
365 return( (real) (val>>16) + (mant/65536.0) );
368 real get2dot14(FILE *ttf) {
369 int32 val = getushort(ttf);
370 int mant = val&0x3fff;
371 /* This oddity may be needed to deal with the first 2 bits being signed */
372 /* and the low-order bits unsigned */
373 return( (real) ((val<<16)>>(16+14)) + (mant/16384.0) );
376 static Encoding *enc_from_platspec(int platform,int specific) {
377 char *enc;
378 Encoding *e;
380 enc = "Custom";
381 if ( platform==0 ) {
382 enc = "Unicode";
383 if ( specific==4 )
384 enc = "UnicodeFull";
385 } else if ( platform==1 ) {
386 if ( specific==0 )
387 enc = "Mac";
388 else if ( specific==1 )
389 enc = "Sjis";
390 else if ( specific==2 )
391 enc = "Big5hkscs"; /* Or should we just guess big5? Both are wrong sometimes */
392 else if ( specific==3 )
393 enc = "EUC-KR";
394 else if ( specific==25 )
395 enc = "EUC-CN";
396 } else if ( platform==2 ) { /* obselete */
397 if ( specific==0 )
398 enc = "ASCII";
399 else if ( specific==1 )
400 enc = "Unicode";
401 else if ( specific==2 )
402 enc = "ISO8859-1";
403 } else if ( platform==3 ) {
404 if ( specific==1 || specific==0 ) /* symbol (sp=0) is just unicode (PUA) */
405 enc = "Unicode";
406 else if ( specific==2 )
407 enc = "Sjis";
408 else if ( specific==3 )
409 enc = "EUC-CN";
410 else if ( specific==4 )
411 enc = "Big5hkscs";
412 else if ( specific==5 )
413 enc = "EUC-KR";
414 else if ( specific==6 )
415 enc = "Johab";
416 else if ( specific==10 )
417 enc = "UnicodeFull";
418 } else if ( platform==7 ) { /* Used internally in freetype, but */
419 if ( specific==0 ) /* there's no harm in looking for it */
420 enc = "AdobeStandard"; /* even if it never happens */
421 else if ( specific==1 ) {
422 /* adobe_expert */;
423 } else if ( specific==2 ) {
424 /* adobe_custom */;
427 e = FindOrMakeEncoding(enc);
428 if ( e==NULL ) {
429 static int p = -1,s = -1;
430 if ( p!=platform || s!=specific ) {
431 LogError( _("The truetype encoding specified by platform=%d specific=%d (which we map to %s) is not supported by your version of iconv(3).\n"),
432 platform, specific, enc );
433 p = platform; s = specific;
436 return( e );
439 static char *_readencstring(FILE *ttf,int offset,int len,
440 int platform,int specific,int language) {
441 long pos = ftell(ttf);
442 unichar_t *str, *pt;
443 char *ret;
444 int i, ch;
445 Encoding *enc;
447 fseek(ttf,offset,SEEK_SET);
449 if ( platform==1 ) {
450 /* Mac is screwy, there are several different varients of MacRoman */
451 /* depending on the language, they didn't get it right when they */
452 /* invented their script system */
453 char *cstr, *cpt;
454 cstr = cpt = galloc(len+1);
455 for ( i=0; i<len; ++i )
456 *cpt++ = getc(ttf);
457 *cpt = '\0';
458 ret = MacStrToUtf8(cstr,specific,language);
459 free(cstr);
460 } else {
461 enc = enc_from_platspec(platform,specific);
462 if ( enc==NULL )
463 return( NULL );
464 if ( enc->is_unicodebmp ) {
465 str = pt = galloc((sizeof(unichar_t)/2)*len+sizeof(unichar_t));
466 for ( i=0; i<len/2; ++i ) {
467 ch = getc(ttf)<<8;
468 *pt++ = ch | getc(ttf);
470 *pt = 0;
471 } else if ( enc->unicode!=NULL ) {
472 str = pt = galloc(sizeof(unichar_t)*len+sizeof(unichar_t));
473 for ( i=0; i<len; ++i )
474 *pt++ = enc->unicode[getc(ttf)];
475 *pt = 0;
476 } else if ( enc->tounicode!=NULL ) {
477 size_t inlen = len+1, outlen = sizeof(unichar_t)*(len+1);
478 char *cstr = galloc(inlen);
479 ICONV_CONST char *in = cstr;
480 char *out;
481 #ifdef UNICHAR_16
482 str = galloc(outlen+2);
483 #else
484 str = galloc(outlen+sizeof(unichar_t));
485 #endif
486 /*str = galloc(outlen+2);*/
487 out = (char *) str;
488 iconv(enc->tounicode,&in,&inlen,&out,&outlen);
489 out[0] = '\0'; out[1] = '\0';
490 #ifndef UNICHAR_16
491 out[2] = '\0'; out[3] = '\0';
492 #endif
493 free(cstr);
494 } else {
495 str = uc_copy("");
497 ret = u2utf8_copy(str);
498 free(str);
500 fseek(ttf,pos,SEEK_SET);
501 return( ret );
504 char *TTFGetFontName(FILE *ttf,int32 offset,int32 off2) {
505 int i,num;
506 int32 tag, length, stringoffset;
507 int plat, spec, lang, name, len, off, val;
508 Encoding *enc;
509 int32 nameoffset = 0;
510 int fullval=0, fullstr=0, fulllen=0, famval=0, famstr=0, famlen=0;
511 int fullplat=0, fullspec=0, fulllang=0, famplat=0, famspec=0, famlang=0;
512 int locale = MSLanguageFromLocale();
513 int maclang = WinLangToMac(locale);
515 fseek(ttf,offset,SEEK_SET);
516 /* version = */ getlong(ttf);
517 num = getushort(ttf);
518 /* srange = */ getushort(ttf);
519 /* esel = */ getushort(ttf);
520 /* rshift = */ getushort(ttf);
521 for ( i=0; i<num; ++i ) {
522 tag = getlong(ttf);
523 /* checksum = */ getlong(ttf);
524 nameoffset = off2+getlong(ttf);
525 length = getlong(ttf);
526 if ( tag==CHR('n','a','m','e'))
527 break;
529 if ( i==num )
530 return( NULL );
532 fseek(ttf,nameoffset,SEEK_SET);
533 /* format = */ getushort(ttf);
534 num = getushort(ttf);
535 stringoffset = nameoffset+getushort(ttf);
536 fullval = famval = 0;
537 for ( i=0; i<num; ++i ) {
538 plat = getushort(ttf);
539 spec = getushort(ttf);
540 lang = getushort(ttf);
541 name = getushort(ttf);
542 len = getushort(ttf);
543 off = getushort(ttf);
544 enc = enc_from_platspec(plat,spec);
545 if ( enc==NULL )
546 continue;
547 val = 0;
548 if ( plat==3 && !enc->is_custom && lang==locale )
549 val = 15;
550 else if ( plat==3 && !enc->is_custom && (lang&0xff)==(locale&0xff) )
551 val = 14;
552 else if ( (plat==0 || plat==1) && !enc->is_custom && lang==maclang )
553 val = 13;
554 /* Ok, that didn't work, how about an english name? */
555 else if ( plat==3 && !enc->is_custom && lang==0x409 )
556 val = 12;
557 else if ( plat==3 && !enc->is_custom && (lang&0xff)==0x09 )
558 val = 11;
559 else if ( (plat==0 || plat==1) && !enc->is_custom && lang==0 )
560 val = 10;
561 /* failing that I'll take what I can get */
562 else if ( !enc->is_custom )
563 val = 1;
564 if ( name==4 && val>fullval ) {
565 fullval = val;
566 fullstr = off;
567 fulllen = len;
568 fullplat = plat;
569 fullspec = spec;
570 fulllang = lang;
571 if ( val==12 )
572 break;
573 } else if ( name==1 && val>famval ) {
574 famval = val;
575 famstr = off;
576 famlen = len;
577 famplat = plat;
578 famspec = spec;
579 famlang = lang;
582 if ( fullval==0 ) {
583 if ( famval==0 )
584 return( NULL );
585 fullstr = famstr;
586 fulllen = famlen;
587 fullplat = famplat;
588 fullspec = famspec;
589 fulllang = famlang;
591 return( _readencstring(ttf,stringoffset+fullstr,fulllen,fullplat,fullspec,fulllang));
595 char *TTFGetPSFontName(FILE *ttf,int32 offset,int32 off2) {
596 int i,num;
597 int32 tag, length, stringoffset;
598 int name, len, off;
599 int32 nameoffset = 0;
601 fseek(ttf,offset,SEEK_SET);
602 /* version = */ getlong(ttf);
603 num = getushort(ttf);
604 /* srange = */ getushort(ttf);
605 /* esel = */ getushort(ttf);
606 /* rshift = */ getushort(ttf);
607 for ( i=0; i<num; ++i ) {
608 tag = getlong(ttf);
609 /* checksum = */ getlong(ttf);
610 nameoffset = off2+getlong(ttf);
611 length = getlong(ttf);
612 if ( tag==CHR('n','a','m','e'))
613 break;
615 if ( i==num )
616 return( NULL );
618 fseek(ttf,nameoffset,SEEK_SET);
619 /* format = */ getushort(ttf);
620 num = getushort(ttf);
621 stringoffset = nameoffset+getushort(ttf);
623 for ( i=0; i<num; ++i ) {
624 /* plat */ getushort(ttf);
625 /* spec */ getushort(ttf);
626 /* lang */ getushort(ttf);
627 name = getushort(ttf);
628 len = getushort(ttf);
629 off = getushort(ttf);
630 if (name == 6) {
631 char *str = malloc(len+1);
632 if (str) {
633 fseek (ttf, stringoffset+off, SEEK_SET);
634 if(fread(str,1,len,ttf)==(size_t)len) {
635 str[len] = '\0';
636 return str;
638 free(str);
642 return NULL;
645 static int PickTTFFont(FILE *ttf,char *filename,char **chosenname) {
646 int32 *offsets, cnt, i, choice, j;
647 char **names;
648 char *pt, *lparen, *rparen;
650 /* TTCF version = */ getlong(ttf);
651 cnt = getlong(ttf);
652 if ( cnt==1 ) {
653 /* This is easy, don't bother to ask the user, there's no choice */
654 int32 offset = getlong(ttf);
655 fseek(ttf,offset,SEEK_SET);
656 return( true );
658 offsets = galloc(cnt*sizeof(int32));
659 for ( i=0; i<cnt; ++i )
660 offsets[i] = getlong(ttf);
661 names = galloc(cnt*sizeof(char *));
662 for ( i=j=0; i<cnt; ++i ) {
663 names[j] = TTFGetFontName(ttf,offsets[i],0);
664 if ( names[j]!=NULL ) ++j;
666 pt = strrchr(filename,'/');
667 if ( pt==NULL ) pt = filename;
668 /* Someone gave me a font "Nafees Nastaleeq(Updated).ttf" and complained */
669 /* that ff wouldn't open it */
670 /* Now someone will complain about "Nafees(Updated).ttc(fo(ob)ar)" */
671 if ( (lparen = strrchr(pt,'('))!=NULL &&
672 (rparen = strrchr(lparen,')'))!=NULL &&
673 rparen[1]=='\0' ) {
674 char *find = copy(lparen+1);
675 pt = strchr(find,')');
676 if ( pt!=NULL ) *pt='\0';
677 for ( choice=cnt-1; choice>=0; --choice )
678 if ( strcmp(names[choice],find)==0 )
679 break;
680 if ( choice==-1 ) {
681 char *end;
682 choice = strtol(find,&end,10);
683 if ( *end!='\0' )
684 choice = -1;
686 if ( choice==-1 ) {
687 char *fn = copy(filename);
688 fn[lparen-filename] = '\0';
689 ff_post_error(_("Not in Collection"),
690 /* GT: The user is trying to open a font file which contains multiple fonts and */
691 /* GT: has asked for a font which is not in that file. */
692 /* GT: The string will look like: <fontname> is not in <filename> */
693 _("%1$s is not in %2$.100s"),find,fn);
694 free(fn);
696 free(find);
697 } else
698 choice = 0;
699 if ( choice!=-1 ) {
700 fseek(ttf,offsets[choice],SEEK_SET);
701 *chosenname = copy(names[choice]);
703 for ( i=0; i<j; ++i )
704 free(names[i]);
705 free(names);
706 free(offsets);
707 return( choice!=-1);
710 static int PickCFFFont(char **fontnames) {
711 unichar_t **names;
712 int cnt, i, choice;
714 for ( cnt=0; fontnames[cnt]!=NULL; ++cnt);
715 names = gcalloc(cnt+1,sizeof(unichar_t *));
716 for ( i=0; i<cnt; ++i )
717 names[i] = uc_copy(fontnames[i]);
718 choice = 0;
719 for ( i=0; i<cnt; ++i )
720 free(names[i]);
721 free(names);
722 return( choice );
725 static void ParseSaveTablesPref(struct ttfinfo *info) {
726 char *pt, *spt;
727 int cnt;
729 info->savecnt = 0;
730 info->savetab = NULL;
731 if ( SaveTablesPref==NULL || *SaveTablesPref=='\0' )
732 return;
733 for ( pt=SaveTablesPref, cnt=0; *pt; ++pt )
734 if ( *pt==',' )
735 ++cnt;
736 info->savecnt = cnt+1;
737 info->savetab = gcalloc(cnt+1,sizeof(struct savetab));
738 for ( pt=spt=SaveTablesPref, cnt=0; ; ++pt ) {
739 if ( *pt==',' || *pt=='\0' ) {
740 uint32 tag;
741 tag = ( ( spt <pt )? spt[0] : ' ' )<<24;
742 tag |= ( ( spt+1<pt )? spt[1] : ' ' )<<16;
743 tag |= ( ( spt+2<pt )? spt[2] : ' ' )<<8 ;
744 tag |= ( ( spt+3<pt )? spt[3] : ' ' ) ;
745 info->savetab[cnt++].tag = tag;
746 if ( *pt )
747 spt = pt+1;
748 else
749 break;
754 static int32 filechecksum(FILE *file, int start, int len) {
755 uint32 sum = 0, chunk;
757 fseek(file,start,SEEK_SET);
758 if ( len!=-1 ) len=(len+3)>>2;
759 while ( len==-1 || --len>=0 ) {
760 chunk = getlong(file);
761 if ( feof(file))
762 break;
763 sum += chunk;
765 return( sum );
768 static void ValidateTTFHead(FILE *ttf,struct ttfinfo *info) {
769 /* When doing font lint we want to check the ttf header and make */
770 /* sure all the offsets and lengths are valid, and the checksums */
771 /* match. Most of the time this is just extra work and we don't */
772 /* bather */
773 uint32 restore_this_pos = ftell(ttf);
774 struct tt_tables {
775 uint32 tag;
776 uint32 checksum;
777 uint32 offset;
778 uint32 length;
779 } *tabs, temp;
780 int i,j;
781 uint32 file_len;
782 int sr, es, rs, e_sr, e_es, e_rs;
783 int hashead, hashhea, hasmaxp, masos2, haspost, hasname, hasos2;
784 int hasloca, hascff, hasglyf;
786 info->numtables = getushort(ttf);
787 sr = getushort(ttf);
788 es = getushort(ttf);
789 rs = getushort(ttf);
790 e_sr = (info->numtables<8?4:info->numtables<16?8:info->numtables<32?16:info->numtables<64?32:64)*16;
791 e_es = (info->numtables<8?2:info->numtables<16?3:info->numtables<32?4:info->numtables<64?5:6);
792 e_rs = info->numtables*16-e_sr;
793 if ( e_sr!=sr || e_es!=es || e_rs!=rs ) {
794 LogError( _("Unexpected values for binsearch header. Based on the number of tables I\n expect searchRange=%d (not %d), entrySel=%d (not %d) rangeShift=%d (not %d)\n"),
795 e_sr, sr, e_es, es, e_rs, rs );
796 info->bad_sfnt_header = true;
799 if ( info->numtables<=0 ) {
800 LogError(_("An sfnt file must contain SOME tables, but this one does not."));
801 info->bad_sfnt_header = true;
802 fseek(ttf,restore_this_pos,SEEK_SET);
803 return;
804 } else if ( info->numtables>1000 ) {
805 LogError(_("An sfnt file may contain a large number of tables, but this one has over 1000\n and that seems like too many\n"));
806 info->bad_sfnt_header = true;
807 fseek(ttf,restore_this_pos,SEEK_SET);
808 return;
811 tabs = galloc(info->numtables*sizeof(struct tt_tables));
813 for ( i=0; i<info->numtables; ++i ) {
814 tabs[i].tag = getlong(ttf);
815 tabs[i].checksum = getlong(ttf);
816 tabs[i].offset = getlong(ttf);
817 tabs[i].length = getlong(ttf);
818 if ( i!=0 && tabs[i].tag<tabs[i-1].tag && !info->bad_sfnt_header ) {
819 LogError(_("Table tags should be in alphabetic order in the font header\n but '%c%c%c%c', appears after '%c%c%c%c'."),
820 tabs[i-1].tag>>24, tabs[i-1].tag>>16, tabs[i-1].tag>>8, tabs[i-1].tag,
821 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
822 info->bad_sfnt_header = true;
825 fseek(ttf,0,SEEK_END);
826 file_len = ftell(ttf);
828 for ( i=0; i<info->numtables; ++i ) for ( j=i+1; j<info->numtables; ++j ) {
829 if ( tabs[i].offset>tabs[j].offset ) {
830 temp = tabs[i];
831 tabs[i] = tabs[j];
832 tabs[j] = temp;
835 for ( i=0; i<info->numtables-1; ++i ) {
836 for ( j=i+1; j<info->numtables; ++j ) {
837 if ( tabs[i].tag==tabs[j].tag ) {
838 LogError(_("Same table tag, '%c%c%c%c', appears twice in sfnt header"),
839 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
840 info->bad_sfnt_header = true;
843 if ( tabs[i].offset+tabs[i].length > tabs[i+1].offset ) {
844 LogError(_("Tables '%c%c%c%c' and '%c%c%c%c' overlap"),
845 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
846 tabs[j].tag>>24, tabs[j].tag>>16, tabs[j].tag>>8, tabs[j].tag );
849 if ( tabs[i].offset+tabs[i].length > file_len ) {
850 LogError(_("Table '%c%c%c%c' extends beyond end of file."),
851 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
852 info->bad_sfnt_header = true;
855 /* Checksums. First file as a whole, then each table */
856 if ( filechecksum(ttf,0,-1)!=(int)0xb1b0afba ) {
857 LogError(_("File checksum is incorrect."));
858 info->bad_sfnt_header = true;
860 for ( i=0; i<info->numtables-1; ++i ) if ( tabs[i].tag!=CHR('h','e','a','d')) {
861 if ( filechecksum(ttf,tabs[i].offset,tabs[i].length)!=(int)tabs[i].checksum ) {
862 LogError(_("Table '%c%c%c%c' has a bad checksum."),
863 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
864 info->bad_sfnt_header = true;
868 hashead = hashhea = hasmaxp = masos2 = haspost = hasname = hasos2 = false;
869 hasloca = hascff = hasglyf = false;
870 for ( i=0; i<info->numtables-1; ++i ) {
871 switch ( tabs[i].tag ) {
872 case CHR('c','v','t',' '):
873 if ( tabs[i].length&1 )
874 LogError(_("Table '%c%c%c%c' has a bad length, must be even."),
875 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
876 break;
877 case CHR('b','h','e','d'): /* Fonts with bitmaps but no outlines get bhea */
878 case CHR('h','e','a','d'):
879 if ( tabs[i].length!=54 )
880 LogError(_("Table '%c%c%c%c' has a bad length, must be 54 but is %d."),
881 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
882 tabs[i].length );
883 hashead = true;
884 break;
885 case CHR('h','h','e','a'):
886 hashhea = true;
887 case CHR('v','h','e','a'):
888 if ( tabs[i].length!=36 )
889 LogError(_("Table '%c%c%c%c' has a bad length, must be 36 but is %d."),
890 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
891 tabs[i].length );
892 break;
893 case CHR('m','a','x','p'):
894 hasmaxp = true;
895 if ( tabs[i].length!=32 && tabs[i].length!=6 )
896 LogError(_("Table '%c%c%c%c' has a bad length, must be 32 or 6 but is %d."),
897 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
898 tabs[i].length );
899 break;
900 case CHR('O','S','/','2'):
901 hasos2 = true;
902 if ( tabs[i].length!=78 && tabs[i].length!=86 && tabs[i].length!=96 )
903 LogError(_("Table '%c%c%c%c' has a bad length, must be 78, 86 or 96 but is %d."),
904 tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
905 tabs[i].length );
906 break;
907 case CHR('p','o','s','t'):
908 haspost = true;
909 break;
910 case CHR('n','a','m','e'):
911 hasname = true;
912 break;
913 case CHR('l','o','c','a'):
914 hasloca = true;
915 break;
916 case CHR('g','l','y','f'):
917 hasglyf = true;
918 break;
919 case CHR('C','F','F',' '):
920 hascff = true;
921 break;
924 if ( !hashead )
925 LogError(_("Missing required table: \"head\""));
926 if ( !hashhea )
927 LogError(_("Missing required table: \"hhea\""));
928 if ( !hasmaxp )
929 LogError(_("Missing required table: \"maxp\""));
930 if ( !haspost )
931 LogError(_("Missing required table: \"post\""));
932 if ( !hasname )
933 LogError(_("Missing required table: \"name\""));
934 if ( hasglyf && !hasloca )
935 LogError(_("Missing required table: \"loca\""));
936 if ( !hasos2 )
937 LogError(_("Missing \"OS/2\" table"));
938 if ( !hasglyf && hasloca )
939 LogError(_("Missing required table: \"glyf\""));
940 if ( !hasglyf && !hascff )
941 LogError(_("This font contains neither \"CFF \" nor \"glyf\"/\"loca\" tables"));
943 free(tabs);
944 fseek(ttf,restore_this_pos,SEEK_SET);
947 static struct tablenames { uint32 tag; char *name; } stdtables[] = {
948 { CHR('a','c','n','t'), N_("accent attachment table") },
949 { CHR('a','v','a','r'), N_("axis variation table") },
950 { CHR('B','A','S','E'), N_("Baseline table (OT version)") },
951 { CHR('b','d','a','t'), N_("bitmap data table (AAT version)") },
952 { CHR('B','D','F',' '), N_("BDF bitmap properties table") },
953 { CHR('b','h','e','d'), N_("bitmap font header table") },
954 { CHR('b','l','o','c'), N_("bitmap location table (AAT version)") },
955 { CHR('b','s','l','n'), N_("baseline table (AAT version)") },
956 { CHR('C','F','F',' '), N_("PostScript font program (Compact Font Format)") },
957 { CHR('C','I','D',' '), N_("Obsolete table for a type1 CID keyed font") },
958 { CHR('c','m','a','p'), N_("character code mapping table") },
959 { CHR('c','v','a','r'), N_("CVT variation table") },
960 { CHR('c','v','t',' '), N_("control value table") },
961 { CHR('D','S','I','G'), N_("digital signature table") },
962 { CHR('E','B','D','T'), N_("bitmap data table (OT version)") },
963 { CHR('E','B','L','C'), N_("bitmap location table (OT version)") },
964 { CHR('E','B','S','C'), N_("embedded bitmap scaling control table") },
965 { CHR('E','L','U','A'), N_("electronic end user license table") },
966 { CHR('f','d','s','c'), N_("font descriptor table") },
967 { CHR('f','e','a','t'), N_("layout feature table") },
968 { CHR('F','e','a','t'), N_("SIL Graphite layout feature table") },
969 { CHR('F','F','T','M'), N_("FontForge time stamp table") },
970 { CHR('f','m','t','x'), N_("font metrics table") },
971 { CHR('f','p','g','m'), N_("font program table") },
972 { CHR('f','v','a','r'), N_("font variation table") },
973 { CHR('g','a','s','p'), N_("grid-fitting and scan-conversion procedure table") },
974 { CHR('G','D','E','F'), N_("glyph definition table") },
975 { CHR('G','l','a','t'), N_("Graphite glyph attribute table") },
976 { CHR('G','l','o','c'), N_("Graphite glyph location in Glat table") },
977 { CHR('g','l','y','f'), N_("glyph outline table") },
978 { CHR('G','P','O','S'), N_("glyph positioning table") },
979 { CHR('g','v','a','r'), N_("glyph variation table") },
980 { CHR('G','S','U','B'), N_("glyph substitution table") },
981 { CHR('h','d','m','x'), N_("horizontal device metrics table") },
982 { CHR('h','e','a','d'), N_("font header table") },
983 { CHR('h','h','e','a'), N_("horizontal header table") },
984 { CHR('h','m','t','x'), N_("horizontal metrics table") },
985 { CHR('h','s','t','y'), N_("horizontal style table") },
986 { CHR('j','u','s','t'), N_("justification table (AAT version)") },
987 { CHR('J','S','T','F'), N_("justification table (OT version)") },
988 { CHR('k','e','r','n'), N_("kerning table") },
989 { CHR('l','c','a','r'), N_("ligature caret table") },
990 { CHR('l','o','c','a'), N_("glyph location table") },
991 { CHR('L','T','S','H'), N_("linear threshold table") },
992 { CHR('M','A','T','H'), N_("math table") },
993 { CHR('m','a','x','p'), N_("maximum profile table") },
994 { CHR('M','M','S','D'), N_("Multi-Master table, obsolete") },
995 { CHR('M','M','F','X'), N_("Multi-Master table, obsolete") },
996 { CHR('m','o','r','t'), N_("metamorphosis table") },
997 { CHR('m','o','r','x'), N_("extended metamorphosis table") },
998 { CHR('n','a','m','e'), N_("name table") },
999 { CHR('o','p','b','d'), N_("optical bounds table") },
1000 { CHR('O','S','/','2'), N_("OS/2 and Windows specific metrics table") },
1001 { CHR('P','C','L','T'), N_("PCL 5 data table") },
1002 { CHR('P','f','E','d'), N_("FontForge font debugging table") },
1003 { CHR('p','o','s','t'), N_("glyph name and PostScript compatibility table") },
1004 { CHR('p','r','e','p'), N_("control value program table") },
1005 { CHR('p','r','o','p'), N_("properties table") },
1006 { CHR('S','i','l','f'), N_("SIL Graphite rule table") },
1007 { CHR('S','i','l','l'), N_("(unspecified) SIL Graphite table") },
1008 { CHR('S','i','l','t'), N_("unknown SIL table") },
1009 { CHR('T','e','X',' '), N_("TeX table") },
1010 { CHR('t','r','a','k'), N_("tracking table") },
1011 { CHR('T','Y','P','1'), N_("Obsolete table for a type1 font") },
1012 { CHR('V','D','M','X'), N_("vertical device metrics table") },
1013 { CHR('v','h','e','a'), N_("vertical header table") },
1014 { CHR('v','m','t','x'), N_("vertical metrics table") },
1015 { CHR('V','O','R','G'), N_("vertical origin table") },
1016 { CHR('Z','a','p','f'), N_("glyph reference table") },
1017 { 0 , NULL }
1020 static int readttfheader(FILE *ttf, struct ttfinfo *info,char *filename,
1021 char **choosenname) {
1022 int i, j, k;
1023 unsigned tag;
1024 int checksum, offset, length, version;
1025 int first = true;
1027 version=getlong(ttf);
1028 if ( version==CHR('t','t','c','f')) {
1029 /* TrueType font collection */
1030 info->is_ttc = true;
1031 if ( !PickTTFFont(ttf,filename,choosenname))
1032 return( 0 );
1033 /* If they picked a font, then we should be left pointing at the */
1034 /* start of the Table Directory for that font */
1035 info->one_of_many = true;
1036 version = getlong(ttf);
1039 /* Apple says that 'typ1' is a valid code for a type1 font wrapped up in */
1040 /* a truetype table structure, but gives no docs on what tables get used */
1041 /* or how */ /* Turns out to be pretty simple */
1042 /* typ1 is used for both type1 fonts and CID type1 fonts, I don't think a version of 'CID ' is actually used */
1043 if ( version==CHR('t','y','p','1') || version==CHR('C','I','D',' ')) {
1044 LogError( _("Nifty, you've got one of the old Apple/Adobe type1 sfnts here\n") );
1045 } else if ( version!=0x00010000 && version!=CHR('t','r','u','e') &&
1046 version!=0x00020000 && /* Windows 3.1 Chinese version used this version for some arphic fonts */
1047 /* See discussion on freetype list, july 2004 */
1048 version!=CHR('O','T','T','O'))
1049 return( 0 ); /* Not version 1 of true type, nor Open Type */
1051 if ( info->openflags & of_fontlint )
1052 ValidateTTFHead(ttf,info);
1054 info->numtables = getushort(ttf);
1055 /* searchRange = */ getushort(ttf);
1056 /* entrySelector = */ getushort(ttf);
1057 /* rangeshift = */ getushort(ttf);
1059 ParseSaveTablesPref(info);
1061 for ( i=0; i<info->numtables; ++i ) {
1062 tag = getlong(ttf);
1063 checksum = getlong(ttf);
1064 offset = getlong(ttf);
1065 length = getlong(ttf);
1066 #ifdef DEBUG
1067 printf( "%c%c%c%c\n", tag>>24, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff );
1068 #endif
1069 switch ( tag ) {
1070 case CHR('B','A','S','E'):
1071 info->base_start = offset;
1072 break;
1073 case CHR('C','F','F',' '):
1074 info->cff_start = offset;
1075 info->cff_length = length;
1076 break;
1077 case CHR('c','m','a','p'):
1078 info->encoding_start = offset;
1079 break;
1080 case CHR('g','a','s','p'):
1081 info->gasp_start = offset;
1082 break;
1083 case CHR('g','l','y','f'):
1084 info->glyph_start = offset;
1085 info->glyph_length = length;
1086 break;
1087 case CHR('G','D','E','F'):
1088 info->gdef_start = offset;
1089 info->gdef_length = length;
1090 break;
1091 case CHR('G','P','O','S'):
1092 info->gpos_start = offset;
1093 info->gpos_length = length;
1094 break;
1095 case CHR('G','S','U','B'):
1096 info->gsub_start = offset;
1097 info->gsub_length = length;
1098 break;
1099 case CHR('b','d','a','t'): /* Apple/MS use a different tag, but the same format. Great. */
1100 case CHR('E','B','D','T'):
1101 info->bitmapdata_start = offset;
1102 info->bitmapdata_length = length;
1103 break;
1104 case CHR('b','l','o','c'): /* Apple/MS use a different tag. Great. */
1105 case CHR('E','B','L','C'):
1106 info->bitmaploc_start = offset;
1107 info->bitmaploc_length = length;
1108 break;
1109 case CHR('b','h','e','d'): /* Apple uses bhed for fonts with only bitmaps */
1110 case CHR('h','e','a','d'):
1111 info->head_start = offset;
1112 break;
1113 case CHR('h','h','e','a'):
1114 info->hhea_start = offset;
1115 break;
1116 case CHR('h','m','t','x'):
1117 info->hmetrics_start = offset;
1118 break;
1119 case CHR('k','e','r','n'):
1120 info->kern_start = offset;
1121 break;
1122 case CHR('l','o','c','a'):
1123 info->glyphlocations_start = offset;
1124 info->loca_length = length;
1125 info->glyph_cnt = length/2-1; /* the minus one is because there is one extra entry to give the length of the last glyph */
1126 if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
1127 break;
1128 case CHR('m','a','x','p'):
1129 info->maxp_start = offset;
1130 info->maxp_len = length;
1131 break;
1132 case CHR('n','a','m','e'):
1133 info->copyright_start = offset;
1134 break;
1135 case CHR('p','o','s','t'):
1136 info->postscript_start = offset;
1137 break;
1138 case CHR('O','S','/','2'):
1139 info->os2_start = offset;
1140 break;
1141 case CHR('C','I','D',' '):
1142 case CHR('T','Y','P','1'):
1143 info->typ1_start = offset;
1144 info->typ1_length = length;
1145 break;
1146 case CHR('v','h','e','a'):
1147 info->vhea_start = offset;
1148 break;
1149 case CHR('v','m','t','x'):
1150 info->vmetrics_start = offset;
1151 break;
1152 case CHR('M','A','T','H'):
1153 info->math_start = offset;
1154 info->math_length = length;
1155 break;
1156 /* to make sense of instrs */
1157 case CHR('c','v','t',' '):
1158 info->cvt_start = offset;
1159 info->cvt_len = length;
1160 break;
1161 case CHR('p','r','e','p'):
1162 info->prep_start = offset;
1163 info->prep_len = length;
1164 break;
1165 case CHR('f','p','g','m'):
1166 info->fpgm_start = offset;
1167 info->fpgm_len = length;
1168 break;
1170 /* non-standard tables I've added */
1171 case CHR('P','f','E','d'):
1172 info->pfed_start = offset;
1173 break;
1174 case CHR('F','F','T','M'):
1175 info->fftm_start = offset;
1176 break;
1177 case CHR('T','e','X',' '):
1178 info->tex_start = offset;
1179 break;
1180 case CHR('B','D','F',' '):
1181 info->bdf_start = offset;
1182 break;
1184 default:
1185 for ( j=0; j<info->savecnt; ++j ) if ( info->savetab[j].tag == tag ) {
1186 info->savetab[j].offset = offset;
1187 info->savetab[j].len = length;
1188 break;
1190 if ( j==info->savecnt ) {
1191 if ( first ) {
1192 LogError( _("The following table(s) in the font have been ignored by FontForge\n") );
1193 first = false;
1195 for ( k=0; stdtables[k].tag!=0; ++k )
1196 if ( stdtables[k].tag == tag )
1197 break;
1198 if ( stdtables[k].tag==0 ) {
1199 LogError( _(" Ignoring '%c%c%c%c'\n"), tag>>24, tag>>16, tag>>8, tag);
1200 } else {
1201 LogError( _(" Ignoring '%c%c%c%c' %s\n"), tag>>24, tag>>16, tag>>8, tag,
1202 _(stdtables[k].name));
1207 if ( info->glyphlocations_start!=0 && info->cff_start!=0 )
1208 LogError( _("This font contains both truetype and PostScript glyph descriptions\n only one will be used.\n"));
1209 else if ( (info->glyphlocations_start!=0) +
1210 (info->cff_start!=0) +
1211 (info->typ1_start!=0)>1 )
1212 LogError( _("This font contains multiple glyph descriptions\n only one will be used.\n"));
1213 if ( info->gpos_start!=0 && info->kern_start!=0 )
1214 LogError( _("This font contains both a 'kern' table and a 'GPOS' table.\n The 'kern' table will only be read if there is no 'kern' feature in 'GPOS'.\n"));
1215 return( true );
1218 static void readdate(FILE *ttf,struct ttfinfo *info,int ismod) {
1219 int date[4], date1970[4], year[2];
1220 int i;
1221 /* Dates in sfnt files are seconds since 1904. I adjust to unix time */
1222 /* seconds since 1970 by figuring out how many seconds were in between */
1224 date[3] = getushort(ttf);
1225 date[2] = getushort(ttf);
1226 date[1] = getushort(ttf);
1227 date[0] = getushort(ttf);
1228 memset(date1970,0,sizeof(date1970));
1229 year[0] = (60*60*24*365L)&0xffff;
1230 year[1] = (60*60*24*365L)>>16;
1231 for ( i=1904; i<1970; ++i ) {
1232 date1970[0] += year[0];
1233 date1970[1] += year[1];
1234 if ( (i&3)==0 && (i%100!=0 || i%400==0))
1235 date1970[0] += 24*60*60L; /* Leap year */
1236 date1970[1] += (date1970[0]>>16);
1237 date1970[0] &= 0xffff;
1238 date1970[2] += date1970[1]>>16;
1239 date1970[1] &= 0xffff;
1240 date1970[3] += date1970[2]>>16;
1241 date1970[2] &= 0xffff;
1244 for ( i=0; i<3; ++i ) {
1245 date[i] -= date1970[i];
1246 date[i+1] += date[i]>>16;
1247 date[i] &= 0xffff;
1249 date[3] -= date1970[3];
1251 *(ismod ? &info->modificationtime : &info->creationtime) =
1252 #ifdef _HAS_LONGLONG
1253 (((long long) date[3])<<48) |
1254 (((long long) date[2])<<32) |
1255 #endif
1256 ( date[1] <<16) |
1257 date[0];
1260 static void readttfhead(FILE *ttf,struct ttfinfo *info) {
1261 /* Here I want units per em, and size of loca entries */
1262 /* oh... also creation/modification times */
1263 int i, flags;
1265 fseek(ttf,info->head_start+4*4,SEEK_SET); /* skip over the version number and a bunch of junk */
1266 flags = getushort(ttf);
1267 info->optimized_for_cleartype = (flags&(1<<13))?1:0;
1268 info->apply_lsb = !(flags&(1<<1));
1269 info->emsize = getushort(ttf);
1271 info->ascent = .8*info->emsize;
1272 info->descent = info->emsize-info->ascent;
1274 for ( i=0; i<12; ++i )
1275 getushort(ttf);
1276 info->macstyle = getushort(ttf);
1277 for ( i=0; i<2; ++i )
1278 getushort(ttf);
1279 info->index_to_loc_is_long = getushort(ttf);
1280 if ( info->index_to_loc_is_long )
1281 info->glyph_cnt = info->loca_length/4-1;
1282 if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
1284 if ( info->fftm_start!=0 ) {
1285 fseek(ttf,info->fftm_start+3*4,SEEK_SET);
1286 } else {
1287 fseek(ttf,info->head_start+4*4+2+2,SEEK_SET);
1289 readdate(ttf,info,0);
1290 readdate(ttf,info,1);
1293 static void readttfhhea(FILE *ttf,struct ttfinfo *info) {
1294 /* Here I want ascent, descent and the number of horizontal metrics */
1295 int i;
1297 fseek(ttf,info->hhea_start+4,SEEK_SET); /* skip over the version number */
1298 info->pfminfo.hhead_ascent = getushort(ttf);
1299 info->pfminfo.hhead_descent = (short) getushort(ttf);
1300 info->pfminfo.hheadascent_add = info->pfminfo.hheaddescent_add = false;
1301 info->pfminfo.linegap = getushort(ttf);
1302 info->pfminfo.hheadset = true;
1303 /*info->ascent = info->pfminfo.hhead_ascent;*/
1305 for ( i=0; i<12; ++i )
1306 getushort(ttf);
1307 info->width_cnt = getushort(ttf);
1310 static void readttfmaxp(FILE *ttf,struct ttfinfo *info) {
1311 /* All I want here is the number of glyphs */
1312 int cnt;
1313 fseek(ttf,info->maxp_start+4,SEEK_SET); /* skip over the version number */
1314 cnt = getushort(ttf);
1315 if ( info->glyph_cnt==0 && info->glyph_length==0 && info->loca_length<=4 &&
1316 info->cff_length==0 && info->typ1_start==0 ) {
1317 /* X11 OpenType bitmap format */;
1318 info->onlystrikes = true;
1319 } else if ( cnt!=info->glyph_cnt && info->loca_length!=0 ) {
1320 ff_post_notice(_("Bad Glyph Count"), _("Font file has bad glyph count field. maxp says: %d sizeof(loca)=>%d"), cnt, info->glyph_cnt);
1321 info->bad_glyph_data = true;
1322 if ( cnt>info->glyph_cnt )
1323 cnt = info->glyph_cnt; /* Use the smaller of the two values */
1325 /* Open Type fonts have no loca table, so we can't calculate the glyph */
1326 /* count from it */
1327 info->glyph_cnt = cnt;
1328 if ( cnt<0 ) info->glyph_cnt = 0;
1331 static char *stripspaces(char *str) {
1332 char *str2 = str, *base = str;
1334 if ( str==NULL )
1335 return( NULL );
1337 while ( *str ) {
1338 if ( *str==' ' )
1339 ++str;
1340 else
1341 *str2++ = *str++;
1343 *str2 = '\0';
1344 return( base );
1347 static void ValidatePostScriptFontName(struct ttfinfo *info, char *str) {
1348 char *end, *pt, *npt;
1349 int complained = false;
1351 /* someone gave me a font where the fontname started with the utf8 byte */
1352 /* order mark. PLRM says only ASCII encoding is supported. CFF says */
1353 /* only printable ASCII should be used */
1354 if ( ((uint8 *) str)[0] == 0xef && ((uint8 *) str)[1]==0xbb && ((uint8 *) str)[2] == 0xbf ) {
1355 LogError(_("The fontname begins with the utf8 byte order sequence. This is illegal. %s"), str+3 );
1356 info->bad_ps_fontname = true;
1357 for ( pt=str+3; *pt; ++pt )
1358 pt[-3] = *pt; /* ANSI says we can't strcpy overlapping strings */
1360 strtod(str,&end);
1361 if ( (*end=='\0' || (isdigit(str[0]) && strchr(str,'#')!=NULL)) &&
1362 *str!='\0' ) {
1363 ff_post_error(_("Bad Font Name"),_("A Postscript name may not be a number"));
1364 info->bad_ps_fontname = true;
1365 *str = 'a';
1366 complained = true;
1368 for ( pt=str; *pt; ++pt ) {
1369 if ( *pt<=' ' || *pt>=0x7f ||
1370 *pt=='(' || *pt=='[' || *pt=='{' || *pt=='<' ||
1371 *pt==')' || *pt==']' || *pt=='}' || *pt=='>' ||
1372 *pt=='%' || *pt=='/' ) {
1373 if ( !complained ) {
1374 ff_post_error(_("Bad Font Name"),_("The Postscript font name \"%.63s\" is invalid.\nIt should be printable ASCII,\nmust not contain (){}[]<>%%/ or space\nand must be shorter than 63 characters"),str);
1375 info->bad_ps_fontname = true;
1377 complained = true;
1378 for ( npt=pt; npt[1]; ++npt )
1379 *npt = npt[1];
1380 *npt = '\0';
1381 --pt;
1384 if ( strlen(str)>63 ) {
1385 ff_post_error(_("Bad Font Name"),_("The Postscript font name \"%.63s\" is invalid.\nIt should be printable ASCII,\nmust not contain (){}[]<>%%/ or space\nand must be shorter than 63 characters"),str);
1386 info->bad_ps_fontname = true;
1387 str[63] = '\0';
1391 char *EnforcePostScriptName(char *old) {
1392 char *end, *pt, *npt, *str = copy(old);
1394 if ( old==NULL )
1395 return( old );
1397 strtod(str,&end);
1398 if ( (*end=='\0' || (isdigit(str[0]) && strchr(str,'#')!=NULL)) &&
1399 *str!='\0' ) {
1400 free(str);
1401 str=galloc(strlen(old)+2);
1402 *str = 'a';
1403 strcpy(str+1,old);
1405 for ( pt=str; *pt; ++pt ) {
1406 if ( *pt<=' ' || *pt>=0x7f ||
1407 *pt=='(' || *pt=='[' || *pt=='{' || *pt=='<' ||
1408 *pt==')' || *pt==']' || *pt=='}' || *pt=='>' ||
1409 *pt=='%' || *pt=='/' ) {
1410 for ( npt=pt; npt[1]; ++npt )
1411 *npt = npt[1];
1412 *npt = '\0';
1415 if ( strlen(str)>63 )
1416 str[63] = '\0';
1417 return( str );
1420 static int IsSubSetOf(const char *substr,const char *fullstr ) {
1421 /* The mac string is often a subset of the unicode string. Certain */
1422 /* characters can't be expressed in the mac encoding and are omitted */
1423 /* or turned to question marks or some such */
1424 const char *pt1, *pt2;
1425 uint32 ch1, ch2;
1427 for ( pt1=substr, pt2=fullstr, ch1=utf8_ildb(&pt1); ch1!=0 ; ) {
1428 if ( *pt2=='\0' )
1429 break;
1430 ch2 = utf8_ildb(&pt2);
1431 if ( ch1==ch2 )
1432 ch1 = utf8_ildb(&pt1);
1434 if ( ch1=='\0' )
1435 return( true );
1437 for ( pt1=substr, pt2=fullstr, ch1=utf8_ildb(&pt1); ch1!=0 ; ) {
1438 if ( *pt2=='\0' )
1439 break;
1440 ch2 = utf8_ildb(&pt2);
1441 if ( ch1==ch2 || ch1=='?' )
1442 ch1 = utf8_ildb(&pt1);
1444 return( ch1=='\0' );
1447 static void TTFAddLangStr(FILE *ttf, struct ttfinfo *info, int id,
1448 int strlen, int stroff,int plat,int spec,int language) {
1449 struct ttflangname *cur, *prev;
1450 char *str;
1452 if ( id<0 || id>=ttf_namemax )
1453 return;
1455 str = _readencstring(ttf,stroff,strlen,plat,spec,language);
1456 if ( str==NULL ) /* we didn't understand the encoding */
1457 return;
1458 if ( id==ttf_postscriptname )
1459 ValidatePostScriptFontName(info,str);
1460 if ( *str=='\0' ) {
1461 free(str);
1462 return;
1465 if ( plat==1 || plat==0 )
1466 language = WinLangFromMac(language);
1467 if ( (language&0xff00)==0 ) language |= 0x400;
1469 for ( prev=NULL, cur=info->names; cur!=NULL && cur->lang!=language; prev = cur, cur=cur->next );
1470 if ( cur==NULL ) {
1471 cur = chunkalloc(sizeof(struct ttflangname));
1472 cur->lang = language;
1473 if ( prev==NULL )
1474 info->names = cur;
1475 else
1476 prev->next = cur;
1478 if ( cur->names[id]==NULL ) {
1479 cur->names[id] = str;
1480 if ( plat==1 || plat==0 )
1481 cur->frommac[id/32] |= (1<<(id&0x1f));
1482 /* There's some wacky bug in gcc. If the optimizer is on then strcmp gets turned */
1483 /* into some inline call. Which would be fine, except the following line goes */
1484 /* bluey. "Called object is not a function", etc. Compiles fine if we turn off */
1485 /* the inlining magic */
1486 #ifdef strcmp
1487 # undef strcmp
1488 #endif
1489 } else if ( strcmp(str,cur->names[id])==0 ) {
1490 free(str);
1491 if ( plat==3 )
1492 cur->frommac[id/32] &= ~(1<<(id&0x1f));
1493 } else if ( plat==1 ) {
1494 /* Mac string doesn't match mac unicode string */
1495 if ( !IsSubSetOf(str,cur->names[id]) )
1496 LogError( _("Warning: Mac and Unicode entries in the 'name' table differ for the\n %s string in the language %s\n Mac String: %s\nMac Unicode String: %s\n"),
1497 TTFNameIds(id),MSLangString(language),
1498 str,cur->names[id]);
1499 else
1500 LogError( _("Warning: Mac string is a subset of the Unicode string in the 'name' table\n for the %s string in the %s language.\n"),
1501 TTFNameIds(id),MSLangString(language));
1502 free(str);
1503 } else if ( plat==3 && (cur->frommac[id/32] & (1<<(id&0x1f))) ) {
1504 if ( !IsSubSetOf(cur->names[id],str) )
1505 LogError( _("Warning: Mac and Windows entries in the 'name' table differ for the\n %s string in the language %s\n Mac String: %s\nWindows String: %s\n"),
1506 TTFNameIds(id),MSLangString(language),
1507 cur->names[id],str);
1508 else
1509 LogError( _("Warning: Mac string is a subset of the Windows string in the 'name' table\n for the %s string in the %s language.\n"),
1510 TTFNameIds(id),MSLangString(language));
1511 free(cur->names[id]);
1512 cur->names[id] = str;
1513 cur->frommac[id/32] &= ~(1<<(id&0x1f));
1514 } else {
1515 int ret;
1516 if ( info->dupnamestate!=0 )
1517 ret = info->dupnamestate;
1518 else
1519 ret = 3;
1520 if ( ret==0 || ret==1 )
1521 free(str);
1522 else {
1523 free(cur->names[id]);
1524 cur->names[id] = str;
1529 static int is_ascii(char *str) { /* isascii is in ctype */
1530 if ( str==NULL )
1531 return( false );
1532 while ( *str && *str<127 && *str>=' ' )
1533 ++str;
1534 return( *str=='\0' );
1537 static char *FindLangEntry(struct ttfinfo *info, int id ) {
1538 /* Look for an entry with string id */
1539 /* we prefer english, if we can't find english look for something in ascii */
1540 struct ttflangname *cur;
1541 char *ret;
1543 for ( cur=info->names; cur!=NULL && cur->lang!=0x409; cur=cur->next );
1544 if ( cur!=NULL && cur->names[id]==NULL ) cur = NULL;
1545 if ( cur==NULL )
1546 for ( cur=info->names; cur!=NULL && (cur->lang&0xf)!=0x09; cur=cur->next );
1547 if ( cur!=NULL && cur->names[id]==NULL ) cur = NULL;
1548 if ( cur==NULL )
1549 for ( cur=info->names; cur!=NULL && !is_ascii(cur->names[id]); cur=cur->next );
1550 if ( cur==NULL )
1551 for ( cur=info->names; cur!=NULL && cur->names[id]==NULL; cur=cur->next );
1552 if ( cur==NULL )
1553 return( NULL );
1554 ret = copy(cur->names[id]);
1555 return( ret );
1558 struct otfname *FindAllLangEntries(FILE *ttf, struct ttfinfo *info, int id ) {
1559 /* Look for all entries with string id under windows platform */
1560 int32 here = ftell(ttf);
1561 int i, cnt, tableoff;
1562 int platform, specific, language, name, str_len, stroff;
1563 struct otfname *head=NULL, *cur;
1565 if ( info->copyright_start!=0 && id!=0 ) {
1566 fseek(ttf,info->copyright_start,SEEK_SET);
1567 /* format selector = */ getushort(ttf);
1568 cnt = getushort(ttf);
1569 tableoff = info->copyright_start+getushort(ttf);
1570 for ( i=0; i<cnt; ++i ) {
1571 platform = getushort(ttf);
1572 specific = getushort(ttf);
1573 language = getushort(ttf);
1574 name = getushort(ttf);
1575 str_len = getushort(ttf);
1576 stroff = getushort(ttf);
1578 if ( platform==3 && name==id ) {
1579 char *temp = _readencstring(ttf,tableoff+stroff,str_len,platform,specific,language);
1580 if ( temp!=NULL ) {
1581 cur = chunkalloc(sizeof(struct otfname));
1582 cur->next = head;
1583 head = cur;
1584 cur->lang = language;
1585 cur->name = temp;
1589 fseek(ttf,here,SEEK_SET);
1591 return( head );
1594 static void readttfcopyrights(FILE *ttf,struct ttfinfo *info) {
1595 int i, cnt, tableoff;
1596 int platform, specific, language, name, str_len, stroff;
1598 if ( info->copyright_start!=0 ) {
1599 fseek(ttf,info->copyright_start,SEEK_SET);
1600 /* format selector = */ getushort(ttf);
1601 cnt = getushort(ttf);
1602 tableoff = info->copyright_start+getushort(ttf);
1603 for ( i=0; i<cnt; ++i ) {
1604 platform = getushort(ttf);
1605 specific = getushort(ttf);
1606 language = getushort(ttf);
1607 name = getushort(ttf);
1608 str_len = getushort(ttf);
1609 stroff = getushort(ttf);
1611 TTFAddLangStr(ttf,info,name,str_len,tableoff+stroff,
1612 platform,specific,language);
1616 if ( info->copyright==NULL )
1617 info->copyright = FindLangEntry(info,ttf_copyright);
1618 if ( info->familyname==NULL )
1619 info->familyname = FindLangEntry(info,ttf_family);
1620 if ( info->fullname==NULL )
1621 info->fullname = FindLangEntry(info,ttf_fullname);
1622 if ( info->version==NULL )
1623 info->version = FindLangEntry(info,ttf_version);
1624 if ( info->fontname==NULL )
1625 info->fontname = FindLangEntry(info,ttf_postscriptname);
1627 if ( info->fontname != NULL && *info->fontname=='\0' ) {
1628 free(info->fontname);
1629 info->fontname = NULL;
1631 if ( info->familyname != NULL && *info->familyname=='\0' ) {
1632 free(info->familyname);
1633 info->familyname = NULL;
1635 if ( info->fullname != NULL && *info->fullname=='\0' ) {
1636 free(info->fullname);
1637 info->fullname = NULL;
1640 /* OpenType spec says the version string should begin with "Version " and */
1641 /* end with a space and have a number in between */
1642 if ( info->version==NULL ) info->version = copy("1.0");
1643 else if ( strnmatch(info->version,"Version ",8)==0 ) {
1644 char *temp = copy(info->version+8);
1645 if ( temp[strlen(temp)-1]==' ' )
1646 temp[strlen(temp)-1] = '\0';
1647 free(info->version);
1648 info->version = temp;
1650 if ( info->fontname==NULL ) {
1651 if ( info->fullname!=NULL )
1652 info->fontname = stripspaces(copy(info->fullname));
1653 if ( info->fontname==NULL && info->familyname!=NULL )
1654 info->fontname = stripspaces(copy(info->familyname));
1655 if ( info->fontname!=NULL )
1656 ValidatePostScriptFontName(info,info->fontname);
1660 static void readttfpreglyph(FILE *ttf,struct ttfinfo *info) {
1661 if ( info->head_start!=0 )
1662 readttfhead(ttf,info);
1663 if ( info->hhea_start!=0 )
1664 readttfhhea(ttf,info);
1665 if ( info->maxp_start!=0 )
1666 readttfmaxp(ttf,info);
1667 readttfcopyrights(ttf,info); /* This one has internal checks */
1670 #define _On_Curve 1
1671 #define _X_Short 2
1672 #define _Y_Short 4
1673 #define _Repeat 8
1674 #define _X_Same 0x10
1675 #define _Y_Same 0x20
1677 static void FigureControls(SplinePoint *from, SplinePoint *to, BasePoint *cp,
1678 int is_order2) {
1679 /* What are the control points for 2 cp bezier which will provide the same*/
1680 /* curve as that for the 1 cp bezier specified above */
1681 real b, c, d;
1683 if ( is_order2 ) {
1684 from->nextcp = to->prevcp = *cp;
1685 if ( cp->x==to->me.x && cp->y==to->me.y ) {
1686 /* I would lose track of the proper location of this cp if I left */
1687 /* it here (would end up with from->nonextcp, which would mean I'd*/
1688 /* use from->me rather than to->me in tottf.c:SSAddPoints. So we */
1689 /* distort it a little */
1690 BasePoint off;
1691 double len;
1692 off.x = from->me.x-to->me.x; off.y = from->me.y-to->me.y;
1693 len = sqrt(off.x*off.x+off.y*off.y);
1694 if ( len>3 ) {
1695 /* move the cp slightly toward from, but on the line between the two */
1696 from->nextcp.x = (to->prevcp.x += rint(off.x/len));
1697 from->nextcp.y = (to->prevcp.y += rint(off.y/len));
1700 } else {
1701 d = from->me.x;
1702 c = 2*cp->x - 2*from->me.x;
1703 b = to->me.x+from->me.x-2*cp->x;
1704 from->nextcp.x = d+c/3;
1705 to->prevcp.x = from->nextcp.x + (c+b)/3;
1707 d = from->me.y;
1708 c = 2*cp->y - 2*from->me.y;
1709 b = to->me.y+from->me.y-2*cp->y;
1710 from->nextcp.y = d+c/3;
1711 to->prevcp.y = from->nextcp.y + (c+b)/3;
1714 if ( from->me.x!=from->nextcp.x || from->me.y!=from->nextcp.y )
1715 from->nonextcp = false;
1716 if ( to->me.x!=to->prevcp.x || to->me.y!=to->prevcp.y )
1717 to->noprevcp = false;
1718 if ( is_order2 && (to->noprevcp || from->nonextcp)) {
1719 to->noprevcp = from->nonextcp = true;
1720 from->nextcp = from->me;
1721 to->prevcp = to->me;
1725 static SplineSet *ttfbuildcontours(int path_cnt,uint16 *endpt, char *flags,
1726 BasePoint *pts, int is_order2) {
1727 SplineSet *head=NULL, *last=NULL, *cur;
1728 int i, path, start, last_off;
1729 SplinePoint *sp;
1731 for ( path=i=0; path<path_cnt; ++path ) {
1732 if ( endpt[path]<i ) /* Sigh. Yes there are fonts with bad endpt info */
1733 continue;
1734 cur = chunkalloc(sizeof(SplineSet));
1735 if ( head==NULL )
1736 head = cur;
1737 else
1738 last->next = cur;
1739 last = cur;
1740 last_off = false;
1741 start = i;
1742 sp = NULL;
1743 while ( i<=endpt[path] ) {
1744 if ( flags[i]&_On_Curve ) {
1745 sp = chunkalloc(sizeof(SplinePoint));
1746 sp->me = sp->nextcp = sp->prevcp = pts[i];
1747 sp->nonextcp = sp->noprevcp = true;
1748 sp->ttfindex = i;
1749 sp->nextcpindex = 0xffff;
1750 if ( last_off && cur->last!=NULL )
1751 FigureControls(cur->last,sp,&pts[i-1],is_order2);
1752 last_off = false;
1753 } else if ( last_off ) {
1754 /* two off curve points get a third on curve point created */
1755 /* half-way between them. Now isn't that special */
1756 sp = chunkalloc(sizeof(SplinePoint));
1757 sp->me.x = (pts[i].x+pts[i-1].x)/2;
1758 sp->me.y = (pts[i].y+pts[i-1].y)/2;
1759 sp->nextcp = sp->prevcp = sp->me;
1760 sp->nonextcp = true;
1761 sp->ttfindex = 0xffff;
1762 sp->nextcpindex = i;
1763 if ( last_off && cur->last!=NULL )
1764 FigureControls(cur->last,sp,&pts[i-1],is_order2);
1765 /* last_off continues to be true */
1766 } else {
1767 if ( cur->first!=NULL )
1768 cur->last->nextcpindex = i;
1769 last_off = true;
1770 sp = NULL;
1772 if ( sp!=NULL ) {
1773 if ( cur->first==NULL )
1774 cur->first = sp;
1775 else
1776 SplineMake(cur->last,sp,is_order2);
1777 cur->last = sp;
1779 ++i;
1781 if ( start==i-1 ) {
1782 /* MS chinese fonts have contours consisting of a single off curve*/
1783 /* point. What on earth do they think that means? */
1784 /* Oh. I see. It's used to possition marks and such */
1785 if ( cur->first==NULL ) {
1786 sp = chunkalloc(sizeof(SplinePoint));
1787 sp->me.x = pts[start].x;
1788 sp->me.y = pts[start].y;
1789 sp->nextcp = sp->prevcp = sp->me;
1790 sp->nonextcp = sp->noprevcp = true;
1791 sp->ttfindex = i-1;
1792 sp->nextcpindex = 0xffff;
1793 cur->first = cur->last = sp;
1795 } else if ( !(flags[start]&_On_Curve) && !(flags[i-1]&_On_Curve) ) {
1796 sp = chunkalloc(sizeof(SplinePoint));
1797 sp->me.x = (pts[start].x+pts[i-1].x)/2;
1798 sp->me.y = (pts[start].y+pts[i-1].y)/2;
1799 sp->nextcp = sp->prevcp = sp->me;
1800 sp->nonextcp = true;
1801 sp->ttfindex = 0xffff;
1802 sp->nextcpindex = start;
1803 FigureControls(cur->last,sp,&pts[i-1],is_order2);
1804 SplineMake(cur->last,sp,is_order2);
1805 cur->last = sp;
1806 FigureControls(sp,cur->first,&pts[start],is_order2);
1807 } else if ( !(flags[i-1]&_On_Curve)) {
1808 FigureControls(cur->last,cur->first,&pts[i-1],is_order2);
1809 cur->last->nextcpindex = i-1;
1810 } else if ( !(flags[start]&_On_Curve) ) {
1811 FigureControls(cur->last,cur->first,&pts[start],is_order2);
1812 sp->nextcpindex = start;
1814 if ( cur->last!=cur->first ) {
1815 SplineMake(cur->last,cur->first,is_order2);
1816 cur->last = cur->first;
1818 for ( sp=cur->first; ; ) {
1819 /*if ( sp->ttfindex!=0xffff && SPInterpolate(sp) )
1820 sp->dontinterpolate = true;*/ /* TODO: needs checking */
1821 if ( sp->next==NULL )
1822 break;
1823 sp=sp->next->to;
1824 if ( sp==cur->first )
1825 break;
1828 return( head );
1831 static void readttfsimpleglyph(FILE *ttf,struct ttfinfo *info,SplineChar *sc, int path_cnt) {
1832 uint16 *endpt = galloc((path_cnt+1)*sizeof(uint16));
1833 uint8 *instructions;
1834 char *flags;
1835 BasePoint *pts;
1836 int i, j, tot, len;
1837 int last_pos;
1839 for ( i=0; i<path_cnt; ++i ) {
1840 endpt[i] = getushort(ttf);
1841 if ( i!=0 && endpt[i]<endpt[i-1] ) {
1842 info->bad_glyph_data = true;
1843 LogError( _("Bad tt font: contour ends make no sense in glyph %d.\n"),
1844 sc->orig_pos );
1845 return;
1848 if ( path_cnt==0 ) {
1849 tot = 0;
1850 pts = galloc(sizeof(BasePoint));
1851 } else {
1852 tot = endpt[path_cnt-1]+1;
1853 pts = galloc(tot*sizeof(BasePoint));
1856 len = getushort(ttf);
1857 instructions = galloc(len);
1858 for ( i=0; i<len; ++i )
1859 instructions[i] = getc(ttf);
1861 flags = galloc(tot);
1862 for ( i=0; i<tot; ++i ) {
1863 flags[i] = getc(ttf);
1864 if ( flags[i]&_Repeat ) {
1865 int cnt = getc(ttf);
1866 if ( i+cnt>=tot ) {
1867 IError("Flag count is wrong (or total is): %d %d", i+cnt, tot );
1868 cnt = tot-i-1;
1870 for ( j=0; j<cnt; ++j )
1871 flags[i+j+1] = flags[i];
1872 i += cnt;
1874 if ( feof(ttf))
1875 break;
1877 if ( i!=tot )
1878 IError("Flag count is wrong (or total is): %d %d in glyph %d", i, tot, sc->orig_pos );
1880 last_pos = 0;
1881 for ( i=0; i<tot; ++i ) {
1882 if ( flags[i]&_X_Short ) {
1883 int off = getc(ttf);
1884 if ( !(flags[i]&_X_Same ) )
1885 off = -off;
1886 pts[i].x = last_pos + off;
1887 } else if ( flags[i]&_X_Same )
1888 pts[i].x = last_pos;
1889 else
1890 pts[i].x = last_pos + (short) getushort(ttf);
1891 last_pos = pts[i].x;
1894 last_pos = 0;
1895 for ( i=0; i<tot; ++i ) {
1896 if ( flags[i]&_Y_Short ) {
1897 int off = getc(ttf);
1898 if ( !(flags[i]&_Y_Same ) )
1899 off = -off;
1900 pts[i].y = last_pos + off;
1901 } else if ( flags[i]&_Y_Same )
1902 pts[i].y = last_pos;
1903 else
1904 pts[i].y = last_pos + (short) getushort(ttf);
1905 last_pos = pts[i].y;
1908 sc->layers[ly_fore].splines = ttfbuildcontours(path_cnt,endpt,flags,pts,info->to_order2);
1909 if ( info->to_order2 && len!=0 ) {
1910 sc->ttf_instrs_len = len;
1911 sc->ttf_instrs = instructions;
1912 } else
1913 free(instructions);
1914 SCCatagorizePoints(sc);
1915 free(endpt);
1916 free(flags);
1917 free(pts);
1918 if ( feof(ttf)) {
1919 LogError( _("Reached end of file when reading simple glyph\n") );
1920 info->bad_glyph_data = true;
1924 static void readttfcompositglyph(FILE *ttf,struct ttfinfo *info,SplineChar *sc, int32 end) {
1925 RefChar *head=NULL, *last=NULL, *cur=NULL;
1926 int flags=0, arg1, arg2;
1927 int use_my_metrics=0;
1929 if ( ftell(ttf)>=end ) {
1930 LogError( _("Empty composite %d\n"), sc->orig_pos );
1931 info->bad_glyph_data = true;
1932 return;
1935 do {
1936 if ( ftell(ttf)>=end ) {
1937 LogError( _("Bad flags value, implied MORE components at end of glyph %d\n"), sc->orig_pos );
1938 info->bad_glyph_data = true;
1939 break;
1941 cur = RefCharCreate();
1942 flags = getushort(ttf);
1943 cur->orig_pos = getushort(ttf);
1944 if ( feof(ttf) || cur->orig_pos>=info->glyph_cnt ) {
1945 LogError(_("Reference to glyph %d out of bounds when parsing 'glyf' table.\n"), cur->orig_pos );
1946 info->bad_glyph_data = true;
1947 cur->orig_pos = 0;
1949 if ( info->inuse!=NULL )
1950 info->inuse[cur->orig_pos] = true;
1951 if ( flags&_ARGS_ARE_WORDS ) {
1952 arg1 = (short) getushort(ttf);
1953 arg2 = (short) getushort(ttf);
1954 } else {
1955 arg1 = (signed char) getc(ttf);
1956 arg2 = (signed char) getc(ttf);
1958 cur->use_my_metrics = (flags & _USE_MY_METRICS) ? 1 : 0;
1959 if ( cur->use_my_metrics ) {
1960 if ( use_my_metrics ) {
1961 LogError( _("Use-my-metrics flag set on at least two components in glyph %d\n"), sc->orig_pos );
1962 info->bad_glyph_data = true;
1963 } else
1964 use_my_metrics = true;
1966 cur->round_translation_to_grid = (flags & _ROUND) ? 1 : 0;
1967 if ( flags & _ARGS_ARE_XY ) {
1968 /* There is some very strange stuff (half-)documented on the apple*/
1969 /* site about how these should be interpretted when there are */
1970 /* scale factors, or rotations */
1971 /* It isn't well enough described to be comprehensible */
1972 /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
1973 /* Microsoft says nothing about this */
1974 /* Adobe implies this is a difference between MS and Apple */
1975 /* MS doesn't do this, Apple does (GRRRGH!!!!) */
1976 /* Adobe says that setting bit 12 means that this will not happen */
1977 /* Adobe says that setting bit 11 means that this will happen */
1978 /* So if either bit is set we know when this happens, if neither */
1979 /* we guess... But I still don't know how to interpret the */
1980 /* apple mode under rotation... */
1981 /* I notice that FreeType does nothing about rotation nor does it */
1982 /* interpret bits 11&12 */
1983 /* Ah. It turns out that even Apple does not do what Apple's docs */
1984 /* claim it does. I think I've worked it out (see below), but... */
1985 /* Bleah! */
1986 cur->transform[4] = arg1;
1987 cur->transform[5] = arg2;
1988 } else {
1989 /* Somehow we can get offsets by looking at the points in the */
1990 /* points so far generated and comparing them to the points in */
1991 /* the current componant */
1992 /* How exactly is not described on any of the Apple, MS, Adobe */
1993 /* freetype looks up arg1 in the set of points we've got so far */
1994 /* looks up arg2 in the new component (before renumbering) */
1995 /* offset.x = arg1.x - arg2.x; offset.y = arg1.y - arg2.y; */
1996 /* This fixup needs to be done later though (after all glyphs */
1997 /* have been loaded) */
1998 cur->match_pt_base = arg1;
1999 cur->match_pt_ref = arg2;
2000 cur->point_match = true;
2002 cur->transform[0] = cur->transform[3] = 1.0;
2003 if ( flags & _SCALE )
2004 cur->transform[0] = cur->transform[3] = get2dot14(ttf);
2005 else if ( flags & _XY_SCALE ) {
2006 cur->transform[0] = get2dot14(ttf);
2007 cur->transform[3] = get2dot14(ttf);
2008 } else if ( flags & _MATRIX ) {
2009 cur->transform[0] = get2dot14(ttf);
2010 cur->transform[1] = get2dot14(ttf);
2011 cur->transform[2] = get2dot14(ttf);
2012 cur->transform[3] = get2dot14(ttf);
2014 if ( flags & _ARGS_ARE_XY ) { /* Only muck with these guys if they are real offsets and not point matching */
2015 #ifdef __Mac
2016 /* On mac assume scaled offsets unless told unscaled explicitly */
2017 if ( !(flags&_UNSCALED_OFFSETS) &&
2018 #else
2019 /* everywhere else assume unscaled offsets unless told scaled explicitly */
2020 if ( (flags & _SCALED_OFFSETS) &&
2021 #endif
2022 (flags & _ARGS_ARE_XY) && (flags&(_SCALE|_XY_SCALE|_MATRIX))) {
2023 /*static int asked = 0;*/
2024 /* This is not what Apple documents on their website. But it is */
2025 /* what appears to match the behavior of their rasterizer */
2026 /* Apple has changed their documentation (without updating their */
2027 /* changelog), but I believe they are still incorrect */
2028 cur->transform[4] *= sqrt(cur->transform[0]*cur->transform[0]+
2029 cur->transform[1]*cur->transform[1]);
2030 cur->transform[5] *= sqrt(cur->transform[2]*cur->transform[2]+
2031 cur->transform[3]*cur->transform[3]);
2032 #if 0
2033 /* Apple's Chicago is an example */
2034 if ( info->fontname!=NULL && strcmp(info->fontname,"CompositeMac")!=0 && !asked ) {
2035 /* Not interested in the test font I generated myself */
2036 asked = true;
2037 fprintf( stderr, "Neat! You've got a font that actually uses Apple's scaled composite offsets.\n" );
2038 fprintf( stderr, " I've never seen one, could you send me a copy of %s?\n", info->fontname );
2039 fprintf( stderr, " Thanks. gww@silcom.com\n" );
2041 #endif
2044 if ( cur->orig_pos>=info->glyph_cnt ) {
2045 LogError(_("Glyph %d attempts to reference glyph %d which is outside the font\n"), sc->orig_pos, cur->orig_pos );
2046 chunkfree(cur,sizeof(*cur));
2047 } else {
2048 if ( head==NULL )
2049 head = cur;
2050 else
2051 last->next = cur;
2052 last = cur;
2054 if ( feof(ttf)) {
2055 LogError(_("Reached end of file when reading composit glyph\n") );
2056 info->bad_glyph_data = true;
2057 break;
2059 } while ( flags&_MORE );
2060 if ( (flags & _INSTR ) && info->to_order2 && ftell(ttf)<end ) {
2061 sc->ttf_instrs_len = getushort(ttf);
2062 if ( sc->ttf_instrs_len > 0 && ftell(ttf)+sc->ttf_instrs_len<=end ) {
2063 uint8 *instructions = galloc(sc->ttf_instrs_len);
2064 int i;
2065 for ( i=0; i<sc->ttf_instrs_len; ++i )
2066 instructions[i] = getc(ttf);
2067 sc->ttf_instrs = instructions;
2068 } else
2069 sc->ttf_instrs_len = 0;
2071 sc->layers[ly_fore].refs = head;
2074 static SplineChar *readttfglyph(FILE *ttf,struct ttfinfo *info,int start, int end,int gid) {
2075 int path_cnt;
2076 SplineChar *sc = SplineCharCreate(2);
2078 sc->unicodeenc = -1;
2079 sc->vwidth = info->emsize;
2080 sc->orig_pos = gid;
2082 if ( end>(int)info->glyph_length ) {
2083 if ( !info->complainedbeyondglyfend )
2084 LogError(_("Bad glyph (%d), its definition extends beyond the end of the glyf table\n"), gid );
2085 info->bad_glyph_data = true;
2086 info->complainedbeyondglyfend = true;
2087 SplineCharFree(sc);
2088 return( NULL );
2089 } else if ( end<start ) {
2090 LogError(_("Bad glyph (%d), its data length is negative\n"), gid );
2091 SplineCharFree(sc);
2092 return( NULL );
2095 if ( start==end ) {
2096 /* This isn't mentioned, but we seem to get some glyphs with no size,*/
2097 /* not even a path cnt. They appear to be empty glyphs */
2098 return( sc );
2100 fseek(ttf,info->glyph_start+start,SEEK_SET);
2101 path_cnt = (short) getushort(ttf);
2103 #ifdef LUA_FF_LIB
2104 sc->xmin = getushort(ttf);
2105 sc->ymin = getushort(ttf);
2106 sc->xmax = getushort(ttf);
2107 sc->ymax = getushort(ttf);
2108 sc->lsidebearing = sc->xmin;
2109 #endif
2110 if (THread_ttf_glyph_data) {
2111 if ( path_cnt>=0 )
2112 readttfsimpleglyph(ttf,info,sc,path_cnt);
2113 else
2114 readttfcompositglyph(ttf,info,sc,info->glyph_start+end);
2115 if ( start>end ) {
2116 LogError(_("Bad glyph (%d), disordered 'loca' table (start comes after end)\n"), gid );
2117 info->bad_glyph_data = true;
2118 } else if ( ftell(ttf)>(long)(info->glyph_start+end) ) {
2119 LogError(_("Bad glyph (%d), its definition extends beyond the space allowed for it\n"), gid );
2120 info->bad_glyph_data = true;
2123 /* find the bb */
2124 THPatchSplineChar(sc);
2127 return( sc );
2130 static void readttfencodings(FILE *ttf,struct ttfinfo *info, int justinuse);
2132 static void readttfglyphs(FILE *ttf,struct ttfinfo *info) {
2133 int i, anyread;
2134 uint32 *goffsets = galloc((info->glyph_cnt+1)*sizeof(uint32));
2136 /* First we read all the locations. This might not be needed, they may */
2137 /* just follow one another, but nothing I've noticed says that so let's */
2138 /* be careful */
2139 fseek(ttf,info->glyphlocations_start,SEEK_SET);
2140 if ( info->index_to_loc_is_long ) {
2141 for ( i=0; i<=info->glyph_cnt ; ++i )
2142 goffsets[i] = getlong(ttf);
2143 } else {
2144 for ( i=0; i<=info->glyph_cnt ; ++i )
2145 goffsets[i] = 2*getushort(ttf);
2148 info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
2149 if ( !info->is_ttc || (info->openflags&of_all_glyphs_in_ttc)) {
2150 /* read all the glyphs */
2151 for ( i=0; i<info->glyph_cnt ; ++i ) {
2152 info->chars[i] = readttfglyph(ttf,info,goffsets[i],goffsets[i+1],i);
2153 ff_progress_next();
2155 } else {
2156 /* only read the glyphs we actually use in this font */
2157 /* this is complicated by references (and substitutions), */
2158 /* we can't just rely on the encoding to tell us what is used */
2159 info->inuse = gcalloc(info->glyph_cnt,sizeof(char));
2160 readttfencodings(ttf,info,git_justinuse);
2161 if ( info->gsub_start!=0 ) /* Some glyphs may appear in substitutions and not in the encoding... */
2162 readttfgsubUsed(ttf,info);
2163 if ( info->math_start!=0 )
2164 otf_read_math_used(ttf,info);
2165 /* I don't bother to read the morx table because mac doesn't */
2166 /* support ttc files */
2167 anyread = true;
2168 while ( anyread ) {
2169 anyread = false;
2170 for ( i=0; i<info->glyph_cnt ; ++i ) {
2171 if ( info->inuse[i] && info->chars[i]==NULL ) {
2172 info->chars[i] = readttfglyph(ttf,info,goffsets[i],goffsets[i+1],i);
2173 ff_progress_next();
2174 anyread = info->chars[i]!=NULL;
2178 free(info->inuse); info->inuse = NULL;
2180 free(goffsets);
2181 for ( i=0; i<info->glyph_cnt ; ++i )
2182 if ( info->chars[i]!=NULL )
2183 info->chars[i]->orig_pos = i;
2184 ff_progress_next_stage();
2187 /* Standard names for cff */
2188 const char *cffnames[] = {
2189 ".notdef",
2190 "space",
2191 "exclam",
2192 "quotedbl",
2193 "numbersign",
2194 "dollar",
2195 "percent",
2196 "ampersand",
2197 "quoteright",
2198 "parenleft",
2199 "parenright",
2200 "asterisk",
2201 "plus",
2202 "comma",
2203 "hyphen",
2204 "period",
2205 "slash",
2206 "zero",
2207 "one",
2208 "two",
2209 "three",
2210 "four",
2211 "five",
2212 "six",
2213 "seven",
2214 "eight",
2215 "nine",
2216 "colon",
2217 "semicolon",
2218 "less",
2219 "equal",
2220 "greater",
2221 "question",
2222 "at",
2223 "A",
2224 "B",
2225 "C",
2226 "D",
2227 "E",
2228 "F",
2229 "G",
2230 "H",
2231 "I",
2232 "J",
2233 "K",
2234 "L",
2235 "M",
2236 "N",
2237 "O",
2238 "P",
2239 "Q",
2240 "R",
2241 "S",
2242 "T",
2243 "U",
2244 "V",
2245 "W",
2246 "X",
2247 "Y",
2248 "Z",
2249 "bracketleft",
2250 "backslash",
2251 "bracketright",
2252 "asciicircum",
2253 "underscore",
2254 "quoteleft",
2255 "a",
2256 "b",
2257 "c",
2258 "d",
2259 "e",
2260 "f",
2261 "g",
2262 "h",
2263 "i",
2264 "j",
2265 "k",
2266 "l",
2267 "m",
2268 "n",
2269 "o",
2270 "p",
2271 "q",
2272 "r",
2273 "s",
2274 "t",
2275 "u",
2276 "v",
2277 "w",
2278 "x",
2279 "y",
2280 "z",
2281 "braceleft",
2282 "bar",
2283 "braceright",
2284 "asciitilde",
2285 "exclamdown",
2286 "cent",
2287 "sterling",
2288 "fraction",
2289 "yen",
2290 "florin",
2291 "section",
2292 "currency",
2293 "quotesingle",
2294 "quotedblleft",
2295 "guillemotleft",
2296 "guilsinglleft",
2297 "guilsinglright",
2298 "fi",
2299 "fl",
2300 "endash",
2301 "dagger",
2302 "daggerdbl",
2303 "periodcentered",
2304 "paragraph",
2305 "bullet",
2306 "quotesinglbase",
2307 "quotedblbase",
2308 "quotedblright",
2309 "guillemotright",
2310 "ellipsis",
2311 "perthousand",
2312 "questiondown",
2313 "grave",
2314 "acute",
2315 "circumflex",
2316 "tilde",
2317 "macron",
2318 "breve",
2319 "dotaccent",
2320 "dieresis",
2321 "ring",
2322 "cedilla",
2323 "hungarumlaut",
2324 "ogonek",
2325 "caron",
2326 "emdash",
2327 "AE",
2328 "ordfeminine",
2329 "Lslash",
2330 "Oslash",
2331 "OE",
2332 "ordmasculine",
2333 "ae",
2334 "dotlessi",
2335 "lslash",
2336 "oslash",
2337 "oe",
2338 "germandbls",
2339 "onesuperior",
2340 "logicalnot",
2341 "mu",
2342 "trademark",
2343 "Eth",
2344 "onehalf",
2345 "plusminus",
2346 "Thorn",
2347 "onequarter",
2348 "divide",
2349 "brokenbar",
2350 "degree",
2351 "thorn",
2352 "threequarters",
2353 "twosuperior",
2354 "registered",
2355 "minus",
2356 "eth",
2357 "multiply",
2358 "threesuperior",
2359 "copyright",
2360 "Aacute",
2361 "Acircumflex",
2362 "Adieresis",
2363 "Agrave",
2364 "Aring",
2365 "Atilde",
2366 "Ccedilla",
2367 "Eacute",
2368 "Ecircumflex",
2369 "Edieresis",
2370 "Egrave",
2371 "Iacute",
2372 "Icircumflex",
2373 "Idieresis",
2374 "Igrave",
2375 "Ntilde",
2376 "Oacute",
2377 "Ocircumflex",
2378 "Odieresis",
2379 "Ograve",
2380 "Otilde",
2381 "Scaron",
2382 "Uacute",
2383 "Ucircumflex",
2384 "Udieresis",
2385 "Ugrave",
2386 "Yacute",
2387 "Ydieresis",
2388 "Zcaron",
2389 "aacute",
2390 "acircumflex",
2391 "adieresis",
2392 "agrave",
2393 "aring",
2394 "atilde",
2395 "ccedilla",
2396 "eacute",
2397 "ecircumflex",
2398 "edieresis",
2399 "egrave",
2400 "iacute",
2401 "icircumflex",
2402 "idieresis",
2403 "igrave",
2404 "ntilde",
2405 "oacute",
2406 "ocircumflex",
2407 "odieresis",
2408 "ograve",
2409 "otilde",
2410 "scaron",
2411 "uacute",
2412 "ucircumflex",
2413 "udieresis",
2414 "ugrave",
2415 "yacute",
2416 "ydieresis",
2417 "zcaron",
2418 "exclamsmall",
2419 "Hungarumlautsmall",
2420 "dollaroldstyle",
2421 "dollarsuperior",
2422 "ampersandsmall",
2423 "Acutesmall",
2424 "parenleftsuperior",
2425 "parenrightsuperior",
2426 "twodotenleader",
2427 "onedotenleader",
2428 "zerooldstyle",
2429 "oneoldstyle",
2430 "twooldstyle",
2431 "threeoldstyle",
2432 "fouroldstyle",
2433 "fiveoldstyle",
2434 "sixoldstyle",
2435 "sevenoldstyle",
2436 "eightoldstyle",
2437 "nineoldstyle",
2438 "commasuperior",
2439 "threequartersemdash",
2440 "periodsuperior",
2441 "questionsmall",
2442 "asuperior",
2443 "bsuperior",
2444 "centsuperior",
2445 "dsuperior",
2446 "esuperior",
2447 "isuperior",
2448 "lsuperior",
2449 "msuperior",
2450 "nsuperior",
2451 "osuperior",
2452 "rsuperior",
2453 "ssuperior",
2454 "tsuperior",
2455 "ff",
2456 "ffi",
2457 "ffl",
2458 "parenleftinferior",
2459 "parenrightinferior",
2460 "Circumflexsmall",
2461 "hyphensuperior",
2462 "Gravesmall",
2463 "Asmall",
2464 "Bsmall",
2465 "Csmall",
2466 "Dsmall",
2467 "Esmall",
2468 "Fsmall",
2469 "Gsmall",
2470 "Hsmall",
2471 "Ismall",
2472 "Jsmall",
2473 "Ksmall",
2474 "Lsmall",
2475 "Msmall",
2476 "Nsmall",
2477 "Osmall",
2478 "Psmall",
2479 "Qsmall",
2480 "Rsmall",
2481 "Ssmall",
2482 "Tsmall",
2483 "Usmall",
2484 "Vsmall",
2485 "Wsmall",
2486 "Xsmall",
2487 "Ysmall",
2488 "Zsmall",
2489 "colonmonetary",
2490 "onefitted",
2491 "rupiah",
2492 "Tildesmall",
2493 "exclamdownsmall",
2494 "centoldstyle",
2495 "Lslashsmall",
2496 "Scaronsmall",
2497 "Zcaronsmall",
2498 "Dieresissmall",
2499 "Brevesmall",
2500 "Caronsmall",
2501 "Dotaccentsmall",
2502 "Macronsmall",
2503 "figuredash",
2504 "hypheninferior",
2505 "Ogoneksmall",
2506 "Ringsmall",
2507 "Cedillasmall",
2508 "questiondownsmall",
2509 "oneeighth",
2510 "threeeighths",
2511 "fiveeighths",
2512 "seveneighths",
2513 "onethird",
2514 "twothirds",
2515 "zerosuperior",
2516 "foursuperior",
2517 "fivesuperior",
2518 "sixsuperior",
2519 "sevensuperior",
2520 "eightsuperior",
2521 "ninesuperior",
2522 "zeroinferior",
2523 "oneinferior",
2524 "twoinferior",
2525 "threeinferior",
2526 "fourinferior",
2527 "fiveinferior",
2528 "sixinferior",
2529 "seveninferior",
2530 "eightinferior",
2531 "nineinferior",
2532 "centinferior",
2533 "dollarinferior",
2534 "periodinferior",
2535 "commainferior",
2536 "Agravesmall",
2537 "Aacutesmall",
2538 "Acircumflexsmall",
2539 "Atildesmall",
2540 "Adieresissmall",
2541 "Aringsmall",
2542 "AEsmall",
2543 "Ccedillasmall",
2544 "Egravesmall",
2545 "Eacutesmall",
2546 "Ecircumflexsmall",
2547 "Edieresissmall",
2548 "Igravesmall",
2549 "Iacutesmall",
2550 "Icircumflexsmall",
2551 "Idieresissmall",
2552 "Ethsmall",
2553 "Ntildesmall",
2554 "Ogravesmall",
2555 "Oacutesmall",
2556 "Ocircumflexsmall",
2557 "Otildesmall",
2558 "Odieresissmall",
2559 "OEsmall",
2560 "Oslashsmall",
2561 "Ugravesmall",
2562 "Uacutesmall",
2563 "Ucircumflexsmall",
2564 "Udieresissmall",
2565 "Yacutesmall",
2566 "Thornsmall",
2567 "Ydieresissmall",
2568 "001.000",
2569 "001.001",
2570 "001.002",
2571 "001.003",
2572 "Black",
2573 "Bold",
2574 "Book",
2575 "Light",
2576 "Medium",
2577 "Regular",
2578 "Roman",
2579 "Semibold",
2580 NULL
2582 const int nStdStrings = sizeof(cffnames)/sizeof(cffnames[0])-1;
2584 static char **readcfffontnames(FILE *ttf,int *cnt,struct ttfinfo *info) {
2585 uint16 count = getushort(ttf);
2586 int offsize;
2587 uint32 *offsets;
2588 char **names;
2589 int i,j;
2591 if ( cnt!=NULL ) *cnt = count;
2593 if ( count==0 )
2594 return( NULL );
2595 offsets = galloc((count+1)*sizeof(uint32));
2596 offsize = getc(ttf);
2597 for ( i=0; i<=count; ++i )
2598 offsets[i] = getoffset(ttf,offsize);
2599 names = galloc((count+1)*sizeof(char *));
2600 for ( i=0; i<count; ++i ) {
2601 if ( offsets[i+1]<offsets[i] ) {
2602 /* GT: The CFF font type contains a thing called a name INDEX, and that INDEX */
2603 /* GT: is bad. It is an index of many of the names used in the CFF font. */
2604 /* GT: We hope the user will never see this. */
2605 LogError( _("Bad CFF name INDEX\n") );
2606 if ( info!=NULL ) info->bad_cff = true;
2607 while ( i<count ) {
2608 names[i] = copy("");
2609 ++i;
2611 --i;
2612 } else {
2613 names[i] = galloc(offsets[i+1]-offsets[i]+1);
2614 for ( j=0; j<(int)(offsets[i+1]-offsets[i]); ++j )
2615 names[i][j] = getc(ttf);
2616 names[i][j] = '\0';
2619 names[i] = NULL;
2620 free(offsets);
2621 return( names );
2624 static char *addnibble(char *pt, int nib) {
2625 if ( nib<=9 )
2626 *pt++ = nib+'0';
2627 else if ( nib==10 )
2628 *pt++ = '.';
2629 else if ( nib==11 )
2630 *pt++ = 'E';
2631 else if ( nib==12 ) {
2632 *pt++ = 'E';
2633 *pt++ = '-';
2634 } else if ( nib==14 )
2635 *pt++ = '-';
2636 else if ( nib==15 )
2637 *pt++ = '\0';
2638 return( pt );
2641 static int readcffthing(FILE *ttf,int *_ival,real *dval,int *operand,struct ttfinfo *info) {
2642 char buffer[50], *pt;
2643 int ch, ival;
2645 ch = getc(ttf);
2646 if ( ch==12 ) {
2647 *operand = (12<<8) | getc(ttf);
2648 return( 3 );
2649 } else if ( ch<=21 ) {
2650 *operand = ch;
2651 return( 3 );
2652 } else if ( ch==30 ) {
2653 /* fixed format doesn't exist in dict data but does in type2 strings */
2654 pt = buffer;
2655 do {
2656 ch = getc(ttf);
2657 if ( pt<buffer+44 || (ch&0xf)==0xf || (ch&0xf0)==0xf0 ) {
2658 pt = addnibble(pt,ch>>4);
2659 pt = addnibble(pt,ch&0xf);
2661 } while ( pt[-1]!='\0' );
2662 *dval = strtod(buffer,NULL);
2663 return( 2 );
2664 } else if ( ch>=32 && ch<=246 ) {
2665 *_ival = ch-139;
2666 return( 1 );
2667 } else if ( ch>=247 && ch<=250 ) {
2668 *_ival = ((ch-247)<<8) + getc(ttf)+108;
2669 return( 1 );
2670 } else if ( ch>=251 && ch<=254 ) {
2671 *_ival = -((ch-251)<<8) - getc(ttf)-108;
2672 return( 1 );
2673 } else if ( ch==28 ) {
2674 ival = getc(ttf)<<8;
2675 *_ival = (short) (ival | getc(ttf));
2676 return( 1 );
2677 } else if ( ch==29 ) {
2678 /* 4 byte integers exist in dict data but not in type2 strings */
2679 ival = getc(ttf)<<24;
2680 ival = ival | getc(ttf)<<16;
2681 ival = ival | getc(ttf)<<8;
2682 *_ival = (int) (ival | getc(ttf));
2683 return( 1 );
2685 LogError(_("Unexpected value in dictionary %d\n"), ch );
2686 info->bad_cff = true;
2687 *_ival = 0;
2688 return( 0 );
2691 static void skipcfft2thing(FILE *ttf) {
2692 /* The old CFF spec allows little type2 programs to live in the CFF dict */
2693 /* indices. These are designed to allow interpolation of values for mm */
2694 /* fonts. */
2695 /* The Type2 program is terminated by an "endchar" operator */
2696 /* I don't support this, but I shall try to skip over them properly */
2697 /* There's no discussion about how values move from the t2 stack to the */
2698 /* cff stack, as there are no examples of this, it's hard to guess */
2699 int ch;
2701 /* GT: DICT is a magic term inside CFF fonts, as is INDEX, and I guess CFF and type2 */
2702 LogError( _("FontForge does not support type2 programs embedded in CFF DICT INDICES.\n") );
2703 forever {
2704 ch = getc(ttf);
2705 if ( ch>=247 && ch<=254 )
2706 getc(ttf); /* Two byte number */
2707 else if ( ch==255 ) {
2708 getc(ttf); getc(ttf); getc(ttf); getc(ttf);
2709 /* 16.16 number */
2710 } else if ( ch==28 ) {
2711 getc(ttf);
2712 getc(ttf);
2713 } else if ( ch==12 ) {
2714 getc(ttf); /* Two byte operator */
2715 } else if ( ch==14 ) {
2716 return;
2721 struct topdicts {
2722 int32 cff_start;
2724 char *fontname; /* From Name Index */
2726 int version; /* SID */
2727 int notice; /* SID */
2728 int copyright; /* SID */
2729 int fullname; /* SID */
2730 int familyname; /* SID */
2731 int weight; /* SID */
2732 int isfixedpitch;
2733 real italicangle;
2734 real underlinepos;
2735 real underlinewidth;
2736 int painttype;
2737 int charstringtype;
2738 real fontmatrix[6];
2739 int fontmatrix_set;
2740 int uniqueid;
2741 real fontbb[4];
2742 real strokewidth;
2743 int xuid[20];
2744 int charsetoff; /* from start of file */
2745 int encodingoff; /* from start of file */
2746 int charstringsoff; /* from start of file */
2747 int private_size;
2748 int private_offset; /* from start of file */
2749 int synthetic_base; /* font index */
2750 int postscript_code; /* SID */
2751 /* synthetic fonts only (whatever they are) */
2752 int basefontname; /* SID */
2753 /* Multiple master/synthetic fonts */
2754 real basefontblend[16]; /* delta */ /* No description of why this is relevant for mm fonts */
2755 /* Multiple master fonts only */
2756 int blendaxistypes[17]; /* SID */
2757 int nMasters;
2758 int nAxes;
2759 real weightvector[17];
2760 int lenBuildCharArray; /* No description of what this means */
2761 int NormalizeDesignVector; /* SID */ /* No description of what this does */
2762 int ConvertDesignVector; /* SID */ /* No description of what this does */
2763 /* CID fonts only */
2764 int ros_registry; /* SID */
2765 int ros_ordering; /* SID */
2766 int ros_supplement;
2767 real cidfontversion;
2768 int cidfontrevision;
2769 int cidfonttype;
2770 int cidcount;
2771 int uidbase;
2772 int fdarrayoff; /* from start of file */
2773 int fdselectoff; /* from start of file */
2774 int sid_fontname; /* SID */
2775 /* Private stuff */
2776 real bluevalues[14];
2777 real otherblues[10];
2778 real familyblues[14];
2779 real familyotherblues[10];
2780 real bluescale;
2781 real blueshift;
2782 real bluefuzz;
2783 int stdhw;
2784 int stdvw;
2785 real stemsnaph[10];
2786 real stemsnapv[10];
2787 int forcebold;
2788 real forceboldthreshold;
2789 int languagegroup;
2790 real expansionfactor;
2791 int initialRandomSeed;
2792 int subrsoff; /* from start of this private table */
2793 int defaultwidthx;
2794 int nominalwidthx;
2796 struct pschars glyphs;
2797 struct pschars local_subrs;
2798 uint16 *charset;
2801 static void TopDictFree(struct topdicts *dict) {
2802 int i;
2804 free(dict->charset);
2805 for ( i=0; i<dict->glyphs.cnt; ++i )
2806 free(dict->glyphs.values[i]);
2807 free(dict->glyphs.values);
2808 free(dict->glyphs.lens);
2809 for ( i=0; i<dict->local_subrs.cnt; ++i )
2810 free(dict->local_subrs.values[i]);
2811 free(dict->local_subrs.values);
2812 free(dict->local_subrs.lens);
2813 free(dict);
2816 static void readcffsubrs(FILE *ttf, struct pschars *subs, struct ttfinfo *info) {
2817 uint16 count = getushort(ttf);
2818 int offsize;
2819 uint32 *offsets;
2820 int i,j, base;
2821 int err = false;
2823 memset(subs,'\0',sizeof(struct pschars));
2824 if ( count==0 )
2825 return;
2826 subs->cnt = count;
2827 subs->lens = galloc(count*sizeof(int));
2828 subs->values = galloc(count*sizeof(uint8 *));
2829 offsets = galloc((count+1)*sizeof(uint32));
2830 offsize = getc(ttf);
2831 for ( i=0; i<=count; ++i )
2832 offsets[i] = getoffset(ttf,offsize);
2833 base = ftell(ttf)-1;
2834 for ( i=0; i<count; ++i ) {
2835 if ( offsets[i+1]>offsets[i] && offsets[i+1]-offsets[i]<0x10000 ) {
2836 subs->lens[i] = offsets[i+1]-offsets[i];
2837 subs->values[i] = galloc(offsets[i+1]-offsets[i]+1);
2838 for ( j=0; j<(int)(offsets[i+1]-offsets[i]); ++j )
2839 subs->values[i][j] = getc(ttf);
2840 subs->values[i][j] = '\0';
2841 } else {
2842 if ( !err )
2843 LogError( _("Bad subroutine INDEX in cff font.\n" ));
2844 info->bad_cff = true;
2845 err = true;
2846 subs->lens[i] = 1;
2847 subs->values[i] = galloc(2);
2848 subs->values[i][0] = 11; /* return */
2849 subs->values[i][1] = '\0';
2850 fseek(ttf,base+offsets[i+1],SEEK_SET);
2853 free(offsets);
2856 static struct topdicts *readcfftopdict(FILE *ttf, char *fontname, int len,
2857 struct ttfinfo *info) {
2858 struct topdicts *td = gcalloc(1,sizeof(struct topdicts));
2859 long base = ftell(ttf);
2860 int ival, oval, sp, ret, i;
2861 real stack[50];
2863 if ( fontname!=NULL )
2864 ValidatePostScriptFontName(info,fontname);
2866 td->fontname = fontname;
2867 td->underlinepos = -100;
2868 td->underlinewidth = 50;
2869 td->charstringtype = 2;
2870 td->fontmatrix[0] = td->fontmatrix[3] = .001;
2872 td->notice = td->copyright = td->fullname = td->familyname = td->weight = td->version = -1;
2873 td->postscript_code = td->basefontname = -1;
2874 td->synthetic_base = td->ros_registry = -1;
2875 td->fdarrayoff = td->fdselectoff = td->sid_fontname = -1;
2876 td->blendaxistypes[0] = -1;
2878 /* Multiple master fonts can have Type2 operators here, particularly */
2879 /* blend operators. We're ignoring that */
2880 while ( ftell(ttf)<base+len ) {
2881 sp = 0;
2882 while ( (ret=readcffthing(ttf,&ival,&stack[sp],&oval,info))!=3 && ftell(ttf)<base+len ) {
2883 if ( ret==1 )
2884 stack[sp]=ival;
2885 if ( ret!=0 && sp<45 )
2886 ++sp;
2888 if ( ret==3 && oval==31 /* "T2" operator, can have 0 arguments */ ) {
2889 skipcfft2thing(ttf);
2890 } else if ( sp==0 ) {
2891 LogError( _("No argument to operator\n") );
2892 info->bad_cff = true;
2893 } else if ( ret==3 ) switch( oval ) {
2894 case 0:
2895 td->version = stack[sp-1];
2896 break;
2897 case 1:
2898 td->notice = stack[sp-1];
2899 break;
2900 case (12<<8)+0:
2901 td->copyright = stack[sp-1];
2902 break;
2903 case 2:
2904 td->fullname = stack[sp-1];
2905 break;
2906 case 3:
2907 td->familyname = stack[sp-1];
2908 break;
2909 case 4:
2910 td->weight = stack[sp-1];
2911 break;
2912 case (12<<8)+1:
2913 td->isfixedpitch = stack[sp-1];
2914 break;
2915 case (12<<8)+2:
2916 td->italicangle = stack[sp-1];
2917 break;
2918 case (12<<8)+3:
2919 td->underlinepos = stack[sp-1];
2920 break;
2921 case (12<<8)+4:
2922 td->underlinewidth = stack[sp-1];
2923 break;
2924 case (12<<8)+5:
2925 td->painttype = stack[sp-1];
2926 break;
2927 case (12<<8)+6:
2928 td->charstringtype = stack[sp-1];
2929 break;
2930 case (12<<8)+7:
2931 memcpy(td->fontmatrix,stack,(sp>=6?6:sp)*sizeof(real));
2932 td->fontmatrix_set = 1;
2933 break;
2934 case 13:
2935 td->uniqueid = stack[sp-1];
2936 break;
2937 case 5:
2938 memcpy(td->fontbb,stack,(sp>=4?4:sp)*sizeof(real));
2939 break;
2940 case (12<<8)+8:
2941 td->strokewidth = stack[sp-1];
2942 break;
2943 case 14:
2944 for ( i=0; i<sp && i<20; ++i )
2945 td->xuid[i] = stack[i];
2946 break;
2947 case 15:
2948 td->charsetoff = stack[sp-1];
2949 break;
2950 case 16:
2951 td->encodingoff = stack[sp-1];
2952 break;
2953 case 17:
2954 td->charstringsoff = stack[sp-1];
2955 break;
2956 case 18:
2957 td->private_size = stack[0];
2958 td->private_offset = stack[1];
2959 break;
2960 case (12<<8)+20:
2961 LogError( _("FontForge does not support synthetic fonts\n") );
2962 td->synthetic_base = stack[sp-1];
2963 break;
2964 case (12<<8)+21:
2965 td->postscript_code = stack[sp-1];
2966 break;
2967 case (12<<8)+22:
2968 td->basefontname = stack[sp-1];
2969 break;
2970 case (12<<8)+23:
2971 for ( i=0; i<sp && i<16; ++i )
2972 td->basefontblend[i] = stack[i];
2973 break;
2974 case (12<<8)+24:
2975 LogError( _("FontForge does not support type2 multiple master fonts\n") );
2976 info->bad_cff = true;
2977 td->nMasters = stack[0];
2978 td->nAxes = sp-4;
2979 memcpy(td->weightvector,stack+1,(sp-4)*sizeof(real));
2980 td->lenBuildCharArray = stack[sp-3];
2981 td->NormalizeDesignVector = stack[sp-2]; /* These are type2 charstrings, even in type1 fonts */
2982 td->ConvertDesignVector = stack[sp-1];
2983 break;
2984 case (12<<8)+26:
2985 for ( i=0; i<sp && i<16; ++i )
2986 td->blendaxistypes[i] = stack[i];
2987 td->blendaxistypes[i] = -1;
2988 break;
2989 case (12<<8)+30:
2990 td->ros_registry = stack[0];
2991 td->ros_ordering = stack[1];
2992 td->ros_supplement = stack[2];
2993 break;
2994 case (12<<8)+31:
2995 td->cidfontversion = stack[sp-1];
2996 break;
2997 case (12<<8)+32:
2998 td->cidfontrevision = stack[sp-1];
2999 break;
3000 case (12<<8)+33:
3001 td->cidfonttype = stack[sp-1];
3002 break;
3003 case (12<<8)+34:
3004 td->cidcount = stack[sp-1];
3005 break;
3006 case (12<<8)+35:
3007 td->uidbase = stack[sp-1];
3008 break;
3009 case (12<<8)+36:
3010 td->fdarrayoff = stack[sp-1];
3011 break;
3012 case (12<<8)+37:
3013 td->fdselectoff = stack[sp-1];
3014 break;
3015 case (12<<8)+38:
3016 td->sid_fontname = stack[sp-1];
3017 break;
3018 case (12<<8)+39:
3019 LogError(_("FontForge does not support Chameleon fonts\n"));;
3020 break;
3021 default:
3022 LogError(_("Unknown operator in %s: %x\n"), fontname, oval );
3023 info->bad_cff = true;
3024 break;
3027 return( td );
3030 static void readcffprivate(FILE *ttf, struct topdicts *td, struct ttfinfo *info) {
3031 int ival, oval, sp, ret, i;
3032 real stack[50];
3033 int32 end = td->cff_start+td->private_offset+td->private_size;
3035 fseek(ttf,td->cff_start+td->private_offset,SEEK_SET);
3037 td->subrsoff = -1;
3038 td->expansionfactor = .06;
3039 td->bluefuzz = 1;
3040 td->blueshift = 7;
3041 td->bluescale = .039625;
3043 while ( ftell(ttf)<end ) {
3044 if ( feof(ttf) ) {
3045 LogError("End of file found when reading private dictionary.\n" );
3046 break;
3048 sp = 0;
3049 while ( (ret=readcffthing(ttf,&ival,&stack[sp],&oval,info))!=3 && ftell(ttf)<end ) {
3050 if ( ret==1 )
3051 stack[sp]=ival;
3052 if ( ret!=0 && sp<45 )
3053 ++sp;
3055 if ( ret==3 && oval==31 /* "T2" operator, can have 0 arguments */ ) {
3056 skipcfft2thing(ttf);
3057 } else if ( sp==0 && oval!=6 && oval!=7 && oval!=8 && oval!=9 && oval !=(12<<8)+12 && oval !=(12<<8)+13) {
3058 LogError( _("No argument to operator %d in private dict\n"), oval );
3059 info->bad_cff = true;
3060 } else if ( ret==3 ) switch( oval ) {
3061 case 6:
3062 for ( i=0; i<sp && i<14; ++i ) {
3063 td->bluevalues[i] = stack[i];
3064 if ( i!=0 )
3065 td->bluevalues[i] += td->bluevalues[i-1];
3067 break;
3068 case 7:
3069 for ( i=0; i<sp && i<10; ++i ) {
3070 td->otherblues[i] = stack[i];
3071 if ( i!=0 )
3072 td->otherblues[i] += td->otherblues[i-1];
3074 break;
3075 case 8:
3076 for ( i=0; i<sp && i<14; ++i ) {
3077 td->familyblues[i] = stack[i];
3078 if ( i!=0 )
3079 td->familyblues[i] += td->familyblues[i-1];
3081 break;
3082 case 9:
3083 for ( i=0; i<sp && i<10; ++i ) {
3084 td->familyotherblues[i] = stack[i];
3085 if ( i!=0 )
3086 td->familyotherblues[i] += td->familyotherblues[i-1];
3088 break;
3089 case (12<<8)+9:
3090 td->bluescale = stack[sp-1];
3091 break;
3092 case (12<<8)+10:
3093 td->blueshift = stack[sp-1];
3094 break;
3095 case (12<<8)+11:
3096 td->bluefuzz = stack[sp-1];
3097 break;
3098 case 10:
3099 td->stdhw = stack[sp-1];
3100 break;
3101 case 11:
3102 td->stdvw = stack[sp-1];
3103 break;
3104 case (12<<8)+12:
3105 for ( i=0; i<sp && i<10; ++i ) {
3106 td->stemsnaph[i] = stack[i];
3107 if ( i!=0 )
3108 td->stemsnaph[i] += td->stemsnaph[i-1];
3110 break;
3111 case (12<<8)+13:
3112 for ( i=0; i<sp && i<10; ++i ) {
3113 td->stemsnapv[i] = stack[i];
3114 if ( i!=0 )
3115 td->stemsnapv[i] += td->stemsnapv[i-1];
3117 break;
3118 case (12<<8)+14:
3119 td->forcebold = stack[sp-1];
3120 break;
3121 case (12<<8)+15: /* obsolete */
3122 td->forceboldthreshold = stack[sp-1];
3123 break;
3124 case (12<<8)+16:
3125 /* lenIV. -1 => unencrypted charstrings */
3126 /* obsolete */
3127 break;
3128 case (12<<8)+17:
3129 td->languagegroup = stack[sp-1];
3130 break;
3131 case (12<<8)+18:
3132 td->expansionfactor = stack[sp-1];
3133 break;
3134 case (12<<8)+19:
3135 td->initialRandomSeed = stack[sp-1];
3136 break;
3137 case 19:
3138 td->subrsoff = stack[sp-1];
3139 break;
3140 case 20:
3141 td->defaultwidthx = stack[sp-1];
3142 break;
3143 case 21:
3144 td->nominalwidthx = stack[sp-1];
3145 break;
3146 default:
3147 LogError(_("Unknown operator in %s: %x\n"), td->fontname, oval );
3148 info->bad_cff = true;
3149 break;
3153 if ( td->subrsoff!=-1 ) {
3154 fseek(ttf,td->cff_start+td->private_offset+td->subrsoff,SEEK_SET);
3155 readcffsubrs(ttf,&td->local_subrs,info);
3159 static struct topdicts **readcfftopdicts(FILE *ttf, char **fontnames, int32 cff_start,
3160 struct ttfinfo *info, struct topdicts *parent_dict) {
3161 uint16 count = getushort(ttf);
3162 int offsize;
3163 uint32 *offsets;
3164 struct topdicts **dicts;
3165 int i;
3167 if ( count==0 )
3168 return( NULL );
3169 offsets = galloc((count+1)*sizeof(uint32));
3170 offsize = getc(ttf);
3171 for ( i=0; i<=count; ++i )
3172 offsets[i] = getoffset(ttf,offsize);
3173 dicts = galloc((count+1)*sizeof(struct topdicts *));
3174 for ( i=0; i<count; ++i ) {
3175 dicts[i] = readcfftopdict(ttf,fontnames!=NULL?fontnames[i]:NULL,
3176 offsets[i+1]-offsets[i], info);
3177 if ( parent_dict!=NULL && parent_dict->fontmatrix_set ) {
3178 MatMultiply(parent_dict->fontmatrix,dicts[i]->fontmatrix,dicts[i]->fontmatrix);
3180 dicts[i]->cff_start = cff_start;
3182 dicts[i] = NULL;
3183 free(offsets);
3184 return( dicts );
3187 static const char *FFgetsid(int sid,char **strings,int scnt,struct ttfinfo *info) {
3188 if ( sid==-1 )
3189 return( NULL );
3190 else if ( sid<nStdStrings )
3191 return( cffnames[sid] );
3192 else if ( sid-nStdStrings>scnt ) {
3193 LogError( _("Bad sid %d (must be less than %d)\n"), sid, scnt+nStdStrings );
3194 if ( info!=NULL ) info->bad_cff = true;
3195 return( NULL );
3196 } else
3197 return( strings[sid-nStdStrings]);
3200 /* I really expect to deal with encodings in ttf cmap, but ocasionally we */
3201 /* get a bare cff */
3202 static void readcffenc(FILE *ttf,struct topdicts *dict,struct ttfinfo *info,
3203 char **strings, int scnt) {
3204 int format, cnt, i, j, pos, first, last, dupenc, sid;
3205 const char *name;
3206 EncMap *map;
3208 if ( info->encoding_start!=0 ) /* Use the cmap instead */
3209 return;
3210 if ( info->subfontcnt!=0 )
3211 return; /* Use cids instead */
3213 for ( i=0; i<info->glyph_cnt; ++i ) {
3214 if ( info->chars[i]->unicodeenc==-1 )
3215 info->chars[i]->unicodeenc = UniFromName(info->chars[i]->name,ui_none,&custom);
3218 map = EncMapNew(256,256,&custom);
3219 if ( dict->encodingoff==0 || dict->encodingoff==1 ) {
3220 /* Standard Encodings */
3221 char **enc = dict->encodingoff==0 ? AdobeStandardEncoding : AdobeExpertEncoding;
3222 map->enc = FindOrMakeEncoding( dict->encodingoff==0 ?
3223 "AdobeStandard" : "Custom" );
3224 if ( map->enc==NULL )
3225 map->enc = &custom;
3226 for ( i=0; i<info->glyph_cnt; ++i ) {
3227 for ( pos=0; pos<256; ++pos )
3228 if ( strcmp(info->chars[i]->name,enc[pos])==0 )
3229 break;
3230 if ( pos<256 )
3231 map->map[pos] = i;
3233 } else {
3234 fseek(ttf,dict->cff_start+dict->encodingoff,SEEK_SET);
3235 format = getc(ttf);
3236 if ( (format&0x7f)==0 ) {
3237 cnt = getc(ttf);
3238 for ( i=1; i<=cnt && i<info->glyph_cnt; ++i )
3239 map->map[getc(ttf)] = i;
3240 } else if ( (format&0x7f)==1 ) {
3241 cnt = getc(ttf);
3242 pos = 0;
3243 for ( i=0; i<cnt ; ++i ) {
3244 first = getc(ttf);
3245 last = first + getc(ttf)-1;
3246 while ( first<=last && first<256 ) {
3247 if ( pos<info->glyph_cnt )
3248 map->map[first] = pos;
3249 ++pos;
3250 ++first;
3253 } else {
3254 LogError( _("Unexpected encoding format in cff: %d\n"), format );
3255 if ( info!=NULL ) info->bad_cff = true;
3257 if ( format&0x80 ) {
3258 cnt = getc(ttf);
3259 for ( i=0; i<cnt; ++i ) {
3260 dupenc = getc(ttf);
3261 sid = getushort(ttf);
3262 name = FFgetsid(sid,strings,scnt,info);
3263 if ( name==NULL ) /* Table is erroneous */
3264 break;
3265 for ( j=0; j<info->glyph_cnt; ++j )
3266 if ( strcmp(name,info->chars[j]->name)==0 )
3267 break;
3268 if ( j!=info->glyph_cnt )
3269 map->map[dupenc] = j;
3273 info->map = map;
3276 static void readcffset(FILE *ttf,struct topdicts *dict,struct ttfinfo *info) {
3277 int len = dict->glyphs.cnt;
3278 int i;
3279 int format, cnt, j, first;
3281 i = 0;
3282 if ( dict->charsetoff==0 ) {
3283 /* ISO Adobe charset */
3284 dict->charset = galloc(len*sizeof(uint16));
3285 for ( i=0; i<len && i<=228; ++i )
3286 dict->charset[i] = i;
3287 } else if ( dict->charsetoff==1 ) {
3288 /* Expert charset */
3289 dict->charset = galloc((len<162?162:len)*sizeof(uint16));
3290 dict->charset[0] = 0; /* .notdef */
3291 dict->charset[1] = 1;
3292 for ( i=2; i<len && i<=238-227; ++i )
3293 dict->charset[i] = i+227;
3294 dict->charset[12] = 13;
3295 dict->charset[13] = 14;
3296 dict->charset[14] = 15;
3297 dict->charset[15] = 99;
3298 for ( i=16; i<len && i<=248-223; ++i )
3299 dict->charset[i] = i+223;
3300 dict->charset[25] = 27;
3301 dict->charset[26] = 28;
3302 for ( i=27; i<len && i<=266-222; ++i )
3303 dict->charset[i] = i+222;
3304 dict->charset[44] = 109;
3305 dict->charset[45] = 110;
3306 for ( i=46; i<len && i<=318-221; ++i )
3307 dict->charset[i] = i+221;
3308 dict->charset[96] = 158;
3309 dict->charset[97] = 155;
3310 dict->charset[98] = 163;
3311 for ( i=99; i<len && i<=326-220; ++i )
3312 dict->charset[i] = i+220;
3313 dict->charset[107] = 150;
3314 dict->charset[108] = 164;
3315 dict->charset[109] = 169;
3316 for ( i=110; i<len && i<=378-217; ++i )
3317 dict->charset[i] = i+217;
3318 } else if ( dict->charsetoff==2 ) {
3319 /* Expert subset charset */
3320 dict->charset = galloc((len<130?130:len)*sizeof(uint16));
3321 dict->charset[0] = 0; /* .notdef */
3322 dict->charset[1] = 1;
3323 for ( i=2; i<len && i<=238-227; ++i )
3324 dict->charset[i] = i+227;
3325 dict->charset[12] = 13;
3326 dict->charset[13] = 14;
3327 dict->charset[14] = 15;
3328 dict->charset[15] = 99;
3329 for ( i=16; i<len && i<=248-223; ++i )
3330 dict->charset[i] = i+223;
3331 dict->charset[25] = 27;
3332 dict->charset[26] = 28;
3333 for ( i=27; i<len && i<=266-222; ++i )
3334 dict->charset[i] = i+222;
3335 dict->charset[44] = 109;
3336 dict->charset[45] = 110;
3337 for ( i=46; i<len && i<=272-221; ++i )
3338 dict->charset[i] = i+221;
3339 dict->charset[51] = 300;
3340 dict->charset[52] = 301;
3341 dict->charset[53] = 302;
3342 dict->charset[54] = 305;
3343 dict->charset[55] = 314;
3344 dict->charset[56] = 315;
3345 dict->charset[57] = 158;
3346 dict->charset[58] = 155;
3347 dict->charset[59] = 163;
3348 for ( i=60; i<len && i<=326-260; ++i )
3349 dict->charset[i] = i+260;
3350 dict->charset[67] = 150;
3351 dict->charset[68] = 164;
3352 dict->charset[69] = 169;
3353 for ( i=110; i<len && i<=346-217; ++i )
3354 dict->charset[i] = i+217;
3355 } else {
3356 dict->charset = galloc(len*sizeof(uint16));
3357 dict->charset[0] = 0; /* .notdef */
3358 fseek(ttf,dict->cff_start+dict->charsetoff,SEEK_SET);
3359 format = getc(ttf);
3360 if ( format==0 ) {
3361 for ( i=1; i<len; ++i )
3362 dict->charset[i] = getushort(ttf);
3363 } else if ( format==1 ) {
3364 for ( i = 1; i<len; ) {
3365 first = dict->charset[i++] = getushort(ttf);
3366 cnt = getc(ttf);
3367 for ( j=0; j<cnt; ++j )
3368 dict->charset[i++] = ++first;
3370 } else if ( format==2 ) {
3371 for ( i = 1; i<len; ) {
3372 first = dict->charset[i++] = getushort(ttf);
3373 cnt = getushort(ttf);
3374 for ( j=0; j<cnt; ++j )
3375 dict->charset[i++] = ++first;
3377 } else {
3378 LogError( _("Unexpected charset format in cff: %d\n"), format );
3379 if ( info!=NULL ) info->bad_cff = true;
3382 while ( i<len ) dict->charset[i++] = 0;
3385 static uint8 *readfdselect(FILE *ttf,int numglyphs,struct ttfinfo *info) {
3386 uint8 *fdselect = gcalloc(numglyphs,sizeof(uint8));
3387 int i, j, format, nr, first, end, fd;
3389 format = getc(ttf);
3390 if ( format==0 ) {
3391 for ( i=0; i<numglyphs; ++i )
3392 fdselect[i] = getc(ttf);
3393 } else if ( format==3 ) {
3394 nr = getushort(ttf);
3395 first = getushort(ttf);
3396 for ( i=0; i<nr; ++i ) {
3397 fd = getc(ttf);
3398 end = getushort(ttf);
3399 for ( j=first; j<end; ++j ) {
3400 if ( j>=numglyphs ) {
3401 LogError( _("Bad fdselect\n") );
3402 if ( info!=NULL ) info->bad_cff = true;
3403 } else
3404 fdselect[j] = fd;
3406 first = end;
3408 } else {
3409 LogError( _("Didn't understand format for fdselect %d\n"), format );
3410 if ( info!=NULL ) info->bad_cff = true;
3412 return( fdselect );
3416 static char *intarray2str(int *array, int size) {
3417 int i,j;
3418 char *pt, *ret;
3420 for ( i=size-1; i>=0 && array[i]==0; --i );
3421 if ( i==-1 )
3422 return( NULL );
3423 ret = pt = galloc((i+1)*12+12);
3424 *pt++ = '[';
3425 for ( j=0; j<=i; ++j ) {
3426 sprintf( pt, "%d ", array[j]);
3427 pt += strlen(pt);
3429 pt[-1]=']';
3430 return( ret );
3433 static char *realarray2str(real *array, int size, int must_be_even) {
3434 int i,j;
3435 char *pt, *ret;
3437 for ( i=size-1; i>=0 && array[i]==0; --i );
3438 if ( i==-1 )
3439 return( NULL );
3440 if ( must_be_even && !(i&1) && array[i]<0 )
3441 ++i; /* Someone gave us a bluevalues of [-20 0] and we reported [-20] */
3442 ret = pt = galloc((i+1)*20+12);
3443 *pt++ = '[';
3444 for ( j=0; j<=i; ++j ) {
3445 sprintf( pt, "%g ", (double) array[j]);
3446 pt += strlen(pt);
3448 pt[-1]=']';
3449 return( ret );
3452 static void privateadd(struct psdict *private,char *key,char *value) {
3453 if ( value==NULL )
3454 return;
3455 private->keys[private->next] = copy(key);
3456 private->values[private->next++] = value;
3459 static void privateaddint(struct psdict *private,char *key,int val) {
3460 char buf[20];
3461 if ( val==0 )
3462 return;
3463 sprintf( buf,"%d", val );
3464 privateadd(private,key,copy(buf));
3467 static void privateaddintarray(struct psdict *private,char *key,int val) {
3468 char buf[20];
3469 if ( val==0 )
3470 return;
3471 sprintf( buf,"[%d]", val );
3472 privateadd(private,key,copy(buf));
3475 static void privateaddreal(struct psdict *private,char *key,double val,double def) {
3476 char buf[20];
3477 if ( val==def )
3478 return;
3479 sprintf( buf,"%g", val );
3480 privateadd(private,key,copy(buf));
3483 static void cffprivatefillup(struct psdict *private, struct topdicts *dict) {
3484 private->cnt = 14;
3485 private->keys = galloc(14*sizeof(char *));
3486 private->values = galloc(14*sizeof(char *));
3487 privateadd(private,"BlueValues",
3488 realarray2str(dict->bluevalues,sizeof(dict->bluevalues)/sizeof(dict->bluevalues[0]),true));
3489 privateadd(private,"OtherBlues",
3490 realarray2str(dict->otherblues,sizeof(dict->otherblues)/sizeof(dict->otherblues[0]),true));
3491 privateadd(private,"FamilyBlues",
3492 realarray2str(dict->familyblues,sizeof(dict->familyblues)/sizeof(dict->familyblues[0]),true));
3493 privateadd(private,"FamilyOtherBlues",
3494 realarray2str(dict->familyotherblues,sizeof(dict->familyotherblues)/sizeof(dict->familyotherblues[0]),true));
3495 privateaddreal(private,"BlueScale",dict->bluescale,0.039625);
3496 privateaddreal(private,"BlueShift",dict->blueshift,7);
3497 privateaddreal(private,"BlueFuzz",dict->bluefuzz,1);
3498 privateaddintarray(private,"StdHW",dict->stdhw);
3499 privateaddintarray(private,"StdVW",dict->stdvw);
3500 privateadd(private,"StemSnapH",
3501 realarray2str(dict->stemsnaph,sizeof(dict->stemsnaph)/sizeof(dict->stemsnaph[0]),false));
3502 privateadd(private,"StemSnapV",
3503 realarray2str(dict->stemsnapv,sizeof(dict->stemsnapv)/sizeof(dict->stemsnapv[0]),false));
3504 if ( dict->forcebold )
3505 privateadd(private,"ForceBold",copy("true"));
3506 if ( dict->forceboldthreshold!=0 )
3507 privateaddreal(private,"ForceBoldThreshold",dict->forceboldthreshold,0);
3508 privateaddint(private,"LanguageGroup",dict->languagegroup);
3509 privateaddreal(private,"ExpansionFactor",dict->expansionfactor,0.06);
3512 static SplineFont *cffsffillup(struct topdicts *subdict, char **strings,
3513 int scnt, struct ttfinfo *info) {
3514 SplineFont *sf = SplineFontEmpty();
3515 int emsize;
3516 static int nameless;
3518 sf->fontname = utf8_verify_copy(FFgetsid(subdict->sid_fontname,strings,scnt,info));
3519 if ( sf->fontname==NULL ) {
3520 char buffer[40];
3521 sprintf(buffer,"UntitledSubFont_%d", ++nameless );
3522 sf->fontname = copy(buffer);
3525 if ( subdict->fontmatrix[0]==0 )
3526 emsize = 1000;
3527 else
3528 emsize = rint( 1/subdict->fontmatrix[0] );
3529 sf->ascent = .8*emsize;
3530 sf->descent = emsize - sf->ascent;
3531 if ( subdict->copyright!=-1 )
3532 sf->copyright = utf8_verify_copy(FFgetsid(subdict->copyright,strings,scnt,info));
3533 else
3534 sf->copyright = utf8_verify_copy(FFgetsid(subdict->notice,strings,scnt,info));
3535 sf->familyname = utf8_verify_copy(FFgetsid(subdict->familyname,strings,scnt,info));
3536 sf->fullname = utf8_verify_copy(FFgetsid(subdict->fullname,strings,scnt,info));
3537 sf->weight = utf8_verify_copy(FFgetsid(subdict->weight,strings,scnt,info));
3538 sf->version = utf8_verify_copy(FFgetsid(subdict->version,strings,scnt,info));
3539 sf->italicangle = subdict->italicangle;
3540 sf->upos = subdict->underlinepos;
3541 sf->uwidth = subdict->underlinewidth;
3542 sf->xuid = intarray2str(subdict->xuid,sizeof(subdict->xuid)/sizeof(subdict->xuid[0]));
3543 sf->uniqueid = subdict->uniqueid;
3544 sf->strokewidth = subdict->strokewidth;
3545 sf->strokedfont = subdict->painttype==2;
3547 if ( subdict->private_size>0 ) {
3548 sf->private = gcalloc(1,sizeof(struct psdict));
3549 cffprivatefillup(sf->private,subdict);
3551 return( sf );
3554 static void cffinfofillup(struct ttfinfo *info, struct topdicts *dict,
3555 char **strings, int scnt ) {
3557 info->glyph_cnt = dict->glyphs.cnt;
3558 if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
3560 if ( dict->fontmatrix[0]==0 )
3561 info->emsize = 1000;
3562 else
3563 info->emsize = rint( 1/dict->fontmatrix[0] );
3564 #if 1
3565 info->ascent = .8*info->emsize;
3566 #else
3567 info->ascent = dict->fontbb[3]*info->emsize/(dict->fontbb[3]-dict->fontbb[1]);
3568 #endif
3569 info->descent = info->emsize - info->ascent;
3570 if ( dict->copyright!=-1 || dict->notice!=-1 )
3571 free( info->copyright );
3572 if ( dict->copyright!=-1 )
3573 info->copyright = utf8_verify_copy(FFgetsid(dict->copyright,strings,scnt,info));
3574 else if ( dict->notice!=-1 )
3575 info->copyright = utf8_verify_copy(FFgetsid(dict->notice,strings,scnt,info));
3576 if ( dict->familyname!=-1 ) {
3577 free(info->familyname);
3578 info->familyname = utf8_verify_copy(FFgetsid(dict->familyname,strings,scnt,info));
3580 if ( dict->fullname!=-1 ) {
3581 free(info->fullname);
3582 info->fullname = utf8_verify_copy(FFgetsid(dict->fullname,strings,scnt,info));
3584 if ( dict->weight!=-1 ) {
3585 free(info->weight);
3586 info->weight = utf8_verify_copy(FFgetsid(dict->weight,strings,scnt,info));
3588 if ( dict->version!=-1 ) {
3589 free(info->version);
3590 info->version = utf8_verify_copy(FFgetsid(dict->version,strings,scnt,info));
3592 if ( dict->fontname!=NULL ) {
3593 free(info->fontname);
3594 info->fontname = utf8_verify_copy(dict->fontname);
3596 info->italicAngle = dict->italicangle;
3597 info->upos = dict->underlinepos;
3598 info->uwidth = dict->underlinewidth;
3599 info->xuid = intarray2str(dict->xuid,sizeof(dict->xuid)/sizeof(dict->xuid[0]));
3600 info->uniqueid = dict->uniqueid;
3601 info->strokewidth = dict->strokewidth;
3602 info->strokedfont = dict->painttype==2;
3604 if ( dict->private_size>0 ) {
3605 info->private = gcalloc(1,sizeof(struct psdict));
3606 cffprivatefillup(info->private,dict);
3608 if ( dict->ros_registry!=-1 ) {
3609 info->cidregistry = copy(FFgetsid(dict->ros_registry,strings,scnt,info));
3610 info->ordering = copy(FFgetsid(dict->ros_ordering,strings,scnt,info));
3611 info->supplement = dict->ros_supplement;
3612 info->cidfontversion = dict->cidfontversion;
3616 static void cfffigure(struct ttfinfo *info, struct topdicts *dict,
3617 char **strings, int scnt, struct pschars *gsubrs) {
3618 int i, cstype;
3619 struct pschars *subrs;
3620 struct pscontext pscontext;
3621 memset(&pscontext,0,sizeof(pscontext));
3623 cffinfofillup(info, dict, strings, scnt );
3625 /* The format allows for some dicts that are type1 strings and others that */
3626 /* are type2s. Which means that the global subrs will have a different bias */
3627 /* as we flip from font to font. So we can't set the bias when we read in */
3628 /* the subrs but must wait until we know which font we're working on. */
3629 cstype = dict->charstringtype;
3630 pscontext.is_type2 = cstype-1;
3631 pscontext.painttype = dict->painttype;
3632 gsubrs->bias = cstype==1 ? 0 :
3633 gsubrs->cnt < 1240 ? 107 :
3634 gsubrs->cnt <33900 ? 1131 : 32768;
3635 subrs = &dict->local_subrs;
3636 subrs->bias = cstype==1 ? 0 :
3637 subrs->cnt < 1240 ? 107 :
3638 subrs->cnt <33900 ? 1131 : 32768;
3640 info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
3641 for ( i=0; i<info->glyph_cnt; ++i ) {
3642 info->chars[i] = PSCharStringToBB(
3643 dict->glyphs.values[i], dict->glyphs.lens[i],&pscontext,
3644 subrs,gsubrs,FFgetsid(dict->charset[i],strings,scnt,info));
3645 info->chars[i]->vwidth = info->emsize;
3646 if ( cstype==2 ) {
3647 if ( info->chars[i]->width == (int16) 0x8000 )
3648 info->chars[i]->width = dict->defaultwidthx;
3649 else
3650 info->chars[i]->width += dict->nominalwidthx;
3653 /* Need to do a reference fixup here !!!!! just in case some idiot */
3654 /* used type1 char strings -- or used the depreciated meaning of */
3655 /* endchar (==seac) */
3658 static void cidfigure(struct ttfinfo *info, struct topdicts *dict,
3659 char **strings, int scnt, struct pschars *gsubrs, struct topdicts **subdicts,
3660 uint8 *fdselect) {
3661 int i, j, cstype, uni, cid;
3662 struct pschars *subrs;
3663 SplineFont *sf;
3664 struct cidmap *map;
3665 char buffer[100];
3666 struct pscontext pscontext;
3667 EncMap *encmap = NULL;
3669 memset(&pscontext,0,sizeof(pscontext));
3671 cffinfofillup(info, dict, strings, scnt );
3673 /* We'll set the encmap later */
3674 /*info->map = encmap = EncMapNew(info->glyph_cnt,info->glyph_cnt,&custom);*/
3676 for ( j=0; subdicts[j]!=NULL; ++j );
3677 info->subfontcnt = j;
3678 info->subfonts = gcalloc(j+1,sizeof(SplineFont *));
3679 for ( j=0; subdicts[j]!=NULL; ++j ) {
3680 info->subfonts[j] = cffsffillup(subdicts[j],strings,scnt,info);
3681 info->subfonts[j]->map = encmap;
3682 info->subfonts[j]->glyphmin = -1;
3684 /* here we also deal with glyphmin */
3686 for ( i=0; i<info->glyph_cnt; ++i ) {
3687 sf = info->subfonts[ fdselect[i] ];
3688 cid = dict->charset[i];
3689 if ( cid>=sf->glyphcnt ) {
3690 if (sf->glyphmin == -1) {
3691 sf->glyphmin = cid;
3693 sf->glyphcnt = sf->glyphmax = cid+1;
3695 /*if ( cid>=encmap->enccount )
3696 encmap->enccount = cid+1;*/
3698 for ( j=0; subdicts[j]!=NULL; ++j )
3699 info->subfonts[j]->glyphs = gcalloc(info->subfonts[j]->glyphcnt,sizeof(SplineChar *));
3701 /*encmap->encmax = encmap->enccount;*/
3702 /*encmap->map = galloc(encmap->enccount*sizeof(int));*/
3703 /*memset(encmap->map,-1,encmap->enccount*sizeof(int));*/
3705 info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
3707 /* info->chars provides access to the chars ordered by glyph, which the */
3708 /* ttf routines care about */
3709 /* sf->glyphs provides access to the chars ordered by CID. Not sure what */
3710 /* would happen to a kern from one font to another... */
3712 map = FindCidMap(info->cidregistry,info->ordering,info->supplement,NULL);
3714 for ( i=0; i<info->glyph_cnt; ++i ) {
3715 j = fdselect[i];
3716 sf = info->subfonts[j];
3717 /* The format allows for some dicts that are type1 strings and others that */
3718 /* are type2s. Which means that the global subrs will have a different bias */
3719 /* as we flip from font to font. So we can't set the bias when we read in */
3720 /* the subrs but must wait until we know which font we're working on. */
3721 cstype = subdicts[j]->charstringtype;
3722 pscontext.is_type2 = cstype-1;
3723 pscontext.painttype = subdicts[j]->painttype;
3724 gsubrs->bias = cstype==1 ? 0 :
3725 gsubrs->cnt < 1240 ? 107 :
3726 gsubrs->cnt <33900 ? 1131 : 32768;
3727 subrs = &subdicts[j]->local_subrs;
3728 subrs->bias = cstype==1 ? 0 :
3729 subrs->cnt < 1240 ? 107 :
3730 subrs->cnt <33900 ? 1131 : 32768;
3731 cid = dict->charset[i];
3732 /*encmap->map[cid] = cid;*/
3733 uni = CID2NameUni(map,cid,buffer,sizeof(buffer));
3734 info->chars[i] = PSCharStringToBB(
3735 dict->glyphs.values[i], dict->glyphs.lens[i],&pscontext,
3736 subrs,gsubrs,buffer);
3737 info->chars[i]->vwidth = sf->ascent+sf->descent;
3738 info->chars[i]->unicodeenc = uni;
3739 sf->glyphs[cid] = info->chars[i];
3740 sf->glyphs[cid]->parent = sf;
3741 sf->glyphs[cid]->orig_pos = i; /* fixed in 0.80.1 */
3742 if ( sf->glyphs[cid]->layers[ly_fore].refs!=NULL )
3743 IError( "Reference found in CID font. Can't fix it up");
3744 THPatchSplineChar(sf->glyphs[cid]);
3745 if ( cstype==2 ) {
3746 if ( sf->glyphs[cid]->width == (int16) 0x8000 )
3747 sf->glyphs[cid]->width = subdicts[j]->defaultwidthx;
3748 else
3749 sf->glyphs[cid]->width += subdicts[j]->nominalwidthx;
3751 ff_progress_next();
3753 /* No need to do a reference fixup here-- the chars aren't associated */
3754 /* with any encoding as is required for seac */
3757 static int readcffglyphs(FILE *ttf,struct ttfinfo *info) {
3758 int offsize;
3759 int hdrsize;
3760 char **fontnames, **strings;
3761 struct topdicts **dicts, **subdicts;
3762 int i, j, which;
3763 struct pschars gsubs;
3764 uint8 *fdselect;
3765 int scnt;
3767 fseek(ttf,info->cff_start,SEEK_SET);
3768 if ( getc(ttf)!='\1' ) { /* Major version */
3769 LogError( _("CFF version mismatch\n" ));
3770 info->bad_cff = true;
3771 return( 0 );
3773 getc(ttf); /* Minor version */
3774 hdrsize = getc(ttf);
3775 offsize = getc(ttf);
3776 if ( hdrsize!=4 )
3777 fseek(ttf,info->cff_start+hdrsize,SEEK_SET);
3778 fontnames = readcfffontnames(ttf,NULL,info);
3779 which = 0;
3780 if ( fontnames[1]!=NULL ) { /* More than one? Can that even happen in OpenType? */
3781 which = PickCFFFont(fontnames);
3782 if ( which==-1 ) {
3783 for ( i=0; fontnames[i]!=NULL; ++i )
3784 free(fontnames[i]);
3785 free(fontnames);
3786 return( 0 );
3789 dicts = readcfftopdicts(ttf,fontnames,info->cff_start,info, NULL);
3790 /* String index is just the same as fontname index */
3791 strings = readcfffontnames(ttf,&scnt,info);
3792 readcffsubrs(ttf,&gsubs,info );
3793 /* Can be many fonts here. Only decompose the one */
3794 if ( dicts[which]->charstringsoff!=-1 ) {
3795 fseek(ttf,info->cff_start+dicts[which]->charstringsoff,SEEK_SET);
3796 readcffsubrs(ttf,&dicts[which]->glyphs,info);
3798 if ( dicts[which]->private_offset!=-1 )
3799 readcffprivate(ttf,dicts[which],info);
3800 if ( dicts[which]->charsetoff!=-1 )
3801 readcffset(ttf,dicts[which],info);
3802 if ( dicts[which]->fdarrayoff==-1 )
3803 cfffigure(info,dicts[which],strings,scnt,&gsubs);
3804 else {
3805 fseek(ttf,info->cff_start+dicts[which]->fdarrayoff,SEEK_SET);
3806 subdicts = readcfftopdicts(ttf,NULL,info->cff_start,info,dicts[which]);
3807 fseek(ttf,info->cff_start+dicts[which]->fdselectoff,SEEK_SET);
3808 fdselect = readfdselect(ttf,dicts[which]->glyphs.cnt,info);
3809 for ( j=0; subdicts[j]!=NULL; ++j ) {
3810 if ( subdicts[j]->private_offset!=-1 )
3811 readcffprivate(ttf,subdicts[j],info);
3812 if ( subdicts[j]->charsetoff!=-1 )
3813 readcffset(ttf,subdicts[j],info);
3815 cidfigure(info,dicts[which],strings,scnt,&gsubs,subdicts,fdselect);
3816 for ( j=0; subdicts[j]!=NULL; ++j )
3817 TopDictFree(subdicts[j]);
3818 free(subdicts); free(fdselect);
3820 if ( dicts[which]->encodingoff!=-1 )
3821 readcffenc(ttf,dicts[which],info,strings,scnt);
3823 if ( dicts[which]->fdarrayoff==-1 ) {
3824 for ( i=0; i<info->glyph_cnt ; ++i )
3825 if ( info->chars[i]!=NULL )
3826 info->chars[i]->orig_pos = i;
3829 if ( info->to_order2 ) {
3830 for ( i=0; i<info->glyph_cnt; ++i )
3831 SCConvertToOrder2(info->chars[i]);
3834 for ( i=0; fontnames[i]!=NULL && i<1; ++i ) {
3835 free(fontnames[i]);
3836 TopDictFree(dicts[i]);
3838 free(fontnames); free(dicts);
3839 if ( strings!=NULL ) {
3840 for ( i=0; strings[i]!=NULL; ++i )
3841 free(strings[i]);
3842 free(strings);
3844 for ( i=0; i<gsubs.cnt; ++i )
3845 free(gsubs.values[i]);
3846 free(gsubs.values); free(gsubs.lens);
3848 return( 1 );
3851 static int readtyp1glyphs(FILE *ttf,struct ttfinfo *info) {
3852 FontDict *fd;
3853 FILE *tmp;
3854 int i;
3855 SplineChar *sc;
3857 fseek(ttf,info->typ1_start,SEEK_SET);
3858 /* There appear to be about 20 bytes of garbage (well, I don't know what they */
3859 /* mean, so they are garbage to me) before the start of the PostScript. But */
3860 /* it's not exactly 20. I've seen 22 and 24. So see if we can find "%!PS-Adobe" */
3861 /* in the first few bytes of the file, and skip to there if found */
3862 { char buffer[41];
3863 if(fread(buffer,1,sizeof(buffer),ttf) != sizeof(buffer))
3864 return( false );
3865 buffer[40] = '\0';
3866 for ( i=39; i>=0; --i )
3867 if ( buffer[i]=='%' && buffer[i+1]=='!' )
3868 break;
3869 if ( i<0 )
3870 i = 0;
3871 fseek(ttf,info->typ1_start+i,SEEK_SET);
3874 tmp = tmpfile();
3875 for ( i=0; i<(int)info->typ1_length; ++i )
3876 putc(getc(ttf),tmp);
3877 rewind(tmp);
3878 fd = _ReadPSFont(tmp);
3879 fclose(tmp);
3880 if ( fd!=NULL ) {
3881 SplineFont *sf = SplineFontFromPSFont(fd);
3882 PSFontFree(fd);
3883 info->emsize = (sf->ascent+sf->descent);
3884 info->ascent = sf->ascent;
3885 info->descent = sf->descent;
3886 if ( sf->subfontcnt!=0 ) {
3887 info->subfontcnt = sf->subfontcnt;
3888 info->subfonts = sf->subfonts;
3889 info->cidregistry = copy(sf->cidregistry);
3890 info->ordering = copy(sf->ordering);
3891 info->supplement = sf->supplement;
3892 info->cidfontversion = sf->cidversion;
3893 sf->subfonts = NULL;
3894 sf->subfontcnt = 0;
3895 } else {
3896 info->chars = sf->glyphs;
3897 info->glyph_cnt = sf->glyphcnt;
3898 for ( i=sf->glyphcnt-1; i>=0; --i ) if ( (sc=sf->glyphs[i])!=NULL )
3899 sc->parent = NULL;
3900 sf->glyphs = NULL;
3901 sf->glyphcnt = 0;
3903 SplineFontFree(sf);
3904 return( true );
3906 return( false );
3909 static void readttfwidths(FILE *ttf,struct ttfinfo *info) {
3910 int i,j;
3911 int lastwidth = info->emsize, lsb;
3912 /* I'm not interested in the lsb, I'm not sure what it means if it differs*/
3913 /* from that is specified in the outline. Do we move the outline? */
3914 /* Ah... I am interested in it if bit 1 of 'head'.flags is set, then we */
3915 /* do move the outline */
3916 int check_width_consistency = info->cff_start!=0 && info->glyph_start==0;
3917 SplineChar *sc;
3918 real trans[6];
3920 memset(trans,0,sizeof(trans));
3921 trans[0] = trans[3] = 1;
3923 fseek(ttf,info->hmetrics_start,SEEK_SET);
3924 for ( i=0; i<info->width_cnt && i<info->glyph_cnt; ++i ) {
3925 lastwidth = getushort(ttf);
3926 lsb = (short) getushort(ttf);
3927 if ( (sc = info->chars[i])!=NULL ) { /* can happen in ttc files */
3928 if ( check_width_consistency && sc->width!=lastwidth ) {
3929 if ( info->fontname!=NULL && sc->name!=NULL )
3930 LogError("In %s, in glyph %s, 'CFF ' advance width (%d) and\n 'hmtx' width (%d) do not match. (Subsequent mismatches will not be reported)\n",
3931 info->fontname, sc->name, sc->width, lastwidth );
3932 else
3933 LogError("In GID %d, 'CFF ' advance width (%d) and 'hmtx' width (%d) do not match.\n (Subsequent mismatches will not be reported)\n",
3934 i, sc->width, lastwidth );
3935 info->bad_metrics = true;
3936 check_width_consistency = false;
3938 sc->width = lastwidth;
3939 sc->widthset = true;
3940 if ( info->apply_lsb ) {
3941 if ( sc->lsidebearing!=lsb ) {
3942 trans[4] = lsb-sc->lsidebearing;
3943 SplinePointListTransform(sc->layers[ly_fore].splines,trans,true);
3948 if ( i==0 ) {
3949 LogError( _("Invalid ttf hmtx table (or hhea), numOfLongMetrics is 0\n") );
3950 info->bad_metrics = true;
3953 for ( j=i; j<info->glyph_cnt; ++j ) {
3954 if ( (sc = info->chars[j])!=NULL ) { /* In a ttc file we may skip some */
3955 sc->width = lastwidth;
3956 sc->widthset = true;
3957 if ( info->apply_lsb ) {
3958 lsb = (short) getushort(ttf);
3959 if ( sc->lsidebearing!=lsb ) {
3960 trans[4] = lsb-sc->lsidebearing;
3961 SplinePointListTransform(sc->layers[ly_fore].splines,trans,true);
3968 static void dummywidthsfromstrike(FILE *ttf,struct ttfinfo *info) {
3969 BDFFont *bdf;
3970 int i, cnt;
3971 double scaled_sum;
3972 (void)ttf; /* -Wall */
3973 if ( info->bitmaps==NULL )
3974 return;
3975 #if 0
3976 for ( bdf=info->bitmaps; bdf->next!=NULL; bdf=bdf->next );
3977 for ( i=0; i<bdf->glyphcnt; ++i ) if ( bdf->glyphs[i]!=NULL ) {
3978 bdf->glyphs[i]->sc->width = info->emsize*bdf->glyphs[i]->width/bdf->pixelsize;
3979 bdf->glyphs[i]->sc->widthset = true;
3981 #else
3982 for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
3983 cnt = 0; scaled_sum = 0;
3984 for ( bdf=info->bitmaps; bdf->next!=NULL; bdf=bdf->next ) {
3985 if ( i<bdf->glyphcnt && bdf->glyphs[i]!=NULL ) {
3986 scaled_sum += ((double) (info->emsize*bdf->glyphs[i]->width))/bdf->pixelsize;
3987 ++cnt;
3990 if ( cnt!=0 ) {
3991 info->chars[i]->width = scaled_sum/cnt;
3992 info->chars[i]->widthset = true;
3995 #endif
3998 static void readttfvwidths(FILE *ttf,struct ttfinfo *info) {
3999 int i,j;
4000 int lastvwidth = info->emsize, vwidth_cnt, tsb/*, cnt=0*/;
4001 /* int32 voff=0; */
4003 fseek(ttf,info->vhea_start+4+4,SEEK_SET); /* skip over the version number & typo right/left */
4004 info->pfminfo.vlinegap = getushort(ttf);
4005 info->pfminfo.vheadset = true;
4007 for ( i=0; i<12; ++i )
4008 getushort(ttf);
4009 vwidth_cnt = getushort(ttf);
4011 fseek(ttf,info->vmetrics_start,SEEK_SET);
4012 for ( i=0; i<vwidth_cnt && i<info->glyph_cnt; ++i ) {
4013 lastvwidth = getushort(ttf);
4014 tsb = getushort(ttf);
4015 if ( info->chars[i]!=NULL ) { /* can happen in ttc files */
4016 info->chars[i]->vwidth = lastvwidth;
4017 info->chars[i]->tsb = tsb;
4020 if ( i==0 ) {
4021 LogError( _("Invalid ttf vmtx table (or vhea), numOfLongVerMetrics is 0\n") );
4022 info->bad_metrics = true;
4025 for ( j=i; j<info->glyph_cnt; ++j ) {
4026 if ( info->chars[j]!=NULL ) /* In a ttc file we may skip some */
4027 info->chars[j]->vwidth = lastvwidth;
4032 static int modenc(int enc,int modtype) {
4033 (void)modtype; /* for -Wall */
4034 return( enc );
4037 static int badencoding(struct ttfinfo *info) {
4038 if ( !info->bad_cmap ) {
4039 LogError("Bad encoding information in 'cmap' table.");
4040 info->bad_cmap = true;
4042 return( -1 );
4045 static int umodenc(int enc,int modtype, struct ttfinfo *info) {
4046 if ( modtype==-1 )
4047 return( -1 );
4048 if ( modtype<=1 /* Unicode */ ) {
4049 /* No conversion needed, already unicode */;
4050 #ifdef FROM_CJK_ICONV
4051 } else if ( modtype==2 /* SJIS */ ) {
4052 if ( enc<=127 ) {
4053 /* Latin */
4054 if ( enc=='\\' ) enc = 0xa5; /* Yen */
4055 } else if ( enc>=161 && enc<=223 ) {
4056 /* Katakana */
4057 enc = unicode_from_jis201[enc];
4058 } else if ( enc<255 ) {
4059 /* This is erroneous as I understand SJIS */
4060 enc = badencoding(info);
4061 } else {
4062 int ch1 = enc>>8, ch2 = enc&0xff;
4063 if ( ch1 >= 129 && ch1<= 159 )
4064 ch1 -= 112;
4065 else
4066 ch1 -= 176;
4067 ch1 <<= 1;
4068 if ( ch2>=159 )
4069 ch2-= 126;
4070 else if ( ch2>127 ) {
4071 --ch1;
4072 ch2 -= 32;
4073 } else {
4074 --ch1;
4075 ch2 -= 31;
4077 if ( ch1<0x21 || ch2<0x21 || ch1>0x7f || ch2>0x7f )
4078 enc = badencoding(info);
4079 else
4080 enc = unicode_from_jis208[(ch1-0x21)*94+(ch2-0x21)];
4082 } else if ( modtype==3 /* GB2312 offset by 0x8080, parse just like wansung */ ) {
4083 if ( enc>0xa1a1 ) {
4084 enc -= 0xa1a1;
4085 enc = (enc>>8)*94 + (enc&0xff);
4086 enc = unicode_from_gb2312[enc];
4087 if ( enc==0 ) enc = -1;
4088 } else if ( enc>0x100 )
4089 enc = badencoding(info);
4090 } else if ( modtype==4 /* BIG5 */ ) { /* old ms docs say big5 is modtype==3, but new ones say 4 */
4091 if ( enc>0x8100 )
4092 enc = unicode_from_big5hkscs[enc-0x8100];
4093 else if ( enc>0x100 )
4094 enc = badencoding(info);
4095 } else if ( modtype==5 /* Wansung == KSC 5601-1987, I hope */ ) {
4096 if ( enc>0xa1a1 ) {
4097 enc -= 0xa1a1;
4098 enc = (enc>>8)*94 + (enc&0xff);
4099 enc = unicode_from_ksc5601[enc];
4100 if ( enc==0 ) enc = -1;
4101 } else if ( enc>0x100 )
4102 enc = badencoding(info);
4103 } else if ( modtype==6 /* Johab */ ) {
4104 if ( enc>0x8400 )
4105 enc = unicode_from_johab[enc-0x8400];
4106 else if ( enc>0x100 )
4107 enc = badencoding(info);
4108 #else
4109 } else {
4110 enc = badencoding(info);
4111 #endif
4113 if ( enc==0 )
4114 enc = -1;
4115 return( enc );
4118 struct cmap_encs {
4119 int platform;
4120 int specific;
4121 int offset;
4122 int lang;
4123 int format;
4124 Encoding *enc;
4127 static int SubtableIsntSupported(FILE *ttf,uint32 offset,struct cmap_encs *cmap_enc, struct ttfinfo *info) {
4128 uint32 here = ftell(ttf);
4129 int format, len, ret=false;
4131 fseek(ttf,offset,SEEK_SET);
4133 cmap_enc->format = format = getushort(ttf);
4134 if ( format<0 || (format&1) || format>12 ) {
4135 LogError( _("Encoding subtable for platform=%d, specific=%d has an unsupported format %d.\n"),
4136 cmap_enc->platform, cmap_enc->specific, format );
4137 info->bad_cmap = true;
4138 ret = true;
4141 if ( format!=12 && format!=10 && format!=8 ) {
4142 len = getushort(ttf);
4143 cmap_enc->lang = getushort(ttf);
4144 } else {
4145 /* padding */ getushort(ttf);
4146 len = getlong(ttf);
4147 cmap_enc->lang = getlong(ttf);
4149 if ( len==0 ) {
4150 LogError( _("Encoding subtable for platform=%d, specific=%d has a 0 length subtable.\n"),
4151 cmap_enc->platform, cmap_enc->specific );
4152 info->bad_cmap = true;
4153 ret = true;
4155 fseek(ttf,here,SEEK_SET);
4156 return( ret );
4159 static int SubtableMustBe14(FILE *ttf,uint32 offset,struct ttfinfo *info) {
4160 uint32 here = ftell(ttf);
4161 int format, ret=true;
4163 fseek(ttf,offset,SEEK_SET);
4165 format = getushort(ttf);
4166 if ( format!=14 ) {
4167 LogError( _("Encoding subtable for platform=%d, specific=%d (which must be 14)\nhas an unsupported format %d.\n"),
4168 0, 5, format );
4169 info->bad_cmap = true;
4170 ret = false;
4172 fseek(ttf,here,SEEK_SET);
4173 return( ret );
4176 static void ApplyVariationSequenceSubtable(FILE *ttf,uint32 vs_map,
4177 struct ttfinfo *info,int justinuse) {
4178 int sub_table_len, vs_cnt, i, j, rcnt, gid;
4179 struct vs_data { int vs; uint32 def, non_def; } *vs_data;
4180 SplineChar *sc;
4182 fseek(ttf,vs_map,SEEK_SET);
4183 /* We/ve already checked the format is 14 */ getushort(ttf);
4184 sub_table_len = getlong(ttf);
4185 vs_cnt = getlong(ttf);
4186 vs_data = galloc(vs_cnt*sizeof(struct vs_data));
4187 for ( i=0; i<vs_cnt; ++i ) {
4188 vs_data[i].vs = get3byte(ttf);
4189 vs_data[i].def = getlong(ttf);
4190 vs_data[i].non_def = getlong(ttf);
4193 for ( i=0; i<vs_cnt; ++i ) {
4194 if ( vs_data[i].def!=0 && justinuse==git_normal ) {
4195 fseek(ttf,vs_map+vs_data[i].def,SEEK_SET);
4196 rcnt = getlong(ttf);
4197 for ( j=0; j<rcnt; ++j ) {
4198 int start_uni = get3byte(ttf);
4199 int cnt = getc(ttf);
4200 int uni;
4201 for ( uni=start_uni; uni<=start_uni+cnt; ++uni ) {
4202 SplineChar *sc=NULL;
4203 struct altuni *altuni;
4204 for ( gid = 0; gid<info->glyph_cnt; ++gid ) {
4205 if ( (sc = info->chars[gid])!=NULL ) {
4206 if ( sc->unicodeenc==uni )
4207 break;
4208 for ( altuni = sc->altuni; altuni!=NULL; altuni=altuni->next )
4209 if ( altuni->unienc==uni && altuni->vs == -1 && altuni->fid==0 )
4210 break;
4211 if ( altuni!=NULL )
4212 break;
4215 if ( gid==info->glyph_cnt ) {
4216 LogError( _("No glyph with unicode U+%05x in font\n"),
4217 uni );
4218 info->bad_cmap = true;
4219 } else {
4220 altuni = chunkalloc(sizeof(struct altuni));
4221 altuni->unienc = uni;
4222 altuni->vs = vs_data[i].vs;
4223 altuni->fid = 0;
4224 altuni->next = sc->altuni;
4225 sc->altuni = altuni;
4230 if ( vs_data[i].non_def!=0 ) {
4231 fseek(ttf,vs_map+vs_data[i].non_def,SEEK_SET);
4232 rcnt = getlong(ttf);
4233 for ( j=0; j<rcnt; ++j ) {
4234 int uni = get3byte(ttf);
4235 int curgid = getushort(ttf);
4236 if ( justinuse==git_justinuse ) {
4237 if ( curgid<info->glyph_cnt && curgid>=0)
4238 info->inuse[curgid] = 1;
4239 } else if ( justinuse==git_justinuse ) {
4240 if ( curgid<info->glyph_cnt && curgid>=0 &&
4241 (sc=info->chars[curgid])!=NULL && sc->name==NULL ) {
4242 char buffer[32];
4243 sprintf(buffer, "u%04X.vs%04X", uni, vs_data[i].vs );
4244 sc->name = copy(buffer);
4246 } else {
4247 if ( curgid>=info->glyph_cnt || curgid<0 ||
4248 info->chars[curgid]==NULL ) {
4249 LogError( _("GID out of range (%d) in format 14 'cmap' subtable\n"),
4250 curgid );
4251 info->bad_cmap = true;
4252 } else {
4253 SplineChar *sc = info->chars[curgid];
4254 struct altuni *altuni = chunkalloc(sizeof(struct altuni));
4255 altuni->unienc = uni;
4256 altuni->vs = vs_data[i].vs;
4257 altuni->fid = 0;
4258 altuni->next = sc->altuni;
4259 sc->altuni = altuni;
4265 free(vs_data);
4268 static enum uni_interp amscheck(struct ttfinfo *info, EncMap *map) {
4269 int cnt = 0;
4270 /* Try to guess if the font uses the AMS math PUA assignments */
4272 if ( map==NULL )
4273 return( ui_none );
4275 if ( 0xe668<map->enccount && map->map[0xe668]!=-1 &&
4276 info->chars[map->map[0xe668]]->unicodeenc=='b' )
4277 ++cnt;
4278 if ( 0xe3c8<map->enccount && map->map[0xe626]!=-1 &&
4279 info->chars[map->map[0xe626]]->unicodeenc==0xe626 )
4280 ++cnt;
4281 if ( 0xe3c8<map->enccount && map->map[0xe3c8]!=-1 &&
4282 info->chars[map->map[0xe3c8]]->unicodeenc==0x29e1 )
4283 ++cnt;
4284 if ( 0x2A7C<map->enccount && map->map[0x2A7C]!=-1 &&
4285 info->chars[map->map[0x2A7C]]->unicodeenc==0xE32A )
4286 ++cnt;
4287 if ( 0x2920<map->enccount && map->map[0x2920]!=-1 &&
4288 info->chars[map->map[0x2920]]->unicodeenc==0xE221 )
4289 ++cnt;
4290 return( cnt>=2 ? ui_ams : ui_none );
4293 static int PickCMap(struct cmap_encs *cmap_encs,int enccnt,int def) {
4294 char buffer[500];
4295 char **choices, *encname;
4296 int i, ret;
4297 static char *macscripts[]= { N_("Roman"), N_("Japanese"), N_("Traditional Chinese"), N_("Korean"),
4298 N_("Arabic"), N_("Hebrew"), N_("Greek"),
4299 /* GT: Don't ask me what RSymbol means, I don't know either. It's in apple's */
4300 /* GT: docs though */
4301 N_("Cyrillic"), N_("RSymbol"), N_("Devanagari"),
4302 /* 10*/ N_("Gurmukhi"), N_("Gujarati"), NULL, NULL, NULL,
4303 NULL, NULL, NULL, NULL, NULL,
4304 /* 20*/ NULL, N_("Thai"), NULL, NULL, NULL, N_("Simplified Chinese"),
4305 NULL, NULL, NULL, N_("Central European"),
4306 /* 30*/ NULL, NULL, NULL };
4308 choices = galloc(enccnt*sizeof(char *));
4309 for ( i=0; i<enccnt; ++i ) {
4310 encname = NULL;
4311 if ( cmap_encs[i].platform==1 && cmap_encs[i].specific<32 ) {
4312 encname = macscripts[cmap_encs[i].specific];
4313 if ( encname!=NULL )
4314 encname = _(encname);
4315 } else if ( cmap_encs[i].platform==0 ) {
4316 switch ( cmap_encs[i].specific ) {
4317 case 0:
4318 encname = N_("Unicode 1.0");
4319 break;
4320 case 1:
4321 encname = N_("Unicode 1.1");
4322 break;
4323 case 2:
4324 encname = N_("ISO 10646:1993");
4325 break;
4326 case 3:
4327 encname = N_("Unicode 2.0+, BMP only");
4328 break;
4329 case 4:
4330 encname = N_("Unicode 2.0+, all planes");
4331 break;
4333 } else if ( cmap_encs[i].platform==3 && cmap_encs[i].specific==0 )
4334 encname = N_("\"Symbol\"");
4335 if ( encname==NULL )
4336 encname = cmap_encs[i].enc->enc_name;
4338 sprintf(buffer,"%d (%s) %d %s %s %s",
4339 cmap_encs[i].platform,
4340 cmap_encs[i].platform==0 ? _("Unicode") :
4341 cmap_encs[i].platform==1 ? _("Apple") :
4342 cmap_encs[i].platform==2 ? _("ISO (Deprecated)") :
4343 cmap_encs[i].platform==3 ? _("MicroSoft") :
4344 cmap_encs[i].platform==4 ? _("Custom") :
4345 cmap_encs[i].platform==7 ? _("FreeType internals") :
4346 _("Unknown"),
4347 cmap_encs[i].specific,
4348 encname,
4349 cmap_encs[i].platform==1 && cmap_encs[i].lang!=0? MacLanguageFromCode(cmap_encs[i].lang-1) : "",
4350 cmap_encs[i].format == 0 ? "Byte encoding table" :
4351 cmap_encs[i].format == 2 ? "High-byte mapping through table" :
4352 cmap_encs[i].format == 4 ? "Segment mapping to delta values" :
4353 cmap_encs[i].format == 6 ? "Trimmed table mapping" :
4354 cmap_encs[i].format == 8 ? "mixed 16-bit and 32-bit coverage" :
4355 cmap_encs[i].format == 10 ? "Trimmed array" :
4356 cmap_encs[i].format == 12 ? "Segmented coverage" :
4357 "Unknown format" );
4358 choices[i] = copy(buffer);
4360 ret = ff_choose(_("Pick a CMap subtable"),(const char **) choices,enccnt,def,
4361 _("Pick a CMap subtable"));
4362 for ( i=0; i<enccnt; ++i )
4363 free(choices[i]);
4364 free(choices);
4365 return( ret );
4368 /* 'cmap' table: readttfcmap */
4369 static void readttfencodings(FILE *ttf,struct ttfinfo *info, int justinuse) {
4370 int i,j, def, unicode_cmap, unicode4_cmap, dcnt, dcmap_cnt, dc;
4371 int nencs, version, usable_encs;
4372 Encoding *enc = &custom;
4373 const int32 *trans=NULL;
4374 enum uni_interp interp = ui_none;
4375 int platform, specific;
4376 int offset, encoff=0;
4377 int format, len;
4378 uint32 vs_map=0;
4379 uint16 table[256];
4380 int segCount;
4381 uint16 *endchars, *startchars, *delta, *rangeOffset, *glyphs;
4382 int index, last;
4383 int mod = 0;
4384 SplineChar *sc;
4385 uint8 *used;
4386 int badencwarned=false;
4387 int glyph_tot;
4388 Encoding *temp;
4389 EncMap *map;
4390 struct cmap_encs *cmap_encs, desired_cmaps[2], *dcmap;
4392 fseek(ttf,info->encoding_start,SEEK_SET);
4393 version = getushort(ttf);
4394 nencs = getushort(ttf);
4395 if ( version!=0 && nencs==0 )
4396 nencs = version; /* Sometimes they are backwards */ /* Or was I just confused early on? */
4397 cmap_encs = galloc(nencs*sizeof(struct cmap_encs));
4398 for ( i=usable_encs=0; i<nencs; ++i ) {
4399 cmap_encs[usable_encs].platform = getushort(ttf);
4400 cmap_encs[usable_encs].specific = getushort(ttf);
4401 cmap_encs[usable_encs].offset = getlong(ttf);
4402 if ( cmap_encs[usable_encs].platform == 0 && cmap_encs[usable_encs].specific == 5 ) {
4403 /* This isn't a true encoding. */
4404 /* It's an optional set of encoding modifications (sort of) */
4405 /* applied to a format 4/10 encoding (unicode BMP/Full) */
4406 if ( SubtableMustBe14(ttf,info->encoding_start+cmap_encs[usable_encs].offset,info) )
4407 vs_map = info->encoding_start+cmap_encs[usable_encs].offset;
4408 continue;
4410 temp = enc_from_platspec(cmap_encs[usable_encs].platform,cmap_encs[usable_encs].specific);
4411 if ( temp==NULL ) /* iconv doesn't support this. Some sun iconvs seem limited */
4412 temp = FindOrMakeEncoding("Custom");
4413 cmap_encs[usable_encs].enc = temp;
4414 if ( SubtableIsntSupported(ttf,info->encoding_start+cmap_encs[usable_encs].offset,
4415 &cmap_encs[usable_encs],info))
4416 continue;
4417 ++usable_encs;
4419 if ( usable_encs==0 ) {
4420 LogError( _("Could not find any valid encoding tables" ));
4421 free(cmap_encs);
4422 return;
4424 def = -1;
4425 enc = &custom;
4426 unicode_cmap = unicode4_cmap = -1;
4427 for ( i=0; i<usable_encs; ++i ) {
4428 temp = cmap_encs[i].enc;
4429 platform = cmap_encs[i].platform;
4430 specific = cmap_encs[i].specific;
4431 offset = cmap_encs[i].offset;
4433 if ( (platform==3 && specific==10) || (platform==0 && specific==4) ) { /* MS Unicode 4 byte */
4434 enc = temp;
4435 def = i;
4436 unicode4_cmap = i;
4437 } else if ( !enc->is_unicodefull && (!prefer_cjk_encodings ||
4438 (!enc->is_japanese && !enc->is_korean && !enc->is_tradchinese &&
4439 !enc->is_simplechinese)) &&
4440 (( platform==3 && specific==1 ) || /* MS Unicode */
4441 /* Well I should only deal with apple unicode specific==0 (default) and 3 (U2.0 semantics) */
4442 /* but apple ships dfonts with specific==1 (Unicode 1.1 semantics) */
4443 /* which is stupid of them */
4444 ( platform==0 /*&& (specific==0 || specific==3)*/ ))) { /* Apple Unicode */
4445 enc = temp;
4446 def = i;
4447 } else if ( platform==3 && specific==0 && enc->is_custom ) {
4448 /* Only select symbol if we don't have something better */
4449 enc = temp;
4450 def = i;
4451 /* Now I had assumed this would be a 1 byte encoding, but it turns*/
4452 /* out to map into the unicode private use area at U+f000-U+F0FF */
4453 /* so it's a 2 byte enc */
4454 /* Mac platform specific encodings are script numbers. 0=>roman, 1=>jap, 2=>big5, 3=>korean, 4=>arab, 5=>hebrew, 6=>greek, 7=>cyrillic, ... 25=>simplified chinese */
4455 } else if ( platform==1 && specific==0 && enc->is_custom ) {
4456 enc = temp;
4457 def = i;
4458 } else if ( platform==1 && (specific==2 ||specific==1||specific==3||specific==25) &&
4459 !enc->is_unicodefull &&
4460 (prefer_cjk_encodings || !enc->is_unicodebmp) ) {
4461 enc = temp;
4462 def = i;
4463 } else if ( platform==3 && (specific>=2 && specific<=6 ) &&
4464 !enc->is_unicodefull &&
4465 (prefer_cjk_encodings || !enc->is_unicodebmp) ) {
4466 /* Old ms docs say that specific==3 => big 5, new docs say specific==4 => big5 */
4467 /* Ain't that jus' great? */
4468 enc = temp;
4469 def = i;
4471 if ( (platform==3 && specific==1) ||
4472 (platform==0 && specific==3))
4473 unicode_cmap = i;
4476 if ( justinuse==git_justinuse || !ask_user_for_cmap || (i = PickCMap(cmap_encs,usable_encs,def))==-1 )
4477 i = def;
4479 if ( i==-1 ) {
4480 LogError( _("Could not find a usable encoding table" ));
4481 free(cmap_encs);
4482 return;
4485 info->platform = cmap_encs[i].platform;
4486 info->specific = cmap_encs[i].specific;
4488 desired_cmaps[0] = cmap_encs[i]; dcnt = 1;
4489 if ( unicode4_cmap!=-1 ) {
4490 if ( i!=unicode4_cmap ) {
4491 desired_cmaps[1] = cmap_encs[unicode4_cmap];
4492 ++dcnt;
4494 } else if ( unicode_cmap!=-1 ) {
4495 if ( i!=unicode_cmap ) {
4496 desired_cmaps[1] = cmap_encs[unicode_cmap];
4497 ++dcnt;
4499 } else {
4500 if ( i!=def && def!=-1 ) {
4501 desired_cmaps[1] = cmap_encs[def];
4502 ++dcnt;
4506 map = NULL;
4507 if ( justinuse==git_justinuse ) {
4508 dcmap_cnt = usable_encs;
4509 dcmap = cmap_encs;
4510 } else {
4511 dcmap_cnt = dcnt;
4512 dcmap = desired_cmaps;
4514 for ( dc=dcmap_cnt-1; dc>=0; --dc ) {
4515 /* if justinuse then look at all cmaps and tick the glyphs they use */
4516 /* otherwise dcmap_cnt will be either 1 or 2. If 1 then this subtable */
4517 /* contains both the encoding and the source for unicode encodings */
4518 /* if dcmap_cnt==2 then when dc==0 we are setting up the encoding */
4519 /* and when dc==1 we are setting up the unicode code points */
4520 int dounicode = (dc==dcmap_cnt-1);
4521 enc = dcmap[dc].enc;
4522 encoff = dcmap[dc].offset;
4524 if ( dc==0 && justinuse==git_normal ) {
4525 interp = interp_from_encoding(enc,ui_none);
4526 mod = 0;
4527 if ( dcmap[dc].platform==3 && (dcmap[dc].specific>=2 && dcmap[dc].specific<=6 ))
4528 mod = dcmap[dc].specific;
4529 else if ( dcmap[dc].platform==1 && (dcmap[dc].specific==2 ||dcmap[dc].specific==1||dcmap[dc].specific==3||dcmap[dc].specific==25))
4530 mod = dcmap[dc].specific==1?2:dcmap[dc].specific==2?4:dcmap[dc].specific==3?5:3; /* convert to ms specific */
4531 info->map = map = EncMapNew(enc->char_cnt,info->glyph_cnt,enc);
4532 info->uni_interp = interp;
4535 fseek(ttf,info->encoding_start+encoff,SEEK_SET);
4536 format = getushort(ttf);
4537 if ( format!=12 && format!=10 && format!=8 ) {
4538 len = getushort(ttf);
4539 /* version/language = */ getushort(ttf);
4540 } else {
4541 /* padding */ getushort(ttf);
4542 len = getlong(ttf);
4543 /* language = */ getlong(ttf);
4545 if ( enc->is_unicodebmp && (format==8 || format==10 || format==12))
4546 enc = FindOrMakeEncoding("UnicodeFull");
4548 if ( format==0 ) {
4549 if ( justinuse==git_normal && map!=NULL && map->enccount<256 ) {
4550 map->map = grealloc(map->map,256*sizeof(int));
4551 memset(map->map,-1,(256-map->enccount)*sizeof(int));
4552 map->enccount = map->encmax = 256;
4554 for ( i=0; i<len-6; ++i )
4555 table[i] = getc(ttf);
4556 trans = enc->unicode;
4557 if ( trans==NULL && dcmap[dc].platform==1 )
4558 trans = MacEncToUnicode(dcmap[dc].specific,dcmap[dc].lang-1);
4559 for ( i=0; i<256 && i<len-6; ++i )
4560 if ( justinuse==git_normal ) {
4561 if ( table[i]<info->glyph_cnt && info->chars[table[i]]!=NULL ) {
4562 if ( map!=NULL )
4563 map->map[i] = table[i];
4564 if ( dounicode && trans!=NULL )
4565 info->chars[table[i]]->unicodeenc = trans[i];
4567 } else if ( table[i]<info->glyph_cnt && info->chars[table[i]]!=NULL )
4568 info->inuse[table[i]] = 1;
4569 } else if ( format==4 ) {
4570 segCount = getushort(ttf)/2;
4571 /* searchRange = */ getushort(ttf);
4572 /* entrySelector = */ getushort(ttf);
4573 /* rangeShift = */ getushort(ttf);
4574 endchars = galloc(segCount*sizeof(uint16));
4575 used = gcalloc(65536,sizeof(uint8));
4576 for ( i=0; i<segCount; ++i )
4577 endchars[i] = getushort(ttf);
4578 if ( getushort(ttf)!=0 )
4579 IError("Expected 0 in 'cmap' format 4 subtable");
4580 startchars = galloc(segCount*sizeof(uint16));
4581 for ( i=0; i<segCount; ++i )
4582 startchars[i] = getushort(ttf);
4583 delta = galloc(segCount*sizeof(uint16));
4584 for ( i=0; i<segCount; ++i )
4585 delta[i] = getushort(ttf);
4586 rangeOffset = galloc(segCount*sizeof(uint16));
4587 for ( i=0; i<segCount; ++i )
4588 rangeOffset[i] = getushort(ttf);
4589 len -= 8*sizeof(uint16) +
4590 4*segCount*sizeof(uint16);
4591 /* that's the amount of space left in the subtable and it must */
4592 /* be filled with glyphIDs */
4593 if ( len<0 ) {
4594 IError("This font has an illegal format 4 subtable with too little space for all the segments.\nThis error is not recoverable.\nBye" );
4595 exit(1);
4597 glyphs = galloc(len);
4598 glyph_tot = len/2;
4599 for ( i=0; i<glyph_tot; ++i )
4600 glyphs[i] = getushort(ttf);
4601 for ( i=0; i<segCount; ++i ) {
4602 if ( rangeOffset[i]==0 && startchars[i]==0xffff )
4603 /* Done */;
4604 else if ( rangeOffset[i]==0 ) {
4605 for ( j=startchars[i]; j<=endchars[i]; ++j ) {
4606 if ( justinuse==git_justinuse && (uint16) (j+delta[i])<info->glyph_cnt )
4607 info->inuse[(uint16) (j+delta[i])] = true;
4608 else if ( (uint16) (j+delta[i])>=info->glyph_cnt || info->chars[(uint16) (j+delta[i])]==NULL ) {
4609 LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
4610 (uint16) (j+delta[i]), modenc(j,mod), modenc(j,mod));
4611 info->bad_cmap = true;
4612 } else {
4613 int uenc = umodenc(j,mod,info);
4614 int lenc = modenc(j,mod);
4615 if ( uenc!=-1 && used[uenc] ) {
4616 if ( !badencwarned ) {
4617 LogError( _("Multiple glyphs map to the same unicode encoding U+%04X, only one will be used\n"), uenc );
4618 info->bad_cmap = true;
4619 badencwarned = true;
4621 } else {
4622 if ( uenc!=-1 && dounicode ) used[uenc] = true;
4623 if ( dounicode && info->chars[(uint16) (j+delta[i])]->unicodeenc==-1 )
4624 info->chars[(uint16) (j+delta[i])]->unicodeenc = uenc;
4625 if ( map!=NULL && lenc<map->enccount )
4626 map->map[lenc] = (uint16) (j+delta[i]);
4630 } else if ( rangeOffset[i]!=0xffff ) {
4631 /* Apple says a rangeOffset of 0xffff means no glyph */
4632 /* OpenType doesn't mention this */
4633 for ( j=startchars[i]; j<=endchars[i]; ++j ) {
4634 int temp = (i-segCount+rangeOffset[i]/2) + j-startchars[i];
4635 if ( temp<glyph_tot )
4636 index = glyphs[ temp ];
4637 else {
4638 /* This happened in mingliu.ttc(PMingLiU) */
4639 if ( justinuse==git_normal ) {
4640 LogError( _("Glyph index out of bounds. Was %d, must be less than %d.\n In attempt to associate a glyph with encoding %x in segment %d\n with platform=%d, specific=%d (in 'cmap')\n"),
4641 temp, glyph_tot, j, i, dcmap[dc].platform, dcmap[dc].specific );
4642 info->bad_cmap = true;
4644 index = 0;
4646 if ( index!=0 ) {
4647 index = (unsigned short) (index+delta[i]);
4648 if ( index>=info->glyph_cnt ) {
4649 /* This isn't mentioned either, but in some */
4650 /* MS Chinese fonts (kaiu.ttf) the index */
4651 /* goes out of bounds. and MS's ttf dump */
4652 /* program says it is treated as 0 */
4653 LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
4654 index, modenc(j,mod), modenc(j,mod));
4655 info->bad_cmap = true;
4656 } else if ( justinuse==git_justinuse )
4657 info->inuse[index] = 1;
4658 else if ( info->chars[index]==NULL ) {
4659 LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
4660 index, modenc(j,mod), modenc(j,mod));
4661 info->bad_cmap = true;
4662 } else {
4663 int uenc = umodenc(j,mod,info);
4664 int lenc = modenc(j,mod);
4665 if ( uenc!=-1 && used[uenc] ) {
4666 if ( !badencwarned ) {
4667 LogError( _("Multiple glyphs map to the same unicode encoding U+%04X, only one will be used\n"), uenc );
4668 info->bad_cmap = true;
4669 badencwarned = true;
4671 } else {
4672 if ( uenc!=-1 && dounicode ) used[uenc] = true;
4673 if ( dounicode && info->chars[index]->unicodeenc==-1 )
4674 info->chars[index]->unicodeenc = uenc;
4675 if ( map!=NULL && lenc<map->enccount )
4676 map->map[lenc] = index;
4681 } else {
4682 LogError( _("Use of a range offset of 0xffff to mean a missing glyph in cmap table\n") );
4683 info->bad_cmap = true;
4686 free(glyphs);
4687 free(rangeOffset);
4688 free(delta);
4689 free(startchars);
4690 free(endchars);
4691 free(used);
4692 } else if ( format==6 ) {
4693 /* trimmed array format */
4694 /* Well, the docs say it's for 2byte encodings, but Apple actually*/
4695 /* uses it for 1 byte encodings which don't fit into the require-*/
4696 /* ments for a format 0 sub-table. See Zapfino.dfont */
4697 int first, count;
4698 first = getushort(ttf);
4699 count = getushort(ttf);
4700 trans = enc->unicode;
4701 if ( trans==NULL && dcmap[dc].platform==1 && first+count<=256 )
4702 trans = MacEncToUnicode(dcmap[dc].specific,dcmap[dc].lang-1);
4703 if ( justinuse==git_justinuse )
4704 for ( i=0; i<count; ++i )
4705 info->inuse[getushort(ttf)]= 1;
4706 else {
4707 for ( i=0; i<count; ++i ) {
4708 int gid = getushort(ttf);
4709 if ( dounicode )
4710 info->chars[gid]->unicodeenc = trans!=NULL ? trans[first+1] : first+i;
4711 if ( map!=NULL && first+i < map->enccount )
4712 map->map[first+i] = gid;
4715 } else if ( format==2 ) {
4716 int max_sub_head_key = 0, cnt, max_pos= -1;
4717 struct subhead *subheads;
4719 for ( i=0; i<256; ++i ) {
4720 table[i] = getushort(ttf)/8; /* Sub-header keys */
4721 if ( table[i]>max_sub_head_key ) {
4722 max_sub_head_key = table[i]; /* The entry is a byte pointer, I want a pointer in units of struct subheader */
4723 max_pos = i;
4726 subheads = galloc((max_sub_head_key+1)*sizeof(struct subhead));
4727 for ( i=0; i<=max_sub_head_key; ++i ) {
4728 subheads[i].first = getushort(ttf);
4729 subheads[i].cnt = getushort(ttf);
4730 subheads[i].delta = getushort(ttf);
4731 subheads[i].rangeoff = (getushort(ttf)-
4732 (max_sub_head_key-i)*sizeof(struct subhead)-
4733 sizeof(short))/sizeof(short);
4735 cnt = (len-(ftell(ttf)-(info->encoding_start+encoff)))/sizeof(short);
4736 /* The count is the number of glyph indexes to read. it is the */
4737 /* length of the entire subtable minus that bit we've read so far */
4738 glyphs = galloc(cnt*sizeof(short));
4739 for ( i=0; i<cnt; ++i )
4740 glyphs[i] = getushort(ttf);
4741 last = -1;
4742 for ( i=0; i<256; ++i ) {
4743 if ( table[i]==0 ) {
4744 /* Special case, single byte encoding entry, look it up in */
4745 /* subhead */
4746 /* In the one example I've got of this encoding (wcl-02.ttf) the chars */
4747 /* 0xfd, 0xfe, 0xff are said to exist but there is no mapping */
4748 /* for them. */
4749 if ( i>=max_pos )
4750 index = 0; /* the subhead says there are 256 entries, but in fact there are only 193, so attempting to find these guys should give an error */
4751 else if ( i<subheads[0].first || i>=subheads[0].first+subheads[0].cnt ||
4752 subheads[0].rangeoff+(i-subheads[0].first)>=cnt )
4753 index = 0;
4754 else if ( (index = glyphs[subheads[0].rangeoff+(i-subheads[0].first)])!= 0 )
4755 index = (uint32) (index+subheads[0].delta);
4756 /* I assume the single byte codes are just ascii or latin1*/
4757 if ( index!=0 && index<info->glyph_cnt ) {
4758 if ( justinuse==git_justinuse )
4759 info->inuse[index] = 1;
4760 else if ( info->chars[index]==NULL )
4761 /* Do Nothing */;
4762 else {
4763 int lenc = modenc(i,mod);
4764 if ( dounicode && info->chars[index]->unicodeenc==-1 )
4765 info->chars[index]->unicodeenc = i;
4766 if ( map!=NULL && lenc<map->enccount )
4767 map->map[lenc] = index;
4770 } else {
4771 int k = table[i];
4772 for ( j=0; j<subheads[k].cnt; ++j ) {
4773 int enc, lenc;
4774 if ( subheads[k].rangeoff+j>=cnt )
4775 index = 0;
4776 else if ( (index = glyphs[subheads[k].rangeoff+j])!= 0 )
4777 index = (uint16) (index+subheads[k].delta);
4778 if ( index!=0 && index<info->glyph_cnt ) {
4779 enc = (i<<8)|(j+subheads[k].first);
4780 lenc = modenc(enc,mod);
4781 if ( justinuse==git_justinuse )
4782 info->inuse[index] = 1;
4783 else if ( info->chars[index]==NULL )
4784 /* Do Nothing */;
4785 else {
4786 if ( dounicode && info->chars[index]->unicodeenc==-1 )
4787 info->chars[index]->unicodeenc = umodenc(enc,mod,info);
4788 if ( map!=NULL && lenc<map->enccount )
4789 map->map[lenc] = index;
4793 /*if ( last==-1 ) last = i;*/
4796 free(subheads);
4797 free(glyphs);
4798 } else if ( format==8 ) {
4799 uint32 ngroups, start, end, startglyph;
4800 if ( !enc->is_unicodefull ) {
4801 IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
4802 enc = FindOrMakeEncoding("UnicodeFull");
4804 /* I'm now assuming unicode surrogate encoding, so I just ignore */
4805 /* the is32 table (it will be set for the surrogates and not for */
4806 /* anything else */
4807 fseek(ttf,8192,SEEK_CUR);
4808 ngroups = getlong(ttf);
4809 for ( j=0; j<(int)ngroups; ++j ) {
4810 start = getlong(ttf);
4811 end = getlong(ttf);
4812 startglyph = getlong(ttf);
4813 if ( justinuse==git_justinuse )
4814 for ( i=start; i<=(int)end; ++i )
4815 info->inuse[startglyph+i-start]= 1;
4816 else
4817 for ( i=start; i<=(int)end; ++i ) {
4818 int uenc = ((i>>16)-0xd800)*0x400 + (i&0xffff)-0xdc00 + 0x10000;
4819 sc = info->chars[startglyph+i-start];
4820 if ( dounicode && sc->unicodeenc==-1 )
4821 sc->unicodeenc = uenc;
4822 if ( map!=NULL && sc->unicodeenc < map->enccount )
4823 map->map[uenc] = startglyph+i-start;
4826 } else if ( format==10 ) {
4827 /* same as format 6, except for 4byte chars */
4828 int first, count;
4829 if ( !enc->is_unicodefull ) {
4830 IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
4831 enc = FindOrMakeEncoding("UnicodeFull");
4833 first = getlong(ttf);
4834 count = getlong(ttf);
4835 if ( justinuse==git_justinuse )
4836 for ( i=0; i<count; ++i )
4837 info->inuse[getushort(ttf)]= 1;
4838 else
4839 for ( i=0; i<count; ++i ) {
4840 int gid = getushort(ttf);
4841 if ( dounicode )
4842 info->chars[gid]->unicodeenc = first+i;
4843 if ( map!=NULL && first+i < map->enccount )
4844 map->map[first+i] = gid;
4846 } else if ( format==12 ) {
4847 uint32 ngroups, start, end, startglyph;
4848 if ( !enc->is_unicodefull ) {
4849 IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
4850 enc = FindOrMakeEncoding("UnicodeFull");
4852 ngroups = getlong(ttf);
4853 for ( j=0; j<(int)ngroups; ++j ) {
4854 start = getlong(ttf);
4855 end = getlong(ttf);
4856 startglyph = getlong(ttf);
4857 if ( justinuse==git_justinuse ) {
4858 for ( i=start; i<=(int)end; ++i )
4859 if ( startglyph+i-start < (unsigned)info->glyph_cnt )
4860 info->inuse[startglyph+i-start]= 1;
4861 else
4862 break;
4863 } else
4864 for ( i=start; i<=(int)end; ++i ) {
4865 if ( startglyph+i-start >= (unsigned)info->glyph_cnt ||
4866 info->chars[startglyph+i-start]==NULL ) {
4867 LogError( _("Bad font: Encoding data out of range.\n") );
4868 info->bad_cmap = true;
4869 break;
4870 } else {
4871 if ( dounicode )
4872 info->chars[startglyph+i-start]->unicodeenc = i;
4873 if ( map!=NULL && i < map->enccount && i>=0)
4874 map->map[i] = startglyph+i-start;
4880 free(cmap_encs);
4881 if ( info->chars!=NULL )
4882 for ( i=0; i<info->glyph_cnt; ++i )
4883 if ( info->chars[i]!=NULL && info->chars[i]->unicodeenc==0xffff )
4884 info->chars[i]->unicodeenc = -1;
4885 info->vs_start = vs_map;
4886 if ( vs_map!=0 )
4887 ApplyVariationSequenceSubtable(ttf,vs_map,info,justinuse);
4888 if ( justinuse==git_normal ) {
4889 if ( interp==ui_none )
4890 info->uni_interp = amscheck(info,map);
4891 map->enc = enc; /* This can be changed from the initial value */
4893 info->map = map;
4896 static void readttfos2metrics(FILE *ttf,struct ttfinfo *info) {
4897 int i, sel;
4899 fseek(ttf,info->os2_start,SEEK_SET);
4900 info->os2_version = getushort(ttf);
4901 #ifdef LUA_FF_LIB
4902 info->pfminfo.avgwidth = getushort(ttf);
4903 #else
4904 /* avgwidth */ getushort(ttf);
4905 #endif
4906 info->pfminfo.weight = getushort(ttf);
4907 info->pfminfo.width = getushort(ttf);
4908 info->pfminfo.fstype = getushort(ttf);
4909 info->pfminfo.os2_subxsize = getushort(ttf);
4910 info->pfminfo.os2_subysize = getushort(ttf);
4911 info->pfminfo.os2_subxoff = getushort(ttf);
4912 info->pfminfo.os2_subyoff = getushort(ttf);
4913 info->pfminfo.os2_supxsize = getushort(ttf);
4914 info->pfminfo.os2_supysize = getushort(ttf);
4915 info->pfminfo.os2_supxoff = getushort(ttf);
4916 info->pfminfo.os2_supyoff = getushort(ttf);
4917 info->pfminfo.os2_strikeysize = getushort(ttf);
4918 info->pfminfo.os2_strikeypos = getushort(ttf);
4919 info->pfminfo.os2_family_class = getushort(ttf);
4920 for ( i=0; i<10; ++i )
4921 info->pfminfo.panose[i] = getc(ttf);
4922 info->pfminfo.pfmfamily = info->pfminfo.panose[0]==2 ? 0x11 : /* might be 0x21 */ /* Text & Display maps to either serif 0x11 or sans 0x21 or monospace 0x31 */
4923 info->pfminfo.panose[0]==3 ? 0x41 : /* Script */
4924 info->pfminfo.panose[0]==4 ? 0x51 : /* Decorative */
4925 0x51; /* And pictorial doesn't fit into pfm */
4926 info->pfminfo.unicoderanges[0] = getlong(ttf);
4927 info->pfminfo.unicoderanges[1] = getlong(ttf);
4928 info->pfminfo.unicoderanges[2] = getlong(ttf);
4929 info->pfminfo.unicoderanges[3] = getlong(ttf);
4930 info->pfminfo.hasunicoderanges = true;
4931 info->pfminfo.os2_vendor[0] = getc(ttf);
4932 info->pfminfo.os2_vendor[1] = getc(ttf);
4933 info->pfminfo.os2_vendor[2] = getc(ttf);
4934 info->pfminfo.os2_vendor[3] = getc(ttf);
4935 sel = getushort(ttf);
4936 if ( info->os2_version>=4 ) {
4937 info->use_typo_metrics = (sel&128)?1:0;
4938 info->weight_width_slope_only = (sel&256)?1:0;
4940 #ifdef LUA_FF_LIB
4941 info->pfminfo.firstchar = getushort(ttf);
4942 info->pfminfo.lastchar = getushort(ttf);
4943 #else
4944 /* firstchar */ getushort(ttf);
4945 /* lastchar */ getushort(ttf);
4946 #endif
4947 info->pfminfo.os2_typoascent = getushort(ttf);
4948 info->pfminfo.os2_typodescent = (short) getushort(ttf);
4949 if ( info->pfminfo.os2_typoascent-info->pfminfo.os2_typodescent == info->emsize ) {
4950 info->ascent = info->pfminfo.os2_typoascent;
4951 info->descent = -info->pfminfo.os2_typodescent;
4953 info->pfminfo.os2_typolinegap = getushort(ttf);
4954 info->pfminfo.os2_winascent = getushort(ttf);
4955 info->pfminfo.os2_windescent = getushort(ttf);
4956 info->pfminfo.winascent_add = info->pfminfo.windescent_add = false;
4957 info->pfminfo.typoascent_add = info->pfminfo.typodescent_add = false;
4958 info->pfminfo.pfmset = true;
4959 info->pfminfo.panose_set = true;
4960 info->pfminfo.subsuper_set = true;
4961 if ( info->os2_version>=1 ) {
4962 info->pfminfo.codepages[0] = getlong(ttf);
4963 info->pfminfo.codepages[1] = getlong(ttf);
4964 info->pfminfo.hascodepages = true;
4966 #ifdef LUA_FF_LIB
4967 if ( info->os2_version>=3 ) { /* TH just in case */
4968 info->pfminfo.os2_xheight = getushort(ttf); /* four new fields */
4969 info->pfminfo.os2_capheight = getushort(ttf);
4970 info->pfminfo.os2_defaultchar = getushort(ttf);
4971 info->pfminfo.os2_breakchar = getushort(ttf);
4973 #endif
4974 if ( info->os2_version==0 ) {
4975 LogError("Windows will reject fonts with an OS/2 version number of 0\n");
4976 info->bad_os2_version = true;
4977 } else if ( info->os2_version==1 && info->cff_start!=0 ) {
4978 LogError("Windows will reject otf (cff) fonts with an OS/2 version number of 1\n");
4979 info->bad_os2_version = true;
4983 #if 0
4984 static int cmapEncFromName(struct ttfinfo *info,const char *nm, int glyphid) {
4985 int uni;
4986 int i;
4988 if ( info->map!=NULL )
4989 uni = EncFromName(nm,info->uni_interp,info->map->enc);
4990 else
4991 uni = EncFromName(nm,ui_none,&custom);
4992 if ( uni==-1 )
4993 return( -1 );
4995 for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
4996 if ( info->chars[i]->unicodeenc==uni ) {
4997 if ( info->complainedmultname )
4998 /* Don't do it again */;
4999 else if ( info->chars[i]->name!=NULL && strcmp(info->chars[i]->name,nm)==0 )
5000 LogError( _("Warning: Glyph %d has the same name (%s) as Glyph %d\n"),
5001 i, nm, glyphid );
5002 else
5003 LogError( _("Warning: Glyph %d is named %s which should mean it is mapped to\n Unicode U+%04X, but Glyph %d already has that encoding.\n"),
5004 glyphid, nm, uni, i);
5005 info->complainedmultname = true;
5006 return( -1 );
5009 return( uni );
5011 #endif
5013 static void readttfpostnames(FILE *ttf,struct ttfinfo *info) {
5014 int i,j;
5015 int format, len, gc, gcbig, val;
5016 const char *name;
5017 char buffer[30];
5018 uint16 *indexes;
5019 int notdefwarned = false;
5020 int anynames = false;
5022 ff_progress_change_line2(_("Reading Names"));
5024 /* Give ourselves an xuid, just in case they want to convert to PostScript*/
5025 /* (even type42) */
5026 if ( xuid!=NULL && info->fd==NULL && info->xuid==NULL ) {
5027 info->xuid = galloc(strlen(xuid)+20);
5028 sprintf(info->xuid,"[%s %d]", xuid, (rand()&0xffffff));
5031 if ( info->postscript_start!=0 ) {
5032 fseek(ttf,info->postscript_start,SEEK_SET);
5033 format = getlong(ttf);
5034 info->italicAngle = getfixed(ttf);
5035 info->upos = (short) getushort(ttf);
5036 info->uwidth = (short) getushort(ttf);
5037 info->upos += info->uwidth/2; /* 'post' defn of this field is different from FontInfo defn and I didn't notice */
5038 /* fixedpitch = */ getlong(ttf);
5039 /* mem1 = */ getlong(ttf);
5040 /* mem2 = */ getlong(ttf);
5041 /* mem3 = */ getlong(ttf);
5042 /* mem4 = */ getlong(ttf);
5043 if ( format==0x00020000 ) {
5044 gc = getushort(ttf);
5045 indexes = gcalloc(65536,sizeof(uint16));
5046 /* the index table is backwards from the way I want to use it */
5047 gcbig = 0;
5048 for ( i=0; i<gc; ++i ) {
5049 indexes[val = getushort(ttf)] = i;
5050 if ( val>=258 ) ++gcbig;
5053 /* if we are only loading bitmaps, we can get holes in our data */
5054 for ( i=0; i<258; ++i ) if ( indexes[i]!=0 || i==0 ) if ( indexes[i]<info->glyph_cnt && info->chars[indexes[i]]!=NULL ) {
5055 info->chars[indexes[i]]->name = copy(ttfstandardnames[i]);
5056 #if 0 /* Too many fonts have badly named glyphs */
5057 if ( info->chars[indexes[i]]->unicodeenc==-1 )
5058 info->chars[indexes[i]]->unicodeenc = cmapEncFromName(info,ttfstandardnames[i],indexes[i]);
5059 #endif
5061 gcbig += 258;
5062 for ( i=258; i<gcbig; ++i ) {
5063 char *nm;
5064 len = getc(ttf);
5065 if ( len<0 ) /* Don't crash on EOF */
5066 break;
5067 nm = galloc(len+1);
5068 for ( j=0; j<len; ++j )
5069 nm[j] = getc(ttf);
5070 nm[j] = '\0';
5071 if ( indexes[i]<info->glyph_cnt && info->chars[indexes[i]]!=NULL ) {
5072 if (info->chars[indexes[i]]->name)
5073 free( info->chars[indexes[i]]->name );
5074 info->chars[indexes[i]]->name = nm;
5075 #if 0 /* Too many fonts have badly named glyphs */
5076 if ( info->chars[indexes[i]]->unicodeenc==-1 )
5077 info->chars[indexes[i]]->unicodeenc = cmapEncFromName(info,nm,indexes[i]);
5078 #endif
5081 free(indexes);
5082 anynames = true;
5086 if ( info->fd!=NULL && info->fd->chars!=NULL) {
5087 EncMap *map = NULL;
5088 struct pschars *chars = info->fd->chars;
5089 if ( info->map==NULL )
5090 info->map = map = EncMapNew(65536,65536,FindOrMakeEncoding("UnicodeBmp"));
5091 /* In type42 fonts the names are stored in a postscript /CharStrings dictionary */
5092 for ( i=0; i<chars->next; ++i ) {
5093 int gid = (intpt) (chars->values[i]);
5094 if ( gid>=0 && gid<info->glyph_cnt && chars->keys[i]!=NULL ) {
5095 free(info->chars[gid]->name);
5096 info->chars[gid]->name = chars->keys[i];
5097 info->chars[gid]->unicodeenc = UniFromName(chars->keys[i],info->uni_interp,info->map->enc);
5098 if ( map!=NULL && info->chars[gid]->unicodeenc!=-1 &&
5099 info->chars[gid]->unicodeenc<map->enccount)
5100 map->map[ info->chars[gid]->unicodeenc ] = gid;
5101 chars->keys[i] = NULL;
5102 chars->values[i] = NULL;
5103 } else
5104 chars->values[i] = NULL;
5108 for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
5109 /* info->chars[i] can be null in some TTC files */
5110 if ( i!=0 && info->chars[i]->name!=NULL &&
5111 strcmp(info->chars[i]->name,".notdef")==0 ) {
5112 /* for some reason MS puts out fonts where several characters */
5113 /* are called .notdef (and only one is a real notdef). So if we */
5114 /* find a glyph other than 0 called ".notdef" then pretend it had */
5115 /* no name */
5116 if ( !notdefwarned ) {
5117 notdefwarned = true;
5118 LogError( _("Glyph %d is called \".notdef\", a singularly inept choice of name (only glyph 0\n may be called .notdef)\nFontForge will rename it.\n"), i );
5120 free(info->chars[i]->name);
5121 info->chars[i]->name = NULL;
5122 /* I used to check for glyphs with bad names (ie. names indicative of */
5123 /* another unicode code point than the one applied to the glyph) but */
5124 /* this proves too early for that check, as we don't have the altunis*/
5125 /* figured out yet. So I've moved that into its own routine later */
5127 /* And some volt files actually assign nul strings to the name */
5128 if ( (info->chars[i]->name!=NULL && *info->chars[i]->name!='\0' ))
5129 continue;
5130 free(info->chars[i]->name); /* If it's a null string get rid of it */
5131 if ( i==0 )
5132 name = ".notdef";
5133 else if ( info->chars[i]->unicodeenc<0 ) {
5134 /* Do this later */;
5135 name = NULL;
5136 } else {
5137 name = StdGlyphName(buffer,info->chars[i]->unicodeenc,info->uni_interp,NULL);
5138 if (THtest_duplicate_glyph_names && anynames ) {
5139 for ( j=0; j<info->glyph_cnt; ++j ) {
5140 if ( info->chars[j]!=NULL && j!=i && info->chars[j]->name!=NULL ) {
5141 if ( strcmp(info->chars[j]->name,name)==0 ) {
5142 name = NULL;
5143 break;
5149 ff_progress_next();
5150 info->chars[i]->name = copy(name);
5153 /* If we have a GSUB table we can give some unencoded glyphs names */
5154 /* for example if we have a vrt2 substitution of A to <unencoded> */
5155 /* we could name the unencoded "A.vrt2" (though in this case we might */
5156 /* try A.vert instead */ /* Werner suggested this */
5157 for ( i=info->glyph_cnt-1; i>=0 ; --i )
5158 if ( info->chars[i]!=NULL && info->chars[i]->name==NULL )
5159 break;
5160 if ( i>=0 && info->vs_start!=0 )
5161 ApplyVariationSequenceSubtable(ttf,info->vs_start,info,git_findnames);
5162 if ( i>=0 && info->gsub_start!=0 )
5163 GuessNamesFromGSUB(ttf,info);
5164 if ( i>=0 && info->math_start!=0 )
5165 GuessNamesFromMATH(ttf,info);
5167 for ( i=0; i<info->glyph_cnt; ++i ) {
5168 /* info->chars[i] can be null in some TTC files */
5169 if ( info->chars[i]==NULL )
5170 continue;
5171 if ( info->chars[i]->name!=NULL )
5172 continue;
5173 if ( info->ordering!=NULL )
5174 sprintf(buffer, "%.20s-%d", info->ordering, i );
5175 else if ( info->map!=NULL && info->map->backmap[i]!=-1 )
5176 sprintf(buffer, "nounicode.%d.%d.%x", info->platform, info->specific,
5177 (int) info->map->backmap[i] );
5178 else
5179 sprintf( buffer, "glyph%d", i );
5180 info->chars[i]->name = copy(buffer);
5181 ff_progress_next();
5183 ff_progress_next_stage();
5186 static void readttfgasp(FILE *ttf,struct ttfinfo *info) {
5187 int i, cnt;
5189 if ( info->gasp_start==0 )
5190 return;
5192 fseek(ttf,info->gasp_start,SEEK_SET);
5193 info->gasp_version = getushort(ttf);
5194 if ( info->gasp_version!=0 && info->gasp_version!=1 )
5195 return; /* We only support 'gasp' versions 0&1 (no other versions currently) */
5196 info->gasp_cnt = cnt = getushort(ttf);
5197 if ( cnt==0 )
5198 return;
5199 info->gasp = galloc(cnt*sizeof(struct gasp));
5200 for ( i=0; i<cnt; ++i ) {
5201 info->gasp[i].ppem = getushort(ttf);
5202 info->gasp[i].flags = getushort(ttf);
5206 static void UnfigureControls(Spline *spline,BasePoint *pos) {
5207 pos->x = rint( (spline->splines[0].c+2*spline->splines[0].d)/2 );
5208 pos->y = rint( (spline->splines[1].c+2*spline->splines[1].d)/2 );
5211 int ttfFindPointInSC(SplineChar *sc,int layer,int pnum,BasePoint *pos,
5212 RefChar *bound) {
5213 SplineSet *ss;
5214 SplinePoint *sp;
5215 int last=0, ret;
5216 RefChar *refs;
5218 for ( ss = sc->layers[layer].splines; ss!=NULL; ss=ss->next ) {
5219 for ( sp=ss->first; ; ) {
5220 if ( sp->ttfindex==pnum ) {
5221 *pos = sp->me;
5222 return(-1);
5223 } else if ( sp->nextcpindex==pnum ) {
5224 if ( sp->next!=NULL && sp->next->order2 )
5225 *pos = sp->nextcp;
5226 else {
5227 /* fix this up to be 2 degree bezier control point */
5228 UnfigureControls(sp->next,pos);
5230 return( -1 );
5232 if ( !sp->nonextcp && last<=sp->nextcpindex )
5233 last = sp->nextcpindex+1;
5234 else if ( sp->ttfindex!=0xffff )
5235 last = sp->ttfindex+1;
5236 if ( sp->next==NULL )
5237 break;
5238 sp = sp->next->to;
5239 if ( sp==ss->first )
5240 break;
5243 for ( refs=sc->layers[layer].refs; refs!=NULL; refs=refs->next ) {
5244 if ( refs==bound ) {
5245 LogError( _("Invalid point match. Point would be after this reference.\n") );
5246 return( 0x800000 );
5248 ret = ttfFindPointInSC(refs->sc,ly_fore,pnum-last,pos,NULL);
5249 if ( ret==-1 ) {
5250 BasePoint p;
5251 p.x = refs->transform[0]*pos->x + refs->transform[2]*pos->y + refs->transform[4];
5252 p.y = refs->transform[1]*pos->x + refs->transform[3]*pos->y + refs->transform[5];
5253 *pos = p;
5254 return( -1 );
5256 last += ret;
5257 if ( last>pnum ) {
5258 IError("Point match failure last=%d, pnum=%d", last, pnum );
5259 return( 0x800000 );
5262 return( last ); /* Count of number of points in the character */
5265 static void ttfPointMatch(SplineChar *sc,RefChar *rf) {
5266 BasePoint sofar, inref;
5268 if ( ttfFindPointInSC(sc,ly_fore,rf->match_pt_base,&sofar,rf)!=-1 ||
5269 ttfFindPointInSC(rf->sc,ly_fore,rf->match_pt_ref,&inref,NULL)!=-1 ) {
5270 LogError( _("Could not match points in composite glyph (%d to %d) when adding %s to %s\n"),
5271 rf->match_pt_base, rf->match_pt_ref, rf->sc->name, sc->name);
5272 return;
5274 rf->transform[4] = sofar.x-inref.x;
5275 rf->transform[5] = sofar.y-inref.y;
5278 int ttfFixupRef(SplineChar **chars,int i) {
5279 RefChar *ref, *prev, *next;
5281 if ( chars[i]==NULL ) /* Can happen in ttc files */
5282 return( false );
5283 if ( chars[i]->ticked )
5284 return( false );
5285 chars[i]->ticked = true;
5286 prev = NULL;
5287 for ( ref=chars[i]->layers[ly_fore].refs; ref!=NULL; ref=next ) {
5288 if ( ref->sc!=NULL )
5289 break; /* Already done */
5290 next = ref->next;
5291 if ( !ttfFixupRef(chars,ref->orig_pos)) {
5292 if ( prev==NULL )
5293 chars[i]->layers[ly_fore].refs = next;
5294 else
5295 prev->next = next;
5296 chunkfree(ref,sizeof(RefChar));
5297 } else {
5298 ref->sc = chars[ref->orig_pos];
5299 ref->adobe_enc = getAdobeEnc(ref->sc->name);
5300 if ( ref->point_match )
5301 ttfPointMatch(chars[i],ref);
5302 SCReinstanciateRefChar(chars[i],ref,ly_fore);
5303 SCMakeDependent(chars[i],ref->sc);
5304 prev = ref;
5307 chars[i]->ticked = false;
5308 return( true );
5311 static void ttfFixupReferences(struct ttfinfo *info) {
5312 int i;
5314 ff_progress_change_line2(_("Fixing up References"));
5315 for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL )
5316 info->chars[i]->ticked = false;
5317 for ( i=0; i<info->glyph_cnt; ++i ) {
5318 ttfFixupRef(info->chars,i);
5319 ff_progress_next();
5321 ff_progress_next_stage();
5324 static void TtfCopyTableBlindly(struct ttfinfo *info,FILE *ttf,
5325 uint32 start,uint32 len,uint32 tag) {
5326 struct ttf_table *tab;
5328 if ( start==0 || len==0 )
5329 return;
5330 if ( len>0x1000000 ) {
5331 LogError( _("Unlikely length for table, so I'm ignoring it. %u\n"), len );
5332 return;
5335 tab = chunkalloc(sizeof(struct ttf_table));
5336 tab->tag = tag;
5337 tab->len = len;
5338 tab->data = galloc(len);
5339 fseek(ttf,start,SEEK_SET);
5340 if (fread(tab->data,1,len,ttf) != (size_t)len) {
5341 LogError( _("Unable to read %u bytes for data, so I'm ignoring it.\n"), len );
5342 if (tab->data !=NULL) free(tab->data);
5343 if (tab !=NULL) free(tab);
5344 return;
5346 tab->next = info->tabs;
5347 info->tabs = tab;
5350 static int LookupListHasFeature(OTLookup *otl,uint32 tag) {
5351 FeatureScriptLangList *feat;
5353 while ( otl!=NULL ) {
5354 for ( feat = otl->features; feat!=NULL; feat=feat->next )
5355 if ( feat->featuretag == tag )
5356 return( true );
5357 otl = otl->next;
5359 return( false );
5362 static int readttf(FILE *ttf, struct ttfinfo *info, char *filename) {
5363 char *oldloc;
5364 int i;
5366 ff_progress_change_stages(3);
5367 if ( !readttfheader(ttf,info,filename,&info->chosenname)) {
5368 return( 0 );
5370 oldloc = setlocale(LC_NUMERIC,"C"); /* TrueType doesn't need this but opentype dictionaries do */
5371 readttfpreglyph(ttf,info);
5372 ff_progress_change_total(info->glyph_cnt);
5374 /* If font only contains bitmaps, then only read bitmaps */
5375 if ( (info->glyphlocations_start==0 || info->glyph_length==0) &&
5376 info->cff_start==0 && info->typ1_start==0 &&
5377 info->bitmapdata_start!=0 && info->bitmaploc_start!=0 )
5378 info->onlystrikes = true;
5380 if ( !info->onlystrikes &&
5381 info->glyphlocations_start!=0 && info->glyph_start!=0 &&
5382 info->cff_start!=0 ) {
5383 char *buts[4];
5384 int choice;
5385 buts[0] = _("TTF 'glyf'");
5386 buts[1] = _("OTF 'CFF '");
5387 buts[2] = _("_Cancel");
5388 buts[3] = NULL;
5389 choice = ff_ask(_("Pick a font, any font..."),(const char **) buts,0,2,_("This font contains both a TrueType 'glyf' table and an OpenType 'CFF ' table. FontForge can only deal with one at a time, please pick which one you want to use"));
5390 if ( choice==2 ) {
5391 setlocale(LC_NUMERIC,oldloc);
5392 return( 0 );
5393 } else if ( choice==0 )
5394 info->cff_start=0;
5395 else
5396 info->glyph_start = info->glyphlocations_start = 0;
5399 if ( info->onlystrikes ) {
5400 info->chars = gcalloc(info->glyph_cnt+1,sizeof(SplineChar *));
5401 info->to_order2 = new_fonts_are_order2;
5402 } else if ( info->glyphlocations_start!=0 && info->glyph_start!=0 ) {
5403 info->to_order2 = (!loaded_fonts_same_as_new ||
5404 (loaded_fonts_same_as_new && new_fonts_are_order2));
5405 readttfglyphs(ttf,info);
5406 } else if ( info->cff_start!=0 ) {
5407 info->to_order2 = (loaded_fonts_same_as_new && new_fonts_are_order2);
5408 if ( !readcffglyphs(ttf,info) ) {
5409 setlocale(LC_NUMERIC,oldloc);
5410 return( 0 );
5412 } else if ( info->typ1_start!=0 ) {
5413 if ( !readtyp1glyphs(ttf,info) ) {
5414 setlocale(LC_NUMERIC,oldloc);
5415 return( 0 );
5417 } else {
5418 setlocale(LC_NUMERIC,oldloc);
5419 return( 0 );
5421 if ( info->bitmapdata_start!=0 && info->bitmaploc_start!=0 )
5422 ; /*TTFLoadBitmaps(ttf,info,info->onlyonestrike);*/
5423 else if ( info->onlystrikes )
5424 ff_post_error( _("No Bitmap Strikes"), _("No (useable) bitmap strikes in this TTF font: %s"), filename==NULL ? "<unknown>" : filename );
5425 if ( info->onlystrikes && info->bitmaps==NULL ) {
5426 free(info->chars);
5427 setlocale(LC_NUMERIC,oldloc);
5428 return( 0 );
5430 if ( info->hmetrics_start!=0 )
5431 readttfwidths(ttf,info);
5432 else if ( info->bitmapdata_start!=0 && info->bitmaploc_start!=0 )
5433 dummywidthsfromstrike(ttf,info);
5434 if ( info->vmetrics_start!=0 && info->vhea_start!=0 )
5435 readttfvwidths(ttf,info);
5436 /* 'cmap' is not meaningful for cid keyed fonts, and not supplied for */
5437 /* type42 fonts */
5438 /* Oops. It is meaningful for cid fonts. It just seemed redundant to me */
5439 /* but that was my ignorance. Adobe complains that FF doesn't read it */
5440 /* (We've already (probably) set the unicodeencs of the glyphs according */
5441 /* to the cidmap files, but we can override that here. Mmm. what about a*/
5442 /* glyph in cidmap but not in cmap???? */
5443 if ( /* info->cidregistry==NULL && */ info->encoding_start!=0 )
5444 readttfencodings(ttf,info,git_normal);
5445 if ( info->os2_start!=0 )
5446 readttfos2metrics(ttf,info);
5447 readttfpostnames(ttf,info); /* If no postscript table we'll guess at names */
5448 if ( info->gdef_start!=0 ) /* ligature caret positioning info */
5449 readttfgdef(ttf,info);
5450 if ( info->base_start!=0 )
5451 readttfbase(ttf,info);
5452 if ( info->gasp_start!=0 )
5453 readttfgasp(ttf,info);
5454 /* read the cvt table before reading variation data */
5455 if ( info->to_order2 ) {
5456 /* Yes, even though we've looked at maxp already, let's make a blind */
5457 /* copy too for those fields we can't compute on our own */
5458 /* Like size of twilight zone, etc. */
5459 TtfCopyTableBlindly(info,ttf,info->maxp_start,info->maxp_len,CHR('m','a','x','p'));
5460 TtfCopyTableBlindly(info,ttf,info->cvt_start,info->cvt_len,CHR('c','v','t',' '));
5461 TtfCopyTableBlindly(info,ttf,info->fpgm_start,info->fpgm_len,CHR('f','p','g','m'));
5462 TtfCopyTableBlindly(info,ttf,info->prep_start,info->prep_len,CHR('p','r','e','p'));
5464 for ( i=0; i<info->savecnt; ++i ) if ( info->savetab[i].offset!=0 )
5465 TtfCopyTableBlindly(info,ttf,info->savetab[i].offset,info->savetab[i].len,info->savetab[i].tag);
5466 if ( info->gpos_start!=0 ) /* kerning info may live in the gpos table too */
5467 readttfgpossub(ttf,info,true);
5468 /* Load the 'kern' table if the GPOS table either didn't exist or didn't */
5469 /* contain any kerning info */
5470 if ( info->kern_start!=0 && !LookupListHasFeature(info->gpos_lookups,CHR('k','e','r','n')))
5471 readttfkerns(ttf,info);
5472 if ( info->gsub_start!=0 )
5473 readttfgpossub(ttf,info,false);
5475 if ( info->pfed_start!=0 )
5476 pfed_read(ttf,info);
5477 if ( info->tex_start!=0 )
5478 tex_read(ttf,info);
5479 if ( info->math_start!=0 )
5480 otf_read_math(ttf,info);
5481 setlocale(LC_NUMERIC,oldloc);
5482 if ( !info->onlystrikes && info->glyphlocations_start!=0 && info->glyph_start!=0 )
5483 ttfFixupReferences(info);
5484 /* Can't fix up any postscript references until we create a SplineFont */
5485 /* so the check for cff is delayed. Generally there aren't any cff refs */
5486 /* anyway */
5487 return( true );
5490 static void SymbolFixup(struct ttfinfo *info) {
5491 /* convert a two-byte symbol encoding (one using PUA) into expected */
5492 /* one-byte encoding. */
5493 int i, max;
5494 EncMap *map = info->map;
5496 max = -1;
5497 for ( i=map->enccount-1; i>=0; --i ) {
5498 if ( map->map[i]==-1 )
5499 continue;
5500 if ( i>=0xf000 && i<=0xf0ff ) {
5501 map->map[i-0xf000] = map->map[i];
5502 map->map[i] = -1;
5503 continue;
5505 if ( i>max ) max = i;
5507 map->enccount = max;
5510 static void NameConsistancyCheck(SplineFont *sf,EncMap *map) {
5511 /* Many fonts seem to have glyph names which mean something other than */
5512 /* what the encoding says of the glyph */
5513 /* I used to ask about fixing the names up, but people didn't like that */
5514 /* so now I just produce warnings */
5515 int gid, uni;
5516 SplineChar *sc;
5517 #if 0
5518 char buffer[100];
5519 int response, asked=-1;
5520 char *buts[5];
5521 #endif
5523 #if 0
5524 buts[0] = _("Yes"); buts[1] = _("Yes to _All");
5525 buts[2] = _("No _to All"); buts[3] = _("No");
5526 buts[4] = NULL;
5527 #endif
5529 for ( gid = 0 ; gid<sf->glyphcnt; ++gid ) if ( (sc=sf->glyphs[gid])!=NULL ) {
5530 if ( sc->name!=NULL &&
5531 strcmp(sc->name,".null")!=0 &&
5532 strcmp(sc->name,"nonmarkingreturn")!=0 &&
5533 (uni = UniFromName(sc->name,sf->uni_interp,map==NULL ? &custom : map->enc))!= -1 &&
5534 sc->unicodeenc != uni ) {
5535 #if 1
5536 if ( uni>=0xe000 && uni<=0xf8ff )
5537 /* Don't complain about adobe's old PUA assignments for things like "eight.oldstyle" */;
5538 else if ( uni<0x20 )
5539 /* Nor about control characters */;
5540 else if ( sc->unicodeenc==-1 ) {
5541 #if 0
5542 LogError(_("The glyph named %.30s is not mapped to any unicode code point.\nBut its name indicates it should be mapped to U+%04X.\n"),
5543 sc->name,uni);
5544 #endif
5545 } else {
5546 /* Ah, but suppose there's an altuni? */
5547 struct altuni *alt;
5548 for ( alt = sc->altuni; alt!=NULL && alt->unienc!=uni; alt=alt->next );
5549 if ( alt==NULL )
5550 LogError( _("The glyph named %.30s is mapped to U+%04X.\nBut its name indicates it should be mapped to U+%04X.\n"),
5551 sc->name,sc->unicodeenc, uni);
5552 else if ( alt->vs==0 ) {
5553 alt->unienc = sc->unicodeenc;
5554 sc->unicodeenc = uni;
5557 #else
5558 if ( asked!=-1 )
5559 response = asked;
5560 else if ( sc->unicodeenc==-1 )
5561 response = ff_ask(_("Bad glyph name"),(const char **) buts,1,1,_("The glyph named %.30s is not mapped to any unicode code point. But its name indicates it should be mapped to U+%04X.\nWould you like to retain the name in spite of this?"),
5562 sc->name,uni);
5563 else
5564 response = ff_ask(_("Bad glyph name"),(const char **) buts,1,1,_("The glyph named %.30s is mapped to U+%04X.\nBut its name indicates it should be mapped to U+%04X.\nWould you like to retain the name in spite of this?"),
5565 sc->name,sc->unicodeenc, uni);
5566 if ( response==1 )
5567 asked = response = 0;
5568 else if ( response==2 )
5569 asked = response = 3;
5570 if ( response==3 ) {
5571 free(sc->name);
5572 if ( sc->unicodeenc==-1 )
5573 sc->name = StdGlyphName(buffer,sc->unicodeenc,sf->uni_interp,NULL);
5574 else {
5575 sprintf( buffer, "glyph%d", gid );
5576 sc->name = copy( buffer );
5579 #endif
5584 static void UseGivenEncoding(SplineFont *sf,struct ttfinfo *info) {
5585 int i;
5586 RefChar *rf, *prev, *next;
5587 SplineChar *sc;
5589 sf->glyphs = info->chars;
5590 sf->glyphcnt = sf->glyphmax = info->glyph_cnt;
5591 for ( i=0; i<sf->glyphcnt; ++i )
5592 if ( (sc = sf->glyphs[i])!=NULL ) {
5593 sc->layers[ly_fore].order2 = sc->layers[ly_back].order2 = info->to_order2;
5594 sc->parent = sf;
5597 /* A CFF font could contain type1 charstrings, or a type2 font could use */
5598 /* the depreciated convention that endchar =~ seac */
5599 if ( info->cff_length!=0 )
5600 SFInstanciateRefs(sf);
5602 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
5603 for ( rf = sf->glyphs[i]->layers[ly_fore].refs, prev=NULL; rf!=NULL; rf = next ) {
5604 next = rf->next;
5605 if ( rf->sc==NULL ) {
5606 if ( prev==NULL ) sf->glyphs[i]->layers[ly_fore].refs = next;
5607 else prev->next = next;
5608 RefCharFree(rf);
5609 } else {
5610 rf->orig_pos = rf->sc->orig_pos;
5611 rf->unicode_enc = rf->sc->unicodeenc;
5612 prev = rf;
5616 sf->map = info->map;
5617 sf->uni_interp = info->uni_interp;
5618 NameConsistancyCheck(sf, sf->map);
5621 static void SFRelativeWinAsDs(SplineFont *sf) {
5622 if ( !sf->pfminfo.winascent_add || !sf->pfminfo.windescent_add ||
5623 !sf->pfminfo.hheadascent_add || !sf->pfminfo.hheaddescent_add ) {
5624 DBounds b;
5625 CIDLayerFindBounds(sf,ly_fore,&b);
5626 if ( !sf->pfminfo.winascent_add ) {
5627 sf->pfminfo.winascent_add = true;
5628 if ( sf->pfminfo.os2_winascent < sf->ascent/8 ) {
5629 /* There was a bug for a while which gave us really bad values */
5630 sf->pfminfo.os2_winascent = 0;
5631 sf->pfminfo.windescent_add = true;
5632 sf->pfminfo.os2_windescent = 0;
5633 } else
5634 sf->pfminfo.os2_winascent -= b.maxy;
5636 if ( !sf->pfminfo.windescent_add ) {
5637 sf->pfminfo.windescent_add = true;
5638 sf->pfminfo.os2_windescent += b.miny;
5640 if ( !sf->pfminfo.hheadascent_add ) {
5641 sf->pfminfo.hheadascent_add = true;
5642 sf->pfminfo.hhead_ascent -= b.maxy;
5644 if ( !sf->pfminfo.hheaddescent_add ) {
5645 sf->pfminfo.hheaddescent_add = true;
5646 sf->pfminfo.hhead_descent -= b.miny;
5649 if ( !sf->pfminfo.typoascent_add ) {
5650 sf->pfminfo.typoascent_add = true;
5651 sf->pfminfo.os2_typoascent -= sf->ascent;
5653 if ( !sf->pfminfo.typodescent_add ) {
5654 sf->pfminfo.typodescent_add = true;
5655 sf->pfminfo.os2_typodescent -= -sf->descent;
5659 static void PsuedoEncodeUnencoded(EncMap *map,struct ttfinfo *info) {
5660 int extras, base;
5661 int i;
5663 for ( i=0; i<info->glyph_cnt; ++i )
5664 if ( info->chars[i]!=NULL )
5665 info->chars[i]->ticked = false;
5666 for ( i=0; i<map->enccount; ++i )
5667 if ( map->map[i]!=-1 )
5668 info->chars[map->map[i]]->ticked = true;
5669 extras = 0;
5670 for ( i=0; i<info->glyph_cnt; ++i )
5671 if ( info->chars[i]!=NULL && !info->chars[i]->ticked )
5672 ++extras;
5673 if ( extras!=0 ) {
5674 /* UnicodeBmp has its own Private Use Areas */
5675 /* if (strcmp(map->enc_name","UnicodeBmp")==0) { */
5676 /* if ( (info->glyph_cnt < 0x18FF) && (map->enccount<0xE000)) */
5677 /* base = 0xE000 */
5678 /* else if ( map->enccount<0xF0000 ) */
5679 /* base = 0xF0000; */
5680 /* else if ( map->enccount<0x100000 ) */
5681 /* base = 0x100000; */
5682 /* else */
5683 /* base = map->enccount; */
5684 /* } else { */
5685 if ( map->enccount<=256 )
5686 base = 256;
5687 else if ( map->enccount<=65536 )
5688 base = 65536;
5689 else if ( map->enccount<=17*65536 )
5690 base = 17*65536;
5691 else
5692 base = map->enccount;
5693 if ( base+extras>map->encmax ) {
5694 map->map = grealloc(map->map,(base+extras)*sizeof(int));
5695 memset(map->map+map->enccount,-1,(base+extras-map->enccount)*sizeof(int));
5696 map->encmax = base+extras;
5698 map->enccount = base+extras;
5699 extras = 0;
5700 for ( i=0; i<info->glyph_cnt; ++i )
5701 if ( info->chars[i]!=NULL && !info->chars[i]->ticked )
5702 map->map[base+extras++] = i;
5706 static void MapDoBack(EncMap *map,struct ttfinfo *info) {
5707 int i;
5709 if ( map==NULL ) /* CID fonts */
5710 return;
5711 free(map->backmap); /* CFF files have this */
5712 map->backmax = info->glyph_cnt;
5713 map->backmap = galloc(info->glyph_cnt*sizeof(int));
5714 memset(map->backmap,-1,info->glyph_cnt*sizeof(int));
5715 for ( i = map->enccount-1; i>=0; --i )
5716 if ( map->map[i]>=0 && map->map[i]<info->glyph_cnt )
5717 if ( map->backmap[map->map[i]]==-1 )
5718 map->backmap[map->map[i]] = i;
5721 static SplineFont *SFFillFromTTF(struct ttfinfo *info) {
5722 SplineFont *sf, *_sf;
5723 int i,k;
5724 SplineChar *sc;
5725 struct ttf_table *last[2], *tab, *next;
5728 sf = SplineFontEmpty();
5729 sf->display_size = -default_fv_font_size;
5730 #ifdef LUA_FF_LIB
5731 sf->units_per_em = info->emsize;
5732 #endif
5733 sf->display_antialias = default_fv_antialias;
5734 sf->fontname = info->fontname;
5735 sf->fullname = info->fullname;
5736 sf->familyname = info->familyname;
5737 sf->chosenname = info->chosenname;
5738 sf->onlybitmaps = info->onlystrikes;
5739 sf->layers[ly_fore].order2 = info->to_order2;
5740 sf->layers[ly_back].order2 = info->to_order2;
5741 sf->comments = info->fontcomments;
5742 sf->fontlog = info->fontlog;
5743 sf->cvt_names = info->cvt_names;
5745 sf->creationtime = info->creationtime;
5746 sf->modificationtime = info->modificationtime;
5748 sf->design_size = info->design_size;
5749 sf->design_range_bottom = info->design_range_bottom;
5750 sf->design_range_top = info->design_range_top;
5751 sf->fontstyle_id = info->fontstyle_id;
5752 sf->fontstyle_name = info->fontstyle_name;
5754 sf->gasp_cnt = info->gasp_cnt;
5755 sf->gasp = info->gasp;
5756 sf->MATH = info->math;
5758 sf->texdata = info->texdata;
5760 sf->mark_class_cnt = info->mark_class_cnt;
5761 sf->mark_classes = info->mark_classes;
5762 sf->mark_class_names = info->mark_class_names;
5764 if ( info->fd!=NULL ) { /* Special hack for type42 fonts */
5765 sf->fontname = copy(info->fd->fontname);
5766 sf->uniqueid = info->fd->uniqueid;
5767 sf->xuid = XUIDFromFD(info->fd->xuid);
5768 if ( info->fd->fontinfo!=NULL ) {
5769 sf->familyname = utf8_verify_copy(info->fd->fontinfo->familyname);
5770 sf->fullname = utf8_verify_copy(info->fd->fontinfo->fullname);
5771 sf->copyright = utf8_verify_copy(info->fd->fontinfo->notice);
5772 sf->weight = utf8_verify_copy(info->fd->fontinfo->weight);
5773 sf->version = utf8_verify_copy(info->fd->fontinfo->version);
5774 sf->italicangle = info->fd->fontinfo->italicangle;
5775 sf->upos = info->fd->fontinfo->underlineposition*(sf->ascent+sf->descent);
5776 sf->uwidth = info->fd->fontinfo->underlinethickness*(sf->ascent+sf->descent);
5780 if ( sf->fontname==NULL ) {
5781 sf->fontname = EnforcePostScriptName(sf->fullname);
5782 if ( sf->fontname==NULL )
5783 sf->fontname = EnforcePostScriptName(sf->familyname);
5784 if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName("UntitledTTF");
5786 if ( sf->fullname==NULL ) sf->fullname = copy( sf->fontname );
5787 if ( sf->familyname==NULL ) sf->familyname = copy( sf->fontname );
5788 if ( sf->weight==NULL ) {
5789 if ( info->weight != NULL )
5790 sf->weight = info->weight;
5791 else if ( info->pfminfo.pfmset )
5792 sf->weight = copy( info->pfminfo.weight <= 100 ? "Thin" :
5793 info->pfminfo.weight <= 200 ? "Extra-Light" :
5794 info->pfminfo.weight <= 300 ? "Light" :
5795 info->pfminfo.weight <= 400 ? "Book" :
5796 info->pfminfo.weight <= 500 ? "Medium" :
5797 info->pfminfo.weight <= 600 ? "Demi" :
5798 info->pfminfo.weight <= 700 ? "Bold" :
5799 info->pfminfo.weight <= 800 ? "Heavy" :
5800 "Black" );
5801 else
5802 sf->weight = copy("");
5803 } else
5804 free( info->weight );
5805 if ( sf->copyright==NULL )
5806 sf->copyright = info->copyright;
5807 else
5808 free( info->copyright );
5809 sf->version = info->version;
5810 sf->italicangle = info->italicAngle;
5811 sf->strokewidth = info->strokewidth;
5812 sf->strokedfont = info->strokedfont;
5813 sf->upos = info->upos;
5814 sf->uwidth = info->uwidth;
5815 sf->ascent = info->ascent;
5816 if ( info->vhea_start!=0 && info->vmetrics_start!=0 )
5817 sf->hasvmetrics = true;
5818 sf->descent = info->descent;
5819 sf->private = info->private;
5820 sf->xuid = info->xuid;
5821 sf->uniqueid = info->uniqueid;
5822 sf->pfminfo = info->pfminfo;
5823 sf->os2_version = info->os2_version;
5824 sf->use_typo_metrics = info->use_typo_metrics;
5825 sf->weight_width_slope_only = info->weight_width_slope_only;
5826 sf->head_optimized_for_cleartype = info->optimized_for_cleartype;
5827 sf->gasp_version = info->gasp_version;
5828 sf->names = info->names;
5829 sf->anchor = info->ahead;
5830 sf->kerns = info->khead;
5831 sf->vkerns = info->vkhead;
5832 sf->possub = info->possub;
5833 sf->gpos_lookups = info->gpos_lookups;
5834 sf->gsub_lookups = info->gsub_lookups;
5836 last[0] = sf->ttf_tables;
5837 last[1] = NULL;
5838 for ( tab=info->tabs; tab!=NULL; tab = next ) {
5839 next = tab->next;
5840 if ( tab->tag==CHR('f','p','g','m') || tab->tag==CHR('p','r','e','p') ||
5841 tab->tag==CHR('c','v','t',' ') || tab->tag==CHR('m','a','x','p')) {
5842 if ( last[0]==NULL )
5843 sf->ttf_tables = tab;
5844 else
5845 last[0]->next = tab;
5846 last[0] = tab;
5847 } else {
5848 if ( last[1]==NULL )
5849 sf->ttf_tab_saved = tab;
5850 else
5851 last[1]->next = tab;
5852 last[1] = tab;
5854 tab->next = NULL;
5857 if ( info->twobytesymbol )
5858 /* rework ms symbol encodings */
5859 SymbolFixup(info);
5860 if ( info->map==NULL && info->subfonts==NULL ) /* Can happen when reading a ttf from a pdf */
5861 info->map = EncMapFromEncoding(sf,FindOrMakeEncoding("original"));
5862 if ( info->subfontcnt==0 )
5863 PsuedoEncodeUnencoded(info->map,info);
5864 MapDoBack(info->map,info);
5865 sf->map = info->map;
5866 sf->cidregistry = info->cidregistry;
5867 sf->ordering = info->ordering;
5868 sf->supplement = info->supplement;
5869 sf->cidversion = info->cidfontversion;
5870 sf->bitmaps = info->bitmaps;
5871 sf->grid = info->guidelines;
5872 sf->horiz_base = info->horiz_base;
5873 sf->vert_base = info->vert_base;
5874 if ( info->layers!=NULL ) {
5875 info->layers[ly_fore] = sf->layers[ly_fore];
5876 sf->layers[ly_fore].name = NULL;
5877 if ( info->layers[ly_back].name==NULL )
5878 info->layers[ly_back].name = sf->layers[ly_back].name;
5879 else
5880 free( sf->layers[ly_back].name );
5881 free( sf->layers );
5882 sf->layers = info->layers;
5883 sf->layer_cnt = info->layer_cnt;
5887 for ( i=0; i<info->glyph_cnt; ++i ) if ( info->chars[i]!=NULL ) {
5888 SCOrderAP(info->chars[i]);
5891 if ( info->subfontcnt == 0 ) {
5892 UseGivenEncoding(sf,info);
5893 } else {
5894 sf->subfontcnt = info->subfontcnt;
5895 sf->subfonts = info->subfonts;
5896 free(info->chars); /* This is the GID->char index, don't need it now */
5897 for ( i=0; i<sf->subfontcnt; ++i ) {
5898 sf->subfonts[i]->cidmaster = sf;
5899 sf->subfonts[i]->hasvmetrics = sf->hasvmetrics;
5903 /* I thought the languages were supposed to be ordered, but it seems */
5904 /* that is not always the case. Order everything, just in case */
5905 { int isgpos; OTLookup *otl;
5906 for ( isgpos=0; isgpos<2; ++isgpos )
5907 for ( otl= isgpos? sf->gpos_lookups:sf->gsub_lookups; otl!=NULL; otl=otl->next )
5908 otl->features = FLOrder(otl->features);
5911 if ( info->cff_length!=0 && !sf->layers[ly_fore].order2 ) {
5912 /* Clean up the hint masks, We create an initial hintmask whether we */
5913 /* need it or not */
5914 k=0;
5915 do {
5916 _sf = k<sf->subfontcnt?sf->subfonts[k]:sf;
5917 for ( i=0; i<sf->glyphcnt; ++i ) {
5918 if ( (sc = _sf->glyphs[i])!=NULL && !sc->hconflicts && !sc->vconflicts &&
5919 sc->layers[ly_fore].splines!=NULL ) {
5920 chunkfree( sc->layers[ly_fore].splines->first->hintmask,sizeof(HintMask) );
5921 sc->layers[ly_fore].splines->first->hintmask = NULL;
5924 ++k;
5925 } while ( k<sf->subfontcnt );
5927 /* more info */
5928 sf->units_per_em = info->emsize ;
5929 sf->pfminfo = info->pfminfo ;
5930 sf->names = info->names ;
5932 SFRelativeWinAsDs(sf);
5933 free(info->savetab);
5934 /*if (info->chars) {
5935 int i;
5936 for(i=0; info->chars[i]; i++)
5937 if (info->chars[i]->name)
5938 free(info->chars[i]->name);
5940 sf->loadvalidation_state =
5941 (info->bad_ps_fontname ?lvs_bad_ps_fontname:0) |
5942 (info->bad_glyph_data ?lvs_bad_glyph_table:0) |
5943 (info->bad_cff ?lvs_bad_cff_table:0) |
5944 (info->bad_metrics ?lvs_bad_metrics_table:0) |
5945 (info->bad_cmap ?lvs_bad_cmap_table:0) |
5946 (info->bad_embedded_bitmap ?lvs_bad_bitmaps_table:0) |
5947 (info->bad_gx ?lvs_bad_gx_table:0) |
5948 (info->bad_ot ?lvs_bad_ot_table:0) |
5949 (info->bad_os2_version ?lvs_bad_os2_version:0)|
5950 (info->bad_sfnt_header ?lvs_bad_sfnt_header:0);
5951 return( sf );
5954 SplineFont *_SFReadTTF(FILE *ttf, int flags,enum openflags openflags, char *filename,struct fontdict *fd) {
5955 struct ttfinfo info;
5956 int ret;
5958 memset(&info,'\0',sizeof(struct ttfinfo));
5959 info.onlystrikes = (flags&ttf_onlystrikes)?1:0;
5960 info.onlyonestrike = (flags&ttf_onlyonestrike)?1:0;
5961 info.use_typo_metrics = true;
5962 info.openflags = openflags;
5963 info.fd = fd;
5964 ret = readttf(ttf,&info,filename);
5965 if ( !ret )
5966 return( NULL );
5967 return( SFFillFromTTF(&info));
5970 SplineFont *SFReadTTF(char *filename, int flags, enum openflags openflags) {
5971 FILE *ttf;
5972 SplineFont *sf;
5973 char *temp=filename, *pt, *lparen, *rparen;
5975 pt = strrchr(filename,'/');
5976 if ( pt==NULL ) pt = filename;
5977 if ( (lparen = strrchr(pt,'('))!=NULL &&
5978 (rparen = strrchr(lparen,')'))!=NULL &&
5979 rparen[1]=='\0' ) {
5980 temp = copy(filename);
5981 pt = temp + (lparen-filename);
5982 *pt = '\0';
5984 ttf = fopen(temp,"rb");
5985 if ( temp!=filename ) free(temp);
5986 if ( ttf==NULL )
5987 return( NULL );
5989 sf = _SFReadTTF(ttf,flags,openflags,filename,NULL);
5990 fclose(ttf);
5991 return( sf );
5994 #ifdef LUA_FF_LIB
5996 static int readttfinfo(FILE *ttf, struct ttfinfo *info, char *filename) {
5998 if ( !readttfheader(ttf,info,filename,&info->chosenname)) {
5999 return( 0 );
6001 readttfpreglyph(ttf,info);
6002 if ( info->os2_start!=0 )
6003 readttfos2metrics(ttf,info);
6004 if ( info->postscript_start!=0 ) {
6005 fseek(ttf,info->postscript_start,SEEK_SET);
6006 (void)getlong(ttf);
6007 info->italicAngle = getfixed(ttf);
6009 return( true );
6012 /* I am not sure what happens to the ttinfo struct's members.
6013 perhaps some need free()-ing
6016 void THPatchSplineChar (SplineChar *sc)
6018 DBounds bb;
6019 if (sc->layers!=NULL && sc->layers[ly_fore].splines != NULL) {
6020 if (sc->xmax==0 && sc->ymax==0 && sc->xmin==0 && sc->ymin==0) {
6021 SplineCharFindBounds(sc,&bb);
6022 sc->xmin = bb.minx;
6023 sc->ymin = bb.miny;
6024 sc->xmax = bb.maxx;
6025 sc->ymax = bb.maxy;
6027 /* free the curves */
6028 SplinePointListsFree(sc->layers[ly_fore].splines);
6029 sc->layers[ly_fore].splines=NULL;
6031 if (sc->layers[ly_fore].refs!=NULL) {
6032 RefCharsFree(sc->layers[ly_fore].refs);
6033 sc->layers[ly_fore].refs = NULL;
6038 static SplineFont *SFFillFromTTFInfo(struct ttfinfo *info) {
6039 SplineFont *sf ;
6041 sf = SplineFontEmpty();
6043 sf->fontname = info->fontname;
6044 sf->fullname = info->fullname;
6045 sf->familyname = info->familyname;
6047 if ( info->fd!=NULL ) { /* Special hack for type42 fonts */
6048 sf->fontname = copy(info->fd->fontname);
6049 if ( info->fd->fontinfo!=NULL ) {
6050 sf->familyname = utf8_verify_copy(info->fd->fontinfo->familyname);
6051 sf->fullname = utf8_verify_copy(info->fd->fontinfo->fullname);
6052 sf->weight = utf8_verify_copy(info->fd->fontinfo->weight);
6055 if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName(sf->fullname);
6056 if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName(sf->familyname);
6057 if ( sf->fontname==NULL ) sf->fontname = EnforcePostScriptName("UntitledTTF");
6059 if ( sf->fullname==NULL ) sf->fullname = copy( sf->fontname );
6060 if ( sf->familyname==NULL ) sf->familyname = copy( sf->fontname );
6061 if ( sf->weight==NULL ) {
6062 if ( info->weight != NULL )
6063 sf->weight = info->weight;
6064 else if ( info->pfminfo.pfmset )
6065 sf->weight = copy( info->pfminfo.weight <= 100 ? "Thin" :
6066 info->pfminfo.weight <= 200 ? "Extra-Light" :
6067 info->pfminfo.weight <= 300 ? "Light" :
6068 info->pfminfo.weight <= 400 ? "Book" :
6069 info->pfminfo.weight <= 500 ? "Medium" :
6070 info->pfminfo.weight <= 600 ? "Demi" :
6071 info->pfminfo.weight <= 700 ? "Bold" :
6072 info->pfminfo.weight <= 800 ? "Heavy" :
6073 "Black" );
6074 else
6075 sf->weight = copy("");
6076 } else
6077 free( info->weight );
6078 sf->version = info->version;
6079 sf->italicangle = info->italicAngle;
6080 sf->names = info->names;
6081 sf->units_per_em = info->emsize ;
6082 sf->pfminfo = info->pfminfo ;
6084 free(info->savetab);
6085 if (info->chosenname)
6086 free(info->chosenname);
6087 if ( sf->copyright==NULL )
6088 sf->copyright = info->copyright;
6089 else
6090 free( info->copyright );
6091 return( sf );
6094 SplineFont *_SFReadTTFInfo(FILE *ttf, int flags,enum openflags openflags, char *filename,struct fontdict *fd) {
6095 struct ttfinfo info;
6096 int ret;
6097 (void)openflags; /* for -Wall */
6098 memset(&info,'\0',sizeof(struct ttfinfo));
6099 info.onlystrikes = (flags&ttf_onlystrikes)?1:0;
6100 info.onlyonestrike = (flags&ttf_onlyonestrike)?1:0;
6101 info.use_typo_metrics = true;
6102 info.fd = fd;
6103 ret = readttfinfo(ttf,&info,filename);
6104 if ( !ret )
6105 return( NULL );
6106 return( SFFillFromTTFInfo(&info));
6109 SplineFont *SFReadTTFInfo(char *filename, int flags, enum openflags openflags) {
6110 FILE *ttf;
6111 SplineFont *sf;
6112 char *temp=filename, *pt, *lparen, *rparen;
6114 pt = strrchr(filename,'/');
6115 if ( pt==NULL ) pt = filename;
6116 if ( (lparen = strrchr(pt,'('))!=NULL &&
6117 (rparen = strrchr(lparen,')'))!=NULL &&
6118 rparen[1]=='\0' ) {
6119 temp = copy(filename);
6120 pt = temp + (lparen-filename);
6121 *pt = '\0';
6123 ttf = fopen(temp,"rb");
6124 if ( temp!=filename ) free(temp);
6125 if ( ttf==NULL )
6126 return( NULL );
6128 sf = _SFReadTTFInfo(ttf,flags,openflags,filename,NULL);
6129 fclose(ttf);
6130 return( sf );
6132 #endif
6134 SplineFont *_CFFParse(FILE *temp,int len, char *fontsetname) {
6135 struct ttfinfo info;
6136 (void)fontsetname; /* for -Wall */
6138 memset(&info,'\0',sizeof(info));
6139 info.cff_start = 0;
6140 info.cff_length = len;
6141 info.barecff = true;
6142 if ( !readcffglyphs(temp,&info) )
6143 return( NULL );
6144 return( SFFillFromTTF(&info));
6147 SplineFont *CFFParse(char *filename) {
6148 FILE *cff = fopen(filename,"r");
6149 SplineFont *sf;
6150 long len;
6152 if ( cff == NULL )
6153 return( NULL );
6154 fseek(cff,0,SEEK_END);
6155 len = ftell(cff);
6156 fseek(cff,0,SEEK_SET);
6157 sf = _CFFParse(cff,len,NULL);
6158 fclose(cff);
6159 return( sf );
6162 char **NamesReadCFF(char *filename) {
6163 FILE *cff = fopen(filename,"rb");
6164 int32 hdrsize, offsize;
6165 char **fontnames;
6167 if ( cff==NULL )
6168 return( NULL );
6169 if ( getc(cff)!='\1' ) { /* Major version */
6170 LogError( _("CFF version mismatch\n") );
6171 fclose(cff);
6172 return( NULL );
6174 getc(cff); /* Minor version */
6175 hdrsize = getc(cff);
6176 offsize = getc(cff);
6177 if ( hdrsize!=4 )
6178 fseek(cff,hdrsize,SEEK_SET);
6179 fontnames = readcfffontnames(cff,NULL,NULL);
6180 fclose(cff);
6181 return( fontnames );
6184 char **NamesReadTTF(char *filename) {
6185 FILE *ttf = fopen(filename,"rb");
6186 int32 version, cnt, *offsets;
6187 int i,j;
6188 char **ret = NULL;
6189 char *temp;
6191 if ( ttf==NULL )
6192 return( NULL );
6193 version=getlong(ttf);
6194 if ( version==CHR('t','t','c','f')) {
6195 /* TTCF version = */ getlong(ttf);
6196 cnt = getlong(ttf);
6197 offsets = galloc(cnt*sizeof(int32));
6198 for ( i=0; i<cnt; ++i )
6199 offsets[i] = getlong(ttf);
6200 ret = galloc((cnt+1)*sizeof(char *));
6201 for ( i=j=0; i<cnt; ++i ) {
6202 temp = TTFGetFontName(ttf,offsets[i],0);
6203 if ( temp!=NULL )
6204 ret[j++] = temp;
6206 ret[j] = NULL;
6207 free(offsets);
6208 } else {
6209 temp = TTFGetFontName(ttf,0,0);
6210 if ( temp!=NULL ) {
6211 ret = galloc(2*sizeof(char *));
6212 ret[0] = temp;
6213 ret[1] = NULL;
6216 fclose(ttf);
6217 return(ret);