beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / luafontloader / fontforge / fontforge / tottf.c
blob3a1f02c273e640d65726087d831d705471a18df1
1 /* Copyright (C) 2000-2008 by George Williams */
2 /*
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "pfaedit.h"
28 #include <math.h>
29 #include <unistd.h>
30 #include <time.h>
31 #include <locale.h>
32 #include <utype.h>
33 #include <ustring.h>
34 #include <chardata.h>
36 #ifdef __CygWin
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <unistd.h>
40 #endif
42 #include "ttf.h"
44 char *TTFFoundry=NULL;
46 /* This file produces a ttf file given a splinefont. */
48 /* ************************************************************************** */
50 /* Required tables:
51 cmap encoding
52 head header data
53 hhea horizontal metrics header data
54 hmtx horizontal metrics (widths, lsidebearing)
55 maxp various maxima in the font
56 name various names associated with the font
57 post postscript names and other stuff
58 Required by windows but not mac
59 OS/2 bleah.
60 Required for TrueType
61 loca pointers to the glyphs
62 glyf character shapes
63 Required for OpenType (Postscript)
64 CFF A complete postscript CFF font here with all its internal tables
65 Required for bitmaps
66 bdat/EBDT bitmap data
67 bloc/EBLC pointers to bitmaps
68 bhed for apple bitmap only fonts, replaces head
69 Optional for bitmaps
70 EBSC bitmap scaling table (used in windows "bitmap-only" fonts)
71 OpenType
72 GPOS (opentype, if kern,anchor data are present)
73 GSUB (opentype, if ligature (other subs) data are present)
74 GDEF (opentype, if anchor data are present)
75 MATH
76 MATH (MS proposal, if math data present)
77 additional tables
78 cvt for hinting
79 gasp to control when things should be hinted
80 fpgm for hinting (currently only copied and dumped verbatim)
81 prep for hinting (currently only copied and dumped verbatim)
82 FontForge
83 PfEd My own table
84 TeX
85 TeX TeX specific info (stuff that used to live in tfm files)
88 const char *ttfstandardnames[258] = {
89 ".notdef",
90 ".null",
91 "nonmarkingreturn",
92 "space",
93 "exclam",
94 "quotedbl",
95 "numbersign",
96 "dollar",
97 "percent",
98 "ampersand",
99 "quotesingle",
100 "parenleft",
101 "parenright",
102 "asterisk",
103 "plus",
104 "comma",
105 "hyphen",
106 "period",
107 "slash",
108 "zero",
109 "one",
110 "two",
111 "three",
112 "four",
113 "five",
114 "six",
115 "seven",
116 "eight",
117 "nine",
118 "colon",
119 "semicolon",
120 "less",
121 "equal",
122 "greater",
123 "question",
124 "at",
125 "A",
126 "B",
127 "C",
128 "D",
129 "E",
130 "F",
131 "G",
132 "H",
133 "I",
134 "J",
135 "K",
136 "L",
137 "M",
138 "N",
139 "O",
140 "P",
141 "Q",
142 "R",
143 "S",
144 "T",
145 "U",
146 "V",
147 "W",
148 "X",
149 "Y",
150 "Z",
151 "bracketleft",
152 "backslash",
153 "bracketright",
154 "asciicircum",
155 "underscore",
156 "grave",
157 "a",
158 "b",
159 "c",
160 "d",
161 "e",
162 "f",
163 "g",
164 "h",
165 "i",
166 "j",
167 "k",
168 "l",
169 "m",
170 "n",
171 "o",
172 "p",
173 "q",
174 "r",
175 "s",
176 "t",
177 "u",
178 "v",
179 "w",
180 "x",
181 "y",
182 "z",
183 "braceleft",
184 "bar",
185 "braceright",
186 "asciitilde",
187 "Adieresis",
188 "Aring",
189 "Ccedilla",
190 "Eacute",
191 "Ntilde",
192 "Odieresis",
193 "Udieresis",
194 "aacute",
195 "agrave",
196 "acircumflex",
197 "adieresis",
198 "atilde",
199 "aring",
200 "ccedilla",
201 "eacute",
202 "egrave",
203 "ecircumflex",
204 "edieresis",
205 "iacute",
206 "igrave",
207 "icircumflex",
208 "idieresis",
209 "ntilde",
210 "oacute",
211 "ograve",
212 "ocircumflex",
213 "odieresis",
214 "otilde",
215 "uacute",
216 "ugrave",
217 "ucircumflex",
218 "udieresis",
219 "dagger",
220 "degree",
221 "cent",
222 "sterling",
223 "section",
224 "bullet",
225 "paragraph",
226 "germandbls",
227 "registered",
228 "copyright",
229 "trademark",
230 "acute",
231 "dieresis",
232 "notequal",
233 "AE",
234 "Oslash",
235 "infinity",
236 "plusminus",
237 "lessequal",
238 "greaterequal",
239 "yen",
240 "mu",
241 "partialdiff",
242 "summation",
243 "product",
244 "pi",
245 "integral",
246 "ordfeminine",
247 "ordmasculine",
248 "Omega",
249 "ae",
250 "oslash",
251 "questiondown",
252 "exclamdown",
253 "logicalnot",
254 "radical",
255 "florin",
256 "approxequal",
257 "Delta",
258 "guillemotleft",
259 "guillemotright",
260 "ellipsis",
261 "nonbreakingspace",
262 "Agrave",
263 "Atilde",
264 "Otilde",
265 "OE",
266 "oe",
267 "endash",
268 "emdash",
269 "quotedblleft",
270 "quotedblright",
271 "quoteleft",
272 "quoteright",
273 "divide",
274 "lozenge",
275 "ydieresis",
276 "Ydieresis",
277 "fraction",
278 "currency",
279 "guilsinglleft",
280 "guilsinglright",
281 "fi",
282 "fl",
283 "daggerdbl",
284 "periodcentered",
285 "quotesinglbase",
286 "quotedblbase",
287 "perthousand",
288 "Acircumflex",
289 "Ecircumflex",
290 "Aacute",
291 "Edieresis",
292 "Egrave",
293 "Iacute",
294 "Icircumflex",
295 "Idieresis",
296 "Igrave",
297 "Oacute",
298 "Ocircumflex",
299 "apple",
300 "Ograve",
301 "Uacute",
302 "Ucircumflex",
303 "Ugrave",
304 "dotlessi",
305 "circumflex",
306 "tilde",
307 "macron",
308 "breve",
309 "dotaccent",
310 "ring",
311 "cedilla",
312 "hungarumlaut",
313 "ogonek",
314 "caron",
315 "Lslash",
316 "lslash",
317 "Scaron",
318 "scaron",
319 "Zcaron",
320 "zcaron",
321 "brokenbar",
322 "Eth",
323 "eth",
324 "Yacute",
325 "yacute",
326 "Thorn",
327 "thorn",
328 "minus",
329 "multiply",
330 "onesuperior",
331 "twosuperior",
332 "threesuperior",
333 "onehalf",
334 "onequarter",
335 "threequarters",
336 "franc",
337 "Gbreve",
338 "gbreve",
339 "Idotaccent",
340 "Scedilla",
341 "scedilla",
342 "Cacute",
343 "cacute",
344 "Ccaron",
345 "ccaron",
346 "dcroat"
350 void putshort(FILE *file,int sval) {
351 putc((sval>>8)&0xff,file);
352 putc(sval&0xff,file);
355 void putlong(FILE *file,int val) {
356 putc((val>>24)&0xff,file);
357 putc((val>>16)&0xff,file);
358 putc((val>>8)&0xff,file);
359 putc(val&0xff,file);
361 #define dumpabsoffset putlong
363 static void dumpoffset(FILE *file,int offsize,int val) {
364 if ( offsize==1 )
365 putc(val,file);
366 else if ( offsize==2 )
367 putshort(file,val);
368 else if ( offsize==3 ) {
369 putc((val>>16)&0xff,file);
370 putc((val>>8)&0xff,file);
371 putc(val&0xff,file);
372 } else
373 putlong(file,val);
376 void putfixed(FILE *file,real dval) {
377 int val;
378 int mant;
380 val = floor(dval);
381 mant = floor(65536.*(dval-val));
382 val = (val<<16) | mant;
383 putlong(file,val);
386 int ttfcopyfile(FILE *ttf, FILE *other, int pos, char *tab_name) {
387 int ch;
388 int ret = 1;
390 if ( ferror(ttf) || ferror(other)) {
391 IError("Disk error of some nature. Perhaps no space on device?\nGenerated font will be unusable" );
392 } else if ( pos!=ftell(ttf)) {
393 IError("File Offset wrong for ttf table (%s), %d expected %d", tab_name, ftell(ttf), pos );
395 rewind(other);
396 while (( ch = getc(other))!=EOF )
397 putc(ch,ttf);
398 if ( ferror(other)) ret = 0;
399 if ( fclose(other)) ret = 0;
400 return( ret );
403 static void FigureFullMetricsEnd(SplineFont *sf,struct glyphinfo *gi, int istt ) {
404 /* We can reduce the size of the width array by removing a run at the end */
405 /* of the same width. So start at the end, find the width of the last */
406 /* character we'll output, then run backwards as long as we've got the */
407 /* same width */
408 /* (do same thing for vertical metrics too */
409 int i, lasti, lastv, lastdefault = istt ? 3 : 1;
410 int width, vwidth;
412 lasti = lastv = gi->gcnt-1;
413 for ( i=gi->gcnt-1; i>lastdefault && gi->bygid[i]==-1; --i );
414 if ( i>=lastdefault ) {
415 width = sf->glyphs[gi->bygid[i]]->width;
416 vwidth = sf->glyphs[gi->bygid[i]]->vwidth;
417 lasti = lastv = i;
418 for ( i=lasti-1; i>=lastdefault; --i ) {
419 if ( SCWorthOutputting(sf->glyphs[gi->bygid[i]]) ) {
420 if ( sf->glyphs[gi->bygid[i]]->width!=width )
421 break;
422 else
423 lasti = i;
426 gi->lasthwidth = lasti;
427 if ( sf->hasvmetrics ) {
428 for ( i=lastv-1; i>=lastdefault; --i ) {
429 if ( SCWorthOutputting(sf->glyphs[gi->bygid[i]]) ) {
430 if ( sf->glyphs[gi->bygid[i]]->vwidth!=vwidth )
431 break;
432 else
433 lastv = i;
436 gi->lastvwidth = lastv;
438 } else {
439 gi->lasthwidth = 0;
440 gi->lastvwidth = 0;
445 #define _On_Curve 1
446 #define _X_Short 2
447 #define _Y_Short 4
448 #define _Repeat 8
449 #define _X_Same 0x10
450 #define _Y_Same 0x20
452 int RefDepth(RefChar *ref,int layer) {
453 int rd, temp;
454 SplineChar *sc = ref->sc;
456 if ( sc->layers[layer].refs==NULL || sc->layers[layer].splines!=NULL )
457 return( 1 );
458 rd = 0;
459 for ( ref = sc->layers[layer].refs; ref!=NULL; ref=ref->next ) {
460 if ( ref->transform[0]>=-2 || ref->transform[0]<=1.999939 ||
461 ref->transform[1]>=-2 || ref->transform[1]<=1.999939 ||
462 ref->transform[2]>=-2 || ref->transform[2]<=1.999939 ||
463 ref->transform[3]>=-2 || ref->transform[3]<=1.999939 ) {
464 temp = RefDepth(ref,layer);
465 if ( temp>rd ) rd = temp;
468 return( rd+1 );
471 void SFDummyUpCIDs(struct glyphinfo *gi,SplineFont *sf) {
472 int i,j,k,max;
473 int *bygid;
475 max = 0;
476 for ( k=0; k<sf->subfontcnt; ++k )
477 if ( sf->subfonts[k]->glyphcnt>max ) max = sf->subfonts[k]->glyphcnt;
478 if ( max == 0 )
479 return;
481 sf->glyphs = gcalloc(max,sizeof(SplineChar *));
482 sf->glyphcnt = sf->glyphmax = max;
483 sf->glyphmin = 0;
484 for ( k=0; k<sf->subfontcnt; ++k )
485 for ( i=0; i<sf->subfonts[k]->glyphcnt; ++i ) if ( sf->subfonts[k]->glyphs[i]!=NULL )
486 sf->glyphs[i] = sf->subfonts[k]->glyphs[i];
488 if ( gi==NULL )
489 return;
491 bygid = galloc((sf->glyphcnt+3)*sizeof(int));
492 memset(bygid,0xff, (sf->glyphcnt+3)*sizeof(int));
494 j=1;
495 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
496 if ( bygid[0]== -1 && strcmp(sf->glyphs[i]->name,".notdef")==0 ) {
497 sf->glyphs[i]->ttf_glyph = 0;
498 bygid[0] = i;
499 } else if ( SCWorthOutputting(sf->glyphs[i])) {
500 sf->glyphs[i]->ttf_glyph = j;
501 bygid[j++] = i;
504 gi->bygid = bygid;
505 gi->gcnt = j;
508 static void AssignNotdefNull(SplineFont *sf,int *bygid, int iscff) {
509 int i;
511 /* The first three glyphs are magic, glyph 0 is .notdef */
512 /* glyph 1 is .null and glyph 2 is nonmarking return */
513 /* We may generate them automagically */
515 bygid[0] = bygid[1] = bygid[2] = -1;
516 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
517 if ( bygid[0]== -1 && strcmp(sf->glyphs[i]->name,".notdef")==0 ) {
518 sf->glyphs[i]->ttf_glyph = 0;
519 bygid[0] = i;
520 } else if ( !iscff && bygid[1]== -1 &&
521 (strcmp(sf->glyphs[i]->name,".null")==0 ||
522 strcmp(sf->glyphs[i]->name,"uni0000")==0 ||
523 (i==1 && strcmp(sf->glyphs[1]->name,"glyph1")==0)) ) {
524 sf->glyphs[i]->ttf_glyph = 1;
525 bygid[1] = i;
526 } else if ( !iscff && bygid[2]== -1 &&
527 (strcmp(sf->glyphs[i]->name,"nonmarkingreturn")==0 ||
528 strcmp(sf->glyphs[i]->name,"uni000D")==0 ||
529 (i==2 && strcmp(sf->glyphs[2]->name,"glyph2")==0)) ) {
530 sf->glyphs[i]->ttf_glyph = 2;
531 bygid[2] = i;
536 static int AssignTTFGlyph(struct glyphinfo *gi,SplineFont *sf,EncMap *map,int iscff) {
537 int *bygid = galloc((sf->glyphcnt+3)*sizeof(int));
538 int i,j;
540 memset(bygid,0xff, (sf->glyphcnt+3)*sizeof(int));
542 AssignNotdefNull(sf,bygid,iscff);
544 j = iscff ? 1 : 3;
545 for ( i=0; i<map->enccount; ++i ) if ( map->map[i]!=-1 ) {
546 SplineChar *sc = sf->glyphs[map->map[i]];
547 if ( SCWorthOutputting(sc) && sc->ttf_glyph==-1
548 #if HANYANG
549 && (!iscff || !sc->compositionunit)
550 #endif
552 sc->ttf_glyph = j;
553 bygid[j++] = sc->orig_pos;
557 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
558 SplineChar *sc = sf->glyphs[i];
559 if ( SCWorthOutputting(sc) && sc->ttf_glyph==-1
560 #if HANYANG
561 && (!iscff || !sc->compositionunit)
562 #endif
564 sc->ttf_glyph = j;
565 bygid[j++] = i;
568 gi->bygid = bygid;
569 gi->gcnt = j;
570 return j;
573 /* Standard names for cff */
574 extern const char *cffnames[];
575 extern const int nStdStrings;
577 static int storesid(struct alltabs *at,char *str) {
578 int i;
579 FILE *news;
580 char *pt;
581 long pos;
583 if ( str!=NULL ) { /* NULL is the magic string at end of array */
584 for ( i=0; cffnames[i]!=NULL; ++i ) {
585 if ( strcmp(cffnames[i],str)==0 )
586 return( i );
590 pos = ftell(at->sidf)+1;
591 if ( pos>=65536 && !at->sidlongoffset ) {
592 at->sidlongoffset = true;
593 news = tmpfile();
594 rewind(at->sidh);
595 for ( i=0; i<at->sidcnt; ++i )
596 putlong(news,getushort(at->sidh));
597 fclose(at->sidh);
598 at->sidh = news;
600 if ( at->sidlongoffset )
601 putlong(at->sidh,pos);
602 else
603 putshort(at->sidh,pos);
605 if ( str!=NULL ) {
606 for ( pt=str; *pt; ++pt )
607 putc(*pt,at->sidf);
609 return( at->sidcnt++ + nStdStrings );
612 static void dumpint(FILE *cfff,int num) {
614 if ( num>=-107 && num<=107 )
615 putc(num+139,cfff);
616 else if ( num>=108 && num<=1131 ) {
617 num -= 108;
618 putc((num>>8)+247,cfff);
619 putc(num&0xff,cfff);
620 } else if ( num>=-1131 && num<=-108 ) {
621 num = -num;
622 num -= 108;
623 putc((num>>8)+251,cfff);
624 putc(num&0xff,cfff);
625 } else if ( num>=-32768 && num<32768 ) {
626 putc(28,cfff);
627 putc(num>>8,cfff);
628 putc(num&0xff,cfff);
629 } else { /* In dict data we have 4 byte ints, in type2 strings we don't */
630 putc(29,cfff);
631 putc((num>>24)&0xff,cfff);
632 putc((num>>16)&0xff,cfff);
633 putc((num>>8)&0xff,cfff);
634 putc(num&0xff,cfff);
638 static void dumpdbl(FILE *cfff,double d) {
639 if ( d-rint(d)>-.00001 && d-rint(d)<.00001 )
640 dumpint(cfff,(int) d);
641 else {
642 /* The type2 strings have a fixed format, but the dict data does not */
643 char buffer[20], *pt;
644 int sofar,n,odd;
645 sprintf( buffer, "%g", d);
646 sofar = 0; odd=true;
647 putc(30,cfff); /* Start a double */
648 for ( pt=buffer; *pt; ++pt ) {
649 if ( isdigit(*pt) )
650 n = *pt-'0';
651 else if ( *pt=='.' )
652 n = 0xa;
653 else if ( *pt=='-' )
654 n = 0xe;
655 else if (( *pt=='E' || *pt=='e') && pt[1]=='-' ) {
656 n = 0xc;
657 ++pt;
658 } else if ( *pt=='E' || *pt=='e')
659 n = 0xb;
660 else
661 n = 0; /* Should never happen */
662 if ( odd ) {
663 sofar = n<<4;
664 odd = false;
665 } else {
666 putc(sofar|n,cfff);
667 sofar=0;
668 odd = true;
671 if ( sofar==0 )
672 putc(0xff,cfff);
673 else
674 putc(sofar|0xf,cfff);
678 static void dumpoper(FILE *cfff,int oper ) {
679 if ( oper!=-1 ) {
680 if ( oper>=256 )
681 putc(oper>>8,cfff);
682 putc(oper&0xff,cfff);
686 static void dumpdbloper(FILE *cfff,double d, int oper ) {
687 dumpdbl(cfff,d);
688 dumpoper(cfff,oper);
691 static void dumpintoper(FILE *cfff,int v, int oper ) {
692 dumpint(cfff,v);
693 dumpoper(cfff,oper);
696 static void dumpsizedint(FILE *cfff,int big,int num, int oper ) {
697 if ( big ) {
698 putc(29,cfff);
699 putc((num>>24)&0xff,cfff);
700 putc((num>>16)&0xff,cfff);
701 putc((num>>8)&0xff,cfff);
702 putc(num&0xff,cfff);
703 } else {
704 putc(28,cfff);
705 putc(num>>8,cfff);
706 putc(num&0xff,cfff);
708 dumpoper(cfff,oper);
711 static void dumpsid(FILE *cfff,struct alltabs *at,char *str,int oper) {
712 if ( str==NULL )
713 return;
714 dumpint(cfff,storesid(at,str));
715 dumpoper(cfff,oper);
718 static void DumpStrDouble(char *pt,FILE *cfff,int oper) {
719 real d;
720 if ( *pt=='[' ) ++pt; /* For StdHW, StdVW */
721 d = strtod(pt,NULL);
722 dumpdbloper(cfff,d,oper);
725 static void DumpDblArray(real *arr,int n,FILE *cfff, int oper) {
726 int mi,i;
728 for ( mi=n-1; mi>=0 && arr[mi]==0; --mi );
729 if ( mi<0 )
730 return;
731 dumpdbl(cfff,arr[0]);
732 for ( i=1; i<=mi; ++i )
733 dumpdbl(cfff,arr[i]-arr[i-1]);
734 dumpoper(cfff,oper);
737 static void DumpStrArray(char *pt,FILE *cfff,int oper) {
738 real d, last=0;
739 char *end;
741 while ( *pt==' ' ) ++pt;
742 if ( *pt=='\0' )
743 return;
744 if ( *pt=='[' ) ++pt;
745 while ( *pt==' ' ) ++pt;
746 while ( *pt!=']' && *pt!='\0' ) {
747 d = strtod(pt,&end);
748 if ( pt==end ) /* User screwed up. Should be a number */
749 break;
750 dumpdbl(cfff,d-last);
751 last = d;
752 pt = end;
753 while ( *pt==' ' ) ++pt;
755 dumpoper(cfff,oper);
758 static void dumpcffheader(SplineFont *sf,FILE *cfff) {
759 putc('\1',cfff); /* Major version: 1 */
760 putc('\0',cfff); /* Minor version: 0 */
761 putc('\4',cfff); /* Header size in bytes */
762 putc('\4',cfff); /* Absolute Offset size. */
763 /* I don't think there are any absolute offsets that aren't encoded */
764 /* in a dict as numbers (ie. inherently variable sized items) */
767 static void dumpcffnames(SplineFont *sf,FILE *cfff) {
768 char *pt;
770 putshort(cfff,1); /* One font name */
771 putc('\1',cfff); /* Offset size */
772 putc('\1',cfff); /* Offset to first name */
773 putc('\1'+strlen(sf->fontname),cfff);
774 for ( pt=sf->fontname; *pt; ++pt )
775 putc(*pt,cfff);
778 static void dumpcffcharset(SplineFont *sf,struct alltabs *at) {
779 int i;
781 at->gn_sid = gcalloc(at->gi.gcnt,sizeof(uint32));
782 putc(0,at->charset);
783 /* I always use a format 0 charset. ie. an array of SIDs in random order */
785 /* First element must be ".notdef" and is omitted */
787 for ( i=1; i<at->gi.gcnt; ++i )
788 if ( at->gi.bygid[i]!=-1 && SCWorthOutputting(sf->glyphs[at->gi.bygid[i]])) {
789 at->gn_sid[i] = storesid(at,sf->glyphs[at->gi.bygid[i]]->name);
790 putshort(at->charset,at->gn_sid[i]);
794 static void dumpcffcidset(SplineFont *sf,struct alltabs *at) {
795 int gid, start;
797 putc(2,at->charset);
799 start = -1; /* Glyph 0 always maps to CID 0, and is omitted */
800 for ( gid = 1; gid<at->gi.gcnt; ++gid ) {
801 if ( start==-1 )
802 start = gid;
803 else if ( at->gi.bygid[gid]-at->gi.bygid[start]!=gid-start ) {
804 putshort(at->charset,at->gi.bygid[start]);
805 putshort(at->charset,at->gi.bygid[gid-1]-at->gi.bygid[start]);
806 start = gid;
809 if ( start!=-1 ) {
810 putshort(at->charset,at->gi.bygid[start]);
811 putshort(at->charset,at->gi.bygid[gid-1]-at->gi.bygid[start]);
815 static void dumpcfffdselect(SplineFont *sf,struct alltabs *at) {
816 int cid, k, lastfd, cnt;
817 int gid;
819 putc(3,at->fdselect);
820 putshort(at->fdselect,0); /* number of ranges, fill in later */
822 for ( k=0; k<sf->subfontcnt; ++k )
823 if ( SCWorthOutputting(sf->subfonts[k]->glyphs[0]))
824 break;
825 if ( k==sf->subfontcnt ) --k; /* If CID 0 not defined, put it in last font */
826 putshort(at->fdselect,0);
827 putc(k,at->fdselect);
828 lastfd = k;
829 cnt = 1;
830 for ( gid = 1; gid<at->gi.gcnt; ++gid ) {
831 cid = at->gi.bygid[gid];
832 for ( k=0; k<sf->subfontcnt; ++k ) {
833 if ( cid<sf->subfonts[k]->glyphcnt &&
834 SCWorthOutputting(sf->subfonts[k]->glyphs[cid]) )
835 break;
837 if ( k==sf->subfontcnt )
838 /* Doesn't map to a glyph, irrelevant */;
839 else {
840 if ( k!=lastfd ) {
841 putshort(at->fdselect,gid);
842 putc(k,at->fdselect);
843 lastfd = k;
844 ++cnt;
848 putshort(at->fdselect,gid);
849 fseek(at->fdselect,1,SEEK_SET);
850 putshort(at->fdselect,cnt);
851 fseek(at->fdselect,0,SEEK_END);
854 static void dumpcffencoding(SplineFont *sf,struct alltabs *at) {
855 int i, cnt, anydups;
856 uint32 start_pos = ftell(at->encoding);
857 SplineChar *sc;
858 EncMap *map = at->map;
860 putc(0,at->encoding);
861 /* I always use a format 0 encoding. ie. an array of glyph indexes */
862 putc(0xff,at->encoding); /* fixup later */
864 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
865 sf->glyphs[i]->ticked = false;
867 cnt = 0;
868 anydups = 0;
869 for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && (sc=sf->glyphs[map->map[i]])!=NULL ) {
870 if ( sc->ttf_glyph>255 )
871 continue;
872 if ( sc->ticked ) {
873 ++anydups;
874 } else if ( sc->ttf_glyph>0 ) {
875 if ( cnt>=255 )
876 break;
877 putc(i,at->encoding);
878 ++cnt;
879 sc->ticked = true;
882 if ( anydups ) {
883 fseek(at->encoding,start_pos,SEEK_SET);
884 putc(0x80,at->encoding);
885 putc(cnt,at->encoding);
886 fseek(at->encoding,0,SEEK_END);
887 putc(anydups,at->encoding);
889 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
890 sf->glyphs[i]->ticked = false;
891 for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && (sc=sf->glyphs[map->map[i]])!=NULL ) {
892 if ( sc->ttf_glyph>255 )
893 continue;
894 if ( sc->ticked ) {
895 putc(i,at->encoding);
896 putshort(at->encoding,at->gn_sid[sc->ttf_glyph]);
898 sc->ticked = true;
900 } else {
901 fseek(at->encoding,start_pos+1,SEEK_SET);
902 putc(cnt,at->encoding);
903 fseek(at->encoding,0,SEEK_END);
905 free( at->gn_sid );
906 at->gn_sid = NULL;
909 static void _dumpcffstrings(FILE *file, struct pschars *strs) {
910 int i, len, offsize;
912 /* First figure out the offset size */
913 len = 1;
914 for ( i=0; i<strs->next; ++i )
915 len += strs->lens[i];
917 /* Then output the index size and offsets */
918 putshort( file, strs->next );
919 if ( strs->next!=0 ) {
920 /* presumably offsets are unsigned. But the docs don't state this in the obvious place */
921 offsize = len<=255?1:len<=65535?2:len<=0xffffff?3:4;
922 putc(offsize,file);
923 len = 1;
924 for ( i=0; i<strs->next; ++i ) {
925 dumpoffset(file,offsize,len);
926 len += strs->lens[i];
928 dumpoffset(file,offsize,len);
930 /* last of all the strings */
931 for ( i=0; i<strs->next; ++i ) {
932 uint8 *pt = strs->values[i], *end = pt+strs->lens[i];
933 while ( pt<end )
934 putc( *pt++, file );
939 static FILE *dumpcffstrings(struct pschars *strs) {
940 FILE *file = tmpfile();
941 _dumpcffstrings(file,strs);
942 PSCharsFree(strs);
943 return( file );
946 int SFFigureDefWidth(SplineFont *sf, int *_nomwid) {
947 uint16 *widths; uint32 *cumwid;
948 int nomwid, defwid, i, sameval=(int) 0x80000000, maxw=0, allsame=true;
949 int cnt,j;
951 for ( i=0; i<sf->glyphcnt; ++i )
952 if ( SCWorthOutputting(sf->glyphs[i]) ) {
953 if ( maxw<sf->glyphs[i]->width ) maxw = sf->glyphs[i]->width;
954 if ( sameval == 0x8000000 )
955 sameval = sf->glyphs[i]->width;
956 else if ( sameval!=sf->glyphs[i]->width )
957 allsame = false;
959 if ( allsame ) {
960 nomwid = defwid = sameval;
961 } else {
962 ++maxw;
963 if ( maxw>65535 ) maxw = 3*(sf->ascent+sf->descent);
964 widths = gcalloc(maxw,sizeof(uint16));
965 cumwid = gcalloc(maxw,sizeof(uint32));
966 defwid = 0; cnt=0;
967 for ( i=0; i<sf->glyphcnt; ++i )
968 if ( SCWorthOutputting(sf->glyphs[i]) &&
969 sf->glyphs[i]->width>=0 &&
970 sf->glyphs[i]->width<maxw )
971 if ( ++widths[sf->glyphs[i]->width] > cnt ) {
972 defwid = sf->glyphs[i]->width;
973 cnt = widths[defwid];
975 widths[defwid] = 0;
976 for ( i=0; i<maxw; ++i )
977 for ( j=-107; j<=107; ++j )
978 if ( i+j>=0 && i+j<maxw )
979 cumwid[i] += widths[i+j];
980 cnt = 0; nomwid = 0;
981 for ( i=0; i<maxw; ++i )
982 if ( cnt<cumwid[i] ) {
983 cnt = cumwid[i];
984 nomwid = i;
986 free(widths); free(cumwid);
988 if ( _nomwid!=NULL )
989 *_nomwid = nomwid;
990 return( defwid );
993 static void ATFigureDefWidth(SplineFont *sf, struct alltabs *at, int subfont) {
994 int nomwid, defwid;
996 defwid = SFFigureDefWidth(sf,&nomwid);
997 if ( subfont==-1 )
998 at->defwid = defwid;
999 else
1000 at->fds[subfont].defwid = defwid;
1001 if ( subfont==-1 )
1002 at->nomwid = nomwid;
1003 else
1004 at->fds[subfont].nomwid = nomwid;
1007 static void dumpcffprivate(SplineFont *sf,struct alltabs *at,int subfont,
1008 int subrcnt) {
1009 char *pt;
1010 FILE *private = subfont==-1?at->private:at->fds[subfont].private;
1011 int mi,i;
1012 real bluevalues[14], otherblues[10];
1013 real snapcnt[12];
1014 real stemsnaph[12], stemsnapv[12];
1015 real stdhw[1], stdvw[1];
1016 int hasblue=0, hash=0, hasv=0, bs;
1017 int nomwid, defwid;
1018 EncMap *map = at->map;
1019 double bluescale;
1021 /* The private dict is not in an index, so no index header. Just the data */
1023 if ( subfont==-1 )
1024 defwid = at->defwid;
1025 else
1026 defwid = at->fds[subfont].defwid;
1027 dumpintoper(private,defwid,20); /* Default Width */
1028 if ( subfont==-1 )
1029 nomwid = at->nomwid;
1030 else
1031 nomwid = at->fds[subfont].nomwid;
1032 dumpintoper(private,nomwid,21); /* Nominative Width */
1034 bs = SplineFontIsFlexible(sf,at->gi.layer,at->gi.flags);
1035 hasblue = PSDictHasEntry(sf->private,"BlueValues")!=NULL;
1036 hash = PSDictHasEntry(sf->private,"StdHW")!=NULL;
1037 hasv = PSDictHasEntry(sf->private,"StdVW")!=NULL;
1038 ff_progress_change_stages(2+autohint_before_generate+!hasblue);
1040 otherblues[0] = otherblues[1] = bluevalues[0] = bluevalues[1] = 0;
1041 if ( !hasblue ) {
1042 FindBlues(sf,at->gi.layer,bluevalues,otherblues);
1043 ff_progress_next_stage();
1046 stdhw[0] = stdvw[0] = 0;
1047 if ( !hash ) {
1048 FindHStems(sf,stemsnaph,snapcnt);
1049 mi = -1;
1050 for ( i=0; stemsnaph[i]!=0 && i<12; ++i )
1051 if ( mi==-1 ) mi = i;
1052 else if ( snapcnt[i]>snapcnt[mi] ) mi = i;
1053 if ( mi!=-1 ) stdhw[0] = stemsnaph[mi];
1056 if ( !hasv ) {
1057 FindVStems(sf,stemsnapv,snapcnt);
1058 mi = -1;
1059 for ( i=0; stemsnapv[i]!=0 && i<12; ++i )
1060 if ( mi==-1 ) mi = i;
1061 else if ( snapcnt[i]>snapcnt[mi] ) mi = i;
1062 if ( mi!=-1 ) stdvw[0] = stemsnapv[mi];
1064 ff_progress_change_line1(_("Saving OpenType Font"));
1066 if ( hasblue )
1067 DumpStrArray(PSDictHasEntry(sf->private,"BlueValues"),private,6);
1068 else
1069 DumpDblArray(bluevalues,sizeof(bluevalues)/sizeof(bluevalues[0]),private,6);
1070 if ( (pt=PSDictHasEntry(sf->private,"OtherBlues"))!=NULL )
1071 DumpStrArray(pt,private,7);
1072 else if ( !hasblue )
1073 DumpDblArray(otherblues,sizeof(otherblues)/sizeof(otherblues[0]),private,7);
1074 if ( (pt=PSDictHasEntry(sf->private,"FamilyBlues"))!=NULL )
1075 DumpStrArray(pt,private,8);
1076 bluescale = BlueScaleFigure(sf->private,bluevalues,otherblues);
1077 if ( (pt=PSDictHasEntry(sf->private,"FamilyOtherBlues"))!=NULL )
1078 DumpStrArray(pt,private,9);
1079 if ( (pt=PSDictHasEntry(sf->private,"BlueScale"))!=NULL )
1080 DumpStrDouble(pt,private,(12<<8)+9);
1081 else if ( bluescale!=-1 )
1082 dumpdbloper(private,bluescale,(12<<8)+9);
1083 if ( (pt=PSDictHasEntry(sf->private,"BlueShift"))!=NULL )
1084 DumpStrDouble(pt,private,(12<<8)+10);
1085 else
1086 dumpintoper(private,bs,(12<<8)+10);
1087 if ( (pt=PSDictHasEntry(sf->private,"BlueFuzz"))!=NULL )
1088 DumpStrDouble(pt,private,(12<<8)+11);
1089 if ( hash ) {
1090 DumpStrDouble(PSDictHasEntry(sf->private,"StdHW"),private,10);
1091 if ( (pt=PSDictHasEntry(sf->private,"StemSnapH"))!=NULL )
1092 DumpStrArray(pt,private,(12<<8)|12);
1093 } else {
1094 if ( stdhw[0]!=0 )
1095 dumpdbloper(private,stdhw[0],10);
1096 DumpDblArray(stemsnaph,sizeof(stemsnaph)/sizeof(stemsnaph[0]),private,(12<<8)|12);
1098 if ( hasv ) {
1099 DumpStrDouble(PSDictHasEntry(sf->private,"StdVW"),private,11);
1100 if ( (pt=PSDictHasEntry(sf->private,"StemSnapV"))!=NULL )
1101 DumpStrArray(pt,private,(12<<8)|13);
1102 } else {
1103 if ( stdvw[0]!=0 )
1104 dumpdbloper(private,stdvw[0],11);
1105 DumpDblArray(stemsnapv,sizeof(stemsnapv)/sizeof(stemsnapv[0]),private,(12<<8)|13);
1107 if ( (pt=PSDictHasEntry(sf->private,"ForceBold"))!=NULL ) {
1108 dumpintoper(private,*pt=='t'||*pt=='T',(12<<8)|14);
1109 } else if ( sf->weight!=NULL &&
1110 (strstrmatch(sf->weight,"Bold")!=NULL ||
1111 strstrmatch(sf->weight,"Demi")!=NULL ||
1112 strstrmatch(sf->weight,"Fett")!=NULL ||
1113 strstrmatch(sf->weight,"Gras")!=NULL ||
1114 strstrmatch(sf->weight,"Heavy")!=NULL ||
1115 strstrmatch(sf->weight,"Black")!=NULL))
1116 dumpintoper(private,1,(12<<8)|14);
1117 if ( (pt=PSDictHasEntry(sf->private,"LanguageGroup"))!=NULL )
1118 DumpStrDouble(pt,private,(12<<8)+17);
1119 else if ( map->enc->is_japanese ||
1120 map->enc->is_korean ||
1121 map->enc->is_tradchinese ||
1122 map->enc->is_simplechinese )
1123 dumpintoper(private,1,(12<<8)|17);
1124 if ( (pt=PSDictHasEntry(sf->private,"ExpansionFactor"))!=NULL )
1125 DumpStrDouble(pt,private,(12<<8)+18);
1126 if ( subrcnt!=0 )
1127 dumpsizedint(private,false,ftell(private)+3+1,19); /* Subrs */
1129 if ( subfont==-1 )
1130 at->privatelen = ftell(private);
1131 else
1132 at->fds[subfont].privatelen = ftell(private);
1135 /* When we exit this the topdict is not complete, we still need to fill in */
1136 /* values for charset,encoding,charstrings and private. Then we need to go */
1137 /* back and fill in the table length (at lenpos) */
1138 static void dumpcfftopdict(SplineFont *sf,struct alltabs *at) {
1139 char *pt, *end;
1140 FILE *cfff = at->cfff;
1141 DBounds b;
1143 putshort(cfff,1); /* One top dict */
1144 putc('\2',cfff); /* Offset size */
1145 putshort(cfff,1); /* Offset to topdict */
1146 at->lenpos = ftell(cfff);
1147 putshort(cfff,0); /* placeholder for final position (final offset in index points beyond last element) */
1148 dumpsid(cfff,at,sf->version,0);
1149 dumpsid(cfff,at,sf->copyright,1);
1150 dumpsid(cfff,at,sf->fullname?sf->fullname:sf->fontname,2);
1151 dumpsid(cfff,at,sf->familyname,3);
1152 dumpsid(cfff,at,sf->weight,4);
1153 if ( at->gi.fixed_width!=-1 ) dumpintoper(cfff,1,(12<<8)|1);
1154 if ( sf->italicangle!=0 ) dumpdbloper(cfff,sf->italicangle,(12<<8)|2);
1155 if ( sf->upos!=-100 ) dumpdbloper(cfff,sf->upos,(12<<8)|3);
1156 if ( sf->uwidth!=50 ) dumpdbloper(cfff,sf->uwidth,(12<<8)|4);
1157 if ( sf->strokedfont ) {
1158 dumpintoper(cfff,2,(12<<8)|5);
1159 dumpdbloper(cfff,sf->strokewidth,(12<<8)|8);
1161 /* We'll never set CharstringType */
1162 if ( sf->ascent+sf->descent!=1000 ) {
1163 dumpdbl(cfff,1.0/(sf->ascent+sf->descent));
1164 dumpint(cfff,0);
1165 dumpint(cfff,0);
1166 dumpdbl(cfff,1.0/(sf->ascent+sf->descent));
1167 dumpint(cfff,0);
1168 dumpintoper(cfff,0,(12<<8)|7);
1170 if ( sf->uniqueid!=-1 && sf->use_uniqueid )
1171 dumpintoper(cfff, sf->uniqueid?sf->uniqueid:4000000 + (rand()&0x3ffff), 13 );
1172 SplineFontLayerFindBounds(sf,at->gi.layer,&b);
1173 at->gi.xmin = b.minx;
1174 at->gi.ymin = b.miny;
1175 at->gi.xmax = b.maxx;
1176 at->gi.ymax = b.maxy;
1177 dumpdbl(cfff,floor(b.minx));
1178 dumpdbl(cfff,floor(b.miny));
1179 dumpdbl(cfff,ceil(b.maxx));
1180 dumpdbloper(cfff,ceil(b.maxy),5);
1181 /* We'll never set StrokeWidth */
1182 if ( sf->xuid!=NULL && sf->use_xuid ) {
1183 pt = sf->xuid; if ( *pt=='[' ) ++pt;
1184 while ( *pt && *pt!=']' ) {
1185 dumpint(cfff,strtol(pt,&end,10));
1186 if ( pt==end ) /* garbage in XUID */
1187 break;
1188 for ( pt = end; *pt==' '; ++pt );
1190 putc(14,cfff);
1191 if ( sf->changed_since_xuidchanged )
1192 SFIncrementXUID(sf);
1194 /* Offset to charset (oper=15) needed here */
1195 /* Offset to encoding (oper=16) needed here (not for CID )*/
1196 /* Offset to charstrings (oper=17) needed here */
1197 /* Length of, and Offset to private (oper=18) needed here (not for CID )*/
1200 static int dumpcffdict(SplineFont *sf,struct alltabs *at) {
1201 FILE *fdarray = at->fdarray;
1202 int pstart;
1203 /* according to the PSRef Man v3, only fontname, fontmatrix and private */
1204 /* appear in this dictionary */
1206 dumpsid(fdarray,at,sf->fontname,(12<<8)|38);
1207 if ( sf->ascent+sf->descent!=1000 ) {
1208 dumpdbl(fdarray,1.0/(sf->ascent+sf->descent));
1209 dumpint(fdarray,0);
1210 dumpint(fdarray,0);
1211 dumpdbl(fdarray,1.0/(sf->ascent+sf->descent));
1212 dumpint(fdarray,0);
1213 dumpintoper(fdarray,0,(12<<8)|7);
1215 pstart = ftell(fdarray);
1216 dumpsizedint(fdarray,false,0,-1); /* private length */
1217 dumpsizedint(fdarray,true,0,18); /* private offset */
1218 return( pstart );
1221 static void dumpcffdictindex(SplineFont *sf,struct alltabs *at) {
1222 int i;
1223 int pos;
1225 putshort(at->fdarray,sf->subfontcnt);
1226 putc('\2',at->fdarray); /* DICTs aren't very big, and there are at most 255 */
1227 putshort(at->fdarray,1); /* Offset to first dict */
1228 for ( i=0; i<sf->subfontcnt; ++i )
1229 putshort(at->fdarray,0); /* Dump offset placeholders (note there's one extra to mark the end) */
1230 pos = ftell(at->fdarray)-1;
1231 for ( i=0; i<sf->subfontcnt; ++i ) {
1232 at->fds[i].fillindictmark = dumpcffdict(sf->subfonts[i],at);
1233 at->fds[i].eodictmark = ftell(at->fdarray);
1234 if ( at->fds[i].eodictmark>65536 )
1235 IError("The DICT INDEX got too big, result won't work");
1237 fseek(at->fdarray,2*sizeof(short)+sizeof(char),SEEK_SET);
1238 for ( i=0; i<sf->subfontcnt; ++i )
1239 putshort(at->fdarray,at->fds[i].eodictmark-pos);
1240 fseek(at->fdarray,0,SEEK_END);
1243 static void dumpcffcidtopdict(SplineFont *sf,struct alltabs *at) {
1244 char *pt, *end;
1245 FILE *cfff = at->cfff;
1246 DBounds b;
1247 int cidcnt=0, k;
1249 for ( k=0; k<sf->subfontcnt; ++k )
1250 if ( sf->subfonts[k]->glyphcnt>cidcnt ) cidcnt = sf->subfonts[k]->glyphcnt;
1252 putshort(cfff,1); /* One top dict */
1253 putc('\2',cfff); /* Offset size */
1254 putshort(cfff,1); /* Offset to topdict */
1255 at->lenpos = ftell(cfff);
1256 putshort(cfff,0); /* placeholder for final position */
1257 dumpsid(cfff,at,sf->cidregistry,-1);
1258 dumpsid(cfff,at,sf->ordering,-1);
1259 dumpintoper(cfff,sf->supplement,(12<<8)|30); /* ROS operator must be first */
1260 dumpdbloper(cfff,sf->cidversion,(12<<8)|31);
1261 dumpintoper(cfff,cidcnt,(12<<8)|34);
1262 if ( sf->use_uniqueid )
1263 dumpintoper(cfff, sf->uniqueid?sf->uniqueid:4000000 + (rand()&0x3ffff), (12<<8)|35 );
1265 dumpsid(cfff,at,sf->copyright,1);
1266 dumpsid(cfff,at,sf->fullname?sf->fullname:sf->fontname,2);
1267 dumpsid(cfff,at,sf->familyname,3);
1268 dumpsid(cfff,at,sf->weight,4);
1269 /* FontMatrix (identity here, real ones in sub fonts)*/
1270 /* Actually there is no fontmatrix in the adobe cid font I'm looking at */
1271 /* which means it should default to [.001...] but it doesn't so the */
1272 /* docs aren't completely accurate */
1273 /* I now see I've no idea what the FontMatrix means in a CID keyed font */
1274 /* it seems to be ignored everywhere */
1275 #if 0
1276 dumpdbl(cfff,1.0);
1277 dumpint(cfff,0);
1278 dumpint(cfff,0);
1279 dumpdbl(cfff,1.0);
1280 dumpint(cfff,0);
1281 dumpintoper(cfff,0,(12<<8)|7);
1282 #endif
1284 CIDLayerFindBounds(sf,at->gi.layer,&b);
1285 at->gi.xmin = b.minx;
1286 at->gi.ymin = b.miny;
1287 at->gi.xmax = b.maxx;
1288 at->gi.ymax = b.maxy;
1289 dumpdbl(cfff,floor(b.minx));
1290 dumpdbl(cfff,floor(b.miny));
1291 dumpdbl(cfff,ceil(b.maxx));
1292 dumpdbloper(cfff,ceil(b.maxy),5);
1293 /* We'll never set StrokeWidth */
1294 if ( sf->xuid!=NULL && sf->use_xuid ) {
1295 pt = sf->xuid; if ( *pt=='[' ) ++pt;
1296 while ( *pt && *pt!=']' ) {
1297 dumpint(cfff,strtol(pt,&end,10));
1298 for ( pt = end; *pt==' '; ++pt );
1300 putc(14,cfff);
1301 if ( sf->changed_since_xuidchanged )
1302 SFIncrementXUID(sf);
1304 #if 0
1305 /* Acrobat doesn't seem to care about a private dict here. Ghostscript */
1306 /* dies. Tech Note: 5176.CFF.PDF, top of page 23 says: */
1307 /* A Private DICT is required, but may be specified as having */
1308 /* a length of 0 if there are no non-default values to be stored*/
1309 /* No indication >where< it is required. I assumed everywhere. Perhaps */
1310 /* just in basefonts? */
1311 dumpint(cfff,0); /* Docs say a private dict is required and they don't specifically omit CID top dicts */
1312 dumpintoper(cfff,0,18); /* But they do say it can be zero */
1313 #endif
1314 /* Offset to charset (oper=15) needed here */
1315 /* Offset to charstrings (oper=17) needed here */
1316 /* Offset to FDArray (oper=12,36) needed here */
1317 /* Offset to FDSelect (oper=12,37) needed here */
1320 static int isStdEncoding(SplineFont *sf,EncMap *map) {
1321 int i;
1323 for ( i=0; i<256 && i<map->enccount; ++i ) if ( map->map[i]!=-1 && sf->glyphs[map->map[i]]!=NULL )
1324 if ( sf->glyphs[map->map[i]]->unicodeenc!=-1 )
1325 if ( sf->glyphs[map->map[i]]->unicodeenc!=unicode_from_adobestd[i] )
1326 return( 0 );
1328 return( 1 );
1331 static void finishup(SplineFont *sf,struct alltabs *at) {
1332 int strlen, shlen, glen,enclen,csetlen,cstrlen,prvlen;
1333 int base, eotop, strhead;
1334 int output_enc = ( at->format==ff_cff && !isStdEncoding(sf,at->map));
1336 storesid(at,NULL); /* end the strings index */
1337 strlen = ftell(at->sidf) + (shlen = ftell(at->sidh));
1338 glen = sizeof(short); /* Single entry: 0, no globals */
1339 enclen = ftell(at->encoding);
1340 csetlen = ftell(at->charset);
1341 cstrlen = ftell(at->charstrings);
1342 prvlen = ftell(at->private);
1343 base = ftell(at->cfff);
1344 if ( base+6*3+strlen+glen+enclen+csetlen+cstrlen+prvlen > 32767 ) {
1345 at->cfflongoffset = true;
1346 base += 5*5+4;
1347 } else
1348 base += 5*3+4;
1349 strhead = 2+(at->sidcnt>1);
1350 base += strhead;
1352 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen,15); /* Charset */
1353 if ( output_enc ) /* encoding offset */
1354 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen,16); /* encoding offset */
1355 else {
1356 dumpsizedint(at->cfff,at->cfflongoffset,0,16);
1357 enclen = 0;
1359 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+enclen,17);/* charstrings */
1360 dumpsizedint(at->cfff,at->cfflongoffset,at->privatelen,-1);
1361 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+enclen+cstrlen,18); /* private size */
1362 eotop = base-strhead-at->lenpos-1;
1363 if ( at->cfflongoffset ) {
1364 fseek(at->cfff,3,SEEK_SET);
1365 putc(4,at->cfff);
1367 fseek(at->cfff,at->lenpos,SEEK_SET);
1368 putshort(at->cfff,eotop);
1369 fseek(at->cfff,0,SEEK_END);
1371 /* String Index */
1372 putshort(at->cfff,at->sidcnt-1);
1373 if ( at->sidcnt!=1 ) { /* Everybody gets an added NULL */
1374 putc(at->sidlongoffset?4:2,at->cfff);
1375 if ( !ttfcopyfile(at->cfff,at->sidh,base,"CFF-StringBase")) at->error = true;
1376 if ( !ttfcopyfile(at->cfff,at->sidf,base+shlen,"CFF-StringData")) at->error = true;
1379 /* Global Subrs */
1380 putshort(at->cfff,0);
1382 /* Charset */
1383 if ( !ttfcopyfile(at->cfff,at->charset,base+strlen+glen,"CFF-Charset")) at->error = true;
1385 /* Encoding */
1386 if ( !ttfcopyfile(at->cfff,at->encoding,base+strlen+glen+csetlen,"CFF-Encoding")) at->error = true;
1388 /* Char Strings */
1389 if ( !ttfcopyfile(at->cfff,at->charstrings,base+strlen+glen+csetlen+enclen,"CFF-CharStrings")) at->error = true;
1391 /* Private & Subrs */
1392 if ( !ttfcopyfile(at->cfff,at->private,base+strlen+glen+csetlen+enclen+cstrlen,"CFF-Private")) at->error = true;
1395 static void finishupcid(SplineFont *sf,struct alltabs *at) {
1396 int strlen, shlen, glen,csetlen,cstrlen,fdsellen,fdarrlen,prvlen;
1397 int base, eotop, strhead;
1398 int i;
1400 storesid(at,NULL); /* end the strings index */
1401 strlen = ftell(at->sidf) + (shlen = ftell(at->sidh));
1402 glen = ftell(at->globalsubrs);
1403 /* No encodings */
1404 csetlen = ftell(at->charset);
1405 fdsellen = ftell(at->fdselect);
1406 cstrlen = ftell(at->charstrings);
1407 fdarrlen = ftell(at->fdarray);
1408 base = ftell(at->cfff);
1410 at->cfflongoffset = true;
1411 base += 5*4+4+2; /* two of the opers below are two byte opers */
1412 strhead = 2+(at->sidcnt>1);
1413 base += strhead;
1415 prvlen = 0;
1416 for ( i=0; i<sf->subfontcnt; ++i ) {
1417 fseek(at->fdarray,at->fds[i].fillindictmark,SEEK_SET);
1418 dumpsizedint(at->fdarray,false,at->fds[i].privatelen,-1); /* Private len */
1419 dumpsizedint(at->fdarray,true,base+strlen+glen+csetlen+fdsellen+cstrlen+fdarrlen+prvlen,18); /* Private offset */
1420 prvlen += ftell(at->fds[i].private); /* private & subrs */
1423 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen,15); /* charset */
1424 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen,(12<<8)|37); /* fdselect */
1425 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+fdsellen,17); /* charstrings */
1426 dumpsizedint(at->cfff,at->cfflongoffset,base+strlen+glen+csetlen+fdsellen+cstrlen,(12<<8)|36); /* fdarray */
1427 eotop = base-strhead-at->lenpos-1;
1428 fseek(at->cfff,at->lenpos,SEEK_SET);
1429 putshort(at->cfff,eotop);
1430 fseek(at->cfff,0,SEEK_END);
1432 /* String Index */
1433 putshort(at->cfff,at->sidcnt-1);
1434 if ( at->sidcnt!=1 ) { /* Everybody gets an added NULL */
1435 putc(at->sidlongoffset?4:2,at->cfff);
1436 if ( !ttfcopyfile(at->cfff,at->sidh,base,"CFF-StringBase")) at->error = true;
1437 if ( !ttfcopyfile(at->cfff,at->sidf,base+shlen,"CFF-StringData")) at->error = true;
1440 /* Global Subrs */
1441 if ( !ttfcopyfile(at->cfff,at->globalsubrs,base+strlen,"CFF-GlobalSubrs")) at->error = true;
1443 /* Charset */
1444 if ( !ttfcopyfile(at->cfff,at->charset,base+strlen+glen,"CFF-Charset")) at->error = true;
1446 /* FDSelect */
1447 if ( !ttfcopyfile(at->cfff,at->fdselect,base+strlen+glen+csetlen,"CFF-FDSelect")) at->error = true;
1449 /* Char Strings */
1450 if ( !ttfcopyfile(at->cfff,at->charstrings,base+strlen+glen+csetlen+fdsellen,"CFF-CharStrings")) at->error = true;
1452 /* FDArray (DICT Index) */
1453 if ( !ttfcopyfile(at->cfff,at->fdarray,base+strlen+glen+csetlen+fdsellen+cstrlen,"CFF-FDArray")) at->error = true;
1455 /* Private & Subrs */
1456 prvlen = 0;
1457 for ( i=0; i<sf->subfontcnt; ++i ) {
1458 int temp = ftell(at->fds[i].private);
1459 if ( !ttfcopyfile(at->cfff,at->fds[i].private,
1460 base+strlen+glen+csetlen+fdsellen+cstrlen+fdarrlen+prvlen,"CFF-PrivateSubrs")) at->error = true;
1461 prvlen += temp;
1464 free(at->fds);
1467 static int dumpcffhmtx(struct alltabs *at,SplineFont *sf,int bitmaps) {
1468 DBounds b;
1469 SplineChar *sc;
1470 int i,cnt;
1471 int dovmetrics = sf->hasvmetrics;
1472 int width = at->gi.fixed_width;
1474 at->gi.hmtx = tmpfile();
1475 if ( dovmetrics )
1476 at->gi.vmtx = tmpfile();
1477 FigureFullMetricsEnd(sf,&at->gi,bitmaps); /* Bitmap fonts use ttf convention of 3 magic glyphs */
1478 if ( at->gi.bygid[0]!=-1 && (sf->glyphs[at->gi.bygid[0]]->width==width || width==-1 )) {
1479 putshort(at->gi.hmtx,sf->glyphs[at->gi.bygid[0]]->width);
1480 SplineCharLayerFindBounds(sf->glyphs[at->gi.bygid[0]],at->gi.layer,&b);
1481 putshort(at->gi.hmtx,b.minx);
1482 if ( dovmetrics ) {
1483 putshort(at->gi.vmtx,sf->glyphs[at->gi.bygid[0]]->vwidth);
1484 putshort(at->gi.vmtx,/*sf->vertical_origin-*/b.miny);
1486 } else {
1487 putshort(at->gi.hmtx,width==-1?(sf->ascent+sf->descent)/2:width);
1488 putshort(at->gi.hmtx,0);
1489 if ( dovmetrics ) {
1490 putshort(at->gi.vmtx,sf->ascent+sf->descent);
1491 putshort(at->gi.vmtx,0);
1494 cnt = 1;
1495 if ( bitmaps ) {
1496 if ( width==-1 ) width = (sf->ascent+sf->descent)/3;
1497 putshort(at->gi.hmtx,width);
1498 putshort(at->gi.hmtx,0);
1499 if ( dovmetrics ) {
1500 putshort(at->gi.vmtx,sf->ascent+sf->descent);
1501 putshort(at->gi.vmtx,0);
1503 putshort(at->gi.hmtx,width);
1504 putshort(at->gi.hmtx,0);
1505 if ( dovmetrics ) {
1506 putshort(at->gi.vmtx,sf->ascent+sf->descent);
1507 putshort(at->gi.vmtx,0);
1509 cnt = 3;
1512 for ( i=cnt; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
1513 sc = sf->glyphs[at->gi.bygid[i]];
1514 if ( SCWorthOutputting(sc) ) {
1515 if ( i<=at->gi.lasthwidth )
1516 putshort(at->gi.hmtx,sc->width);
1517 SplineCharLayerFindBounds(sc,at->gi.layer,&b);
1518 putshort(at->gi.hmtx,b.minx);
1519 if ( dovmetrics ) {
1520 if ( i<=at->gi.lastvwidth )
1521 putshort(at->gi.vmtx,sc->vwidth);
1522 putshort(at->gi.vmtx,/*sf->vertical_origin-*/b.maxy);
1524 ++cnt;
1525 if ( i==at->gi.lasthwidth )
1526 at->gi.hfullcnt = cnt;
1527 if ( i==at->gi.lastvwidth )
1528 at->gi.vfullcnt = cnt;
1531 at->gi.hmtxlen = ftell(at->gi.hmtx);
1532 if ( at->gi.hmtxlen&2 ) putshort(at->gi.hmtx,0);
1533 if ( dovmetrics ) {
1534 at->gi.vmtxlen = ftell(at->gi.vmtx);
1535 if ( at->gi.vmtxlen&2 ) putshort(at->gi.vmtx,0);
1538 at->gi.maxp->numGlyphs = cnt;
1539 return( true );
1542 static void dumpcffcidhmtx(struct alltabs *at,SplineFont *_sf) {
1543 DBounds b;
1544 SplineChar *sc;
1545 int cid,i,cnt=0,max;
1546 SplineFont *sf = NULL;
1547 int dovmetrics = _sf->hasvmetrics;
1549 at->gi.hmtx = tmpfile();
1550 if ( dovmetrics )
1551 at->gi.vmtx = tmpfile();
1552 FigureFullMetricsEnd(_sf,&at->gi,false);
1554 max = 0;
1555 for ( i=0; i<_sf->subfontcnt; ++i )
1556 if ( max<_sf->subfonts[i]->glyphcnt )
1557 max = _sf->subfonts[i]->glyphcnt;
1558 for ( cid = 0; cid<max; ++cid ) {
1559 for ( i=0; i<_sf->subfontcnt; ++i ) {
1560 sf = _sf->subfonts[i];
1561 if ( cid<sf->glyphcnt && SCWorthOutputting(sf->glyphs[cid]))
1562 break;
1564 if ( i!=_sf->subfontcnt ) {
1565 sc = sf->glyphs[cid];
1566 if ( sc->ttf_glyph<=at->gi.lasthwidth )
1567 putshort(at->gi.hmtx,sc->width);
1568 SplineCharLayerFindBounds(sc,at->gi.layer,&b);
1569 putshort(at->gi.hmtx,b.minx);
1570 if ( dovmetrics ) {
1571 if ( sc->ttf_glyph<=at->gi.lastvwidth )
1572 putshort(at->gi.vmtx,sc->vwidth);
1573 putshort(at->gi.vmtx,/*sf->vertical_origin-*/b.maxy);
1575 ++cnt;
1576 if ( sc->ttf_glyph==at->gi.lasthwidth )
1577 at->gi.hfullcnt = cnt;
1578 if ( sc->ttf_glyph==at->gi.lastvwidth )
1579 at->gi.vfullcnt = cnt;
1580 } else if ( cid==0 ) {
1581 /* Create a dummy entry for .notdef */
1582 sf = _sf->subfonts[0];
1583 putshort(at->gi.hmtx,sf->ascent+sf->descent);
1584 putshort(at->gi.hmtx,0);
1585 ++cnt;
1586 if ( dovmetrics ) {
1587 putshort(at->gi.vmtx,sf->ascent+sf->descent);
1588 putshort(at->gi.vmtx,0);
1592 at->gi.hmtxlen = ftell(at->gi.hmtx);
1593 if ( at->gi.hmtxlen&2 ) putshort(at->gi.hmtx,0);
1594 if ( dovmetrics ) {
1595 at->gi.vmtxlen = ftell(at->gi.vmtx);
1596 if ( at->gi.vmtxlen&2 ) putshort(at->gi.vmtx,0);
1599 at->gi.maxp->numGlyphs = cnt;
1602 static int dumptype2glyphs(SplineFont *sf,struct alltabs *at) {
1603 int i;
1604 struct pschars *subrs, *chrs;
1606 at->cfff = tmpfile();
1607 at->sidf = tmpfile();
1608 at->sidh = tmpfile();
1609 at->charset = tmpfile();
1610 at->encoding = tmpfile();
1611 at->private = tmpfile();
1613 dumpcffheader(sf,at->cfff);
1614 dumpcffnames(sf,at->cfff);
1615 dumpcffcharset(sf,at);
1616 ff_progress_change_stages(2+at->gi.strikecnt);
1618 ATFigureDefWidth(sf,at,-1);
1619 if ((chrs =SplineFont2ChrsSubrs2(sf,at->nomwid,at->defwid,at->gi.bygid,at->gi.gcnt,at->gi.flags,&subrs,at->gi.layer))==NULL )
1620 return( false );
1621 dumpcffprivate(sf,at,-1,subrs->next);
1622 if ( subrs->next!=0 )
1623 _dumpcffstrings(at->private,subrs);
1624 ff_progress_next_stage();
1625 at->charstrings = dumpcffstrings(chrs);
1626 PSCharsFree(subrs);
1627 if ( at->charstrings == NULL )
1628 return( false );
1629 if ( at->format==ff_cff && !isStdEncoding(sf,at->map))
1630 dumpcffencoding(sf,at); /* Do this after we've assigned glyph ids */
1631 dumpcfftopdict(sf,at);
1632 finishup(sf,at);
1634 at->cfflen = ftell(at->cfff);
1635 if ( at->cfflen&3 ) {
1636 for ( i=4-(at->cfflen&3); i>0; --i )
1637 putc('\0',at->cfff);
1640 if ( at->format!=ff_cff )
1641 dumpcffhmtx(at,sf,false);
1642 free(at->gn_sid); at->gn_sid=NULL;
1643 return( true );
1646 static int dumpcidglyphs(SplineFont *sf,struct alltabs *at) {
1647 int i;
1648 struct pschars *glbls = NULL, *chrs;
1650 at->cfff = tmpfile();
1651 at->sidf = tmpfile();
1652 at->sidh = tmpfile();
1653 at->charset = tmpfile();
1654 at->fdselect = tmpfile();
1655 at->fdarray = tmpfile();
1656 at->globalsubrs = tmpfile();
1658 at->fds = gcalloc(sf->subfontcnt,sizeof(struct fd2data));
1659 for ( i=0; i<sf->subfontcnt; ++i ) {
1660 at->fds[i].private = tmpfile();
1661 ATFigureDefWidth(sf->subfonts[i],at,i);
1663 if ( (chrs = CID2ChrsSubrs2(sf,at->fds,at->gi.flags,&glbls,at->gi.layer))==NULL )
1664 return( false );
1665 for ( i=0; i<sf->subfontcnt; ++i ) {
1666 dumpcffprivate(sf->subfonts[i],at,i,at->fds[i].subrs->next);
1667 if ( at->fds[i].subrs->next!=0 )
1668 _dumpcffstrings(at->fds[i].private,at->fds[i].subrs);
1669 PSCharsFree(at->fds[i].subrs);
1671 _dumpcffstrings(at->globalsubrs,glbls);
1672 PSCharsFree(glbls);
1674 dumpcffheader(sf,at->cfff);
1675 dumpcffnames(sf,at->cfff);
1676 dumpcffcidset(sf,at);
1677 dumpcfffdselect(sf,at);
1678 dumpcffdictindex(sf,at);
1679 if ( (at->charstrings = dumpcffstrings(chrs))==NULL )
1680 return( false );
1681 dumpcffcidtopdict(sf,at);
1682 finishupcid(sf,at);
1684 at->cfflen = ftell(at->cfff);
1685 if ( at->cfflen&3 ) {
1686 for ( i=4-(at->cfflen&3); i>0; --i )
1687 putc('\0',at->cfff);
1690 if ( at->format!=ff_cffcid )
1691 dumpcffcidhmtx(at,sf);
1692 return( true );
1697 static void OS2WeightCheck(struct pfminfo *pfminfo,char *weight) {
1698 if ( weight==NULL ) {
1699 /* default it */
1700 } else if ( strstrmatch(weight,"medi")!=NULL ) {
1701 pfminfo->weight = 500;
1702 pfminfo->panose[2] = 6;
1703 } else if ( strstrmatch(weight,"demi")!=NULL ||
1704 strstrmatch(weight,"halb")!=NULL ||
1705 (strstrmatch(weight,"semi")!=NULL &&
1706 strstrmatch(weight,"bold")!=NULL) ) {
1707 pfminfo->weight = 600;
1708 pfminfo->panose[2] = 7;
1709 } else if ( strstrmatch(weight,"bold")!=NULL ||
1710 strstrmatch(weight,"fett")!=NULL ||
1711 strstrmatch(weight,"gras")!=NULL ) {
1712 pfminfo->weight = 700;
1713 pfminfo->panose[2] = 8;
1714 } else if ( strstrmatch(weight,"heavy")!=NULL ) {
1715 pfminfo->weight = 800;
1716 pfminfo->panose[2] = 9;
1717 } else if ( strstrmatch(weight,"black")!=NULL ) {
1718 pfminfo->weight = 900;
1719 pfminfo->panose[2] = 10;
1720 } else if ( strstrmatch(weight,"nord")!=NULL ) {
1721 pfminfo->weight = 950;
1722 pfminfo->panose[2] = 11;
1723 } else if ( strstrmatch(weight,"thin")!=NULL ) {
1724 pfminfo->weight = 100;
1725 pfminfo->panose[2] = 2;
1726 } else if ( strstrmatch(weight,"extra")!=NULL ||
1727 strstrmatch(weight,"light")!=NULL ) {
1728 pfminfo->weight = 200;
1729 pfminfo->panose[2] = 3;
1730 } else if ( strstrmatch(weight,"light")!=NULL ) {
1731 pfminfo->weight = 300;
1732 pfminfo->panose[2] = 4;
1736 void SFDefaultOS2Simple(struct pfminfo *pfminfo,SplineFont *sf) {
1737 pfminfo->pfmfamily = 0x11;
1738 pfminfo->panose[0] = 2;
1739 pfminfo->weight = 400;
1740 pfminfo->panose[2] = 5;
1741 pfminfo->width = 5;
1742 pfminfo->panose[3] = 3;
1743 pfminfo->winascent_add = pfminfo->windescent_add = true;
1744 pfminfo->hheadascent_add = pfminfo->hheaddescent_add = true;
1745 pfminfo->typoascent_add = pfminfo->typodescent_add = true;
1746 pfminfo->os2_winascent = pfminfo->os2_windescent = 0;
1748 if ( sf->subfonts!=NULL ) sf = sf->subfonts[0];
1749 pfminfo->linegap = pfminfo->vlinegap = pfminfo->os2_typolinegap =
1750 rint(.09*(sf->ascent+sf->descent));
1753 void SFDefaultOS2SubSuper(struct pfminfo *pfminfo,int emsize,double italic_angle) {
1754 double s = sin(italic_angle*3.1415926535897932/180.0);
1755 pfminfo->os2_supysize = pfminfo->os2_subysize = .7*emsize;
1756 pfminfo->os2_supxsize = pfminfo->os2_subxsize = .65*emsize;
1757 pfminfo->os2_subyoff = .14*emsize;
1758 pfminfo->os2_supyoff = .48*emsize;
1759 pfminfo->os2_supxoff = s*pfminfo->os2_supyoff;
1760 pfminfo->os2_subxoff = -s*pfminfo->os2_subyoff;
1761 pfminfo->os2_strikeysize = 102*emsize/2048;
1762 pfminfo->os2_strikeypos = 530*emsize/2048;
1765 void SFDefaultOS2Info(struct pfminfo *pfminfo,SplineFont *sf,char *fontname) {
1766 int samewid= -1;
1767 char *weight = sf->cidmaster==NULL ? sf->weight : sf->cidmaster->weight;
1769 if ( sf->pfminfo.pfmset ) {
1770 if ( pfminfo!=&sf->pfminfo )
1771 *pfminfo = sf->pfminfo;
1772 if ( !pfminfo->panose_set ) {
1773 struct pfminfo info;
1774 memset(&info,0,sizeof(info));
1775 sf->pfminfo.pfmset = false;
1776 SFDefaultOS2Info(&info,sf,fontname);
1777 sf->pfminfo.pfmset = true;
1778 memcpy(pfminfo->panose,info.panose,sizeof(info.panose));
1780 } else {
1781 struct pfminfo hold;
1782 if ( pfminfo->hheadset || pfminfo->vheadset )
1783 hold = *pfminfo;
1784 else
1785 hold.hheadset = hold.vheadset = false;
1786 memset(pfminfo,'\0',sizeof(*pfminfo));
1787 SFDefaultOS2Simple(pfminfo,sf);
1788 samewid = CIDOneWidth(sf);
1790 pfminfo->pfmfamily = 0x10;
1791 if ( samewid>0 ) {
1792 pfminfo->pfmfamily = 0x30;
1793 /* pfminfo->panose[3] = 9; */ /* This is done later */
1794 } else if ( strstrmatch(fontname,"sans")!=NULL )
1795 pfminfo->pfmfamily = 0x20;
1796 else if ( strstrmatch(fontname,"script")!=NULL ) {
1797 pfminfo->pfmfamily = 0x40;
1798 pfminfo->panose[0] = 3;
1800 if ( samewid==-1 )
1801 pfminfo->pfmfamily |= 0x1; /* Else it assumes monospace */
1803 /* urw uses 4 character abreviations */
1804 if ( weight!=NULL )
1805 OS2WeightCheck(pfminfo,weight);
1806 OS2WeightCheck(pfminfo,fontname);
1808 if ( strstrmatch(fontname,"ultra")!=NULL &&
1809 strstrmatch(fontname,"condensed")!=NULL ) {
1810 pfminfo->width = 1;
1811 pfminfo->panose[3] = 8;
1812 } else if ( strstrmatch(fontname,"extra")!=NULL &&
1813 strstrmatch(fontname,"condensed")!=NULL ) {
1814 pfminfo->width = 2;
1815 pfminfo->panose[3] = 8;
1816 } else if ( strstrmatch(fontname,"semi")!=NULL &&
1817 strstrmatch(fontname,"condensed")!=NULL ) {
1818 pfminfo->width = 4;
1819 pfminfo->panose[3] = 6;
1820 } else if ( strstrmatch(fontname,"condensed")!=NULL ||
1821 strstrmatch(fontname,"narrow")!=NULL ) {
1822 pfminfo->width = 3;
1823 pfminfo->panose[3] = 6;
1824 } else if ( strstrmatch(fontname,"ultra")!=NULL &&
1825 strstrmatch(fontname,"expanded")!=NULL ) {
1826 pfminfo->width = 9;
1827 pfminfo->panose[3] = 7;
1828 } else if ( strstrmatch(fontname,"extra")!=NULL &&
1829 strstrmatch(fontname,"expanded")!=NULL ) {
1830 pfminfo->width = 8;
1831 pfminfo->panose[3] = 7;
1832 } else if ( strstrmatch(fontname,"semi")!=NULL &&
1833 strstrmatch(fontname,"expanded")!=NULL ) {
1834 pfminfo->width = 6;
1835 pfminfo->panose[3] = 5;
1836 } else if ( strstrmatch(fontname,"expanded")!=NULL ) {
1837 pfminfo->width = 7;
1838 pfminfo->panose[3] = 5;
1840 if ( samewid>0 )
1841 pfminfo->panose[3] = 9;
1842 if ( hold.hheadset ) {
1843 pfminfo->hheadset = true;
1844 pfminfo->hheadascent_add = hold.hheadascent_add;
1845 pfminfo->hheaddescent_add = hold.hheaddescent_add;
1846 pfminfo->hhead_ascent = hold.hhead_ascent;
1847 pfminfo->hhead_descent = hold.hhead_descent;
1848 pfminfo->linegap = hold.linegap;
1850 if ( hold.vheadset ) {
1851 pfminfo->vheadset = true;
1852 pfminfo->vlinegap = hold.vlinegap;
1855 if ( !pfminfo->subsuper_set )
1856 SFDefaultOS2SubSuper(pfminfo,sf->ascent+sf->descent,sf->italicangle);
1859 char *utf8_verify_copy(const char *str) {
1860 /* When given a postscript string it SHOULD be in ASCII. But it will often*/
1861 /* contain a copyright symbol (sometimes in latin1, sometimes in macroman)*/
1862 /* unfortunately both encodings use 0xa9 for copyright so we can't distinguish */
1863 /* guess that it's latin1 (or that copyright is the only odd char which */
1864 /* means a latin1 conversion will work for macs too). */
1866 if ( str==NULL )
1867 return( NULL );
1869 if ( utf8_valid(str))
1870 return( copy(str)); /* Either in ASCII (good) or appears to be utf8*/
1871 return( latin1_2_utf8_copy(str));
1874 int SFHasInstructions(SplineFont *sf) {
1875 int i;
1877 if ( sf->subfontcnt!=0 )
1878 return( false ); /* Truetype doesn't support cid keyed fonts */
1880 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL ) {
1881 if ( strcmp(sf->glyphs[i]->name,".notdef")==0 )
1882 continue; /* ff produces fonts with instructions in .notdef & not elsewhere. Ignore these */
1883 if ( sf->glyphs[i]->ttf_instrs!=NULL )
1884 return( true );
1886 return( false );
1889 static int dumpcff(struct alltabs *at,SplineFont *sf,enum fontformat format,
1890 FILE *cff) {
1891 int ret;
1893 if ( format==ff_cff ) {
1894 AssignTTFGlyph(&at->gi,sf,at->map,true);
1895 ret = dumptype2glyphs(sf,at);
1896 } else {
1897 SFDummyUpCIDs(&at->gi,sf); /* life is easier if we ignore the seperate fonts of a cid keyed fonts and treat it as flat */
1898 ret = dumpcidglyphs(sf,at);
1899 free(sf->glyphs); sf->glyphs = NULL;
1900 sf->glyphcnt = sf->glyphmax = sf->glyphmin = 0;
1902 free( at->gi.bygid );
1904 if ( !ret )
1905 at->error = true;
1906 else if ( at->gi.flags & ps_flag_nocffsugar ) {
1907 if ( !ttfcopyfile(cff,at->cfff,0,"CFF"))
1908 at->error = true;
1909 } else {
1910 long len;
1911 char buffer[80];
1912 fprintf(cff,"%%!PS-Adobe-3.0 Resource-FontSet\n");
1913 fprintf(cff,"%%%%DocumentNeedResources:ProcSet (FontSetInit)\n");
1914 fprintf(cff,"%%%%Title: (FontSet/%s)\n", sf->fontname);
1915 fprintf(cff,"%%%%EndComments\n" );
1916 fprintf(cff,"%%%%IncludeResource: ProcSet(FontSetInit)\n" );
1917 fprintf(cff,"%%%%BeginResource: FontSet(%s)\n", sf->fontname );
1918 fprintf(cff,"/FontSetInit /ProcSet findresource begin\n" );
1919 fseek(at->cfff,0,SEEK_END);
1920 len = ftell(at->cfff);
1921 rewind(at->cfff);
1922 sprintf( buffer, "/%s %ld StartData\n", sf->fontname, len );
1923 fprintf(cff,"%%%%BeginData: %ld Binary Bytes\n", (long) (len+strlen(buffer)) );
1924 fputs(buffer,cff);
1925 if ( !ttfcopyfile(cff,at->cfff,ftell(cff),"CFF"))
1926 at->error = true;
1927 fprintf(cff,"\n%%%%EndData\n" );
1928 fprintf(cff,"%%%%EndResource\n" );
1929 fprintf(cff,"%%%%EOF\n" );
1931 return( !at->error );
1934 int _WriteTTFFont(FILE *ttf,SplineFont *sf,enum fontformat format,
1935 int32 *bsizes, enum bitmapformat bf,int flags,EncMap *map, int layer) {
1936 struct alltabs at;
1937 char *oldloc;
1938 int i, anyglyphs;
1940 oldloc = setlocale(LC_NUMERIC,"C"); /* TrueType probably doesn't need this, but OpenType does for floats in dictionaries */
1941 if ( format==ff_otfcid || format== ff_cffcid ) {
1942 if ( sf->cidmaster ) sf = sf->cidmaster;
1943 } else {
1944 if ( sf->subfontcnt!=0 ) sf = sf->subfonts[0];
1947 if ( sf->subfontcnt==0 ) {
1948 anyglyphs = false;
1949 for ( i=sf->glyphcnt-1; i>0 ; --i ) {
1950 if ( SCWorthOutputting(sf->glyphs[i])) {
1951 anyglyphs = true;
1952 if ( sf->glyphs[i]->unicodeenc!=-1 )
1953 break;
1956 if ( !anyglyphs && !sf->internal_temp ) {
1957 ff_post_error(_("No Encoded Glyphs"),_("Warning: Font contained no glyphs"));
1959 if ( format!=ff_ttfsym && !(flags&ttf_flag_symbol) && !sf->internal_temp ) {
1960 if ( i==0 && anyglyphs ) {
1961 if ( map->enccount<=256 ) {
1962 char *buts[3];
1963 buts[0] = _("_Yes"); buts[1] = _("_No"); buts[2] = NULL;
1964 if ( ff_ask(_("No Encoded Glyphs"),(const char **) buts,0,1,_("This font contains no glyphs with unicode encodings.\nWould you like to use a \"Symbol\" encoding instead of Unicode?"))==0 )
1965 flags |= ttf_flag_symbol;
1966 } else
1967 ff_post_error(_("No Encoded Glyphs"),_("This font contains no glyphs with unicode encodings.\nYou will probably not be able to use the output."));
1972 for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i]!=NULL )
1973 sf->glyphs[i]->ttf_glyph = -1;
1975 memset(&at,'\0',sizeof(struct alltabs));
1976 at.gi.flags = flags;
1977 at.gi.layer = layer;
1978 at.gi.is_ttf = false;
1979 at.applemode = 0;
1980 at.opentypemode = 0;
1981 at.msbitmaps = false;
1982 at.applebitmaps = false;
1983 at.gi.onlybitmaps = false;
1984 at.gi.bsizes = bsizes;
1985 at.gi.fixed_width = CIDOneWidth(sf);
1986 at.isotf = false;
1987 at.format = format;
1988 at.next_strid = 256;
1989 at.sf = sf;
1990 at.map = map;
1992 if ( format==ff_cff || format==ff_cffcid ) {
1993 dumpcff(&at,sf,format,ttf);
1994 } else {
1995 /* TODO: remove top function layers here */
1997 setlocale(LC_NUMERIC,oldloc);
1998 if ( at.error || ferror(ttf))
1999 return( 0 );
2001 #ifdef __CygWin
2002 /* Modern versions of windows want the execute bit set on a ttf file */
2003 /* I've no idea what this corresponds to in windows, nor any idea on */
2004 /* how to set it from the windows UI, but this seems to work */
2006 struct stat buf;
2007 fstat(fileno(ttf),&buf);
2008 fchmod(fileno(ttf),S_IXUSR | buf.st_mode );
2010 #endif
2012 return( 1 );
2015 int WriteTTFFont(char *fontname,SplineFont *sf,enum fontformat format,
2016 int32 *bsizes, enum bitmapformat bf,int flags,EncMap *map, int layer) {
2017 FILE *ttf;
2018 int ret;
2020 if ( strstr(fontname,"://")!=NULL ) {
2021 if (( ttf = tmpfile())==NULL )
2022 return( 0 );
2023 } else {
2024 if (( ttf=fopen(fontname,"wb+"))==NULL )
2025 return( 0 );
2027 ret = _WriteTTFFont(ttf,sf,format,bsizes,bf,flags,map,layer);
2028 if ( fclose(ttf)==-1 )
2029 return( 0 );
2030 return( ret );