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)  

tottf.c
Go to the documentation of this file.
1 /* Copyright (C) 2000-2012 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 "fontforge.h"
28 #include <math.h>
29 #include <time.h>
30 #include <utype.h>
31 
32 #ifdef __CygWin
33  #include <sys/types.h>
34  #include <sys/stat.h>
35  #include <unistd.h>
36 #endif
37 
38 #include "ttf.h"
39 
41 
42 /* This file produces a ttf file given a splinefont. */
43 
44 /* ************************************************************************** */
45 
46 /* Required tables:
47  cmap encoding
48  head header data
49  hhea horizontal metrics header data
50  hmtx horizontal metrics (widths, lsidebearing)
51  maxp various maxima in the font
52  name various names associated with the font
53  post postscript names and other stuff
54 Required by windows but not mac
55  OS/2 bleah.
56 Required for TrueType
57  loca pointers to the glyphs
58  glyf character shapes
59 Required for OpenType (PostScript)
60  CFF A complete postscript CFF font here with all its internal tables
61 Required for bitmaps
62  bdat/EBDT bitmap data
63  bloc/EBLC pointers to bitmaps
64  bhed for apple bitmap only fonts, replaces head
65 Optional for bitmaps
66  EBSC bitmap scaling table (used in windows "bitmap-only" fonts)
67 "Advanced Typograpy"
68  Apple
69  feat (mapping between morx features and 'name' names)
70  kern (if data are present)
71  lcar (ligature caret, if data present)
72  morx (substitutions, if data present)
73  prop (glyph properties, if data present)
74  opbd (optical bounds, if data present)
75  OpenType
76  GPOS (opentype, if kern,anchor data are present)
77  GSUB (opentype, if ligature (other subs) data are present)
78  GDEF (opentype, if anchor data are present)
79 MATH
80  MATH (MS proposal, if math data present)
81 Apple variation tables (for distortable (multiple master type) fonts)
82  fvar (font variations)
83  gvar (glyph variations)
84  cvar (cvt variations)
85  avar (axis variations)
86 additional tables
87  cvt for hinting
88  gasp to control when things should be hinted
89  fpgm for hinting (currently only copied and dumped verbatim)
90  prep for hinting (currently only copied and dumped verbatim)
91 FontForge
92  PfEd My own table
93 TeX
94  TeX TeX specific info (stuff that used to live in tfm files)
95 */
96 
97 const char *ttfstandardnames[258] = {
98 ".notdef",
99 ".null",
100 "nonmarkingreturn",
101 "space",
102 "exclam",
103 "quotedbl",
104 "numbersign",
105 "dollar",
106 "percent",
107 "ampersand",
108 "quotesingle",
109 "parenleft",
110 "parenright",
111 "asterisk",
112 "plus",
113 "comma",
114 "hyphen",
115 "period",
116 "slash",
117 "zero",
118 "one",
119 "two",
120 "three",
121 "four",
122 "five",
123 "six",
124 "seven",
125 "eight",
126 "nine",
127 "colon",
128 "semicolon",
129 "less",
130 "equal",
131 "greater",
132 "question",
133 "at",
134 "A",
135 "B",
136 "C",
137 "D",
138 "E",
139 "F",
140 "G",
141 "H",
142 "I",
143 "J",
144 "K",
145 "L",
146 "M",
147 "N",
148 "O",
149 "P",
150 "Q",
151 "R",
152 "S",
153 "T",
154 "U",
155 "V",
156 "W",
157 "X",
158 "Y",
159 "Z",
160 "bracketleft",
161 "backslash",
162 "bracketright",
163 "asciicircum",
164 "underscore",
165 "grave",
166 "a",
167 "b",
168 "c",
169 "d",
170 "e",
171 "f",
172 "g",
173 "h",
174 "i",
175 "j",
176 "k",
177 "l",
178 "m",
179 "n",
180 "o",
181 "p",
182 "q",
183 "r",
184 "s",
185 "t",
186 "u",
187 "v",
188 "w",
189 "x",
190 "y",
191 "z",
192 "braceleft",
193 "bar",
194 "braceright",
195 "asciitilde",
196 "Adieresis",
197 "Aring",
198 "Ccedilla",
199 "Eacute",
200 "Ntilde",
201 "Odieresis",
202 "Udieresis",
203 "aacute",
204 "agrave",
205 "acircumflex",
206 "adieresis",
207 "atilde",
208 "aring",
209 "ccedilla",
210 "eacute",
211 "egrave",
212 "ecircumflex",
213 "edieresis",
214 "iacute",
215 "igrave",
216 "icircumflex",
217 "idieresis",
218 "ntilde",
219 "oacute",
220 "ograve",
221 "ocircumflex",
222 "odieresis",
223 "otilde",
224 "uacute",
225 "ugrave",
226 "ucircumflex",
227 "udieresis",
228 "dagger",
229 "degree",
230 "cent",
231 "sterling",
232 "section",
233 "bullet",
234 "paragraph",
235 "germandbls",
236 "registered",
237 "copyright",
238 "trademark",
239 "acute",
240 "dieresis",
241 "notequal",
242 "AE",
243 "Oslash",
244 "infinity",
245 "plusminus",
246 "lessequal",
247 "greaterequal",
248 "yen",
249 "mu",
250 "partialdiff",
251 "summation",
252 "product",
253 "pi",
254 "integral",
255 "ordfeminine",
256 "ordmasculine",
257 "Omega",
258 "ae",
259 "oslash",
260 "questiondown",
261 "exclamdown",
262 "logicalnot",
263 "radical",
264 "florin",
265 "approxequal",
266 "Delta",
267 "guillemotleft",
268 "guillemotright",
269 "ellipsis",
270 "nonbreakingspace",
271 "Agrave",
272 "Atilde",
273 "Otilde",
274 "OE",
275 "oe",
276 "endash",
277 "emdash",
278 "quotedblleft",
279 "quotedblright",
280 "quoteleft",
281 "quoteright",
282 "divide",
283 "lozenge",
284 "ydieresis",
285 "Ydieresis",
286 "fraction",
287 "currency",
288 "guilsinglleft",
289 "guilsinglright",
290 "fi",
291 "fl",
292 "daggerdbl",
293 "periodcentered",
294 "quotesinglbase",
295 "quotedblbase",
296 "perthousand",
297 "Acircumflex",
298 "Ecircumflex",
299 "Aacute",
300 "Edieresis",
301 "Egrave",
302 "Iacute",
303 "Icircumflex",
304 "Idieresis",
305 "Igrave",
306 "Oacute",
307 "Ocircumflex",
308 "apple",
309 "Ograve",
310 "Uacute",
311 "Ucircumflex",
312 "Ugrave",
313 "dotlessi",
314 "circumflex",
315 "tilde",
316 "macron",
317 "breve",
318 "dotaccent",
319 "ring",
320 "cedilla",
321 "hungarumlaut",
322 "ogonek",
323 "caron",
324 "Lslash",
325 "lslash",
326 "Scaron",
327 "scaron",
328 "Zcaron",
329 "zcaron",
330 "brokenbar",
331 "Eth",
332 "eth",
333 "Yacute",
334 "yacute",
335 "Thorn",
336 "thorn",
337 "minus",
338 "multiply",
339 "onesuperior",
340 "twosuperior",
341 "threesuperior",
342 "onehalf",
343 "onequarter",
344 "threequarters",
345 "franc",
346 "Gbreve",
347 "gbreve",
348 "Idotaccent",
349 "Scedilla",
350 "scedilla",
351 "Cacute",
352 "cacute",
353 "Ccaron",
354 "ccaron",
355 "dcroat"
356 };
357 /* Relates Unicode blocks as in
358  http://unicode.org/Public/UNIDATA/Blocks.txt
359  to bit positions in the OpenType standard Unicode Character Range
360  field 'ulUnicodeRange'.
361  Note that the OpenType standard specifies bits for a subset
362  of the Unicode blocks.
363  */
364 static int uniranges[][3] = {
365  { 0x20, 0x7e, 0 }, /* Basic Latin */
366  { 0xa0, 0xff, 1 }, /* Latin-1 Supplement */
367  { 0x100, 0x17f, 2 }, /* Latin Extended-A */
368  { 0x180, 0x24f, 3 }, /* Latin Extended-B */
369  { 0x250, 0x2af, 4 }, /* IPA Extensions */
370  { 0x2b0, 0x2ff, 5 }, /* Spacing Modifier Letters */
371  { 0x300, 0x36f, 6 }, /* Combining Diacritical Marks */
372  { 0x370, 0x3ff, 7 }, /* Greek and Coptic */
373  { 0x400, 0x52f, 9 }, /* Cyrillic / Cyrillic Supplement */
374  { 0x530, 0x58f, 10 }, /* Armenian */
375  { 0x590, 0x5ff, 11 }, /* Hebrew */
376  { 0x600, 0x6ff, 13 }, /* Arabic */
377  { 0x700, 0x74f, 71 }, /* Syriac */
378  { 0x750, 0x77f, 13 }, /* Arabic Supplement */
379  { 0x780, 0x7bf, 72 }, /* Thaana */
380  { 0x7c0, 0x7ff, 14 }, /* N'Ko */
381  /* { 0x800, 0x83f, ? }, Samaritan */
382  /* { 0x840, 0x85f, ? }, Mandaic */
383  { 0x900, 0x97f, 15 }, /* Devanagari */
384  { 0x980, 0x9ff, 16 }, /* Bengali */
385  { 0xa00, 0xa7f, 17 }, /* Gurmukhi */
386  { 0xa80, 0xaff, 18 }, /* Gujarati */
387  { 0xb00, 0xb7f, 19 }, /* Oriya */
388  { 0xb80, 0xbff, 20 }, /* Tamil */
389  { 0xc00, 0xc7f, 21 }, /* Telugu */
390  { 0xc80, 0xcff, 22 }, /* Kannada */
391  { 0xd00, 0xd7f, 23 }, /* Malayalam */
392  { 0xd80, 0xdff, 73 }, /* Sinhala */
393  { 0xe00, 0xe7f, 24 }, /* Thai */
394  { 0xe80, 0xeff, 25 }, /* Lao */
395  { 0xf00, 0xfbf, 70 }, /* Tibetan */
396  { 0x1000, 0x109f, 74 }, /* Myanmar */
397  { 0x10a0, 0x10ff, 26 }, /* Georgian */
398  { 0x1100, 0x11ff, 28 }, /* Hangul Jamo */
399  { 0x1200, 0x137f, 75 }, /* Ethiopic */
400  { 0x1380, 0x139f, 75 }, /* Ethiopic Supplement */
401  { 0x13a0, 0x13ff, 76 }, /* Cherokee */
402  { 0x1400, 0x167f, 77 }, /* Unified Canadian Aboriginal Symbols */
403  { 0x1680, 0x169f, 78 }, /* Ogham */
404  { 0x16a0, 0x16ff, 79 }, /* Runic */
405  { 0x1700, 0x1714, 84 }, /* Tagalog */
406  { 0x1720, 0x1736, 84 }, /* Harunoo */
407  { 0x1740, 0x1753, 84 }, /* Buhid */
408  { 0x1750, 0x1773, 84 }, /* Tagbanwa */
409  { 0x1780, 0x17ff, 80 }, /* Khmer */
410  { 0x1800, 0x18af, 81 }, /* Mongolian */
411  { 0x18B0, 0x18f5, 77 }, /* Unified Canadian Aboriginal Symbols Extended */
412  { 0x1900, 0x194f, 93 }, /* Limbu */
413  { 0x1950, 0x197f, 94 }, /* Tai Le */
414  { 0x1980, 0x19DF, 95 }, /* New Tai Lue */
415  { 0x19e0, 0x19ff, 80 }, /* Khmer Symbols */
416  { 0x1A00, 0x1A1F, 96 }, /* Buginese */
417  { 0x1B00, 0x1B7f, 27 }, /* Balinese */
418  { 0x1B80, 0x1BB9, 112 }, /* Sudanese */
419  /*{ 0x1bc0, 0x1bff, ? }, Batak */
420  { 0x1C00, 0x1C4F, 113 }, /* Lepcha */
421  { 0x1C50, 0x1C7F, 114 }, /* Ol Chiki */
422  /*{ 0x1cd0, 0x1cff, ? }, Vedic Extensions */
423  { 0x1d00, 0x1dbf, 4 }, /* Phonetic Extensions & Supplement */
424  { 0x1d80, 0x1dff, 6 }, /* Combining Diacritical Marks Supplement */
425  { 0x1e00, 0x1eff, 29 }, /* Latin Extended Additional */
426  { 0x1f00, 0x1fff, 30 }, /* Greek Extended */
427  { 0x2000, 0x206f, 31 }, /* General Punctuation */
428  { 0x2070, 0x209f, 32 }, /* Superscripts and Subscripts */
429  { 0x20a0, 0x20cf, 33 }, /* Currency Symbols */
430  { 0x20d0, 0x20ff, 34 }, /* Combining Marks for Symbols */
431  { 0x2100, 0x214f, 35 }, /* Letterlike Symbols */
432  { 0x2150, 0x218f, 36 }, /* Number Forms */
433  { 0x2190, 0x21ff, 37 }, /* Arrows */
434  { 0x2200, 0x22ff, 38 }, /* Mathematical Operators */
435  { 0x2300, 0x237f, 39 }, /* Miscellaneous Technical */
436  { 0x2400, 0x243f, 40 }, /* Control Pictures */
437  { 0x2440, 0x245f, 41 }, /* Optical Character Recognition */
438  { 0x2460, 0x24ff, 42 }, /* Enclosed Alphanumerics */
439  { 0x2500, 0x257f, 43 }, /* Box Drawing */
440  { 0x2580, 0x259f, 44 }, /* Block Elements */
441  { 0x25a0, 0x25ff, 45 }, /* Geometric Shapes */
442  { 0x2600, 0x267f, 46 }, /* Miscellaneous Symbols */
443  { 0x2700, 0x27bf, 47 }, /* Dingbats */
444  { 0x27c0, 0x27ef, 38 }, /* Miscellaneous Mathematical Symbols-A */
445  { 0x27f0, 0x27ff, 37 }, /* Supplementary Arrows-A */
446  { 0x2800, 0x28ff, 82 }, /* Braille Patterns */
447  { 0x2900, 0x297f, 37 }, /* Supplementary Arrows-B */
448  { 0x2980, 0x2aff, 38 }, /* Miscellaneous Mathematical Symbols-B /
449  Supplemental Mathematical Operators */
450  { 0x2b00, 0x2bff, 37 }, /* Miscellaneous Symbols and Arrows */
451  { 0x2C00, 0x2C5E, 97 }, /* Glagolitic */
452  { 0x2c60, 0x2c7f, 29 }, /* Latin Extended-C */
453  { 0x2c80, 0x2cff, 8 }, /* Coptic */
454  { 0x2D00, 0x2D25, 26 }, /* Georgian Supplement */
455  { 0x2D30, 0x2D6F, 98 }, /* Tifinagh */
456  { 0x2d80, 0x2ddf, 75 }, /* Ethiopic Extended */
457  { 0x2de0, 0x2dff, 9 }, /* Cyrillic Extended-A */
458  { 0x2e00, 0x2e7f, 31 }, /* Supplemental Punctuation */
459  { 0x2e80, 0x2fff, 59 }, /* CJK Radicals Supplement / Kangxi Radicals /
460  Ideographic Description Characters */
461  { 0x3000, 0x303f, 48 }, /* CJK Symbols and Punctuation */
462  { 0x3040, 0x309f, 49 }, /* Hiragana */
463  { 0x30a0, 0x30ff, 50 }, /* Katakana */
464  { 0x3100, 0x312f, 51 }, /* Bopomofo */
465  { 0x3130, 0x318f, 52 }, /* Hangul Compatibility Jamo */
466  { 0x3190, 0x319f, 59 }, /* Kanbun */
467  { 0x31a0, 0x31bf, 51 }, /* Bopomofo Extended */
468  { 0x31f0, 0x31ff, 50 }, /* Katakana Phonetic Extensions */
469  { 0x3200, 0x32ff, 54 }, /* Enclosed CJK Letters and Months */
470  { 0x3300, 0x33ff, 55 }, /* CJK compatability */
471  { 0x3400, 0x4dbf, 59 }, /* CJK Unified Ideographs Extension A */
472  { 0x4dc0, 0x4dff, 99 }, /* Yijing Hexagram Symbols */
473  { 0x4e00, 0x9fff, 59 }, /* CJK Unified Ideographs */
474  { 0xa000, 0xa4cf, 81 }, /* Yi Syllables / Yi Radicals */
475  /*{ 0xA4d0, 0xA4ff, ? }, Lisu */
476  { 0xA500, 0xA62b, 12 }, /* Vai */
477  { 0xa640, 0xa69f, 9 }, /* Cyrillic Extended-B */
478  /*{ 0xa6a0, 0xa6ff, ? }, Bamum */
479  { 0xa700, 0xa71f, 5 }, /* Modifier Tone Letters */
480  { 0xa720, 0xa7ff, 29 }, /* Latin Extended-D */
481  { 0xA800, 0xA82F, 100 }, /* Syloti Nagri */
482  /*{ 0xa830, 0xa83f, ? }, Common Indic Number Forms */
483  { 0xa840, 0xa87f, 53 }, /* Phags-pa */
484  { 0xA880, 0xA8D9, 115 }, /* Saurashtra */
485  /*{ 0xA8E0, 0xA8FF, ? }, Devanagari Extended */
486  { 0xA900, 0xA92F, 116 }, /* Kayah Li */
487  { 0xA930, 0xA95F, 117 }, /* Rejang */
488  /*{ 0xA960, 0xA97F, 28? }, Hangul Jamo Extended-A */
489  /*{ 0xA980, 0xA9DF, ? }, Javanese */
490  { 0xAA00, 0xAA5F, 118 }, /* Cham */
491  /*{ 0xAA60, 0xAA7F, 74? }, Myanmar Extended-A */
492  /*{ 0xAA80, 0xAADF, ? }, Tai Viet */
493  /*{ 0xab00, 0xab2f, 75? }, Ethiopic Extended-A */
494  /*{ 0xabc0, 0xabff, ? }, Meetei Mayek */
495  { 0xac00, 0xd7af, 56 }, /* Hangul Syllables */
496  { 0xd800, 0xdfff, 57 }, /* Non-Plane 0 */
497  { 0xe000, 0xf8ff, 60 }, /* Private Use Area */
498 
499  { 0xf900, 0xfaff, 61 }, /* CJK Compatibility Ideographs */
500  /* 12 ideographs in The IBM 32 Compatibility Additions are CJK unified
501  ideographs despite their names: see The Unicode Standard 4.0, p.475 */
502  { 0xfa0e, 0xfa0f, 59 },
503  { 0xfa10, 0xfa10, 61 },
504  { 0xfa11, 0xfa11, 59 },
505  { 0xfa12, 0xfa12, 61 },
506  { 0xfa13, 0xfa14, 59 },
507  { 0xfa15, 0xfa1e, 61 },
508  { 0xfa1f, 0xfa1f, 59 },
509  { 0xfa20, 0xfa20, 61 },
510  { 0xfa21, 0xfa21, 59 },
511  { 0xfa22, 0xfa22, 61 },
512  { 0xfa23, 0xfa24, 59 },
513  { 0xfa25, 0xfa26, 61 },
514  { 0xfa27, 0xfa29, 59 },
515  { 0xfa2a, 0xfaff, 61 }, /* CJK Compatibility Ideographs */
516 
517  { 0xfb00, 0xfb4f, 62 }, /* Alphabetic Presentation Forms */
518  { 0xfb50, 0xfdff, 63 }, /* Arabic Presentation Forms-A */
519  { 0xfe00, 0xfe0f, 91 }, /* Variation Selectors */
520  { 0xfe20, 0xfe2f, 64 }, /* Combining Half Marks */
521  { 0xfe30, 0xfe4f, 65 }, /* CJK Compatibility Forms */
522  { 0xfe50, 0xfe6f, 66 }, /* Small Form Variants */
523  { 0xfe70, 0xfeef, 67 }, /* Arabic Presentation Forms-B */
524  { 0xff00, 0xffef, 68 }, /* Halfwidth and Fullwidth Forms */
525  { 0xfff0, 0xffff, 69 }, /* Specials */
526 
527  { 0x10000, 0x1007f, 101 }, /* Linear B Syllabary */
528  { 0x10080, 0x100ff, 101 }, /* Linear B Ideograms */
529  { 0x10100, 0x1013f, 101 }, /* Aegean Numbers */
530  { 0x10140, 0x1018F, 102 }, /* Ancient Greek Numbers */
531  { 0x10190, 0x101CF, 119 }, /* Ancient Symbols */
532  { 0x101D0, 0x101FF, 120 }, /* Phaistos Disc */
533  { 0x102A0, 0x102D0, 121 }, /* Carian */
534  { 0x10280, 0x1029C, 121 }, /* Lycian */
535  { 0x10300, 0x1032f, 85 }, /* Old Italic */
536  { 0x10330, 0x1034f, 86 }, /* Gothic */
537  { 0x10380, 0x1039F, 103 }, /* Ugaritic */
538  { 0x103A0, 0x103D6, 104 }, /* Old Persian */
539  { 0x10400, 0x1044f, 87 }, /* Deseret */
540  { 0x10450, 0x1047f, 105 }, /* Shavian */
541  { 0x10480, 0x104af, 106 }, /* Osmanya */
542  { 0x10800, 0x1083f, 107 }, /* Cypriot Syllabary */
543  /*{ 0x10840, 0x1085f, ? }, Imperial Aramaic */
544  { 0x10900, 0x1091f, 58 }, /* Phoenician */
545  { 0x10920, 0x10939, 121 }, /* Lydian */
546  { 0x10A00, 0x10A5F, 108 }, /* Kharoshthi */
547  /*{ 0x10A60, 0x10A7F, ? }, Old South Arabian */
548  /*{ 0x10B00, 0x10B3F, ? }, Avestan */
549  /*{ 0x10B40, 0x10B5F, ? }, Inscriptional Parthian */
550  /*{ 0x10B60, 0x10B7F, ? }, Inscriptional Pahlavi */
551  /*{ 0x10C00, 0x10C4F, ? }, Old Turkic */
552  /*{ 0x10E60, 0x10E7F, ? }, Rumi Numeral Symbols */
553  /*{ 0x11000, 0x1107F, ? }, Brahmi */
554  /*{ 0x11000, 0x1107F, ? }, Kaithi */
555  { 0x12000, 0x1247F, 110 }, /* Cuneiform; Numbers & Punctuation */
556  /*{ 0x13000, 0x1342F, ? }, Egyptian Hieroglyphs */
557  /*{ 0x16800, 0x16A3F, ? }, Bamum Supplement */
558  /*{ 0x1B000, 0x1B0FF, ? }, Kana Supplement */
559  { 0x1d000, 0x1d1ff, 88 }, /* Byzantine Musical Symbols / Musical Symbols */
560  /*{ 0x1D200, 0x1D24F, ? }, Ancient Greek Musical Notation */
561  { 0x1d300, 0x1d35f, 109 }, /* Tai Xuan Jing Symbols */
562  { 0x1D360, 0x1D37F, 111 }, /* Counting Rod Numerals */
563  { 0x1d400, 0x1d7ff, 89 }, /* Mathematical Alphanumeric Symbols */
564  { 0x1F000, 0x1F02B, 122 }, /* Mahjong Tiles */
565  { 0x1F030, 0x1F093, 122 }, /* Dominos */
566  /*{ 0x1F0A0, 0x1F0FF, ? }, Playing Cards */
567  /*{ 0x1F100, 0x1F1FF, ? }, Enclosed Alphanumeric Supplement */
568  /*{ 0x1F200, 0x1F2FF, ? }, Enclosed Ideographic Supplement */
569  /*{ 0x1F300, 0x1F5FF, ? }, Miscellaneous Symbols And Pictographs */
570  /*{ 0x1F600, 0x1F64F, ? }, Emoticons */
571  /*{ 0x1F680, 0x1F6FF, ? }, Transport And Map Symbols */
572  /*{ 0x1F700, 0x1F77F, ? }, Alchemical Symbols */
573  { 0x20000, 0x2a6df, 59 }, /* CJK Unified Ideographs Extension B */
574  /*{ 0x2A700, 0x2B73F, 59? }, CJK Unified Ideographs Extension C */
575  /*{ 0x2B740, 0x2B81F, 59? }, CJK Unified Ideographs Extension D */
576  { 0x2f800, 0x2fa1f, 61 }, /* CJK Compatibility Ideographs Supplement */
577  { 0xe0000, 0xe007f, 92 }, /* Tags */
578  { 0xe0100, 0xe01ef, 91 }, /* Variation Selectors Supplement */
579  { 0xf0000, 0xffffd, 90 }, /* Supplementary Private Use Area-A */
580  { 0x100000, 0x10fffd, 90 }, /* Supplementary Private Use Area-B */
581 };
582 
583 static int32 getuint32(FILE *ttf) {
584  int ch1 = getc(ttf);
585  int ch2 = getc(ttf);
586  int ch3 = getc(ttf);
587  int ch4 = getc(ttf);
588  if ( ch4==EOF )
589 return( EOF );
590 return( (ch1<<24)|(ch2<<16)|(ch3<<8)|ch4 );
591 }
592 
593 static int short_too_long_warned = 0;
594 
595 void putshort(FILE *file,int sval) {
596  if ( sval<-32768 || sval>65535 )
597  if (!short_too_long_warned) {
598  IError(_("Attempt to output %d into a 16-bit field. It will be truncated and the file may not be useful."), sval );
600  }
601  putc((sval>>8)&0xff,file);
602  putc(sval&0xff,file);
603 }
604 
605 static void putu24(FILE *file,int val) {
606  putc((val>>16)&0xff,file);
607  putc((val>>8)&0xff,file);
608  putc(val&0xff,file);
609 }
610 
611 void putlong(FILE *file,int val) {
612  putc((val>>24)&0xff,file);
613  putc((val>>16)&0xff,file);
614  putc((val>>8)&0xff,file);
615  putc(val&0xff,file);
616 }
617 #define dumpabsoffset putlong
618 
619 static void dumpoffset(FILE *file,int offsize,int val) {
620  if ( offsize==1 )
621  putc(val,file);
622  else if ( offsize==2 )
623  putshort(file,val);
624  else if ( offsize==3 ) {
625  putc((val>>16)&0xff,file);
626  putc((val>>8)&0xff,file);
627  putc(val&0xff,file);
628  } else
629  putlong(file,val);
630 }
631 
632 static void put2d14(FILE *file,real dval) {
633  int val;
634  int mant;
635 
636  val = floor(dval);
637  mant = floor(16384.*(dval-val));
638  val = (val<<14) | mant;
639  putshort(file,val);
640 }
641 
642 void putfixed(FILE *file,real dval) {
643  int val;
644  int mant;
645 
646  val = floor(dval);
647  mant = floor(65536.*(dval-val));
648  val = (val<<16) | mant;
649  putlong(file,val);
650 }
651 
652 int ttfcopyfile(FILE *ttf, FILE *other, int pos, const char *tab_name) {
653  int ch;
654  int ret = 1;
655 
656  if ( ferror(ttf) || ferror(other)) {
657  IError("Disk error of some nature. Perhaps no space on device?\nGenerated font will be unusable" );
658  } else if ( pos!=ftell(ttf)) {
659  IError("File Offset wrong for ttf table (%s), %d expected %d", tab_name, ftell(ttf), pos );
660  }
661  rewind(other);
662  while (( ch = getc(other))!=EOF )
663  putc(ch,ttf);
664  if ( ferror(other)) ret = 0;
665  if ( fclose(other)) ret = 0;
666 return( ret );
667 }
668 
669 static void FigureFullMetricsEnd(SplineFont *sf,struct glyphinfo *gi, int istt ) {
670  /* We can reduce the size of the width array by removing a run at the end */
671  /* of the same width. So start at the end, find the width of the last */
672  /* character we'll output, then run backwards as long as we've got the */
673  /* same width */
674  /* (do same thing for vertical metrics too */
675  int i, lasti, lastv, lastdefault = istt ? 3 : 1;
676  int width, vwidth;
677 
678  lasti = lastv = gi->gcnt-1;
679  for ( i=gi->gcnt-1; i>lastdefault && gi->bygid[i]==-1; --i );
680  if ( i>=lastdefault ) {
681  width = sf->glyphs[gi->bygid[i]]->width;
682  vwidth = sf->glyphs[gi->bygid[i]]->vwidth;
683  lasti = lastv = i;
684  for ( i=lasti-1; i>=lastdefault; --i ) {
685  if ( SCWorthOutputting(sf->glyphs[gi->bygid[i]]) ) {
686  if ( sf->glyphs[gi->bygid[i]]->width!=width )
687  break;
688  else
689  lasti = i;
690  }
691  }
692  gi->lasthwidth = lasti;
693  if ( sf->hasvmetrics ) {
694  for ( i=lastv-1; i>=lastdefault; --i ) {
695  if ( SCWorthOutputting(sf->glyphs[gi->bygid[i]]) ) {
696  if ( sf->glyphs[gi->bygid[i]]->vwidth!=vwidth )
697  break;
698  else
699  lastv = i;
700  }
701  }
702  gi->lastvwidth = lastv;
703  }
704  } else {
705  gi->lasthwidth = 0;
706  gi->lastvwidth = 0;
707  }
708 }
709 
710 static void dumpghstruct(struct glyphinfo *gi,struct glyphhead *gh) {
711 
712  putshort(gi->glyphs,gh->numContours);
713  putshort(gi->glyphs,gh->xmin);
714  putshort(gi->glyphs,gh->ymin);
715  putshort(gi->glyphs,gh->xmax);
716  putshort(gi->glyphs,gh->ymax);
717  if ( gh->xmin<gi->xmin ) gi->xmin = gh->xmin;
718  if ( gh->ymin<gi->ymin ) gi->ymin = gh->ymin;
719  if ( gh->xmax>gi->xmax ) gi->xmax = gh->xmax;
720  if ( gh->ymax>gi->ymax ) gi->ymax = gh->ymax;
721 }
722 
723 static void ttfdumpmetrics(SplineChar *sc,struct glyphinfo *gi,DBounds *b) {
724  int width=sc->width;
725  int vwidth=sc->vwidth;
726 
727  if ( width<0 ) width=0;
728  if ( vwidth<0 ) vwidth=0;
729 
730  if ( sc->ttf_glyph<=gi->lasthwidth )
731  putshort(gi->hmtx,width);
732  putshort(gi->hmtx,b->minx);
733  if ( sc->parent->hasvmetrics ) {
734  if ( sc->ttf_glyph<=gi->lastvwidth )
735  putshort(gi->vmtx,vwidth);
736  putshort(gi->vmtx, sc->parent->ascent - b->maxy);
737  }
738  if ( sc->ttf_glyph==gi->lasthwidth )
739  gi->hfullcnt = sc->ttf_glyph+1;
740  if ( sc->ttf_glyph==gi->lastvwidth )
741  gi->vfullcnt = sc->ttf_glyph+1;
742 }
743 
745  SplineSet *head=NULL, *last, *ss, *tss;
746  RefChar *ref;
747 
748  for ( ss=sc->layers[layer].splines; ss!=NULL; ss=ss->next ) {
749  tss = sc->layers[layer].order2 ? SplinePointListCopy1(ss) : SSttfApprox(ss);
750  if ( head==NULL ) head = tss;
751  else last->next = tss;
752  last = tss;
753  }
754  for ( ref=sc->layers[layer].refs; ref!=NULL; ref=ref->next ) {
755  for ( ss=ref->layers[0].splines; ss!=NULL; ss=ss->next ) {
756  tss = sc->layers[layer].order2 ? SplinePointListCopy1(ss) : SSttfApprox(ss);
757  if ( head==NULL ) head = tss;
758  else last->next = tss;
759  last = tss;
760  }
761  }
762 return( head );
763 }
764 
765 #define _On_Curve 1
766 #define _X_Short 2
767 #define _Y_Short 4
768 #define _Repeat 8
769 #define _X_Same 0x10
770 #define _Y_Same 0x20
771 
772 int SSAddPoints(SplineSet *ss,int ptcnt,BasePoint *bp, char *flags) {
773  SplinePoint *sp, *first, *nextsp;
774  int startcnt = ptcnt;
775 
776  if ( ss->first->prev!=NULL &&
777  ss->first->prev->from->nextcpindex==startcnt ) {
778  if ( flags!=NULL ) flags[ptcnt] = 0;
779  bp[ptcnt].x = rint(ss->first->prevcp.x);
780  bp[ptcnt++].y = rint(ss->first->prevcp.y);
781  } else if ( ss->first->ttfindex!=ptcnt && ss->first->ttfindex!=0xfffe )
782  IError("Unexpected point count in SSAddPoints" );
783 
784  first = NULL;
785  for ( sp=ss->first; sp!=first ; ) {
786  if ( sp->ttfindex!=0xffff ) {
787  if ( flags!=NULL ) flags[ptcnt] = _On_Curve;
788  bp[ptcnt].x = rint(sp->me.x);
789  bp[ptcnt].y = rint(sp->me.y);
790  sp->ttfindex = ptcnt++;
791  } else if ( !SPInterpolate( sp ) ) {
792  /* If an on curve point is midway between two off curve points*/
793  /* it may be omitted and will be interpolated on read in */
794  if ( flags!=NULL ) flags[ptcnt] = _On_Curve;
795  bp[ptcnt].x = rint(sp->me.x);
796  bp[ptcnt].y = rint(sp->me.y);
797  sp->ttfindex = ptcnt++;
798  }
799  nextsp = sp->next!=NULL ? sp->next->to : NULL;
800  if ( sp->nextcpindex == startcnt )
801  /* This control point is actually our first point, not our last */
802  break;
803  if ( (sp->nextcpindex !=0xffff && sp->nextcpindex!=0xfffe ) ||
804  !sp->nonextcp ) {
805  if ( flags!=NULL ) flags[ptcnt] = 0;
806  bp[ptcnt].x = rint(sp->nextcp.x);
807  bp[ptcnt++].y = rint(sp->nextcp.y);
808  }
809  if ( nextsp==NULL )
810  break;
811  if ( first==NULL ) first = sp;
812  sp = nextsp;
813  }
814 return( ptcnt );
815 }
816 
817 static void dumppointarrays(struct glyphinfo *gi,BasePoint *bp, char *fs, int pc) {
818  BasePoint last;
819  int i,flags;
820  int lastflag, flagcnt;
821 
822  if ( gi->maxp->maxPoints<pc )
823  gi->maxp->maxPoints = pc;
824 
825  /* flags */
826  last.x = last.y = 0;
827  lastflag = -1; flagcnt = 0;
828  for ( i=0; i<pc; ++i ) {
829  flags = 0;
830  if ( fs==NULL || fs[i] )
831  flags = _On_Curve; /* points are on curve */
832  if ( last.x==bp[i].x )
833  flags |= _X_Same;
834  else if ( bp[i].x-last.x>-256 && bp[i].x-last.x<255 ) {
835  flags |= _X_Short;
836  if ( bp[i].x>=last.x )
837  flags |= _X_Same; /* In this context it means positive */
838  }
839  if ( last.y==bp[i].y )
840  flags |= _Y_Same;
841  else if ( bp[i].y-last.y>-256 && bp[i].y-last.y<255 ) {
842  flags |= _Y_Short;
843  if ( bp[i].y>=last.y )
844  flags |= _Y_Same; /* In this context it means positive */
845  }
846  last = bp[i];
847  if ( lastflag==-1 ) {
848  lastflag = flags;
849  flagcnt = 0;
850  } else if ( flags!=lastflag ) {
851  if ( flagcnt!=0 )
852  lastflag |= _Repeat;
853  putc(lastflag,gi->glyphs);
854  if ( flagcnt!=0 )
855  putc(flagcnt,gi->glyphs);
856  lastflag = flags;
857  flagcnt = 0;
858  } else {
859  if ( ++flagcnt == 255 ) {
860  putc(lastflag|_Repeat,gi->glyphs);
861  putc(255,gi->glyphs);
862  lastflag = -1;
863  flagcnt = 0;
864  }
865  }
866  }
867  if ( lastflag!=-1 ) {
868  if ( flagcnt!=0 )
869  lastflag |= _Repeat;
870  putc(lastflag,gi->glyphs);
871  if ( flagcnt!=0 )
872  putc(flagcnt,gi->glyphs);
873  }
874 
875  /* xcoords */
876  last.x = 0;
877  for ( i=0; i<pc; ++i ) {
878  if ( last.x==bp[i].x )
879  /* Do Nothing */;
880  else if ( bp[i].x-last.x>-256 && bp[i].x-last.x<255 ) {
881  if ( bp[i].x>=last.x )
882  putc(bp[i].x-last.x,gi->glyphs);
883  else
884  putc(last.x-bp[i].x,gi->glyphs);
885  } else
886  putshort(gi->glyphs,bp[i].x-last.x);
887  last.x = bp[i].x;
888  }
889  /* ycoords */
890  last.y = 0;
891  for ( i=0; i<pc; ++i ) {
892  if ( last.y==bp[i].y )
893  /* Do Nothing */;
894  else if ( bp[i].y-last.y>-256 && bp[i].y-last.y<255 ) {
895  if ( bp[i].y>=last.y )
896  putc(bp[i].y-last.y,gi->glyphs);
897  else
898  putc(last.y-bp[i].y,gi->glyphs);
899  } else
900  putshort(gi->glyphs,bp[i].y-last.y);
901  last.y = bp[i].y;
902  }
903  if ( ftell(gi->glyphs)&1 ) /* Pad the file so that the next glyph */
904  putc('\0',gi->glyphs); /* on a word boundary */
905 }
906 
907 static void dumpinstrs(struct glyphinfo *gi,uint8 *instrs,int cnt) {
908  int i;
909 
910  if ( (gi->flags&ttf_flag_nohints) ) {
911  putshort(gi->glyphs,0);
912 return;
913  }
914  /* Do we ever want to call AutoHint and AutoInst here? I think not. */
915 
916  if ( gi->maxp->maxglyphInstr<cnt ) gi->maxp->maxglyphInstr=cnt;
917  putshort(gi->glyphs,cnt);
918  for ( i=0; i<cnt; ++i )
919  putc( instrs[i],gi->glyphs );
920 }
921 
922 static void dumpmissingglyph(SplineFont *sf,struct glyphinfo *gi,int fixedwidth) {
923  /* Or .notdef */
924  struct glyphhead gh;
925  BasePoint bp[10];
926  uint8 instrs[50];
927  int stemcvt, stem;
928  char *stempt;
929 
930  stem = 0;
931  if ( sf->private!=NULL && (stempt=PSDictHasEntry(sf->private,"StdVW"))!=NULL )
932  stem = strtod(stempt,NULL);
933  else if ( sf->private!=NULL && (stempt=PSDictHasEntry(sf->private,"StdHW"))!=NULL )
934  stem = strtod(stempt,NULL);
935  if ( stem<=0 )
936  stem = (sf->ascent+sf->descent)/30;
937 
938  gi->pointcounts[gi->next_glyph] = 8;
939  gi->loca[gi->next_glyph++] = ftell(gi->glyphs);
940  gi->maxp->maxContours = 2;
941 
942  gh.numContours = 2;
943  gh.ymin = 0;
944  gh.ymax = 2*(sf->ascent+sf->descent)/3;
945  gh.xmax = 5*stem+(sf->ascent+sf->descent)/10;
946  gh.xmin = stem;
947  gh.xmax += stem;
948  if ( gh.ymax>sf->ascent ) gh.ymax = sf->ascent;
949  dumpghstruct(gi,&gh);
950 
951  bp[0].x = stem; bp[0].y = 0;
952  bp[1].x = stem; bp[1].y = gh.ymax;
953  bp[2].x = gh.xmax; bp[2].y = gh.ymax;
954  bp[3].x = gh.xmax; bp[3].y = 0;
955 
956  bp[4].x = 2*stem; bp[4].y = stem;
957  bp[5].x = gh.xmax-stem; bp[5].y = stem;
958  bp[6].x = gh.xmax-stem; bp[6].y = gh.ymax-stem;
959  bp[7].x = 2*stem; bp[7].y = gh.ymax-stem;
960 
961  if ( !gi->ttc_composite_font ) {
962  stemcvt = TTF_getcvtval(gi->sf,stem);
963 
964  instrs[0] = 0xb1; /* Pushb, 2byte */
965  instrs[1] = 1; /* Point 1 */
966  instrs[2] = 0; /* Point 0 */
967  instrs[3] = 0x2f; /* MDAP, rounded (pt0) */
968  instrs[4] = 0x3c; /* ALIGNRP, (pt1 same pos as pt0)*/
969  instrs[5] = 0xb2; /* Pushb, 3byte */
970  instrs[6] = 7; /* Point 7 */
971  instrs[7] = 4; /* Point 4 */
972  instrs[8] = stemcvt; /* CVT entry for our stem width */
973  instrs[9] = 0xe0+0x0d; /* MIRP, don't set rp0, minimum, rounded, black */
974  instrs[10] = 0x32; /* SHP[rp2] (pt7 same pos as pt4) */
975  instrs[11] = 0xb1; /* Pushb, 2byte */
976  instrs[12] = 6; /* Point 6 */
977  instrs[13] = 5; /* Point 5 */
978  instrs[14] = 0xc0+0x1c; /* MDRP, set rp0, minimum, rounded, grey */
979  instrs[15] = 0x3c; /* ALIGNRP, (pt6 same pos as pt5)*/
980  instrs[16] = 0xb2; /* Pushb, 3byte */
981  instrs[17] = 3; /* Point 3 */
982  instrs[18] = 2; /* Point 2 */
983  instrs[19] = stemcvt; /* CVT entry for our stem width */
984  instrs[20] = 0xe0+0x0d; /* MIRP, dont set rp0, minimum, rounded, black */
985  instrs[21] = 0x32; /* SHP[rp2] (pt3 same pos as pt2) */
986 
987  instrs[22] = 0x00; /* SVTCA, y axis */
988 
989  instrs[23] = 0xb1; /* Pushb, 2byte */
990  instrs[24] = 3; /* Point 3 */
991  instrs[25] = 0; /* Point 0 */
992  instrs[26] = 0x2f; /* MDAP, rounded */
993  instrs[27] = 0x3c; /* ALIGNRP, (pt3 same height as pt0)*/
994  instrs[28] = 0xb2; /* Pushb, 3byte */
995  instrs[29] = 5; /* Point 5 */
996  instrs[30] = 4; /* Point 4 */
997  instrs[31] = stemcvt; /* CVT entry for our stem width */
998  instrs[32] = 0xe0+0x0d; /* MIRP, don't set rp0, minimum, rounded, black */
999  instrs[33] = 0x32; /* SHP[rp2] (pt5 same height as pt4) */
1000  instrs[34] = 0xb2; /* Pushb, 3byte */
1001  instrs[35] = 7; /* Point 7 */
1002  instrs[36] = 6; /* Point 6 */
1003  instrs[37] = TTF_getcvtval(gi->sf,bp[6].y); /* CVT entry for top height */
1004  instrs[38] = 0xe0+0x1c; /* MIRP, set rp0, minimum, rounded, grey */
1005  instrs[39] = 0x3c; /* ALIGNRP (pt7 same height as pt6) */
1006  instrs[40] = 0xb2; /* Pushb, 3byte */
1007  instrs[41] = 1; /* Point 1 */
1008  instrs[42] = 2; /* Point 2 */
1009  instrs[43] = stemcvt; /* CVT entry for our stem width */
1010  instrs[44] = 0xe0+0x0d; /* MIRP, dont set rp0, minimum, rounded, black */
1011  instrs[45] = 0x32; /* SHP[rp2] (pt1 same height as pt2) */
1012 
1013  /* We've touched all points in all dimensions */
1014  /* Don't need any IUP */
1015  }
1016 
1017  /* end contours array */
1018  putshort(gi->glyphs,4-1);
1019  putshort(gi->glyphs,8-1);
1020  /* instruction length&instructions */
1021  if ( !gi->ttc_composite_font )
1022  dumpinstrs(gi,instrs,46);
1023  else
1024  dumpinstrs(gi,NULL,0);
1025 
1026  dumppointarrays(gi,bp,NULL,8);
1027 
1028  if ( fixedwidth<=0 )
1029  putshort(gi->hmtx,gh.xmax + 2*stem);
1030  else
1031  putshort(gi->hmtx,fixedwidth);
1032  putshort(gi->hmtx,stem);
1033  if ( sf->hasvmetrics ) {
1034  putshort(gi->vmtx,sf->ascent+sf->descent);
1035  putshort(gi->vmtx,/*sf->vertical_origin-*/gh.ymax);
1036  }
1037 }
1038 
1039 static void dumpblankglyph(struct glyphinfo *gi,SplineFont *sf,int fixedwidth) {
1040  int advance = gi->next_glyph==1?0:fixedwidth<=0?(sf->ascent+sf->descent)/3:
1041  fixedwidth;
1042  /* For reasons quite obscure to me, glyph 1 has an advance width of 0 */
1043  /* even in a mono-spaced font like CourierNew.ttf */
1044 
1045  /* These don't get a glyph header, because there are no contours */
1046  gi->pointcounts[gi->next_glyph] = 0;
1047  gi->loca[gi->next_glyph++] = ftell(gi->glyphs);
1048  putshort(gi->hmtx,advance);
1049  putshort(gi->hmtx,0);
1050  if ( sf->hasvmetrics ) {
1051  putshort(gi->vmtx,gi->next_glyph==2?0:(sf->ascent+sf->descent));
1052  putshort(gi->vmtx,0);
1053  }
1054 }
1055 
1056 static void dumpspace(SplineChar *sc, struct glyphinfo *gi) {
1057  /* These don't get a glyph header, because there are no contours */
1058  DBounds b;
1059  gi->pointcounts[gi->next_glyph] = 0;
1060  gi->loca[gi->next_glyph++] = ftell(gi->glyphs);
1061  memset(&b,0,sizeof(b));
1062  ttfdumpmetrics(sc,gi,&b);
1063 }
1064 
1065 static int IsTTFRefable(SplineChar *sc,int layer) {
1066  RefChar *ref;
1067 
1068  if ( sc->layers[layer].refs==NULL || sc->layers[layer].splines!=NULL )
1069 return( false );
1070 
1071  for ( ref=sc->layers[layer].refs; ref!=NULL; ref=ref->next ) {
1072  if ( ref->transform[0]<-2 || ref->transform[0]>1.999939 ||
1073  ref->transform[1]<-2 || ref->transform[1]>1.999939 ||
1074  ref->transform[2]<-2 || ref->transform[2]>1.999939 ||
1075  ref->transform[3]<-2 || ref->transform[3]>1.999939 )
1076 return( false );
1077  }
1078 return( true );
1079 }
1080 
1082  int rd, temp;
1083  SplineChar *sc = ref->sc;
1084 
1085  if ( sc->layers[layer].refs==NULL || sc->layers[layer].splines!=NULL )
1086 return( 1 );
1087  rd = 0;
1088  for ( ref = sc->layers[layer].refs; ref!=NULL; ref=ref->next ) {
1089  if ( ref->transform[0]>=-2 || ref->transform[0]<=1.999939 ||
1090  ref->transform[1]>=-2 || ref->transform[1]<=1.999939 ||
1091  ref->transform[2]>=-2 || ref->transform[2]<=1.999939 ||
1092  ref->transform[3]>=-2 || ref->transform[3]<=1.999939 ) {
1093  temp = RefDepth(ref,layer);
1094  if ( temp>rd ) rd = temp;
1095  }
1096  }
1097 return( rd+1 );
1098 }
1099 
1100 static void CountCompositeMaxPts(SplineChar *sc,struct glyphinfo *gi) {
1101  RefChar *ref;
1102  int ptcnt = 0, index;
1103 
1104  for ( ref=sc->layers[gi->layer].refs; ref!=NULL; ref=ref->next ) {
1105  if ( ref->sc->ttf_glyph==-1 )
1106  continue;
1107  index = ref->sc->ttf_glyph;
1108  if ( gi->pointcounts[index]==-1 )
1109  CountCompositeMaxPts(ref->sc,gi);
1110  ptcnt += gi->pointcounts[index];
1111  }
1112  gi->pointcounts[sc->ttf_glyph] = ptcnt;
1113  if ( gi->maxp->maxCompositPts<ptcnt ) gi->maxp->maxCompositPts=ptcnt;
1114 }
1115 
1116 /* In order3 fonts we figure out the composite point counts at the end */
1117 /* when we know how many points are in each sub-glyph */
1119  int i;
1120 
1121  for ( i=0; i<gi->gcnt; ++i ) if ( gi->bygid[i]!=-1 && sf->glyphs[gi->bygid[i]]->ttf_glyph!=-1 ) {
1122  if ( sf->glyphs[gi->bygid[i]]->layers[gi->layer].splines==NULL &&
1123  sf->glyphs[gi->bygid[i]]->layers[gi->layer].refs!=NULL &&
1124  gi->pointcounts[i]== -1 )
1125  CountCompositeMaxPts(sf->glyphs[gi->bygid[i]],gi);
1126  }
1127 }
1128 
1129 static void dumpcomposite(SplineChar *sc, struct glyphinfo *gi) {
1130  struct glyphhead gh;
1131  DBounds bb;
1132  int i, ptcnt, ctcnt, flags, sptcnt, rd;
1133  SplineSet *ss;
1134  RefChar *ref;
1135  SplineChar *isc = sc->ttf_instrs==NULL && sc->parent->mm!=NULL && sc->parent->mm->apple ?
1136  sc->parent->mm->normal->glyphs[sc->orig_pos] : sc;
1137  int arg1, arg2;
1138 
1139  if ( gi->next_glyph!=sc->ttf_glyph )
1140  IError("Glyph count wrong in ttf output");
1141  if ( gi->next_glyph>=gi->maxp->numGlyphs )
1142  IError("max glyph count wrong in ttf output");
1143  gi->loca[gi->next_glyph] = ftell(gi->glyphs);
1144 
1146  gh.numContours = -1;
1147  gh.xmin = floor(bb.minx); gh.ymin = floor(bb.miny);
1148  gh.xmax = ceil(bb.maxx); gh.ymax = ceil(bb.maxy);
1149  dumpghstruct(gi,&gh);
1150 
1151  i=ptcnt=ctcnt=0;
1152  for ( ref=sc->layers[gi->layer].refs; ref!=NULL; ref=ref->next, ++i ) {
1153  if ( ref->sc->ttf_glyph==-1 ) {
1154  /*if ( sc->layers[gi->layer].refs->next==NULL || any )*/
1155  continue;
1156  }
1157  flags = 0;
1158  if ( ref->round_translation_to_grid )
1159  flags |= _ROUND;
1160  if ( ref->use_my_metrics )
1162  if ( ref->next!=NULL )
1163  flags |= _MORE; /* More components */
1164  else if ( isc->ttf_instrs_len!=0 ) /* Composits also inherit instructions */
1165  flags |= _INSTR; /* Instructions appear after last ref */
1166  if ( ref->transform[1]!=0 || ref->transform[2]!=0 )
1167  flags |= _MATRIX; /* Need a full matrix */
1168  else if ( ref->transform[0]!=ref->transform[3] )
1169  flags |= _XY_SCALE; /* different xy scales */
1170  else if ( ref->transform[0]!=1. )
1171  flags |= _SCALE; /* xy scale is same */
1172  if ( ref->point_match ) {
1173  arg1 = ref->match_pt_base;
1174  arg2 = ref->match_pt_ref;
1175  } else {
1176  arg1 = rint(ref->transform[4]);
1177  arg2 = rint(ref->transform[5]);
1179  /* The values I output are the values I want to see */
1180  /* There is some very strange stuff wrongly-documented on the apple*/
1181  /* site about how these should be interpretted when there are */
1182  /* scale factors, or rotations */
1183  /* That description does not match the behavior of their rasterizer*/
1184  /* I've reverse engineered something else (see parsettf.c) */
1185  /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
1186  /* Adobe says that setting bit 12 means that this will not happen */
1187  /* Apple doesn't mention bit 12 though...(but they do support it) */
1188  }
1189  if ( arg1<-128 || arg1>127 ||
1190  arg2<-128 || arg2>127 )
1192  putshort(gi->glyphs,flags);
1193  putshort(gi->glyphs,ref->sc->ttf_glyph==-1?0:ref->sc->ttf_glyph);
1194  if ( flags&_ARGS_ARE_WORDS ) {
1195  putshort(gi->glyphs,(short)arg1);
1196  putshort(gi->glyphs,(short)arg2);
1197  } else {
1198  putc((char) arg1,gi->glyphs);
1199  putc((char) arg2,gi->glyphs);
1200  }
1201  if ( flags&_MATRIX ) {
1202  put2d14(gi->glyphs,ref->transform[0]);
1203  put2d14(gi->glyphs,ref->transform[1]);
1204  put2d14(gi->glyphs,ref->transform[2]);
1205  put2d14(gi->glyphs,ref->transform[3]);
1206  } else if ( flags&_XY_SCALE ) {
1207  put2d14(gi->glyphs,ref->transform[0]);
1208  put2d14(gi->glyphs,ref->transform[3]);
1209  } else if ( flags&_SCALE ) {
1210  put2d14(gi->glyphs,ref->transform[0]);
1211  }
1212  sptcnt = SSTtfNumberPoints(ref->layers[0].splines);
1213  for ( ss=ref->layers[0].splines; ss!=NULL ; ss=ss->next ) {
1214  ++ctcnt;
1215  }
1216  if ( sc->layers[gi->layer].order2 )
1217  ptcnt += sptcnt;
1218  else if ( ptcnt>=0 && gi->pointcounts[ref->sc->ttf_glyph==-1?0:ref->sc->ttf_glyph]>=0 )
1219  ptcnt += gi->pointcounts[ref->sc->ttf_glyph==-1?0:ref->sc->ttf_glyph];
1220  else
1221  ptcnt = -1;
1222  rd = RefDepth(ref,gi->layer);
1223  if ( rd>gi->maxp->maxcomponentdepth )
1224  gi->maxp->maxcomponentdepth = rd;
1225  }
1226 
1227  if ( isc->ttf_instrs_len!=0 )
1228  dumpinstrs(gi,isc->ttf_instrs,isc->ttf_instrs_len);
1229 
1230  gi->pointcounts[gi->next_glyph++] = ptcnt;
1231  if ( gi->maxp->maxnumcomponents<i ) gi->maxp->maxnumcomponents = i;
1232  if ( gi->maxp->maxCompositPts<ptcnt ) gi->maxp->maxCompositPts=ptcnt;
1233  if ( gi->maxp->maxCompositCtrs<ctcnt ) gi->maxp->maxCompositCtrs=ctcnt;
1234 
1235  ttfdumpmetrics(sc,gi,&bb);
1236  if ( ftell(gi->glyphs)&1 ) /* Pad the file so that the next glyph */
1237  putc('\0',gi->glyphs); /* on a word boundary, can only happen if odd number of instrs */
1238 }
1239 
1240 static void dumpglyph(SplineChar *sc, struct glyphinfo *gi) {
1241  struct glyphhead gh;
1242  DBounds bb;
1243  SplineSet *ss, *ttfss;
1244  int contourcnt, ptcnt, origptcnt;
1245  BasePoint *bp;
1246  char *fs;
1247  SplineChar *isc = sc->ttf_instrs==NULL && sc->parent->mm!=NULL && sc->parent->mm->apple ?
1248  sc->parent->mm->normal->glyphs[sc->orig_pos] : sc;
1249 
1250  /* This must have been an error on my part, can't just remove points */
1251  /* they might be matched to anchors or something */
1252 /* I haven't seen this documented, but ttf rasterizers are unhappy with a */
1253 /* glyph that consists of a single point. Glyphs containing two single points*/
1254 /* are ok, glyphs with a single point and anything else are ok, glyphs with */
1255 /* a line are ok. But a single point is not ok. Dunno why */
1256  if ( sc->layers[gi->layer].splines==NULL && sc->layers[gi->layer].refs==NULL ) {
1257  dumpspace(sc,gi);
1258 return;
1259  }
1260 
1261  if ( gi->next_glyph!=sc->ttf_glyph )
1262  IError("Glyph count wrong in ttf output");
1263  if ( gi->next_glyph>=gi->maxp->numGlyphs )
1264  IError("max glyph count wrong in ttf output");
1265  gi->loca[gi->next_glyph] = ftell(gi->glyphs);
1266 
1267  ttfss = SCttfApprox(sc,gi->layer);
1268  ptcnt = SSTtfNumberPoints(ttfss);
1269  for ( ss=ttfss, contourcnt=0; ss!=NULL; ss=ss->next ) {
1270  ++contourcnt;
1271  }
1272  origptcnt = ptcnt;
1273 
1274  SplineSetQuickBounds(ttfss,&bb);
1275  gh.numContours = contourcnt;
1276  gh.xmin = floor(bb.minx); gh.ymin = floor(bb.miny);
1277  gh.xmax = ceil(bb.maxx); gh.ymax = ceil(bb.maxy);
1278  dumpghstruct(gi,&gh);
1279  if ( contourcnt>gi->maxp->maxContours ) gi->maxp->maxContours = contourcnt;
1280  if ( ptcnt>gi->maxp->maxPoints ) gi->maxp->maxPoints = ptcnt;
1281 
1282  bp = malloc(ptcnt*sizeof(BasePoint));
1283  fs = malloc(ptcnt);
1284  ptcnt = contourcnt = 0;
1285  for ( ss=ttfss; ss!=NULL; ss=ss->next ) {
1286  ptcnt = SSAddPoints(ss,ptcnt,bp,fs);
1287  putshort(gi->glyphs,ptcnt-1);
1288  }
1289  if ( ptcnt!=origptcnt )
1290  IError( "Point count wrong calculated=%d, actual=%d in %.20s", origptcnt, ptcnt, sc->name );
1291  gi->pointcounts[gi->next_glyph++] = ptcnt;
1292 
1293  dumpinstrs(gi,isc->ttf_instrs,isc->ttf_instrs_len);
1294 
1295  dumppointarrays(gi,bp,fs,ptcnt);
1296  SplinePointListsFree(ttfss);
1297  free(bp);
1298  free(fs);
1299 
1300  ttfdumpmetrics(sc,gi,&bb);
1301 }
1302 
1304  int i,j,k,max;
1305  int *bygid;
1306 
1307  max = 0;
1308  for ( k=0; k<sf->subfontcnt; ++k )
1309  if ( sf->subfonts[k]->glyphcnt>max ) max = sf->subfonts[k]->glyphcnt;
1310  if ( max == 0 )
1311 return;
1312 
1313  sf->glyphs = calloc(max,sizeof(SplineChar *));
1314  sf->glyphcnt = sf->glyphmax = max;
1315  for ( k=0; k<sf->subfontcnt; ++k )
1316  for ( i=0; i<sf->subfonts[k]->glyphcnt; ++i ) if ( sf->subfonts[k]->glyphs[i]!=NULL )
1317  sf->glyphs[i] = sf->subfonts[k]->glyphs[i];
1318 
1319  if ( gi==NULL )
1320 return;
1321 
1322  bygid = malloc((sf->glyphcnt+3)*sizeof(int));
1323  memset(bygid,0xff, (sf->glyphcnt+3)*sizeof(int));
1324 
1325  j=1;
1326  for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
1327  if ( bygid[0]== -1 && strcmp(sf->glyphs[i]->name,".notdef")==0 ) {
1328  sf->glyphs[i]->ttf_glyph = 0;
1329  bygid[0] = i;
1330  } else if ( SCWorthOutputting(sf->glyphs[i])) {
1331  sf->glyphs[i]->ttf_glyph = j;
1332  bygid[j++] = i;
1333  }
1334  }
1335  gi->bygid = bygid;
1336  gi->gcnt = j;
1337 }
1338 
1339 static void AssignNotdefNull(SplineFont *sf,int *bygid, int iscff) {
1340  int i;
1341 
1342  /* The first three glyphs are magic, glyph 0 is .notdef */
1343  /* glyph 1 is .null and glyph 2 is nonmarking return */
1344  /* We may generate them automagically */
1345  for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
1346  if ( bygid[0]== -1 && strcmp(sf->glyphs[i]->name,".notdef")==0 ) {
1347  sf->glyphs[i]->ttf_glyph = 0;
1348  bygid[0] = i;
1349  } else if ( !iscff && bygid[1]== -1 &&
1350  (strcmp(sf->glyphs[i]->name,".null")==0 ||
1351  strcmp(sf->glyphs[i]->name,"uni0000")==0 ||
1352  (i==1 && strcmp(sf->glyphs[1]->name,"glyph1")==0)) ) {
1353  sf->glyphs[i]->ttf_glyph = 1;
1354  bygid[1] = i;
1355  } else if ( !iscff && bygid[2]== -1 &&
1356  (strcmp(sf->glyphs[i]->name,"nonmarkingreturn")==0 ||
1357  strcmp(sf->glyphs[i]->name,"uni000D")==0 ||
1358  (i==2 && strcmp(sf->glyphs[2]->name,"glyph2")==0)) ) {
1359  sf->glyphs[i]->ttf_glyph = 2;
1360  bygid[2] = i;
1361  }
1362  }
1363 }
1364 
1365 static int AssignTTFGlyph(struct glyphinfo *gi,SplineFont *sf,EncMap *map,int iscff) {
1366  int *bygid = malloc((sf->glyphcnt+3)*sizeof(int));
1367  int i,j;
1368 
1369  memset(bygid,0xff, (sf->glyphcnt+3)*sizeof(int));
1370 
1371  AssignNotdefNull(sf,bygid,iscff);
1372 
1373  j = iscff ? 1 : 3;
1374  for ( i=0; i<map->enccount; ++i ) if ( map->map[i]!=-1 ) {
1375  SplineChar *sc = sf->glyphs[map->map[i]];
1376  if ( SCWorthOutputting(sc) && sc->ttf_glyph==-1
1377 #if HANYANG
1378  && (!iscff || !sc->compositionunit)
1379 #endif
1380  ) {
1381  sc->ttf_glyph = j;
1382  bygid[j++] = sc->orig_pos;
1383  }
1384  }
1385 
1386  for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
1387  SplineChar *sc = sf->glyphs[i];
1388  if ( SCWorthOutputting(sc) && sc->ttf_glyph==-1
1389 #if HANYANG
1390  && (!iscff || !sc->compositionunit)
1391 #endif
1392  ) {
1393  sc->ttf_glyph = j;
1394  bygid[j++] = i;
1395  }
1396  }
1397  gi->bygid = bygid;
1398  gi->gcnt = j;
1399 return j;
1400 }
1401 
1402 static int dumpglyphs(SplineFont *sf,struct glyphinfo *gi) {
1403  int i;
1404  int fixed = gi->fixed_width;
1405 
1407  QuickBlues(sf,gi->layer,&gi->bd);
1408  /*FindBlues(sf,gi->blues,NULL);*/
1410 
1411  if ( !gi->onlybitmaps ) {
1412  if ( sf->layers[gi->layer].order2 )
1413  for ( i=0; i<sf->glyphcnt; ++i ) {
1414  SplineChar *sc = sf->glyphs[i];
1415  if ( SCWorthOutputting(sc) )
1416  if ( !SCPointsNumberedProperly(sc,gi->layer)) {
1417  free(sc->ttf_instrs); sc->ttf_instrs = NULL;
1418  sc->ttf_instrs_len = 0;
1419  SCNumberPoints(sc,gi->layer);
1420  }
1421  }
1422  }
1423 
1424  gi->maxp->numGlyphs = gi->gcnt;
1425  gi->loca = malloc((gi->maxp->numGlyphs+1)*sizeof(uint32));
1426  gi->pointcounts = malloc((gi->maxp->numGlyphs+1)*sizeof(int32));
1427  memset(gi->pointcounts,-1,(gi->maxp->numGlyphs+1)*sizeof(int32));
1428  gi->next_glyph = 0;
1429  gi->glyphs = tmpfile2();
1430  gi->hmtx = tmpfile2();
1431  if ( sf->hasvmetrics )
1432  gi->vmtx = tmpfile2();
1433  FigureFullMetricsEnd(sf,gi,true);
1434 
1435  if ( fixed>0 ) {
1436  gi->lasthwidth = 3;
1437  gi->hfullcnt = 3;
1438  }
1439  for ( i=0; i<gi->gcnt; ++i ) {
1440  if ( i==0 ) {
1441  if ( gi->bygid[0]!=-1 && (fixed<=0 || sf->glyphs[gi->bygid[0]]->width==fixed))
1442  dumpglyph(sf->glyphs[gi->bygid[0]],gi);
1443  else
1445  } else if ( i<=2 && gi->bygid[i]==-1 )
1446  dumpblankglyph(gi,sf,fixed);
1447  else if ( gi->onlybitmaps ) {
1448  if ( gi->bygid[i]!=-1 && sf->glyphs[gi->bygid[i]]->ttf_glyph>0 )
1449  dumpspace(sf->glyphs[gi->bygid[i]],gi);
1450  } else {
1451  if ( gi->bygid[i]!=-1 && sf->glyphs[gi->bygid[i]]->ttf_glyph>0 ) {
1452  if ( IsTTFRefable(sf->glyphs[gi->bygid[i]],gi->layer) )
1453  dumpcomposite(sf->glyphs[gi->bygid[i]],gi);
1454  else
1455  dumpglyph(sf->glyphs[gi->bygid[i]],gi);
1456  }
1457  }
1458  if ( (ftell(gi->glyphs)&3) != 0 ) {
1459  /* Apple says glyphs must be 16bit aligned */
1460  if ( ftell(gi->glyphs)&1 )
1461  putc('\0',gi->glyphs);
1462  /* MS says glyphs should be 32bit aligned */
1463  if ( ftell(gi->glyphs)&2 )
1464  putshort(gi->glyphs,0);
1465  }
1466  if ( !ff_progress_next())
1467 return( false );
1468  }
1469 
1470  /* extra location entry points to end of last glyph */
1471  gi->loca[gi->next_glyph] = ftell(gi->glyphs);
1472  /* Microsoft's Font Validator wants the last loca entry to point into the */
1473  /* glyph table. I think that's an error on their part, but it's so easy */
1474  /* to fix, I might as well (instead of pointing to right after the table)*/
1475  /* Sigh. But if I do that, it complains that there's extra stuff in the */
1476  /* glyph table. There's just no pleasing them */
1477  /* putlong(gi->glyphs,0);*/
1478  gi->glyph_len = ftell(gi->glyphs);
1479  gi->hmtxlen = ftell(gi->hmtx);
1480  /* pad out to four bytes */
1481  if ( gi->hmtxlen&2 ) putshort(gi->hmtx,0);
1482  if ( gi->loca[gi->next_glyph]&3 ) {
1483  for ( i=4-(gi->loca[gi->next_glyph]&3); i>0; --i )
1484  putc('\0',gi->glyphs);
1485  }
1486  if ( sf->hasvmetrics ) {
1487  gi->vmtxlen = ftell(gi->vmtx);
1488  if ( gi->vmtxlen&2 ) putshort(gi->vmtx,0);
1489  }
1490  if ( !sf->layers[gi->layer].order2 )
1492  free(gi->pointcounts);
1493 
1494 return( true );
1495 }
1496 
1497 static int storesid(struct alltabs *at,const char *str) {
1498  int i;
1499  FILE *news;
1500  const char *pt;
1501  long pos;
1502 
1503  if ( str!=NULL ) { /* NULL is the magic string at end of array */
1504  for ( i=0; cffnames[i]!=NULL; ++i ) {
1505  if ( strcmp(cffnames[i],str)==0 )
1506 return( i );
1507  }
1508  }
1509 
1510  pos = ftell(at->sidf)+1;
1511  if ( pos>=65536 && !at->sidlongoffset ) {
1512  at->sidlongoffset = true;
1513  news = tmpfile2();
1514  rewind(at->sidh);
1515  for ( i=0; i<at->sidcnt; ++i )
1516  putlong(news,getushort(at->sidh));
1517  fclose(at->sidh);
1518  at->sidh = news;
1519  }
1520  if ( at->sidlongoffset )
1521  putlong(at->sidh,pos);
1522  else
1523  putshort(at->sidh,pos);
1524 
1525  if ( str!=NULL ) {
1526  for ( pt=str; *pt; ++pt )
1527  putc(*pt,at->sidf);
1528  }
1529 return( at->sidcnt++ + nStdStrings );
1530 }
1531 
1532 static void dumpint(FILE *cfff,int num) {
1533 
1534  if ( num>=-107 && num<=107 )
1535  putc(num+139,cfff);
1536  else if ( num>=108 && num<=1131 ) {
1537  num -= 108;
1538  putc((num>>8)+247,cfff);
1539  putc(num&0xff,cfff);
1540  } else if ( num>=-1131 && num<=-108 ) {
1541  num = -num;
1542  num -= 108;
1543  putc((num>>8)+251,cfff);
1544  putc(num&0xff,cfff);
1545  } else if ( num>=-32768 && num<32768 ) {
1546  putc(28,cfff);
1547  putc(num>>8,cfff);
1548  putc(num&0xff,cfff);
1549  } else { /* In dict data we have 4 byte ints, in type2 strings we don't */
1550  putc(29,cfff);
1551  putc((num>>24)&0xff,cfff);
1552  putc((num>>16)&0xff,cfff);
1553  putc((num>>8)&0xff,cfff);
1554  putc(num&0xff,cfff);
1555  }
1556 }
1557 
1558 static void dumpdbl(FILE *cfff,double d) {
1559  if ( d-rint(d)>-.00001 && d-rint(d)<.00001 )
1560  dumpint(cfff,(int) d);
1561  else {
1562  /* The type2 strings have a fixed format, but the dict data does not */
1563  char buffer[20], *pt;
1564  int sofar,n,odd;
1565  sprintf( buffer, "%g", d);
1566  sofar = 0; odd=true;
1567  putc(30,cfff); /* Start a double */
1568  for ( pt=buffer; *pt; ++pt ) {
1569  if ( isdigit(*pt) )
1570  n = *pt-'0';
1571  else if ( *pt=='.' )
1572  n = 0xa;
1573  else if ( *pt=='-' )
1574  n = 0xe;
1575  else if (( *pt=='E' || *pt=='e') && pt[1]=='-' ) {
1576  n = 0xc;
1577  ++pt;
1578  } else if ( *pt=='E' || *pt=='e')
1579  n = 0xb;
1580  else
1581  n = 0; /* Should never happen */
1582  if ( odd ) {
1583  sofar = n<<4;
1584  odd = false;
1585  } else {
1586  putc(sofar|n,cfff);
1587  sofar=0;
1588  odd = true;
1589  }
1590  }
1591  if ( sofar==0 )
1592  putc(0xff,cfff);
1593  else
1594  putc(sofar|0xf,cfff);
1595  }
1596 }
1597 
1598 static void dumpoper(FILE *cfff,int oper ) {
1599  if ( oper!=-1 ) {
1600  if ( oper>=256 )
1601  putc(oper>>8,cfff);
1602  putc(oper&0xff,cfff);
1603  }
1604 }
1605 
1606 static void dumpdbloper(FILE *cfff,double d, int oper ) {
1607  dumpdbl(cfff,d);
1608  dumpoper(cfff,oper);
1609 }
1610 
1611 static void dumpintoper(FILE *cfff,int v, int oper ) {
1612  dumpint(cfff,v);
1613  dumpoper(cfff,oper);
1614 }
1615 
1616 static void dumpsizedint(FILE *cfff,int big,int num, int oper ) {
1617  if ( big ) {
1618  putc(29,cfff);
1619  putc((num>>24)&0xff,cfff);
1620  putc((num>>16)&0xff,cfff);
1621  putc((num>>8)&0xff,cfff);
1622  putc(num&0xff,cfff);
1623  } else {
1624  putc(28,cfff);
1625  putc(num>>8,cfff);
1626  putc(num&0xff,cfff);
1627  }
1628  dumpoper(cfff,oper);
1629 }
1630 
1631 static void dumpsid(FILE *cfff,struct alltabs *at,char *str,int oper) {
1632  if ( str==NULL )
1633 return;
1634  dumpint(cfff,storesid(at,str));
1635  dumpoper(cfff,oper);
1636 }
1637 
1638 static void DumpStrDouble(char *pt,FILE *cfff,int oper) {
1639  real d;
1640  if ( *pt=='[' ) ++pt; /* For StdHW, StdVW */
1641  d = strtod(pt,NULL);
1642  dumpdbloper(cfff,d,oper);
1643 }
1644 
1645 static void DumpDblArray(real *arr,int n,FILE *cfff, int oper) {
1646  int mi,i;
1647 
1648  for ( mi=n-1; mi>=0 && arr[mi]==0; --mi );
1649  if ( mi<0 )
1650 return;
1651  dumpdbl(cfff,arr[0]);
1652  for ( i=1; i<=mi; ++i )
1653  dumpdbl(cfff,arr[i]-arr[i-1]);
1654  dumpoper(cfff,oper);
1655 }
1656 
1657 static void DumpStrArray(char *pt,FILE *cfff,int oper) {
1658  real d, last=0;
1659  char *end;
1660 
1661  while ( *pt==' ' ) ++pt;
1662  if ( *pt=='\0' )
1663 return;
1664  if ( *pt=='[' ) ++pt;
1665  while ( *pt==' ' ) ++pt;
1666  while ( *pt!=']' && *pt!='\0' ) {
1667  d = strtod(pt,&end);
1668  if ( pt==end ) /* User screwed up. Should be a number */
1669  break;
1670  dumpdbl(cfff,d-last);
1671  last = d;
1672  pt = end;
1673  while ( *pt==' ' ) ++pt;
1674  }
1675  dumpoper(cfff,oper);
1676 }
1677 
1678 static void dumpcffheader(FILE *cfff) {
1679  putc('\1',cfff); /* Major version: 1 */
1680  putc('\0',cfff); /* Minor version: 0 */
1681  putc('\4',cfff); /* Header size in bytes */
1682  putc('\4',cfff); /* Absolute Offset size. */
1683  /* I don't think there are any absolute offsets that aren't encoded */
1684  /* in a dict as numbers (ie. inherently variable sized items) */
1685 }
1686 
1687 static void dumpcffnames(SplineFont *sf,FILE *cfff) {
1688  char *pt;
1689 
1690  putshort(cfff,1); /* One font name */
1691  putc('\1',cfff); /* Offset size */
1692  putc('\1',cfff); /* Offset to first name */
1693  putc('\1'+strlen(sf->fontname),cfff);
1694  for ( pt=sf->fontname; *pt; ++pt )
1695  putc(*pt,cfff);
1696 }
1697 
1698 static void dumpcffcharset(SplineFont *sf,struct alltabs *at) {
1699  int i;
1700 
1701  at->gn_sid = calloc(at->gi.gcnt,sizeof(uint32));
1702  putc(0,at->charset);
1703  /* I always use a format 0 charset. ie. an array of SIDs in random order */
1704 
1705  /* First element must be ".notdef" and is omitted */
1706 
1707  for ( i=1; i<at->gi.gcnt; ++i )
1708  if ( at->gi.bygid[i]!=-1 && SCWorthOutputting(sf->glyphs[at->gi.bygid[i]])) {
1709  at->gn_sid[i] = storesid(at,sf->glyphs[at->gi.bygid[i]]->name);
1710  putshort(at->charset,at->gn_sid[i]);
1711  }
1712 }
1713 
1714 static void dumpcffcidset(struct alltabs *at) {
1715  int gid, start;
1716 
1717  putc(2,at->charset);
1718 
1719  start = -1; /* Glyph 0 always maps to CID 0, and is omitted */
1720  for ( gid = 1; gid<at->gi.gcnt; ++gid ) {
1721  if ( start==-1 )
1722  start = gid;
1723  else if ( at->gi.bygid[gid]-at->gi.bygid[start]!=gid-start ) {
1724  putshort(at->charset,at->gi.bygid[start]);
1725  putshort(at->charset,at->gi.bygid[gid-1]-at->gi.bygid[start]);
1726  start = gid;
1727  }
1728  }
1729  if ( start!=-1 ) {
1730  putshort(at->charset,at->gi.bygid[start]);
1731  putshort(at->charset,at->gi.bygid[gid-1]-at->gi.bygid[start]);
1732  }
1733 }
1734 
1735 static void dumpcfffdselect(SplineFont *sf,struct alltabs *at) {
1736  int cid, k, lastfd, cnt;
1737  int gid;
1738 
1739  putc(3,at->fdselect);
1740  putshort(at->fdselect,0); /* number of ranges, fill in later */
1741 
1742  for ( k=0; k<sf->subfontcnt; ++k )
1743  if ( SCWorthOutputting(sf->subfonts[k]->glyphs[0]))
1744  break;
1745  if ( k==sf->subfontcnt ) --k; /* If CID 0 not defined, put it in last font */
1746  putshort(at->fdselect,0);
1747  putc(k,at->fdselect);
1748  lastfd = k;
1749  cnt = 1;
1750  for ( gid = 1; gid<at->gi.gcnt; ++gid ) {
1751  cid = at->gi.bygid[gid];
1752  for ( k=0; k<sf->subfontcnt; ++k ) {
1753  if ( cid<sf->subfonts[k]->glyphcnt &&
1754  SCWorthOutputting(sf->subfonts[k]->glyphs[cid]) )
1755  break;
1756  }
1757  if ( k==sf->subfontcnt )
1758  /* Doesn't map to a glyph, irrelevant */;
1759  else {
1760  if ( k!=lastfd ) {
1761  putshort(at->fdselect,gid);
1762  putc(k,at->fdselect);
1763  lastfd = k;
1764  ++cnt;
1765  }
1766  }
1767  }
1768  putshort(at->fdselect,gid);
1769  fseek(at->fdselect,1,SEEK_SET);
1770  putshort(at->fdselect,cnt);
1771  fseek(at->fdselect,0,SEEK_END);
1772 }
1773 
1774 static void dumpcffencoding(SplineFont *sf,struct alltabs *at) {
1775  int i, cnt, anydups;
1776  uint32 start_pos = ftell(at->encoding);
1777  SplineChar *sc;
1778  EncMap *map = at->map;
1779 
1780  putc(0,at->encoding);
1781  /* I always use a format 0 encoding. ie. an array of glyph indexes */
1782  putc(0xff,at->encoding); /* fixup later */
1783 
1784  for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
1785  sf->glyphs[i]->ticked = false;
1786 
1787  cnt = 0;
1788  anydups = 0;
1789  for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && (sc=sf->glyphs[map->map[i]])!=NULL ) {
1790  if ( sc->ttf_glyph>255 )
1791  continue;
1792  if ( sc->ticked ) {
1793  ++anydups;
1794  } else if ( sc->ttf_glyph>0 ) {
1795  if ( cnt>=255 )
1796  break;
1797  putc(i,at->encoding);
1798  ++cnt;
1799  sc->ticked = true;
1800  }
1801  }
1802  if ( anydups ) {
1804  putc(0x80,at->encoding);
1805  putc(cnt,at->encoding);
1806  fseek(at->encoding,0,SEEK_END);
1807  putc(anydups,at->encoding);
1808 
1809  for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
1810  sf->glyphs[i]->ticked = false;
1811  for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && (sc=sf->glyphs[map->map[i]])!=NULL ) {
1812  if ( sc->ttf_glyph>255 )
1813  continue;
1814  if ( sc->ticked ) {
1815  putc(i,at->encoding);
1816  putshort(at->encoding,at->gn_sid[sc->ttf_glyph]);
1817  }
1818  sc->ticked = true;
1819  }
1820  } else {
1822  putc(cnt,at->encoding);
1823  fseek(at->encoding,0,SEEK_END);
1824  }
1825  free( at->gn_sid );
1826  at->gn_sid = NULL;
1827 }
1828 
1829 static void _dumpcffstrings(FILE *file, struct pschars *strs) {
1830  int i, len, offsize;
1831 
1832  /* First figure out the offset size */
1833  len = 1;
1834  for ( i=0; i<strs->next; ++i )
1835  len += strs->lens[i];
1836 
1837  /* Then output the index size and offsets */
1838  putshort( file, strs->next );
1839  if ( strs->next!=0 ) {
1840  /* presumably offsets are unsigned. But the docs don't state this in the obvious place */
1841  offsize = len<=255?1:len<=65535?2:len<=0xffffff?3:4;
1842  putc(offsize,file);
1843  len = 1;
1844  for ( i=0; i<strs->next; ++i ) {
1845  dumpoffset(file,offsize,len);
1846  len += strs->lens[i];
1847  }
1848  dumpoffset(file,offsize,len);
1849 
1850  /* last of all the strings */
1851  for ( i=0; i<strs->next; ++i ) {
1852  uint8 *pt = strs->values[i], *end = pt+strs->lens[i];
1853  while ( pt<end ) {
1854  putc( *pt++, file );
1855  }
1856  }
1857  }
1858 }
1859 
1860 static FILE *dumpcffstrings(struct pschars *strs) {
1861  FILE *file = tmpfile2();
1863  PSCharsFree(strs);
1864 return( file );
1865 }
1866 
1867 int SFFigureDefWidth(SplineFont *sf, int *_nomwid) {
1868  uint16 *widths; uint32 *cumwid;
1869  int nomwid, defwid, i, j, sameval=(int) 0x80000000, maxw=0, allsame=true;
1870  unsigned cnt;
1871 
1872  for ( i=0; i<sf->glyphcnt; ++i )
1873  if ( SCWorthOutputting(sf->glyphs[i]) ) {
1874  if ( maxw<sf->glyphs[i]->width ) maxw = sf->glyphs[i]->width;
1875  if ( sameval == 0x8000000 )
1876  sameval = sf->glyphs[i]->width;
1877  else if ( sameval!=sf->glyphs[i]->width )
1878  allsame = false;
1879  }
1880  if ( allsame ) {
1881  nomwid = defwid = sameval;
1882  } else {
1883  ++maxw;
1884  if ( maxw>65535 ) maxw = 3*(sf->ascent+sf->descent);
1885  widths = calloc(maxw,sizeof(uint16));
1886  cumwid = calloc(maxw,sizeof(uint32));
1887  defwid = 0; cnt=0;
1888  for ( i=0; i<sf->glyphcnt; ++i )
1889  if ( SCWorthOutputting(sf->glyphs[i]) &&
1890  sf->glyphs[i]->width>=0 &&
1891  sf->glyphs[i]->width<maxw )
1892  if ( ++widths[sf->glyphs[i]->width] > cnt ) {
1893  defwid = sf->glyphs[i]->width;
1894  cnt = widths[defwid];
1895  }
1896  widths[defwid] = 0;
1897  for ( i=0; i<maxw; ++i )
1898  for ( j=-107; j<=107; ++j )
1899  if ( i+j>=0 && i+j<maxw )
1900  cumwid[i] += widths[i+j];
1901  cnt = 0; nomwid = 0;
1902  for ( i=0; i<maxw; ++i )
1903  if ( cnt<cumwid[i] ) {
1904  cnt = cumwid[i];
1905  nomwid = i;
1906  }
1907  free(widths); free(cumwid);
1908  }
1909  if ( _nomwid!=NULL )
1910  *_nomwid = nomwid;
1911 return( defwid );
1912 }
1913 
1914 static void ATFigureDefWidth(SplineFont *sf, struct alltabs *at, int subfont) {
1915  int nomwid, defwid;
1916 
1917  defwid = SFFigureDefWidth(sf,&nomwid);
1918  if ( subfont==-1 )
1919  at->defwid = defwid;
1920  else
1921  at->fds[subfont].defwid = defwid;
1922  if ( subfont==-1 )
1923  at->nomwid = nomwid;
1924  else
1925  at->fds[subfont].nomwid = nomwid;
1926 }
1927 
1928 static void dumpcffprivate(SplineFont *sf,struct alltabs *at,int subfont,
1929  int subrcnt) {
1930  char *pt;
1931  FILE *private = subfont==-1?at->private:at->fds[subfont].private;
1932  int mi,i;
1933  real bluevalues[14], otherblues[10];
1934  real snapcnt[12];
1935  real stemsnaph[12], stemsnapv[12];
1936  real stdhw[1], stdvw[1];
1937  int hasblue=0, hash=0, hasv=0, bs;
1938  int nomwid, defwid;
1939  EncMap *map = at->map;
1940  double bluescale;
1941 
1942  /* The private dict is not in an index, so no index header. Just the data */
1943 
1944  if ( subfont==-1 )
1945  defwid = at->defwid;
1946  else
1947  defwid = at->fds[subfont].defwid;
1948  dumpintoper(private,defwid,20); /* Default Width */
1949  if ( subfont==-1 )
1950  nomwid = at->nomwid;
1951  else
1952  nomwid = at->fds[subfont].nomwid;
1953  dumpintoper(private,nomwid,21); /* Nominative Width */
1954 
1955  bs = SplineFontIsFlexible(sf,at->gi.layer,at->gi.flags);
1956  hasblue = PSDictHasEntry(sf->private,"BlueValues")!=NULL;
1957  hash = PSDictHasEntry(sf->private,"StdHW")!=NULL;
1958  hasv = PSDictHasEntry(sf->private,"StdVW")!=NULL;
1960  if ( autohint_before_generate ) {
1961  ff_progress_change_line1(_("Auto Hinting Font..."));
1964  }
1965 
1966  otherblues[0] = otherblues[1] = bluevalues[0] = bluevalues[1] = 0;
1967  if ( !hasblue ) {
1970  }
1971 
1972  stdhw[0] = stdvw[0] = 0;
1973  if ( !hash ) {
1974  FindHStems(sf,stemsnaph,snapcnt);
1975  mi = -1;
1976  for ( i=0; i<12 && stemsnaph[i]!=0; ++i )
1977  if ( mi==-1 ) mi = i;
1978  else if ( snapcnt[i]>snapcnt[mi] ) mi = i;
1979  if ( mi!=-1 ) stdhw[0] = stemsnaph[mi];
1980  }
1981 
1982  if ( !hasv ) {
1983  FindVStems(sf,stemsnapv,snapcnt);
1984  mi = -1;
1985  for ( i=0; i<12 && stemsnapv[i]!=0; ++i )
1986  if ( mi==-1 ) mi = i;
1987  else if ( snapcnt[i]>snapcnt[mi] ) mi = i;
1988  if ( mi!=-1 ) stdvw[0] = stemsnapv[mi];
1989  }
1990  ff_progress_change_line1(_("Saving OpenType Font"));
1991 
1992  if ( hasblue )
1993  DumpStrArray(PSDictHasEntry(sf->private,"BlueValues"),private,6);
1994  else
1995  DumpDblArray(bluevalues,sizeof(bluevalues)/sizeof(bluevalues[0]),private,6);
1996  if ( (pt=PSDictHasEntry(sf->private,"OtherBlues"))!=NULL )
1997  DumpStrArray(pt,private,7);
1998  else if ( !hasblue )
1999  DumpDblArray(otherblues,sizeof(otherblues)/sizeof(otherblues[0]),private,7);
2000  if ( (pt=PSDictHasEntry(sf->private,"FamilyBlues"))!=NULL )
2001  DumpStrArray(pt,private,8);
2002  bluescale = BlueScaleFigure(sf->private,bluevalues,otherblues);
2003  if ( (pt=PSDictHasEntry(sf->private,"FamilyOtherBlues"))!=NULL )
2004  DumpStrArray(pt,private,9);
2005  if ( (pt=PSDictHasEntry(sf->private,"BlueScale"))!=NULL )
2006  DumpStrDouble(pt,private,(12<<8)+9);
2007  else if ( bluescale!=-1 )
2008  dumpdbloper(private,bluescale,(12<<8)+9);
2009  if ( (pt=PSDictHasEntry(sf->private,"BlueShift"))!=NULL )
2010  DumpStrDouble(pt,private,(12<<8)+10);
2011  else
2012  dumpintoper(private,bs,(12<<8)+10);
2013  if ( (pt=PSDictHasEntry(sf->private,"BlueFuzz"))!=NULL )
2014  DumpStrDouble(pt,private,(12<<8)+11);
2015  if ( hash ) {
2016  DumpStrDouble(PSDictHasEntry(sf->private,"StdHW"),private,10);
2017  if ( (pt=PSDictHasEntry(sf->private,"StemSnapH"))!=NULL )
2018  DumpStrArray(pt,private,(12<<8)|12);
2019  } else {
2020  if ( stdhw[0]!=0 )
2021  dumpdbloper(private,stdhw[0],10);
2022  DumpDblArray(stemsnaph,sizeof(stemsnaph)/sizeof(stemsnaph[0]),private,(12<<8)|12);
2023  }
2024  if ( hasv ) {
2025  DumpStrDouble(PSDictHasEntry(sf->private,"StdVW"),private,11);
2026  if ( (pt=PSDictHasEntry(sf->private,"StemSnapV"))!=NULL )
2027  DumpStrArray(pt,private,(12<<8)|13);
2028  } else {
2029  if ( stdvw[0]!=0 )
2030  dumpdbloper(private,stdvw[0],11);
2031  DumpDblArray(stemsnapv,sizeof(stemsnapv)/sizeof(stemsnapv[0]),private,(12<<8)|13);
2032  }
2033  if ( (pt=PSDictHasEntry(sf->private,"ForceBold"))!=NULL ) {
2034  dumpintoper(private,*pt=='t'||*pt=='T',(12<<8)|14);
2035  } else if ( sf->weight!=NULL &&
2036  (strstrmatch(sf->weight,"Bold")!=NULL ||
2037  strstrmatch(sf->weight,"Demi")!=NULL ||
2038  strstrmatch(sf->weight,"Fett")!=NULL ||
2039  strstrmatch(sf->weight,"Gras")!=NULL ||
2040  strstrmatch(sf->weight,"Heavy")!=NULL ||
2041  strstrmatch(sf->weight,"Black")!=NULL))
2042  dumpintoper(private,1,(12<<8)|14);
2043  if ( (pt=PSDictHasEntry(sf->private,"LanguageGroup"))!=NULL )
2044  DumpStrDouble(pt,private,(12<<8)+17);
2045  else if ( map==NULL )
2046  /* Do Nothing */;
2047  else if ( map->enc->is_japanese ||
2048  map->enc->is_korean ||
2049  map->enc->is_tradchinese ||
2050  map->enc->is_simplechinese )
2051  dumpintoper(private,1,(12<<8)|17);
2052  if ( (pt=PSDictHasEntry(sf->private,"ExpansionFactor"))!=NULL )
2053  DumpStrDouble(pt,private,(12<<8)+18);
2054  if ( subrcnt!=0 )
2055  dumpsizedint(private,false,ftell(private)+3+1,19); /* Subrs */
2056 
2057  if ( subfont==-1 )
2058  at->privatelen = ftell(private);
2059  else
2060  at->fds[subfont].privatelen = ftell(private);
2061 }
2062 
2063 /* When we exit this the topdict is not complete, we still need to fill in */
2064 /* values for charset,encoding,charstrings and private. Then we need to go */
2065 /* back and fill in the table length (at lenpos) */
2066 static void dumpcfftopdict(SplineFont *sf,struct alltabs *at) {
2067  char *pt, *end;
2068  FILE *cfff = at->cfff;
2069  DBounds b;
2070 
2071  putshort(cfff,1); /* One top dict */
2072  putc('\2',cfff); /* Offset size */
2073  putshort(cfff,1); /* Offset to topdict */
2074  at->lenpos = ftell(cfff);
2075  putshort(cfff,0); /* placeholder for final position (final offset in index points beyond last element) */
2076  dumpsid(cfff,at,sf->version,0);
2077  dumpsid(cfff,at,sf->copyright,1);
2078  dumpsid(cfff,at,sf->fullname?sf->fullname:sf->fontname,2);
2079  dumpsid(cfff,at,sf->familyname,3);
2080  dumpsid(cfff,at,sf->weight,4);
2081  if ( at->gi.fixed_width>0 ) dumpintoper(cfff,1,(12<<8)|1);
2082  if ( sf->italicangle!=0 ) dumpdbloper(cfff,sf->italicangle,(12<<8)|2);
2083  if ( sf->upos!=-100 ) dumpdbloper(cfff,sf->upos,(12<<8)|3);
2084  if ( sf->uwidth!=50 ) dumpdbloper(cfff,sf->uwidth,(12<<8)|4);
2085  if ( sf->strokedfont ) {
2086  dumpintoper(cfff,2,(12<<8)|5);
2087  dumpdbloper(cfff,sf->strokewidth,(12<<8)|8);
2088  }
2089  /* We'll never set CharstringType */
2090  if ( sf->ascent+sf->descent!=1000 ) {
2091  dumpdbl(cfff,1.0/(sf->ascent+sf->descent));
2092  dumpint(cfff,0);
2093  dumpint(cfff,0);
2094  dumpdbl(cfff,1.0/(sf->ascent+sf->descent));
2095  dumpint(cfff,0);
2096  dumpintoper(cfff,0,(12<<8)|7);
2097  }
2098  if ( sf->uniqueid!=-1 && sf->use_uniqueid )
2099  dumpintoper(cfff, sf->uniqueid?sf->uniqueid:4000000 + (rand()&0x3ffff), 13 );
2101  at->gi.xmin = b.minx;
2102  at->gi.ymin = b.miny;
2103  at->gi.xmax = b.maxx;
2104  at->gi.ymax = b.maxy;
2105  dumpdbl(cfff,floor(b.minx));
2106  dumpdbl(cfff,floor(b.miny));
2107  dumpdbl(cfff,ceil(b.maxx));
2108  dumpdbloper(cfff,ceil(b.maxy),5);
2109  /* We'll never set StrokeWidth */
2110  if ( sf->xuid!=NULL && sf->use_xuid ) {
2111  pt = sf->xuid; if ( *pt=='[' ) ++pt;
2112  while ( *pt && *pt!=']' ) {
2113  dumpint(cfff,strtol(pt,&end,10));
2114  if ( pt==end ) /* garbage in XUID */
2115  break;
2116  for ( pt = end; *pt==' '; ++pt );
2117  }
2118  putc(14,cfff);
2119  if ( sf->changed_since_xuidchanged )
2121  }
2122  /* Offset to charset (oper=15) needed here */
2123  /* Offset to encoding (oper=16) needed here (not for CID )*/
2124  /* Offset to charstrings (oper=17) needed here */
2125  /* Length of, and Offset to private (oper=18) needed here (not for CID )*/
2126 }
2127 
2128 static int dumpcffdict(SplineFont *sf,struct alltabs *at) {
2129  FILE *fdarray = at->fdarray;
2130  int pstart;
2131  /* according to the PSRef Man v3, only fontname, fontmatrix and private */
2132  /* appear in this dictionary */
2133 
2134  dumpsid(fdarray,at,sf->fontname,(12<<8)|38);
2135  if ( sf->ascent+sf->descent!=1000 ) {
2136  dumpdbl(fdarray,1.0/(sf->ascent+sf->descent));
2137  dumpint(fdarray,0);
2138  dumpint(fdarray,0);
2139  dumpdbl(fdarray,1.0/(sf->ascent+sf->descent));
2140  dumpint(fdarray,0);
2141  dumpintoper(fdarray,0,(12<<8)|7);
2142  }
2143  pstart = ftell(fdarray);
2144  dumpsizedint(fdarray,false,0,-1); /* private length */
2145  dumpsizedint(fdarray,true,0,18); /* private offset */
2146 return( pstart );
2147 }
2148 
2149 static void dumpcffdictindex(SplineFont *sf,struct alltabs *at) {
2150  int i;
2151  int pos;
2152 
2153  putshort(at->fdarray,sf->subfontcnt);
2154  putc('\2',at->fdarray); /* DICTs aren't very big, and there are at most 255 */
2155  putshort(at->fdarray,1); /* Offset to first dict */
2156  for ( i=0; i<sf->subfontcnt; ++i )
2157  putshort(at->fdarray,0); /* Dump offset placeholders (note there's one extra to mark the end) */
2158  pos = ftell(at->fdarray)-1;
2159  for ( i=0; i<sf->subfontcnt; ++i ) {
2160  at->fds[i].fillindictmark = dumpcffdict(sf->subfonts[i],at);
2161  at->fds[i].eodictmark = ftell(at->fdarray);
2162  if ( at->fds[i].eodictmark>65536 )
2163  IError("The DICT INDEX got too big, result won't work");
2164  }
2165  fseek(at->fdarray,2*sizeof(short)+sizeof(char),SEEK_SET);
2166  for ( i=0; i<sf->subfontcnt; ++i )
2167  putshort(at->fdarray,at->fds[i].eodictmark-pos);
2168  fseek(at->fdarray,0,SEEK_END);
2169 }
2170 
2171 static void dumpcffcidtopdict(SplineFont *sf,struct alltabs *at) {
2172  char *pt, *end;
2173  FILE *cfff = at->cfff;
2174  DBounds b;
2175  int cidcnt=0, k;
2176 
2177  for ( k=0; k<sf->subfontcnt; ++k )
2178  if ( sf->subfonts[k]->glyphcnt>cidcnt ) cidcnt = sf->subfonts[k]->glyphcnt;
2179 
2180  putshort(cfff,1); /* One top dict */
2181  putc('\2',cfff); /* Offset size */
2182  putshort(cfff,1); /* Offset to topdict */
2183  at->lenpos = ftell(cfff);
2184  putshort(cfff,0); /* placeholder for final position */
2185  dumpsid(cfff,at,sf->cidregistry,-1);
2186  dumpsid(cfff,at,sf->ordering,-1);
2187  dumpintoper(cfff,sf->supplement,(12<<8)|30); /* ROS operator must be first */
2188  dumpdbloper(cfff,sf->cidversion,(12<<8)|31);
2189  dumpintoper(cfff,cidcnt,(12<<8)|34);
2190  if ( sf->use_uniqueid )
2191  dumpintoper(cfff, sf->uniqueid?sf->uniqueid:4000000 + (rand()&0x3ffff), (12<<8)|35 );
2192 
2193  dumpsid(cfff,at,sf->copyright,1);
2194  dumpsid(cfff,at,sf->fullname?sf->fullname:sf->fontname,2);
2195  dumpsid(cfff,at,sf->familyname,3);
2196  dumpsid(cfff,at,sf->weight,4);
2197  /* FontMatrix (identity here, real ones in sub fonts)*/
2198  /* Actually there is no fontmatrix in the adobe cid font I'm looking at */
2199  /* which means it should default to [.001...] but it doesn't so the */
2200  /* docs aren't completely accurate */
2201  /* I now see I've no idea what the FontMatrix means in a CID keyed font */
2202  /* it seems to be ignored everywhere, so we omit it */
2203 
2204  CIDLayerFindBounds(sf,at->gi.layer,&b);
2205  at->gi.xmin = b.minx;
2206  at->gi.ymin = b.miny;
2207  at->gi.xmax = b.maxx;
2208  at->gi.ymax = b.maxy;
2209  dumpdbl(cfff,floor(b.minx));
2210  dumpdbl(cfff,floor(b.miny));
2211  dumpdbl(cfff,ceil(b.maxx));
2212  dumpdbloper(cfff,ceil(b.maxy),5);
2213  /* We'll never set StrokeWidth */
2214  if ( sf->xuid!=NULL && sf->use_xuid ) {
2215  pt = sf->xuid; if ( *pt=='[' ) ++pt;
2216  while ( *pt && *pt!=']' ) {
2217  dumpint(cfff,strtol(pt,&end,10));
2218  for ( pt = end; *pt==' '; ++pt );
2219  }
2220  putc(14,cfff);
2221  if ( sf->changed_since_xuidchanged )
2223  }
2224  /* Acrobat doesn't seem to care about a private dict here. Ghostscript */
2225  /* dies. Tech Note: 5176.CFF.PDF, top of page 23 says: */
2226  /* A Private DICT is required, but may be specified as having */
2227  /* a length of 0 if there are no non-default values to be stored*/
2228  /* No indication >where< it is required. I assumed everywhere. Perhaps */
2229  /* just in basefonts? */
2230  /* Omit it. */
2231 
2232  /* Offset to charset (oper=15) needed here */
2233  /* Offset to charstrings (oper=17) needed here */
2234  /* Offset to FDArray (oper=12,36) needed here */
2235  /* Offset to FDSelect (oper=12,37) needed here */
2236 }
2237 
2239  int i;
2240 
2241  for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && sf->glyphs[map->map[i]]!=NULL )
2242  if ( sf->glyphs[map->map[i]]->unicodeenc!=-1 )
2243  if ( sf->glyphs[map->map[i]]->unicodeenc!=unicode_from_adobestd[i] )
2244 return( 0 );
2245 
2246 return( 1 );
2247 }
2248 
2249 static void finishup(SplineFont *sf,struct alltabs *at) {
2250  int strlen, shlen, glen,enclen,csetlen,cstrlen,prvlen;
2251  int base, eotop, strhead;
2252  int output_enc = ( at->format==ff_cff && !isStdEncoding(sf,at->map));
2253 
2254  storesid(at,NULL); /* end the strings index */
2255  strlen = ftell(at->sidf) + (shlen = ftell(at->sidh));
2256  glen = sizeof(short); /* Single entry: 0, no globals */
2257  enclen = ftell(at->encoding);
2258  csetlen = ftell(at->charset);
2259  cstrlen = ftell(at->charstrings);
2260  prvlen = ftell(at->private);
2261  base = ftell(at->cfff);
2262  if ( base+6*3+strlen+glen+enclen+csetlen+cstrlen+prvlen > 32767 ) {
2263  at->cfflongoffset = true;
2264  base += 5*5+4;
2265  } else
2266  base += 5*3+4;
2267  strhead = 2+(at->sidcnt>1);
2268  base += strhead;
2269 
2270  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen,15); /* Charset */
2271  if ( output_enc ) /* encoding offset */
2272  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen,16); /* encoding offset */
2273  else {
2274  dumpsizedint(at->cfff,at->cfflongoffset,0,16);
2275  enclen = 0;
2276  }
2277  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+enclen,17);/* charstrings */
2278  dumpsizedint(at->cfff,at->cfflongoffset,at->privatelen,-1);
2279  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+enclen+cstrlen,18); /* private size */
2280  eotop = base-strhead-at->lenpos-1;
2281  if ( at->cfflongoffset ) {
2282  fseek(at->cfff,3,SEEK_SET);
2283  putc(4,at->cfff);
2284  }
2285  fseek(at->cfff,at->lenpos,SEEK_SET);
2286  putshort(at->cfff,eotop);
2287  fseek(at->cfff,0,SEEK_END);
2288 
2289  /* String Index */
2290  putshort(at->cfff,at->sidcnt-1);
2291  if ( at->sidcnt!=1 ) { /* Everybody gets an added NULL */
2292  putc(at->sidlongoffset?4:2,at->cfff);
2293  if ( !ttfcopyfile(at->cfff,at->sidh,base,"CFF-StringBase")) at->error = true;
2294  if ( !ttfcopyfile(at->cfff,at->sidf,base+shlen,"CFF-StringData")) at->error = true;
2295  }
2296 
2297  /* Global Subrs */
2298  putshort(at->cfff,0);
2299 
2300  /* Charset */
2301  if ( !ttfcopyfile(at->cfff,at->charset,base+strlen+glen,"CFF-Charset")) at->error = true;
2302 
2303  /* Encoding */
2304  if ( !ttfcopyfile(at->cfff,at->encoding,base+strlen+glen+csetlen,"CFF-Encoding")) at->error = true;
2305 
2306  /* Char Strings */
2307  if ( !ttfcopyfile(at->cfff,at->charstrings,base+strlen+glen+csetlen+enclen,"CFF-CharStrings")) at->error = true;
2308 
2309  /* Private & Subrs */
2310  if ( !ttfcopyfile(at->cfff,at->private,base+strlen+glen+csetlen+enclen+cstrlen,"CFF-Private")) at->error = true;
2311 }
2312 
2313 static void finishupcid(SplineFont *sf,struct alltabs *at) {
2314  int strlen, shlen, glen,csetlen,cstrlen,fdsellen,fdarrlen,prvlen;
2315  int base, eotop, strhead;
2316  int i;
2317 
2318  storesid(at,NULL); /* end the strings index */
2319  strlen = ftell(at->sidf) + (shlen = ftell(at->sidh));
2320  glen = ftell(at->globalsubrs);
2321  /* No encodings */
2322  csetlen = ftell(at->charset);
2323  fdsellen = ftell(at->fdselect);
2324  cstrlen = ftell(at->charstrings);
2325  fdarrlen = ftell(at->fdarray);
2326  base = ftell(at->cfff);
2327 
2328  at->cfflongoffset = true;
2329  base += 5*4+4+2; /* two of the opers below are two byte opers */
2330  strhead = 2+(at->sidcnt>1);
2331  base += strhead;
2332 
2333  prvlen = 0;
2334  for ( i=0; i<sf->subfontcnt; ++i ) {
2336  dumpsizedint(at->fdarray,false,at->fds[i].privatelen,-1); /* Private len */
2337  dumpsizedint(at->fdarray,true,base+strlen+glen+csetlen+fdsellen+cstrlen+fdarrlen+prvlen,18); /* Private offset */
2338  prvlen += ftell(at->fds[i].private); /* private & subrs */
2339  }
2340 
2341  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen,15); /* charset */
2342  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen,(12<<8)|37); /* fdselect */
2343  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+fdsellen,17); /* charstrings */
2344  dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+fdsellen+cstrlen,(12<<8)|36); /* fdarray */
2345  eotop = base-strhead-at->lenpos-1;
2346  fseek(at->cfff,at->lenpos,SEEK_SET);
2347  putshort(at->cfff,eotop);
2348  fseek(at->cfff,0,SEEK_END);
2349 
2350  /* String Index */
2351  putshort(at->cfff,at->sidcnt-1);
2352  if ( at->sidcnt!=1 ) { /* Everybody gets an added NULL */
2353  putc(at->sidlongoffset?4:2,at->cfff);
2354  if ( !ttfcopyfile(at->cfff,at->sidh,base,"CFF-StringBase")) at->error = true;
2355  if ( !ttfcopyfile(at->cfff,at->sidf,base+shlen,"CFF-StringData")) at->error = true;
2356  }
2357 
2358  /* Global Subrs */
2359  if ( !ttfcopyfile(at->cfff,at->globalsubrs,base+strlen,"CFF-GlobalSubrs")) at->error = true;
2360 
2361  /* Charset */
2362  if ( !ttfcopyfile(at->cfff,at->charset,base+strlen+glen,"CFF-Charset")) at->error = true;
2363 
2364  /* FDSelect */
2365  if ( !ttfcopyfile(at->cfff,at->fdselect,base+strlen+glen+csetlen,"CFF-FDSelect")) at->error = true;
2366 
2367  /* Char Strings */
2368  if ( !ttfcopyfile(at->cfff,at->charstrings,base+strlen+glen+csetlen+fdsellen,"CFF-CharStrings")) at->error = true;
2369 
2370  /* FDArray (DICT Index) */
2371  if ( !ttfcopyfile(at->cfff,at->fdarray,base+strlen+glen+csetlen+fdsellen+cstrlen,"CFF-FDArray")) at->error = true;
2372 
2373  /* Private & Subrs */
2374  prvlen = 0;
2375  for ( i=0; i<sf->subfontcnt; ++i ) {
2376  int temp = ftell(at->fds[i].private);
2377  if ( !ttfcopyfile(at->cfff,at->fds[i].private,
2378  base+strlen+glen+csetlen+fdsellen+cstrlen+fdarrlen+prvlen,"CFF-PrivateSubrs")) at->error = true;
2379  prvlen += temp;
2380  }
2381 
2382  free(at->fds);
2383 }
2384 
2385 static int dumpcffhmtx(struct alltabs *at,SplineFont *sf,int bitmaps) {
2386  DBounds b;
2387  SplineChar *sc;
2388  int i,cnt;
2389  int dovmetrics = sf->hasvmetrics;
2390  int width = at->gi.fixed_width;
2391 
2392  at->gi.hmtx = tmpfile2();
2393  if ( dovmetrics )
2394  at->gi.vmtx = tmpfile2();
2395  FigureFullMetricsEnd(sf,&at->gi,bitmaps); /* Bitmap fonts use ttf convention of 3 magic glyphs */
2396  if ( at->gi.bygid[0]!=-1 && (sf->glyphs[at->gi.bygid[0]]->width==width || width<=0 )) {
2397  putshort(at->gi.hmtx,sf->glyphs[at->gi.bygid[0]]->width);
2398  SplineCharLayerFindBounds(sf->glyphs[at->gi.bygid[0]],at->gi.layer,&b);
2399  putshort(at->gi.hmtx,b.minx);
2400  if ( dovmetrics ) {
2401  putshort(at->gi.vmtx,sf->glyphs[at->gi.bygid[0]]->vwidth);
2402  putshort(at->gi.vmtx,/*sf->vertical_origin-*/b.miny);
2403  }
2404  } else {
2405  putshort(at->gi.hmtx,width<=0?(sf->ascent+sf->descent)/2:width);
2406  putshort(at->gi.hmtx,0);
2407  if ( dovmetrics ) {
2408  putshort(at->gi.vmtx,sf->ascent+sf->descent);
2409  putshort(at->gi.vmtx,0);
2410  }
2411  }
2412  cnt = 1;
2413  if ( bitmaps ) {
2414  if ( width<=0 ) width = (sf->ascent+sf->descent)/3;
2415  putshort(at->gi.hmtx,width);
2416  putshort(at->gi.hmtx,0);
2417  if ( dovmetrics ) {
2418  putshort(at->gi.vmtx,sf->ascent+sf->descent);
2419  putshort(at->gi.vmtx,0);
2420  }
2421  putshort(at->gi.hmtx,width);
2422  putshort(at->gi.hmtx,0);
2423  if ( dovmetrics ) {
2424  putshort(at->gi.vmtx,sf->ascent+sf->descent);
2425  putshort(at->gi.vmtx,0);
2426  }
2427  cnt = 3;
2428  }
2429 
2430  for ( i=cnt; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
2431  sc = sf->glyphs[at->gi.bygid[i]];
2432  if ( SCWorthOutputting(sc) ) {
2433  if ( i<=at->gi.lasthwidth )
2434  putshort(at->gi.hmtx,sc->width);
2436  putshort(at->gi.hmtx,b.minx);
2437  if ( dovmetrics ) {
2438  if ( i<=at->gi.lastvwidth )
2439  putshort(at->gi.vmtx,sc->vwidth);
2440  putshort(at->gi.vmtx,/*sf->vertical_origin-*/b.maxy);
2441  }
2442  ++cnt;
2443  if ( i==at->gi.lasthwidth )
2444  at->gi.hfullcnt = cnt;
2445  if ( i==at->gi.lastvwidth )
2446  at->gi.vfullcnt = cnt;
2447  }
2448  }
2449  at->gi.hmtxlen = ftell(at->gi.hmtx);
2450  if ( at->gi.hmtxlen&2 ) putshort(at->gi.hmtx,0);
2451  if ( dovmetrics ) {
2452  at->gi.vmtxlen = ftell(at->gi.vmtx);
2453  if ( at->gi.vmtxlen&2 ) putshort(at->gi.vmtx,0);
2454  }
2455 
2456  at->gi.maxp->numGlyphs = cnt;
2457 return( true );
2458 }
2459 
2460 static void dumpcffcidhmtx(struct alltabs *at,SplineFont *_sf) {
2461  DBounds b;
2462  SplineChar *sc;
2463  int cid,i,cnt=0,max;
2464  SplineFont *sf;
2465  int dovmetrics = _sf->hasvmetrics;
2466 
2467  at->gi.hmtx = tmpfile2();
2468  if ( dovmetrics )
2469  at->gi.vmtx = tmpfile2();
2470  FigureFullMetricsEnd(_sf,&at->gi,false);
2471 
2472  max = 0;
2473  for ( i=0; i<_sf->subfontcnt; ++i )
2474  if ( max<_sf->subfonts[i]->glyphcnt )
2475  max = _sf->subfonts[i]->glyphcnt;
2476  for ( cid = 0; cid<max; ++cid ) {
2477  for ( i=0; i<_sf->subfontcnt; ++i ) {
2478  sf = _sf->subfonts[i];
2479  if ( cid<sf->glyphcnt && SCWorthOutputting(sf->glyphs[cid]))
2480  break;
2481  }
2482  if ( i!=_sf->subfontcnt ) {
2483  sc = sf->glyphs[cid];
2484  if ( sc->ttf_glyph<=at->gi.lasthwidth )
2485  putshort(at->gi.hmtx,sc->width);
2487  putshort(at->gi.hmtx,b.minx);
2488  if ( dovmetrics ) {
2489  if ( sc->ttf_glyph<=at->gi.lastvwidth )
2490  putshort(at->gi.vmtx,sc->vwidth);
2491  putshort(at->gi.vmtx,/*sf->vertical_origin-*/b.maxy);
2492  }
2493  ++cnt;
2494  if ( sc->ttf_glyph==at->gi.lasthwidth )
2495  at->gi.hfullcnt = cnt;
2496  if ( sc->ttf_glyph==at->gi.lastvwidth )
2497  at->gi.vfullcnt = cnt;
2498  } else if ( cid==0 ) {
2499  /* Create a dummy entry for .notdef */
2500  sf = _sf->subfonts[0];
2501  putshort(at->gi.hmtx,sf->ascent+sf->descent);
2502  putshort(at->gi.hmtx,0);
2503  ++cnt;
2504  if ( dovmetrics ) {
2505  putshort(at->gi.vmtx,sf->ascent+sf->descent);
2506  putshort(at->gi.vmtx,0);
2507  }
2508  }
2509  }
2510  at->gi.hmtxlen = ftell(at->gi.hmtx);
2511  if ( at->gi.hmtxlen&2 ) putshort(at->gi.hmtx,0);
2512  if ( dovmetrics ) {
2513  at->gi.vmtxlen = ftell(at->gi.vmtx);
2514  if ( at->gi.vmtxlen&2 ) putshort(at->gi.vmtx,0);
2515  }
2516 
2517  at->gi.maxp->numGlyphs = cnt;
2518 }
2519 
2520 static int dumptype2glyphs(SplineFont *sf,struct alltabs *at) {
2521  int i;
2522  struct pschars *subrs, *chrs;
2523 
2524  at->cfff = tmpfile2();
2525  at->sidf = tmpfile2();
2526  at->sidh = tmpfile2();
2527  at->charset = tmpfile2();
2528  at->encoding = tmpfile2();
2529  at->private = tmpfile2();
2530 
2531  dumpcffheader(at->cfff);
2532  dumpcffnames(sf,at->cfff);
2533  dumpcffcharset(sf,at);
2535 
2536  ATFigureDefWidth(sf,at,-1);
2537  if ((chrs =SplineFont2ChrsSubrs2(sf,at->nomwid,at->defwid,at->gi.bygid,at->gi.gcnt,at->gi.flags,&subrs,at->gi.layer))==NULL )
2538 return( false );
2539  dumpcffprivate(sf,at,-1,subrs->next);
2540  if ( subrs->next!=0 )
2543  at->charstrings = dumpcffstrings(chrs);
2544  PSCharsFree(subrs);
2545  if ( at->charstrings == NULL )
2546 return( false );
2547  if ( at->format==ff_cff && !isStdEncoding(sf,at->map))
2548  dumpcffencoding(sf,at); /* Do this after we've assigned glyph ids */
2549  dumpcfftopdict(sf,at);
2550  finishup(sf,at);
2551 
2552  at->cfflen = ftell(at->cfff);
2553  if ( at->cfflen&3 ) {
2554  for ( i=4-(at->cfflen&3); i>0; --i )
2555  putc('\0',at->cfff);
2556  }
2557 
2558  if ( at->format!=ff_cff )
2559  dumpcffhmtx(at,sf,false);
2560  free(at->gn_sid); at->gn_sid=NULL;
2561 return( true );
2562 }
2563 
2564 static int dumpcidglyphs(SplineFont *sf,struct alltabs *at) {
2565  int i;
2566  struct pschars *glbls = NULL, *chrs;
2567 
2568  at->cfff = tmpfile2();
2569  at->sidf = tmpfile2();
2570  at->sidh = tmpfile2();
2571  at->charset = tmpfile2();
2572  at->fdselect = tmpfile2();
2573  at->fdarray = tmpfile2();
2574  at->globalsubrs = tmpfile2();
2575 
2576  at->fds = calloc(sf->subfontcnt,sizeof(struct fd2data));
2577  for ( i=0; i<sf->subfontcnt; ++i ) {
2578  at->fds[i].private = tmpfile2();
2579  ATFigureDefWidth(sf->subfonts[i],at,i);
2580  }
2581  if ( (chrs = CID2ChrsSubrs2(sf,at->fds,at->gi.flags,&glbls,at->gi.layer))==NULL )
2582 return( false );
2583  for ( i=0; i<sf->subfontcnt; ++i ) {
2584  dumpcffprivate(sf->subfonts[i],at,i,at->fds[i].subrs->next);
2585  if ( at->fds[i].subrs->next!=0 )
2586  _dumpcffstrings(at->fds[i].private,at->fds[i].subrs);
2587  PSCharsFree(at->fds[i].subrs);
2588  }
2589  _dumpcffstrings(at->globalsubrs,glbls);
2590  PSCharsFree(glbls);
2591 
2592  dumpcffheader(at->cfff);
2593  dumpcffnames(sf,at->cfff);
2594  dumpcffcidset(at);
2595  dumpcfffdselect(sf,at);
2596  dumpcffdictindex(sf,at);
2597  if ( (at->charstrings = dumpcffstrings(chrs))==NULL )
2598 return( false );
2599  dumpcffcidtopdict(sf,at);
2600  finishupcid(sf,at);
2601 
2602  at->cfflen = ftell(at->cfff);
2603  if ( at->cfflen&3 ) {
2604  for ( i=4-(at->cfflen&3); i>0; --i )
2605  putc('\0',at->cfff);
2606  }
2607 
2608  if ( at->format!=ff_cffcid )
2609  dumpcffcidhmtx(at,sf);
2610 return( true );
2611 }
2612 
2614  int i;
2615 
2616  if ( sf->subfontcnt!=0 ) {
2617  for ( i=0; i<sf->subfontcnt; ++i )
2618  if ( AnyInstructions(sf->subfonts[i]))
2619 return( true );
2620  } else {
2621  for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
2622  if ( sf->glyphs[i]->ttf_instrs_len!=0 )
2623 return( true );
2624  }
2625  }
2626 return( false );
2627 }
2628 
2629 void cvt_unix_to_1904( long long time, int32 result[2]) {
2630  uint32 date1970[4], tm[4];
2631  uint32 year[2];
2632  int i;
2633 
2634  tm[0] = time &0xffff;
2635  tm[1] = (time>>16)&0xffff;
2636  tm[2] = (time>>32)&0xffff;
2637  tm[3] = (time>>48)&0xffff;
2638  memset(date1970,0,sizeof(date1970));
2639  year[0] = (60*60*24*365L)&0xffff;
2640  year[1] = (60*60*24*365L)>>16;
2641  for ( i=1904; i<1970; ++i ) {
2642  date1970[0] += year[0];
2643  date1970[1] += year[1];
2644  if ( (i&3)==0 && (i%100!=0 || i%400==0))
2645  date1970[0] += 24*60*60L; /* Leap year */
2646  date1970[1] += (date1970[0]>>16);
2647  date1970[0] &= 0xffff;
2648  date1970[2] += date1970[1]>>16;
2649  date1970[1] &= 0xffff;
2650  date1970[3] += date1970[2]>>16;
2651  date1970[2] &= 0xffff;
2652  }
2653 
2654  for ( i=0; i<3; ++i ) {
2655  tm[i] += date1970[i];
2656  tm[i+1] += tm[i]>>16;
2657  tm[i] &= 0xffff;
2658  }
2659  tm[3] -= date1970[3];
2660 
2661  result[0] = (tm[1]<<16) | tm[0];
2662  result[1] = (tm[3]<<16) | tm[2];
2663 }
2664 
2665 static void sethead(struct head *head,SplineFont *sf,struct alltabs *at,
2666  enum fontformat format, int32 *bsizes) {
2667  int i, lr, rl, indic_rearrange, arabic;
2668  ASM *sm;
2669  struct ttflangname *useng;
2670  float vn;
2671 
2672  if ( at->gi.xmin==15000 ) at->gi.xmin = 0;
2673  if ( at->gi.ymin==15000 ) at->gi.ymin = 0;
2674  if ( bsizes!=NULL && format==ff_none ) {
2675  if ( sf->ascent >at->gi.ymax ) at->gi.ymax = sf->ascent;
2676  if ( -sf->descent<at->gi.ymin ) at->gi.ymin = -sf->descent;
2677  }
2678  head->xmin = at->gi.xmin;
2679  head->ymin = at->gi.ymin;
2680  head->xmax = at->gi.xmax;
2681  head->ymax = at->gi.ymax;
2682 
2683  lr = rl = arabic = 0;
2684  for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
2685  SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
2686  int uni = sc->unicodeenc ;
2687  if ( SCRightToLeft(sc) )
2688  rl = 1;
2689  else if (( uni!=-1 && uni<0x10000 && islefttoright(uni)) ||
2690  (uni>=0x10300 && uni<0x107ff))
2691  lr = 1;
2692  if ( SCScriptFromUnicode(sc)==CHR('a','r','a','b') )
2693  arabic = 1;
2694  }
2695 
2696  head->version = 0x00010000;
2697  head->revision = sf->sfntRevision;
2698  if ( sf->sfntRevision==sfntRevisionUnset ) {
2699  head->revision = 0x00010000;
2700  for ( useng=sf->names; useng!=NULL; useng=useng->next )
2701  if ( useng->lang==0x409 )
2702  break;
2703  if ( useng!=NULL && useng->names[ttf_version]!=NULL &&
2704  sscanf(useng->names[ttf_version], "Version %f", &vn)==1 ) {
2705  head->revision = vn*65536;
2706  } else if ( sf->subfontcnt!=0 ) {
2707  int val, mant;
2708  val = floor(sf->cidversion);
2709  mant = floor(65536.*((double)sf->cidversion-val));
2710  head->revision = (val<<16) | mant;
2711  } else if ( sf->version!=NULL ) {
2712  char *pt=sf->version;
2713  double dval;
2714  int val, mant;
2715  while ( *pt && !isdigit(*pt) && *pt!='.' ) ++pt;
2716  if ( *pt ) {
2717  dval = strtod(pt,NULL);
2718  val = floor(dval);
2719  mant = floor(65536.*(dval-val));
2720  head->revision = (val<<16) | mant;
2721  }
2722  }
2723  }
2724  head->checksumAdj = 0;
2725  head->magicNum = 0x5f0f3cf5;
2726  head->flags = 8|2|1; /* baseline at 0, lsbline at 0, round ppem */
2727  if ( format>=ff_ttf && format<=ff_ttfdfont ) {
2728  if ( AnyInstructions(sf) )
2729  head->flags = 0x10|8|4|2|1; /* baseline at 0, lsbline at 0, round ppem, instructions may depend on point size, instructions change metrics */
2730  }
2731  /* If a font contains embedded bitmaps, and if some of those bitmaps have */
2732  /* a different advance width from that expected by scaling, then windows */
2733  /* will only notice the fact if the 0x10 bit is set (even though this has*/
2734  /* nothing to do with instructions) */
2735 /* Apple flags */
2736  if ( sf->hasvmetrics )
2737  head->flags |= (1<<5); /* designed to be layed out vertically */
2738  /* Bit 6 must be zero */
2739  if ( arabic )
2740  head->flags |= (1<<7);
2741  if ( sf->sm )
2742  head->flags |= (1<<8); /* has metamorphesis effects */
2743  if ( rl )
2744  head->flags |= (1<<9);
2745  indic_rearrange = 0;
2746  for ( sm = sf->sm; sm!=NULL; sm=sm->next )
2747  if ( sm->type == asm_indic )
2748  indic_rearrange = true;
2749  if ( indic_rearrange )
2750  head->flags |= (1<<10);
2751 /* End apple flags */
2752  if ( sf->head_optimized_for_cleartype )
2753  head->flags |= (1<<13);
2754  head->emunits = sf->ascent+sf->descent;
2756  head->lowestreadable = 8;
2757  head->locais32 = 1;
2758  if ( at->gi.glyph_len<0x20000 )
2759  head->locais32 = 0;
2760 
2761  /* I assume we've always got some neutrals (spaces, punctuation) */
2762  if ( lr && rl )
2763  head->dirhint = 0;
2764  else if ( rl )
2765  head->dirhint = -2;
2766  else
2767  head->dirhint = 2;
2768  if ( rl )
2769  head->flags |= (1<<9); /* Apple documents this */
2770  /* if there are any indic characters, set bit 10 */
2771 
2772  cvt_unix_to_1904(sf->creationtime,head->createtime);
2773  cvt_unix_to_1904(sf->modificationtime,head->modtime);
2774 }
2775 
2776 static void sethhead(struct hhead *hhead,struct hhead *vhead,struct alltabs *at, SplineFont *sf) {
2777  int i, width, rbearing, height, bbearing;
2778  int ymax, ymin, xmax, xmin, off;
2779  DBounds bb;
2780  /* Might as well fill in the vhead even if we don't use it */
2781  /* we just won't dump it out if we don't want it */
2782 
2783  width = 0x80000000; rbearing = 0x7fffffff; height = 0x80000000; bbearing=0x7fffffff;
2784  xmax = ymax = 0x80000000; xmin = ymin = 0x7fffffff;
2785  for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
2786  SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
2788  if ( sc->width>width ) width = sc->width;
2789  if ( sc->vwidth>height ) height = sc->vwidth;
2790  if ( sc->width-bb.maxx < rbearing ) rbearing = sc->width-bb.maxx;
2791  if ( sc->vwidth-bb.maxy < bbearing ) bbearing = sc->vwidth-bb.maxy;
2792  if ( bb.maxy > ymax ) ymax = bb.maxy;
2793  if ( bb.miny < ymin ) ymin = bb.miny;
2794  if ( bb.maxx > xmax ) xmax = bb.maxx;
2795  if ( bb.minx < xmin ) xmin = bb.minx;
2796  }
2797 
2798  if ( at->head.ymax>ymax ) ymax = at->head.ymax; /* If generated .notdef glyph is bigger than real glyphs */
2799  if ( at->head.ymin<ymin ) ymin = at->head.ymin;
2800 
2801  if ( ymax==0 && ymin==0 ) {
2802  /* this can happen in a bitmap only font */
2803  ymax = sf->ascent;
2804  ymin = -sf->descent;
2805  }
2806  hhead->version = 0x00010000;
2807  if ( sf->pfminfo.hheadascent_add )
2808  hhead->ascender = ymax + sf->pfminfo.hhead_ascent;
2809  else
2810  hhead->ascender = sf->pfminfo.hhead_ascent;
2811  if ( sf->pfminfo.hheaddescent_add )
2812  hhead->descender = ymin + sf->pfminfo.hhead_descent;
2813  else
2814  hhead->descender = sf->pfminfo.hhead_descent;
2815  hhead->linegap = sf->pfminfo.linegap;
2816 
2817  vhead->version = 0x00011000;
2818  off = (sf->ascent+sf->descent)/2;
2819  vhead->ascender = xmax-off;
2820  vhead->descender = xmin-off;
2821  vhead->linegap = sf->pfminfo.linegap;
2822 
2823  at->isfixed = at->gi.fixed_width>0;
2824  hhead->maxwidth = width;
2825  hhead->minlsb = at->head.xmin;
2826  hhead->minrsb = rbearing;
2827  /* Apple's ftxvalidator says the min sidebearing should be 0 even if it isn't */
2828  if ( hhead->minlsb>0 ) hhead->minlsb = 0;
2829  if ( hhead->minrsb>0 ) hhead->minrsb = 0;
2830  hhead->maxextent = at->head.xmax;
2831  if ( sf->italicangle==0 )
2832  hhead->caretSlopeRise = 1;
2833  else {
2834  hhead->caretSlopeRise = 100;
2835  hhead->caretSlopeRun = (int) rint(100*tan(-sf->italicangle*3.1415926535897/180.));
2836  }
2837 
2838  vhead->maxwidth = height;
2839  vhead->minlsb = at->head.ymin;
2840  vhead->minrsb = bbearing;
2841  vhead->maxextent = at->head.ymax;
2842  vhead->caretSlopeRise = 0;
2843  vhead->caretSlopeRun = 1;
2844  /* Are there vertical oblique fonts? */
2845 
2846  hhead->numMetrics = at->gi.hfullcnt;
2847  vhead->numMetrics = at->gi.vfullcnt;
2848 }
2849 
2850 static void OS2WeightCheck(struct pfminfo *pfminfo,char *weight) {
2851  if ( weight==NULL ) {
2852  /* default it */
2853  } else if ( strstrmatch(weight,"medi")!=NULL ) {
2854  pfminfo->weight = 500;
2855  pfminfo->panose[2] = 6;
2856  } else if ( strstrmatch(weight,"demi")!=NULL ||
2857  strstrmatch(weight,"halb")!=NULL ||
2858  (strstrmatch(weight,"semi")!=NULL &&
2859  strstrmatch(weight,"bold")!=NULL) ) {
2860  pfminfo->weight = 600;
2861  pfminfo->panose[2] = 7;
2862  } else if ( strstrmatch(weight,"bold")!=NULL ||
2863  strstrmatch(weight,"fett")!=NULL ||
2864  strstrmatch(weight,"gras")!=NULL ) {
2865  pfminfo->weight = 700;
2866  pfminfo->panose[2] = 8;
2867  } else if ( strstrmatch(weight,"heavy")!=NULL ) {
2868  pfminfo->weight = 800;
2869  pfminfo->panose[2] = 9;
2870  } else if ( strstrmatch(weight,"black")!=NULL ) {
2871  pfminfo->weight = 900;
2872  pfminfo->panose[2] = 10;
2873  } else if ( strstrmatch(weight,"nord")!=NULL ) {
2874  pfminfo->weight = 950;
2875  pfminfo->panose[2] = 11;
2876  } else if ( strstrmatch(weight,"thin")!=NULL ) {
2877  pfminfo->weight = 100;
2878  pfminfo->panose[2] = 2;
2879  } else if ( strstrmatch(weight,"extra")!=NULL ||
2880  strstrmatch(weight,"light")!=NULL ) {
2881  pfminfo->weight = 200;
2882  pfminfo->panose[2] = 3;
2883  } else if ( strstrmatch(weight,"light")!=NULL ) {
2884  pfminfo->weight = 300;
2885  pfminfo->panose[2] = 4;
2886  }
2887 }
2888 
2890  pfminfo->pfmfamily = 0x11;
2891  pfminfo->panose[0] = 2;
2892  pfminfo->weight = 400;
2893  pfminfo->panose[2] = 5;
2894  pfminfo->width = 5;
2895  pfminfo->panose[3] = 3;
2900 
2901  if ( sf->subfonts!=NULL ) sf = sf->subfonts[0];
2903  rint(.09*(sf->ascent+sf->descent));
2904 }
2905 
2906 void SFDefaultOS2SubSuper(struct pfminfo *pfminfo,int emsize,double italic_angle) {
2907  double s = sin(italic_angle*3.1415926535897932/180.0);
2908  pfminfo->os2_supysize = pfminfo->os2_subysize = .7*emsize;
2909  pfminfo->os2_supxsize = pfminfo->os2_subxsize = .65*emsize;
2910  pfminfo->os2_subyoff = .14*emsize;
2911  pfminfo->os2_supyoff = .48*emsize;
2914  pfminfo->os2_strikeysize = 102*emsize/2048;
2915  pfminfo->os2_strikeypos = 530*emsize/2048;
2916 }
2917 
2919  int samewid= -1;
2920  char *weight = sf->cidmaster==NULL ? sf->weight : sf->cidmaster->weight;
2921 
2922  if ( sf->pfminfo.pfmset ) {
2923  if ( pfminfo!=&sf->pfminfo )
2924  *pfminfo = sf->pfminfo;
2925  if ( !pfminfo->panose_set ) {
2926  struct pfminfo info;
2927  memset(&info,0,sizeof(info));
2928  sf->pfminfo.pfmset = false;
2930  sf->pfminfo.pfmset = true;
2931  memcpy(pfminfo->panose,info.panose,sizeof(info.panose));
2932  }
2933  } else {
2934  struct pfminfo hold;
2935  if ( pfminfo->hheadset || pfminfo->vheadset )
2936  hold = *pfminfo;
2937  else
2938  hold.hheadset = hold.vheadset = false;
2939  memset(pfminfo,'\0',sizeof(*pfminfo));
2941  samewid = CIDOneWidth(sf);
2942 
2943  pfminfo->pfmfamily = 0x10;
2944  if ( samewid>0 ) {
2945  pfminfo->pfmfamily = 0x30;
2946  /* pfminfo->panose[3] = 9; */ /* This is done later */
2947  } else if ( strstrmatch(fontname,"sans")!=NULL )
2948  pfminfo->pfmfamily = 0x20;
2949  else if ( strstrmatch(fontname,"script")!=NULL ) {
2950  pfminfo->pfmfamily = 0x40;
2951  pfminfo->panose[0] = 3;
2952  }
2953  if ( samewid==-1 )
2954  pfminfo->pfmfamily |= 0x1; /* Else it assumes monospace */
2955 
2956 /* urw uses 4 character abreviations */
2957  if ( weight!=NULL )
2960 
2961  if ( strstrmatch(fontname,"ultra")!=NULL &&
2962  strstrmatch(fontname,"condensed")!=NULL ) {
2963  pfminfo->width = 1;
2964  pfminfo->panose[3] = 8;
2965  } else if ( strstrmatch(fontname,"extra")!=NULL &&
2966  strstrmatch(fontname,"condensed")!=NULL ) {
2967  pfminfo->width = 2;
2968  pfminfo->panose[3] = 8;
2969  } else if ( strstrmatch(fontname,"semi")!=NULL &&
2970  strstrmatch(fontname,"condensed")!=NULL ) {
2971  pfminfo->width = 4;
2972  pfminfo->panose[3] = 6;
2973  } else if ( strstrmatch(fontname,"condensed")!=NULL ||
2974  strstrmatch(fontname,"narrow")!=NULL ) {
2975  pfminfo->width = 3;
2976  pfminfo->panose[3] = 6;
2977  } else if ( strstrmatch(fontname,"ultra")!=NULL &&
2978  strstrmatch(fontname,"expanded")!=NULL ) {
2979  pfminfo->width = 9;
2980  pfminfo->panose[3] = 7;
2981  } else if ( strstrmatch(fontname,"extra")!=NULL &&
2982  strstrmatch(fontname,"expanded")!=NULL ) {
2983  pfminfo->width = 8;
2984  pfminfo->panose[3] = 7;
2985  } else if ( strstrmatch(fontname,"semi")!=NULL &&
2986  strstrmatch(fontname,"expanded")!=NULL ) {
2987  pfminfo->width = 6;
2988  pfminfo->panose[3] = 5;
2989  } else if ( strstrmatch(fontname,"expanded")!=NULL ) {
2990  pfminfo->width = 7;
2991  pfminfo->panose[3] = 5;
2992  }
2993  if ( samewid>0 )
2994  pfminfo->panose[3] = 9;
2995  if ( hold.hheadset ) {
2996  pfminfo->hheadset = true;
2997  pfminfo->hheadascent_add = hold.hheadascent_add;
2998  pfminfo->hheaddescent_add = hold.hheaddescent_add;
2999  pfminfo->hhead_ascent = hold.hhead_ascent;
3000  pfminfo->hhead_descent = hold.hhead_descent;
3001  pfminfo->linegap = hold.linegap;
3002  }
3003  if ( hold.vheadset ) {
3004  pfminfo->vheadset = true;
3005  pfminfo->vlinegap = hold.vlinegap;
3006  }
3007  }
3008  if ( !pfminfo->subsuper_set )
3009  SFDefaultOS2SubSuper(pfminfo,sf->ascent+sf->descent,sf->italicangle);
3010 }
3011 
3013  int i;
3014  int acnt=0, pcnt=0;
3015 
3016  for ( i=0; i<map->enccount && i<0xffff; ++i ) {
3017  if ( map->map[i]!=-1 && sf->glyphs[map->map[i]]!=NULL &&
3018  sf->glyphs[map->map[i]]->ttf_glyph!=-1 ) {
3019  if ( i>=0xf000 && i<=0xf0ff )
3020  ++pcnt;
3021  else if ( i>=0x20 && i<=0xff )
3022  ++acnt;
3023  }
3024  }
3025 return( pcnt>acnt );
3026 }
3027 
3029  int i;
3030  uint32 latin1[8];
3031  int has_ascii, has_lineart=0, has_radical=0, has_summation=0;
3032  int cp852=0, cp775=0, cp861=0, cp860=0, cp857=0, cp855=0, cp862=0, cp863=0;
3033  int cp864=0, cp865=0, cp866=0, cp869=0, cp737=0, cp708=0, mac=0;
3034  int k;
3035  SplineChar *sc;
3036  SplineFont *sub;
3037 
3038  memset(latin1,0,sizeof(latin1));
3039  k=0;
3040  do {
3041  sub = k<sf->subfontcnt? sf->subfonts[k] : sf;
3042  for ( i=0; i<sub->glyphcnt; ++i ) if ( (sc = sub->glyphs[i])!=NULL ) {
3043  if ( sc->unicodeenc<256 && sc->unicodeenc>=0 )
3044  latin1[(sc->unicodeenc>>5)] |= 1<<(sc->unicodeenc&31);
3045  }
3046  ++k;
3047  } while ( k<sf->subfontcnt );
3048 
3049  has_ascii = latin1[1]==0xffffffff && latin1[2]==0xffffffff &&
3050  (latin1[3]&0x7fffffff)==0x7fffffff; /* DEL is not a char */
3051  CodePage[0] = CodePage[1] = 0;
3052 
3053  k=0;
3054  do {
3055  sub = k<sf->subfontcnt? sf->subfonts[k] : sf;
3056  for ( i=0; i<sub->glyphcnt; ++i ) if ( (sc = sub->glyphs[i])!=NULL ) {
3057  int uni = sc->unicodeenc;
3058  if ( uni==0xde && has_ascii )
3059  CodePage[0] |= 1<<0; /* (ANSI) Latin1 */
3060  else if ( uni==0x255a && has_ascii ) {
3061  CodePage[1] |= 1U<<30; /* WE/latin1 */ /* Not latin1 at all */
3062  CodePage[1] |= 1U<<31; /* US */
3063  } else if ( uni==0x13d && has_ascii ) {
3064  CodePage[0] |= 1<<1; /* latin2 */
3065  ++cp852;
3066  } else if ( uni==0x411 ) {
3067  CodePage[0] |= 1<<2; /* cyrillic */
3068  ++cp866;
3069  ++cp855;
3070  } else if ( uni==0x405 ) {
3071  ++cp855;
3072  } else if ( uni==0x386 ) {
3073  CodePage[0] |= 1<<3; /* greek */
3074  ++cp869;
3075  ++cp737;
3076  } else if ( uni==0x130 && has_ascii ) {
3077  CodePage[0] |= 1<<4; /* turkish */
3078  ++cp857;
3079  } else if ( uni==0x5d0 ) {
3080  CodePage[0] |= 1<<5; /* hebrew */
3081  ++cp862;
3082  } else if ( uni==0x631 ) {
3083  CodePage[0] |= 1<<6; /* arabic */
3084  ++cp864;
3085  ++cp708;
3086  } else if ( uni==0x157 && has_ascii ) {
3087  CodePage[0] |= 1<<7; /* baltic */
3088  ++cp775;
3089  } else if ( uni==0x20AB && has_ascii ) {
3090  CodePage[0] |= 1<<8; /* vietnamese */
3091  } else if ( uni==0xe45 )
3092  CodePage[0] |= 1<<16; /* thai */
3093  else if ( uni==0x30a8 )
3094  CodePage[0] |= 1<<17; /* japanese */
3095  else if ( uni==0x3105 )
3096  CodePage[0] |= 1<<18; /* simplified chinese */
3097  else if ( uni==0x3131 )
3098  CodePage[0] |= 1<<19; /* korean wansung */
3099  else if ( uni==0x592E )
3100  CodePage[0] |= 1<<20; /* traditional chinese */
3101  else if ( uni==0xacf4 )
3102  CodePage[0] |= 1<<21; /* korean Johab */
3103  else if ( uni==0x2030 && has_ascii )
3104  ++mac;
3105  else if ( uni==0x2665 && has_ascii )
3106  CodePage[0] |= 1U<<30; /* OEM */
3107  /* the symbol bit doesn't mean it contains the glyphs in symbol */
3108  /* rather that one is using a symbol encoding. Or that there are */
3109  /* glyphs with unicode encoding between 0xf000 and 0xf0ff, in which */
3110  /* case those guys should be given a symbol encoding */
3111  /* There's a bug in the way otf fonts handle this (but not ttf) and */
3112  /* they only seem to list the symbol glyphs. */
3113  /* Hence we don't test uni==0x21d4 */
3114  /* This doesn't work well either. In ttf fonts the bit is ignored */
3115  /* in otf fonts the bit means "ignore all other bits" */
3116  else if ( uni>=0xf000 && uni<=0xf0ff )
3117  CodePage[0] |= 1U<<31; /* symbol */
3118  else if ( uni==0xc5 && has_ascii )
3119  ++cp865;
3120  else if ( uni==0xe9 && has_ascii )
3121  ++cp863;
3122  else if ( uni==0xf5 && has_ascii )
3123  ++cp860;
3124  else if ( uni==0xfe && has_ascii )
3125  ++cp861;
3126  else if ( uni==0x2524 )
3127  ++has_lineart;
3128  else if ( uni==0x255c )
3129  ++cp866;
3130  else if ( uni==0xbd )
3131  ++cp869;
3132  else if ( uni==0x221A )
3133  has_radical=true;
3134  else if ( uni==0x2211 )
3135  has_summation=true;
3136  }
3137  ++k;
3138  } while ( k<sf->subfontcnt );
3139  if ( cp852 && has_lineart )
3140  CodePage[1] |= 1<<26; /* latin2 */
3141  if ( cp775 && has_lineart )
3142  CodePage[1] |= 1<<27; /* baltic */
3143  if ( cp861 && has_lineart )
3144  CodePage[1] |= 1<<22; /* MS-DOS Icelandic */
3145  if ( cp866==2 && has_lineart )
3146  CodePage[1] |= 1<<17; /* MS DOS Russian */
3147  if ( cp855==2 && has_lineart )
3148  CodePage[1] |= 1<<25; /* IBM Cyrillic */
3149  if ( cp869==2 && has_lineart )
3150  CodePage[1] |= 1<<16; /* IBM Greek */
3151  if ( cp737 && has_lineart && has_radical )
3152  CodePage[1] |= 1<<28; /* Greek, former 437 G */
3153  if ( cp857 && has_lineart )
3154  CodePage[1] |= 1<<24; /* IBM turkish */
3155  if ( cp862 && has_lineart && has_radical )
3156  CodePage[1] |= 1<<21; /* hebrew */
3157  if ( cp864 && has_radical )
3158  CodePage[1] |= 1<<19; /* arabic */
3159  if ( cp708 && has_lineart)
3160  CodePage[1] |= 1<<29; /* arabic; ASMO 708 */
3161  if ( cp863 && has_lineart && has_radical )
3162  CodePage[1] |= 1<<20; /* MS-DOS Canadian French */
3163  if ( cp865 && has_lineart && has_radical )
3164  CodePage[1] |= 1<<18; /* MS-DOS Nordic */
3165  if ( cp860 && has_lineart && has_radical )
3166  CodePage[1] |= 1<<23; /* MS-DOS Portuguese */
3167  if ( mac && has_summation )
3168  CodePage[0] |= 1U<<29; /* mac roman */
3169 }
3170 
3172  int i, k;
3173  unsigned j;
3174  SplineChar *sc;
3175  SplineFont *sub;
3176 
3177  memset(Ranges,0,4*sizeof(uint32));
3178  k=0;
3179  do {
3180  sub = k<sf->subfontcnt? sf->subfonts[k] : sf;
3181  for ( i=0; i<sub->glyphcnt; ++i ) if ( (sc = sub->glyphs[i])!=NULL ) {
3182  if ( SCWorthOutputting(sc) && sc->unicodeenc!=-1 ) {
3183  if ( sc->unicodeenc > 0xffff )
3184  Ranges[57>>5] |= (1<<(57&31));
3185  for ( j=0; j<sizeof(uniranges)/sizeof(uniranges[0]); ++j )
3186  if ( sc->unicodeenc>=uniranges[j][0] &&
3187  sc->unicodeenc<=uniranges[j][1] ) {
3188  int bit = uniranges[j][2];
3189  Ranges[bit>>5] |= (1<<(bit&31));
3190  break;
3191  }
3192  }
3193  }
3194  ++k;
3195  } while ( k<sf->subfontcnt );
3196 }
3197 
3198 static void WinBB(SplineFont *sf,uint16 *winascent,uint16 *windescent,struct alltabs *at) {
3199  /* The windows ascent/descent is calculated on the ymin/max of the */
3200  /* glyphs in the so called ANSI character set. I'm going to pretend */
3201  /* that's Latin1 with a few additions */
3202  /* Well, that's what is documented, but the documentation says contradictory */
3203  /* things. I believe that winAscent should be the same as hhea.ascent */
3204 
3205  *winascent = at->head.ymax;
3206  *windescent = -at->head.ymin; /* Should be positive */
3207  if ( sf->cidmaster!=NULL )
3208  sf = sf->cidmaster;
3209 
3210  if ( sf->pfminfo.winascent_add )
3211  *winascent += sf->pfminfo.os2_winascent;
3212  else
3213  *winascent = sf->pfminfo.os2_winascent;
3214  if ( sf->pfminfo.windescent_add )
3215  *windescent += sf->pfminfo.os2_windescent;
3216  else
3217  *windescent = sf->pfminfo.os2_windescent;
3218 }
3219 
3220 static void redohead(struct alltabs *at);
3221 
3222 static void setos2(struct os2 *os2,struct alltabs *at, SplineFont *sf,
3223  enum fontformat format) {
3224  int i,cnt1,cnt2,first,last,avg1,avg2,gid;
3225  char *pt;
3226  static int const weightFactors[26] = { 64, 14, 27, 35, 100, 20, 14, 42, 63,
3227  3, 6, 35, 20, 56, 56, 17, 4, 49, 56, 71, 31, 10, 18, 3, 18, 2 };
3228  EncMap *map;
3229  SplineChar *sc;
3230  int modformat = format;
3231 
3232  os2->version = 1;
3233  if ( format==ff_otf || format==ff_otfcid )
3234  os2->version = 3;
3235  if ( sf->use_typo_metrics || sf->weight_width_slope_only )
3236  os2->version = 4;
3237  if ( sf->os2_version > os2->version )
3238  os2->version = sf->os2_version;
3239  if (( format>=ff_ttf && format<=ff_otfdfont) && (at->gi.flags&ttf_flag_symbol))
3240  modformat = ff_ttfsym;
3241 
3242  os2->weightClass = sf->pfminfo.weight;
3243  os2->widthClass = sf->pfminfo.width;
3244  os2->fstype = 0x8;
3245  if ( sf->pfminfo.fstype!=-1 )
3246  os2->fstype = sf->pfminfo.fstype;
3247  if ( !sf->pfminfo.subsuper_set )
3248  SFDefaultOS2SubSuper(&sf->pfminfo,sf->ascent+sf->descent,sf->italicangle);
3249  os2->ysupYSize = sf->pfminfo.os2_supysize;
3250  os2->ysubXSize = sf->pfminfo.os2_subxsize;
3251  os2->ysubYSize = sf->pfminfo.os2_subysize;
3252  os2->ysupXSize = sf->pfminfo.os2_supxsize;
3253  os2->ysubYOff = sf->pfminfo.os2_subyoff;
3254  os2->ysubXOff = sf->pfminfo.os2_subxoff;
3255  os2->ysupXOff = sf->pfminfo.os2_supxoff;
3256  os2->ysupYOff = sf->pfminfo.os2_supyoff;
3257  os2->yStrikeoutSize = sf->pfminfo.os2_strikeysize;
3258  os2->yStrikeoutPos = sf->pfminfo.os2_strikeypos;
3259  if ( sf->pfminfo.stylemap!=-1 ) {
3260  int changed = 0;
3261  os2->fsSel = sf->pfminfo.stylemap;
3262  /* Make sure fsSel and macStyle don't contradict */
3263  if (at->head.macstyle&1 && !(os2->fsSel&32)) {at->head.macstyle &= 0x7E; changed=1;}
3264  if (at->head.macstyle&2 && !(os2->fsSel&1)) {at->head.macstyle &= 0x7D; changed=1;}
3265  if (changed) redohead(at);
3266  } else {
3267  os2->fsSel = (at->head.macstyle&1?32:0)|(at->head.macstyle&2?1:0);
3268  if ( os2->fsSel==0 && sf->pfminfo.weight==400 )
3269  os2->fsSel = 64; /* Regular */
3270  }
3271  if ( sf->fullname!=NULL && strstrmatch(sf->fullname,"outline")!=NULL )
3272  os2->fsSel |= 8;
3273  if ( os2->version>=4 ) {
3274  if ( strstrmatch(sf->fontname,"Obli")!=NULL ) {
3275  os2->fsSel &= ~1; /* Turn off Italic */
3276  os2->fsSel |= 512; /* Turn on Oblique */
3277  }
3278  if ( sf->use_typo_metrics )
3279  os2->fsSel |= 128; /* Don't use win ascent/descent for line spacing */
3280  if ( sf->weight_width_slope_only )
3281  os2->fsSel |= 256;
3282  }
3283 /* David Lemon @Adobe.COM
3284 1) The sTypoAscender and sTypoDescender values should sum to 2048 in
3285 a 2048-unit font. They indicate the position of the em square
3286 relative to the baseline.
3287 GWW: Almost, sTypoAscender-sTypoDescender == EmSize
3288 
3289 2) The usWinAscent and usWinDescent values represent the maximum
3290 height and depth of specific glyphs within the font, and some
3291 applications will treat them as the top and bottom of the font
3292 bounding box. (the "ANSI" glyphs)
3293 GWW: That's what's documented. But it means non-ANSI glyphs get clipped. So the
3294 docs are wrong.
3295 */
3296  if ( sf->pfminfo.typoascent_add )
3297  os2->ascender = sf->ascent + sf->pfminfo.os2_typoascent;
3298  else
3299  os2->ascender = sf->pfminfo.os2_typoascent;
3300  if ( sf->pfminfo.typodescent_add )
3301  os2->descender = -sf->descent + sf->pfminfo.os2_typodescent; /* Should be neg */
3302  else
3303  os2->descender = sf->pfminfo.os2_typodescent;
3304  WinBB(sf,&os2->winascent,&os2->windescent,at);
3305  os2->linegap = sf->pfminfo.os2_typolinegap;
3306  os2->sFamilyClass = sf->pfminfo.os2_family_class;
3307 
3308  avg1 = avg2 = last = 0; first = 0xffff;
3309  cnt1 = cnt2 = 0;
3310  for ( i=0; i<sf->glyphcnt; ++i ) if ( (sc = sf->glyphs[i])!=NULL ) {
3311  if ( SCWorthOutputting(sc) && sc->unicodeenc!=-1 ) {
3312  /* Don't include the dummy glyphs (.notdef, .null, etc.) they aren't */
3313  /* really encoded. Don't include glyphs out of BMP, OS/2 uses shorts */
3314  /* for the first/last char and can't represent them. */
3315  /* If no BMP glyphs, then first should be 0xffff. If any outside */
3316  /* BMP then last is 0xffff */
3317  /* sc->ttf_glyph>2 is to skip the first few truetype glyphs but */
3318  /* that doesn't work for cff files which only have .notdef to ignore */
3319  if ( ( format>=ff_ttf && format<=ff_otfdfont && sc->ttf_glyph>2) ||
3320  ( format>=ff_ttf && format<=ff_otfdfont && sc->ttf_glyph>0) ) {
3321  if ( sc->unicodeenc<=0xffff ) {
3322  if ( sc->unicodeenc<first ) first = sc->unicodeenc;
3323  if ( sc->unicodeenc>last ) last = sc->unicodeenc;
3324  } else {
3325  last = 0xffff;
3326  }
3327  }
3328  if ( sc->width!=0 ) {
3329  avg2 += sc->width; ++cnt2;
3330  }
3331  if ( sc->unicodeenc==' ') {
3332  avg1 += sc->width * 166; ++cnt1;
3333  } else if (sc->unicodeenc>='a' && sc->unicodeenc<='z') {
3334  avg1 += sc->width * weightFactors[sc->unicodeenc-'a']; ++cnt1;
3335  }
3336  }
3337  }
3338  if ( sf->pfminfo.hasunicoderanges )
3339  memcpy(os2->unicoderange,sf->pfminfo.unicoderanges,sizeof(os2->unicoderange));
3340  else
3342  if ( modformat==ff_ttfsym ) /* MS Symbol font has this set to zero. Does it matter? */
3343  memset(os2->unicoderange,0,sizeof(os2->unicoderange));
3344 
3345  if ( sf->pfminfo.pfmset )
3346  strncpy(os2->achVendID,sf->pfminfo.os2_vendor,4);
3347  else if ( TTFFoundry!=NULL )
3349  else
3350  memcpy(os2->achVendID,"PfEd",4);
3351  for ( pt=os2->achVendID; pt<os2->achVendID && *pt!='\0'; ++pt );
3352  while ( pt<os2->achVendID ) *pt++ = ' '; /* Pad with spaces not NUL */
3353 
3354  /* v1,2 & v3,4 have different ways of calculating avgCharWid. */
3355  /* but I'm told that using the v3 way breaks display of CJK fonts in windows */
3356  os2->avgCharWid = 500;
3358  if ( cnt1==27 )
3359  os2->v1_avgCharWid = avg1/1000;
3360  if ( cnt2!=0 )
3361  os2->v3_avgCharWid = avg2/cnt2;
3362  memcpy(os2->panose,sf->pfminfo.panose,sizeof(os2->panose));
3363  map = at->map;
3364  if ( modformat==ff_ttfsym ) {
3365  if ( sf->pfminfo.hascodepages )
3366  memcpy(os2->ulCodePage,sf->pfminfo.codepages,sizeof(os2->ulCodePage));
3367  else {
3368  os2->ulCodePage[0] = 0x80000000;
3369  os2->ulCodePage[1] = 0;
3370  }
3371  if ( AlreadyMSSymbolArea(sf,map)) {
3372  first = 0xf0ff; last = 0;
3373  for ( i=0xf020; i<map->enccount && i<=0xf0ff; ++i )
3374  if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
3375  sf->glyphs[gid]->ttf_glyph!=-1 ) {
3376  if ( i<first ) first = i;
3377  if ( i>last ) last = i;
3378  }
3379  for ( i=0; i<map->enccount && i<=255; ++i )
3380  if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
3381  sf->glyphs[gid]->ttf_glyph!=-1 ) {
3382  if ( i+0xf000<first ) first = i+0xf000;
3383  if ( i+0xf000>last ) last = i+0xf000;
3384  }
3385  os2->firstcharindex = first; /* This gets mapped to space */
3386  os2->lastcharindex = last;
3387  } else {
3388  first = 255; last = 0;
3389  for ( i=0; i<map->enccount && i<=255; ++i )
3390  if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
3391  sf->glyphs[gid]->ttf_glyph!=-1 ) {
3392  if ( i<first ) first = i;
3393  if ( i>last ) last = i;
3394  }
3395  for ( i=0xf020; i<map->enccount && i<=0xf0ff; ++i )
3396  if ( (gid=map->map[i])!=-1 && sf->glyphs[gid]!=NULL &&
3397  sf->glyphs[gid]->ttf_glyph!=-1 ) {
3398  if ( i-0xf000<first ) first = i-0xf000;
3399  if ( i-0xf000>last ) last = i-0xf000;
3400  }
3401  if ( first<' ' ) first = ' ';
3402  os2->firstcharindex = 0xf000 + first; /* This gets mapped to space */
3403  os2->lastcharindex = 0xf000 + last;
3404  }
3405  } else {
3407  os2->lastcharindex = last;
3408  if ( sf->pfminfo.hascodepages )
3409  memcpy(os2->ulCodePage,sf->pfminfo.codepages,sizeof(os2->ulCodePage));
3410  else
3412  /* Herbert Duerr: */
3413  /* Some old versions of Windows do not provide access to all */
3414  /* glyphs in a font if the fonts contains non-PUA symbols */
3415  /* and thus only has sets the codepage flag for symbol */
3416  /* => a workaround for this problem on Windows legacy versions */
3417  /* is to use an OS2-table version without codepage flags */
3418  /* GWW: */
3419  /* This sounds to me like a windows bug rather than one in ff */
3420  /* and this is a work-around for windows. As far as I can tell */
3421  /* ff is setting the codepage field properly, it's just that */
3422  /* windows doesn't interpret that bit correctly */
3423  /* GWW: Things get worse. Windows no longer accepts a version 0 */
3424  /* for OS/2. FontLab simply lies and says we have a latin1 */
3425  /* code page when we don't. */
3426  if( !sf->pfminfo.hascodepages )
3427  if( (os2->ulCodePage[0]&~(1U<<31))==0 && os2->ulCodePage[1]==0 )
3428  os2->ulCodePage[0] |= 1;
3429  }
3430 
3431  if ( os2->version>=2 ) {
3432  if ( sf->pfminfo.os2_xheight!=0 )
3433  os2->xHeight = sf->pfminfo.os2_xheight;
3434  else {
3435  double xh = SFXHeight(sf,at->gi.layer,true);
3436  os2->xHeight = (xh >= 0.0 ? xh : 0);
3437  }
3438  if ( sf->pfminfo.os2_capheight!=0 )
3439  os2->capHeight = sf->pfminfo.os2_capheight;
3440  else {
3441  double caph = SFCapHeight(sf,at->gi.layer,true);
3442  os2->capHeight = (caph >= 0.0 ? caph : 0);
3443  }
3444  os2->defChar = 0;
3445  if ( format==ff_otf || format==ff_otfcid )
3446  os2->defChar = ' ';
3447  os2->breakChar = ' ';
3448  os2->maxContext = 1; /* Kerning will set this to 2, ligature to whatever */
3449  }
3450 
3451  if ( os2->version>=3 && os2->v3_avgCharWid!=0 )
3453  else if ( os2->v1_avgCharWid!=0 )
3455  else if ( os2->v3_avgCharWid!=0 )
3457 }
3458 
3459 static void redoloca(struct alltabs *at) {
3460  int i;
3461 
3462  at->loca = tmpfile2();
3463  if ( at->head.locais32 ) {
3464  for ( i=0; i<=at->maxp.numGlyphs; ++i )
3465  putlong(at->loca,at->gi.loca[i]);
3466  at->localen = sizeof(int32)*(at->maxp.numGlyphs+1);
3467  } else {
3468  for ( i=0; i<=at->maxp.numGlyphs; ++i )
3469  putshort(at->loca,at->gi.loca[i]/2);
3470  at->localen = sizeof(int16)*(at->maxp.numGlyphs+1);
3471  if ( ftell(at->loca)&2 )
3472  putshort(at->loca,0);
3473  }
3474  if ( at->format!=ff_type42 && at->format!=ff_type42cid ) {
3475  free(at->gi.loca);
3476  at->gi.loca = NULL;
3477  }
3478 }
3479 
3480 static void dummyloca(struct alltabs *at) {
3481 
3482  at->loca = tmpfile2();
3483  if ( at->head.locais32 ) {
3484  putlong(at->loca,0);
3485  at->localen = sizeof(int32);
3486  } else {
3487  putshort(at->loca,0);
3488  at->localen = sizeof(int16);
3489  putshort(at->loca,0); /* pad it */
3490  }
3491 }
3492 
3493 static void redohead(struct alltabs *at) {
3494  at->headf = tmpfile2();
3495 
3496  putlong(at->headf,at->head.version);
3497  putlong(at->headf,at->head.revision);
3498  putlong(at->headf,at->head.checksumAdj);
3499  putlong(at->headf,at->head.magicNum);
3500  putshort(at->headf,at->head.flags);
3501  putshort(at->headf,at->head.emunits);
3502  putlong(at->headf,at->head.createtime[1]);
3503  putlong(at->headf,at->head.createtime[0]);
3504  putlong(at->headf,at->head.modtime[1]);
3505  putlong(at->headf,at->head.modtime[0]);
3506  putshort(at->headf,at->head.xmin);
3507  putshort(at->headf,at->head.ymin);
3508  putshort(at->headf,at->head.xmax);
3509  putshort(at->headf,at->head.ymax);
3510  putshort(at->headf,at->head.macstyle);
3511  putshort(at->headf,at->head.lowestreadable);
3512  putshort(at->headf,at->head.dirhint);
3513  putshort(at->headf,at->head.locais32);
3514  putshort(at->headf,at->head.glyphformat);
3515 
3516  at->headlen = ftell(at->headf);
3517  if ( (at->headlen&2)!=0 )
3518  putshort(at->headf,0);
3519 }
3520 
3521 static void redohhead(struct alltabs *at,int isv) {
3522  int i;
3523  struct hhead *head;
3524  FILE *f;
3525 
3526  if ( !isv ) {
3527  f = at->hheadf = tmpfile2();
3528  head = &at->hhead;
3529  } else {
3530  f = at->vheadf = tmpfile2();
3531  head = &at->vhead;
3532  }
3533 
3534  putlong(f,head->version);
3535  putshort(f,head->ascender);
3536  putshort(f,head->descender);
3537  putshort(f,head->linegap);
3538  putshort(f,head->maxwidth);
3539  putshort(f,head->minlsb);
3540  putshort(f,head->minrsb);
3541  putshort(f,head->maxextent);
3542  putshort(f,head->caretSlopeRise);
3543  putshort(f,head->caretSlopeRun);
3544  for ( i=0; i<5; ++i )
3545  putshort(f,head->mbz[i]);
3546  putshort(f,head->metricformat);
3547  putshort(f,head->numMetrics);
3548 
3549  if ( !isv ) {
3550  at->hheadlen = ftell(f);
3551  if ( (at->hheadlen&2)!=0 )
3552  putshort(f,0);
3553  } else {
3554  at->vheadlen = ftell(f);
3555  if ( (at->vheadlen&2)!=0 )
3556  putshort(f,0);
3557  }
3558 }
3559 
3560 static void redomaxp(struct alltabs *at,enum fontformat format) {
3561  at->maxpf = tmpfile2();
3562 
3563  putlong(at->maxpf,at->maxp.version);
3564  putshort(at->maxpf,at->maxp.numGlyphs);
3565  if ( format!=ff_otf && format!=ff_otfcid ) {
3566  putshort(at->maxpf,at->maxp.maxPoints);
3567  putshort(at->maxpf,at->maxp.maxContours);
3568  putshort(at->maxpf,at->maxp.maxCompositPts);
3570  putshort(at->maxpf,at->maxp.maxZones);
3571  putshort(at->maxpf,at->maxp.maxTwilightPts);
3572  putshort(at->maxpf,at->maxp.maxStorage);
3573  putshort(at->maxpf,at->maxp.maxFDEFs);
3574  putshort(at->maxpf,at->maxp.maxIDEFs);
3575  putshort(at->maxpf,at->maxp.maxStack);
3576  putshort(at->maxpf,at->maxp.maxglyphInstr);
3579  }
3580 
3581  at->maxplen = ftell(at->maxpf);
3582  if ( (at->maxplen&2)!=0 )
3583  putshort(at->maxpf,0);
3584 }
3585 
3586 static void redoos2(struct alltabs *at) {
3587  int i;
3588  at->os2f = tmpfile2();
3589 
3590  putshort(at->os2f,at->os2.version);
3591  putshort(at->os2f,at->os2.avgCharWid);
3592  putshort(at->os2f,at->os2.weightClass);
3593  putshort(at->os2f,at->os2.widthClass);
3594  putshort(at->os2f,at->os2.fstype);
3595  putshort(at->os2f,at->os2.ysubXSize);
3596  putshort(at->os2f,at->os2.ysubYSize);
3597  putshort(at->os2f,at->os2.ysubXOff);
3598  putshort(at->os2f,at->os2.ysubYOff);
3599  putshort(at->os2f,at->os2.ysupXSize);
3600  putshort(at->os2f,at->os2.ysupYSize);
3601  putshort(at->os2f,at->os2.ysupXOff);
3602  putshort(at->os2f,at->os2.ysupYOff);
3603  putshort(at->os2f,at->os2.yStrikeoutSize);
3604  putshort(at->os2f,at->os2.yStrikeoutPos);
3605  putshort(at->os2f,at->os2.sFamilyClass);
3606  for ( i=0; i<10; ++i )
3607  putc(at->os2.panose[i],at->os2f);
3608  for ( i=0; i<4; ++i )
3609  putlong(at->os2f,at->os2.unicoderange[i]);
3610  for ( i=0; i<4; ++i )
3611  putc(at->os2.achVendID[i],at->os2f);
3612  putshort(at->os2f,at->os2.fsSel);
3613  putshort(at->os2f,at->os2.firstcharindex);
3614  putshort(at->os2f,at->os2.lastcharindex);
3615  putshort(at->os2f,at->os2.ascender);
3616  putshort(at->os2f,at->os2.descender);
3617  putshort(at->os2f,at->os2.linegap);
3618  putshort(at->os2f,at->os2.winascent);
3619  putshort(at->os2f,at->os2.windescent);
3620  if ( at->os2.version>=1 ) {
3621  putlong(at->os2f,at->os2.ulCodePage[0]);
3622  putlong(at->os2f,at->os2.ulCodePage[1]);
3623  }
3624 
3625  if ( at->os2.version>=2 ) {
3626  putshort(at->os2f,at->os2.xHeight);
3627  putshort(at->os2f,at->os2.capHeight);
3628  putshort(at->os2f,at->os2.defChar);
3629  putshort(at->os2f,at->os2.breakChar);
3630  putshort(at->os2f,at->os2.maxContext);
3631  }
3632 
3633  at->os2len = ftell(at->os2f);
3634  if ( (at->os2len&2)!=0 )
3635  putshort(at->os2f,0);
3636 }
3637 
3638 static void dumpgasp(struct alltabs *at, SplineFont *sf) {
3639  int i;
3640 
3641  at->gaspf = tmpfile2();
3642  if ( sf->gasp_cnt==0 ) {
3643  putshort(at->gaspf,0); /* Old version number */
3644  /* For fonts with no instructions always dump a gasp table which */
3645  /* asks for grey and no grid fit */
3646  putshort(at->gaspf,1);
3647  putshort(at->gaspf,0xffff); /* Upper bound on pixels/em for this range */
3648  putshort(at->gaspf,0x2); /* Grey scale, no gridfitting */
3649  /* No hints, so no grids to fit */
3650  } else {
3651  putshort(at->gaspf,sf->gasp_version); /* New version number, with clear type info */
3652  putshort(at->gaspf,sf->gasp_cnt);
3653  for ( i=0; i<sf->gasp_cnt; ++i ) {
3654  putshort(at->gaspf,sf->gasp[i].ppem);
3655  putshort(at->gaspf,sf->gasp[i].flags);
3656  }
3657  }
3658  at->gasplen = ftell(at->gaspf);
3659  /* This table is always 32 bit aligned */
3660 }
3661 
3662 static void dumpstr(FILE *file,char *str) {
3663  do {
3664  putc(*str,file);
3665  } while ( *str++!='\0' );
3666 }
3667 
3668 static void dumpustr(FILE *file,char *utf8_str) {
3669  unichar_t *ustr = utf82u_copy(utf8_str), *pt=ustr;
3670  do {
3671  putc(*pt>>8,file);
3672  putc(*pt&0xff,file);
3673  } while ( *pt++!='\0' );
3674  free(ustr);
3675 }
3676 
3677 static void dumppstr(FILE *file,const char *str) {
3678  putc(strlen(str),file);
3679  fwrite(str,sizeof(char),strlen(str),file);
3680 }
3681 
3682 char *utf8_verify_copy(const char *str) {
3683  /* When given a postscript string it SHOULD be in ASCII. But it will often*/
3684  /* contain a copyright symbol (sometimes in latin1, sometimes in macroman)*/
3685  /* unfortunately both encodings use 0xa9 for copyright so we can't distinguish */
3686  /* guess that it's latin1 (or that copyright is the only odd char which */
3687  /* means a latin1 conversion will work for macs too). */
3688 
3689  if ( str==NULL )
3690 return( NULL );
3691 
3692  if ( utf8_valid(str))
3693 return( copy(str)); /* Either in ASCII (good) or appears to be utf8*/
3694 return( latin1_2_utf8_copy(str));
3695 }
3696 
3697 /* Oh. If the encoding is symbol (platform=3, specific=0) then Windows won't */
3698 /* accept the font unless the name table also has entries for (3,0). I'm not */
3699 /* sure if this is the case for the CJK encodings (docs don't mention that) */
3700 /* but let's do it just in case */
3702  time_t now;
3703  struct tm *tm;
3704  char buffer[200];
3705 
3706  if ( dummy->names[ttf_copyright]==NULL || *dummy->names[ttf_copyright]=='\0' )
3707  dummy->names[ttf_copyright] = utf8_verify_copy(sf->copyright);
3708  if ( dummy->names[ttf_family]==NULL || *dummy->names[ttf_family]=='\0' )
3709  dummy->names[ttf_family] = utf8_verify_copy(sf->familyname);
3710  if ( dummy->names[ttf_subfamily]==NULL || *dummy->names[ttf_subfamily]=='\0' )
3712  if ( dummy->names[ttf_uniqueid]==NULL || *dummy->names[ttf_uniqueid]=='\0' ) {
3713  time(&now);
3714  tm = localtime(&now);
3715  sprintf( buffer, "%s : %s : %d-%d-%d",
3716  TTFFoundry?TTFFoundry:"FontForge 2.0",
3717  sf->fullname!=NULL?sf->fullname:sf->fontname,
3718  tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900 );
3719  dummy->names[ttf_uniqueid] = copy(buffer);
3720  }
3721  if ( dummy->names[ttf_fullname]==NULL || *dummy->names[ttf_fullname]=='\0' )
3722  dummy->names[ttf_fullname] = utf8_verify_copy(sf->fullname);
3723  if ( dummy->names[ttf_version]==NULL || *dummy->names[ttf_version]=='\0' ) {
3724  if ( sf->subfontcnt!=0 )
3725  sprintf( buffer, "Version %f ", (double)sf->cidversion );
3726  else if ( sf->version!=NULL )
3727  sprintf(buffer,"Version %.20s ", sf->version);
3728  else
3729  strcpy(buffer,"Version 1.0" );
3730  dummy->names[ttf_version] = copy(buffer);
3731  }
3732  if ( dummy->names[ttf_postscriptname]==NULL || *dummy->names[ttf_postscriptname]=='\0' )
3733  dummy->names[ttf_postscriptname] = utf8_verify_copy(sf->fontname);
3734 }
3735 
3736 typedef struct {
3743 } NameEntry;
3744 
3745 typedef struct {
3747  int cur, max;
3748  enum fontformat format;
3752 } NamTab;
3753 
3754 static int compare_entry(const void *_mn1, const void *_mn2) {
3755  const NameEntry *mn1 = _mn1, *mn2 = _mn2;
3756 
3757  if ( mn1->platform!=mn2->platform )
3758 return( mn1->platform - mn2->platform );
3759  if ( mn1->specific!=mn2->specific )
3760 return( mn1->specific - mn2->specific );
3761  if ( mn1->lang!=mn2->lang )
3762 return( mn1->lang - mn2->lang );
3763 
3764 return( mn1->strid-mn2->strid );
3765 }
3766 
3767 static void AddEncodedName(NamTab *nt,char *utf8name,uint16 lang,uint16 strid) {
3768  NameEntry *ne;
3769  int maclang, macenc= -1, specific;
3770  char *macname = NULL;
3771 
3772  if ( strid==ttf_postscriptname && lang!=0x409 )
3773 return; /* Should not happen, but it did */
3774 
3775  if ( nt->cur+6>=nt->max ) {
3776  if ( nt->cur==0 )
3777  nt->entries = malloc((nt->max=100)*sizeof(NameEntry));
3778  else
3779  nt->entries = realloc(nt->entries,(nt->max+=100)*sizeof(NameEntry));
3780  }
3781 
3782  ne = nt->entries + nt->cur;
3783 
3784  ne->platform = 3; /* Windows */
3785  ne->specific = 1; /* unicode */
3786  ne->lang = lang;
3787  ne->strid = strid;
3788  ne->offset = ftell(nt->strings);
3789  ne->len = 2*utf82u_strlen(utf8name);
3790  dumpustr(nt->strings,utf8name);
3791  ++ne;
3792 
3793  if ( nt->format==ff_ttfsym ) {
3794  *ne = ne[-1];
3795  ne->specific = 0; /* Windows "symbol" */
3796  ++ne;
3797  }
3798 
3799  maclang = WinLangToMac(lang);
3800  if ( !nt->applemode && lang!=0x409 )
3801  maclang = 0xffff;
3802  if ( maclang!=0xffff ) {
3803 #ifdef FONTFORGE_CONFIG_APPLE_UNICODE_NAMES
3804  if ( strid!=ttf_postscriptname ) {
3805  *ne = ne[-1];
3806  ne->platform = 0; /* Mac unicode */
3807  ne->specific = 0; /* 3 => Unicode 2.0 semantics */ /* 0 ("default") is also a reasonable value */
3808  ne->lang = maclang;
3809  ++ne;
3810  }
3811 #endif
3812 
3813  macenc = MacEncFromMacLang(maclang);
3814  macname = Utf8ToMacStr(utf8name,macenc,maclang);
3815  if ( macname!=NULL ) {
3816  ne->platform = 1; /* apple non-unicode encoding */
3817  ne->specific = macenc; /* whatever */
3818  ne->lang = maclang;
3819  ne->strid = strid;
3820  ne->offset = ftell(nt->strings);
3821  ne->len = strlen(macname);
3822  dumpstr(nt->strings,macname);
3823  ++ne;
3824  free(macname);
3825  }
3826  }
3827 
3828  specific = nt->encoding_name->is_korean ? 5 : /* Wansung, korean */
3829  nt->encoding_name->is_japanese ? 2 : /* SJIS */
3830  nt->encoding_name->is_simplechinese ? 3 :/* packed gb2312, don't know the real name */
3831  strmatch(nt->encoding_name->enc_name,"EUC-GB12345")==0 ? 3 :/* Lie */
3832  nt->encoding_name->is_tradchinese ? 4 : /* Big5, traditional Chinese */
3833  -1;
3834  if ( specific != -1 ) {
3835  ne->platform = 3; /* windows */
3836  ne->specific = specific; /* whatever */
3837  ne->lang = lang;
3838  ne->strid = strid;
3839  if ( macname!=NULL &&
3840  (( specific== 2 && macenc==1 ) || /* Japanese */
3841  ( specific== 3 && macenc==25 ) || /* simplified chinese */
3842  ( specific== 4 && macenc==2 ) || /* traditional chinese */
3843  ( specific== 5 && macenc==3 )) ) { /* wansung korean */
3844  ne->offset = ne[-1].offset;
3845  ne->len = ne[-1].len;
3846  } else {
3847  char *space, *out;
3848  const char *encname;
3849  ICONV_CONST char *in;
3850  Encoding *enc;
3851  size_t inlen, outlen;
3852  ne->offset = ftell(nt->strings);
3853  encname = nt->encoding_name->is_japanese ? "SJIS" :
3854  strmatch(nt->encoding_name->enc_name,"JOHAB")==0 ? "JOHAB" :
3855  nt->encoding_name->is_korean ? "EUC-KR" :
3856  nt->encoding_name->is_simplechinese ? "EUC-CN" :
3857  nt->encoding_name->enc_name;
3858  enc = FindOrMakeEncoding(encname);
3859  if ( enc==NULL )
3860  --ne;
3861  else {
3862  unichar_t *uin = utf82u_copy(utf8name);
3863  outlen = 3*strlen(utf8name)+10;
3864  out = space = malloc(outlen+2);
3865  in = (char *) uin; inlen = 2*u_strlen(uin);
3866  iconv(enc->fromunicode,NULL,NULL,NULL,NULL); /* should not be needed, but just in case */
3867  iconv(enc->fromunicode,&in,&inlen,&out,&outlen);
3868  out[0] = '\0'; out[1] = '\0';
3869  ne->offset =