w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

parsettf.c
Go to the documentation of this file.
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:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
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.
12 
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.
15 
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.
26  */
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"
34 
36 extern const char *ttfstandardnames[];
37 extern int ask_user_for_cmap;
38 extern char *SaveTablesPref;
39 
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
44 
47 
49 int ask_user_for_cmap = false;
50 
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 */
64 
66 
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 }};
280 
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;
287 
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;
298  }
299  }
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);
306  langcode = langlocalecode = -1;
307  for ( i=0; ms_2_locals[i].loc_name!=NULL; ++i ) {
308  if ( strmatch(langcountry,ms_2_locals[i].loc_name)==0 ) {
309  langlocalecode = ms_2_locals[i].local_id;
310  langcode = langlocalecode&0x3ff;
311  break;
312  } else if ( strncmp(language,ms_2_locals[i].loc_name,langlen)==0 )
313  langcode = ms_2_locals[i].local_id&0x3ff;
314  }
315  if ( langcode==-1 ) /* Default to English */
316  langcode = 0x9;
317  return( langlocalecode==-1 ? (langcode|0x400) : langlocalecode );
318 }
319 /* ************************************************************************** */
320 
321 int getushort(FILE *ttf) {
322  int ch1 = getc(ttf);
323  int ch2 = getc(ttf);
324  if ( ch2==EOF )
325  return( EOF );
326  return( (ch1<<8)|ch2 );
327 }
328 
329 int get3byte(FILE *ttf) {
330  int ch1 = getc(ttf);
331  int ch2 = getc(ttf);
332  int ch3 = getc(ttf);
333  if ( ch3==EOF )
334  return( EOF );
335  return( (ch1<<16)|(ch2<<8)|ch3 );
336 }
337 
339  int ch1 = getc(ttf);
340  int ch2 = getc(ttf);
341  int ch3 = getc(ttf);
342  int ch4 = getc(ttf);
343  if ( ch4==EOF )
344  return( EOF );
345  return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
346 }
347 
348 static int32 getoffset(FILE *ttf, int offsize) {
349  if ( offsize==1 )
350  return( getc(ttf));
351  else if ( offsize==2 )
352  return( getushort(ttf));
353  else if ( offsize==3 )
354  return( get3byte(ttf));
355  else
356  return( getlong(ttf));
357 }
358 
360  int32 val = getlong(ttf);
361  int mant = val&0xffff;
362  /* This oddity may be needed to deal with the first 16 bits being signed */
363  /* and the low-order bits unsigned */
364  return( (real) (val>>16) + (mant/65536.0) );
365 }
366 
368  int32 val = getushort(ttf);
369  int mant = val&0x3fff;
370  /* This oddity may be needed to deal with the first 2 bits being signed */
371  /* and the low-order bits unsigned */
372  return( (real) ((val<<16)>>(16+14)) + (mant/16384.0) );
373 }
374 
375 static Encoding *enc_from_platspec(int platform,int specific) {
376  char *enc;
377  Encoding *e;
378 
379  enc = "Custom";
380  if ( platform==0 ) {
381  enc = "Unicode";
382  if ( specific==4 )
383  enc = "UnicodeFull";
384  } else if ( platform==1 ) {
385  if ( specific==0 )
386  enc = "Mac";
387  else if ( specific==1 )
388  enc = "Sjis";
389  else if ( specific==2 )
390  enc = "Big5hkscs"; /* Or should we just guess big5? Both are wrong sometimes */
391  else if ( specific==3 )
392  enc = "EUC-KR";
393  else if ( specific==25 )
394  enc = "EUC-CN";
395  } else if ( platform==2 ) { /* obselete */
396  if ( specific==0 )
397  enc = "ASCII";
398  else if ( specific==1 )
399  enc = "Unicode";
400  else if ( specific==2 )
401  enc = "ISO8859-1";
402  } else if ( platform==3 ) {
403  if ( specific==1 || specific==0 ) /* symbol (sp=0) is just unicode (PUA) */
404  enc = "Unicode";
405  else if ( specific==2 )
406  enc = "Sjis";
407  else if ( specific==3 )
408  enc = "EUC-CN";
409  else if ( specific==4 )
410  enc = "Big5hkscs";
411  else if ( specific==5 )
412  enc = "EUC-KR";
413  else if ( specific==6 )
414  enc = "Johab";
415  else if ( specific==10 )
416  enc = "UnicodeFull";
417  } else if ( platform==7 ) { /* Used internally in freetype, but */
418  if ( specific==0 ) /* there's no harm in looking for it */
419  enc = "AdobeStandard"; /* even if it never happens */
420  else if ( specific==1 ) {
421  /* adobe_expert */;
422  } else if ( specific==2 ) {
423  /* adobe_custom */;
424  }
425  }
427  if ( e==NULL ) {
428  static int p = -1,s = -1;
429  if ( p!=platform || s!=specific ) {
430  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"),
431  platform, specific, enc );
432  p = platform;
433  s = specific;
434  }
435  }
436  return( e );
437 }
438 
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;
446 
447  fseek(ttf,offset,SEEK_SET);
448 
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);
469  }
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("");
496  }
497  ret = u2utf8_copy(str);
498  free(str);
499  }
500  fseek(ttf,pos,SEEK_SET);
501  return( ret );
502 }
503 
505  int i,num;
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;
513  int maclang = WinLangToMac(locale);
514 
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;
528  }
529  if ( i==num )
530  return( NULL );
531 
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;
580  }
581  }
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;
590  }
591  return( _readencstring(ttf,stringoffset+fullstr,fulllen,fullplat,fullspec,fulllang));
592 }
593 
595  int i,num;
597  int name, len, off;
598  int32 nameoffset = 0;
599 
600  fseek(ttf,offset,SEEK_SET);
601  /* version = */ getlong(ttf);
602  num = getushort(ttf);
603  /* srange = */ getushort(ttf);
604  /* esel = */ getushort(ttf);
605  /* rshift = */ getushort(ttf);
606  for ( i=0; i<num; ++i ) {
607  tag = getlong(ttf);
608  /* checksum = */ getlong(ttf);
609  nameoffset = off2+getlong(ttf);
610  length = getlong(ttf);
611  if ( tag==CHR('n','a','m','e'))
612  break;
613  }
614  if ( i==num )
615  return( NULL );
616 
617  fseek(ttf,nameoffset,SEEK_SET);
618  /* format = */ getushort(ttf);
619  num = getushort(ttf);
620  stringoffset = nameoffset+getushort(ttf);
621 
622  for ( i=0; i<num; ++i ) {
623  /* plat */ getushort(ttf);
624  /* spec */ getushort(ttf);
625  /* lang */ getushort(ttf);
626  name = getushort(ttf);
627  len = getushort(ttf);
628  off = getushort(ttf);
629  if (name == 6) {
630  char *str = malloc(len+1);
631  if (str) {
632  fseek (ttf, stringoffset+off, SEEK_SET);
633  if(fread(str,1,len,ttf)==(size_t)len) {
634  str[len] = '\0';
635  return str;
636  }
637  free(str);
638  }
639  }
640  }
641  return NULL;
642 }
643 
644 static int PickTTFFont(FILE *ttf,char *filename,char **chosenname) {
645  int32 *offsets, cnt, i, choice, j;
646  char **names;
647  char *pt, *lparen, *rparen;
648 
649  /* TTCF version = */ getlong(ttf);
650  cnt = getlong(ttf);
651  if ( cnt==1 ) {
652  /* This is easy, don't bother to ask the user, there's no choice */
653  int32 offset = getlong(ttf);
654  fseek(ttf,offset,SEEK_SET);
655  return( true );
656  }
657  offsets = galloc(cnt*sizeof(int32));
658  for ( i=0; i<cnt; ++i )
659  offsets[i] = getlong(ttf);
660  names = galloc(cnt*sizeof(char *));
661  for ( i=j=0; i<cnt; ++i ) {
662  names[j] = TTFGetFontName(ttf,offsets[i],0);
663  if ( names[j]!=NULL )
664  ++j;
665  }
666  pt = strrchr(filename,'/');
667  if ( pt==NULL )
668  pt = filename;
669  /* Someone gave me a font "Nafees Nastaleeq(Updated).ttf" and complained */
670  /* that ff wouldn't open it */
671  /* Now someone will complain about "Nafees(Updated).ttc(fo(ob)ar)" */
672  if ( (lparen = strrchr(pt,'('))!=NULL && (rparen = strrchr(lparen,')'))!=NULL && rparen[1]=='\0' ) {
673  char *find = copy(lparen+1);
674  pt = strchr(find,')');
675  if ( pt!=NULL ) *pt='\0';
676  for ( choice=cnt-1; choice>=0; --choice )
677  if ( strcmp(names[choice],find)==0 )
678  break;
679  if ( choice==-1 ) {
680  char *end;
681  choice = strtol(find,&end,10);
682  if ( *end!='\0' )
683  choice = -1;
684  }
685  if ( choice==-1 ) {
686  char *fn = copy(filename);
687  fn[lparen-filename] = '\0';
688  ff_post_error(_("Not in Collection"),
689  /* GT: The user is trying to open a font file which contains multiple fonts and */
690  /* GT: has asked for a font which is not in that file. */
691  /* GT: The string will look like: <fontname> is not in <filename> */
692  _("%1$s is not in %2$.100s"),find,fn);
693  free(fn);
694  }
695  free(find);
696  } else
697  choice = 0;
698  if ( choice!=-1 ) {
699  fseek(ttf,offsets[choice],SEEK_SET);
700  *chosenname = copy(names[choice]);
701  }
702  for ( i=0; i<j; ++i )
703  free(names[i]);
704  free(names);
705  free(offsets);
706 return( choice!=-1);
707 }
708 
709 static int PickCFFFont(char **fontnames) {
710  unichar_t **names;
711  int cnt, i, choice;
712 
713  for ( cnt=0; fontnames[cnt]!=NULL; ++cnt){;}
714  names = gcalloc(cnt+1,sizeof(unichar_t *));
715  for ( i=0; i<cnt; ++i )
716  names[i] = uc_copy(fontnames[i]);
717  choice = 0;
718  for ( i=0; i<cnt; ++i )
719  free(names[i]);
720  free(names);
721  return( choice );
722 }
723 
724 static void ParseSaveTablesPref(struct ttfinfo *info) {
725  char *pt, *spt;
726  int cnt;
727 
728  info->savecnt = 0;
729  info->savetab = NULL;
730  if ( SaveTablesPref==NULL || *SaveTablesPref=='\0' )
731  return;
732  for ( pt=SaveTablesPref, cnt=0; *pt; ++pt )
733  if ( *pt==',' )
734  ++cnt;
735  info->savecnt = cnt+1;
736  info->savetab = gcalloc(cnt+1,sizeof(struct savetab));
737  for ( pt=spt=SaveTablesPref, cnt=0; ; ++pt ) {
738  if ( *pt==',' || *pt=='\0' ) {
739  uint32 tag;
740  tag = ( ( spt <pt )? spt[0] : ' ' )<<24;
741  tag |= ( ( spt+1<pt )? spt[1] : ' ' )<<16;
742  tag |= ( ( spt+2<pt )? spt[2] : ' ' )<<8 ;
743  tag |= ( ( spt+3<pt )? spt[3] : ' ' ) ;
744  info->savetab[cnt++].tag = tag;
745  if ( *pt )
746  spt = pt+1;
747  else
748  break;
749  }
750  }
751 }
752 
753 static int32 filechecksum(FILE *file, int start, int len) {
754  uint32 sum = 0, chunk;
756  if ( len!=-1 )
757  len=(len+3)>>2;
758  while ( len==-1 || --len>=0 ) {
759  chunk = getlong(file);
760  if ( feof(file))
761  break;
762  sum += chunk;
763  }
764  return( sum );
765 }
766 
767 static void ValidateTTFHead(FILE *ttf,struct ttfinfo *info) {
768  /* When doing font lint we want to check the ttf header and make */
769  /* sure all the offsets and lengths are valid, and the checksums */
770  /* match. Most of the time this is just extra work and we don't */
771  /* bather */
772  uint32 restore_this_pos = ftell(ttf);
773  struct tt_tables {
774  uint32 tag;
776  uint32 offset;
777  uint32 length;
778  } *tabs, temp;
779  int i,j;
781  int sr, es, rs, e_sr, e_es, e_rs;
782  int hashead, hashhea, hasmaxp, masos2, haspost, hasname, hasos2;
783  int hasloca, hascff, hasglyf;
784 
785  info->numtables = getushort(ttf);
786  sr = getushort(ttf);
787  es = getushort(ttf);
788  rs = getushort(ttf);
789  e_sr = (info->numtables<8?4:info->numtables<16?8:info->numtables<32?16:info->numtables<64?32:64)*16;
790  e_es = (info->numtables<8?2:info->numtables<16?3:info->numtables<32?4:info->numtables<64?5:6);
791  e_rs = info->numtables*16-e_sr;
792  if ( e_sr!=sr || e_es!=es || e_rs!=rs ) {
793  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"),
794  e_sr, sr, e_es, es, e_rs, rs );
795  info->bad_sfnt_header = true;
796  }
797 
798  if ( info->numtables<=0 ) {
799  LogError(_("An sfnt file must contain SOME tables, but this one does not."));
800  info->bad_sfnt_header = true;
801  fseek(ttf,restore_this_pos,SEEK_SET);
802  return;
803  } else if ( info->numtables>1000 ) {
804  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"));
805  info->bad_sfnt_header = true;
806  fseek(ttf,restore_this_pos,SEEK_SET);
807  return;
808  }
809 
810  tabs = galloc(info->numtables*sizeof(struct tt_tables));
811 
812  for ( i=0; i<info->numtables; ++i ) {
813  tabs[i].tag = getlong(ttf);
814  tabs[i].checksum = getlong(ttf);
815  tabs[i].offset = getlong(ttf);
816  tabs[i].length = getlong(ttf);
817  if ( i!=0 && tabs[i].tag<tabs[i-1].tag && !info->bad_sfnt_header ) {
818  LogError(_("Table tags should be in alphabetic order in the font header\n but '%c%c%c%c', appears after '%c%c%c%c'."),
819  tabs[i-1].tag>>24, tabs[i-1].tag>>16, tabs[i-1].tag>>8, tabs[i-1].tag,
820  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
821  info->bad_sfnt_header = true;
822  }
823  }
824  fseek(ttf,0,SEEK_END);
825  file_len = ftell(ttf);
826 
827  for ( i=0; i<info->numtables; ++i ) for ( j=i+1; j<info->numtables; ++j ) {
828  if ( tabs[i].offset>tabs[j].offset ) {
829  temp = tabs[i];
830  tabs[i] = tabs[j];
831  tabs[j] = temp;
832  }
833  }
834  for ( i=0; i<info->numtables-1; ++i ) {
835  for ( j=i+1; j<info->numtables; ++j ) {
836  if ( tabs[i].tag==tabs[j].tag ) {
837  LogError(_("Same table tag, '%c%c%c%c', appears twice in sfnt header"),
838  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
839  info->bad_sfnt_header = true;
840  }
841  }
842  if ( tabs[i].offset+tabs[i].length > tabs[i+1].offset ) {
843  LogError(_("Tables '%c%c%c%c' and '%c%c%c%c' overlap"),
844  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
845  tabs[j].tag>>24, tabs[j].tag>>16, tabs[j].tag>>8, tabs[j].tag );
846  }
847  }
848  if ( tabs[i].offset+tabs[i].length > file_len ) {
849  LogError(_("Table '%c%c%c%c' extends beyond end of file."),
850  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
851  info->bad_sfnt_header = true;
852  }
853 
854  /* Checksums. First file as a whole, then each table */
855  if ( filechecksum(ttf,0,-1)!=(int)0xb1b0afba ) {
856  LogError(_("File checksum is incorrect."));
857  info->bad_sfnt_header = true;
858  }
859  for ( i=0; i<info->numtables-1; ++i ) if ( tabs[i].tag!=CHR('h','e','a','d')) {
860  if ( filechecksum(ttf,tabs[i].offset,tabs[i].length)!=(int)tabs[i].checksum ) {
861  LogError(_("Table '%c%c%c%c' has a bad checksum."),
862  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
863  info->bad_sfnt_header = true;
864  }
865  }
866 
867  hashead = hashhea = hasmaxp = masos2 = haspost = hasname = hasos2 = false;
868  hasloca = hascff = hasglyf = false;
869  for ( i=0; i<info->numtables-1; ++i ) {
870  switch ( tabs[i].tag ) {
871  case CHR('c','v','t',' '):
872  if ( tabs[i].length&1 )
873  LogError(_("Table '%c%c%c%c' has a bad length, must be even."),
874  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag );
875  break;
876  case CHR('b','h','e','d'): /* Fonts with bitmaps but no outlines get bhea */
877  case CHR('h','e','a','d'):
878  if ( tabs[i].length!=54 )
879  LogError(_("Table '%c%c%c%c' has a bad length, must be 54 but is %d."),
880  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
881  tabs[i].length );
882  hashead = true;
883  break;
884  case CHR('h','h','e','a'):
885  hashhea = true;
886  case CHR('v','h','e','a'):
887  if ( tabs[i].length!=36 )
888  LogError(_("Table '%c%c%c%c' has a bad length, must be 36 but is %d."),
889  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
890  tabs[i].length );
891  break;
892  case CHR('m','a','x','p'):
893  hasmaxp = true;
894  if ( tabs[i].length!=32 && tabs[i].length!=6 )
895  LogError(_("Table '%c%c%c%c' has a bad length, must be 32 or 6 but is %d."),
896  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
897  tabs[i].length );
898  break;
899  case CHR('O','S','/','2'):
900  hasos2 = true;
901  if ( tabs[i].length!=78 && tabs[i].length!=86 && tabs[i].length!=96 )
902  LogError(_("Table '%c%c%c%c' has a bad length, must be 78, 86 or 96 but is %d."),
903  tabs[i].tag>>24, tabs[i].tag>>16, tabs[i].tag>>8, tabs[i].tag,
904  tabs[i].length );
905  break;
906  case CHR('p','o','s','t'):
907  haspost = true;
908  break;
909  case CHR('n','a','m','e'):
910  hasname = true;
911  break;
912  case CHR('l','o','c','a'):
913  hasloca = true;
914  break;
915  case CHR('g','l','y','f'):
916  hasglyf = true;
917  break;
918  case CHR('C','F','F',' '):
919  hascff = true;
920  break;
921  }
922  }
923  if ( !hashead )
924  LogError(_("Missing required table: \"head\""));
925  if ( !hashhea )
926  LogError(_("Missing required table: \"hhea\""));
927  if ( !hasmaxp )
928  LogError(_("Missing required table: \"maxp\""));
929  if ( !haspost )
930  LogError(_("Missing required table: \"post\""));
931  if ( !hasname )
932  LogError(_("Missing required table: \"name\""));
933  if ( hasglyf && !hasloca )
934  LogError(_("Missing required table: \"loca\""));
935  if ( !hasos2 )
936  LogError(_("Missing \"OS/2\" table"));
937  if ( !hasglyf && hasloca )
938  LogError(_("Missing required table: \"glyf\""));
939  if ( !hasglyf && !hascff )
940  LogError(_("This font contains neither \"CFF \" nor \"glyf\"/\"loca\" tables"));
941 
942  free(tabs);
943  fseek(ttf,restore_this_pos,SEEK_SET);
944 }
945 
946 static struct tablenames { uint32 tag; char *name; } stdtables[] = {
947  { CHR('a','c','n','t'), N_("accent attachment table") },
948  { CHR('a','v','a','r'), N_("axis variation table") },
949  { CHR('B','A','S','E'), N_("Baseline table (OT version)") },
950  { CHR('b','d','a','t'), N_("bitmap data table (AAT version)") },
951  { CHR('B','D','F',' '), N_("BDF bitmap properties table") },
952  { CHR('b','h','e','d'), N_("bitmap font header table") },
953  { CHR('b','l','o','c'), N_("bitmap location table (AAT version)") },
954  { CHR('b','s','l','n'), N_("baseline table (AAT version)") },
955  { CHR('C','F','F',' '), N_("PostScript font program (Compact Font Format)") },
956  { CHR('C','I','D',' '), N_("Obsolete table for a type1 CID keyed font") },
957  { CHR('c','m','a','p'), N_("character code mapping table") },
958  { CHR('c','v','a','r'), N_("CVT variation table") },
959  { CHR('c','v','t',' '), N_("control value table") },
960  { CHR('D','S','I','G'), N_("digital signature table") },
961  { CHR('E','B','D','T'), N_("bitmap data table (OT version)") },
962  { CHR('E','B','L','C'), N_("bitmap location table (OT version)") },
963  { CHR('E','B','S','C'), N_("embedded bitmap scaling control table") },
964  { CHR('E','L','U','A'), N_("electronic end user license table") },
965  { CHR('f','d','s','c'), N_("font descriptor table") },
966  { CHR('f','e','a','t'), N_("layout feature table") },
967  { CHR('F','e','a','t'), N_("SIL Graphite layout feature table") },
968  { CHR('F','F','T','M'), N_("FontForge time stamp table") },
969  { CHR('f','m','t','x'), N_("font metrics table") },
970  { CHR('f','p','g','m'), N_("font program table") },
971  { CHR('f','v','a','r'), N_("font variation table") },
972  { CHR('g','a','s','p'), N_("grid-fitting and scan-conversion procedure table") },
973  { CHR('G','D','E','F'), N_("glyph definition table") },
974  { CHR('G','l','a','t'), N_("Graphite glyph attribute table") },
975  { CHR('G','l','o','c'), N_("Graphite glyph location in Glat table") },
976  { CHR('g','l','y','f'), N_("glyph outline table") },
977  { CHR('G','P','O','S'), N_("glyph positioning table") },
978  { CHR('g','v','a','r'), N_("glyph variation table") },
979  { CHR('G','S','U','B'), N_("glyph substitution table") },
980  { CHR('h','d','m','x'), N_("horizontal device metrics table") },
981  { CHR('h','e','a','d'), N_("font header table") },
982  { CHR('h','h','e','a'), N_("horizontal header table") },
983  { CHR('h','m','t','x'), N_("horizontal metrics table") },
984  { CHR('h','s','t','y'), N_("horizontal style table") },
985  { CHR('j','u','s','t'), N_("justification table (AAT version)") },
986  { CHR('J','S','T','F'), N_("justification table (OT version)") },
987  { CHR('k','e','r','n'), N_("kerning table") },
988  { CHR('l','c','a','r'), N_("ligature caret table") },
989  { CHR('l','o','c','a'), N_("glyph location table") },
990  { CHR('L','T','S','H'), N_("linear threshold table") },
991  { CHR('M','A','T','H'), N_("math table") },
992  { CHR('m','a','x','p'), N_("maximum profile table") },
993  { CHR('M','M','S','D'), N_("Multi-Master table, obsolete") },
994  { CHR('M','M','F','X'), N_("Multi-Master table, obsolete") },
995  { CHR('m','o','r','t'), N_("metamorphosis table") },
996  { CHR('m','o','r','x'), N_("extended metamorphosis table") },
997  { CHR('n','a','m','e'), N_("name table") },
998  { CHR('o','p','b','d'), N_("optical bounds table") },
999  { CHR('O','S','/','2'), N_("OS/2 and Windows specific metrics table") },
1000  { CHR('P','C','L','T'), N_("PCL 5 data table") },
1001  { CHR('P','f','E','d'), N_("FontForge font debugging table") },
1002  { CHR('p','o','s','t'), N_("glyph name and PostScript compatibility table") },
1003  { CHR('p','r','e','p'), N_("control value program table") },
1004  { CHR('p','r','o','p'), N_("properties table") },
1005  { CHR('S','i','l','f'), N_("SIL Graphite rule table") },
1006  { CHR('S','i','l','l'), N_("(unspecified) SIL Graphite table") },
1007  { CHR('S','i','l','t'), N_("unknown SIL table") },
1008  { CHR('T','e','X',' '), N_("TeX table") },
1009  { CHR('t','r','a','k'), N_("tracking table") },
1010  { CHR('T','Y','P','1'), N_("Obsolete table for a type1 font") },
1011  { CHR('V','D','M','X'), N_("vertical device metrics table") },
1012  { CHR('v','h','e','a'), N_("vertical header table") },
1013  { CHR('v','m','t','x'), N_("vertical metrics table") },
1014  { CHR('V','O','R','G'), N_("vertical origin table") },
1015  { CHR('Z','a','p','f'), N_("glyph reference table") },
1016  { 0 , NULL }
1017 };
1018 
1019 static int readttfheader(FILE *ttf, struct ttfinfo *info,char *filename,
1020  char **choosenname) {
1021  int i, j, k;
1022  unsigned tag;
1023  int checksum, offset, length, version;
1024  int first = true;
1025 
1026  version=getlong(ttf);
1027  if ( version==CHR('t','t','c','f')) {
1028  /* TrueType font collection */
1029  info->is_ttc = true;
1030  if ( !PickTTFFont(ttf,filename,choosenname))
1031 return( 0 );
1032  /* If they picked a font, then we should be left pointing at the */
1033  /* start of the Table Directory for that font */
1034  info->one_of_many = true;
1035  version = getlong(ttf);
1036  }
1037 
1038  /* Apple says that 'typ1' is a valid code for a type1 font wrapped up in */
1039  /* a truetype table structure, but gives no docs on what tables get used */
1040  /* or how */ /* Turns out to be pretty simple */
1041  /* typ1 is used for both type1 fonts and CID type1 fonts, I don't think a version of 'CID ' is actually used */
1042  if ( version==CHR('t','y','p','1') || version==CHR('C','I','D',' ')) {
1043  LogError( _("Nifty, you've got one of the old Apple/Adobe type1 sfnts here\n") );
1044  } else if ( version!=0x00010000 && version!=CHR('t','r','u','e') &&
1045  version!=0x00020000 && /* Windows 3.1 Chinese version used this version for some arphic fonts */
1046  /* See discussion on freetype list, july 2004 */
1047  version!=CHR('O','T','T','O'))
1048 return( 0 ); /* Not version 1 of true type, nor Open Type */
1049 
1050  if ( info->openflags & of_fontlint )
1051  ValidateTTFHead(ttf,info);
1052 
1053  info->numtables = getushort(ttf);
1054  /* searchRange = */ getushort(ttf);
1055  /* entrySelector = */ getushort(ttf);
1056  /* rangeshift = */ getushort(ttf);
1057 
1059 
1060  for ( i=0; i<info->numtables; ++i ) {
1061  tag = getlong(ttf);
1062  checksum = getlong(ttf);
1063  offset = getlong(ttf);
1064  length = getlong(ttf);
1065 #ifdef DEBUG
1066  printf( "%c%c%c%c\n", tag>>24, (tag>>16)&0xff, (tag>>8)&0xff, tag&0xff );
1067 #endif
1068  switch ( tag ) {
1069  case CHR('B','A','S','E'):
1070  info->base_start = offset;
1071  break;
1072  case CHR('C','F','F',' '):
1073  info->cff_start = offset;
1074  info->cff_length = length;
1075  break;
1076  case CHR('c','m','a','p'):
1077  info->encoding_start = offset;
1078  break;
1079  case CHR('g','a','s','p'):
1080  info->gasp_start = offset;
1081  break;
1082  case CHR('g','l','y','f'):
1083  info->glyph_start = offset;
1084  info->glyph_length = length;
1085  break;
1086  case CHR('G','D','E','F'):
1087  info->gdef_start = offset;
1088  info->gdef_length = length;
1089  break;
1090  case CHR('G','P','O','S'):
1091  info->gpos_start = offset;
1092  info->gpos_length = length;
1093  break;
1094  case CHR('G','S','U','B'):
1095  info->gsub_start = offset;
1096  info->gsub_length = length;
1097  break;
1098  case CHR('b','d','a','t'): /* Apple/MS use a different tag, but the same format. Great. */
1099  case CHR('E','B','D','T'):
1100  info->bitmapdata_start = offset;
1101  info->bitmapdata_length = length;
1102  break;
1103  case CHR('b','l','o','c'): /* Apple/MS use a different tag. Great. */
1104  case CHR('E','B','L','C'):
1105  info->bitmaploc_start = offset;
1106  info->bitmaploc_length = length;
1107  break;
1108  case CHR('b','h','e','d'): /* Apple uses bhed for fonts with only bitmaps */
1109  case CHR('h','e','a','d'):
1110  info->head_start = offset;
1111  break;
1112  case CHR('h','h','e','a'):
1113  info->hhea_start = offset;
1114  break;
1115  case CHR('h','m','t','x'):
1116  info->hmetrics_start = offset;
1117  break;
1118  case CHR('k','e','r','n'):
1119  info->kern_start = offset;
1120  break;
1121  case CHR('l','o','c','a'):
1122  info->glyphlocations_start = offset;
1123  info->loca_length = length;
1124  info->glyph_cnt = length/2-1; /* the minus one is because there is one extra entry to give the length of the last glyph */
1125  if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
1126  break;
1127  case CHR('m','a','x','p'):
1128  info->maxp_start = offset;
1129  info->maxp_len = length;
1130  break;
1131  case CHR('n','a','m','e'):
1132  info->copyright_start = offset;
1133  break;
1134  case CHR('p','o','s','t'):
1135  info->postscript_start = offset;
1136  break;
1137  case CHR('O','S','/','2'):
1138  info->os2_start = offset;
1139  break;
1140  case CHR('C','I','D',' '):
1141  case CHR('T','Y','P','1'):
1142  info->typ1_start = offset;
1143  info->typ1_length = length;
1144  break;
1145  case CHR('v','h','e','a'):
1146  info->vhea_start = offset;
1147  break;
1148  case CHR('v','m','t','x'):
1149  info->vmetrics_start = offset;
1150  break;
1151  case CHR('M','A','T','H'):
1152  info->math_start = offset;
1153  info->math_length = length;
1154  break;
1155  /* to make sense of instrs */
1156  case CHR('c','v','t',' '):
1157  info->cvt_start = offset;
1158  info->cvt_len = length;
1159  break;
1160  case CHR('p','r','e','p'):
1161  info->prep_start = offset;
1162  info->prep_len = length;
1163  break;
1164  case CHR('f','p','g','m'):
1165  info->fpgm_start = offset;
1166  info->fpgm_len = length;
1167  break;
1168 
1169  /* non-standard tables I've added */
1170  case CHR('P','f','E','d'):
1171  info->pfed_start = offset;
1172  break;
1173  case CHR('F','F','T','M'):
1174  info->fftm_start = offset;
1175  break;
1176  case CHR('T','e','X',' '):
1177  info->tex_start = offset;
1178  break;
1179  case CHR('B','D','F',' '):
1180  info->bdf_start = offset;
1181  break;
1182 
1183  default:
1184  for ( j=0; j<info->savecnt; ++j ) if ( info->savetab[j].tag == tag ) {
1185  info->savetab[j].offset = offset;
1186  info->savetab[j].len = length;
1187  break;
1188  }
1189  if ( j==info->savecnt ) {
1190  if ( first ) {
1191  LogError( _("The following table(s) in the font have been ignored by FontForge\n") );
1192  first = false;
1193  }
1194  for ( k=0; stdtables[k].tag!=0; ++k )
1195  if ( stdtables[k].tag == tag )
1196  break;
1197  if ( stdtables[k].tag==0 ) {
1198  LogError( _(" Ignoring '%c%c%c%c'\n"), tag>>24, tag>>16, tag>>8, tag);
1199  } else {
1200  LogError( _(" Ignoring '%c%c%c%c' %s\n"), tag>>24, tag>>16, tag>>8, tag,
1201  _(stdtables[k].name));
1202  }
1203  }
1204  }
1205  }
1206  if ( info->glyphlocations_start!=0 && info->cff_start!=0 )
1207  LogError( _("This font contains both truetype and PostScript glyph descriptions\n only one will be used.\n"));
1208  else if ( (info->glyphlocations_start!=0) +
1209  (info->cff_start!=0) +
1210  (info->typ1_start!=0)>1 )
1211  LogError( _("This font contains multiple glyph descriptions\n only one will be used.\n"));
1212  if ( info->gpos_start!=0 && info->kern_start!=0 )
1213  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"));
1214 return( true );
1215 }
1216 
1217 static void readdate(FILE *ttf,struct ttfinfo *info,int ismod) {
1218  int date[4], date1970[4], year[2];
1219  int i;
1220  /* Dates in sfnt files are seconds since 1904. I adjust to unix time */
1221  /* seconds since 1970 by figuring out how many seconds were in between */
1222 
1223  date[3] = getushort(ttf);
1224  date[2] = getushort(ttf);
1225  date[1] = getushort(ttf);
1226  date[0] = getushort(ttf);
1227  memset(date1970,0,sizeof(date1970));
1228  year[0] = (60*60*24*365L)&0xffff;
1229  year[1] = (60*60*24*365L)>>16;
1230  for ( i=1904; i<1970; ++i ) {
1231  date1970[0] += year[0];
1232  date1970[1] += year[1];
1233  if ( (i&3)==0 && (i%100!=0 || i%400==0))
1234  date1970[0] += 24*60*60L; /* Leap year */
1235  date1970[1] += (date1970[0]>>16);
1236  date1970[0] &= 0xffff;
1237  date1970[2] += date1970[1]>>16;
1238  date1970[1] &= 0xffff;
1239  date1970[3] += date1970[2]>>16;
1240  date1970[2] &= 0xffff;
1241  }
1242 
1243  for ( i=0; i<3; ++i ) {
1244  date[i] -= date1970[i];
1245  date[i+1] += date[i]>>16;
1246  date[i] &= 0xffff;
1247  }
1248  date[3] -= date1970[3];
1249 
1250  *(ismod ? &info->modificationtime : &info->creationtime) =
1251 #ifdef _HAS_LONGLONG
1252  (((long long) date[3])<<48) |
1253  (((long long) date[2])<<32) |
1254 #endif
1255  ( date[1] <<16) |
1256  date[0];
1257 }
1258 
1259 static void readttfhead(FILE *ttf,struct ttfinfo *info) {
1260  /* Here I want units per em, and size of loca entries */
1261  /* oh... also creation/modification times */
1262  int i, flags;
1263 
1264  fseek(ttf,info->head_start+4*4,SEEK_SET); /* skip over the version number and a bunch of junk */
1265  flags = getushort(ttf);
1266  info->optimized_for_cleartype = (flags&(1<<13))?1:0;
1267  info->apply_lsb = !(flags&(1<<1));
1268  info->emsize = getushort(ttf);
1269 
1270  info->ascent = .8*info->emsize;
1271  info->descent = info->emsize-info->ascent;
1272 
1273  for ( i=0; i<12; ++i )
1274  getushort(ttf);
1275  info->macstyle = getushort(ttf);
1276  for ( i=0; i<2; ++i )
1277  getushort(ttf);
1278  info->index_to_loc_is_long = getushort(ttf);
1279  if ( info->index_to_loc_is_long )
1280  info->glyph_cnt = info->loca_length/4-1;
1281  if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
1282 
1283  if ( info->fftm_start!=0 ) {
1284  fseek(ttf,info->fftm_start+3*4,SEEK_SET);
1285  } else {
1286  fseek(ttf,info->head_start+4*4+2+2,SEEK_SET);
1287  }
1288  readdate(ttf,info,0);
1289  readdate(ttf,info,1);
1290 }
1291 
1292 static void readttfhhea(FILE *ttf,struct ttfinfo *info) {
1293  /* Here I want ascent, descent and the number of horizontal metrics */
1294  int i;
1295 
1296  fseek(ttf,info->hhea_start+4,SEEK_SET); /* skip over the version number */
1297  info->pfminfo.hhead_ascent = getushort(ttf);
1298  info->pfminfo.hhead_descent = (short) getushort(ttf);
1299  info->pfminfo.hheadascent_add = info->pfminfo.hheaddescent_add = false;
1300  info->pfminfo.linegap = getushort(ttf);
1301  info->pfminfo.hheadset = true;
1302  /*info->ascent = info->pfminfo.hhead_ascent;*/
1303 
1304  for ( i=0; i<12; ++i )
1305  getushort(ttf);
1306  info->width_cnt = getushort(ttf);
1307 }
1308 
1309 static void readttfmaxp(FILE *ttf,struct ttfinfo *info) {
1310  /* All I want here is the number of glyphs */
1311  int cnt;
1312  fseek(ttf,info->maxp_start+4,SEEK_SET); /* skip over the version number */
1313  cnt = getushort(ttf);
1314  if ( info->glyph_cnt==0 && info->glyph_length==0 && info->loca_length<=4 &&
1315  info->cff_length==0 && info->typ1_start==0 ) {
1316  /* X11 OpenType bitmap format */;
1317  info->onlystrikes = true;
1318  } else if ( cnt!=info->glyph_cnt && info->loca_length!=0 ) {
1319  ff_post_notice(_("Bad Glyph Count"), _("Font file has bad glyph count field. maxp says: %d sizeof(loca)=>%d"), cnt, info->glyph_cnt);
1320  info->bad_glyph_data = true;
1321  if ( cnt>info->glyph_cnt )
1322  cnt = info->glyph_cnt; /* Use the smaller of the two values */
1323  }
1324  /* Open Type fonts have no loca table, so we can't calculate the glyph */
1325  /* count from it */
1326  info->glyph_cnt = cnt;
1327  if ( cnt<0 ) info->glyph_cnt = 0;
1328 }
1329 
1330 static char *stripspaces(char *str) {
1331  char *str2 = str, *base = str;
1332 
1333  if ( str==NULL )
1334 return( NULL );
1335 
1336  while ( *str ) {
1337  if ( *str==' ' )
1338  ++str;
1339  else
1340  *str2++ = *str++;
1341  }
1342  *str2 = '\0';
1343 return( base );
1344 }
1345 
1346 static void ValidatePostScriptFontName(struct ttfinfo *info, char *str) {
1347  char *end, *pt, *npt;
1348  int complained = false;
1349 
1350  /* someone gave me a font where the fontname started with the utf8 byte */
1351  /* order mark. PLRM says only ASCII encoding is supported. CFF says */
1352  /* only printable ASCII should be used */
1353  if ( ((uint8 *) str)[0] == 0xef && ((uint8 *) str)[1]==0xbb && ((uint8 *) str)[2] == 0xbf ) {
1354  LogError(_("The fontname begins with the utf8 byte order sequence. This is illegal. %s"), str+3 );
1355  info->bad_ps_fontname = true;
1356  for ( pt=str+3; *pt; ++pt )
1357  pt[-3] = *pt; /* ANSI says we can't strcpy overlapping strings */
1358  }
1359  strtod(str,&end);
1360  if ( (*end=='\0' || (isdigit(str[0]) && strchr(str,'#')!=NULL)) &&
1361  *str!='\0' ) {
1362  ff_post_error(_("Bad Font Name"),_("A Postscript name may not be a number"));
1363  info->bad_ps_fontname = true;
1364  *str = 'a';
1365  complained = true;
1366  }
1367  for ( pt=str; *pt; ++pt ) {
1368  if ( *pt<=' ' || *pt>=0x7f ||
1369  *pt=='(' || *pt=='[' || *pt=='{' || *pt=='<' ||
1370  *pt==')' || *pt==']' || *pt=='}' || *pt=='>' ||
1371  *pt=='%' || *pt=='/' ) {
1372  if ( !complained ) {
1373  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);
1374  info->bad_ps_fontname = true;
1375  }
1376  complained = true;
1377  for ( npt=pt; npt[1]; ++npt )
1378  *npt = npt[1];
1379  *npt = '\0';
1380  --pt;
1381  }
1382  }
1383  if ( strlen(str)>63 ) {
1384  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);
1385  info->bad_ps_fontname = true;
1386  str[63] = '\0';
1387  }
1388 }
1389 
1390 char *EnforcePostScriptName(char *old) {
1391  char *end, *pt, *npt, *str = copy(old);
1392 
1393  if ( old==NULL )
1394 return( old );
1395 
1396  strtod(str,&end);
1397  if ( (*end=='\0' || (isdigit(str[0]) && strchr(str,'#')!=NULL)) &&
1398  *str!='\0' ) {
1399  free(str);
1400  str=galloc(strlen(old)+2);
1401  *str = 'a';
1402  strcpy(str+1,old);
1403  }
1404  for ( pt=str; *pt; ++pt ) {
1405  if ( *pt<=' ' || *pt>=0x7f ||
1406  *pt=='(' || *pt=='[' || *pt=='{' || *pt=='<' ||
1407  *pt==')' || *pt==']' || *pt=='}' || *pt=='>' ||
1408  *pt=='%' || *pt=='/' ) {
1409  for ( npt=pt; npt[1]; ++npt )
1410  *npt = npt[1];
1411  *npt = '\0';
1412  }
1413  }
1414  if ( strlen(str)>63 )
1415  str[63] = '\0';
1416 return( str );
1417 }
1418 
1419 static int IsSubSetOf(const char *substr,const char *fullstr ) {
1420  /* The mac string is often a subset of the unicode string. Certain */
1421  /* characters can't be expressed in the mac encoding and are omitted */
1422  /* or turned to question marks or some such */
1423  const char *pt1, *pt2;
1424  uint32 ch1, ch2;
1425 
1426  for ( pt1=substr, pt2=fullstr, ch1=utf8_ildb(&pt1); ch1!=0 ; ) {
1427  if ( *pt2=='\0' )
1428  break;
1429  ch2 = utf8_ildb(&pt2);
1430  if ( ch1==ch2 )
1431  ch1 = utf8_ildb(&pt1);
1432  }
1433  if ( ch1=='\0' )
1434 return( true );
1435 
1436  for ( pt1=substr, pt2=fullstr, ch1=utf8_ildb(&pt1); ch1!=0 ; ) {
1437  if ( *pt2=='\0' )
1438  break;
1439  ch2 = utf8_ildb(&pt2);
1440  if ( ch1==ch2 || ch1=='?' )
1441  ch1 = utf8_ildb(&pt1);
1442  }
1443 return( ch1=='\0' );
1444 }
1445 
1446 static void TTFAddLangStr(FILE *ttf, struct ttfinfo *info, int id,
1447  int strlen, int stroff,int plat,int spec,int language) {
1448  struct ttflangname *cur, *prev;
1449  char *str;
1450 
1451  if ( id<0 || id>=ttf_namemax )
1452 return;
1453 
1454  str = _readencstring(ttf,stroff,strlen,plat,spec,language);
1455  if ( str==NULL ) /* we didn't understand the encoding */
1456 return;
1457  if ( id==ttf_postscriptname )
1459  if ( *str=='\0' ) {
1460  free(str);
1461 return;
1462  }
1463 
1464  if ( plat==1 || plat==0 )
1466  if ( (language&0xff00)==0 ) language |= 0x400;
1467 
1468  for ( prev=NULL, cur=info->names; cur!=NULL && cur->lang!=language; prev = cur, cur=cur->next );
1469  if ( cur==NULL ) {
1470  cur = chunkalloc(sizeof(struct ttflangname));
1471  cur->lang = language;
1472  if ( prev==NULL )
1473  info->names = cur;
1474  else
1475  prev->next = cur;
1476  }
1477  if ( cur->names[id]==NULL ) {
1478  cur->names[id] = str;
1479  if ( plat==1 || plat==0 )
1480  cur->frommac[id/32] |= (1<<(id&0x1f));
1481 /* There's some wacky bug in gcc. If the optimizer is on then strcmp gets turned */
1482 /* into some inline call. Which would be fine, except the following line goes */
1483 /* bluey. "Called object is not a function", etc. Compiles fine if we turn off */
1484 /* the inlining magic */
1485 #ifdef strcmp
1486 # undef strcmp
1487 #endif
1488  } else if ( strcmp(str,cur->names[id])==0 ) {
1489  free(str);
1490  if ( plat==3 )
1491  cur->frommac[id/32] &= ~(1<<(id&0x1f));
1492  } else if ( plat==1 ) {
1493  /* Mac string doesn't match mac unicode string */
1494  if ( !IsSubSetOf(str,cur->names[id]) )
1495  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  str,cur->names[id]);
1498  else
1499  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  free(str);
1502  } else if ( plat==3 && (cur->frommac[id/32] & (1<<(id&0x1f))) ) {
1503  if ( !IsSubSetOf(cur->names[id],str) )
1504  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  cur->names[id],str);
1507  else
1508  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  free(cur->names[id]);
1511  cur->names[id] = str;
1512  cur->frommac[id/32] &= ~(1<<(id&0x1f));
1513  } else {
1514  int ret;
1515  if ( info->dupnamestate!=0 )
1516  ret = info->dupnamestate;
1517  else
1518  ret = 3;
1519  if ( ret==0 || ret==1 )
1520  free(str);
1521  else {
1522  free(cur->names[id]);
1523  cur->names[id] = str;
1524  }
1525  }
1526 }
1527 
1528 static int is_ascii(char *str) { /* isascii is in ctype */
1529  if ( str==NULL )
1530 return( false );
1531  while ( *str && *str<127 && *str>=' ' )
1532  ++str;
1533 return( *str=='\0' );
1534 }
1535 
1536 static char *FindLangEntry(struct ttfinfo *info, int id ) {
1537  /* Look for an entry with string id */
1538  /* we prefer english, if we can't find english look for something in ascii */
1539  struct ttflangname *cur;
1540  char *ret;
1541 
1542  for ( cur=info->names; cur!=NULL && cur->lang!=0x409; cur=cur->next );
1543  if ( cur!=NULL && cur->names[id]==NULL ) cur = NULL;
1544  if ( cur==NULL )
1545  for ( cur=info->names; cur!=NULL && (cur->lang&0xf)!=0x09; cur=cur->next );
1546  if ( cur!=NULL && cur->names[id]==NULL ) cur = NULL;
1547  if ( cur==NULL )
1548  for ( cur=info->names; cur!=NULL && !is_ascii(cur->names[id]); cur=cur->next );
1549  if ( cur==NULL )
1550  for ( cur=info->names; cur!=NULL && cur->names[id]==NULL; cur=cur->next );
1551  if ( cur==NULL )
1552 return( NULL );
1553  ret = copy(cur->names[id]);
1554 return( ret );
1555 }
1556 
1557 struct otfname *FindAllLangEntries(FILE *ttf, struct ttfinfo *info, int id ) {
1558  /* Look for all entries with string id under windows platform */
1559  int32 here = ftell(ttf);
1560  int i, cnt, tableoff;
1561  int platform, specific, language, name, str_len, stroff;
1562  struct otfname *head=NULL, *cur;
1563 
1564  if ( info->copyright_start!=0 && id!=0 ) {
1565  fseek(ttf,info->copyright_start,SEEK_SET);
1566  /* format selector = */ getushort(ttf);
1567  cnt = getushort(ttf);
1568  tableoff = info->copyright_start+getushort(ttf);
1569  for ( i=0; i<cnt; ++i ) {
1570  platform = getushort(ttf);
1571  specific = getushort(ttf);
1572  language = getushort(ttf);
1573  name = getushort(ttf);
1574  str_len = getushort(ttf);
1575  stroff = getushort(ttf);
1576 
1577  if ( platform==3 && name==id ) {
1578  char *temp = _readencstring(ttf,tableoff+stroff,str_len,platform,specific,language);
1579  if ( temp!=NULL ) {
1580  cur = chunkalloc(sizeof(struct otfname));
1581  cur->next = head;
1582  head = cur;
1583  cur->lang = language;
1584  cur->name = temp;
1585  }
1586  }
1587  }
1588  fseek(ttf,here,SEEK_SET);
1589  }
1590 return( head );
1591 }
1592 
1593 static void readttfcopyrights(FILE *ttf,struct ttfinfo *info) {
1594  int i, cnt, tableoff;
1595  int platform, specific, language, name, str_len, stroff;
1596 
1597  if ( info->copyright_start!=0 ) {
1598  fseek(ttf,info->copyright_start,SEEK_SET);
1599  /* format selector = */ getushort(ttf);
1600  cnt = getushort(ttf);
1601  tableoff = info->copyright_start+getushort(ttf);
1602  for ( i=0; i<cnt; ++i ) {
1603  platform = getushort(ttf);
1604  specific = getushort(ttf);
1605  language = getushort(ttf);
1606  name = getushort(ttf);
1607  str_len = getushort(ttf);
1608  stroff = getushort(ttf);
1609 
1610  TTFAddLangStr(ttf,info,name,str_len,tableoff+stroff,
1611  platform,specific,language);
1612  }
1613  }
1614 
1615  if ( info->copyright==NULL )
1616  info->copyright = FindLangEntry(info,ttf_copyright);
1617  if ( info->familyname==NULL )
1618  info->familyname = FindLangEntry(info,ttf_family);
1619  if ( info->fullname==NULL )
1620  info->fullname = FindLangEntry(info,ttf_fullname);
1621  if ( info->version==NULL )
1622  info->version = FindLangEntry(info,ttf_version);
1623  if ( info->fontname==NULL )
1625 
1626  if ( info->fontname != NULL && *info->fontname=='\0' ) {
1627  free(info->fontname);
1628  info->fontname = NULL;
1629  }
1630  if ( info->familyname != NULL && *info->familyname=='\0' ) {
1631  free(info->familyname);
1632  info->familyname = NULL;
1633  }
1634  if ( info->fullname != NULL && *info->fullname=='\0' ) {
1635  free(info->fullname);
1636  info->fullname = NULL;
1637  }
1638 
1639  /* OpenType spec says the version string should begin with "Version " and */
1640  /* end with a space and have a number in between */
1641  if ( info->version==NULL ) info->version = copy("1.0");
1642  else if ( strnmatch(info->version,"Version ",8)==0 ) {
1643  char *temp = copy(info->version+8);
1644  if ( temp[strlen(temp)-1]==' ' )
1645  temp[strlen(temp)-1] = '\0';
1646  free(info->version);
1647  info->version = temp;
1648  }
1649  if ( info->fontname==NULL ) {
1650  if ( info->fullname!=NULL )
1651  info->fontname = stripspaces(copy(info->fullname));
1652  if ( info->fontname==NULL && info->familyname!=NULL )
1653  info->fontname = stripspaces(copy(info->familyname));
1654  if ( info->fontname!=NULL )
1656  }
1657 }
1658 
1659 static void readttfpreglyph(FILE *ttf,struct ttfinfo *info) {
1660  if ( info->head_start!=0 )
1661  readttfhead(ttf,info);
1662  if ( info->hhea_start!=0 )
1663  readttfhhea(ttf,info);
1664  if ( info->maxp_start!=0 )
1665  readttfmaxp(ttf,info);
1666  readttfcopyrights(ttf,info); /* This one has internal checks */
1667 }
1668 
1669 #define _On_Curve 1
1670 #define _X_Short 2
1671 #define _Y_Short 4
1672 #define _Repeat 8
1673 #define _X_Same 0x10
1674 #define _Y_Same 0x20
1675 
1677  int is_order2) {
1678  /* What are the control points for 2 cp bezier which will provide the same*/
1679  /* curve as that for the 1 cp bezier specified above */
1680  real b, c, d;
1681 
1682  if ( is_order2 ) {
1683  from->nextcp = to->prevcp = *cp;
1684  if ( cp->x==to->me.x && cp->y==to->me.y ) {
1685  /* I would lose track of the proper location of this cp if I left */
1686  /* it here (would end up with from->nonextcp, which would mean I'd*/
1687  /* use from->me rather than to->me in tottf.c:SSAddPoints. So we */
1688  /* distort it a little */
1689  BasePoint off;
1690  double len;
1691  off.x = from->me.x-to->me.x; off.y = from->me.y-to->me.y;
1692  len = sqrt(off.x*off.x+off.y*off.y);
1693  if ( len>3 ) {
1694  /* move the cp slightly toward from, but on the line between the two */
1695  from->nextcp.x = (to->prevcp.x += rint(off.x/len));
1696  from->nextcp.y = (to->prevcp.y += rint(off.y/len));
1697  }
1698  }
1699  } else {
1700  d = from->me.x;
1701  c = 2*cp->x - 2*from->me.x;
1702  b = to->me.x+from->me.x-2*cp->x;
1703  from->nextcp.x = d+c/3;
1704  to->prevcp.x = from->nextcp.x + (c+b)/3;
1705 
1706  d = from->me.y;
1707  c = 2*cp->y - 2*from->me.y;
1708  b = to->me.y+from->me.y-2*cp->y;
1709  from->nextcp.y = d+c/3;
1710  to->prevcp.y = from->nextcp.y + (c+b)/3;
1711  }
1712 
1713  if ( from->me.x!=from->nextcp.x || from->me.y!=from->nextcp.y )
1714  from->nonextcp = false;
1715  if ( to->me.x!=to->prevcp.x || to->me.y!=to->prevcp.y )
1716  to->noprevcp = false;
1717  if ( is_order2 && (to->noprevcp || from->nonextcp)) {
1718  to->noprevcp = from->nonextcp = true;
1719  from->nextcp = from->me;
1720  to->prevcp = to->me;
1721  }
1722 }
1723 
1724 static SplineSet *ttfbuildcontours(int path_cnt,uint16 *endpt, char *flags,
1725  BasePoint *pts, int is_order2) {
1726  SplineSet *head=NULL, *last=NULL, *cur;
1727  int i, path, start, last_off;
1728  SplinePoint *sp;
1729 
1730  for ( path=i=0; path<path_cnt; ++path ) {
1731  if ( endpt[path]<i ) /* Sigh. Yes there are fonts with bad endpt info */
1732  continue;
1733  cur = chunkalloc(sizeof(SplineSet));
1734  if ( head==NULL )
1735  head = cur;
1736  else
1737  last->next = cur;
1738  last = cur;
1739  last_off = false;
1740  start = i;
1741  sp = NULL;
1742  while ( i<=endpt[path] ) {
1743  if ( flags[i]&_On_Curve ) {
1744  sp = chunkalloc(sizeof(SplinePoint));
1745  sp->me = sp->nextcp = sp->prevcp = pts[i];
1746  sp->nonextcp = sp->noprevcp = true;
1747  sp->ttfindex = i;
1748  sp->nextcpindex = 0xffff;
1749  if ( last_off && cur->last!=NULL )
1750  FigureControls(cur->last,sp,&pts[i-1],is_order2);
1751  last_off = false;
1752  } else if ( last_off ) {
1753  /* two off curve points get a third on curve point created */
1754  /* half-way between them. Now isn't that special */
1755  sp = chunkalloc(sizeof(SplinePoint));
1756  sp->me.x = (pts[i].x+pts[i-1].x)/2;
1757  sp->me.y = (pts[i].y+pts[i-1].y)/2;
1758  sp->nextcp = sp->prevcp = sp->me;
1759  sp->nonextcp = true;
1760  sp->ttfindex = 0xffff;
1761  sp->nextcpindex = i;
1762  if ( last_off && cur->last!=NULL )
1763  FigureControls(cur->last,sp,&pts[i-1],is_order2);
1764  /* last_off continues to be true */
1765  } else {
1766  if ( cur->first!=NULL )
1767  cur->last->nextcpindex = i;
1768  last_off = true;
1769  sp = NULL;
1770  }
1771  if ( sp!=NULL ) {
1772  if ( cur->first==NULL )
1773  cur->first = sp;
1774  else
1775  SplineMake(cur->last,sp,is_order2);
1776  cur->last = sp;
1777  }
1778  ++i;
1779  }
1780  if ( start==i-1 ) {
1781  /* MS chinese fonts have contours consisting of a single off curve*/
1782  /* point. What on earth do they think that means? */
1783  /* Oh. I see. It's used to possition marks and such */
1784  if ( cur->first==NULL ) {
1785  sp = chunkalloc(sizeof(SplinePoint));
1786  sp->me.x = pts[start].x;
1787  sp->me.y = pts[start].y;
1788  sp->nextcp = sp->prevcp = sp->me;
1789  sp->nonextcp = sp->noprevcp = true;
1790  sp->ttfindex = i-1;
1791  sp->nextcpindex = 0xffff;
1792  cur->first = cur->last = sp;
1793  }
1794  } else if ( !(flags[start]&_On_Curve) && !(flags[i-1]&_On_Curve) ) {
1795  sp = chunkalloc(sizeof(SplinePoint));
1796  sp->me.x = (pts[start].x+pts[i-1].x)/2;
1797  sp->me.y = (pts[start].y+pts[i-1].y)/2;
1798  sp->nextcp = sp->prevcp = sp->me;
1799  sp->nonextcp = true;
1800  sp->ttfindex = 0xffff;
1801  sp->nextcpindex = start;
1802  FigureControls(cur->last,sp,&pts[i-1],is_order2);
1803  SplineMake(cur->last,sp,is_order2);
1804  cur->last = sp;
1805  FigureControls(sp,cur->first,&pts[start],is_order2);
1806  } else if ( !(flags[i-1]&_On_Curve)) {
1807  FigureControls(cur->last,cur->first,&pts[i-1],is_order2);
1808  cur->last->nextcpindex = i-1;
1809  } else if ( !(flags[start]&_On_Curve) ) {
1810  FigureControls(cur->last,cur->first,&pts[start],is_order2);
1811  sp->nextcpindex = start;
1812  }
1813  if ( cur->last!=cur->first ) {
1814  SplineMake(cur->last,cur->first,is_order2);
1815  cur->last = cur->first;
1816  }
1817  for ( sp=cur->first; ; ) {
1818  /*if ( sp->ttfindex!=0xffff && SPInterpolate(sp) )
1819  sp->dontinterpolate = true;*/ /* TODO: needs checking */
1820  if ( sp->next==NULL )
1821  break;
1822  sp=sp->next->to;
1823  if ( sp==cur->first )
1824  break;
1825  }
1826  }
1827 return( head );
1828 }
1829 
1830 static void readttfsimpleglyph(FILE *ttf,struct ttfinfo *info,SplineChar *sc, int path_cnt) {
1831  uint16 *endpt = galloc((path_cnt+1)*sizeof(uint16));
1832  uint8 *instructions;
1833  char *flags;
1834  BasePoint *pts;
1835  int i, j, tot, len;
1836  int last_pos;
1837 
1838  for ( i=0; i<path_cnt; ++i ) {
1839  endpt[i] = getushort(ttf);
1840  if ( i!=0 && endpt[i]<endpt[i-1] ) {
1841  info->bad_glyph_data = true;
1842  LogError( _("Bad tt font: contour ends make no sense in glyph %d.\n"),
1843  sc->orig_pos );
1844 return;
1845  }
1846  }
1847  if ( path_cnt==0 ) {
1848  tot = 0;
1849  pts = galloc(sizeof(BasePoint));
1850  } else {
1851  tot = endpt[path_cnt-1]+1;
1852  pts = galloc(tot*sizeof(BasePoint));
1853  }
1854 
1855  len = getushort(ttf);
1856  instructions = galloc(len);
1857  for ( i=0; i<len; ++i )
1858  instructions[i] = getc(ttf);
1859 
1860  flags = galloc(tot);
1861  for ( i=0; i<tot; ++i ) {
1862  flags[i] = getc(ttf);
1863  if ( flags[i]&_Repeat ) {
1864  int cnt = getc(ttf);
1865  if ( i+cnt>=tot ) {
1866  IError("Flag count is wrong (or total is): %d %d", i+cnt, tot );
1867  cnt = tot-i-1;
1868  }
1869  for ( j=0; j<cnt; ++j )
1870  flags[i+j+1] = flags[i];
1871  i += cnt;
1872  }
1873  if ( feof(ttf))
1874  break;
1875  }
1876  if ( i!=tot )
1877  IError("Flag count is wrong (or total is): %d %d in glyph %d", i, tot, sc->orig_pos );
1878 
1879  last_pos = 0;
1880  for ( i=0; i<tot; ++i ) {
1881  if ( flags[i]&_X_Short ) {
1882  int off = getc(ttf);
1883  if ( !(flags[i]&_X_Same ) )
1884  off = -off;
1885  pts[i].x = last_pos + off;
1886  } else if ( flags[i]&_X_Same )
1887  pts[i].x = last_pos;
1888  else
1889  pts[i].x = last_pos + (short) getushort(ttf);
1890  last_pos = pts[i].x;
1891  }
1892 
1893  last_pos = 0;
1894  for ( i=0; i<tot; ++i ) {
1895  if ( flags[i]&_Y_Short ) {
1896  int off = getc(ttf);
1897  if ( !(flags[i]&_Y_Same ) )
1898  off = -off;
1899  pts[i].y = last_pos + off;
1900  } else if ( flags[i]&_Y_Same )
1901  pts[i].y = last_pos;
1902  else
1903  pts[i].y = last_pos + (short) getushort(ttf);
1904  last_pos = pts[i].y;
1905  }
1906 
1907  sc->layers[ly_fore].splines = ttfbuildcontours(path_cnt,endpt,flags,pts,info->to_order2);
1908  if ( info->to_order2 && len!=0 ) {
1909  sc->ttf_instrs_len = len;
1910  sc->ttf_instrs = instructions;
1911  } else
1912  free(instructions);
1914  free(endpt);
1915  free(flags);
1916  free(pts);
1917  if ( feof(ttf)) {
1918  LogError( _("Reached end of file when reading simple glyph\n") );
1919  info->bad_glyph_data = true;
1920  }
1921 }
1922 
1924  RefChar *head=NULL, *last=NULL, *cur=NULL;
1925  int flags=0, arg1, arg2;
1926  int use_my_metrics=0;
1927 
1928  if ( ftell(ttf)>=end ) {
1929  LogError( _("Empty composite %d\n"), sc->orig_pos );
1930  info->bad_glyph_data = true;
1931 return;
1932  }
1933 
1934  do {
1935  if ( ftell(ttf)>=end ) {
1936  LogError( _("Bad flags value, implied MORE components at end of glyph %d\n"), sc->orig_pos );
1937  info->bad_glyph_data = true;
1938  break;
1939  }
1940  cur = RefCharCreate();
1941  flags = getushort(ttf);
1942  cur->orig_pos = getushort(ttf);
1943  if ( feof(ttf) || cur->orig_pos>=info->glyph_cnt ) {
1944  LogError(_("Reference to glyph %d out of bounds when parsing 'glyf' table.\n"), cur->orig_pos );
1945  info->bad_glyph_data = true;
1946  cur->orig_pos = 0;
1947  }
1948  if ( info->inuse!=NULL )
1949  info->inuse[cur->orig_pos] = true;
1950  if ( flags&_ARGS_ARE_WORDS ) {
1951  arg1 = (short) getushort(ttf);
1952  arg2 = (short) getushort(ttf);
1953  } else {
1954  arg1 = (signed char) getc(ttf);
1955  arg2 = (signed char) getc(ttf);
1956  }
1957  cur->use_my_metrics = (flags & _USE_MY_METRICS) ? 1 : 0;
1958  if ( cur->use_my_metrics ) {
1959  if ( use_my_metrics ) {
1960  LogError( _("Use-my-metrics flag set on at least two components in glyph %d\n"), sc->orig_pos );
1961  info->bad_glyph_data = true;
1962  } else
1963  use_my_metrics = true;
1964  }
1965  cur->round_translation_to_grid = (flags & _ROUND) ? 1 : 0;
1966  if ( flags & _ARGS_ARE_XY ) {
1967  /* There is some very strange stuff (half-)documented on the apple*/
1968  /* site about how these should be interpretted when there are */
1969  /* scale factors, or rotations */
1970  /* It isn't well enough described to be comprehensible */
1971  /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
1972  /* Microsoft says nothing about this */
1973  /* Adobe implies this is a difference between MS and Apple */
1974  /* MS doesn't do this, Apple does (GRRRGH!!!!) */
1975  /* Adobe says that setting bit 12 means that this will not happen */
1976  /* Adobe says that setting bit 11 means that this will happen */
1977  /* So if either bit is set we know when this happens, if neither */
1978  /* we guess... But I still don't know how to interpret the */
1979  /* apple mode under rotation... */
1980  /* I notice that FreeType does nothing about rotation nor does it */
1981  /* interpret bits 11&12 */
1982  /* Ah. It turns out that even Apple does not do what Apple's docs */
1983  /* claim it does. I think I've worked it out (see below), but... */
1984  /* Bleah! */
1985  cur->transform[4] = arg1;
1986  cur->transform[5] = arg2;
1987  } else {
1988  /* Somehow we can get offsets by looking at the points in the */
1989  /* points so far generated and comparing them to the points in */
1990  /* the current componant */
1991  /* How exactly is not described on any of the Apple, MS, Adobe */
1992  /* freetype looks up arg1 in the set of points we've got so far */
1993  /* looks up arg2 in the new component (before renumbering) */
1994  /* offset.x = arg1.x - arg2.x; offset.y = arg1.y - arg2.y; */
1995  /* This fixup needs to be done later though (after all glyphs */
1996  /* have been loaded) */
1997  cur->match_pt_base = arg1;
1998  cur->match_pt_ref = arg2;
1999  cur->point_match = true;
2000  }
2001  cur->transform[0] = cur->transform[3] = 1.0;
2002  if ( flags & _SCALE )
2003  cur->transform[0] = cur->transform[3] = get2dot14(ttf);
2004  else if ( flags & _XY_SCALE ) {
2005  cur->transform[0] = get2dot14(ttf);
2006  cur->transform[3] = get2dot14(ttf);
2007  } else if ( flags & _MATRIX ) {
2008  cur->transform[0] = get2dot14(ttf);
2009  cur->transform[1] = get2dot14(ttf);
2010  cur->transform[2] = get2dot14(ttf);
2011  cur->transform[3] = get2dot14(ttf);
2012  }
2013  if ( flags & _ARGS_ARE_XY ) { /* Only muck with these guys if they are real offsets and not point matching */
2014 #ifdef __Mac
2015  /* On mac assume scaled offsets unless told unscaled explicitly */
2016  if ( !(flags&_UNSCALED_OFFSETS) &&
2017 #else
2018  /* everywhere else assume unscaled offsets unless told scaled explicitly */
2019  if ( (flags & _SCALED_OFFSETS) &&
2020 #endif
2022  /*static int asked = 0;*/
2023  /* This is not what Apple documents on their website. But it is */
2024  /* what appears to match the behavior of their rasterizer */
2025  /* Apple has changed their documentation (without updating their */
2026  /* changelog), but I believe they are still incorrect */
2027  cur->transform[4] *= sqrt(cur->transform[0]*cur->transform[0]+
2028  cur->transform[1]*cur->transform[1]);
2029  cur->transform[5] *= sqrt(cur->transform[2]*cur->transform[2]+
2030  cur->transform[3]*cur->transform[3]);
2031 #if 0
2032  /* Apple's Chicago is an example */
2033  if ( info->fontname!=NULL && strcmp(info->fontname,"CompositeMac")!=0 && !asked ) {
2034  /* Not interested in the test font I generated myself */
2035  asked = true;
2036  fprintf( stderr, "Neat! You've got a font that actually uses Apple's scaled composite offsets.\n" );
2037  fprintf( stderr, " I've never seen one, could you send me a copy of %s?\n", info->fontname );
2038  fprintf( stderr, " Thanks. gww@silcom.com\n" );
2039  }
2040 #endif
2041  }
2042  }
2043  if ( cur->orig_pos>=info->glyph_cnt ) {
2044  LogError(_("Glyph %d attempts to reference glyph %d which is outside the font\n"), sc->orig_pos, cur->orig_pos );
2045  chunkfree(cur,sizeof(*cur));
2046  } else {
2047  if ( head==NULL )
2048  head = cur;
2049  else
2050  last->next = cur;
2051  last = cur;
2052  }
2053  if ( feof(ttf)) {
2054  LogError(_("Reached end of file when reading composit glyph\n") );
2055  info->bad_glyph_data = true;
2056  break;
2057  }
2058  } while ( flags&_MORE );
2059  if ( (flags & _INSTR ) && info->to_order2 && ftell(ttf)<end ) {
2060  sc->ttf_instrs_len = getushort(ttf);
2061  if ( sc->ttf_instrs_len > 0 && ftell(ttf)+sc->ttf_instrs_len<=end ) {
2062  uint8 *instructions = galloc(sc->ttf_instrs_len);
2063  int i;
2064  for ( i=0; i<sc->ttf_instrs_len; ++i )
2065  instructions[i] = getc(ttf);
2066  sc->ttf_instrs = instructions;
2067  } else
2068  sc->ttf_instrs_len = 0;
2069  }
2070  sc->layers[ly_fore].refs = head;
2071 }
2072 
2073 static SplineChar *readttfglyph(FILE *ttf,struct ttfinfo *info,int start, int end,int gid) {
2074  int path_cnt;
2076 
2077  sc->unicodeenc = -1;
2078  sc->vwidth = info->emsize;
2079  sc->orig_pos = gid;
2080 
2081  if ( end>(int)info->glyph_length ) {
2082  if ( !info->complainedbeyondglyfend )
2083  LogError(_("Bad glyph (%d), its definition extends beyond the end of the glyf table\n"), gid );
2084  info->bad_glyph_data = true;
2085  info->complainedbeyondglyfend = true;
2086  SplineCharFree(sc);
2087 return( NULL );
2088  } else if ( end<start ) {
2089  LogError(_("Bad glyph (%d), its data length is negative\n"), gid );
2090  SplineCharFree(sc);
2091 return( NULL );
2092  }
2093 
2094  if ( start==end ) {
2095  /* This isn't mentioned, but we seem to get some glyphs with no size,*/
2096  /* not even a path cnt. They appear to be empty glyphs */
2097 return( sc );
2098  }
2099  fseek(ttf,info->glyph_start+start,SEEK_SET);
2100  path_cnt = (short) getushort(ttf);
2101 
2102 #ifdef LUA_FF_LIB
2103  sc->xmin = getushort(ttf);
2104  sc->ymin = getushort(ttf);
2105  sc->xmax = getushort(ttf);
2106  sc->ymax = getushort(ttf);
2107  sc->lsidebearing = sc->xmin;
2108 #endif
2109  if (THread_ttf_glyph_data) {
2110  if ( path_cnt>=0 )
2111  readttfsimpleglyph(ttf,info,sc,path_cnt);
2112  else
2113  readttfcompositglyph(ttf,info,sc,info->glyph_start+end);
2114  if ( start>end ) {
2115  LogError(_("Bad glyph (%d), disordered 'loca' table (start comes after end)\n"), gid );
2116  info->bad_glyph_data = true;
2117  } else if ( ftell(ttf)>(long)(info->glyph_start+end) ) {
2118  LogError(_("Bad glyph (%d), its definition extends beyond the space allowed for it\n"), gid );
2119  info->bad_glyph_data = true;
2120  }
2121 
2122  /* find the bb */
2123  THPatchSplineChar(sc);
2124  }
2125 
2126 return( sc );
2127 }
2128 
2129 static void readttfencodings(FILE *ttf,struct ttfinfo *info, int justinuse);
2130 
2131 static void readttfglyphs(FILE *ttf,struct ttfinfo *info) {
2132  int i, anyread;
2133  uint32 *goffsets = galloc((info->glyph_cnt+1)*sizeof(uint32));
2134 
2135  /* First we read all the locations. This might not be needed, they may */
2136  /* just follow one another, but nothing I've noticed says that so let's */
2137  /* be careful */
2138  fseek(ttf,info->glyphlocations_start,SEEK_SET);
2139  if ( info->index_to_loc_is_long ) {
2140  for ( i=0; i<=info->glyph_cnt ; ++i )
2141  goffsets[i] = getlong(ttf);
2142  } else {
2143  for ( i=0; i<=info->glyph_cnt ; ++i )
2144  goffsets[i] = 2*getushort(ttf);
2145  }
2146 
2147  info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
2148  if ( !info->is_ttc || (info->openflags&of_all_glyphs_in_ttc)) {
2149  /* read all the glyphs */
2150  for ( i=0; i<info->glyph_cnt ; ++i ) {
2151  info->chars[i] = readttfglyph(ttf,info,goffsets[i],goffsets[i+1],i);
2152  ff_progress_next();
2153  }
2154  } else {
2155  /* only read the glyphs we actually use in this font */
2156  /* this is complicated by references (and substitutions), */
2157  /* we can't just rely on the encoding to tell us what is used */
2158  info->inuse = gcalloc(info->glyph_cnt,sizeof(char));
2160  if ( info->gsub_start!=0 ) /* Some glyphs may appear in substitutions and not in the encoding... */
2161  readttfgsubUsed(ttf,info);
2162  if ( info->math_start!=0 )
2163  otf_read_math_used(ttf,info);
2164  /* I don't bother to read the morx table because mac doesn't */
2165  /* support ttc files */
2166  anyread = true;
2167  while ( anyread ) {
2168  anyread = false;
2169  for ( i=0; i<info->glyph_cnt ; ++i ) {
2170  if ( info->inuse[i] && info->chars[i]==NULL ) {
2171  info->chars[i] = readttfglyph(ttf,info,goffsets[i],goffsets[i+1],i);
2172  ff_progress_next();
2173  anyread = info->chars[i]!=NULL;
2174  }
2175  }
2176  }
2177  free(info->inuse); info->inuse = NULL;
2178  }
2179  free(goffsets);
2180  for ( i=0; i<info->glyph_cnt ; ++i )
2181  if ( info->chars[i]!=NULL )
2182  info->chars[i]->orig_pos = i;
2184 }
2185 
2186 /* Standard names for cff */
2187 const char *cffnames[] = {
2188  ".notdef",
2189  "space",
2190  "exclam",
2191  "quotedbl",
2192  "numbersign",
2193  "dollar",
2194  "percent",
2195  "ampersand",
2196  "quoteright",
2197  "parenleft",
2198  "parenright",
2199  "asterisk",
2200  "plus",
2201  "comma",
2202  "hyphen",
2203  "period",
2204  "slash",
2205  "zero",
2206  "one",
2207  "two",
2208  "three",
2209  "four",
2210  "five",
2211  "six",
2212  "seven",
2213  "eight",
2214  "nine",
2215  "colon",
2216  "semicolon",
2217  "less",
2218  "equal",
2219  "greater",
2220  "question",
2221  "at",
2222  "A",
2223  "B",
2224  "C",
2225  "D",
2226  "E",
2227  "F",
2228  "G",
2229  "H",
2230  "I",
2231  "J",
2232  "K",
2233  "L",
2234  "M",
2235  "N",
2236  "O",
2237  "P",
2238  "Q",
2239  "R",
2240  "S",
2241  "T",
2242  "U",
2243  "V",
2244  "W",
2245  "X",
2246  "Y",
2247  "Z",
2248  "bracketleft",
2249  "backslash",
2250  "bracketright",
2251  "asciicircum",
2252  "underscore",
2253  "quoteleft",
2254  "a",
2255  "b",
2256  "c",
2257  "d",
2258  "e",
2259  "f",
2260  "g",
2261  "h",
2262  "i",
2263  "j",
2264  "k",
2265  "l",
2266  "m",
2267  "n",
2268  "o",
2269  "p",
2270  "q",
2271  "r",
2272  "s",
2273  "t",
2274  "u",
2275  "v",
2276  "w",
2277  "x",
2278  "y",
2279  "z",
2280  "braceleft",
2281  "bar",
2282  "braceright",
2283  "asciitilde",
2284  "exclamdown",
2285  "cent",
2286  "sterling",
2287  "fraction",
2288  "yen",
2289  "florin",
2290  "section",
2291  "currency",
2292  "quotesingle",
2293  "quotedblleft",
2294  "guillemotleft",
2295  "guilsinglleft",
2296  "guilsinglright",
2297  "fi",
2298  "fl",
2299  "endash",
2300  "dagger",
2301  "daggerdbl",
2302  "periodcentered",
2303  "paragraph",
2304  "bullet",
2305  "quotesinglbase",
2306  "quotedblbase",
2307  "quotedblright",
2308  "guillemotright",
2309  "ellipsis",
2310  "perthousand",
2311  "questiondown",
2312  "grave",
2313  "acute",
2314  "circumflex",
2315  "tilde",
2316  "macron",
2317  "breve",
2318  "dotaccent",
2319  "dieresis",
2320  "ring",
2321  "cedilla",
2322  "hungarumlaut",
2323  "ogonek",
2324  "caron",
2325  "emdash",
2326  "AE",
2327  "ordfeminine",
2328  "Lslash",
2329  "Oslash",
2330  "OE",
2331  "ordmasculine",
2332  "ae",
2333  "dotlessi",
2334  "lslash",
2335  "oslash",
2336  "oe",
2337  "germandbls",
2338  "onesuperior",
2339  "logicalnot",
2340  "mu",
2341  "trademark",
2342  "Eth",
2343  "onehalf",
2344  "plusminus",
2345  "Thorn",
2346  "onequarter",
2347  "divide",
2348  "brokenbar",
2349  "degree",
2350  "thorn",
2351  "threequarters",
2352  "twosuperior",
2353  "registered",
2354  "minus",
2355  "eth",
2356  "multiply",
2357  "threesuperior",
2358  "copyright",
2359  "Aacute",
2360  "Acircumflex",
2361  "Adieresis",
2362  "Agrave",
2363  "Aring",
2364  "Atilde",
2365  "Ccedilla",
2366  "Eacute",
2367  "Ecircumflex",
2368  "Edieresis",
2369  "Egrave",
2370  "Iacute",
2371  "Icircumflex",
2372  "Idieresis",
2373  "Igrave",
2374  "Ntilde",
2375  "Oacute",
2376  "Ocircumflex",
2377  "Odieresis",
2378  "Ograve",
2379  "Otilde",
2380  "Scaron",
2381  "Uacute",
2382  "Ucircumflex",
2383  "Udieresis",
2384  "Ugrave",
2385  "Yacute",
2386  "Ydieresis",
2387  "Zcaron",
2388  "aacute",
2389  "acircumflex",
2390  "adieresis",
2391  "agrave",
2392  "aring",
2393  "atilde",
2394  "ccedilla",
2395  "eacute",
2396  "ecircumflex",
2397  "edieresis",
2398  "egrave",
2399  "iacute",
2400  "icircumflex",
2401  "idieresis",
2402  "igrave",
2403  "ntilde",
2404  "oacute",
2405  "ocircumflex",
2406  "odieresis",
2407  "ograve",
2408  "otilde",
2409  "scaron",
2410  "uacute",
2411  "ucircumflex",
2412  "udieresis",
2413  "ugrave",
2414  "yacute",
2415  "ydieresis",
2416  "zcaron",
2417  "exclamsmall",
2418  "Hungarumlautsmall",
2419  "dollaroldstyle",
2420  "dollarsuperior",
2421  "ampersandsmall",
2422  "Acutesmall",
2423  "parenleftsuperior",
2424  "parenrightsuperior",
2425  "twodotenleader",
2426  "onedotenleader",
2427  "zerooldstyle",
2428  "oneoldstyle",
2429  "twooldstyle",
2430  "threeoldstyle",
2431  "fouroldstyle",
2432  "fiveoldstyle",
2433  "sixoldstyle",
2434  "sevenoldstyle",
2435  "eightoldstyle",
2436  "nineoldstyle",
2437  "commasuperior",
2438  "threequartersemdash",
2439  "periodsuperior",
2440  "questionsmall",
2441  "asuperior",
2442  "bsuperior",
2443  "centsuperior",
2444  "dsuperior",
2445  "esuperior",
2446  "isuperior",
2447  "lsuperior",
2448  "msuperior",
2449  "nsuperior",
2450  "osuperior",
2451  "rsuperior",
2452  "ssuperior",
2453  "tsuperior",
2454  "ff",
2455  "ffi",
2456  "ffl",
2457  "parenleftinferior",
2458  "parenrightinferior",
2459  "Circumflexsmall",
2460  "hyphensuperior",
2461  "Gravesmall",
2462  "Asmall",
2463  "Bsmall",
2464  "Csmall",
2465  "Dsmall",
2466  "Esmall",
2467  "Fsmall",
2468  "Gsmall",
2469  "Hsmall",
2470  "Ismall",
2471  "Jsmall",
2472  "Ksmall",
2473  "Lsmall",
2474  "Msmall",
2475  "Nsmall",
2476  "Osmall",
2477  "Psmall",
2478  "Qsmall",
2479  "Rsmall",
2480  "Ssmall",
2481  "Tsmall",
2482  "Usmall",
2483  "Vsmall",
2484  "Wsmall",
2485  "Xsmall",
2486  "Ysmall",
2487  "Zsmall",
2488  "colonmonetary",
2489  "onefitted",
2490  "rupiah",
2491  "Tildesmall",
2492  "exclamdownsmall",
2493  "centoldstyle",
2494  "Lslashsmall",
2495  "Scaronsmall",
2496  "Zcaronsmall",
2497  "Dieresissmall",
2498  "Brevesmall",
2499  "Caronsmall",
2500  "Dotaccentsmall",
2501  "Macronsmall",
2502  "figuredash",
2503  "hypheninferior",
2504  "Ogoneksmall",
2505  "Ringsmall",
2506  "Cedillasmall",
2507  "questiondownsmall",
2508  "oneeighth",
2509  "threeeighths",
2510  "fiveeighths",
2511  "seveneighths",
2512  "onethird",
2513  "twothirds",
2514  "zerosuperior",
2515  "foursuperior",
2516  "fivesuperior",
2517  "sixsuperior",
2518  "sevensuperior",
2519  "eightsuperior",
2520  "ninesuperior",
2521  "zeroinferior",
2522  "oneinferior",
2523  "twoinferior",
2524  "threeinferior",
2525  "fourinferior",
2526  "fiveinferior",
2527  "sixinferior",
2528  "seveninferior",
2529  "eightinferior",
2530  "nineinferior",
2531  "centinferior",
2532  "dollarinferior",
2533  "periodinferior",
2534  "commainferior",
2535  "Agravesmall",
2536  "Aacutesmall",
2537  "Acircumflexsmall",
2538  "Atildesmall",
2539  "Adieresissmall",
2540  "Aringsmall",
2541  "AEsmall",
2542  "Ccedillasmall",
2543  "Egravesmall",
2544  "Eacutesmall",
2545  "Ecircumflexsmall",
2546  "Edieresissmall",
2547  "Igravesmall",
2548  "Iacutesmall",
2549  "Icircumflexsmall",
2550  "Idieresissmall",
2551  "Ethsmall",
2552  "Ntildesmall",
2553  "Ogravesmall",
2554  "Oacutesmall",
2555  "Ocircumflexsmall",
2556  "Otildesmall",
2557  "Odieresissmall",
2558  "OEsmall",
2559  "Oslashsmall",
2560  "Ugravesmall",
2561  "Uacutesmall",
2562  "Ucircumflexsmall",
2563  "Udieresissmall",
2564  "Yacutesmall",
2565  "Thornsmall",
2566  "Ydieresissmall",
2567  "001.000",
2568  "001.001",
2569  "001.002",
2570  "001.003",
2571  "Black",
2572  "Bold",
2573  "Book",
2574  "Light",
2575  "Medium",
2576  "Regular",
2577  "Roman",
2578  "Semibold",
2579  NULL
2580 };
2581 const int nStdStrings = sizeof(cffnames)/sizeof(cffnames[0])-1;
2582 
2583 static char **readcfffontnames(FILE *ttf,int *cnt,struct ttfinfo *info) {
2584  uint16 count = getushort(ttf);
2585  int offsize;
2586  uint32 *offsets;
2587  char **names;
2588  int i,j;
2589 
2590  if ( cnt!=NULL ) *cnt = count;
2591 
2592  if ( count==0 )
2593 return( NULL );
2594  offsets = galloc((count+1)*sizeof(uint32));
2595  offsize = getc(ttf);
2596  for ( i=0; i<=count; ++i )
2597  offsets[i] = getoffset(ttf,offsize);
2598  names = galloc((count+1)*sizeof(char *));
2599  for ( i=0; i<count; ++i ) {
2600  if ( offsets[i+1]<offsets[i] ) {
2601 /* GT: The CFF font type contains a thing called a name INDEX, and that INDEX */
2602 /* GT: is bad. It is an index of many of the names used in the CFF font. */
2603 /* GT: We hope the user will never see this. */
2604  LogError( _("Bad CFF name INDEX\n") );
2605  if ( info!=NULL ) info->bad_cff = true;
2606  while ( i<count ) {
2607  names[i] = copy("");
2608  ++i;
2609  }
2610  --i;
2611  } else {
2612  names[i] = galloc(offsets[i+1]-offsets[i]+1);
2613  for ( j=0; j<(int)(offsets[i+1]-offsets[i]); ++j )
2614  names[i][j] = getc(ttf);
2615  names[i][j] = '\0';
2616  }
2617  }
2618  names[i] = NULL;
2619  free(offsets);
2620 return( names );
2621 }
2622 
2623 static char *addnibble(char *pt, int nib) {
2624  if ( nib<=9 )
2625  *pt++ = nib+'0';
2626  else if ( nib==10 )
2627  *pt++ = '.';
2628  else if ( nib==11 )
2629  *pt++ = 'E';
2630  else if ( nib==12 ) {
2631  *pt++ = 'E';
2632  *pt++ = '-';
2633  } else if ( nib==14 )
2634  *pt++ = '-';
2635  else if ( nib==15 )
2636  *pt++ = '\0';
2637 return( pt );
2638 }
2639 
2640 static int readcffthing(FILE *ttf,int *_ival,real *dval,int *operand,struct ttfinfo *info) {
2641  char buffer[50], *pt;
2642  int ch, ival;
2643 
2644  ch = getc(ttf);
2645  if ( ch==12 ) {
2646  *operand = (12<<8) | getc(ttf);
2647 return( 3 );
2648  } else if ( ch<=21 ) {
2649  *operand = ch;
2650 return( 3 );
2651  } else if ( ch==30 ) {
2652  /* fixed format doesn't exist in dict data but does in type2 strings */
2653  pt = buffer;
2654  do {
2655  ch = getc(ttf);
2656  if ( pt<buffer+44 || (ch&0xf)==0xf || (ch&0xf0)==0xf0 ) {
2657  pt = addnibble(pt,ch>>4);
2658  pt = addnibble(pt,ch&0xf);
2659  }
2660  } while ( pt[-1]!='\0' );
2661  *dval = strtod(buffer,NULL);
2662 return( 2 );
2663  } else if ( ch>=32 && ch<=246 ) {
2664  *_ival = ch-139;
2665 return( 1 );
2666  } else if ( ch>=247 && ch<=250 ) {
2667  *_ival = ((ch-247)<<8) + getc(ttf)+108;
2668 return( 1 );
2669  } else if ( ch>=251 && ch<=254 ) {
2670  *_ival = -((ch-251)<<8) - getc(ttf)-108;
2671 return( 1 );
2672  } else if ( ch==28 ) {
2673  ival = getc(ttf)<<8;
2674  *_ival = (short) (ival | getc(ttf));
2675 return( 1 );
2676  } else if ( ch==29 ) {
2677  /* 4 byte integers exist in dict data but not in type2 strings */
2678  ival = getc(ttf)<<24;
2679  ival = ival | getc(ttf)<<16;
2680  ival = ival | getc(ttf)<<8;
2681  *_ival = (int) (ival | getc(ttf));
2682 return( 1 );
2683  }
2684  LogError(_("Unexpected value in dictionary %d\n"), ch );
2685  info->bad_cff = true;
2686  *_ival = 0;
2687 return( 0 );
2688 }
2689 
2690 static void skipcfft2thing(FILE *ttf) {
2691  /* The old CFF spec allows little type2 programs to live in the CFF dict */
2692  /* indices. These are designed to allow interpolation of values for mm */
2693  /* fonts. */
2694  /* The Type2 program is terminated by an "endchar" operator */
2695  /* I don't support this, but I shall try to skip over them properly */
2696  /* There's no discussion about how values move from the t2 stack to the */
2697  /* cff stack, as there are no examples of this, it's hard to guess */
2698  int ch;
2699 
2700 /* GT: DICT is a magic term inside CFF fonts, as is INDEX, and I guess CFF and type2 */
2701  LogError( _("FontForge does not support type2 programs embedded in CFF DICT INDICES.\n") );
2702  forever {
2703  ch = getc(ttf);
2704  if ( ch>=247 && ch<=254 )
2705  getc(ttf); /* Two byte number */
2706  else if ( ch==255 ) {
2707  getc(ttf); getc(ttf); getc(ttf); getc(ttf);
2708  /* 16.16 number */
2709  } else if ( ch==28 ) {
2710  getc(ttf);
2711  getc(ttf);
2712  } else if ( ch==12 ) {
2713  getc(ttf); /* Two byte operator */
2714  } else if ( ch==14 ) {
2715 return;
2716  }
2717  }
2718 }
2719 
2720 struct topdicts {
2722 
2723  char *fontname; /* From Name Index */
2724 
2725  int version; /* SID */
2726  int notice; /* SID */
2727  int copyright; /* SID */
2728  int fullname; /* SID */
2729  int familyname; /* SID */
2730  int weight; /* SID */
2742  int xuid[20];
2743  int charsetoff; /* from start of file */
2744  int encodingoff; /* from start of file */
2745  int charstringsoff; /* from start of file */
2747  int private_offset; /* from start of file */
2748  int synthetic_base; /* font index */
2749  int postscript_code; /* SID */
2750  /* synthetic fonts only (whatever they are) */
2751  int basefontname; /* SID */
2752  /* Multiple master/synthetic fonts */
2753  real basefontblend[16]; /* delta */ /* No description of why this is relevant for mm fonts */
2754  /* Multiple master fonts only */
2755  int blendaxistypes[17]; /* SID */
2757  int nAxes;
2759  int lenBuildCharArray; /* No description of what this means */
2760  int NormalizeDesignVector; /* SID */ /* No description of what this does */
2761  int ConvertDesignVector; /* SID */ /* No description of what this does */
2762  /* CID fonts only */
2763  int ros_registry; /* SID */
2764  int ros_ordering; /* SID */
2770  int uidbase;
2771  int fdarrayoff; /* from start of file */
2772  int fdselectoff; /* from start of file */
2773  int sid_fontname; /* SID */
2774 /* Private stuff */
2782  int stdhw;
2783  int stdvw;
2791  int subrsoff; /* from start of this private table */
2794 
2795  struct pschars glyphs;
2796  struct pschars local_subrs;
2798 };
2799 
2800 static void TopDictFree(struct topdicts *dict) {
2801  int i;
2802 
2803  free(dict->charset);
2804  for ( i=0; i<dict->glyphs.cnt; ++i )
2805  free(dict->glyphs.values[i]);
2806  free(dict->glyphs.values);
2807  free(dict->glyphs.lens);
2808  for ( i=0; i<dict->local_subrs.cnt; ++i )
2809  free(dict->local_subrs.values[i]);
2810  free(dict->local_subrs.values);
2811  free(dict->local_subrs.lens);
2812  free(dict);
2813 }
2814 
2815 static void readcffsubrs(FILE *ttf, struct pschars *subs, struct ttfinfo *info) {
2816  uint16 count = getushort(ttf);
2817  int offsize;
2818  uint32 *offsets;
2819  int i,j, base;
2820  int err = false;
2821 
2822  memset(subs,'\0',sizeof(struct pschars));
2823  if ( count==0 )
2824 return;
2825  subs->cnt = count;
2826  subs->lens = galloc(count*sizeof(int));
2827  subs->values = galloc(count*sizeof(uint8 *));
2828  offsets = galloc((count+1)*sizeof(uint32));
2829  offsize = getc(ttf);
2830  for ( i=0; i<=count; ++i )
2831  offsets[i] = getoffset(ttf,offsize);
2832  base = ftell(ttf)-1;
2833  for ( i=0; i<count; ++i ) {
2834  if ( offsets[i+1]>offsets[i] && offsets[i+1]-offsets[i]<0x10000 ) {
2835  subs->lens[i] = offsets[i+1]-offsets[i];
2836  subs->values[i] = galloc(offsets[i+1]-offsets[i]+1);
2837  for ( j=0; j<(int)(offsets[i+1]-offsets[i]); ++j )
2838  subs->values[i][j] = getc(ttf);
2839  subs->values[i][j] = '\0';
2840  } else {
2841  if ( !err )
2842  LogError( _("Bad subroutine INDEX in cff font.\n" ));
2843  info->bad_cff = true;
2844  err = true;
2845  subs->lens[i] = 1;
2846  subs->values[i] = galloc(2);
2847  subs->values[i][0] = 11; /* return */
2848  subs->values[i][1] = '\0';
2849  fseek(ttf,base+offsets[i+1],SEEK_SET);
2850  }
2851  }
2852  free(offsets);
2853 }
2854 
2855 static struct topdicts *readcfftopdict(FILE *ttf, char *fontname, int len,
2856  struct ttfinfo *info) {
2857  struct topdicts *td = gcalloc(1,sizeof(struct topdicts));
2858  long base = ftell(ttf);
2859  int ival, oval, sp, ret, i;
2860  real stack[50];
2861 
2862  if ( fontname!=NULL )
2864 
2865  td->fontname = fontname;
2866  td->underlinepos = -100;
2867  td->underlinewidth = 50;
2868  td->charstringtype = 2;
2869  td->fontmatrix[0] = td->fontmatrix[3] = .001;
2870 
2871  td->notice = td->copyright = td->fullname = td->familyname = td->weight = td->version = -1;
2872  td->postscript_code = td->basefontname = -1;
2873  td->synthetic_base = td->ros_registry = -1;
2874  td->fdarrayoff = td->fdselectoff = td->sid_fontname = -1;
2875  td->blendaxistypes[0] = -1;
2876 
2877  /* Multiple master fonts can have Type2 operators here, particularly */
2878  /* blend operators. We're ignoring that */
2879  while ( ftell(ttf)<base+len ) {
2880  sp = 0;
2881  while ( (ret=readcffthing(ttf,&ival,&stack[sp],&oval,info))!=3 && ftell(ttf)<base+len ) {
2882  if ( ret==1 )
2883  stack[sp]=ival;
2884  if ( ret!=0 && sp<45 )
2885  ++sp;
2886  }
2887  if ( ret==3 && oval==31 /* "T2" operator, can have 0 arguments */ ) {
2888  skipcfft2thing(ttf);
2889  } else if ( sp==0 ) {
2890  LogError( _("No argument to operator\n") );
2891  info->bad_cff = true;
2892  } else if ( ret==3 ) switch( oval ) {
2893  case 0:
2894  td->version = stack[sp-1];
2895  break;
2896  case 1:
2897  td->notice = stack[sp-1];
2898  break;
2899  case (12<<8)+0:
2900  td->copyright = stack[sp-1];
2901  break;
2902  case 2:
2903  td->fullname = stack[sp-1];
2904  break;
2905  case 3:
2906  td->familyname = stack[sp-1];
2907  break;
2908  case 4:
2909  td->weight = stack[sp-1];
2910  break;
2911  case (12<<8)+1:
2912  td->isfixedpitch = stack[sp-1];
2913  break;
2914  case (12<<8)+2:
2915  td->italicangle = stack[sp-1];
2916  break;
2917  case (12<<8)+3:
2918  td->underlinepos = stack[sp-1];
2919  break;
2920  case (12<<8)+4:
2921  td->underlinewidth = stack[sp-1];
2922  break;
2923  case (12<<8)+5:
2924  td->painttype = stack[sp-1];
2925  break;
2926  case (12<<8)+6:
2927  td->charstringtype = stack[sp-1];
2928  break;
2929  case (12<<8)+7:
2930  memcpy(td->fontmatrix,stack,(sp>=6?6:sp)*sizeof(real));
2931  td->fontmatrix_set = 1;
2932  break;
2933  case 13:
2934  td->uniqueid = stack[sp-1];
2935  break;
2936  case 5:
2937  memcpy(td->fontbb,stack,(sp>=4?4:sp)*sizeof(real));
2938  break;
2939  case (12<<8)+8:
2940  td->strokewidth = stack[sp-1];
2941  break;
2942  case 14:
2943  for ( i=0; i<sp && i<20; ++i )
2944  td->xuid[i] = stack[i];
2945  break;
2946  case 15:
2947  td->charsetoff = stack[sp-1];
2948  break;
2949  case 16:
2950  td->encodingoff = stack[sp-1];
2951  break;
2952  case 17:
2953  td->charstringsoff = stack[sp-1];
2954  break;
2955  case 18:
2956  td->private_size = stack[0];
2957  td->private_offset = stack[1];
2958  break;
2959  case (12<<8)+20:
2960  LogError( _("FontForge does not support synthetic fonts\n") );
2961  td->synthetic_base = stack[sp-1];
2962  break;
2963  case (12<<8)+21:
2964  td->postscript_code = stack[sp-1];
2965  break;
2966  case (12<<8)+22:
2967  td->basefontname = stack[sp-1];
2968  break;
2969  case (12<<8)+23:
2970  for ( i=0; i<sp && i<16; ++i )
2971  td->basefontblend[i] = stack[i];
2972  break;
2973  case (12<<8)+24:
2974  LogError( _("FontForge does not support type2 multiple master fonts\n") );
2975  info->bad_cff = true;
2976  td->nMasters = stack[0];
2977  td->nAxes = sp-4;
2978  memcpy(td->weightvector,stack+1,(sp-4)*sizeof(real));
2979  td->lenBuildCharArray = stack[sp-3];
2980  td->NormalizeDesignVector = stack[sp-2]; /* These are type2 charstrings, even in type1 fonts */
2981  td->ConvertDesignVector = stack[sp-1];
2982  break;
2983  case (12<<8)+26:
2984  for ( i=0; i<sp && i<16; ++i )
2985  td->blendaxistypes[i] = stack[i];
2986  td->blendaxistypes[i] = -1;
2987  break;
2988  case (12<<8)+30:
2989  td->ros_registry = stack[0];
2990  td->ros_ordering = stack[1];
2991  td->ros_supplement = stack[2];
2992  break;
2993  case (12<<8)+31:
2994  td->cidfontversion = stack[sp-1];
2995  break;
2996  case (12<<8)+32:
2997  td->cidfontrevision = stack[sp-1];
2998  break;
2999  case (12<<8)+33:
3000  td->cidfonttype = stack[sp-1];
3001  break;
3002  case (12<<8)+34:
3003  td->cidcount = stack[sp-1];
3004  break;
3005  case (12<<8)+35:
3006  td->uidbase = stack[sp-1];
3007  break;
3008  case (12<<8)+36:
3009  td->fdarrayoff = stack[sp-1];
3010  break;
3011  case (12<<8)+37:
3012  td->fdselectoff = stack[sp-1];
3013  break;
3014  case (12<<8)+38:
3015  td->sid_fontname = stack[sp-1];
3016  break;
3017  case (12<<8)+39:
3018  LogError(_("FontForge does not support Chameleon fonts\n"));;
3019  break;
3020  default:
3021  LogError(_("Unknown operator in %s: %x\n"), fontname, oval );
3022  info->bad_cff = true;
3023  break;
3024  }
3025  }
3026 return( td );
3027 }
3028 
3029 static void readcffprivate(FILE *ttf, struct topdicts *td, struct ttfinfo *info) {
3030  int ival, oval, sp, ret, i;
3031  real stack[50];
3033 
3034  fseek(ttf,td->cff_start+td->private_offset,SEEK_SET);
3035 
3036  td->subrsoff = -1;
3037  td->expansionfactor = .06;
3038  td->bluefuzz = 1;
3039  td->blueshift = 7;
3040  td->bluescale = .039625;
3041 
3042  while ( ftell(ttf)<end ) {
3043  if ( feof(ttf) ) {
3044  LogError("End of file found when reading private dictionary.\n" );
3045  break;
3046  }
3047  sp = 0;
3048  while ( (ret=readcffthing(ttf,&ival,&stack[sp],&oval,info))!=3 && ftell(ttf)<end ) {
3049  if ( ret==1 )
3050  stack[sp]=ival;
3051  if ( ret!=0 && sp<45 )
3052  ++sp;
3053  }
3054  if ( ret==3 && oval==31 /* "T2" operator, can have 0 arguments */ ) {
3055  skipcfft2thing(ttf);
3056  } else if ( sp==0 && oval!=6 && oval!=7 && oval!=8 && oval!=9 && oval !=(12<<8)+12 && oval !=(12<<8)+13) {
3057  LogError( _("No argument to operator %d in private dict\n"), oval );
3058  info->bad_cff = true;
3059  } else if ( ret==3 ) switch( oval ) {
3060  case 6:
3061  for ( i=0; i<sp && i<14; ++i ) {
3062  td->bluevalues[i] = stack[i];
3063  if ( i!=0 )
3064  td->bluevalues[i] += td->bluevalues[i-1];
3065  }
3066  break;
3067  case 7:
3068  for ( i=0; i<sp && i<10; ++i ) {
3069  td->otherblues[i] = stack[i];
3070  if ( i!=0 )
3071  td->otherblues[i] += td->otherblues[i-1];
3072  }
3073  break;
3074  case 8:
3075  for ( i=0; i<sp && i<14; ++i ) {
3076  td->familyblues[i] = stack[i];
3077  if ( i!=0 )
3078  td->familyblues[i] += td->familyblues[i-1];
3079  }
3080  break;
3081  case 9:
3082  for ( i=0; i<sp && i<10; ++i ) {
3083  td->familyotherblues[i] = stack[i];
3084  if ( i!=0 )
3085  td->familyotherblues[i] += td->familyotherblues[i-1];
3086  }
3087  break;
3088  case (12<<8)+9:
3089  td->bluescale = stack[sp-1];
3090  break;
3091  case (12<<8)+10:
3092  td->blueshift = stack[sp-1];
3093  break;
3094  case (12<<8)+11:
3095  td->bluefuzz = stack[sp-1];
3096  break;
3097  case 10:
3098  td->stdhw = stack[sp-1];
3099  break;
3100  case 11:
3101  td->stdvw = stack[sp-1];
3102  break;
3103  case (12<<8)+12:
3104  for ( i=0; i<sp && i<10; ++i ) {
3105  td->stemsnaph[i] = stack[i];
3106  if ( i!=0 )
3107  td->stemsnaph[i] += td->stemsnaph[i-1];
3108  }
3109  break;
3110  case (12<<8)+13:
3111  for ( i=0; i<sp && i<10; ++i ) {
3112  td->stemsnapv[i] = stack[i];
3113  if ( i!=0 )
3114  td->stemsnapv[i] += td->stemsnapv[i-1];
3115  }
3116  break;
3117  case (12<<8)+14:
3118  td->forcebold = stack[sp-1];
3119  break;
3120  case (12<<8)+15: /* obsolete */
3121  td->forceboldthreshold = stack[sp-1];
3122  break;
3123  case (12<<8)+16:
3124  /* lenIV. -1 => unencrypted charstrings */
3125  /* obsolete */
3126  break;
3127  case (12<<8)+17:
3128  td->languagegroup = stack[sp-1];
3129  break;
3130  case (12<<8)+18:
3131  td->expansionfactor = stack[sp-1];
3132  break;
3133  case (12<<8)+19:
3134  td->initialRandomSeed = stack[sp-1];
3135  break;
3136  case 19:
3137  td->subrsoff = stack[sp-1];
3138  break;
3139  case 20:
3140  td->defaultwidthx = stack[sp-1];
3141  break;
3142  case 21:
3143  td->nominalwidthx = stack[sp-1];
3144  break;
3145  default:
3146  LogError(_("Unknown operator in %s: %x\n"), td->fontname, oval );
3147  info->bad_cff = true;
3148  break;
3149  }
3150  }
3151 
3152  if ( td->subrsoff!=-1 ) {
3153  fseek(ttf,td->cff_start+td->private_offset+td->subrsoff,SEEK_SET);
3154  readcffsubrs(ttf,&td->local_subrs,info);
3155  }
3156 }
3157 
3158 static struct topdicts **readcfftopdicts(FILE *ttf, char **fontnames, int32 cff_start,
3159  struct ttfinfo *info, struct topdicts *parent_dict) {
3160  uint16 count = getushort(ttf);
3161  int offsize;
3162  uint32 *offsets;
3163  struct topdicts **dicts;
3164  int i;
3165 
3166  if ( count==0 )
3167 return( NULL );
3168  offsets = galloc((count+1)*sizeof(uint32));
3169  offsize = getc(ttf);
3170  for ( i=0; i<=count; ++i )
3171  offsets[i] = getoffset(ttf,offsize);
3172  dicts = galloc((count+1)*sizeof(struct topdicts *));
3173  for ( i=0; i<count; ++i ) {
3174  dicts[i] = readcfftopdict(ttf,fontnames!=NULL?fontnames[i]:NULL,
3175  offsets[i+1]-offsets[i], info);
3176  if ( parent_dict!=NULL && parent_dict->fontmatrix_set ) {
3177  MatMultiply(parent_dict->fontmatrix,dicts[i]->fontmatrix,dicts[i]->fontmatrix);
3178  }
3179  dicts[i]->cff_start = cff_start;
3180  }
3181  dicts[i] = NULL;
3182  free(offsets);
3183 return( dicts );
3184 }
3185 
3186 static const char *FFgetsid(int sid,char **strings,int scnt,struct ttfinfo *info) {
3187  if ( sid==-1 )
3188 return( NULL );
3189  else if ( sid<nStdStrings )
3190 return( cffnames[sid] );
3191  else if ( sid-nStdStrings>scnt ) {
3192  LogError( _("Bad sid %d (must be less than %d)\n"), sid, scnt+nStdStrings );
3193  if ( info!=NULL ) info->bad_cff = true;
3194 return( NULL );
3195  } else
3196 return( strings[sid-nStdStrings]);
3197 }
3198 
3199 /* I really expect to deal with encodings in ttf cmap, but ocasionally we */
3200 /* get a bare cff */
3201 static void readcffenc(FILE *ttf,struct topdicts *dict,struct ttfinfo *info,
3202  char **strings, int scnt) {
3203  int format, cnt, i, j, pos, first, last, dupenc, sid;
3204  const char *name;
3205  EncMap *map;
3206 
3207  if ( info->encoding_start!=0 ) /* Use the cmap instead */
3208 return;
3209  if ( info->subfontcnt!=0 )
3210 return; /* Use cids instead */
3211 
3212  for ( i=0; i<info->glyph_cnt; ++i ) {
3213  if ( info->chars[i]->unicodeenc==-1 )
3214  info->chars[i]->unicodeenc = UniFromName(info->chars[i]->name,ui_none,&custom);
3215  }
3216 
3217  map = EncMapNew(256,256,&custom);
3218  if ( dict->encodingoff==0 || dict->encodingoff==1 ) {
3219  /* Standard Encodings */
3221  map->enc = FindOrMakeEncoding( dict->encodingoff==0 ?
3222  "AdobeStandard" : "Custom" );
3223  if ( map->enc==NULL )
3224  map->enc = &custom;
3225  for ( i=0; i<info->glyph_cnt; ++i ) {
3226  for ( pos=0; pos<256; ++pos )
3227  if ( strcmp(info->chars[i]->name,enc[pos])==0 )
3228  break;
3229  if ( pos<256 )
3230  map->map[pos] = i;
3231  }
3232  } else {
3233  fseek(ttf,dict->cff_start+dict->encodingoff,SEEK_SET);
3234  format = getc(ttf);
3235  if ( (format&0x7f)==0 ) {
3236  cnt = getc(ttf);
3237  for ( i=1; i<=cnt && i<info->glyph_cnt; ++i )
3238  map->map[getc(ttf)] = i;
3239  } else if ( (format&0x7f)==1 ) {
3240  cnt = getc(ttf);
3241  pos = 0;
3242  for ( i=0; i<cnt ; ++i ) {
3243  first = getc(ttf);
3244  last = first + getc(ttf)-1;
3245  while ( first<=last && first<256 ) {
3246  if ( pos<info->glyph_cnt )
3247  map->map[first] = pos;
3248  ++pos;
3249  ++first;
3250  }
3251  }
3252  } else {
3253  LogError( _("Unexpected encoding format in cff: %d\n"), format );
3254  if ( info!=NULL ) info->bad_cff = true;
3255  }
3256  if ( format&0x80 ) {
3257  cnt = getc(ttf);
3258  for ( i=0; i<cnt; ++i ) {
3259  dupenc = getc(ttf);
3260  sid = getushort(ttf);
3261  name = FFgetsid(sid,strings,scnt,info);
3262  if ( name==NULL ) /* Table is erroneous */
3263  break;
3264  for ( j=0; j<info->glyph_cnt; ++j )
3265  if ( strcmp(name,info->chars[j]->name)==0 )
3266  break;
3267  if ( j!=info->glyph_cnt )
3268  map->map[dupenc] = j;
3269  }
3270  }
3271  }
3272  info->map = map;
3273 }
3274 
3275 static void readcffset(FILE *ttf,struct topdicts *dict,struct ttfinfo *info) {
3276  int len = dict->glyphs.cnt;
3277  int i;
3278  int format, cnt, j, first;
3279 
3280  i = 0;
3281  if ( dict->charsetoff==0 ) {
3282  /* ISO Adobe charset */
3283  dict->charset = galloc(len*sizeof(uint16));
3284  for ( i=0; i<len && i<=228; ++i )
3285  dict->charset[i] = i;
3286  } else if ( dict->charsetoff==1 ) {
3287  /* Expert charset */
3288  dict->charset = galloc((len<162?162:len)*sizeof(uint16));
3289  dict->charset[0] = 0; /* .notdef */
3290  dict->charset[1] = 1;
3291  for ( i=2; i<len && i<=238-227; ++i )
3292  dict->charset[i] = i+227;
3293  dict->charset[12] = 13;
3294  dict->charset[13] = 14;
3295  dict->charset[14] = 15;
3296  dict->charset[15] = 99;
3297  for ( i=16; i<len && i<=248-223; ++i )
3298  dict->charset[i] = i+223;
3299  dict->charset[25] = 27;
3300  dict->charset[26] = 28;
3301  for ( i=27; i<len && i<=266-222; ++i )
3302  dict->charset[i] = i+222;
3303  dict->charset[44] = 109;
3304  dict->charset[45] = 110;
3305  for ( i=46; i<len && i<=318-221; ++i )
3306  dict->charset[i] = i+221;
3307  dict->charset[96] = 158;
3308  dict->charset[97] = 155;
3309  dict->charset[98] = 163;
3310  for ( i=99; i<len && i<=326-220; ++i )
3311  dict->charset[i] = i+220;
3312  dict->charset[107] = 150;
3313  dict->charset[108] = 164;
3314  dict->charset[109] = 169;
3315  for ( i=110; i<len && i<=378-217; ++i )
3316  dict->charset[i] = i+217;
3317  } else if ( dict->charsetoff==2 ) {
3318  /* Expert subset charset */
3319  dict->charset = galloc((len<130?130:len)*sizeof(uint16));
3320  dict->charset[0] = 0; /* .notdef */
3321  dict->charset[1] = 1;
3322  for ( i=2; i<len && i<=238-227; ++i )
3323  dict->charset[i] = i+227;
3324  dict->charset[12] = 13;
3325  dict->charset[13] = 14;
3326  dict->charset[14] = 15;
3327  dict->charset[15] = 99;
3328  for ( i=16; i<len && i<=248-223; ++i )
3329  dict->charset[i] = i+223;
3330  dict->charset[25] = 27;
3331  dict->charset[26] = 28;
3332  for ( i=27; i<len && i<=266-222; ++i )
3333  dict->charset[i] = i+222;
3334  dict->charset[44] = 109;
3335  dict->charset[45] = 110;
3336  for ( i=46; i<len && i<=272-221; ++i )
3337  dict->charset[i] = i+221;
3338  dict->charset[51] = 300;
3339  dict->charset[52] = 301;
3340  dict->charset[53] = 302;
3341  dict->charset[54] = 305;
3342  dict->charset[55] = 314;
3343  dict->charset[56] = 315;
3344  dict->charset[57] = 158;
3345  dict->charset[58] = 155;
3346  dict->charset[59] = 163;
3347  for ( i=60; i<len && i<=326-260; ++i )
3348  dict->charset[i] = i+260;
3349  dict->charset[67] = 150;
3350  dict->charset[68] = 164;
3351  dict->charset[69] = 169;
3352  for ( i=110; i<len && i<=346-217; ++i )
3353  dict->charset[i] = i+217;
3354  } else {
3355  dict->charset = galloc(len*sizeof(uint16));
3356  dict->charset[0] = 0; /* .notdef */
3357  fseek(ttf,dict->cff_start+dict->charsetoff,SEEK_SET);
3358  format = getc(ttf);
3359  if ( format==0 ) {
3360  for ( i=1; i<len; ++i )
3361  dict->charset[i] = getushort(ttf);
3362  } else if ( format==1 ) {
3363  for ( i = 1; i<len; ) {
3364  first = dict->charset[i++] = getushort(ttf);
3365  cnt = getc(ttf);
3366  for ( j=0; j<cnt; ++j )
3367  dict->charset[i++] = ++first;
3368  }
3369  } else if ( format==2 ) {
3370  for ( i = 1; i<len; ) {
3371  first = dict->charset[i++] = getushort(ttf);
3372  cnt = getushort(ttf);
3373  for ( j=0; j<cnt; ++j )
3374  dict->charset[i++] = ++first;
3375  }
3376  } else {
3377  LogError( _("Unexpected charset format in cff: %d\n"), format );
3378  if ( info!=NULL ) info->bad_cff = true;
3379  }
3380  }
3381  while ( i<len ) dict->charset[i++] = 0;
3382 }
3383 
3384 static uint8 *readfdselect(FILE *ttf,int numglyphs,struct ttfinfo *info) {
3385  uint8 *fdselect = gcalloc(numglyphs,sizeof(uint8));
3386  int i, j, format, nr, first, end, fd;
3387 
3388  format = getc(ttf);
3389  if ( format==0 ) {
3390  for ( i=0; i<numglyphs; ++i )
3391  fdselect[i] = getc(ttf);
3392  } else if ( format==3 ) {
3393  nr = getushort(ttf);
3394  first = getushort(ttf);
3395  for ( i=0; i<nr; ++i ) {
3396  fd = getc(ttf);
3397  end = getushort(ttf);
3398  for ( j=first; j<end; ++j ) {
3399  if ( j>=numglyphs ) {
3400  LogError( _("Bad fdselect\n") );
3401  if ( info!=NULL ) info->bad_cff = true;
3402  } else
3403  fdselect[j] = fd;
3404  }
3405  first = end;
3406  }
3407  } else {
3408  LogError( _("Didn't understand format for fdselect %d\n"), format );
3409  if ( info!=NULL ) info->bad_cff = true;
3410  }
3411 return( fdselect );
3412 }
3413 
3414 
3415 static char *intarray2str(int *array, int size) {
3416  int i,j;
3417  char *pt, *ret;
3418 
3419  for ( i=size-1; i>=0 && array[i]==0; --i );
3420  if ( i==-1 )
3421 return( NULL );
3422  ret = pt = galloc((i+1)*12+12);
3423  *pt++ = '[';
3424  for ( j=0; j<=i; ++j ) {
3425  sprintf( pt, "%d ", array[j]);
3426  pt += strlen(pt);
3427  }
3428  pt[-1]=']';
3429 return( ret );
3430 }
3431 
3432 static char *realarray2str(real *array, int size, int must_be_even) {
3433  int i,j;
3434  char *pt, *ret;
3435 
3436  for ( i=size-1; i>=0 && array[i]==0; --i );
3437  if ( i==-1 )
3438 return( NULL );
3439  if ( must_be_even && !(i&1) && array[i]<0 )
3440  ++i; /* Someone gave us a bluevalues of [-20 0] and we reported [-20] */
3441  ret = pt = galloc((i+1)*20+12);
3442  *pt++ = '[';
3443  for ( j=0; j<=i; ++j ) {
3444  sprintf( pt, "%g ", (double) array[j]);
3445  pt += strlen(pt);
3446  }
3447  pt[-1]=']';
3448 return( ret );
3449 }
3450 
3451 static void privateadd(struct psdict *private,char *key,char *value) {
3452  if ( value==NULL )
3453 return;
3454  private->keys[private->next] = copy(key);
3455  private->values[private->next++] = value;
3456 }
3457 
3458 static void privateaddint(struct psdict *private,char *key,int val) {
3459  char buf[20];
3460  if ( val==0 )
3461 return;
3462  sprintf( buf,"%d", val );
3463  privateadd(private,key,copy(buf));
3464 }
3465 
3466 static void privateaddintarray(struct psdict *private,char *key,int val) {
3467  char buf[20];
3468  if ( val==0 )
3469 return;
3470  sprintf( buf,"[%d]", val );
3471  privateadd(private,key,copy(buf));
3472 }
3473 
3474 static void privateaddreal(struct psdict *private,char *key,double val,double def) {
3475  char buf[20];
3476  if ( val==def )
3477 return;
3478  sprintf( buf,"%g", val );
3479  privateadd(private,key,copy(buf));
3480 }
3481 
3482 static void cffprivatefillup(struct psdict *private, struct topdicts *dict) {
3483  private->cnt = 14;
3484  private->keys = galloc(14*sizeof(char *));
3485  private->values = galloc(14*sizeof(char *));
3486  privateadd(private,"BlueValues",
3487  realarray2str(dict->bluevalues,sizeof(dict->bluevalues)/sizeof(dict->bluevalues[0]),true));
3488  privateadd(private,"OtherBlues",
3489  realarray2str(dict->otherblues,sizeof(dict->otherblues)/sizeof(dict->otherblues[0]),true));
3490  privateadd(private,"FamilyBlues",
3491  realarray2str(dict->familyblues,sizeof(dict->familyblues)/sizeof(dict->familyblues[0]),true));
3492  privateadd(private,"FamilyOtherBlues",
3493  realarray2str(dict->familyotherblues,sizeof(dict->familyotherblues)/sizeof(dict->familyotherblues[0]),true));
3494  privateaddreal(private,"BlueScale",dict->bluescale,0.039625);
3495  privateaddreal(private,"BlueShift",dict->blueshift,7);
3496  privateaddreal(private,"BlueFuzz",dict->bluefuzz,1);
3497  privateaddintarray(private,"StdHW",dict->stdhw);
3498  privateaddintarray(private,"StdVW",dict->stdvw);
3499  privateadd(private,"StemSnapH",
3500  realarray2str(dict->stemsnaph,sizeof(dict->stemsnaph)/sizeof(dict->stemsnaph[0]),false));
3501  privateadd(private,"StemSnapV",
3502  realarray2str(dict->stemsnapv,sizeof(dict->stemsnapv)/sizeof(dict->stemsnapv[0]),false));
3503  if ( dict->forcebold )
3504  privateadd(private,"ForceBold",copy("true"));
3505  if ( dict->forceboldthreshold!=0 )
3506  privateaddreal(private,"ForceBoldThreshold",dict->forceboldthreshold,0);
3507  privateaddint(private,"LanguageGroup",dict->languagegroup);
3508  privateaddreal(private,"ExpansionFactor",dict->expansionfactor,0.06);
3509 }
3510 
3511 static SplineFont *cffsffillup(struct topdicts *subdict, char **strings,
3512  int scnt, struct ttfinfo *info) {
3514  int emsize;
3515  static int nameless;
3516 
3517  sf->fontname = utf8_verify_copy(FFgetsid(subdict->sid_fontname,strings,scnt,info));
3518  if ( sf->fontname==NULL ) {
3519  char buffer[40];
3520  sprintf(buffer,"UntitledSubFont_%d", ++nameless );
3521  sf->fontname = copy(buffer);
3522  }
3523 
3524  if ( subdict->fontmatrix[0]==0 )
3525  emsize = 1000;
3526  else
3527  emsize = rint( 1/subdict->fontmatrix[0] );
3528  sf->ascent = .8*emsize;
3529  sf->descent = emsize - sf->ascent;
3530  if ( subdict->copyright!=-1 )
3531  sf->copyright = utf8_verify_copy(FFgetsid(subdict->copyright,strings,scnt,info));
3532  else
3533  sf->copyright = utf8_verify_copy(FFgetsid(subdict->notice,strings,scnt,info));
3534  sf->familyname = utf8_verify_copy(FFgetsid(subdict->familyname,strings,scnt,info));
3535  sf->fullname = utf8_verify_copy(FFgetsid(subdict->fullname,strings,scnt,info));
3536  sf->weight = utf8_verify_copy(FFgetsid(subdict->weight,strings,scnt,info));
3537  sf->version = utf8_verify_copy(FFgetsid(subdict->version,strings,scnt,info));
3538  sf->italicangle = subdict->italicangle;
3539  sf->upos = subdict->underlinepos;
3540  sf->uwidth = subdict->underlinewidth;
3541  sf->xuid = intarray2str(subdict->xuid,sizeof(subdict->xuid)/sizeof(subdict->xuid[0]));
3542  sf->uniqueid = subdict->uniqueid;
3543  sf->strokewidth = subdict->strokewidth;
3544  sf->strokedfont = subdict->painttype==2;
3545 
3546  if ( subdict->private_size>0 ) {
3547  sf->private = gcalloc(1,sizeof(struct psdict));
3548  cffprivatefillup(sf->private,subdict);
3549  }
3550 return( sf );
3551 }
3552 
3553 static void cffinfofillup(struct ttfinfo *info, struct topdicts *dict,
3554  char **strings, int scnt ) {
3555 
3556  info->glyph_cnt = dict->glyphs.cnt;
3557  if ( info->glyph_cnt<0 ) info->glyph_cnt = 0;
3558 
3559  if ( dict->fontmatrix[0]==0 )
3560  info->emsize = 1000;
3561  else
3562  info->emsize = rint( 1/dict->fontmatrix[0] );
3563 #if 1
3564  info->ascent = .8*info->emsize;
3565 #else
3566  info->ascent = dict->fontbb[3]*info->emsize/(dict->fontbb[3]-dict->fontbb[1]);
3567 #endif
3568  info->descent = info->emsize - info->ascent;
3569  if ( dict->copyright!=-1 || dict->notice!=-1 )
3570  free( info->copyright );
3571  if ( dict->copyright!=-1 )
3572  info->copyright = utf8_verify_copy(FFgetsid(dict->copyright,strings,scnt,info));
3573  else if ( dict->notice!=-1 )
3574  info->copyright = utf8_verify_copy(FFgetsid(dict->notice,strings,scnt,info));
3575  if ( dict->familyname!=-1 ) {
3576  free(info->familyname);
3577  info->familyname = utf8_verify_copy(FFgetsid(dict->familyname,strings,scnt,info));
3578  }
3579  if ( dict->fullname!=-1 ) {
3580  free(info->fullname);
3581  info->fullname = utf8_verify_copy(FFgetsid(dict->fullname,strings,scnt,info));
3582  }
3583  if ( dict->weight!=-1 ) {
3584  free(info->weight);
3585  info->weight = utf8_verify_copy(FFgetsid(dict->weight,strings,scnt,info));
3586  }
3587  if ( dict->version!=-1 ) {
3588  free(info->version);
3589  info->version = utf8_verify_copy(FFgetsid(dict->version,strings,scnt,info));
3590  }
3591  if ( dict->fontname!=NULL ) {
3592  free(info->fontname);
3593  info->fontname = utf8_verify_copy(dict->fontname);
3594  }
3595  info->italicAngle = dict->italicangle;
3596  info->upos = dict->underlinepos;
3597  info->uwidth = dict->underlinewidth;
3598  info->xuid = intarray2str(dict->xuid,sizeof(dict->xuid)/sizeof(dict->xuid[0]));
3599  info->uniqueid = dict->uniqueid;
3600  info->strokewidth = dict->strokewidth;
3601  info->strokedfont = dict->painttype==2;
3602 
3603  if ( dict->private_size>0 ) {
3604  info->private = gcalloc(1,sizeof(struct psdict));
3605  cffprivatefillup(info->private,dict);
3606  }
3607  if ( dict->ros_registry!=-1 ) {
3608  info->cidregistry = copy(FFgetsid(dict->ros_registry,strings,scnt,info));
3609  info->ordering = copy(FFgetsid(dict->ros_ordering,strings,scnt,info));
3610  info->supplement = dict->ros_supplement;
3611  info->cidfontversion = dict->cidfontversion;
3612  }
3613 }
3614 
3615 static void cfffigure(struct ttfinfo *info, struct topdicts *dict,
3616  char **strings, int scnt, struct pschars *gsubrs) {
3617  int i, cstype;
3618  struct pschars *subrs;
3619  struct pscontext pscontext;
3620  memset(&pscontext,0,sizeof(pscontext));
3621 
3622  cffinfofillup(info, dict, strings, scnt );
3623 
3624 /* The format allows for some dicts that are type1 strings and others that */
3625 /* are type2s. Which means that the global subrs will have a different bias */
3626 /* as we flip from font to font. So we can't set the bias when we read in */
3627 /* the subrs but must wait until we know which font we're working on. */
3628  cstype = dict->charstringtype;
3629  pscontext.is_type2 = cstype-1;
3630  pscontext.painttype = dict->painttype;
3631  gsubrs->bias = cstype==1 ? 0 :
3632  gsubrs->cnt < 1240 ? 107 :
3633  gsubrs->cnt <33900 ? 1131 : 32768;
3634  subrs = &dict->local_subrs;
3635  subrs->bias = cstype==1 ? 0 :
3636  subrs->cnt < 1240 ? 107 :
3637  subrs->cnt <33900 ? 1131 : 32768;
3638 
3639  info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
3640  for ( i=0; i<info->glyph_cnt; ++i ) {
3641  info->chars[i] = PSCharStringToBB(
3642  dict->glyphs.values[i], dict->glyphs.lens[i],&pscontext,
3643  subrs,gsubrs,FFgetsid(dict->charset[i],strings,scnt,info));
3644  info->chars[i]->vwidth = info->emsize;
3645  if ( cstype==2 ) {
3646  if ( info->chars[i]->width == (int16) 0x8000 )
3647  info->chars[i]->width = dict->defaultwidthx;
3648  else
3649  info->chars[i]->width += dict->nominalwidthx;
3650  }
3651  }
3652  /* Need to do a reference fixup here !!!!! just in case some idiot */
3653  /* used type1 char strings -- or used the depreciated meaning of */
3654  /* endchar (==seac) */
3655 }
3656 
3657 static void cidfigure(struct ttfinfo *info, struct topdicts *dict,
3658  char **strings, int scnt, struct pschars *gsubrs, struct topdicts **subdicts,
3659  uint8 *fdselect) {
3660  int i, j, cstype, uni, cid;
3661  struct pschars *subrs;
3662  SplineFont *sf;
3663  struct cidmap *map;
3664  char buffer[100];
3665  struct pscontext pscontext;
3666  EncMap *encmap = NULL;
3667 
3668  memset(&pscontext,0,sizeof(pscontext));
3669 
3670  cffinfofillup(info, dict, strings, scnt );
3671 
3672  /* We'll set the encmap later */
3673  /* info->map = encmap = EncMapNew(info->glyph_cnt,info->glyph_cnt,&custom);*/
3674 
3675  for ( j=0; subdicts[j]!=NULL; ++j );
3676  info->subfontcnt = j;
3677  info->subfonts = gcalloc(j+1,sizeof(SplineFont *));
3678  for ( j=0; subdicts[j]!=NULL; ++j ) {
3679  info->subfonts[j] = cffsffillup(subdicts[j],strings,scnt,info);
3680  info->subfonts[j]->map = encmap;
3681  info->subfonts[j]->glyphmin = -1;
3682  }
3683  /* here we also deal with glyphmin */
3684  for ( i=0; i<info->glyph_cnt; ++i ) {
3685  sf = info->subfonts[ fdselect[i] ];
3686  cid = dict->charset[i];
3687  if ( cid>=sf->glyphcnt ) {
3688  if (sf->glyphmin == -1) {
3689  /*
3690  sf->glyphmin = cid;
3691  */
3692  }
3693  sf->glyphcnt = sf->glyphmax = cid+1;
3694  }
3695  /* if ( cid>=encmap->enccount ) encmap->enccount = cid+1;*/
3696  }
3697  for ( j=0; subdicts[j]!=NULL; ++j ) {
3698  info->subfonts[j]->glyphs = gcalloc(info->subfonts[j]->glyphcnt,sizeof(SplineChar *));
3699  }
3700 
3701  /*encmap->encmax = encmap->enccount;*/
3702  /*encmap->map = galloc(encmap->enccount*sizeof(int));*/
3703  /*memset(encmap->map,-1,encmap->enccount*sizeof(int));*/
3704 
3705  info->chars = gcalloc(info->glyph_cnt,sizeof(SplineChar *));
3706 
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... */
3711 
3712  map = FindCidMap(info->cidregistry,info->ordering,info->supplement,NULL);
3713 
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 : gsubrs->cnt < 1240 ? 107 : gsubrs->cnt <33900 ? 1131 : 32768;
3725  subrs = &subdicts[j]->local_subrs;
3726  subrs->bias = cstype==1 ? 0 : subrs->cnt < 1240 ? 107 : subrs->cnt <33900 ? 1131 : 32768;
3727  /*
3728  cid = dict->charset[i];
3729  */
3730  cid = i ;
3731  /*encmap->map[cid] = cid;*/
3732  uni = CID2NameUni(map,cid,buffer,sizeof(buffer));
3733  info->chars[i] = PSCharStringToBB(dict->glyphs.values[i], dict->glyphs.lens[i],&pscontext,subrs,gsubrs,buffer);
3734  info->chars[i]->vwidth = sf->ascent+sf->descent;
3735  info->chars[i]->unicodeenc = uni;
3736  sf->glyphs[cid] = info->chars[i];
3737  sf->glyphs[cid]->parent = sf;
3738  sf->glyphs[cid]->orig_pos = i; /* fixed in 0.80.1 */
3739  if ( sf->glyphs[cid]->layers[ly_fore].refs!=NULL ) {
3740  IError( "Reference found in CID font. Can't fix it up");
3741  }
3742  THPatchSplineChar(sf->glyphs[cid]);
3743  if ( cstype==2 ) {
3744  if ( sf->glyphs[cid]->width == (int16) 0x8000 )
3745  sf->glyphs[cid]->width = subdicts[j]->defaultwidthx;
3746  else
3747  sf->glyphs[cid]->width += subdicts[j]->nominalwidthx;
3748  }
3749  /* moved here */
3750  if (sf->glyphmin == -1) {
3751  /* if (sf->glyphs[cid] != (struct splinechar *)-1) { */
3752  sf->glyphmin = cid ;
3753  /* } */
3754  }
3755  ff_progress_next();
3756  }
3757  /* bonus */
3758  if (sf->glyphmin == -1) {
3759  sf->glyphmin = 0 ;
3760  }
3761  /* No need to do a reference fixup here-- the chars aren't associated */
3762  /* with any encoding as is required for seac */
3763 }
3764 
3765 static int readcffglyphs(FILE *ttf,struct ttfinfo *info) {
3766  int offsize;
3767  int hdrsize;
3768  char **fontnames, **strings;
3769  struct topdicts **dicts, **subdicts;
3770  int i, j, which;
3771  struct pschars gsubs;
3772  uint8 *fdselect;
3773  int scnt;
3774 
3775  fseek(ttf,info->cff_start,SEEK_SET);
3776  if ( getc(ttf)!='\1' ) { /* Major version */
3777  LogError( _("CFF version mismatch\n" ));
3778  info->bad_cff = true;
3779  return 0;
3780  }
3781  getc(ttf); /* Minor version */
3782  hdrsize = getc(ttf);
3783  offsize = getc(ttf);
3784  if ( hdrsize!=4 )
3785  fseek(ttf,info->cff_start+hdrsize,SEEK_SET);
3786  fontnames = readcfffontnames(ttf,NULL,info);
3787  which = 0;
3788  if ( fontnames[1]!=NULL ) { /* More than one? Can that even happen in OpenType? */
3789  which = PickCFFFont(fontnames);
3790  if (which == -1) {
3791  for (i=0; fontnames[i]!=NULL; ++i) {
3792  free(fontnames[i]);
3793  }
3794  free(fontnames);
3795  return 0;
3796  }
3797  }
3798  dicts = readcfftopdicts(ttf,fontnames,info->cff_start,info, NULL);
3799  /* String index is just the same as fontname index */
3800  strings = readcfffontnames(ttf,&scnt,info);
3801  readcffsubrs(ttf,&gsubs,info );
3802  /* Can be many fonts here. Only decompose the one */
3803  if ( dicts[which]->charstringsoff!=-1 ) {
3804  fseek(ttf,info->cff_start+dicts[which]->charstringsoff,SEEK_SET);
3805  readcffsubrs(ttf,&dicts[which]->glyphs,info);
3806  }
3807  if ( dicts[which]->private_offset!=-1 )
3808  readcffprivate(ttf,dicts[which],info);
3809  if ( dicts[which]->charsetoff!=-1 )
3810  readcffset(ttf,dicts[which],info);
3811  if ( dicts[which]->fdarrayoff==-1 )
3812  cfffigure(info,dicts[which],strings,scnt,&gsubs);
3813  else {
3814  fseek(ttf,info->cff_start+dicts[which]->fdarrayoff,SEEK_SET);
3815  subdicts = readcfftopdicts(ttf,NULL,info->cff_start,info,dicts[which]);
3816  fseek(ttf,info->cff_start+dicts[which]->fdselectoff,SEEK_SET);
3817  fdselect = readfdselect(ttf,dicts[which]->glyphs.cnt,info);
3818  for ( j=0; subdicts[j]!=NULL; ++j ) {
3819  if ( subdicts[j]->private_offset!=-1 )
3820  readcffprivate(ttf,subdicts[j],info);
3821  if ( subdicts[j]->charsetoff!=-1 )
3822  readcffset(ttf,subdicts[j],info);
3823  }
3824  cidfigure(info,dicts[which],strings,scnt,&gsubs,subdicts,fdselect);
3825  for ( j=0; subdicts[j]!=NULL; ++j )
3826  TopDictFree(subdicts[j]);
3827  free(subdicts); free(fdselect);
3828  }
3829  if ( dicts[which]->encodingoff!=-1 )
3830  readcffenc(ttf,dicts[which],info,