1 /* Copyright (C) 2000-2008 by George Williams */
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.
35 extern char *AdobeStandardEncoding
[], *AdobeExpertEncoding
[];
36 extern const char *ttfstandardnames
[];
37 extern int ask_user_for_cmap
;
38 extern char *SaveTablesPref
;
41 SplineFont
*_SFReadTTFInfo(FILE *ttf
, int flags
,enum openflags openflags
, char *filename
,struct fontdict
*fd
);
42 void THPatchSplineChar(SplineChar
*sc
);
45 int THtest_duplicate_glyph_names
= 0;
46 int THread_ttf_glyph_data
= 0;
49 int ask_user_for_cmap
= false;
51 /* True Type is a really icky format. Nothing is together. It's badly described */
52 /* much of the description is misleading */
53 /* Apple's version: */
54 /* http://fonts.apple.com/TTRefMan/index.html */
56 /* http://www.microsoft.com/typography/tt/tt.htm */
57 /* An helpful but incomplete description is given at */
58 /* http://www.truetype.demon.co.uk/ttoutln.htm */
59 /* For some things I looked at freetype's code to see how they did it */
60 /* (I think only for what happens if !ARGS_ARE_XY) */
61 /* http://freetype.sourceforge.net/ */
62 /* It grows on you though... now that I understand it better it seems better designed */
63 /* but the docs remain in conflict. Sometimes badly so */
65 int prefer_cjk_encodings
=false;
67 /* ************************************************************************** */
68 static struct ms_2_locales
{ char *loc_name
; int local_id
; } ms_2_locals
[] = {
100 { "zh_TW", 0x404 }, /* Trad */
101 { "zh_CN", 0x804 }, /* Simp */
102 { "zh_HK", 0xc04 }, /* Trad */
103 { "zh_SG", 0x1004 }, /* Simp */
104 { "zh_MO", 0x1404 }, /* Trad */
131 /* No language code for filipino */
140 { "fr", 0x1c0c }, /* West Indes */
149 { "fr_DZ", 0xe40c }, /* North African is most likely to be Algeria, possibly Tunisia */
165 { "iw", 0x40d }, /* Obsolete name for Hebrew */
170 { "in", 0x421 }, /* Obsolete name for Indonesean */
182 { "ko", 0x812 }, /*Johab */
187 { "lt", 0x827 }, /* Classic */
197 { "no_NO", 0x414 }, /* Bokmal */
198 { "no_NO", 0x814 }, /* Nynorsk */
217 /* No language code for Sepedi */
218 { "sr", 0xc1a }, /* Cyrillic */
219 { "sr", 0x81a }, /* Latin */
226 { "es_ES", 0x40a }, /* traditional spanish */
228 { "es_ES", 0xc0a }, /* Modern spanish */
269 { "uz", 0x443 }, /* Latin */
270 { "uz", 0x843 }, /* Cyrillic */
276 { "ji", 0x43d }, /* Obsolete Yiddish */
281 int MSLanguageFromLocale(void) {
282 const char *lang
=NULL
;
284 static char *envs
[] = { "LC_ALL", "LC_MESSAGES", "LANG", NULL
};
285 char langcountry
[8], language
[4];
286 int langcode
, langlocalecode
;
288 for ( i
=0; envs
[i
]!=NULL
; ++i
) {
289 lang
= getenv(envs
[i
]);
291 langlen
= strlen(lang
);
292 if (( langlen
>5 && lang
[5]=='.' && lang
[2]=='_' ) ||
293 (langlen
==5 && lang
[2]=='_' ) ||
295 (langlen
==3)) /* Some obscure languages have a 3 letter code */
296 /* I understand this language */
302 strncpy(langcountry
,lang
,5); langcountry
[5] = '\0';
303 strncpy(language
,lang
,3); language
[3] = '\0';
304 if ( language
[2]=='_' ) language
[2] = '\0';
305 langlen
= strlen(language
);
307 langcode
= langlocalecode
= -1;
308 for ( i
=0; ms_2_locals
[i
].loc_name
!=NULL
; ++i
) {
309 if ( strmatch(langcountry
,ms_2_locals
[i
].loc_name
)==0 ) {
310 langlocalecode
= ms_2_locals
[i
].local_id
;
311 langcode
= langlocalecode
&0x3ff;
313 } else if ( strncmp(language
,ms_2_locals
[i
].loc_name
,langlen
)==0 )
314 langcode
= ms_2_locals
[i
].local_id
&0x3ff;
316 if ( langcode
==-1 ) /* Default to English */
318 return( langlocalecode
==-1 ? (langcode
|0x400) : langlocalecode
);
320 /* ************************************************************************** */
322 int getushort(FILE *ttf
) {
327 return( (ch1
<<8)|ch2
);
330 int get3byte(FILE *ttf
) {
336 return( (ch1
<<16)|(ch2
<<8)|ch3
);
339 int32
getlong(FILE *ttf
) {
346 return( (ch1
<<24)|(ch2
<<16)|(ch3
<<8)|ch4
);
349 static int32
getoffset(FILE *ttf
, int offsize
) {
352 else if ( offsize
==2 )
353 return( getushort(ttf
));
354 else if ( offsize
==3 )
355 return( get3byte(ttf
));
357 return( getlong(ttf
));
360 real
getfixed(FILE *ttf
) {
361 int32 val
= getlong(ttf
);
362 int mant
= val
&0xffff;
363 /* This oddity may be needed to deal with the first 16 bits being signed */
364 /* and the low-order bits unsigned */
365 return( (real
) (val
>>16) + (mant
/65536.0) );
368 real
get2dot14(FILE *ttf
) {
369 int32 val
= getushort(ttf
);
370 int mant
= val
&0x3fff;
371 /* This oddity may be needed to deal with the first 2 bits being signed */
372 /* and the low-order bits unsigned */
373 return( (real
) ((val
<<16)>>(16+14)) + (mant
/16384.0) );
376 static Encoding
*enc_from_platspec(int platform
,int specific
) {
385 } else if ( platform
==1 ) {
388 else if ( specific
==1 )
390 else if ( specific
==2 )
391 enc
= "Big5hkscs"; /* Or should we just guess big5? Both are wrong sometimes */
392 else if ( specific
==3 )
394 else if ( specific
==25 )
396 } else if ( platform
==2 ) { /* obselete */
399 else if ( specific
==1 )
401 else if ( specific
==2 )
403 } else if ( platform
==3 ) {
404 if ( specific
==1 || specific
==0 ) /* symbol (sp=0) is just unicode (PUA) */
406 else if ( specific
==2 )
408 else if ( specific
==3 )
410 else if ( specific
==4 )
412 else if ( specific
==5 )
414 else if ( specific
==6 )
416 else if ( specific
==10 )
418 } else if ( platform
==7 ) { /* Used internally in freetype, but */
419 if ( specific
==0 ) /* there's no harm in looking for it */
420 enc
= "AdobeStandard"; /* even if it never happens */
421 else if ( specific
==1 ) {
423 } else if ( specific
==2 ) {
427 e
= FindOrMakeEncoding(enc
);
429 static int p
= -1,s
= -1;
430 if ( p
!=platform
|| s
!=specific
) {
431 LogError( _("The truetype encoding specified by platform=%d specific=%d (which we map to %s) is not supported by your version of iconv(3).\n"),
432 platform
, specific
, enc
);
433 p
= platform
; s
= specific
;
439 static char *_readencstring(FILE *ttf
,int offset
,int len
,
440 int platform
,int specific
,int language
) {
441 long pos
= ftell(ttf
);
447 fseek(ttf
,offset
,SEEK_SET
);
450 /* Mac is screwy, there are several different varients of MacRoman */
451 /* depending on the language, they didn't get it right when they */
452 /* invented their script system */
454 cstr
= cpt
= galloc(len
+1);
455 for ( i
=0; i
<len
; ++i
)
458 ret
= MacStrToUtf8(cstr
,specific
,language
);
461 enc
= enc_from_platspec(platform
,specific
);
464 if ( enc
->is_unicodebmp
) {
465 str
= pt
= galloc((sizeof(unichar_t
)/2)*len
+sizeof(unichar_t
));
466 for ( i
=0; i
<len
/2; ++i
) {
468 *pt
++ = ch
| getc(ttf
);
471 } else if ( enc
->unicode
!=NULL
) {
472 str
= pt
= galloc(sizeof(unichar_t
)*len
+sizeof(unichar_t
));
473 for ( i
=0; i
<len
; ++i
)
474 *pt
++ = enc
->unicode
[getc(ttf
)];
476 } else if ( enc
->tounicode
!=NULL
) {
477 size_t inlen
= len
+1, outlen
= sizeof(unichar_t
)*(len
+1);
478 char *cstr
= galloc(inlen
);
479 ICONV_CONST
char *in
= cstr
;
482 str
= galloc(outlen
+2);
484 str
= galloc(outlen
+sizeof(unichar_t
));
486 /*str = galloc(outlen+2);*/
488 iconv(enc
->tounicode
,&in
,&inlen
,&out
,&outlen
);
489 out
[0] = '\0'; out
[1] = '\0';
491 out
[2] = '\0'; out
[3] = '\0';
497 ret
= u2utf8_copy(str
);
500 fseek(ttf
,pos
,SEEK_SET
);
504 char *TTFGetFontName(FILE *ttf
,int32 offset
,int32 off2
) {
506 int32 tag
, length
, stringoffset
;
507 int plat
, spec
, lang
, name
, len
, off
, val
;
509 int32 nameoffset
= 0;
510 int fullval
=0, fullstr
=0, fulllen
=0, famval
=0, famstr
=0, famlen
=0;
511 int fullplat
=0, fullspec
=0, fulllang
=0, famplat
=0, famspec
=0, famlang
=0;
512 int locale
= MSLanguageFromLocale();
513 int maclang
= WinLangToMac(locale
);
515 fseek(ttf
,offset
,SEEK_SET
);
516 /* version = */ getlong(ttf
);
517 num
= getushort(ttf
);
518 /* srange = */ getushort(ttf
);
519 /* esel = */ getushort(ttf
);
520 /* rshift = */ getushort(ttf
);
521 for ( i
=0; i
<num
; ++i
) {
523 /* checksum = */ getlong(ttf
);
524 nameoffset
= off2
+getlong(ttf
);
525 length
= getlong(ttf
);
526 if ( tag
==CHR('n','a','m','e'))
532 fseek(ttf
,nameoffset
,SEEK_SET
);
533 /* format = */ getushort(ttf
);
534 num
= getushort(ttf
);
535 stringoffset
= nameoffset
+getushort(ttf
);
536 fullval
= famval
= 0;
537 for ( i
=0; i
<num
; ++i
) {
538 plat
= getushort(ttf
);
539 spec
= getushort(ttf
);
540 lang
= getushort(ttf
);
541 name
= getushort(ttf
);
542 len
= getushort(ttf
);
543 off
= getushort(ttf
);
544 enc
= enc_from_platspec(plat
,spec
);
548 if ( plat
==3 && !enc
->is_custom
&& lang
==locale
)
550 else if ( plat
==3 && !enc
->is_custom
&& (lang
&0xff)==(locale
&0xff) )
552 else if ( (plat
==0 || plat
==1) && !enc
->is_custom
&& lang
==maclang
)
554 /* Ok, that didn't work, how about an english name? */
555 else if ( plat
==3 && !enc
->is_custom
&& lang
==0x409 )
557 else if ( plat
==3 && !enc
->is_custom
&& (lang
&0xff)==0x09 )
559 else if ( (plat
==0 || plat
==1) && !enc
->is_custom
&& lang
==0 )
561 /* failing that I'll take what I can get */
562 else if ( !enc
->is_custom
)
564 if ( name
==4 && val
>fullval
) {
573 } else if ( name
==1 && val
>famval
) {
591 return( _readencstring(ttf
,stringoffset
+fullstr
,fulllen
,fullplat
,fullspec
,fulllang
));
595 char *TTFGetPSFontName(FILE *ttf
,int32 offset
,int32 off2
) {
597 int32 tag
, length
, stringoffset
;
599 int32 nameoffset
= 0;
601 fseek(ttf
,offset
,SEEK_SET
);
602 /* version = */ getlong(ttf
);
603 num
= getushort(ttf
);
604 /* srange = */ getushort(ttf
);
605 /* esel = */ getushort(ttf
);
606 /* rshift = */ getushort(ttf
);
607 for ( i
=0; i
<num
; ++i
) {
609 /* checksum = */ getlong(ttf
);
610 nameoffset
= off2
+getlong(ttf
);
611 length
= getlong(ttf
);
612 if ( tag
==CHR('n','a','m','e'))
618 fseek(ttf
,nameoffset
,SEEK_SET
);
619 /* format = */ getushort(ttf
);
620 num
= getushort(ttf
);
621 stringoffset
= nameoffset
+getushort(ttf
);
623 for ( i
=0; i
<num
; ++i
) {
624 /* plat */ getushort(ttf
);
625 /* spec */ getushort(ttf
);
626 /* lang */ getushort(ttf
);
627 name
= getushort(ttf
);
628 len
= getushort(ttf
);
629 off
= getushort(ttf
);
631 char *str
= malloc(len
+1);
633 fseek (ttf
, stringoffset
+off
, SEEK_SET
);
634 if(fread(str
,1,len
,ttf
)==(size_t)len
) {
645 static int PickTTFFont(FILE *ttf
,char *filename
,char **chosenname
) {
646 int32
*offsets
, cnt
, i
, choice
, j
;
648 char *pt
, *lparen
, *rparen
;
650 /* TTCF version = */ getlong(ttf
);
653 /* This is easy, don't bother to ask the user, there's no choice */
654 int32 offset
= getlong(ttf
);
655 fseek(ttf
,offset
,SEEK_SET
);
658 offsets
= galloc(cnt
*sizeof(int32
));
659 for ( i
=0; i
<cnt
; ++i
)
660 offsets
[i
] = getlong(ttf
);
661 names
= galloc(cnt
*sizeof(char *));
662 for ( i
=j
=0; i
<cnt
; ++i
) {
663 names
[j
] = TTFGetFontName(ttf
,offsets
[i
],0);
664 if ( names
[j
]!=NULL
) ++j
;
666 pt
= strrchr(filename
,'/');
667 if ( pt
==NULL
) pt
= filename
;
668 /* Someone gave me a font "Nafees Nastaleeq(Updated).ttf" and complained */
669 /* that ff wouldn't open it */
670 /* Now someone will complain about "Nafees(Updated).ttc(fo(ob)ar)" */
671 if ( (lparen
= strrchr(pt
,'('))!=NULL
&&
672 (rparen
= strrchr(lparen
,')'))!=NULL
&&
674 char *find
= copy(lparen
+1);
675 pt
= strchr(find
,')');
676 if ( pt
!=NULL
) *pt
='\0';
677 for ( choice
=cnt
-1; choice
>=0; --choice
)
678 if ( strcmp(names
[choice
],find
)==0 )
682 choice
= strtol(find
,&end
,10);
687 char *fn
= copy(filename
);
688 fn
[lparen
-filename
] = '\0';
689 ff_post_error(_("Not in Collection"),
690 /* GT: The user is trying to open a font file which contains multiple fonts and */
691 /* GT: has asked for a font which is not in that file. */
692 /* GT: The string will look like: <fontname> is not in <filename> */
693 _("%1$s is not in %2$.100s"),find
,fn
);
700 fseek(ttf
,offsets
[choice
],SEEK_SET
);
701 *chosenname
= copy(names
[choice
]);
703 for ( i
=0; i
<j
; ++i
)
710 static int PickCFFFont(char **fontnames
) {
714 for ( cnt
=0; fontnames
[cnt
]!=NULL
; ++cnt
);
715 names
= gcalloc(cnt
+1,sizeof(unichar_t
*));
716 for ( i
=0; i
<cnt
; ++i
)
717 names
[i
] = uc_copy(fontnames
[i
]);
719 for ( i
=0; i
<cnt
; ++i
)
725 static void ParseSaveTablesPref(struct ttfinfo
*info
) {
730 info
->savetab
= NULL
;
731 if ( SaveTablesPref
==NULL
|| *SaveTablesPref
=='\0' )
733 for ( pt
=SaveTablesPref
, cnt
=0; *pt
; ++pt
)
736 info
->savecnt
= cnt
+1;
737 info
->savetab
= gcalloc(cnt
+1,sizeof(struct savetab
));
738 for ( pt
=spt
=SaveTablesPref
, cnt
=0; ; ++pt
) {
739 if ( *pt
==',' || *pt
=='\0' ) {
741 tag
= ( ( spt
<pt
)? spt
[0] : ' ' )<<24;
742 tag
|= ( ( spt
+1<pt
)? spt
[1] : ' ' )<<16;
743 tag
|= ( ( spt
+2<pt
)? spt
[2] : ' ' )<<8 ;
744 tag
|= ( ( spt
+3<pt
)? spt
[3] : ' ' ) ;
745 info
->savetab
[cnt
++].tag
= tag
;
754 static int32
filechecksum(FILE *file
, int start
, int len
) {
755 uint32 sum
= 0, chunk
;
757 fseek(file
,start
,SEEK_SET
);
758 if ( len
!=-1 ) len
=(len
+3)>>2;
759 while ( len
==-1 || --len
>=0 ) {
760 chunk
= getlong(file
);
768 static void ValidateTTFHead(FILE *ttf
,struct ttfinfo
*info
) {
769 /* When doing font lint we want to check the ttf header and make */
770 /* sure all the offsets and lengths are valid, and the checksums */
771 /* match. Most of the time this is just extra work and we don't */
773 uint32 restore_this_pos
= ftell(ttf
);
782 int sr
, es
, rs
, e_sr
, e_es
, e_rs
;
783 int hashead
, hashhea
, hasmaxp
, masos2
, haspost
, hasname
, hasos2
;
784 int hasloca
, hascff
, hasglyf
;
786 info
->numtables
= getushort(ttf
);
790 e_sr
= (info
->numtables
<8?4:info
->numtables
<16?8:info
->numtables
<32?16:info
->numtables
<64?32:64)*16;
791 e_es
= (info
->numtables
<8?2:info
->numtables
<16?3:info
->numtables
<32?4:info
->numtables
<64?5:6);
792 e_rs
= info
->numtables
*16-e_sr
;
793 if ( e_sr
!=sr
|| e_es
!=es
|| e_rs
!=rs
) {
794 LogError( _("Unexpected values for binsearch header. Based on the number of tables I\n expect searchRange=%d (not %d), entrySel=%d (not %d) rangeShift=%d (not %d)\n"),
795 e_sr
, sr
, e_es
, es
, e_rs
, rs
);
796 info
->bad_sfnt_header
= true;
799 if ( info
->numtables
<=0 ) {
800 LogError(_("An sfnt file must contain SOME tables, but this one does not."));
801 info
->bad_sfnt_header
= true;
802 fseek(ttf
,restore_this_pos
,SEEK_SET
);
804 } else if ( info
->numtables
>1000 ) {
805 LogError(_("An sfnt file may contain a large number of tables, but this one has over 1000\n and that seems like too many\n"));
806 info
->bad_sfnt_header
= true;
807 fseek(ttf
,restore_this_pos
,SEEK_SET
);
811 tabs
= galloc(info
->numtables
*sizeof(struct tt_tables
));
813 for ( i
=0; i
<info
->numtables
; ++i
) {
814 tabs
[i
].tag
= getlong(ttf
);
815 tabs
[i
].checksum
= getlong(ttf
);
816 tabs
[i
].offset
= getlong(ttf
);
817 tabs
[i
].length
= getlong(ttf
);
818 if ( i
!=0 && tabs
[i
].tag
<tabs
[i
-1].tag
&& !info
->bad_sfnt_header
) {
819 LogError(_("Table tags should be in alphabetic order in the font header\n but '%c%c%c%c', appears after '%c%c%c%c'."),
820 tabs
[i
-1].tag
>>24, tabs
[i
-1].tag
>>16, tabs
[i
-1].tag
>>8, tabs
[i
-1].tag
,
821 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
);
822 info
->bad_sfnt_header
= true;
825 fseek(ttf
,0,SEEK_END
);
826 file_len
= ftell(ttf
);
828 for ( i
=0; i
<info
->numtables
; ++i
) for ( j
=i
+1; j
<info
->numtables
; ++j
) {
829 if ( tabs
[i
].offset
>tabs
[j
].offset
) {
835 for ( i
=0; i
<info
->numtables
-1; ++i
) {
836 for ( j
=i
+1; j
<info
->numtables
; ++j
) {
837 if ( tabs
[i
].tag
==tabs
[j
].tag
) {
838 LogError(_("Same table tag, '%c%c%c%c', appears twice in sfnt header"),
839 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
);
840 info
->bad_sfnt_header
= true;
843 if ( tabs
[i
].offset
+tabs
[i
].length
> tabs
[i
+1].offset
) {
844 LogError(_("Tables '%c%c%c%c' and '%c%c%c%c' overlap"),
845 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
,
846 tabs
[j
].tag
>>24, tabs
[j
].tag
>>16, tabs
[j
].tag
>>8, tabs
[j
].tag
);
849 if ( tabs
[i
].offset
+tabs
[i
].length
> file_len
) {
850 LogError(_("Table '%c%c%c%c' extends beyond end of file."),
851 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
);
852 info
->bad_sfnt_header
= true;
855 /* Checksums. First file as a whole, then each table */
856 if ( filechecksum(ttf
,0,-1)!=(int)0xb1b0afba ) {
857 LogError(_("File checksum is incorrect."));
858 info
->bad_sfnt_header
= true;
860 for ( i
=0; i
<info
->numtables
-1; ++i
) if ( tabs
[i
].tag
!=CHR('h','e','a','d')) {
861 if ( filechecksum(ttf
,tabs
[i
].offset
,tabs
[i
].length
)!=(int)tabs
[i
].checksum
) {
862 LogError(_("Table '%c%c%c%c' has a bad checksum."),
863 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
);
864 info
->bad_sfnt_header
= true;
868 hashead
= hashhea
= hasmaxp
= masos2
= haspost
= hasname
= hasos2
= false;
869 hasloca
= hascff
= hasglyf
= false;
870 for ( i
=0; i
<info
->numtables
-1; ++i
) {
871 switch ( tabs
[i
].tag
) {
872 case CHR('c','v','t',' '):
873 if ( tabs
[i
].length
&1 )
874 LogError(_("Table '%c%c%c%c' has a bad length, must be even."),
875 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
);
877 case CHR('b','h','e','d'): /* Fonts with bitmaps but no outlines get bhea */
878 case CHR('h','e','a','d'):
879 if ( tabs
[i
].length
!=54 )
880 LogError(_("Table '%c%c%c%c' has a bad length, must be 54 but is %d."),
881 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
,
885 case CHR('h','h','e','a'):
887 case CHR('v','h','e','a'):
888 if ( tabs
[i
].length
!=36 )
889 LogError(_("Table '%c%c%c%c' has a bad length, must be 36 but is %d."),
890 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
,
893 case CHR('m','a','x','p'):
895 if ( tabs
[i
].length
!=32 && tabs
[i
].length
!=6 )
896 LogError(_("Table '%c%c%c%c' has a bad length, must be 32 or 6 but is %d."),
897 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
,
900 case CHR('O','S','/','2'):
902 if ( tabs
[i
].length
!=78 && tabs
[i
].length
!=86 && tabs
[i
].length
!=96 )
903 LogError(_("Table '%c%c%c%c' has a bad length, must be 78, 86 or 96 but is %d."),
904 tabs
[i
].tag
>>24, tabs
[i
].tag
>>16, tabs
[i
].tag
>>8, tabs
[i
].tag
,
907 case CHR('p','o','s','t'):
910 case CHR('n','a','m','e'):
913 case CHR('l','o','c','a'):
916 case CHR('g','l','y','f'):
919 case CHR('C','F','F',' '):
925 LogError(_("Missing required table: \"head\""));
927 LogError(_("Missing required table: \"hhea\""));
929 LogError(_("Missing required table: \"maxp\""));
931 LogError(_("Missing required table: \"post\""));
933 LogError(_("Missing required table: \"name\""));
934 if ( hasglyf
&& !hasloca
)
935 LogError(_("Missing required table: \"loca\""));
937 LogError(_("Missing \"OS/2\" table"));
938 if ( !hasglyf
&& hasloca
)
939 LogError(_("Missing required table: \"glyf\""));
940 if ( !hasglyf
&& !hascff
)
941 LogError(_("This font contains neither \"CFF \" nor \"glyf\"/\"loca\" tables"));
944 fseek(ttf
,restore_this_pos
,SEEK_SET
);
947 static struct tablenames
{ uint32 tag
; char *name
; } stdtables
[] = {
948 { CHR('a','c','n','t'), N_("accent attachment table") },
949 { CHR('a','v','a','r'), N_("axis variation table") },
950 { CHR('B','A','S','E'), N_("Baseline table (OT version)") },
951 { CHR('b','d','a','t'), N_("bitmap data table (AAT version)") },
952 { CHR('B','D','F',' '), N_("BDF bitmap properties table") },
953 { CHR('b','h','e','d'), N_("bitmap font header table") },
954 { CHR('b','l','o','c'), N_("bitmap location table (AAT version)") },
955 { CHR('b','s','l','n'), N_("baseline table (AAT version)") },
956 { CHR('C','F','F',' '), N_("PostScript font program (Compact Font Format)") },
957 { CHR('C','I','D',' '), N_("Obsolete table for a type1 CID keyed font") },
958 { CHR('c','m','a','p'), N_("character code mapping table") },
959 { CHR('c','v','a','r'), N_("CVT variation table") },
960 { CHR('c','v','t',' '), N_("control value table") },
961 { CHR('D','S','I','G'), N_("digital signature table") },
962 { CHR('E','B','D','T'), N_("bitmap data table (OT version)") },
963 { CHR('E','B','L','C'), N_("bitmap location table (OT version)") },
964 { CHR('E','B','S','C'), N_("embedded bitmap scaling control table") },
965 { CHR('E','L','U','A'), N_("electronic end user license table") },
966 { CHR('f','d','s','c'), N_("font descriptor table") },
967 { CHR('f','e','a','t'), N_("layout feature table") },
968 { CHR('F','e','a','t'), N_("SIL Graphite layout feature table") },
969 { CHR('F','F','T','M'), N_("FontForge time stamp table") },
970 { CHR('f','m','t','x'), N_("font metrics table") },
971 { CHR('f','p','g','m'), N_("font program table") },
972 { CHR('f','v','a','r'), N_("font variation table") },
973 { CHR('g','a','s','p'), N_("grid-fitting and scan-conversion procedure table") },
974 { CHR('G','D','E','F'), N_("glyph definition table") },
975 { CHR('G','l','a','t'), N_("Graphite glyph attribute table") },
976 { CHR('G','l','o','c'), N_("Graphite glyph location in Glat table") },
977 { CHR('g','l','y','f'), N_("glyph outline table") },
978 { CHR('G','P','O','S'), N_("glyph positioning table") },
979 { CHR('g','v','a','r'), N_("glyph variation table") },
980 { CHR('G','S','U','B'), N_("glyph substitution table") },
981 { CHR('h','d','m','x'), N_("horizontal device metrics table") },
982 { CHR('h','e','a','d'), N_("font header table") },
983 { CHR('h','h','e','a'), N_("horizontal header table") },
984 { CHR('h','m','t','x'), N_("horizontal metrics table") },
985 { CHR('h','s','t','y'), N_("horizontal style table") },
986 { CHR('j','u','s','t'), N_("justification table (AAT version)") },
987 { CHR('J','S','T','F'), N_("justification table (OT version)") },
988 { CHR('k','e','r','n'), N_("kerning table") },
989 { CHR('l','c','a','r'), N_("ligature caret table") },
990 { CHR('l','o','c','a'), N_("glyph location table") },
991 { CHR('L','T','S','H'), N_("linear threshold table") },
992 { CHR('M','A','T','H'), N_("math table") },
993 { CHR('m','a','x','p'), N_("maximum profile table") },
994 { CHR('M','M','S','D'), N_("Multi-Master table, obsolete") },
995 { CHR('M','M','F','X'), N_("Multi-Master table, obsolete") },
996 { CHR('m','o','r','t'), N_("metamorphosis table") },
997 { CHR('m','o','r','x'), N_("extended metamorphosis table") },
998 { CHR('n','a','m','e'), N_("name table") },
999 { CHR('o','p','b','d'), N_("optical bounds table") },
1000 { CHR('O','S','/','2'), N_("OS/2 and Windows specific metrics table") },
1001 { CHR('P','C','L','T'), N_("PCL 5 data table") },
1002 { CHR('P','f','E','d'), N_("FontForge font debugging table") },
1003 { CHR('p','o','s','t'), N_("glyph name and PostScript compatibility table") },
1004 { CHR('p','r','e','p'), N_("control value program table") },
1005 { CHR('p','r','o','p'), N_("properties table") },
1006 { CHR('S','i','l','f'), N_("SIL Graphite rule table") },
1007 { CHR('S','i','l','l'), N_("(unspecified) SIL Graphite table") },
1008 { CHR('S','i','l','t'), N_("unknown SIL table") },
1009 { CHR('T','e','X',' '), N_("TeX table") },
1010 { CHR('t','r','a','k'), N_("tracking table") },
1011 { CHR('T','Y','P','1'), N_("Obsolete table for a type1 font") },
1012 { CHR('V','D','M','X'), N_("vertical device metrics table") },
1013 { CHR('v','h','e','a'), N_("vertical header table") },
1014 { CHR('v','m','t','x'), N_("vertical metrics table") },
1015 { CHR('V','O','R','G'), N_("vertical origin table") },
1016 { CHR('Z','a','p','f'), N_("glyph reference table") },
1020 static int readttfheader(FILE *ttf
, struct ttfinfo
*info
,char *filename
,
1021 char **choosenname
) {
1024 int checksum
, offset
, length
, version
;
1027 version
=getlong(ttf
);
1028 if ( version
==CHR('t','t','c','f')) {
1029 /* TrueType font collection */
1030 info
->is_ttc
= true;
1031 if ( !PickTTFFont(ttf
,filename
,choosenname
))
1033 /* If they picked a font, then we should be left pointing at the */
1034 /* start of the Table Directory for that font */
1035 info
->one_of_many
= true;
1036 version
= getlong(ttf
);
1039 /* Apple says that 'typ1' is a valid code for a type1 font wrapped up in */
1040 /* a truetype table structure, but gives no docs on what tables get used */
1041 /* or how */ /* Turns out to be pretty simple */
1042 /* typ1 is used for both type1 fonts and CID type1 fonts, I don't think a version of 'CID ' is actually used */
1043 if ( version
==CHR('t','y','p','1') || version
==CHR('C','I','D',' ')) {
1044 LogError( _("Nifty, you've got one of the old Apple/Adobe type1 sfnts here\n") );
1045 } else if ( version
!=0x00010000 && version
!=CHR('t','r','u','e') &&
1046 version
!=0x00020000 && /* Windows 3.1 Chinese version used this version for some arphic fonts */
1047 /* See discussion on freetype list, july 2004 */
1048 version
!=CHR('O','T','T','O'))
1049 return( 0 ); /* Not version 1 of true type, nor Open Type */
1051 if ( info
->openflags
& of_fontlint
)
1052 ValidateTTFHead(ttf
,info
);
1054 info
->numtables
= getushort(ttf
);
1055 /* searchRange = */ getushort(ttf
);
1056 /* entrySelector = */ getushort(ttf
);
1057 /* rangeshift = */ getushort(ttf
);
1059 ParseSaveTablesPref(info
);
1061 for ( i
=0; i
<info
->numtables
; ++i
) {
1063 checksum
= getlong(ttf
);
1064 offset
= getlong(ttf
);
1065 length
= getlong(ttf
);
1067 printf( "%c%c%c%c\n", tag
>>24, (tag
>>16)&0xff, (tag
>>8)&0xff, tag
&0xff );
1070 case CHR('B','A','S','E'):
1071 info
->base_start
= offset
;
1073 case CHR('C','F','F',' '):
1074 info
->cff_start
= offset
;
1075 info
->cff_length
= length
;
1077 case CHR('c','m','a','p'):
1078 info
->encoding_start
= offset
;
1080 case CHR('g','a','s','p'):
1081 info
->gasp_start
= offset
;
1083 case CHR('g','l','y','f'):
1084 info
->glyph_start
= offset
;
1085 info
->glyph_length
= length
;
1087 case CHR('G','D','E','F'):
1088 info
->gdef_start
= offset
;
1089 info
->gdef_length
= length
;
1091 case CHR('G','P','O','S'):
1092 info
->gpos_start
= offset
;
1093 info
->gpos_length
= length
;
1095 case CHR('G','S','U','B'):
1096 info
->gsub_start
= offset
;
1097 info
->gsub_length
= length
;
1099 case CHR('b','d','a','t'): /* Apple/MS use a different tag, but the same format. Great. */
1100 case CHR('E','B','D','T'):
1101 info
->bitmapdata_start
= offset
;
1102 info
->bitmapdata_length
= length
;
1104 case CHR('b','l','o','c'): /* Apple/MS use a different tag. Great. */
1105 case CHR('E','B','L','C'):
1106 info
->bitmaploc_start
= offset
;
1107 info
->bitmaploc_length
= length
;
1109 case CHR('b','h','e','d'): /* Apple uses bhed for fonts with only bitmaps */
1110 case CHR('h','e','a','d'):
1111 info
->head_start
= offset
;
1113 case CHR('h','h','e','a'):
1114 info
->hhea_start
= offset
;
1116 case CHR('h','m','t','x'):
1117 info
->hmetrics_start
= offset
;
1119 case CHR('k','e','r','n'):
1120 info
->kern_start
= offset
;
1122 case CHR('l','o','c','a'):
1123 info
->glyphlocations_start
= offset
;
1124 info
->loca_length
= length
;
1125 info
->glyph_cnt
= length
/2-1; /* the minus one is because there is one extra entry to give the length of the last glyph */
1126 if ( info
->glyph_cnt
<0 ) info
->glyph_cnt
= 0;
1128 case CHR('m','a','x','p'):
1129 info
->maxp_start
= offset
;
1130 info
->maxp_len
= length
;
1132 case CHR('n','a','m','e'):
1133 info
->copyright_start
= offset
;
1135 case CHR('p','o','s','t'):
1136 info
->postscript_start
= offset
;
1138 case CHR('O','S','/','2'):
1139 info
->os2_start
= offset
;
1141 case CHR('C','I','D',' '):
1142 case CHR('T','Y','P','1'):
1143 info
->typ1_start
= offset
;
1144 info
->typ1_length
= length
;
1146 case CHR('v','h','e','a'):
1147 info
->vhea_start
= offset
;
1149 case CHR('v','m','t','x'):
1150 info
->vmetrics_start
= offset
;
1152 case CHR('M','A','T','H'):
1153 info
->math_start
= offset
;
1154 info
->math_length
= length
;
1156 /* to make sense of instrs */
1157 case CHR('c','v','t',' '):
1158 info
->cvt_start
= offset
;
1159 info
->cvt_len
= length
;
1161 case CHR('p','r','e','p'):
1162 info
->prep_start
= offset
;
1163 info
->prep_len
= length
;
1165 case CHR('f','p','g','m'):
1166 info
->fpgm_start
= offset
;
1167 info
->fpgm_len
= length
;
1170 /* non-standard tables I've added */
1171 case CHR('P','f','E','d'):
1172 info
->pfed_start
= offset
;
1174 case CHR('F','F','T','M'):
1175 info
->fftm_start
= offset
;
1177 case CHR('T','e','X',' '):
1178 info
->tex_start
= offset
;
1180 case CHR('B','D','F',' '):
1181 info
->bdf_start
= offset
;
1185 for ( j
=0; j
<info
->savecnt
; ++j
) if ( info
->savetab
[j
].tag
== tag
) {
1186 info
->savetab
[j
].offset
= offset
;
1187 info
->savetab
[j
].len
= length
;
1190 if ( j
==info
->savecnt
) {
1192 LogError( _("The following table(s) in the font have been ignored by FontForge\n") );
1195 for ( k
=0; stdtables
[k
].tag
!=0; ++k
)
1196 if ( stdtables
[k
].tag
== tag
)
1198 if ( stdtables
[k
].tag
==0 ) {
1199 LogError( _(" Ignoring '%c%c%c%c'\n"), tag
>>24, tag
>>16, tag
>>8, tag
);
1201 LogError( _(" Ignoring '%c%c%c%c' %s\n"), tag
>>24, tag
>>16, tag
>>8, tag
,
1202 _(stdtables
[k
].name
));
1207 if ( info
->glyphlocations_start
!=0 && info
->cff_start
!=0 )
1208 LogError( _("This font contains both truetype and PostScript glyph descriptions\n only one will be used.\n"));
1209 else if ( (info
->glyphlocations_start
!=0) +
1210 (info
->cff_start
!=0) +
1211 (info
->typ1_start
!=0)>1 )
1212 LogError( _("This font contains multiple glyph descriptions\n only one will be used.\n"));
1213 if ( info
->gpos_start
!=0 && info
->kern_start
!=0 )
1214 LogError( _("This font contains both a 'kern' table and a 'GPOS' table.\n The 'kern' table will only be read if there is no 'kern' feature in 'GPOS'.\n"));
1218 static void readdate(FILE *ttf
,struct ttfinfo
*info
,int ismod
) {
1219 int date
[4], date1970
[4], year
[2];
1221 /* Dates in sfnt files are seconds since 1904. I adjust to unix time */
1222 /* seconds since 1970 by figuring out how many seconds were in between */
1224 date
[3] = getushort(ttf
);
1225 date
[2] = getushort(ttf
);
1226 date
[1] = getushort(ttf
);
1227 date
[0] = getushort(ttf
);
1228 memset(date1970
,0,sizeof(date1970
));
1229 year
[0] = (60*60*24*365L)&0xffff;
1230 year
[1] = (60*60*24*365L)>>16;
1231 for ( i
=1904; i
<1970; ++i
) {
1232 date1970
[0] += year
[0];
1233 date1970
[1] += year
[1];
1234 if ( (i
&3)==0 && (i
%100!=0 || i
%400==0))
1235 date1970
[0] += 24*60*60L; /* Leap year */
1236 date1970
[1] += (date1970
[0]>>16);
1237 date1970
[0] &= 0xffff;
1238 date1970
[2] += date1970
[1]>>16;
1239 date1970
[1] &= 0xffff;
1240 date1970
[3] += date1970
[2]>>16;
1241 date1970
[2] &= 0xffff;
1244 for ( i
=0; i
<3; ++i
) {
1245 date
[i
] -= date1970
[i
];
1246 date
[i
+1] += date
[i
]>>16;
1249 date
[3] -= date1970
[3];
1251 *(ismod
? &info
->modificationtime
: &info
->creationtime
) =
1252 #ifdef _HAS_LONGLONG
1253 (((long long) date
[3])<<48) |
1254 (((long long) date
[2])<<32) |
1260 static void readttfhead(FILE *ttf
,struct ttfinfo
*info
) {
1261 /* Here I want units per em, and size of loca entries */
1262 /* oh... also creation/modification times */
1265 fseek(ttf
,info
->head_start
+4*4,SEEK_SET
); /* skip over the version number and a bunch of junk */
1266 flags
= getushort(ttf
);
1267 info
->optimized_for_cleartype
= (flags
&(1<<13))?1:0;
1268 info
->apply_lsb
= !(flags
&(1<<1));
1269 info
->emsize
= getushort(ttf
);
1271 info
->ascent
= .8*info
->emsize
;
1272 info
->descent
= info
->emsize
-info
->ascent
;
1274 for ( i
=0; i
<12; ++i
)
1276 info
->macstyle
= getushort(ttf
);
1277 for ( i
=0; i
<2; ++i
)
1279 info
->index_to_loc_is_long
= getushort(ttf
);
1280 if ( info
->index_to_loc_is_long
)
1281 info
->glyph_cnt
= info
->loca_length
/4-1;
1282 if ( info
->glyph_cnt
<0 ) info
->glyph_cnt
= 0;
1284 if ( info
->fftm_start
!=0 ) {
1285 fseek(ttf
,info
->fftm_start
+3*4,SEEK_SET
);
1287 fseek(ttf
,info
->head_start
+4*4+2+2,SEEK_SET
);
1289 readdate(ttf
,info
,0);
1290 readdate(ttf
,info
,1);
1293 static void readttfhhea(FILE *ttf
,struct ttfinfo
*info
) {
1294 /* Here I want ascent, descent and the number of horizontal metrics */
1297 fseek(ttf
,info
->hhea_start
+4,SEEK_SET
); /* skip over the version number */
1298 info
->pfminfo
.hhead_ascent
= getushort(ttf
);
1299 info
->pfminfo
.hhead_descent
= (short) getushort(ttf
);
1300 info
->pfminfo
.hheadascent_add
= info
->pfminfo
.hheaddescent_add
= false;
1301 info
->pfminfo
.linegap
= getushort(ttf
);
1302 info
->pfminfo
.hheadset
= true;
1303 /*info->ascent = info->pfminfo.hhead_ascent;*/
1305 for ( i
=0; i
<12; ++i
)
1307 info
->width_cnt
= getushort(ttf
);
1310 static void readttfmaxp(FILE *ttf
,struct ttfinfo
*info
) {
1311 /* All I want here is the number of glyphs */
1313 fseek(ttf
,info
->maxp_start
+4,SEEK_SET
); /* skip over the version number */
1314 cnt
= getushort(ttf
);
1315 if ( info
->glyph_cnt
==0 && info
->glyph_length
==0 && info
->loca_length
<=4 &&
1316 info
->cff_length
==0 && info
->typ1_start
==0 ) {
1317 /* X11 OpenType bitmap format */;
1318 info
->onlystrikes
= true;
1319 } else if ( cnt
!=info
->glyph_cnt
&& info
->loca_length
!=0 ) {
1320 ff_post_notice(_("Bad Glyph Count"), _("Font file has bad glyph count field. maxp says: %d sizeof(loca)=>%d"), cnt
, info
->glyph_cnt
);
1321 info
->bad_glyph_data
= true;
1322 if ( cnt
>info
->glyph_cnt
)
1323 cnt
= info
->glyph_cnt
; /* Use the smaller of the two values */
1325 /* Open Type fonts have no loca table, so we can't calculate the glyph */
1327 info
->glyph_cnt
= cnt
;
1328 if ( cnt
<0 ) info
->glyph_cnt
= 0;
1331 static char *stripspaces(char *str
) {
1332 char *str2
= str
, *base
= str
;
1347 static void ValidatePostScriptFontName(struct ttfinfo
*info
, char *str
) {
1348 char *end
, *pt
, *npt
;
1349 int complained
= false;
1351 /* someone gave me a font where the fontname started with the utf8 byte */
1352 /* order mark. PLRM says only ASCII encoding is supported. CFF says */
1353 /* only printable ASCII should be used */
1354 if ( ((uint8
*) str
)[0] == 0xef && ((uint8
*) str
)[1]==0xbb && ((uint8
*) str
)[2] == 0xbf ) {
1355 LogError(_("The fontname begins with the utf8 byte order sequence. This is illegal. %s"), str
+3 );
1356 info
->bad_ps_fontname
= true;
1357 for ( pt
=str
+3; *pt
; ++pt
)
1358 pt
[-3] = *pt
; /* ANSI says we can't strcpy overlapping strings */
1361 if ( (*end
=='\0' || (isdigit(str
[0]) && strchr(str
,'#')!=NULL
)) &&
1363 ff_post_error(_("Bad Font Name"),_("A Postscript name may not be a number"));
1364 info
->bad_ps_fontname
= true;
1368 for ( pt
=str
; *pt
; ++pt
) {
1369 if ( *pt
<=' ' || *pt
>=0x7f ||
1370 *pt
=='(' || *pt
=='[' || *pt
=='{' || *pt
=='<' ||
1371 *pt
==')' || *pt
==']' || *pt
=='}' || *pt
=='>' ||
1372 *pt
=='%' || *pt
=='/' ) {
1373 if ( !complained
) {
1374 ff_post_error(_("Bad Font Name"),_("The Postscript font name \"%.63s\" is invalid.\nIt should be printable ASCII,\nmust not contain (){}[]<>%%/ or space\nand must be shorter than 63 characters"),str
);
1375 info
->bad_ps_fontname
= true;
1378 for ( npt
=pt
; npt
[1]; ++npt
)
1384 if ( strlen(str
)>63 ) {
1385 ff_post_error(_("Bad Font Name"),_("The Postscript font name \"%.63s\" is invalid.\nIt should be printable ASCII,\nmust not contain (){}[]<>%%/ or space\nand must be shorter than 63 characters"),str
);
1386 info
->bad_ps_fontname
= true;
1391 char *EnforcePostScriptName(char *old
) {
1392 char *end
, *pt
, *npt
, *str
= copy(old
);
1398 if ( (*end
=='\0' || (isdigit(str
[0]) && strchr(str
,'#')!=NULL
)) &&
1401 str
=galloc(strlen(old
)+2);
1405 for ( pt
=str
; *pt
; ++pt
) {
1406 if ( *pt
<=' ' || *pt
>=0x7f ||
1407 *pt
=='(' || *pt
=='[' || *pt
=='{' || *pt
=='<' ||
1408 *pt
==')' || *pt
==']' || *pt
=='}' || *pt
=='>' ||
1409 *pt
=='%' || *pt
=='/' ) {
1410 for ( npt
=pt
; npt
[1]; ++npt
)
1415 if ( strlen(str
)>63 )
1420 static int IsSubSetOf(const char *substr
,const char *fullstr
) {
1421 /* The mac string is often a subset of the unicode string. Certain */
1422 /* characters can't be expressed in the mac encoding and are omitted */
1423 /* or turned to question marks or some such */
1424 const char *pt1
, *pt2
;
1427 for ( pt1
=substr
, pt2
=fullstr
, ch1
=utf8_ildb(&pt1
); ch1
!=0 ; ) {
1430 ch2
= utf8_ildb(&pt2
);
1432 ch1
= utf8_ildb(&pt1
);
1437 for ( pt1
=substr
, pt2
=fullstr
, ch1
=utf8_ildb(&pt1
); ch1
!=0 ; ) {
1440 ch2
= utf8_ildb(&pt2
);
1441 if ( ch1
==ch2
|| ch1
=='?' )
1442 ch1
= utf8_ildb(&pt1
);
1444 return( ch1
=='\0' );
1447 static void TTFAddLangStr(FILE *ttf
, struct ttfinfo
*info
, int id
,
1448 int strlen
, int stroff
,int plat
,int spec
,int language
) {
1449 struct ttflangname
*cur
, *prev
;
1452 if ( id
<0 || id
>=ttf_namemax
)
1455 str
= _readencstring(ttf
,stroff
,strlen
,plat
,spec
,language
);
1456 if ( str
==NULL
) /* we didn't understand the encoding */
1458 if ( id
==ttf_postscriptname
)
1459 ValidatePostScriptFontName(info
,str
);
1465 if ( plat
==1 || plat
==0 )
1466 language
= WinLangFromMac(language
);
1467 if ( (language
&0xff00)==0 ) language
|= 0x400;
1469 for ( prev
=NULL
, cur
=info
->names
; cur
!=NULL
&& cur
->lang
!=language
; prev
= cur
, cur
=cur
->next
);
1471 cur
= chunkalloc(sizeof(struct ttflangname
));
1472 cur
->lang
= language
;
1478 if ( cur
->names
[id
]==NULL
) {
1479 cur
->names
[id
] = str
;
1480 if ( plat
==1 || plat
==0 )
1481 cur
->frommac
[id
/32] |= (1<<(id
&0x1f));
1482 /* There's some wacky bug in gcc. If the optimizer is on then strcmp gets turned */
1483 /* into some inline call. Which would be fine, except the following line goes */
1484 /* bluey. "Called object is not a function", etc. Compiles fine if we turn off */
1485 /* the inlining magic */
1489 } else if ( strcmp(str
,cur
->names
[id
])==0 ) {
1492 cur
->frommac
[id
/32] &= ~(1<<(id
&0x1f));
1493 } else if ( plat
==1 ) {
1494 /* Mac string doesn't match mac unicode string */
1495 if ( !IsSubSetOf(str
,cur
->names
[id
]) )
1496 LogError( _("Warning: Mac and Unicode entries in the 'name' table differ for the\n %s string in the language %s\n Mac String: %s\nMac Unicode String: %s\n"),
1497 TTFNameIds(id
),MSLangString(language
),
1498 str
,cur
->names
[id
]);
1500 LogError( _("Warning: Mac string is a subset of the Unicode string in the 'name' table\n for the %s string in the %s language.\n"),
1501 TTFNameIds(id
),MSLangString(language
));
1503 } else if ( plat
==3 && (cur
->frommac
[id
/32] & (1<<(id
&0x1f))) ) {
1504 if ( !IsSubSetOf(cur
->names
[id
],str
) )
1505 LogError( _("Warning: Mac and Windows entries in the 'name' table differ for the\n %s string in the language %s\n Mac String: %s\nWindows String: %s\n"),
1506 TTFNameIds(id
),MSLangString(language
),
1507 cur
->names
[id
],str
);
1509 LogError( _("Warning: Mac string is a subset of the Windows string in the 'name' table\n for the %s string in the %s language.\n"),
1510 TTFNameIds(id
),MSLangString(language
));
1511 free(cur
->names
[id
]);
1512 cur
->names
[id
] = str
;
1513 cur
->frommac
[id
/32] &= ~(1<<(id
&0x1f));
1516 if ( info
->dupnamestate
!=0 )
1517 ret
= info
->dupnamestate
;
1520 if ( ret
==0 || ret
==1 )
1523 free(cur
->names
[id
]);
1524 cur
->names
[id
] = str
;
1529 static int is_ascii(char *str
) { /* isascii is in ctype */
1532 while ( *str
&& *str
<127 && *str
>=' ' )
1534 return( *str
=='\0' );
1537 static char *FindLangEntry(struct ttfinfo
*info
, int id
) {
1538 /* Look for an entry with string id */
1539 /* we prefer english, if we can't find english look for something in ascii */
1540 struct ttflangname
*cur
;
1543 for ( cur
=info
->names
; cur
!=NULL
&& cur
->lang
!=0x409; cur
=cur
->next
);
1544 if ( cur
!=NULL
&& cur
->names
[id
]==NULL
) cur
= NULL
;
1546 for ( cur
=info
->names
; cur
!=NULL
&& (cur
->lang
&0xf)!=0x09; cur
=cur
->next
);
1547 if ( cur
!=NULL
&& cur
->names
[id
]==NULL
) cur
= NULL
;
1549 for ( cur
=info
->names
; cur
!=NULL
&& !is_ascii(cur
->names
[id
]); cur
=cur
->next
);
1551 for ( cur
=info
->names
; cur
!=NULL
&& cur
->names
[id
]==NULL
; cur
=cur
->next
);
1554 ret
= copy(cur
->names
[id
]);
1558 struct otfname
*FindAllLangEntries(FILE *ttf
, struct ttfinfo
*info
, int id
) {
1559 /* Look for all entries with string id under windows platform */
1560 int32 here
= ftell(ttf
);
1561 int i
, cnt
, tableoff
;
1562 int platform
, specific
, language
, name
, str_len
, stroff
;
1563 struct otfname
*head
=NULL
, *cur
;
1565 if ( info
->copyright_start
!=0 && id
!=0 ) {
1566 fseek(ttf
,info
->copyright_start
,SEEK_SET
);
1567 /* format selector = */ getushort(ttf
);
1568 cnt
= getushort(ttf
);
1569 tableoff
= info
->copyright_start
+getushort(ttf
);
1570 for ( i
=0; i
<cnt
; ++i
) {
1571 platform
= getushort(ttf
);
1572 specific
= getushort(ttf
);
1573 language
= getushort(ttf
);
1574 name
= getushort(ttf
);
1575 str_len
= getushort(ttf
);
1576 stroff
= getushort(ttf
);
1578 if ( platform
==3 && name
==id
) {
1579 char *temp
= _readencstring(ttf
,tableoff
+stroff
,str_len
,platform
,specific
,language
);
1581 cur
= chunkalloc(sizeof(struct otfname
));
1584 cur
->lang
= language
;
1589 fseek(ttf
,here
,SEEK_SET
);
1594 static void readttfcopyrights(FILE *ttf
,struct ttfinfo
*info
) {
1595 int i
, cnt
, tableoff
;
1596 int platform
, specific
, language
, name
, str_len
, stroff
;
1598 if ( info
->copyright_start
!=0 ) {
1599 fseek(ttf
,info
->copyright_start
,SEEK_SET
);
1600 /* format selector = */ getushort(ttf
);
1601 cnt
= getushort(ttf
);
1602 tableoff
= info
->copyright_start
+getushort(ttf
);
1603 for ( i
=0; i
<cnt
; ++i
) {
1604 platform
= getushort(ttf
);
1605 specific
= getushort(ttf
);
1606 language
= getushort(ttf
);
1607 name
= getushort(ttf
);
1608 str_len
= getushort(ttf
);
1609 stroff
= getushort(ttf
);
1611 TTFAddLangStr(ttf
,info
,name
,str_len
,tableoff
+stroff
,
1612 platform
,specific
,language
);
1616 if ( info
->copyright
==NULL
)
1617 info
->copyright
= FindLangEntry(info
,ttf_copyright
);
1618 if ( info
->familyname
==NULL
)
1619 info
->familyname
= FindLangEntry(info
,ttf_family
);
1620 if ( info
->fullname
==NULL
)
1621 info
->fullname
= FindLangEntry(info
,ttf_fullname
);
1622 if ( info
->version
==NULL
)
1623 info
->version
= FindLangEntry(info
,ttf_version
);
1624 if ( info
->fontname
==NULL
)
1625 info
->fontname
= FindLangEntry(info
,ttf_postscriptname
);
1627 if ( info
->fontname
!= NULL
&& *info
->fontname
=='\0' ) {
1628 free(info
->fontname
);
1629 info
->fontname
= NULL
;
1631 if ( info
->familyname
!= NULL
&& *info
->familyname
=='\0' ) {
1632 free(info
->familyname
);
1633 info
->familyname
= NULL
;
1635 if ( info
->fullname
!= NULL
&& *info
->fullname
=='\0' ) {
1636 free(info
->fullname
);
1637 info
->fullname
= NULL
;
1640 /* OpenType spec says the version string should begin with "Version " and */
1641 /* end with a space and have a number in between */
1642 if ( info
->version
==NULL
) info
->version
= copy("1.0");
1643 else if ( strnmatch(info
->version
,"Version ",8)==0 ) {
1644 char *temp
= copy(info
->version
+8);
1645 if ( temp
[strlen(temp
)-1]==' ' )
1646 temp
[strlen(temp
)-1] = '\0';
1647 free(info
->version
);
1648 info
->version
= temp
;
1650 if ( info
->fontname
==NULL
) {
1651 if ( info
->fullname
!=NULL
)
1652 info
->fontname
= stripspaces(copy(info
->fullname
));
1653 if ( info
->fontname
==NULL
&& info
->familyname
!=NULL
)
1654 info
->fontname
= stripspaces(copy(info
->familyname
));
1655 if ( info
->fontname
!=NULL
)
1656 ValidatePostScriptFontName(info
,info
->fontname
);
1660 static void readttfpreglyph(FILE *ttf
,struct ttfinfo
*info
) {
1661 if ( info
->head_start
!=0 )
1662 readttfhead(ttf
,info
);
1663 if ( info
->hhea_start
!=0 )
1664 readttfhhea(ttf
,info
);
1665 if ( info
->maxp_start
!=0 )
1666 readttfmaxp(ttf
,info
);
1667 readttfcopyrights(ttf
,info
); /* This one has internal checks */
1674 #define _X_Same 0x10
1675 #define _Y_Same 0x20
1677 static void FigureControls(SplinePoint
*from
, SplinePoint
*to
, BasePoint
*cp
,
1679 /* What are the control points for 2 cp bezier which will provide the same*/
1680 /* curve as that for the 1 cp bezier specified above */
1684 from
->nextcp
= to
->prevcp
= *cp
;
1685 if ( cp
->x
==to
->me
.x
&& cp
->y
==to
->me
.y
) {
1686 /* I would lose track of the proper location of this cp if I left */
1687 /* it here (would end up with from->nonextcp, which would mean I'd*/
1688 /* use from->me rather than to->me in tottf.c:SSAddPoints. So we */
1689 /* distort it a little */
1692 off
.x
= from
->me
.x
-to
->me
.x
; off
.y
= from
->me
.y
-to
->me
.y
;
1693 len
= sqrt(off
.x
*off
.x
+off
.y
*off
.y
);
1695 /* move the cp slightly toward from, but on the line between the two */
1696 from
->nextcp
.x
= (to
->prevcp
.x
+= rint(off
.x
/len
));
1697 from
->nextcp
.y
= (to
->prevcp
.y
+= rint(off
.y
/len
));
1702 c
= 2*cp
->x
- 2*from
->me
.x
;
1703 b
= to
->me
.x
+from
->me
.x
-2*cp
->x
;
1704 from
->nextcp
.x
= d
+c
/3;
1705 to
->prevcp
.x
= from
->nextcp
.x
+ (c
+b
)/3;
1708 c
= 2*cp
->y
- 2*from
->me
.y
;
1709 b
= to
->me
.y
+from
->me
.y
-2*cp
->y
;
1710 from
->nextcp
.y
= d
+c
/3;
1711 to
->prevcp
.y
= from
->nextcp
.y
+ (c
+b
)/3;
1714 if ( from
->me
.x
!=from
->nextcp
.x
|| from
->me
.y
!=from
->nextcp
.y
)
1715 from
->nonextcp
= false;
1716 if ( to
->me
.x
!=to
->prevcp
.x
|| to
->me
.y
!=to
->prevcp
.y
)
1717 to
->noprevcp
= false;
1718 if ( is_order2
&& (to
->noprevcp
|| from
->nonextcp
)) {
1719 to
->noprevcp
= from
->nonextcp
= true;
1720 from
->nextcp
= from
->me
;
1721 to
->prevcp
= to
->me
;
1725 static SplineSet
*ttfbuildcontours(int path_cnt
,uint16
*endpt
, char *flags
,
1726 BasePoint
*pts
, int is_order2
) {
1727 SplineSet
*head
=NULL
, *last
=NULL
, *cur
;
1728 int i
, path
, start
, last_off
;
1731 for ( path
=i
=0; path
<path_cnt
; ++path
) {
1732 if ( endpt
[path
]<i
) /* Sigh. Yes there are fonts with bad endpt info */
1734 cur
= chunkalloc(sizeof(SplineSet
));
1743 while ( i
<=endpt
[path
] ) {
1744 if ( flags
[i
]&_On_Curve
) {
1745 sp
= chunkalloc(sizeof(SplinePoint
));
1746 sp
->me
= sp
->nextcp
= sp
->prevcp
= pts
[i
];
1747 sp
->nonextcp
= sp
->noprevcp
= true;
1749 sp
->nextcpindex
= 0xffff;
1750 if ( last_off
&& cur
->last
!=NULL
)
1751 FigureControls(cur
->last
,sp
,&pts
[i
-1],is_order2
);
1753 } else if ( last_off
) {
1754 /* two off curve points get a third on curve point created */
1755 /* half-way between them. Now isn't that special */
1756 sp
= chunkalloc(sizeof(SplinePoint
));
1757 sp
->me
.x
= (pts
[i
].x
+pts
[i
-1].x
)/2;
1758 sp
->me
.y
= (pts
[i
].y
+pts
[i
-1].y
)/2;
1759 sp
->nextcp
= sp
->prevcp
= sp
->me
;
1760 sp
->nonextcp
= true;
1761 sp
->ttfindex
= 0xffff;
1762 sp
->nextcpindex
= i
;
1763 if ( last_off
&& cur
->last
!=NULL
)
1764 FigureControls(cur
->last
,sp
,&pts
[i
-1],is_order2
);
1765 /* last_off continues to be true */
1767 if ( cur
->first
!=NULL
)
1768 cur
->last
->nextcpindex
= i
;
1773 if ( cur
->first
==NULL
)
1776 SplineMake(cur
->last
,sp
,is_order2
);
1782 /* MS chinese fonts have contours consisting of a single off curve*/
1783 /* point. What on earth do they think that means? */
1784 /* Oh. I see. It's used to possition marks and such */
1785 if ( cur
->first
==NULL
) {
1786 sp
= chunkalloc(sizeof(SplinePoint
));
1787 sp
->me
.x
= pts
[start
].x
;
1788 sp
->me
.y
= pts
[start
].y
;
1789 sp
->nextcp
= sp
->prevcp
= sp
->me
;
1790 sp
->nonextcp
= sp
->noprevcp
= true;
1792 sp
->nextcpindex
= 0xffff;
1793 cur
->first
= cur
->last
= sp
;
1795 } else if ( !(flags
[start
]&_On_Curve
) && !(flags
[i
-1]&_On_Curve
) ) {
1796 sp
= chunkalloc(sizeof(SplinePoint
));
1797 sp
->me
.x
= (pts
[start
].x
+pts
[i
-1].x
)/2;
1798 sp
->me
.y
= (pts
[start
].y
+pts
[i
-1].y
)/2;
1799 sp
->nextcp
= sp
->prevcp
= sp
->me
;
1800 sp
->nonextcp
= true;
1801 sp
->ttfindex
= 0xffff;
1802 sp
->nextcpindex
= start
;
1803 FigureControls(cur
->last
,sp
,&pts
[i
-1],is_order2
);
1804 SplineMake(cur
->last
,sp
,is_order2
);
1806 FigureControls(sp
,cur
->first
,&pts
[start
],is_order2
);
1807 } else if ( !(flags
[i
-1]&_On_Curve
)) {
1808 FigureControls(cur
->last
,cur
->first
,&pts
[i
-1],is_order2
);
1809 cur
->last
->nextcpindex
= i
-1;
1810 } else if ( !(flags
[start
]&_On_Curve
) ) {
1811 FigureControls(cur
->last
,cur
->first
,&pts
[start
],is_order2
);
1812 sp
->nextcpindex
= start
;
1814 if ( cur
->last
!=cur
->first
) {
1815 SplineMake(cur
->last
,cur
->first
,is_order2
);
1816 cur
->last
= cur
->first
;
1818 for ( sp
=cur
->first
; ; ) {
1819 /*if ( sp->ttfindex!=0xffff && SPInterpolate(sp) )
1820 sp->dontinterpolate = true;*/ /* TODO: needs checking */
1821 if ( sp
->next
==NULL
)
1824 if ( sp
==cur
->first
)
1831 static void readttfsimpleglyph(FILE *ttf
,struct ttfinfo
*info
,SplineChar
*sc
, int path_cnt
) {
1832 uint16
*endpt
= galloc((path_cnt
+1)*sizeof(uint16
));
1833 uint8
*instructions
;
1839 for ( i
=0; i
<path_cnt
; ++i
) {
1840 endpt
[i
] = getushort(ttf
);
1841 if ( i
!=0 && endpt
[i
]<endpt
[i
-1] ) {
1842 info
->bad_glyph_data
= true;
1843 LogError( _("Bad tt font: contour ends make no sense in glyph %d.\n"),
1848 if ( path_cnt
==0 ) {
1850 pts
= galloc(sizeof(BasePoint
));
1852 tot
= endpt
[path_cnt
-1]+1;
1853 pts
= galloc(tot
*sizeof(BasePoint
));
1856 len
= getushort(ttf
);
1857 instructions
= galloc(len
);
1858 for ( i
=0; i
<len
; ++i
)
1859 instructions
[i
] = getc(ttf
);
1861 flags
= galloc(tot
);
1862 for ( i
=0; i
<tot
; ++i
) {
1863 flags
[i
] = getc(ttf
);
1864 if ( flags
[i
]&_Repeat
) {
1865 int cnt
= getc(ttf
);
1867 IError("Flag count is wrong (or total is): %d %d", i
+cnt
, tot
);
1870 for ( j
=0; j
<cnt
; ++j
)
1871 flags
[i
+j
+1] = flags
[i
];
1878 IError("Flag count is wrong (or total is): %d %d in glyph %d", i
, tot
, sc
->orig_pos
);
1881 for ( i
=0; i
<tot
; ++i
) {
1882 if ( flags
[i
]&_X_Short
) {
1883 int off
= getc(ttf
);
1884 if ( !(flags
[i
]&_X_Same
) )
1886 pts
[i
].x
= last_pos
+ off
;
1887 } else if ( flags
[i
]&_X_Same
)
1888 pts
[i
].x
= last_pos
;
1890 pts
[i
].x
= last_pos
+ (short) getushort(ttf
);
1891 last_pos
= pts
[i
].x
;
1895 for ( i
=0; i
<tot
; ++i
) {
1896 if ( flags
[i
]&_Y_Short
) {
1897 int off
= getc(ttf
);
1898 if ( !(flags
[i
]&_Y_Same
) )
1900 pts
[i
].y
= last_pos
+ off
;
1901 } else if ( flags
[i
]&_Y_Same
)
1902 pts
[i
].y
= last_pos
;
1904 pts
[i
].y
= last_pos
+ (short) getushort(ttf
);
1905 last_pos
= pts
[i
].y
;
1908 sc
->layers
[ly_fore
].splines
= ttfbuildcontours(path_cnt
,endpt
,flags
,pts
,info
->to_order2
);
1909 if ( info
->to_order2
&& len
!=0 ) {
1910 sc
->ttf_instrs_len
= len
;
1911 sc
->ttf_instrs
= instructions
;
1914 SCCatagorizePoints(sc
);
1919 LogError( _("Reached end of file when reading simple glyph\n") );
1920 info
->bad_glyph_data
= true;
1924 static void readttfcompositglyph(FILE *ttf
,struct ttfinfo
*info
,SplineChar
*sc
, int32 end
) {
1925 RefChar
*head
=NULL
, *last
=NULL
, *cur
=NULL
;
1926 int flags
=0, arg1
, arg2
;
1927 int use_my_metrics
=0;
1929 if ( ftell(ttf
)>=end
) {
1930 LogError( _("Empty composite %d\n"), sc
->orig_pos
);
1931 info
->bad_glyph_data
= true;
1936 if ( ftell(ttf
)>=end
) {
1937 LogError( _("Bad flags value, implied MORE components at end of glyph %d\n"), sc
->orig_pos
);
1938 info
->bad_glyph_data
= true;
1941 cur
= RefCharCreate();
1942 flags
= getushort(ttf
);
1943 cur
->orig_pos
= getushort(ttf
);
1944 if ( feof(ttf
) || cur
->orig_pos
>=info
->glyph_cnt
) {
1945 LogError(_("Reference to glyph %d out of bounds when parsing 'glyf' table.\n"), cur
->orig_pos
);
1946 info
->bad_glyph_data
= true;
1949 if ( info
->inuse
!=NULL
)
1950 info
->inuse
[cur
->orig_pos
] = true;
1951 if ( flags
&_ARGS_ARE_WORDS
) {
1952 arg1
= (short) getushort(ttf
);
1953 arg2
= (short) getushort(ttf
);
1955 arg1
= (signed char) getc(ttf
);
1956 arg2
= (signed char) getc(ttf
);
1958 cur
->use_my_metrics
= (flags
& _USE_MY_METRICS
) ? 1 : 0;
1959 if ( cur
->use_my_metrics
) {
1960 if ( use_my_metrics
) {
1961 LogError( _("Use-my-metrics flag set on at least two components in glyph %d\n"), sc
->orig_pos
);
1962 info
->bad_glyph_data
= true;
1964 use_my_metrics
= true;
1966 cur
->round_translation_to_grid
= (flags
& _ROUND
) ? 1 : 0;
1967 if ( flags
& _ARGS_ARE_XY
) {
1968 /* There is some very strange stuff (half-)documented on the apple*/
1969 /* site about how these should be interpretted when there are */
1970 /* scale factors, or rotations */
1971 /* It isn't well enough described to be comprehensible */
1972 /* http://fonts.apple.com/TTRefMan/RM06/Chap6glyf.html */
1973 /* Microsoft says nothing about this */
1974 /* Adobe implies this is a difference between MS and Apple */
1975 /* MS doesn't do this, Apple does (GRRRGH!!!!) */
1976 /* Adobe says that setting bit 12 means that this will not happen */
1977 /* Adobe says that setting bit 11 means that this will happen */
1978 /* So if either bit is set we know when this happens, if neither */
1979 /* we guess... But I still don't know how to interpret the */
1980 /* apple mode under rotation... */
1981 /* I notice that FreeType does nothing about rotation nor does it */
1982 /* interpret bits 11&12 */
1983 /* Ah. It turns out that even Apple does not do what Apple's docs */
1984 /* claim it does. I think I've worked it out (see below), but... */
1986 cur
->transform
[4] = arg1
;
1987 cur
->transform
[5] = arg2
;
1989 /* Somehow we can get offsets by looking at the points in the */
1990 /* points so far generated and comparing them to the points in */
1991 /* the current componant */
1992 /* How exactly is not described on any of the Apple, MS, Adobe */
1993 /* freetype looks up arg1 in the set of points we've got so far */
1994 /* looks up arg2 in the new component (before renumbering) */
1995 /* offset.x = arg1.x - arg2.x; offset.y = arg1.y - arg2.y; */
1996 /* This fixup needs to be done later though (after all glyphs */
1997 /* have been loaded) */
1998 cur
->match_pt_base
= arg1
;
1999 cur
->match_pt_ref
= arg2
;
2000 cur
->point_match
= true;
2002 cur
->transform
[0] = cur
->transform
[3] = 1.0;
2003 if ( flags
& _SCALE
)
2004 cur
->transform
[0] = cur
->transform
[3] = get2dot14(ttf
);
2005 else if ( flags
& _XY_SCALE
) {
2006 cur
->transform
[0] = get2dot14(ttf
);
2007 cur
->transform
[3] = get2dot14(ttf
);
2008 } else if ( flags
& _MATRIX
) {
2009 cur
->transform
[0] = get2dot14(ttf
);
2010 cur
->transform
[1] = get2dot14(ttf
);
2011 cur
->transform
[2] = get2dot14(ttf
);
2012 cur
->transform
[3] = get2dot14(ttf
);
2014 if ( flags
& _ARGS_ARE_XY
) { /* Only muck with these guys if they are real offsets and not point matching */
2016 /* On mac assume scaled offsets unless told unscaled explicitly */
2017 if ( !(flags
&_UNSCALED_OFFSETS
) &&
2019 /* everywhere else assume unscaled offsets unless told scaled explicitly */
2020 if ( (flags
& _SCALED_OFFSETS
) &&
2022 (flags
& _ARGS_ARE_XY
) && (flags
&(_SCALE
|_XY_SCALE
|_MATRIX
))) {
2023 /*static int asked = 0;*/
2024 /* This is not what Apple documents on their website. But it is */
2025 /* what appears to match the behavior of their rasterizer */
2026 /* Apple has changed their documentation (without updating their */
2027 /* changelog), but I believe they are still incorrect */
2028 cur
->transform
[4] *= sqrt(cur
->transform
[0]*cur
->transform
[0]+
2029 cur
->transform
[1]*cur
->transform
[1]);
2030 cur
->transform
[5] *= sqrt(cur
->transform
[2]*cur
->transform
[2]+
2031 cur
->transform
[3]*cur
->transform
[3]);
2033 /* Apple's Chicago is an example */
2034 if ( info
->fontname
!=NULL
&& strcmp(info
->fontname
,"CompositeMac")!=0 && !asked
) {
2035 /* Not interested in the test font I generated myself */
2037 fprintf( stderr
, "Neat! You've got a font that actually uses Apple's scaled composite offsets.\n" );
2038 fprintf( stderr
, " I've never seen one, could you send me a copy of %s?\n", info
->fontname
);
2039 fprintf( stderr
, " Thanks. gww@silcom.com\n" );
2044 if ( cur
->orig_pos
>=info
->glyph_cnt
) {
2045 LogError(_("Glyph %d attempts to reference glyph %d which is outside the font\n"), sc
->orig_pos
, cur
->orig_pos
);
2046 chunkfree(cur
,sizeof(*cur
));
2055 LogError(_("Reached end of file when reading composit glyph\n") );
2056 info
->bad_glyph_data
= true;
2059 } while ( flags
&_MORE
);
2060 if ( (flags
& _INSTR
) && info
->to_order2
&& ftell(ttf
)<end
) {
2061 sc
->ttf_instrs_len
= getushort(ttf
);
2062 if ( sc
->ttf_instrs_len
> 0 && ftell(ttf
)+sc
->ttf_instrs_len
<=end
) {
2063 uint8
*instructions
= galloc(sc
->ttf_instrs_len
);
2065 for ( i
=0; i
<sc
->ttf_instrs_len
; ++i
)
2066 instructions
[i
] = getc(ttf
);
2067 sc
->ttf_instrs
= instructions
;
2069 sc
->ttf_instrs_len
= 0;
2071 sc
->layers
[ly_fore
].refs
= head
;
2074 static SplineChar
*readttfglyph(FILE *ttf
,struct ttfinfo
*info
,int start
, int end
,int gid
) {
2076 SplineChar
*sc
= SplineCharCreate(2);
2078 sc
->unicodeenc
= -1;
2079 sc
->vwidth
= info
->emsize
;
2082 if ( end
>(int)info
->glyph_length
) {
2083 if ( !info
->complainedbeyondglyfend
)
2084 LogError(_("Bad glyph (%d), its definition extends beyond the end of the glyf table\n"), gid
);
2085 info
->bad_glyph_data
= true;
2086 info
->complainedbeyondglyfend
= true;
2089 } else if ( end
<start
) {
2090 LogError(_("Bad glyph (%d), its data length is negative\n"), gid
);
2096 /* This isn't mentioned, but we seem to get some glyphs with no size,*/
2097 /* not even a path cnt. They appear to be empty glyphs */
2100 fseek(ttf
,info
->glyph_start
+start
,SEEK_SET
);
2101 path_cnt
= (short) getushort(ttf
);
2104 sc
->xmin
= getushort(ttf
);
2105 sc
->ymin
= getushort(ttf
);
2106 sc
->xmax
= getushort(ttf
);
2107 sc
->ymax
= getushort(ttf
);
2108 sc
->lsidebearing
= sc
->xmin
;
2110 if (THread_ttf_glyph_data
) {
2112 readttfsimpleglyph(ttf
,info
,sc
,path_cnt
);
2114 readttfcompositglyph(ttf
,info
,sc
,info
->glyph_start
+end
);
2116 LogError(_("Bad glyph (%d), disordered 'loca' table (start comes after end)\n"), gid
);
2117 info
->bad_glyph_data
= true;
2118 } else if ( ftell(ttf
)>(long)(info
->glyph_start
+end
) ) {
2119 LogError(_("Bad glyph (%d), its definition extends beyond the space allowed for it\n"), gid
);
2120 info
->bad_glyph_data
= true;
2124 THPatchSplineChar(sc
);
2130 static void readttfencodings(FILE *ttf
,struct ttfinfo
*info
, int justinuse
);
2132 static void readttfglyphs(FILE *ttf
,struct ttfinfo
*info
) {
2134 uint32
*goffsets
= galloc((info
->glyph_cnt
+1)*sizeof(uint32
));
2136 /* First we read all the locations. This might not be needed, they may */
2137 /* just follow one another, but nothing I've noticed says that so let's */
2139 fseek(ttf
,info
->glyphlocations_start
,SEEK_SET
);
2140 if ( info
->index_to_loc_is_long
) {
2141 for ( i
=0; i
<=info
->glyph_cnt
; ++i
)
2142 goffsets
[i
] = getlong(ttf
);
2144 for ( i
=0; i
<=info
->glyph_cnt
; ++i
)
2145 goffsets
[i
] = 2*getushort(ttf
);
2148 info
->chars
= gcalloc(info
->glyph_cnt
,sizeof(SplineChar
*));
2149 if ( !info
->is_ttc
|| (info
->openflags
&of_all_glyphs_in_ttc
)) {
2150 /* read all the glyphs */
2151 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
2152 info
->chars
[i
] = readttfglyph(ttf
,info
,goffsets
[i
],goffsets
[i
+1],i
);
2156 /* only read the glyphs we actually use in this font */
2157 /* this is complicated by references (and substitutions), */
2158 /* we can't just rely on the encoding to tell us what is used */
2159 info
->inuse
= gcalloc(info
->glyph_cnt
,sizeof(char));
2160 readttfencodings(ttf
,info
,git_justinuse
);
2161 if ( info
->gsub_start
!=0 ) /* Some glyphs may appear in substitutions and not in the encoding... */
2162 readttfgsubUsed(ttf
,info
);
2163 if ( info
->math_start
!=0 )
2164 otf_read_math_used(ttf
,info
);
2165 /* I don't bother to read the morx table because mac doesn't */
2166 /* support ttc files */
2170 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
2171 if ( info
->inuse
[i
] && info
->chars
[i
]==NULL
) {
2172 info
->chars
[i
] = readttfglyph(ttf
,info
,goffsets
[i
],goffsets
[i
+1],i
);
2174 anyread
= info
->chars
[i
]!=NULL
;
2178 free(info
->inuse
); info
->inuse
= NULL
;
2181 for ( i
=0; i
<info
->glyph_cnt
; ++i
)
2182 if ( info
->chars
[i
]!=NULL
)
2183 info
->chars
[i
]->orig_pos
= i
;
2184 ff_progress_next_stage();
2187 /* Standard names for cff */
2188 const char *cffnames
[] = {
2419 "Hungarumlautsmall",
2424 "parenleftsuperior",
2425 "parenrightsuperior",
2439 "threequartersemdash",
2458 "parenleftinferior",
2459 "parenrightinferior",
2508 "questiondownsmall",
2582 const int nStdStrings
= sizeof(cffnames
)/sizeof(cffnames
[0])-1;
2584 static char **readcfffontnames(FILE *ttf
,int *cnt
,struct ttfinfo
*info
) {
2585 uint16 count
= getushort(ttf
);
2591 if ( cnt
!=NULL
) *cnt
= count
;
2595 offsets
= galloc((count
+1)*sizeof(uint32
));
2596 offsize
= getc(ttf
);
2597 for ( i
=0; i
<=count
; ++i
)
2598 offsets
[i
] = getoffset(ttf
,offsize
);
2599 names
= galloc((count
+1)*sizeof(char *));
2600 for ( i
=0; i
<count
; ++i
) {
2601 if ( offsets
[i
+1]<offsets
[i
] ) {
2602 /* GT: The CFF font type contains a thing called a name INDEX, and that INDEX */
2603 /* GT: is bad. It is an index of many of the names used in the CFF font. */
2604 /* GT: We hope the user will never see this. */
2605 LogError( _("Bad CFF name INDEX\n") );
2606 if ( info
!=NULL
) info
->bad_cff
= true;
2608 names
[i
] = copy("");
2613 names
[i
] = galloc(offsets
[i
+1]-offsets
[i
]+1);
2614 for ( j
=0; j
<(int)(offsets
[i
+1]-offsets
[i
]); ++j
)
2615 names
[i
][j
] = getc(ttf
);
2624 static char *addnibble(char *pt
, int nib
) {
2631 else if ( nib
==12 ) {
2634 } else if ( nib
==14 )
2641 static int readcffthing(FILE *ttf
,int *_ival
,real
*dval
,int *operand
,struct ttfinfo
*info
) {
2642 char buffer
[50], *pt
;
2647 *operand
= (12<<8) | getc(ttf
);
2649 } else if ( ch
<=21 ) {
2652 } else if ( ch
==30 ) {
2653 /* fixed format doesn't exist in dict data but does in type2 strings */
2657 if ( pt
<buffer
+44 || (ch
&0xf)==0xf || (ch
&0xf0)==0xf0 ) {
2658 pt
= addnibble(pt
,ch
>>4);
2659 pt
= addnibble(pt
,ch
&0xf);
2661 } while ( pt
[-1]!='\0' );
2662 *dval
= strtod(buffer
,NULL
);
2664 } else if ( ch
>=32 && ch
<=246 ) {
2667 } else if ( ch
>=247 && ch
<=250 ) {
2668 *_ival
= ((ch
-247)<<8) + getc(ttf
)+108;
2670 } else if ( ch
>=251 && ch
<=254 ) {
2671 *_ival
= -((ch
-251)<<8) - getc(ttf
)-108;
2673 } else if ( ch
==28 ) {
2674 ival
= getc(ttf
)<<8;
2675 *_ival
= (short) (ival
| getc(ttf
));
2677 } else if ( ch
==29 ) {
2678 /* 4 byte integers exist in dict data but not in type2 strings */
2679 ival
= getc(ttf
)<<24;
2680 ival
= ival
| getc(ttf
)<<16;
2681 ival
= ival
| getc(ttf
)<<8;
2682 *_ival
= (int) (ival
| getc(ttf
));
2685 LogError(_("Unexpected value in dictionary %d\n"), ch
);
2686 info
->bad_cff
= true;
2691 static void skipcfft2thing(FILE *ttf
) {
2692 /* The old CFF spec allows little type2 programs to live in the CFF dict */
2693 /* indices. These are designed to allow interpolation of values for mm */
2695 /* The Type2 program is terminated by an "endchar" operator */
2696 /* I don't support this, but I shall try to skip over them properly */
2697 /* There's no discussion about how values move from the t2 stack to the */
2698 /* cff stack, as there are no examples of this, it's hard to guess */
2701 /* GT: DICT is a magic term inside CFF fonts, as is INDEX, and I guess CFF and type2 */
2702 LogError( _("FontForge does not support type2 programs embedded in CFF DICT INDICES.\n") );
2705 if ( ch
>=247 && ch
<=254 )
2706 getc(ttf
); /* Two byte number */
2707 else if ( ch
==255 ) {
2708 getc(ttf
); getc(ttf
); getc(ttf
); getc(ttf
);
2710 } else if ( ch
==28 ) {
2713 } else if ( ch
==12 ) {
2714 getc(ttf
); /* Two byte operator */
2715 } else if ( ch
==14 ) {
2724 char *fontname
; /* From Name Index */
2726 int version
; /* SID */
2727 int notice
; /* SID */
2728 int copyright
; /* SID */
2729 int fullname
; /* SID */
2730 int familyname
; /* SID */
2731 int weight
; /* SID */
2735 real underlinewidth
;
2744 int charsetoff
; /* from start of file */
2745 int encodingoff
; /* from start of file */
2746 int charstringsoff
; /* from start of file */
2748 int private_offset
; /* from start of file */
2749 int synthetic_base
; /* font index */
2750 int postscript_code
; /* SID */
2751 /* synthetic fonts only (whatever they are) */
2752 int basefontname
; /* SID */
2753 /* Multiple master/synthetic fonts */
2754 real basefontblend
[16]; /* delta */ /* No description of why this is relevant for mm fonts */
2755 /* Multiple master fonts only */
2756 int blendaxistypes
[17]; /* SID */
2759 real weightvector
[17];
2760 int lenBuildCharArray
; /* No description of what this means */
2761 int NormalizeDesignVector
; /* SID */ /* No description of what this does */
2762 int ConvertDesignVector
; /* SID */ /* No description of what this does */
2763 /* CID fonts only */
2764 int ros_registry
; /* SID */
2765 int ros_ordering
; /* SID */
2767 real cidfontversion
;
2768 int cidfontrevision
;
2772 int fdarrayoff
; /* from start of file */
2773 int fdselectoff
; /* from start of file */
2774 int sid_fontname
; /* SID */
2776 real bluevalues
[14];
2777 real otherblues
[10];
2778 real familyblues
[14];
2779 real familyotherblues
[10];
2788 real forceboldthreshold
;
2790 real expansionfactor
;
2791 int initialRandomSeed
;
2792 int subrsoff
; /* from start of this private table */
2796 struct pschars glyphs
;
2797 struct pschars local_subrs
;
2801 static void TopDictFree(struct topdicts
*dict
) {
2804 free(dict
->charset
);
2805 for ( i
=0; i
<dict
->glyphs
.cnt
; ++i
)
2806 free(dict
->glyphs
.values
[i
]);
2807 free(dict
->glyphs
.values
);
2808 free(dict
->glyphs
.lens
);
2809 for ( i
=0; i
<dict
->local_subrs
.cnt
; ++i
)
2810 free(dict
->local_subrs
.values
[i
]);
2811 free(dict
->local_subrs
.values
);
2812 free(dict
->local_subrs
.lens
);
2816 static void readcffsubrs(FILE *ttf
, struct pschars
*subs
, struct ttfinfo
*info
) {
2817 uint16 count
= getushort(ttf
);
2823 memset(subs
,'\0',sizeof(struct pschars
));
2827 subs
->lens
= galloc(count
*sizeof(int));
2828 subs
->values
= galloc(count
*sizeof(uint8
*));
2829 offsets
= galloc((count
+1)*sizeof(uint32
));
2830 offsize
= getc(ttf
);
2831 for ( i
=0; i
<=count
; ++i
)
2832 offsets
[i
] = getoffset(ttf
,offsize
);
2833 base
= ftell(ttf
)-1;
2834 for ( i
=0; i
<count
; ++i
) {
2835 if ( offsets
[i
+1]>offsets
[i
] && offsets
[i
+1]-offsets
[i
]<0x10000 ) {
2836 subs
->lens
[i
] = offsets
[i
+1]-offsets
[i
];
2837 subs
->values
[i
] = galloc(offsets
[i
+1]-offsets
[i
]+1);
2838 for ( j
=0; j
<(int)(offsets
[i
+1]-offsets
[i
]); ++j
)
2839 subs
->values
[i
][j
] = getc(ttf
);
2840 subs
->values
[i
][j
] = '\0';
2843 LogError( _("Bad subroutine INDEX in cff font.\n" ));
2844 info
->bad_cff
= true;
2847 subs
->values
[i
] = galloc(2);
2848 subs
->values
[i
][0] = 11; /* return */
2849 subs
->values
[i
][1] = '\0';
2850 fseek(ttf
,base
+offsets
[i
+1],SEEK_SET
);
2856 static struct topdicts
*readcfftopdict(FILE *ttf
, char *fontname
, int len
,
2857 struct ttfinfo
*info
) {
2858 struct topdicts
*td
= gcalloc(1,sizeof(struct topdicts
));
2859 long base
= ftell(ttf
);
2860 int ival
, oval
, sp
, ret
, i
;
2863 if ( fontname
!=NULL
)
2864 ValidatePostScriptFontName(info
,fontname
);
2866 td
->fontname
= fontname
;
2867 td
->underlinepos
= -100;
2868 td
->underlinewidth
= 50;
2869 td
->charstringtype
= 2;
2870 td
->fontmatrix
[0] = td
->fontmatrix
[3] = .001;
2872 td
->notice
= td
->copyright
= td
->fullname
= td
->familyname
= td
->weight
= td
->version
= -1;
2873 td
->postscript_code
= td
->basefontname
= -1;
2874 td
->synthetic_base
= td
->ros_registry
= -1;
2875 td
->fdarrayoff
= td
->fdselectoff
= td
->sid_fontname
= -1;
2876 td
->blendaxistypes
[0] = -1;
2878 /* Multiple master fonts can have Type2 operators here, particularly */
2879 /* blend operators. We're ignoring that */
2880 while ( ftell(ttf
)<base
+len
) {
2882 while ( (ret
=readcffthing(ttf
,&ival
,&stack
[sp
],&oval
,info
))!=3 && ftell(ttf
)<base
+len
) {
2885 if ( ret
!=0 && sp
<45 )
2888 if ( ret
==3 && oval
==31 /* "T2" operator, can have 0 arguments */ ) {
2889 skipcfft2thing(ttf
);
2890 } else if ( sp
==0 ) {
2891 LogError( _("No argument to operator\n") );
2892 info
->bad_cff
= true;
2893 } else if ( ret
==3 ) switch( oval
) {
2895 td
->version
= stack
[sp
-1];
2898 td
->notice
= stack
[sp
-1];
2901 td
->copyright
= stack
[sp
-1];
2904 td
->fullname
= stack
[sp
-1];
2907 td
->familyname
= stack
[sp
-1];
2910 td
->weight
= stack
[sp
-1];
2913 td
->isfixedpitch
= stack
[sp
-1];
2916 td
->italicangle
= stack
[sp
-1];
2919 td
->underlinepos
= stack
[sp
-1];
2922 td
->underlinewidth
= stack
[sp
-1];
2925 td
->painttype
= stack
[sp
-1];
2928 td
->charstringtype
= stack
[sp
-1];
2931 memcpy(td
->fontmatrix
,stack
,(sp
>=6?6:sp
)*sizeof(real
));
2932 td
->fontmatrix_set
= 1;
2935 td
->uniqueid
= stack
[sp
-1];
2938 memcpy(td
->fontbb
,stack
,(sp
>=4?4:sp
)*sizeof(real
));
2941 td
->strokewidth
= stack
[sp
-1];
2944 for ( i
=0; i
<sp
&& i
<20; ++i
)
2945 td
->xuid
[i
] = stack
[i
];
2948 td
->charsetoff
= stack
[sp
-1];
2951 td
->encodingoff
= stack
[sp
-1];
2954 td
->charstringsoff
= stack
[sp
-1];
2957 td
->private_size
= stack
[0];
2958 td
->private_offset
= stack
[1];
2961 LogError( _("FontForge does not support synthetic fonts\n") );
2962 td
->synthetic_base
= stack
[sp
-1];
2965 td
->postscript_code
= stack
[sp
-1];
2968 td
->basefontname
= stack
[sp
-1];
2971 for ( i
=0; i
<sp
&& i
<16; ++i
)
2972 td
->basefontblend
[i
] = stack
[i
];
2975 LogError( _("FontForge does not support type2 multiple master fonts\n") );
2976 info
->bad_cff
= true;
2977 td
->nMasters
= stack
[0];
2979 memcpy(td
->weightvector
,stack
+1,(sp
-4)*sizeof(real
));
2980 td
->lenBuildCharArray
= stack
[sp
-3];
2981 td
->NormalizeDesignVector
= stack
[sp
-2]; /* These are type2 charstrings, even in type1 fonts */
2982 td
->ConvertDesignVector
= stack
[sp
-1];
2985 for ( i
=0; i
<sp
&& i
<16; ++i
)
2986 td
->blendaxistypes
[i
] = stack
[i
];
2987 td
->blendaxistypes
[i
] = -1;
2990 td
->ros_registry
= stack
[0];
2991 td
->ros_ordering
= stack
[1];
2992 td
->ros_supplement
= stack
[2];
2995 td
->cidfontversion
= stack
[sp
-1];
2998 td
->cidfontrevision
= stack
[sp
-1];
3001 td
->cidfonttype
= stack
[sp
-1];
3004 td
->cidcount
= stack
[sp
-1];
3007 td
->uidbase
= stack
[sp
-1];
3010 td
->fdarrayoff
= stack
[sp
-1];
3013 td
->fdselectoff
= stack
[sp
-1];
3016 td
->sid_fontname
= stack
[sp
-1];
3019 LogError(_("FontForge does not support Chameleon fonts\n"));;
3022 LogError(_("Unknown operator in %s: %x\n"), fontname
, oval
);
3023 info
->bad_cff
= true;
3030 static void readcffprivate(FILE *ttf
, struct topdicts
*td
, struct ttfinfo
*info
) {
3031 int ival
, oval
, sp
, ret
, i
;
3033 int32 end
= td
->cff_start
+td
->private_offset
+td
->private_size
;
3035 fseek(ttf
,td
->cff_start
+td
->private_offset
,SEEK_SET
);
3038 td
->expansionfactor
= .06;
3041 td
->bluescale
= .039625;
3043 while ( ftell(ttf
)<end
) {
3045 LogError("End of file found when reading private dictionary.\n" );
3049 while ( (ret
=readcffthing(ttf
,&ival
,&stack
[sp
],&oval
,info
))!=3 && ftell(ttf
)<end
) {
3052 if ( ret
!=0 && sp
<45 )
3055 if ( ret
==3 && oval
==31 /* "T2" operator, can have 0 arguments */ ) {
3056 skipcfft2thing(ttf
);
3057 } else if ( sp
==0 && oval
!=6 && oval
!=7 && oval
!=8 && oval
!=9 && oval
!=(12<<8)+12 && oval
!=(12<<8)+13) {
3058 LogError( _("No argument to operator %d in private dict\n"), oval
);
3059 info
->bad_cff
= true;
3060 } else if ( ret
==3 ) switch( oval
) {
3062 for ( i
=0; i
<sp
&& i
<14; ++i
) {
3063 td
->bluevalues
[i
] = stack
[i
];
3065 td
->bluevalues
[i
] += td
->bluevalues
[i
-1];
3069 for ( i
=0; i
<sp
&& i
<10; ++i
) {
3070 td
->otherblues
[i
] = stack
[i
];
3072 td
->otherblues
[i
] += td
->otherblues
[i
-1];
3076 for ( i
=0; i
<sp
&& i
<14; ++i
) {
3077 td
->familyblues
[i
] = stack
[i
];
3079 td
->familyblues
[i
] += td
->familyblues
[i
-1];
3083 for ( i
=0; i
<sp
&& i
<10; ++i
) {
3084 td
->familyotherblues
[i
] = stack
[i
];
3086 td
->familyotherblues
[i
] += td
->familyotherblues
[i
-1];
3090 td
->bluescale
= stack
[sp
-1];
3093 td
->blueshift
= stack
[sp
-1];
3096 td
->bluefuzz
= stack
[sp
-1];
3099 td
->stdhw
= stack
[sp
-1];
3102 td
->stdvw
= stack
[sp
-1];
3105 for ( i
=0; i
<sp
&& i
<10; ++i
) {
3106 td
->stemsnaph
[i
] = stack
[i
];
3108 td
->stemsnaph
[i
] += td
->stemsnaph
[i
-1];
3112 for ( i
=0; i
<sp
&& i
<10; ++i
) {
3113 td
->stemsnapv
[i
] = stack
[i
];
3115 td
->stemsnapv
[i
] += td
->stemsnapv
[i
-1];
3119 td
->forcebold
= stack
[sp
-1];
3121 case (12<<8)+15: /* obsolete */
3122 td
->forceboldthreshold
= stack
[sp
-1];
3125 /* lenIV. -1 => unencrypted charstrings */
3129 td
->languagegroup
= stack
[sp
-1];
3132 td
->expansionfactor
= stack
[sp
-1];
3135 td
->initialRandomSeed
= stack
[sp
-1];
3138 td
->subrsoff
= stack
[sp
-1];
3141 td
->defaultwidthx
= stack
[sp
-1];
3144 td
->nominalwidthx
= stack
[sp
-1];
3147 LogError(_("Unknown operator in %s: %x\n"), td
->fontname
, oval
);
3148 info
->bad_cff
= true;
3153 if ( td
->subrsoff
!=-1 ) {
3154 fseek(ttf
,td
->cff_start
+td
->private_offset
+td
->subrsoff
,SEEK_SET
);
3155 readcffsubrs(ttf
,&td
->local_subrs
,info
);
3159 static struct topdicts
**readcfftopdicts(FILE *ttf
, char **fontnames
, int32 cff_start
,
3160 struct ttfinfo
*info
, struct topdicts
*parent_dict
) {
3161 uint16 count
= getushort(ttf
);
3164 struct topdicts
**dicts
;
3169 offsets
= galloc((count
+1)*sizeof(uint32
));
3170 offsize
= getc(ttf
);
3171 for ( i
=0; i
<=count
; ++i
)
3172 offsets
[i
] = getoffset(ttf
,offsize
);
3173 dicts
= galloc((count
+1)*sizeof(struct topdicts
*));
3174 for ( i
=0; i
<count
; ++i
) {
3175 dicts
[i
] = readcfftopdict(ttf
,fontnames
!=NULL
?fontnames
[i
]:NULL
,
3176 offsets
[i
+1]-offsets
[i
], info
);
3177 if ( parent_dict
!=NULL
&& parent_dict
->fontmatrix_set
) {
3178 MatMultiply(parent_dict
->fontmatrix
,dicts
[i
]->fontmatrix
,dicts
[i
]->fontmatrix
);
3180 dicts
[i
]->cff_start
= cff_start
;
3187 static const char *FFgetsid(int sid
,char **strings
,int scnt
,struct ttfinfo
*info
) {
3190 else if ( sid
<nStdStrings
)
3191 return( cffnames
[sid
] );
3192 else if ( sid
-nStdStrings
>scnt
) {
3193 LogError( _("Bad sid %d (must be less than %d)\n"), sid
, scnt
+nStdStrings
);
3194 if ( info
!=NULL
) info
->bad_cff
= true;
3197 return( strings
[sid
-nStdStrings
]);
3200 /* I really expect to deal with encodings in ttf cmap, but ocasionally we */
3201 /* get a bare cff */
3202 static void readcffenc(FILE *ttf
,struct topdicts
*dict
,struct ttfinfo
*info
,
3203 char **strings
, int scnt
) {
3204 int format
, cnt
, i
, j
, pos
, first
, last
, dupenc
, sid
;
3208 if ( info
->encoding_start
!=0 ) /* Use the cmap instead */
3210 if ( info
->subfontcnt
!=0 )
3211 return; /* Use cids instead */
3213 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
3214 if ( info
->chars
[i
]->unicodeenc
==-1 )
3215 info
->chars
[i
]->unicodeenc
= UniFromName(info
->chars
[i
]->name
,ui_none
,&custom
);
3218 map
= EncMapNew(256,256,&custom
);
3219 if ( dict
->encodingoff
==0 || dict
->encodingoff
==1 ) {
3220 /* Standard Encodings */
3221 char **enc
= dict
->encodingoff
==0 ? AdobeStandardEncoding
: AdobeExpertEncoding
;
3222 map
->enc
= FindOrMakeEncoding( dict
->encodingoff
==0 ?
3223 "AdobeStandard" : "Custom" );
3224 if ( map
->enc
==NULL
)
3226 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
3227 for ( pos
=0; pos
<256; ++pos
)
3228 if ( strcmp(info
->chars
[i
]->name
,enc
[pos
])==0 )
3234 fseek(ttf
,dict
->cff_start
+dict
->encodingoff
,SEEK_SET
);
3236 if ( (format
&0x7f)==0 ) {
3238 for ( i
=1; i
<=cnt
&& i
<info
->glyph_cnt
; ++i
)
3239 map
->map
[getc(ttf
)] = i
;
3240 } else if ( (format
&0x7f)==1 ) {
3243 for ( i
=0; i
<cnt
; ++i
) {
3245 last
= first
+ getc(ttf
)-1;
3246 while ( first
<=last
&& first
<256 ) {
3247 if ( pos
<info
->glyph_cnt
)
3248 map
->map
[first
] = pos
;
3254 LogError( _("Unexpected encoding format in cff: %d\n"), format
);
3255 if ( info
!=NULL
) info
->bad_cff
= true;
3257 if ( format
&0x80 ) {
3259 for ( i
=0; i
<cnt
; ++i
) {
3261 sid
= getushort(ttf
);
3262 name
= FFgetsid(sid
,strings
,scnt
,info
);
3263 if ( name
==NULL
) /* Table is erroneous */
3265 for ( j
=0; j
<info
->glyph_cnt
; ++j
)
3266 if ( strcmp(name
,info
->chars
[j
]->name
)==0 )
3268 if ( j
!=info
->glyph_cnt
)
3269 map
->map
[dupenc
] = j
;
3276 static void readcffset(FILE *ttf
,struct topdicts
*dict
,struct ttfinfo
*info
) {
3277 int len
= dict
->glyphs
.cnt
;
3279 int format
, cnt
, j
, first
;
3282 if ( dict
->charsetoff
==0 ) {
3283 /* ISO Adobe charset */
3284 dict
->charset
= galloc(len
*sizeof(uint16
));
3285 for ( i
=0; i
<len
&& i
<=228; ++i
)
3286 dict
->charset
[i
] = i
;
3287 } else if ( dict
->charsetoff
==1 ) {
3288 /* Expert charset */
3289 dict
->charset
= galloc((len
<162?162:len
)*sizeof(uint16
));
3290 dict
->charset
[0] = 0; /* .notdef */
3291 dict
->charset
[1] = 1;
3292 for ( i
=2; i
<len
&& i
<=238-227; ++i
)
3293 dict
->charset
[i
] = i
+227;
3294 dict
->charset
[12] = 13;
3295 dict
->charset
[13] = 14;
3296 dict
->charset
[14] = 15;
3297 dict
->charset
[15] = 99;
3298 for ( i
=16; i
<len
&& i
<=248-223; ++i
)
3299 dict
->charset
[i
] = i
+223;
3300 dict
->charset
[25] = 27;
3301 dict
->charset
[26] = 28;
3302 for ( i
=27; i
<len
&& i
<=266-222; ++i
)
3303 dict
->charset
[i
] = i
+222;
3304 dict
->charset
[44] = 109;
3305 dict
->charset
[45] = 110;
3306 for ( i
=46; i
<len
&& i
<=318-221; ++i
)
3307 dict
->charset
[i
] = i
+221;
3308 dict
->charset
[96] = 158;
3309 dict
->charset
[97] = 155;
3310 dict
->charset
[98] = 163;
3311 for ( i
=99; i
<len
&& i
<=326-220; ++i
)
3312 dict
->charset
[i
] = i
+220;
3313 dict
->charset
[107] = 150;
3314 dict
->charset
[108] = 164;
3315 dict
->charset
[109] = 169;
3316 for ( i
=110; i
<len
&& i
<=378-217; ++i
)
3317 dict
->charset
[i
] = i
+217;
3318 } else if ( dict
->charsetoff
==2 ) {
3319 /* Expert subset charset */
3320 dict
->charset
= galloc((len
<130?130:len
)*sizeof(uint16
));
3321 dict
->charset
[0] = 0; /* .notdef */
3322 dict
->charset
[1] = 1;
3323 for ( i
=2; i
<len
&& i
<=238-227; ++i
)
3324 dict
->charset
[i
] = i
+227;
3325 dict
->charset
[12] = 13;
3326 dict
->charset
[13] = 14;
3327 dict
->charset
[14] = 15;
3328 dict
->charset
[15] = 99;
3329 for ( i
=16; i
<len
&& i
<=248-223; ++i
)
3330 dict
->charset
[i
] = i
+223;
3331 dict
->charset
[25] = 27;
3332 dict
->charset
[26] = 28;
3333 for ( i
=27; i
<len
&& i
<=266-222; ++i
)
3334 dict
->charset
[i
] = i
+222;
3335 dict
->charset
[44] = 109;
3336 dict
->charset
[45] = 110;
3337 for ( i
=46; i
<len
&& i
<=272-221; ++i
)
3338 dict
->charset
[i
] = i
+221;
3339 dict
->charset
[51] = 300;
3340 dict
->charset
[52] = 301;
3341 dict
->charset
[53] = 302;
3342 dict
->charset
[54] = 305;
3343 dict
->charset
[55] = 314;
3344 dict
->charset
[56] = 315;
3345 dict
->charset
[57] = 158;
3346 dict
->charset
[58] = 155;
3347 dict
->charset
[59] = 163;
3348 for ( i
=60; i
<len
&& i
<=326-260; ++i
)
3349 dict
->charset
[i
] = i
+260;
3350 dict
->charset
[67] = 150;
3351 dict
->charset
[68] = 164;
3352 dict
->charset
[69] = 169;
3353 for ( i
=110; i
<len
&& i
<=346-217; ++i
)
3354 dict
->charset
[i
] = i
+217;
3356 dict
->charset
= galloc(len
*sizeof(uint16
));
3357 dict
->charset
[0] = 0; /* .notdef */
3358 fseek(ttf
,dict
->cff_start
+dict
->charsetoff
,SEEK_SET
);
3361 for ( i
=1; i
<len
; ++i
)
3362 dict
->charset
[i
] = getushort(ttf
);
3363 } else if ( format
==1 ) {
3364 for ( i
= 1; i
<len
; ) {
3365 first
= dict
->charset
[i
++] = getushort(ttf
);
3367 for ( j
=0; j
<cnt
; ++j
)
3368 dict
->charset
[i
++] = ++first
;
3370 } else if ( format
==2 ) {
3371 for ( i
= 1; i
<len
; ) {
3372 first
= dict
->charset
[i
++] = getushort(ttf
);
3373 cnt
= getushort(ttf
);
3374 for ( j
=0; j
<cnt
; ++j
)
3375 dict
->charset
[i
++] = ++first
;
3378 LogError( _("Unexpected charset format in cff: %d\n"), format
);
3379 if ( info
!=NULL
) info
->bad_cff
= true;
3382 while ( i
<len
) dict
->charset
[i
++] = 0;
3385 static uint8
*readfdselect(FILE *ttf
,int numglyphs
,struct ttfinfo
*info
) {
3386 uint8
*fdselect
= gcalloc(numglyphs
,sizeof(uint8
));
3387 int i
, j
, format
, nr
, first
, end
, fd
;
3391 for ( i
=0; i
<numglyphs
; ++i
)
3392 fdselect
[i
] = getc(ttf
);
3393 } else if ( format
==3 ) {
3394 nr
= getushort(ttf
);
3395 first
= getushort(ttf
);
3396 for ( i
=0; i
<nr
; ++i
) {
3398 end
= getushort(ttf
);
3399 for ( j
=first
; j
<end
; ++j
) {
3400 if ( j
>=numglyphs
) {
3401 LogError( _("Bad fdselect\n") );
3402 if ( info
!=NULL
) info
->bad_cff
= true;
3409 LogError( _("Didn't understand format for fdselect %d\n"), format
);
3410 if ( info
!=NULL
) info
->bad_cff
= true;
3416 static char *intarray2str(int *array
, int size
) {
3420 for ( i
=size
-1; i
>=0 && array
[i
]==0; --i
);
3423 ret
= pt
= galloc((i
+1)*12+12);
3425 for ( j
=0; j
<=i
; ++j
) {
3426 sprintf( pt
, "%d ", array
[j
]);
3433 static char *realarray2str(real
*array
, int size
, int must_be_even
) {
3437 for ( i
=size
-1; i
>=0 && array
[i
]==0; --i
);
3440 if ( must_be_even
&& !(i
&1) && array
[i
]<0 )
3441 ++i
; /* Someone gave us a bluevalues of [-20 0] and we reported [-20] */
3442 ret
= pt
= galloc((i
+1)*20+12);
3444 for ( j
=0; j
<=i
; ++j
) {
3445 sprintf( pt
, "%g ", (double) array
[j
]);
3452 static void privateadd(struct psdict
*private,char *key
,char *value
) {
3455 private->keys
[private->next
] = copy(key
);
3456 private->values
[private->next
++] = value
;
3459 static void privateaddint(struct psdict
*private,char *key
,int val
) {
3463 sprintf( buf
,"%d", val
);
3464 privateadd(private,key
,copy(buf
));
3467 static void privateaddintarray(struct psdict
*private,char *key
,int val
) {
3471 sprintf( buf
,"[%d]", val
);
3472 privateadd(private,key
,copy(buf
));
3475 static void privateaddreal(struct psdict
*private,char *key
,double val
,double def
) {
3479 sprintf( buf
,"%g", val
);
3480 privateadd(private,key
,copy(buf
));
3483 static void cffprivatefillup(struct psdict
*private, struct topdicts
*dict
) {
3485 private->keys
= galloc(14*sizeof(char *));
3486 private->values
= galloc(14*sizeof(char *));
3487 privateadd(private,"BlueValues",
3488 realarray2str(dict
->bluevalues
,sizeof(dict
->bluevalues
)/sizeof(dict
->bluevalues
[0]),true));
3489 privateadd(private,"OtherBlues",
3490 realarray2str(dict
->otherblues
,sizeof(dict
->otherblues
)/sizeof(dict
->otherblues
[0]),true));
3491 privateadd(private,"FamilyBlues",
3492 realarray2str(dict
->familyblues
,sizeof(dict
->familyblues
)/sizeof(dict
->familyblues
[0]),true));
3493 privateadd(private,"FamilyOtherBlues",
3494 realarray2str(dict
->familyotherblues
,sizeof(dict
->familyotherblues
)/sizeof(dict
->familyotherblues
[0]),true));
3495 privateaddreal(private,"BlueScale",dict
->bluescale
,0.039625);
3496 privateaddreal(private,"BlueShift",dict
->blueshift
,7);
3497 privateaddreal(private,"BlueFuzz",dict
->bluefuzz
,1);
3498 privateaddintarray(private,"StdHW",dict
->stdhw
);
3499 privateaddintarray(private,"StdVW",dict
->stdvw
);
3500 privateadd(private,"StemSnapH",
3501 realarray2str(dict
->stemsnaph
,sizeof(dict
->stemsnaph
)/sizeof(dict
->stemsnaph
[0]),false));
3502 privateadd(private,"StemSnapV",
3503 realarray2str(dict
->stemsnapv
,sizeof(dict
->stemsnapv
)/sizeof(dict
->stemsnapv
[0]),false));
3504 if ( dict
->forcebold
)
3505 privateadd(private,"ForceBold",copy("true"));
3506 if ( dict
->forceboldthreshold
!=0 )
3507 privateaddreal(private,"ForceBoldThreshold",dict
->forceboldthreshold
,0);
3508 privateaddint(private,"LanguageGroup",dict
->languagegroup
);
3509 privateaddreal(private,"ExpansionFactor",dict
->expansionfactor
,0.06);
3512 static SplineFont
*cffsffillup(struct topdicts
*subdict
, char **strings
,
3513 int scnt
, struct ttfinfo
*info
) {
3514 SplineFont
*sf
= SplineFontEmpty();
3516 static int nameless
;
3518 sf
->fontname
= utf8_verify_copy(FFgetsid(subdict
->sid_fontname
,strings
,scnt
,info
));
3519 if ( sf
->fontname
==NULL
) {
3521 sprintf(buffer
,"UntitledSubFont_%d", ++nameless
);
3522 sf
->fontname
= copy(buffer
);
3525 if ( subdict
->fontmatrix
[0]==0 )
3528 emsize
= rint( 1/subdict
->fontmatrix
[0] );
3529 sf
->ascent
= .8*emsize
;
3530 sf
->descent
= emsize
- sf
->ascent
;
3531 if ( subdict
->copyright
!=-1 )
3532 sf
->copyright
= utf8_verify_copy(FFgetsid(subdict
->copyright
,strings
,scnt
,info
));
3534 sf
->copyright
= utf8_verify_copy(FFgetsid(subdict
->notice
,strings
,scnt
,info
));
3535 sf
->familyname
= utf8_verify_copy(FFgetsid(subdict
->familyname
,strings
,scnt
,info
));
3536 sf
->fullname
= utf8_verify_copy(FFgetsid(subdict
->fullname
,strings
,scnt
,info
));
3537 sf
->weight
= utf8_verify_copy(FFgetsid(subdict
->weight
,strings
,scnt
,info
));
3538 sf
->version
= utf8_verify_copy(FFgetsid(subdict
->version
,strings
,scnt
,info
));
3539 sf
->italicangle
= subdict
->italicangle
;
3540 sf
->upos
= subdict
->underlinepos
;
3541 sf
->uwidth
= subdict
->underlinewidth
;
3542 sf
->xuid
= intarray2str(subdict
->xuid
,sizeof(subdict
->xuid
)/sizeof(subdict
->xuid
[0]));
3543 sf
->uniqueid
= subdict
->uniqueid
;
3544 sf
->strokewidth
= subdict
->strokewidth
;
3545 sf
->strokedfont
= subdict
->painttype
==2;
3547 if ( subdict
->private_size
>0 ) {
3548 sf
->private = gcalloc(1,sizeof(struct psdict
));
3549 cffprivatefillup(sf
->private,subdict
);
3554 static void cffinfofillup(struct ttfinfo
*info
, struct topdicts
*dict
,
3555 char **strings
, int scnt
) {
3557 info
->glyph_cnt
= dict
->glyphs
.cnt
;
3558 if ( info
->glyph_cnt
<0 ) info
->glyph_cnt
= 0;
3560 if ( dict
->fontmatrix
[0]==0 )
3561 info
->emsize
= 1000;
3563 info
->emsize
= rint( 1/dict
->fontmatrix
[0] );
3565 info
->ascent
= .8*info
->emsize
;
3567 info
->ascent
= dict
->fontbb
[3]*info
->emsize
/(dict
->fontbb
[3]-dict
->fontbb
[1]);
3569 info
->descent
= info
->emsize
- info
->ascent
;
3570 if ( dict
->copyright
!=-1 || dict
->notice
!=-1 )
3571 free( info
->copyright
);
3572 if ( dict
->copyright
!=-1 )
3573 info
->copyright
= utf8_verify_copy(FFgetsid(dict
->copyright
,strings
,scnt
,info
));
3574 else if ( dict
->notice
!=-1 )
3575 info
->copyright
= utf8_verify_copy(FFgetsid(dict
->notice
,strings
,scnt
,info
));
3576 if ( dict
->familyname
!=-1 ) {
3577 free(info
->familyname
);
3578 info
->familyname
= utf8_verify_copy(FFgetsid(dict
->familyname
,strings
,scnt
,info
));
3580 if ( dict
->fullname
!=-1 ) {
3581 free(info
->fullname
);
3582 info
->fullname
= utf8_verify_copy(FFgetsid(dict
->fullname
,strings
,scnt
,info
));
3584 if ( dict
->weight
!=-1 ) {
3586 info
->weight
= utf8_verify_copy(FFgetsid(dict
->weight
,strings
,scnt
,info
));
3588 if ( dict
->version
!=-1 ) {
3589 free(info
->version
);
3590 info
->version
= utf8_verify_copy(FFgetsid(dict
->version
,strings
,scnt
,info
));
3592 if ( dict
->fontname
!=NULL
) {
3593 free(info
->fontname
);
3594 info
->fontname
= utf8_verify_copy(dict
->fontname
);
3596 info
->italicAngle
= dict
->italicangle
;
3597 info
->upos
= dict
->underlinepos
;
3598 info
->uwidth
= dict
->underlinewidth
;
3599 info
->xuid
= intarray2str(dict
->xuid
,sizeof(dict
->xuid
)/sizeof(dict
->xuid
[0]));
3600 info
->uniqueid
= dict
->uniqueid
;
3601 info
->strokewidth
= dict
->strokewidth
;
3602 info
->strokedfont
= dict
->painttype
==2;
3604 if ( dict
->private_size
>0 ) {
3605 info
->private = gcalloc(1,sizeof(struct psdict
));
3606 cffprivatefillup(info
->private,dict
);
3608 if ( dict
->ros_registry
!=-1 ) {
3609 info
->cidregistry
= copy(FFgetsid(dict
->ros_registry
,strings
,scnt
,info
));
3610 info
->ordering
= copy(FFgetsid(dict
->ros_ordering
,strings
,scnt
,info
));
3611 info
->supplement
= dict
->ros_supplement
;
3612 info
->cidfontversion
= dict
->cidfontversion
;
3616 static void cfffigure(struct ttfinfo
*info
, struct topdicts
*dict
,
3617 char **strings
, int scnt
, struct pschars
*gsubrs
) {
3619 struct pschars
*subrs
;
3620 struct pscontext pscontext
;
3621 memset(&pscontext
,0,sizeof(pscontext
));
3623 cffinfofillup(info
, dict
, strings
, scnt
);
3625 /* The format allows for some dicts that are type1 strings and others that */
3626 /* are type2s. Which means that the global subrs will have a different bias */
3627 /* as we flip from font to font. So we can't set the bias when we read in */
3628 /* the subrs but must wait until we know which font we're working on. */
3629 cstype
= dict
->charstringtype
;
3630 pscontext
.is_type2
= cstype
-1;
3631 pscontext
.painttype
= dict
->painttype
;
3632 gsubrs
->bias
= cstype
==1 ? 0 :
3633 gsubrs
->cnt
< 1240 ? 107 :
3634 gsubrs
->cnt
<33900 ? 1131 : 32768;
3635 subrs
= &dict
->local_subrs
;
3636 subrs
->bias
= cstype
==1 ? 0 :
3637 subrs
->cnt
< 1240 ? 107 :
3638 subrs
->cnt
<33900 ? 1131 : 32768;
3640 info
->chars
= gcalloc(info
->glyph_cnt
,sizeof(SplineChar
*));
3641 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
3642 info
->chars
[i
] = PSCharStringToBB(
3643 dict
->glyphs
.values
[i
], dict
->glyphs
.lens
[i
],&pscontext
,
3644 subrs
,gsubrs
,FFgetsid(dict
->charset
[i
],strings
,scnt
,info
));
3645 info
->chars
[i
]->vwidth
= info
->emsize
;
3647 if ( info
->chars
[i
]->width
== (int16
) 0x8000 )
3648 info
->chars
[i
]->width
= dict
->defaultwidthx
;
3650 info
->chars
[i
]->width
+= dict
->nominalwidthx
;
3653 /* Need to do a reference fixup here !!!!! just in case some idiot */
3654 /* used type1 char strings -- or used the depreciated meaning of */
3655 /* endchar (==seac) */
3658 static void cidfigure(struct ttfinfo
*info
, struct topdicts
*dict
,
3659 char **strings
, int scnt
, struct pschars
*gsubrs
, struct topdicts
**subdicts
,
3661 int i
, j
, cstype
, uni
, cid
;
3662 struct pschars
*subrs
;
3666 struct pscontext pscontext
;
3667 EncMap
*encmap
= NULL
;
3669 memset(&pscontext
,0,sizeof(pscontext
));
3671 cffinfofillup(info
, dict
, strings
, scnt
);
3673 /* We'll set the encmap later */
3674 /*info->map = encmap = EncMapNew(info->glyph_cnt,info->glyph_cnt,&custom);*/
3676 for ( j
=0; subdicts
[j
]!=NULL
; ++j
);
3677 info
->subfontcnt
= j
;
3678 info
->subfonts
= gcalloc(j
+1,sizeof(SplineFont
*));
3679 for ( j
=0; subdicts
[j
]!=NULL
; ++j
) {
3680 info
->subfonts
[j
] = cffsffillup(subdicts
[j
],strings
,scnt
,info
);
3681 info
->subfonts
[j
]->map
= encmap
;
3682 info
->subfonts
[j
]->glyphmin
= -1;
3684 /* here we also deal with glyphmin */
3686 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
3687 sf
= info
->subfonts
[ fdselect
[i
] ];
3688 cid
= dict
->charset
[i
];
3689 if ( cid
>=sf
->glyphcnt
) {
3690 if (sf
->glyphmin
== -1) {
3693 sf
->glyphcnt
= sf
->glyphmax
= cid
+1;
3695 /*if ( cid>=encmap->enccount )
3696 encmap->enccount = cid+1;*/
3698 for ( j
=0; subdicts
[j
]!=NULL
; ++j
)
3699 info
->subfonts
[j
]->glyphs
= gcalloc(info
->subfonts
[j
]->glyphcnt
,sizeof(SplineChar
*));
3701 /*encmap->encmax = encmap->enccount;*/
3702 /*encmap->map = galloc(encmap->enccount*sizeof(int));*/
3703 /*memset(encmap->map,-1,encmap->enccount*sizeof(int));*/
3705 info
->chars
= gcalloc(info
->glyph_cnt
,sizeof(SplineChar
*));
3707 /* info->chars provides access to the chars ordered by glyph, which the */
3708 /* ttf routines care about */
3709 /* sf->glyphs provides access to the chars ordered by CID. Not sure what */
3710 /* would happen to a kern from one font to another... */
3712 map
= FindCidMap(info
->cidregistry
,info
->ordering
,info
->supplement
,NULL
);
3714 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
3716 sf
= info
->subfonts
[j
];
3717 /* The format allows for some dicts that are type1 strings and others that */
3718 /* are type2s. Which means that the global subrs will have a different bias */
3719 /* as we flip from font to font. So we can't set the bias when we read in */
3720 /* the subrs but must wait until we know which font we're working on. */
3721 cstype
= subdicts
[j
]->charstringtype
;
3722 pscontext
.is_type2
= cstype
-1;
3723 pscontext
.painttype
= subdicts
[j
]->painttype
;
3724 gsubrs
->bias
= cstype
==1 ? 0 :
3725 gsubrs
->cnt
< 1240 ? 107 :
3726 gsubrs
->cnt
<33900 ? 1131 : 32768;
3727 subrs
= &subdicts
[j
]->local_subrs
;
3728 subrs
->bias
= cstype
==1 ? 0 :
3729 subrs
->cnt
< 1240 ? 107 :
3730 subrs
->cnt
<33900 ? 1131 : 32768;
3731 cid
= dict
->charset
[i
];
3732 /*encmap->map[cid] = cid;*/
3733 uni
= CID2NameUni(map
,cid
,buffer
,sizeof(buffer
));
3734 info
->chars
[i
] = PSCharStringToBB(
3735 dict
->glyphs
.values
[i
], dict
->glyphs
.lens
[i
],&pscontext
,
3736 subrs
,gsubrs
,buffer
);
3737 info
->chars
[i
]->vwidth
= sf
->ascent
+sf
->descent
;
3738 info
->chars
[i
]->unicodeenc
= uni
;
3739 sf
->glyphs
[cid
] = info
->chars
[i
];
3740 sf
->glyphs
[cid
]->parent
= sf
;
3741 sf
->glyphs
[cid
]->orig_pos
= i
; /* fixed in 0.80.1 */
3742 if ( sf
->glyphs
[cid
]->layers
[ly_fore
].refs
!=NULL
)
3743 IError( "Reference found in CID font. Can't fix it up");
3744 THPatchSplineChar(sf
->glyphs
[cid
]);
3746 if ( sf
->glyphs
[cid
]->width
== (int16
) 0x8000 )
3747 sf
->glyphs
[cid
]->width
= subdicts
[j
]->defaultwidthx
;
3749 sf
->glyphs
[cid
]->width
+= subdicts
[j
]->nominalwidthx
;
3753 /* No need to do a reference fixup here-- the chars aren't associated */
3754 /* with any encoding as is required for seac */
3757 static int readcffglyphs(FILE *ttf
,struct ttfinfo
*info
) {
3760 char **fontnames
, **strings
;
3761 struct topdicts
**dicts
, **subdicts
;
3763 struct pschars gsubs
;
3767 fseek(ttf
,info
->cff_start
,SEEK_SET
);
3768 if ( getc(ttf
)!='\1' ) { /* Major version */
3769 LogError( _("CFF version mismatch\n" ));
3770 info
->bad_cff
= true;
3773 getc(ttf
); /* Minor version */
3774 hdrsize
= getc(ttf
);
3775 offsize
= getc(ttf
);
3777 fseek(ttf
,info
->cff_start
+hdrsize
,SEEK_SET
);
3778 fontnames
= readcfffontnames(ttf
,NULL
,info
);
3780 if ( fontnames
[1]!=NULL
) { /* More than one? Can that even happen in OpenType? */
3781 which
= PickCFFFont(fontnames
);
3783 for ( i
=0; fontnames
[i
]!=NULL
; ++i
)
3789 dicts
= readcfftopdicts(ttf
,fontnames
,info
->cff_start
,info
, NULL
);
3790 /* String index is just the same as fontname index */
3791 strings
= readcfffontnames(ttf
,&scnt
,info
);
3792 readcffsubrs(ttf
,&gsubs
,info
);
3793 /* Can be many fonts here. Only decompose the one */
3794 if ( dicts
[which
]->charstringsoff
!=-1 ) {
3795 fseek(ttf
,info
->cff_start
+dicts
[which
]->charstringsoff
,SEEK_SET
);
3796 readcffsubrs(ttf
,&dicts
[which
]->glyphs
,info
);
3798 if ( dicts
[which
]->private_offset
!=-1 )
3799 readcffprivate(ttf
,dicts
[which
],info
);
3800 if ( dicts
[which
]->charsetoff
!=-1 )
3801 readcffset(ttf
,dicts
[which
],info
);
3802 if ( dicts
[which
]->fdarrayoff
==-1 )
3803 cfffigure(info
,dicts
[which
],strings
,scnt
,&gsubs
);
3805 fseek(ttf
,info
->cff_start
+dicts
[which
]->fdarrayoff
,SEEK_SET
);
3806 subdicts
= readcfftopdicts(ttf
,NULL
,info
->cff_start
,info
,dicts
[which
]);
3807 fseek(ttf
,info
->cff_start
+dicts
[which
]->fdselectoff
,SEEK_SET
);
3808 fdselect
= readfdselect(ttf
,dicts
[which
]->glyphs
.cnt
,info
);
3809 for ( j
=0; subdicts
[j
]!=NULL
; ++j
) {
3810 if ( subdicts
[j
]->private_offset
!=-1 )
3811 readcffprivate(ttf
,subdicts
[j
],info
);
3812 if ( subdicts
[j
]->charsetoff
!=-1 )
3813 readcffset(ttf
,subdicts
[j
],info
);
3815 cidfigure(info
,dicts
[which
],strings
,scnt
,&gsubs
,subdicts
,fdselect
);
3816 for ( j
=0; subdicts
[j
]!=NULL
; ++j
)
3817 TopDictFree(subdicts
[j
]);
3818 free(subdicts
); free(fdselect
);
3820 if ( dicts
[which
]->encodingoff
!=-1 )
3821 readcffenc(ttf
,dicts
[which
],info
,strings
,scnt
);
3823 if ( dicts
[which
]->fdarrayoff
==-1 ) {
3824 for ( i
=0; i
<info
->glyph_cnt
; ++i
)
3825 if ( info
->chars
[i
]!=NULL
)
3826 info
->chars
[i
]->orig_pos
= i
;
3829 if ( info
->to_order2
) {
3830 for ( i
=0; i
<info
->glyph_cnt
; ++i
)
3831 SCConvertToOrder2(info
->chars
[i
]);
3834 for ( i
=0; fontnames
[i
]!=NULL
&& i
<1; ++i
) {
3836 TopDictFree(dicts
[i
]);
3838 free(fontnames
); free(dicts
);
3839 if ( strings
!=NULL
) {
3840 for ( i
=0; strings
[i
]!=NULL
; ++i
)
3844 for ( i
=0; i
<gsubs
.cnt
; ++i
)
3845 free(gsubs
.values
[i
]);
3846 free(gsubs
.values
); free(gsubs
.lens
);
3851 static int readtyp1glyphs(FILE *ttf
,struct ttfinfo
*info
) {
3857 fseek(ttf
,info
->typ1_start
,SEEK_SET
);
3858 /* There appear to be about 20 bytes of garbage (well, I don't know what they */
3859 /* mean, so they are garbage to me) before the start of the PostScript. But */
3860 /* it's not exactly 20. I've seen 22 and 24. So see if we can find "%!PS-Adobe" */
3861 /* in the first few bytes of the file, and skip to there if found */
3863 if(fread(buffer
,1,sizeof(buffer
),ttf
) != sizeof(buffer
))
3866 for ( i
=39; i
>=0; --i
)
3867 if ( buffer
[i
]=='%' && buffer
[i
+1]=='!' )
3871 fseek(ttf
,info
->typ1_start
+i
,SEEK_SET
);
3875 for ( i
=0; i
<(int)info
->typ1_length
; ++i
)
3876 putc(getc(ttf
),tmp
);
3878 fd
= _ReadPSFont(tmp
);
3881 SplineFont
*sf
= SplineFontFromPSFont(fd
);
3883 info
->emsize
= (sf
->ascent
+sf
->descent
);
3884 info
->ascent
= sf
->ascent
;
3885 info
->descent
= sf
->descent
;
3886 if ( sf
->subfontcnt
!=0 ) {
3887 info
->subfontcnt
= sf
->subfontcnt
;
3888 info
->subfonts
= sf
->subfonts
;
3889 info
->cidregistry
= copy(sf
->cidregistry
);
3890 info
->ordering
= copy(sf
->ordering
);
3891 info
->supplement
= sf
->supplement
;
3892 info
->cidfontversion
= sf
->cidversion
;
3893 sf
->subfonts
= NULL
;
3896 info
->chars
= sf
->glyphs
;
3897 info
->glyph_cnt
= sf
->glyphcnt
;
3898 for ( i
=sf
->glyphcnt
-1; i
>=0; --i
) if ( (sc
=sf
->glyphs
[i
])!=NULL
)
3909 static void readttfwidths(FILE *ttf
,struct ttfinfo
*info
) {
3911 int lastwidth
= info
->emsize
, lsb
;
3912 /* I'm not interested in the lsb, I'm not sure what it means if it differs*/
3913 /* from that is specified in the outline. Do we move the outline? */
3914 /* Ah... I am interested in it if bit 1 of 'head'.flags is set, then we */
3915 /* do move the outline */
3916 int check_width_consistency
= info
->cff_start
!=0 && info
->glyph_start
==0;
3920 memset(trans
,0,sizeof(trans
));
3921 trans
[0] = trans
[3] = 1;
3923 fseek(ttf
,info
->hmetrics_start
,SEEK_SET
);
3924 for ( i
=0; i
<info
->width_cnt
&& i
<info
->glyph_cnt
; ++i
) {
3925 lastwidth
= getushort(ttf
);
3926 lsb
= (short) getushort(ttf
);
3927 if ( (sc
= info
->chars
[i
])!=NULL
) { /* can happen in ttc files */
3928 if ( check_width_consistency
&& sc
->width
!=lastwidth
) {
3929 if ( info
->fontname
!=NULL
&& sc
->name
!=NULL
)
3930 LogError("In %s, in glyph %s, 'CFF ' advance width (%d) and\n 'hmtx' width (%d) do not match. (Subsequent mismatches will not be reported)\n",
3931 info
->fontname
, sc
->name
, sc
->width
, lastwidth
);
3933 LogError("In GID %d, 'CFF ' advance width (%d) and 'hmtx' width (%d) do not match.\n (Subsequent mismatches will not be reported)\n",
3934 i
, sc
->width
, lastwidth
);
3935 info
->bad_metrics
= true;
3936 check_width_consistency
= false;
3938 sc
->width
= lastwidth
;
3939 sc
->widthset
= true;
3940 if ( info
->apply_lsb
) {
3941 if ( sc
->lsidebearing
!=lsb
) {
3942 trans
[4] = lsb
-sc
->lsidebearing
;
3943 SplinePointListTransform(sc
->layers
[ly_fore
].splines
,trans
,true);
3949 LogError( _("Invalid ttf hmtx table (or hhea), numOfLongMetrics is 0\n") );
3950 info
->bad_metrics
= true;
3953 for ( j
=i
; j
<info
->glyph_cnt
; ++j
) {
3954 if ( (sc
= info
->chars
[j
])!=NULL
) { /* In a ttc file we may skip some */
3955 sc
->width
= lastwidth
;
3956 sc
->widthset
= true;
3957 if ( info
->apply_lsb
) {
3958 lsb
= (short) getushort(ttf
);
3959 if ( sc
->lsidebearing
!=lsb
) {
3960 trans
[4] = lsb
-sc
->lsidebearing
;
3961 SplinePointListTransform(sc
->layers
[ly_fore
].splines
,trans
,true);
3968 static void dummywidthsfromstrike(FILE *ttf
,struct ttfinfo
*info
) {
3972 (void)ttf
; /* -Wall */
3973 if ( info
->bitmaps
==NULL
)
3976 for ( bdf
=info
->bitmaps
; bdf
->next
!=NULL
; bdf
=bdf
->next
);
3977 for ( i
=0; i
<bdf
->glyphcnt
; ++i
) if ( bdf
->glyphs
[i
]!=NULL
) {
3978 bdf
->glyphs
[i
]->sc
->width
= info
->emsize
*bdf
->glyphs
[i
]->width
/bdf
->pixelsize
;
3979 bdf
->glyphs
[i
]->sc
->widthset
= true;
3982 for ( i
=0; i
<info
->glyph_cnt
; ++i
) if ( info
->chars
[i
]!=NULL
) {
3983 cnt
= 0; scaled_sum
= 0;
3984 for ( bdf
=info
->bitmaps
; bdf
->next
!=NULL
; bdf
=bdf
->next
) {
3985 if ( i
<bdf
->glyphcnt
&& bdf
->glyphs
[i
]!=NULL
) {
3986 scaled_sum
+= ((double) (info
->emsize
*bdf
->glyphs
[i
]->width
))/bdf
->pixelsize
;
3991 info
->chars
[i
]->width
= scaled_sum
/cnt
;
3992 info
->chars
[i
]->widthset
= true;
3998 static void readttfvwidths(FILE *ttf
,struct ttfinfo
*info
) {
4000 int lastvwidth
= info
->emsize
, vwidth_cnt
, tsb
/*, cnt=0*/;
4003 fseek(ttf
,info
->vhea_start
+4+4,SEEK_SET
); /* skip over the version number & typo right/left */
4004 info
->pfminfo
.vlinegap
= getushort(ttf
);
4005 info
->pfminfo
.vheadset
= true;
4007 for ( i
=0; i
<12; ++i
)
4009 vwidth_cnt
= getushort(ttf
);
4011 fseek(ttf
,info
->vmetrics_start
,SEEK_SET
);
4012 for ( i
=0; i
<vwidth_cnt
&& i
<info
->glyph_cnt
; ++i
) {
4013 lastvwidth
= getushort(ttf
);
4014 tsb
= getushort(ttf
);
4015 if ( info
->chars
[i
]!=NULL
) { /* can happen in ttc files */
4016 info
->chars
[i
]->vwidth
= lastvwidth
;
4017 info
->chars
[i
]->tsb
= tsb
;
4021 LogError( _("Invalid ttf vmtx table (or vhea), numOfLongVerMetrics is 0\n") );
4022 info
->bad_metrics
= true;
4025 for ( j
=i
; j
<info
->glyph_cnt
; ++j
) {
4026 if ( info
->chars
[j
]!=NULL
) /* In a ttc file we may skip some */
4027 info
->chars
[j
]->vwidth
= lastvwidth
;
4032 static int modenc(int enc
,int modtype
) {
4033 (void)modtype
; /* for -Wall */
4037 static int badencoding(struct ttfinfo
*info
) {
4038 if ( !info
->bad_cmap
) {
4039 LogError("Bad encoding information in 'cmap' table.");
4040 info
->bad_cmap
= true;
4045 static int umodenc(int enc
,int modtype
, struct ttfinfo
*info
) {
4048 if ( modtype
<=1 /* Unicode */ ) {
4049 /* No conversion needed, already unicode */;
4050 #ifdef FROM_CJK_ICONV
4051 } else if ( modtype
==2 /* SJIS */ ) {
4054 if ( enc
=='\\' ) enc
= 0xa5; /* Yen */
4055 } else if ( enc
>=161 && enc
<=223 ) {
4057 enc
= unicode_from_jis201
[enc
];
4058 } else if ( enc
<255 ) {
4059 /* This is erroneous as I understand SJIS */
4060 enc
= badencoding(info
);
4062 int ch1
= enc
>>8, ch2
= enc
&0xff;
4063 if ( ch1
>= 129 && ch1
<= 159 )
4070 else if ( ch2
>127 ) {
4077 if ( ch1
<0x21 || ch2
<0x21 || ch1
>0x7f || ch2
>0x7f )
4078 enc
= badencoding(info
);
4080 enc
= unicode_from_jis208
[(ch1
-0x21)*94+(ch2
-0x21)];
4082 } else if ( modtype
==3 /* GB2312 offset by 0x8080, parse just like wansung */ ) {
4085 enc
= (enc
>>8)*94 + (enc
&0xff);
4086 enc
= unicode_from_gb2312
[enc
];
4087 if ( enc
==0 ) enc
= -1;
4088 } else if ( enc
>0x100 )
4089 enc
= badencoding(info
);
4090 } else if ( modtype
==4 /* BIG5 */ ) { /* old ms docs say big5 is modtype==3, but new ones say 4 */
4092 enc
= unicode_from_big5hkscs
[enc
-0x8100];
4093 else if ( enc
>0x100 )
4094 enc
= badencoding(info
);
4095 } else if ( modtype
==5 /* Wansung == KSC 5601-1987, I hope */ ) {
4098 enc
= (enc
>>8)*94 + (enc
&0xff);
4099 enc
= unicode_from_ksc5601
[enc
];
4100 if ( enc
==0 ) enc
= -1;
4101 } else if ( enc
>0x100 )
4102 enc
= badencoding(info
);
4103 } else if ( modtype
==6 /* Johab */ ) {
4105 enc
= unicode_from_johab
[enc
-0x8400];
4106 else if ( enc
>0x100 )
4107 enc
= badencoding(info
);
4110 enc
= badencoding(info
);
4127 static int SubtableIsntSupported(FILE *ttf
,uint32 offset
,struct cmap_encs
*cmap_enc
, struct ttfinfo
*info
) {
4128 uint32 here
= ftell(ttf
);
4129 int format
, len
, ret
=false;
4131 fseek(ttf
,offset
,SEEK_SET
);
4133 cmap_enc
->format
= format
= getushort(ttf
);
4134 if ( format
<0 || (format
&1) || format
>12 ) {
4135 LogError( _("Encoding subtable for platform=%d, specific=%d has an unsupported format %d.\n"),
4136 cmap_enc
->platform
, cmap_enc
->specific
, format
);
4137 info
->bad_cmap
= true;
4141 if ( format
!=12 && format
!=10 && format
!=8 ) {
4142 len
= getushort(ttf
);
4143 cmap_enc
->lang
= getushort(ttf
);
4145 /* padding */ getushort(ttf
);
4147 cmap_enc
->lang
= getlong(ttf
);
4150 LogError( _("Encoding subtable for platform=%d, specific=%d has a 0 length subtable.\n"),
4151 cmap_enc
->platform
, cmap_enc
->specific
);
4152 info
->bad_cmap
= true;
4155 fseek(ttf
,here
,SEEK_SET
);
4159 static int SubtableMustBe14(FILE *ttf
,uint32 offset
,struct ttfinfo
*info
) {
4160 uint32 here
= ftell(ttf
);
4161 int format
, ret
=true;
4163 fseek(ttf
,offset
,SEEK_SET
);
4165 format
= getushort(ttf
);
4167 LogError( _("Encoding subtable for platform=%d, specific=%d (which must be 14)\nhas an unsupported format %d.\n"),
4169 info
->bad_cmap
= true;
4172 fseek(ttf
,here
,SEEK_SET
);
4176 static void ApplyVariationSequenceSubtable(FILE *ttf
,uint32 vs_map
,
4177 struct ttfinfo
*info
,int justinuse
) {
4178 int sub_table_len
, vs_cnt
, i
, j
, rcnt
, gid
;
4179 struct vs_data
{ int vs
; uint32 def
, non_def
; } *vs_data
;
4182 fseek(ttf
,vs_map
,SEEK_SET
);
4183 /* We/ve already checked the format is 14 */ getushort(ttf
);
4184 sub_table_len
= getlong(ttf
);
4185 vs_cnt
= getlong(ttf
);
4186 vs_data
= galloc(vs_cnt
*sizeof(struct vs_data
));
4187 for ( i
=0; i
<vs_cnt
; ++i
) {
4188 vs_data
[i
].vs
= get3byte(ttf
);
4189 vs_data
[i
].def
= getlong(ttf
);
4190 vs_data
[i
].non_def
= getlong(ttf
);
4193 for ( i
=0; i
<vs_cnt
; ++i
) {
4194 if ( vs_data
[i
].def
!=0 && justinuse
==git_normal
) {
4195 fseek(ttf
,vs_map
+vs_data
[i
].def
,SEEK_SET
);
4196 rcnt
= getlong(ttf
);
4197 for ( j
=0; j
<rcnt
; ++j
) {
4198 int start_uni
= get3byte(ttf
);
4199 int cnt
= getc(ttf
);
4201 for ( uni
=start_uni
; uni
<=start_uni
+cnt
; ++uni
) {
4202 SplineChar
*sc
=NULL
;
4203 struct altuni
*altuni
;
4204 for ( gid
= 0; gid
<info
->glyph_cnt
; ++gid
) {
4205 if ( (sc
= info
->chars
[gid
])!=NULL
) {
4206 if ( sc
->unicodeenc
==uni
)
4208 for ( altuni
= sc
->altuni
; altuni
!=NULL
; altuni
=altuni
->next
)
4209 if ( altuni
->unienc
==uni
&& altuni
->vs
== -1 && altuni
->fid
==0 )
4215 if ( gid
==info
->glyph_cnt
) {
4216 LogError( _("No glyph with unicode U+%05x in font\n"),
4218 info
->bad_cmap
= true;
4220 altuni
= chunkalloc(sizeof(struct altuni
));
4221 altuni
->unienc
= uni
;
4222 altuni
->vs
= vs_data
[i
].vs
;
4224 altuni
->next
= sc
->altuni
;
4225 sc
->altuni
= altuni
;
4230 if ( vs_data
[i
].non_def
!=0 ) {
4231 fseek(ttf
,vs_map
+vs_data
[i
].non_def
,SEEK_SET
);
4232 rcnt
= getlong(ttf
);
4233 for ( j
=0; j
<rcnt
; ++j
) {
4234 int uni
= get3byte(ttf
);
4235 int curgid
= getushort(ttf
);
4236 if ( justinuse
==git_justinuse
) {
4237 if ( curgid
<info
->glyph_cnt
&& curgid
>=0)
4238 info
->inuse
[curgid
] = 1;
4239 } else if ( justinuse
==git_justinuse
) {
4240 if ( curgid
<info
->glyph_cnt
&& curgid
>=0 &&
4241 (sc
=info
->chars
[curgid
])!=NULL
&& sc
->name
==NULL
) {
4243 sprintf(buffer
, "u%04X.vs%04X", uni
, vs_data
[i
].vs
);
4244 sc
->name
= copy(buffer
);
4247 if ( curgid
>=info
->glyph_cnt
|| curgid
<0 ||
4248 info
->chars
[curgid
]==NULL
) {
4249 LogError( _("GID out of range (%d) in format 14 'cmap' subtable\n"),
4251 info
->bad_cmap
= true;
4253 SplineChar
*sc
= info
->chars
[curgid
];
4254 struct altuni
*altuni
= chunkalloc(sizeof(struct altuni
));
4255 altuni
->unienc
= uni
;
4256 altuni
->vs
= vs_data
[i
].vs
;
4258 altuni
->next
= sc
->altuni
;
4259 sc
->altuni
= altuni
;
4268 static enum uni_interp
amscheck(struct ttfinfo
*info
, EncMap
*map
) {
4270 /* Try to guess if the font uses the AMS math PUA assignments */
4275 if ( 0xe668<map
->enccount
&& map
->map
[0xe668]!=-1 &&
4276 info
->chars
[map
->map
[0xe668]]->unicodeenc
=='b' )
4278 if ( 0xe3c8<map
->enccount
&& map
->map
[0xe626]!=-1 &&
4279 info
->chars
[map
->map
[0xe626]]->unicodeenc
==0xe626 )
4281 if ( 0xe3c8<map
->enccount
&& map
->map
[0xe3c8]!=-1 &&
4282 info
->chars
[map
->map
[0xe3c8]]->unicodeenc
==0x29e1 )
4284 if ( 0x2A7C<map
->enccount
&& map
->map
[0x2A7C]!=-1 &&
4285 info
->chars
[map
->map
[0x2A7C]]->unicodeenc
==0xE32A )
4287 if ( 0x2920<map
->enccount
&& map
->map
[0x2920]!=-1 &&
4288 info
->chars
[map
->map
[0x2920]]->unicodeenc
==0xE221 )
4290 return( cnt
>=2 ? ui_ams
: ui_none
);
4293 static int PickCMap(struct cmap_encs
*cmap_encs
,int enccnt
,int def
) {
4295 char **choices
, *encname
;
4297 static char *macscripts
[]= { N_("Roman"), N_("Japanese"), N_("Traditional Chinese"), N_("Korean"),
4298 N_("Arabic"), N_("Hebrew"), N_("Greek"),
4299 /* GT: Don't ask me what RSymbol means, I don't know either. It's in apple's */
4300 /* GT: docs though */
4301 N_("Cyrillic"), N_("RSymbol"), N_("Devanagari"),
4302 /* 10*/ N_("Gurmukhi"), N_("Gujarati"), NULL
, NULL
, NULL
,
4303 NULL
, NULL
, NULL
, NULL
, NULL
,
4304 /* 20*/ NULL
, N_("Thai"), NULL
, NULL
, NULL
, N_("Simplified Chinese"),
4305 NULL
, NULL
, NULL
, N_("Central European"),
4306 /* 30*/ NULL
, NULL
, NULL
};
4308 choices
= galloc(enccnt
*sizeof(char *));
4309 for ( i
=0; i
<enccnt
; ++i
) {
4311 if ( cmap_encs
[i
].platform
==1 && cmap_encs
[i
].specific
<32 ) {
4312 encname
= macscripts
[cmap_encs
[i
].specific
];
4313 if ( encname
!=NULL
)
4314 encname
= _(encname
);
4315 } else if ( cmap_encs
[i
].platform
==0 ) {
4316 switch ( cmap_encs
[i
].specific
) {
4318 encname
= N_("Unicode 1.0");
4321 encname
= N_("Unicode 1.1");
4324 encname
= N_("ISO 10646:1993");
4327 encname
= N_("Unicode 2.0+, BMP only");
4330 encname
= N_("Unicode 2.0+, all planes");
4333 } else if ( cmap_encs
[i
].platform
==3 && cmap_encs
[i
].specific
==0 )
4334 encname
= N_("\"Symbol\"");
4335 if ( encname
==NULL
)
4336 encname
= cmap_encs
[i
].enc
->enc_name
;
4338 sprintf(buffer
,"%d (%s) %d %s %s %s",
4339 cmap_encs
[i
].platform
,
4340 cmap_encs
[i
].platform
==0 ? _("Unicode") :
4341 cmap_encs
[i
].platform
==1 ? _("Apple") :
4342 cmap_encs
[i
].platform
==2 ? _("ISO (Deprecated)") :
4343 cmap_encs
[i
].platform
==3 ? _("MicroSoft") :
4344 cmap_encs
[i
].platform
==4 ? _("Custom") :
4345 cmap_encs
[i
].platform
==7 ? _("FreeType internals") :
4347 cmap_encs
[i
].specific
,
4349 cmap_encs
[i
].platform
==1 && cmap_encs
[i
].lang
!=0? MacLanguageFromCode(cmap_encs
[i
].lang
-1) : "",
4350 cmap_encs
[i
].format
== 0 ? "Byte encoding table" :
4351 cmap_encs
[i
].format
== 2 ? "High-byte mapping through table" :
4352 cmap_encs
[i
].format
== 4 ? "Segment mapping to delta values" :
4353 cmap_encs
[i
].format
== 6 ? "Trimmed table mapping" :
4354 cmap_encs
[i
].format
== 8 ? "mixed 16-bit and 32-bit coverage" :
4355 cmap_encs
[i
].format
== 10 ? "Trimmed array" :
4356 cmap_encs
[i
].format
== 12 ? "Segmented coverage" :
4358 choices
[i
] = copy(buffer
);
4360 ret
= ff_choose(_("Pick a CMap subtable"),(const char **) choices
,enccnt
,def
,
4361 _("Pick a CMap subtable"));
4362 for ( i
=0; i
<enccnt
; ++i
)
4368 /* 'cmap' table: readttfcmap */
4369 static void readttfencodings(FILE *ttf
,struct ttfinfo
*info
, int justinuse
) {
4370 int i
,j
, def
, unicode_cmap
, unicode4_cmap
, dcnt
, dcmap_cnt
, dc
;
4371 int nencs
, version
, usable_encs
;
4372 Encoding
*enc
= &custom
;
4373 const int32
*trans
=NULL
;
4374 enum uni_interp interp
= ui_none
;
4375 int platform
, specific
;
4376 int offset
, encoff
=0;
4381 uint16
*endchars
, *startchars
, *delta
, *rangeOffset
, *glyphs
;
4386 int badencwarned
=false;
4390 struct cmap_encs
*cmap_encs
, desired_cmaps
[2], *dcmap
;
4392 fseek(ttf
,info
->encoding_start
,SEEK_SET
);
4393 version
= getushort(ttf
);
4394 nencs
= getushort(ttf
);
4395 if ( version
!=0 && nencs
==0 )
4396 nencs
= version
; /* Sometimes they are backwards */ /* Or was I just confused early on? */
4397 cmap_encs
= galloc(nencs
*sizeof(struct cmap_encs
));
4398 for ( i
=usable_encs
=0; i
<nencs
; ++i
) {
4399 cmap_encs
[usable_encs
].platform
= getushort(ttf
);
4400 cmap_encs
[usable_encs
].specific
= getushort(ttf
);
4401 cmap_encs
[usable_encs
].offset
= getlong(ttf
);
4402 if ( cmap_encs
[usable_encs
].platform
== 0 && cmap_encs
[usable_encs
].specific
== 5 ) {
4403 /* This isn't a true encoding. */
4404 /* It's an optional set of encoding modifications (sort of) */
4405 /* applied to a format 4/10 encoding (unicode BMP/Full) */
4406 if ( SubtableMustBe14(ttf
,info
->encoding_start
+cmap_encs
[usable_encs
].offset
,info
) )
4407 vs_map
= info
->encoding_start
+cmap_encs
[usable_encs
].offset
;
4410 temp
= enc_from_platspec(cmap_encs
[usable_encs
].platform
,cmap_encs
[usable_encs
].specific
);
4411 if ( temp
==NULL
) /* iconv doesn't support this. Some sun iconvs seem limited */
4412 temp
= FindOrMakeEncoding("Custom");
4413 cmap_encs
[usable_encs
].enc
= temp
;
4414 if ( SubtableIsntSupported(ttf
,info
->encoding_start
+cmap_encs
[usable_encs
].offset
,
4415 &cmap_encs
[usable_encs
],info
))
4419 if ( usable_encs
==0 ) {
4420 LogError( _("Could not find any valid encoding tables" ));
4426 unicode_cmap
= unicode4_cmap
= -1;
4427 for ( i
=0; i
<usable_encs
; ++i
) {
4428 temp
= cmap_encs
[i
].enc
;
4429 platform
= cmap_encs
[i
].platform
;
4430 specific
= cmap_encs
[i
].specific
;
4431 offset
= cmap_encs
[i
].offset
;
4433 if ( (platform
==3 && specific
==10) || (platform
==0 && specific
==4) ) { /* MS Unicode 4 byte */
4437 } else if ( !enc
->is_unicodefull
&& (!prefer_cjk_encodings
||
4438 (!enc
->is_japanese
&& !enc
->is_korean
&& !enc
->is_tradchinese
&&
4439 !enc
->is_simplechinese
)) &&
4440 (( platform
==3 && specific
==1 ) || /* MS Unicode */
4441 /* Well I should only deal with apple unicode specific==0 (default) and 3 (U2.0 semantics) */
4442 /* but apple ships dfonts with specific==1 (Unicode 1.1 semantics) */
4443 /* which is stupid of them */
4444 ( platform
==0 /*&& (specific==0 || specific==3)*/ ))) { /* Apple Unicode */
4447 } else if ( platform
==3 && specific
==0 && enc
->is_custom
) {
4448 /* Only select symbol if we don't have something better */
4451 /* Now I had assumed this would be a 1 byte encoding, but it turns*/
4452 /* out to map into the unicode private use area at U+f000-U+F0FF */
4453 /* so it's a 2 byte enc */
4454 /* Mac platform specific encodings are script numbers. 0=>roman, 1=>jap, 2=>big5, 3=>korean, 4=>arab, 5=>hebrew, 6=>greek, 7=>cyrillic, ... 25=>simplified chinese */
4455 } else if ( platform
==1 && specific
==0 && enc
->is_custom
) {
4458 } else if ( platform
==1 && (specific
==2 ||specific
==1||specific
==3||specific
==25) &&
4459 !enc
->is_unicodefull
&&
4460 (prefer_cjk_encodings
|| !enc
->is_unicodebmp
) ) {
4463 } else if ( platform
==3 && (specific
>=2 && specific
<=6 ) &&
4464 !enc
->is_unicodefull
&&
4465 (prefer_cjk_encodings
|| !enc
->is_unicodebmp
) ) {
4466 /* Old ms docs say that specific==3 => big 5, new docs say specific==4 => big5 */
4467 /* Ain't that jus' great? */
4471 if ( (platform
==3 && specific
==1) ||
4472 (platform
==0 && specific
==3))
4476 if ( justinuse
==git_justinuse
|| !ask_user_for_cmap
|| (i
= PickCMap(cmap_encs
,usable_encs
,def
))==-1 )
4480 LogError( _("Could not find a usable encoding table" ));
4485 info
->platform
= cmap_encs
[i
].platform
;
4486 info
->specific
= cmap_encs
[i
].specific
;
4488 desired_cmaps
[0] = cmap_encs
[i
]; dcnt
= 1;
4489 if ( unicode4_cmap
!=-1 ) {
4490 if ( i
!=unicode4_cmap
) {
4491 desired_cmaps
[1] = cmap_encs
[unicode4_cmap
];
4494 } else if ( unicode_cmap
!=-1 ) {
4495 if ( i
!=unicode_cmap
) {
4496 desired_cmaps
[1] = cmap_encs
[unicode_cmap
];
4500 if ( i
!=def
&& def
!=-1 ) {
4501 desired_cmaps
[1] = cmap_encs
[def
];
4507 if ( justinuse
==git_justinuse
) {
4508 dcmap_cnt
= usable_encs
;
4512 dcmap
= desired_cmaps
;
4514 for ( dc
=dcmap_cnt
-1; dc
>=0; --dc
) {
4515 /* if justinuse then look at all cmaps and tick the glyphs they use */
4516 /* otherwise dcmap_cnt will be either 1 or 2. If 1 then this subtable */
4517 /* contains both the encoding and the source for unicode encodings */
4518 /* if dcmap_cnt==2 then when dc==0 we are setting up the encoding */
4519 /* and when dc==1 we are setting up the unicode code points */
4520 int dounicode
= (dc
==dcmap_cnt
-1);
4521 enc
= dcmap
[dc
].enc
;
4522 encoff
= dcmap
[dc
].offset
;
4524 if ( dc
==0 && justinuse
==git_normal
) {
4525 interp
= interp_from_encoding(enc
,ui_none
);
4527 if ( dcmap
[dc
].platform
==3 && (dcmap
[dc
].specific
>=2 && dcmap
[dc
].specific
<=6 ))
4528 mod
= dcmap
[dc
].specific
;
4529 else if ( dcmap
[dc
].platform
==1 && (dcmap
[dc
].specific
==2 ||dcmap
[dc
].specific
==1||dcmap
[dc
].specific
==3||dcmap
[dc
].specific
==25))
4530 mod
= dcmap
[dc
].specific
==1?2:dcmap
[dc
].specific
==2?4:dcmap
[dc
].specific
==3?5:3; /* convert to ms specific */
4531 info
->map
= map
= EncMapNew(enc
->char_cnt
,info
->glyph_cnt
,enc
);
4532 info
->uni_interp
= interp
;
4535 fseek(ttf
,info
->encoding_start
+encoff
,SEEK_SET
);
4536 format
= getushort(ttf
);
4537 if ( format
!=12 && format
!=10 && format
!=8 ) {
4538 len
= getushort(ttf
);
4539 /* version/language = */ getushort(ttf
);
4541 /* padding */ getushort(ttf
);
4543 /* language = */ getlong(ttf
);
4545 if ( enc
->is_unicodebmp
&& (format
==8 || format
==10 || format
==12))
4546 enc
= FindOrMakeEncoding("UnicodeFull");
4549 if ( justinuse
==git_normal
&& map
!=NULL
&& map
->enccount
<256 ) {
4550 map
->map
= grealloc(map
->map
,256*sizeof(int));
4551 memset(map
->map
,-1,(256-map
->enccount
)*sizeof(int));
4552 map
->enccount
= map
->encmax
= 256;
4554 for ( i
=0; i
<len
-6; ++i
)
4555 table
[i
] = getc(ttf
);
4556 trans
= enc
->unicode
;
4557 if ( trans
==NULL
&& dcmap
[dc
].platform
==1 )
4558 trans
= MacEncToUnicode(dcmap
[dc
].specific
,dcmap
[dc
].lang
-1);
4559 for ( i
=0; i
<256 && i
<len
-6; ++i
)
4560 if ( justinuse
==git_normal
) {
4561 if ( table
[i
]<info
->glyph_cnt
&& info
->chars
[table
[i
]]!=NULL
) {
4563 map
->map
[i
] = table
[i
];
4564 if ( dounicode
&& trans
!=NULL
)
4565 info
->chars
[table
[i
]]->unicodeenc
= trans
[i
];
4567 } else if ( table
[i
]<info
->glyph_cnt
&& info
->chars
[table
[i
]]!=NULL
)
4568 info
->inuse
[table
[i
]] = 1;
4569 } else if ( format
==4 ) {
4570 segCount
= getushort(ttf
)/2;
4571 /* searchRange = */ getushort(ttf
);
4572 /* entrySelector = */ getushort(ttf
);
4573 /* rangeShift = */ getushort(ttf
);
4574 endchars
= galloc(segCount
*sizeof(uint16
));
4575 used
= gcalloc(65536,sizeof(uint8
));
4576 for ( i
=0; i
<segCount
; ++i
)
4577 endchars
[i
] = getushort(ttf
);
4578 if ( getushort(ttf
)!=0 )
4579 IError("Expected 0 in 'cmap' format 4 subtable");
4580 startchars
= galloc(segCount
*sizeof(uint16
));
4581 for ( i
=0; i
<segCount
; ++i
)
4582 startchars
[i
] = getushort(ttf
);
4583 delta
= galloc(segCount
*sizeof(uint16
));
4584 for ( i
=0; i
<segCount
; ++i
)
4585 delta
[i
] = getushort(ttf
);
4586 rangeOffset
= galloc(segCount
*sizeof(uint16
));
4587 for ( i
=0; i
<segCount
; ++i
)
4588 rangeOffset
[i
] = getushort(ttf
);
4589 len
-= 8*sizeof(uint16
) +
4590 4*segCount
*sizeof(uint16
);
4591 /* that's the amount of space left in the subtable and it must */
4592 /* be filled with glyphIDs */
4594 IError("This font has an illegal format 4 subtable with too little space for all the segments.\nThis error is not recoverable.\nBye" );
4597 glyphs
= galloc(len
);
4599 for ( i
=0; i
<glyph_tot
; ++i
)
4600 glyphs
[i
] = getushort(ttf
);
4601 for ( i
=0; i
<segCount
; ++i
) {
4602 if ( rangeOffset
[i
]==0 && startchars
[i
]==0xffff )
4604 else if ( rangeOffset
[i
]==0 ) {
4605 for ( j
=startchars
[i
]; j
<=endchars
[i
]; ++j
) {
4606 if ( justinuse
==git_justinuse
&& (uint16
) (j
+delta
[i
])<info
->glyph_cnt
)
4607 info
->inuse
[(uint16
) (j
+delta
[i
])] = true;
4608 else if ( (uint16
) (j
+delta
[i
])>=info
->glyph_cnt
|| info
->chars
[(uint16
) (j
+delta
[i
])]==NULL
) {
4609 LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
4610 (uint16
) (j
+delta
[i
]), modenc(j
,mod
), modenc(j
,mod
));
4611 info
->bad_cmap
= true;
4613 int uenc
= umodenc(j
,mod
,info
);
4614 int lenc
= modenc(j
,mod
);
4615 if ( uenc
!=-1 && used
[uenc
] ) {
4616 if ( !badencwarned
) {
4617 LogError( _("Multiple glyphs map to the same unicode encoding U+%04X, only one will be used\n"), uenc
);
4618 info
->bad_cmap
= true;
4619 badencwarned
= true;
4622 if ( uenc
!=-1 && dounicode
) used
[uenc
] = true;
4623 if ( dounicode
&& info
->chars
[(uint16
) (j
+delta
[i
])]->unicodeenc
==-1 )
4624 info
->chars
[(uint16
) (j
+delta
[i
])]->unicodeenc
= uenc
;
4625 if ( map
!=NULL
&& lenc
<map
->enccount
)
4626 map
->map
[lenc
] = (uint16
) (j
+delta
[i
]);
4630 } else if ( rangeOffset
[i
]!=0xffff ) {
4631 /* Apple says a rangeOffset of 0xffff means no glyph */
4632 /* OpenType doesn't mention this */
4633 for ( j
=startchars
[i
]; j
<=endchars
[i
]; ++j
) {
4634 int temp
= (i
-segCount
+rangeOffset
[i
]/2) + j
-startchars
[i
];
4635 if ( temp
<glyph_tot
)
4636 index
= glyphs
[ temp
];
4638 /* This happened in mingliu.ttc(PMingLiU) */
4639 if ( justinuse
==git_normal
) {
4640 LogError( _("Glyph index out of bounds. Was %d, must be less than %d.\n In attempt to associate a glyph with encoding %x in segment %d\n with platform=%d, specific=%d (in 'cmap')\n"),
4641 temp
, glyph_tot
, j
, i
, dcmap
[dc
].platform
, dcmap
[dc
].specific
);
4642 info
->bad_cmap
= true;
4647 index
= (unsigned short) (index
+delta
[i
]);
4648 if ( index
>=info
->glyph_cnt
) {
4649 /* This isn't mentioned either, but in some */
4650 /* MS Chinese fonts (kaiu.ttf) the index */
4651 /* goes out of bounds. and MS's ttf dump */
4652 /* program says it is treated as 0 */
4653 LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
4654 index
, modenc(j
,mod
), modenc(j
,mod
));
4655 info
->bad_cmap
= true;
4656 } else if ( justinuse
==git_justinuse
)
4657 info
->inuse
[index
] = 1;
4658 else if ( info
->chars
[index
]==NULL
) {
4659 LogError( _("Attempt to encode missing glyph %d to %d (0x%x)\n"),
4660 index
, modenc(j
,mod
), modenc(j
,mod
));
4661 info
->bad_cmap
= true;
4663 int uenc
= umodenc(j
,mod
,info
);
4664 int lenc
= modenc(j
,mod
);
4665 if ( uenc
!=-1 && used
[uenc
] ) {
4666 if ( !badencwarned
) {
4667 LogError( _("Multiple glyphs map to the same unicode encoding U+%04X, only one will be used\n"), uenc
);
4668 info
->bad_cmap
= true;
4669 badencwarned
= true;
4672 if ( uenc
!=-1 && dounicode
) used
[uenc
] = true;
4673 if ( dounicode
&& info
->chars
[index
]->unicodeenc
==-1 )
4674 info
->chars
[index
]->unicodeenc
= uenc
;
4675 if ( map
!=NULL
&& lenc
<map
->enccount
)
4676 map
->map
[lenc
] = index
;
4682 LogError( _("Use of a range offset of 0xffff to mean a missing glyph in cmap table\n") );
4683 info
->bad_cmap
= true;
4692 } else if ( format
==6 ) {
4693 /* trimmed array format */
4694 /* Well, the docs say it's for 2byte encodings, but Apple actually*/
4695 /* uses it for 1 byte encodings which don't fit into the require-*/
4696 /* ments for a format 0 sub-table. See Zapfino.dfont */
4698 first
= getushort(ttf
);
4699 count
= getushort(ttf
);
4700 trans
= enc
->unicode
;
4701 if ( trans
==NULL
&& dcmap
[dc
].platform
==1 && first
+count
<=256 )
4702 trans
= MacEncToUnicode(dcmap
[dc
].specific
,dcmap
[dc
].lang
-1);
4703 if ( justinuse
==git_justinuse
)
4704 for ( i
=0; i
<count
; ++i
)
4705 info
->inuse
[getushort(ttf
)]= 1;
4707 for ( i
=0; i
<count
; ++i
) {
4708 int gid
= getushort(ttf
);
4710 info
->chars
[gid
]->unicodeenc
= trans
!=NULL
? trans
[first
+1] : first
+i
;
4711 if ( map
!=NULL
&& first
+i
< map
->enccount
)
4712 map
->map
[first
+i
] = gid
;
4715 } else if ( format
==2 ) {
4716 int max_sub_head_key
= 0, cnt
, max_pos
= -1;
4717 struct subhead
*subheads
;
4719 for ( i
=0; i
<256; ++i
) {
4720 table
[i
] = getushort(ttf
)/8; /* Sub-header keys */
4721 if ( table
[i
]>max_sub_head_key
) {
4722 max_sub_head_key
= table
[i
]; /* The entry is a byte pointer, I want a pointer in units of struct subheader */
4726 subheads
= galloc((max_sub_head_key
+1)*sizeof(struct subhead
));
4727 for ( i
=0; i
<=max_sub_head_key
; ++i
) {
4728 subheads
[i
].first
= getushort(ttf
);
4729 subheads
[i
].cnt
= getushort(ttf
);
4730 subheads
[i
].delta
= getushort(ttf
);
4731 subheads
[i
].rangeoff
= (getushort(ttf
)-
4732 (max_sub_head_key
-i
)*sizeof(struct subhead
)-
4733 sizeof(short))/sizeof(short);
4735 cnt
= (len
-(ftell(ttf
)-(info
->encoding_start
+encoff
)))/sizeof(short);
4736 /* The count is the number of glyph indexes to read. it is the */
4737 /* length of the entire subtable minus that bit we've read so far */
4738 glyphs
= galloc(cnt
*sizeof(short));
4739 for ( i
=0; i
<cnt
; ++i
)
4740 glyphs
[i
] = getushort(ttf
);
4742 for ( i
=0; i
<256; ++i
) {
4743 if ( table
[i
]==0 ) {
4744 /* Special case, single byte encoding entry, look it up in */
4746 /* In the one example I've got of this encoding (wcl-02.ttf) the chars */
4747 /* 0xfd, 0xfe, 0xff are said to exist but there is no mapping */
4750 index
= 0; /* the subhead says there are 256 entries, but in fact there are only 193, so attempting to find these guys should give an error */
4751 else if ( i
<subheads
[0].first
|| i
>=subheads
[0].first
+subheads
[0].cnt
||
4752 subheads
[0].rangeoff
+(i
-subheads
[0].first
)>=cnt
)
4754 else if ( (index
= glyphs
[subheads
[0].rangeoff
+(i
-subheads
[0].first
)])!= 0 )
4755 index
= (uint32
) (index
+subheads
[0].delta
);
4756 /* I assume the single byte codes are just ascii or latin1*/
4757 if ( index
!=0 && index
<info
->glyph_cnt
) {
4758 if ( justinuse
==git_justinuse
)
4759 info
->inuse
[index
] = 1;
4760 else if ( info
->chars
[index
]==NULL
)
4763 int lenc
= modenc(i
,mod
);
4764 if ( dounicode
&& info
->chars
[index
]->unicodeenc
==-1 )
4765 info
->chars
[index
]->unicodeenc
= i
;
4766 if ( map
!=NULL
&& lenc
<map
->enccount
)
4767 map
->map
[lenc
] = index
;
4772 for ( j
=0; j
<subheads
[k
].cnt
; ++j
) {
4774 if ( subheads
[k
].rangeoff
+j
>=cnt
)
4776 else if ( (index
= glyphs
[subheads
[k
].rangeoff
+j
])!= 0 )
4777 index
= (uint16
) (index
+subheads
[k
].delta
);
4778 if ( index
!=0 && index
<info
->glyph_cnt
) {
4779 enc
= (i
<<8)|(j
+subheads
[k
].first
);
4780 lenc
= modenc(enc
,mod
);
4781 if ( justinuse
==git_justinuse
)
4782 info
->inuse
[index
] = 1;
4783 else if ( info
->chars
[index
]==NULL
)
4786 if ( dounicode
&& info
->chars
[index
]->unicodeenc
==-1 )
4787 info
->chars
[index
]->unicodeenc
= umodenc(enc
,mod
,info
);
4788 if ( map
!=NULL
&& lenc
<map
->enccount
)
4789 map
->map
[lenc
] = index
;
4793 /*if ( last==-1 ) last = i;*/
4798 } else if ( format
==8 ) {
4799 uint32 ngroups
, start
, end
, startglyph
;
4800 if ( !enc
->is_unicodefull
) {
4801 IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
4802 enc
= FindOrMakeEncoding("UnicodeFull");
4804 /* I'm now assuming unicode surrogate encoding, so I just ignore */
4805 /* the is32 table (it will be set for the surrogates and not for */
4807 fseek(ttf
,8192,SEEK_CUR
);
4808 ngroups
= getlong(ttf
);
4809 for ( j
=0; j
<(int)ngroups
; ++j
) {
4810 start
= getlong(ttf
);
4812 startglyph
= getlong(ttf
);
4813 if ( justinuse
==git_justinuse
)
4814 for ( i
=start
; i
<=(int)end
; ++i
)
4815 info
->inuse
[startglyph
+i
-start
]= 1;
4817 for ( i
=start
; i
<=(int)end
; ++i
) {
4818 int uenc
= ((i
>>16)-0xd800)*0x400 + (i
&0xffff)-0xdc00 + 0x10000;
4819 sc
= info
->chars
[startglyph
+i
-start
];
4820 if ( dounicode
&& sc
->unicodeenc
==-1 )
4821 sc
->unicodeenc
= uenc
;
4822 if ( map
!=NULL
&& sc
->unicodeenc
< map
->enccount
)
4823 map
->map
[uenc
] = startglyph
+i
-start
;
4826 } else if ( format
==10 ) {
4827 /* same as format 6, except for 4byte chars */
4829 if ( !enc
->is_unicodefull
) {
4830 IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
4831 enc
= FindOrMakeEncoding("UnicodeFull");
4833 first
= getlong(ttf
);
4834 count
= getlong(ttf
);
4835 if ( justinuse
==git_justinuse
)
4836 for ( i
=0; i
<count
; ++i
)
4837 info
->inuse
[getushort(ttf
)]= 1;
4839 for ( i
=0; i
<count
; ++i
) {
4840 int gid
= getushort(ttf
);
4842 info
->chars
[gid
]->unicodeenc
= first
+i
;
4843 if ( map
!=NULL
&& first
+i
< map
->enccount
)
4844 map
->map
[first
+i
] = gid
;
4846 } else if ( format
==12 ) {
4847 uint32 ngroups
, start
, end
, startglyph
;
4848 if ( !enc
->is_unicodefull
) {
4849 IError("I don't support 32 bit characters except for the UCS-4 (MS platform, specific=10)" );
4850 enc
= FindOrMakeEncoding("UnicodeFull");
4852 ngroups
= getlong(ttf
);
4853 for ( j
=0; j
<(int)ngroups
; ++j
) {
4854 start
= getlong(ttf
);
4856 startglyph
= getlong(ttf
);
4857 if ( justinuse
==git_justinuse
) {
4858 for ( i
=start
; i
<=(int)end
; ++i
)
4859 if ( startglyph
+i
-start
< (unsigned)info
->glyph_cnt
)
4860 info
->inuse
[startglyph
+i
-start
]= 1;
4864 for ( i
=start
; i
<=(int)end
; ++i
) {
4865 if ( startglyph
+i
-start
>= (unsigned)info
->glyph_cnt
||
4866 info
->chars
[startglyph
+i
-start
]==NULL
) {
4867 LogError( _("Bad font: Encoding data out of range.\n") );
4868 info
->bad_cmap
= true;
4872 info
->chars
[startglyph
+i
-start
]->unicodeenc
= i
;
4873 if ( map
!=NULL
&& i
< map
->enccount
&& i
>=0)
4874 map
->map
[i
] = startglyph
+i
-start
;
4881 if ( info
->chars
!=NULL
)
4882 for ( i
=0; i
<info
->glyph_cnt
; ++i
)
4883 if ( info
->chars
[i
]!=NULL
&& info
->chars
[i
]->unicodeenc
==0xffff )
4884 info
->chars
[i
]->unicodeenc
= -1;
4885 info
->vs_start
= vs_map
;
4887 ApplyVariationSequenceSubtable(ttf
,vs_map
,info
,justinuse
);
4888 if ( justinuse
==git_normal
) {
4889 if ( interp
==ui_none
)
4890 info
->uni_interp
= amscheck(info
,map
);
4891 map
->enc
= enc
; /* This can be changed from the initial value */
4896 static void readttfos2metrics(FILE *ttf
,struct ttfinfo
*info
) {
4899 fseek(ttf
,info
->os2_start
,SEEK_SET
);
4900 info
->os2_version
= getushort(ttf
);
4902 info
->pfminfo
.avgwidth
= getushort(ttf
);
4904 /* avgwidth */ getushort(ttf
);
4906 info
->pfminfo
.weight
= getushort(ttf
);
4907 info
->pfminfo
.width
= getushort(ttf
);
4908 info
->pfminfo
.fstype
= getushort(ttf
);
4909 info
->pfminfo
.os2_subxsize
= getushort(ttf
);
4910 info
->pfminfo
.os2_subysize
= getushort(ttf
);
4911 info
->pfminfo
.os2_subxoff
= getushort(ttf
);
4912 info
->pfminfo
.os2_subyoff
= getushort(ttf
);
4913 info
->pfminfo
.os2_supxsize
= getushort(ttf
);
4914 info
->pfminfo
.os2_supysize
= getushort(ttf
);
4915 info
->pfminfo
.os2_supxoff
= getushort(ttf
);
4916 info
->pfminfo
.os2_supyoff
= getushort(ttf
);
4917 info
->pfminfo
.os2_strikeysize
= getushort(ttf
);
4918 info
->pfminfo
.os2_strikeypos
= getushort(ttf
);
4919 info
->pfminfo
.os2_family_class
= getushort(ttf
);
4920 for ( i
=0; i
<10; ++i
)
4921 info
->pfminfo
.panose
[i
] = getc(ttf
);
4922 info
->pfminfo
.pfmfamily
= info
->pfminfo
.panose
[0]==2 ? 0x11 : /* might be 0x21 */ /* Text & Display maps to either serif 0x11 or sans 0x21 or monospace 0x31 */
4923 info
->pfminfo
.panose
[0]==3 ? 0x41 : /* Script */
4924 info
->pfminfo
.panose
[0]==4 ? 0x51 : /* Decorative */
4925 0x51; /* And pictorial doesn't fit into pfm */
4926 info
->pfminfo
.unicoderanges
[0] = getlong(ttf
);
4927 info
->pfminfo
.unicoderanges
[1] = getlong(ttf
);
4928 info
->pfminfo
.unicoderanges
[2] = getlong(ttf
);
4929 info
->pfminfo
.unicoderanges
[3] = getlong(ttf
);
4930 info
->pfminfo
.hasunicoderanges
= true;
4931 info
->pfminfo
.os2_vendor
[0] = getc(ttf
);
4932 info
->pfminfo
.os2_vendor
[1] = getc(ttf
);
4933 info
->pfminfo
.os2_vendor
[2] = getc(ttf
);
4934 info
->pfminfo
.os2_vendor
[3] = getc(ttf
);
4935 sel
= getushort(ttf
);
4936 if ( info
->os2_version
>=4 ) {
4937 info
->use_typo_metrics
= (sel
&128)?1:0;
4938 info
->weight_width_slope_only
= (sel
&256)?1:0;
4941 info
->pfminfo
.firstchar
= getushort(ttf
);
4942 info
->pfminfo
.lastchar
= getushort(ttf
);
4944 /* firstchar */ getushort(ttf
);
4945 /* lastchar */ getushort(ttf
);
4947 info
->pfminfo
.os2_typoascent
= getushort(ttf
);
4948 info
->pfminfo
.os2_typodescent
= (short) getushort(ttf
);
4949 if ( info
->pfminfo
.os2_typoascent
-info
->pfminfo
.os2_typodescent
== info
->emsize
) {
4950 info
->ascent
= info
->pfminfo
.os2_typoascent
;
4951 info
->descent
= -info
->pfminfo
.os2_typodescent
;
4953 info
->pfminfo
.os2_typolinegap
= getushort(ttf
);
4954 info
->pfminfo
.os2_winascent
= getushort(ttf
);
4955 info
->pfminfo
.os2_windescent
= getushort(ttf
);
4956 info
->pfminfo
.winascent_add
= info
->pfminfo
.windescent_add
= false;
4957 info
->pfminfo
.typoascent_add
= info
->pfminfo
.typodescent_add
= false;
4958 info
->pfminfo
.pfmset
= true;
4959 info
->pfminfo
.panose_set
= true;
4960 info
->pfminfo
.subsuper_set
= true;
4961 if ( info
->os2_version
>=1 ) {
4962 info
->pfminfo
.codepages
[0] = getlong(ttf
);
4963 info
->pfminfo
.codepages
[1] = getlong(ttf
);
4964 info
->pfminfo
.hascodepages
= true;
4967 if ( info
->os2_version
>=3 ) { /* TH just in case */
4968 info
->pfminfo
.os2_xheight
= getushort(ttf
); /* four new fields */
4969 info
->pfminfo
.os2_capheight
= getushort(ttf
);
4970 info
->pfminfo
.os2_defaultchar
= getushort(ttf
);
4971 info
->pfminfo
.os2_breakchar
= getushort(ttf
);
4974 if ( info
->os2_version
==0 ) {
4975 LogError("Windows will reject fonts with an OS/2 version number of 0\n");
4976 info
->bad_os2_version
= true;
4977 } else if ( info
->os2_version
==1 && info
->cff_start
!=0 ) {
4978 LogError("Windows will reject otf (cff) fonts with an OS/2 version number of 1\n");
4979 info
->bad_os2_version
= true;
4984 static int cmapEncFromName(struct ttfinfo
*info
,const char *nm
, int glyphid
) {
4988 if ( info
->map
!=NULL
)
4989 uni
= EncFromName(nm
,info
->uni_interp
,info
->map
->enc
);
4991 uni
= EncFromName(nm
,ui_none
,&custom
);
4995 for ( i
=0; i
<info
->glyph_cnt
; ++i
) if ( info
->chars
[i
]!=NULL
) {
4996 if ( info
->chars
[i
]->unicodeenc
==uni
) {
4997 if ( info
->complainedmultname
)
4998 /* Don't do it again */;
4999 else if ( info
->chars
[i
]->name
!=NULL
&& strcmp(info
->chars
[i
]->name
,nm
)==0 )
5000 LogError( _("Warning: Glyph %d has the same name (%s) as Glyph %d\n"),
5003 LogError( _("Warning: Glyph %d is named %s which should mean it is mapped to\n Unicode U+%04X, but Glyph %d already has that encoding.\n"),
5004 glyphid
, nm
, uni
, i
);
5005 info
->complainedmultname
= true;
5013 static void readttfpostnames(FILE *ttf
,struct ttfinfo
*info
) {
5015 int format
, len
, gc
, gcbig
, val
;
5019 int notdefwarned
= false;
5020 int anynames
= false;
5022 ff_progress_change_line2(_("Reading Names"));
5024 /* Give ourselves an xuid, just in case they want to convert to PostScript*/
5026 if ( xuid
!=NULL
&& info
->fd
==NULL
&& info
->xuid
==NULL
) {
5027 info
->xuid
= galloc(strlen(xuid
)+20);
5028 sprintf(info
->xuid
,"[%s %d]", xuid
, (rand()&0xffffff));
5031 if ( info
->postscript_start
!=0 ) {
5032 fseek(ttf
,info
->postscript_start
,SEEK_SET
);
5033 format
= getlong(ttf
);
5034 info
->italicAngle
= getfixed(ttf
);
5035 info
->upos
= (short) getushort(ttf
);
5036 info
->uwidth
= (short) getushort(ttf
);
5037 info
->upos
+= info
->uwidth
/2; /* 'post' defn of this field is different from FontInfo defn and I didn't notice */
5038 /* fixedpitch = */ getlong(ttf
);
5039 /* mem1 = */ getlong(ttf
);
5040 /* mem2 = */ getlong(ttf
);
5041 /* mem3 = */ getlong(ttf
);
5042 /* mem4 = */ getlong(ttf
);
5043 if ( format
==0x00020000 ) {
5044 gc
= getushort(ttf
);
5045 indexes
= gcalloc(65536,sizeof(uint16
));
5046 /* the index table is backwards from the way I want to use it */
5048 for ( i
=0; i
<gc
; ++i
) {
5049 indexes
[val
= getushort(ttf
)] = i
;
5050 if ( val
>=258 ) ++gcbig
;
5053 /* if we are only loading bitmaps, we can get holes in our data */
5054 for ( i
=0; i
<258; ++i
) if ( indexes
[i
]!=0 || i
==0 ) if ( indexes
[i
]<info
->glyph_cnt
&& info
->chars
[indexes
[i
]]!=NULL
) {
5055 info
->chars
[indexes
[i
]]->name
= copy(ttfstandardnames
[i
]);
5056 #if 0 /* Too many fonts have badly named glyphs */
5057 if ( info
->chars
[indexes
[i
]]->unicodeenc
==-1 )
5058 info
->chars
[indexes
[i
]]->unicodeenc
= cmapEncFromName(info
,ttfstandardnames
[i
],indexes
[i
]);
5062 for ( i
=258; i
<gcbig
; ++i
) {
5065 if ( len
<0 ) /* Don't crash on EOF */
5068 for ( j
=0; j
<len
; ++j
)
5071 if ( indexes
[i
]<info
->glyph_cnt
&& info
->chars
[indexes
[i
]]!=NULL
) {
5072 if (info
->chars
[indexes
[i
]]->name
)
5073 free( info
->chars
[indexes
[i
]]->name
);
5074 info
->chars
[indexes
[i
]]->name
= nm
;
5075 #if 0 /* Too many fonts have badly named glyphs */
5076 if ( info
->chars
[indexes
[i
]]->unicodeenc
==-1 )
5077 info
->chars
[indexes
[i
]]->unicodeenc
= cmapEncFromName(info
,nm
,indexes
[i
]);
5086 if ( info
->fd
!=NULL
&& info
->fd
->chars
!=NULL
) {
5088 struct pschars
*chars
= info
->fd
->chars
;
5089 if ( info
->map
==NULL
)
5090 info
->map
= map
= EncMapNew(65536,65536,FindOrMakeEncoding("UnicodeBmp"));
5091 /* In type42 fonts the names are stored in a postscript /CharStrings dictionary */
5092 for ( i
=0; i
<chars
->next
; ++i
) {
5093 int gid
= (intpt
) (chars
->values
[i
]);
5094 if ( gid
>=0 && gid
<info
->glyph_cnt
&& chars
->keys
[i
]!=NULL
) {
5095 free(info
->chars
[gid
]->name
);
5096 info
->chars
[gid
]->name
= chars
->keys
[i
];
5097 info
->chars
[gid
]->unicodeenc
= UniFromName(chars
->keys
[i
],info
->uni_interp
,info
->map
->enc
);
5098 if ( map
!=NULL
&& info
->chars
[gid
]->unicodeenc
!=-1 &&
5099 info
->chars
[gid
]->unicodeenc
<map
->enccount
)
5100 map
->map
[ info
->chars
[gid
]->unicodeenc
] = gid
;
5101 chars
->keys
[i
] = NULL
;
5102 chars
->values
[i
] = NULL
;
5104 chars
->values
[i
] = NULL
;
5108 for ( i
=0; i
<info
->glyph_cnt
; ++i
) if ( info
->chars
[i
]!=NULL
) {
5109 /* info->chars[i] can be null in some TTC files */
5110 if ( i
!=0 && info
->chars
[i
]->name
!=NULL
&&
5111 strcmp(info
->chars
[i
]->name
,".notdef")==0 ) {
5112 /* for some reason MS puts out fonts where several characters */
5113 /* are called .notdef (and only one is a real notdef). So if we */
5114 /* find a glyph other than 0 called ".notdef" then pretend it had */
5116 if ( !notdefwarned
) {
5117 notdefwarned
= true;
5118 LogError( _("Glyph %d is called \".notdef\", a singularly inept choice of name (only glyph 0\n may be called .notdef)\nFontForge will rename it.\n"), i
);
5120 free(info
->chars
[i
]->name
);
5121 info
->chars
[i
]->name
= NULL
;
5122 /* I used to check for glyphs with bad names (ie. names indicative of */
5123 /* another unicode code point than the one applied to the glyph) but */
5124 /* this proves too early for that check, as we don't have the altunis*/
5125 /* figured out yet. So I've moved that into its own routine later */
5127 /* And some volt files actually assign nul strings to the name */
5128 if ( (info
->chars
[i
]->name
!=NULL
&& *info
->chars
[i
]->name
!='\0' ))
5130 free(info
->chars
[i
]->name
); /* If it's a null string get rid of it */
5133 else if ( info
->chars
[i
]->unicodeenc
<0 ) {
5134 /* Do this later */;
5137 name
= StdGlyphName(buffer
,info
->chars
[i
]->unicodeenc
,info
->uni_interp
,NULL
);
5138 if (THtest_duplicate_glyph_names
&& anynames
) {
5139 for ( j
=0; j
<info
->glyph_cnt
; ++j
) {
5140 if ( info
->chars
[j
]!=NULL
&& j
!=i
&& info
->chars
[j
]->name
!=NULL
) {
5141 if ( strcmp(info
->chars
[j
]->name
,name
)==0 ) {
5150 info
->chars
[i
]->name
= copy(name
);
5153 /* If we have a GSUB table we can give some unencoded glyphs names */
5154 /* for example if we have a vrt2 substitution of A to <unencoded> */
5155 /* we could name the unencoded "A.vrt2" (though in this case we might */
5156 /* try A.vert instead */ /* Werner suggested this */
5157 for ( i
=info
->glyph_cnt
-1; i
>=0 ; --i
)
5158 if ( info
->chars
[i
]!=NULL
&& info
->chars
[i
]->name
==NULL
)
5160 if ( i
>=0 && info
->vs_start
!=0 )
5161 ApplyVariationSequenceSubtable(ttf
,info
->vs_start
,info
,git_findnames
);
5162 if ( i
>=0 && info
->gsub_start
!=0 )
5163 GuessNamesFromGSUB(ttf
,info
);
5164 if ( i
>=0 && info
->math_start
!=0 )
5165 GuessNamesFromMATH(ttf
,info
);
5167 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
5168 /* info->chars[i] can be null in some TTC files */
5169 if ( info
->chars
[i
]==NULL
)
5171 if ( info
->chars
[i
]->name
!=NULL
)
5173 if ( info
->ordering
!=NULL
)
5174 sprintf(buffer
, "%.20s-%d", info
->ordering
, i
);
5175 else if ( info
->map
!=NULL
&& info
->map
->backmap
[i
]!=-1 )
5176 sprintf(buffer
, "nounicode.%d.%d.%x", info
->platform
, info
->specific
,
5177 (int) info
->map
->backmap
[i
] );
5179 sprintf( buffer
, "glyph%d", i
);
5180 info
->chars
[i
]->name
= copy(buffer
);
5183 ff_progress_next_stage();
5186 static void readttfgasp(FILE *ttf
,struct ttfinfo
*info
) {
5189 if ( info
->gasp_start
==0 )
5192 fseek(ttf
,info
->gasp_start
,SEEK_SET
);
5193 info
->gasp_version
= getushort(ttf
);
5194 if ( info
->gasp_version
!=0 && info
->gasp_version
!=1 )
5195 return; /* We only support 'gasp' versions 0&1 (no other versions currently) */
5196 info
->gasp_cnt
= cnt
= getushort(ttf
);
5199 info
->gasp
= galloc(cnt
*sizeof(struct gasp
));
5200 for ( i
=0; i
<cnt
; ++i
) {
5201 info
->gasp
[i
].ppem
= getushort(ttf
);
5202 info
->gasp
[i
].flags
= getushort(ttf
);
5206 static void UnfigureControls(Spline
*spline
,BasePoint
*pos
) {
5207 pos
->x
= rint( (spline
->splines
[0].c
+2*spline
->splines
[0].d
)/2 );
5208 pos
->y
= rint( (spline
->splines
[1].c
+2*spline
->splines
[1].d
)/2 );
5211 int ttfFindPointInSC(SplineChar
*sc
,int layer
,int pnum
,BasePoint
*pos
,
5218 for ( ss
= sc
->layers
[layer
].splines
; ss
!=NULL
; ss
=ss
->next
) {
5219 for ( sp
=ss
->first
; ; ) {
5220 if ( sp
->ttfindex
==pnum
) {
5223 } else if ( sp
->nextcpindex
==pnum
) {
5224 if ( sp
->next
!=NULL
&& sp
->next
->order2
)
5227 /* fix this up to be 2 degree bezier control point */
5228 UnfigureControls(sp
->next
,pos
);
5232 if ( !sp
->nonextcp
&& last
<=sp
->nextcpindex
)
5233 last
= sp
->nextcpindex
+1;
5234 else if ( sp
->ttfindex
!=0xffff )
5235 last
= sp
->ttfindex
+1;
5236 if ( sp
->next
==NULL
)
5239 if ( sp
==ss
->first
)
5243 for ( refs
=sc
->layers
[layer
].refs
; refs
!=NULL
; refs
=refs
->next
) {
5244 if ( refs
==bound
) {
5245 LogError( _("Invalid point match. Point would be after this reference.\n") );
5248 ret
= ttfFindPointInSC(refs
->sc
,ly_fore
,pnum
-last
,pos
,NULL
);
5251 p
.x
= refs
->transform
[0]*pos
->x
+ refs
->transform
[2]*pos
->y
+ refs
->transform
[4];
5252 p
.y
= refs
->transform
[1]*pos
->x
+ refs
->transform
[3]*pos
->y
+ refs
->transform
[5];
5258 IError("Point match failure last=%d, pnum=%d", last
, pnum
);
5262 return( last
); /* Count of number of points in the character */
5265 static void ttfPointMatch(SplineChar
*sc
,RefChar
*rf
) {
5266 BasePoint sofar
, inref
;
5268 if ( ttfFindPointInSC(sc
,ly_fore
,rf
->match_pt_base
,&sofar
,rf
)!=-1 ||
5269 ttfFindPointInSC(rf
->sc
,ly_fore
,rf
->match_pt_ref
,&inref
,NULL
)!=-1 ) {
5270 LogError( _("Could not match points in composite glyph (%d to %d) when adding %s to %s\n"),
5271 rf
->match_pt_base
, rf
->match_pt_ref
, rf
->sc
->name
, sc
->name
);
5274 rf
->transform
[4] = sofar
.x
-inref
.x
;
5275 rf
->transform
[5] = sofar
.y
-inref
.y
;
5278 int ttfFixupRef(SplineChar
**chars
,int i
) {
5279 RefChar
*ref
, *prev
, *next
;
5281 if ( chars
[i
]==NULL
) /* Can happen in ttc files */
5283 if ( chars
[i
]->ticked
)
5285 chars
[i
]->ticked
= true;
5287 for ( ref
=chars
[i
]->layers
[ly_fore
].refs
; ref
!=NULL
; ref
=next
) {
5288 if ( ref
->sc
!=NULL
)
5289 break; /* Already done */
5291 if ( !ttfFixupRef(chars
,ref
->orig_pos
)) {
5293 chars
[i
]->layers
[ly_fore
].refs
= next
;
5296 chunkfree(ref
,sizeof(RefChar
));
5298 ref
->sc
= chars
[ref
->orig_pos
];
5299 ref
->adobe_enc
= getAdobeEnc(ref
->sc
->name
);
5300 if ( ref
->point_match
)
5301 ttfPointMatch(chars
[i
],ref
);
5302 SCReinstanciateRefChar(chars
[i
],ref
,ly_fore
);
5303 SCMakeDependent(chars
[i
],ref
->sc
);
5307 chars
[i
]->ticked
= false;
5311 static void ttfFixupReferences(struct ttfinfo
*info
) {
5314 ff_progress_change_line2(_("Fixing up References"));
5315 for ( i
=0; i
<info
->glyph_cnt
; ++i
) if ( info
->chars
[i
]!=NULL
)
5316 info
->chars
[i
]->ticked
= false;
5317 for ( i
=0; i
<info
->glyph_cnt
; ++i
) {
5318 ttfFixupRef(info
->chars
,i
);
5321 ff_progress_next_stage();
5324 static void TtfCopyTableBlindly(struct ttfinfo
*info
,FILE *ttf
,
5325 uint32 start
,uint32 len
,uint32 tag
) {
5326 struct ttf_table
*tab
;
5328 if ( start
==0 || len
==0 )
5330 if ( len
>0x1000000 ) {
5331 LogError( _("Unlikely length for table, so I'm ignoring it. %u\n"), len
);
5335 tab
= chunkalloc(sizeof(struct ttf_table
));
5338 tab
->data
= galloc(len
);
5339 fseek(ttf
,start
,SEEK_SET
);
5340 if (fread(tab
->data
,1,len
,ttf
) != (size_t)len
) {
5341 LogError( _("Unable to read %u bytes for data, so I'm ignoring it.\n"), len
);
5342 if (tab
->data
!=NULL
) free(tab
->data
);
5343 if (tab
!=NULL
) free(tab
);
5346 tab
->next
= info
->tabs
;
5350 static int LookupListHasFeature(OTLookup
*otl
,uint32 tag
) {
5351 FeatureScriptLangList
*feat
;
5353 while ( otl
!=NULL
) {
5354 for ( feat
= otl
->features
; feat
!=NULL
; feat
=feat
->next
)
5355 if ( feat
->featuretag
== tag
)
5362 static int readttf(FILE *ttf
, struct ttfinfo
*info
, char *filename
) {
5366 ff_progress_change_stages(3);
5367 if ( !readttfheader(ttf
,info
,filename
,&info
->chosenname
)) {
5370 oldloc
= setlocale(LC_NUMERIC
,"C"); /* TrueType doesn't need this but opentype dictionaries do */
5371 readttfpreglyph(ttf
,info
);
5372 ff_progress_change_total(info
->glyph_cnt
);
5374 /* If font only contains bitmaps, then only read bitmaps */
5375 if ( (info
->glyphlocations_start
==0 || info
->glyph_length
==0) &&
5376 info
->cff_start
==0 && info
->typ1_start
==0 &&
5377 info
->bitmapdata_start
!=0 && info
->bitmaploc_start
!=0 )
5378 info
->onlystrikes
= true;
5380 if ( !info
->onlystrikes
&&
5381 info
->glyphlocations_start
!=0 && info
->glyph_start
!=0 &&
5382 info
->cff_start
!=0 ) {
5385 buts
[0] = _("TTF 'glyf'");
5386 buts
[1] = _("OTF 'CFF '");
5387 buts
[2] = _("_Cancel");
5389 choice
= ff_ask(_("Pick a font, any font..."),(const char **) buts
,0,2,_("This font contains both a TrueType 'glyf' table and an OpenType 'CFF ' table. FontForge can only deal with one at a time, please pick which one you want to use"));
5391 setlocale(LC_NUMERIC
,oldloc
);
5393 } else if ( choice
==0 )
5396 info
->glyph_start
= info
->glyphlocations_start
= 0;
5399 if ( info
->onlystrikes
) {
5400 info
->chars
= gcalloc(info
->glyph_cnt
+1,sizeof(SplineChar
*));
5401 info
->to_order2
= new_fonts_are_order2
;
5402 } else if ( info
->glyphlocations_start
!=0 && info
->glyph_start
!=0 ) {
5403 info
->to_order2
= (!loaded_fonts_same_as_new
||
5404 (loaded_fonts_same_as_new
&& new_fonts_are_order2
));
5405 readttfglyphs(ttf
,info
);
5406 } else if ( info
->cff_start
!=0 ) {
5407 info
->to_order2
= (loaded_fonts_same_as_new
&& new_fonts_are_order2
);
5408 if ( !readcffglyphs(ttf
,info
) ) {
5409 setlocale(LC_NUMERIC
,oldloc
);
5412 } else if ( info
->typ1_start
!=0 ) {
5413 if ( !readtyp1glyphs(ttf
,info
) ) {
5414 setlocale(LC_NUMERIC
,oldloc
);
5418 setlocale(LC_NUMERIC
,oldloc
);
5421 if ( info
->bitmapdata_start
!=0 && info
->bitmaploc_start
!=0 )
5422 ; /*TTFLoadBitmaps(ttf,info,info->onlyonestrike);*/
5423 else if ( info
->onlystrikes
)
5424 ff_post_error( _("No Bitmap Strikes"), _("No (useable) bitmap strikes in this TTF font: %s"), filename
==NULL
? "<unknown>" : filename
);
5425 if ( info
->onlystrikes
&& info
->bitmaps
==NULL
) {
5427 setlocale(LC_NUMERIC
,oldloc
);
5430 if ( info
->hmetrics_start
!=0 )
5431 readttfwidths(ttf
,info
);
5432 else if ( info
->bitmapdata_start
!=0 && info
->bitmaploc_start
!=0 )
5433 dummywidthsfromstrike(ttf
,info
);
5434 if ( info
->vmetrics_start
!=0 && info
->vhea_start
!=0 )
5435 readttfvwidths(ttf
,info
);
5436 /* 'cmap' is not meaningful for cid keyed fonts, and not supplied for */
5438 /* Oops. It is meaningful for cid fonts. It just seemed redundant to me */
5439 /* but that was my ignorance. Adobe complains that FF doesn't read it */
5440 /* (We've already (probably) set the unicodeencs of the glyphs according */
5441 /* to the cidmap files, but we can override that here. Mmm. what about a*/
5442 /* glyph in cidmap but not in cmap???? */
5443 if ( /* info->cidregistry==NULL && */ info
->encoding_start
!=0 )
5444 readttfencodings(ttf
,info
,git_normal
);
5445 if ( info
->os2_start
!=0 )
5446 readttfos2metrics(ttf
,info
);
5447 readttfpostnames(ttf
,info
); /* If no postscript table we'll guess at names */
5448 if ( info
->gdef_start
!=0 ) /* ligature caret positioning info */
5449 readttfgdef(ttf
,info
);
5450 if ( info
->base_start
!=0 )
5451 readttfbase(ttf
,info
);
5452 if ( info
->gasp_start
!=0 )
5453 readttfgasp(ttf
,info
);
5454 /* read the cvt table before reading variation data */
5455 if ( info
->to_order2
) {
5456 /* Yes, even though we've looked at maxp already, let's make a blind */
5457 /* copy too for those fields we can't compute on our own */
5458 /* Like size of twilight zone, etc. */
5459 TtfCopyTableBlindly(info
,ttf
,info
->maxp_start
,info
->maxp_len
,CHR('m','a','x','p'));
5460 TtfCopyTableBlindly(info
,ttf
,info
->cvt_start
,info
->cvt_len
,CHR('c','v','t',' '));
5461 TtfCopyTableBlindly(info
,ttf
,info
->fpgm_start
,info
->fpgm_len
,CHR('f','p','g','m'));
5462 TtfCopyTableBlindly(info
,ttf
,info
->prep_start
,info
->prep_len
,CHR('p','r','e','p'));
5464 for ( i
=0; i
<info
->savecnt
; ++i
) if ( info
->savetab
[i
].offset
!=0 )
5465 TtfCopyTableBlindly(info
,ttf
,info
->savetab
[i
].offset
,info
->savetab
[i
].len
,info
->savetab
[i
].tag
);
5466 if ( info
->gpos_start
!=0 ) /* kerning info may live in the gpos table too */
5467 readttfgpossub(ttf
,info
,true);
5468 /* Load the 'kern' table if the GPOS table either didn't exist or didn't */
5469 /* contain any kerning info */
5470 if ( info
->kern_start
!=0 && !LookupListHasFeature(info
->gpos_lookups
,CHR('k','e','r','n')))
5471 readttfkerns(ttf
,info
);
5472 if ( info
->gsub_start
!=0 )
5473 readttfgpossub(ttf
,info
,false);
5475 if ( info
->pfed_start
!=0 )
5476 pfed_read(ttf
,info
);
5477 if ( info
->tex_start
!=0 )
5479 if ( info
->math_start
!=0 )
5480 otf_read_math(ttf
,info
);
5481 setlocale(LC_NUMERIC
,oldloc
);
5482 if ( !info
->onlystrikes
&& info
->glyphlocations_start
!=0 && info
->glyph_start
!=0 )
5483 ttfFixupReferences(info
);
5484 /* Can't fix up any postscript references until we create a SplineFont */
5485 /* so the check for cff is delayed. Generally there aren't any cff refs */
5490 static void SymbolFixup(struct ttfinfo
*info
) {
5491 /* convert a two-byte symbol encoding (one using PUA) into expected */
5492 /* one-byte encoding. */
5494 EncMap
*map
= info
->map
;
5497 for ( i
=map
->enccount
-1; i
>=0; --i
) {
5498 if ( map
->map
[i
]==-1 )
5500 if ( i
>=0xf000 && i
<=0xf0ff ) {
5501 map
->map
[i
-0xf000] = map
->map
[i
];
5505 if ( i
>max
) max
= i
;
5507 map
->enccount
= max
;
5510 static void NameConsistancyCheck(SplineFont
*sf
,EncMap
*map
) {
5511 /* Many fonts seem to have glyph names which mean something other than */
5512 /* what the encoding says of the glyph */
5513 /* I used to ask about fixing the names up, but people didn't like that */
5514 /* so now I just produce warnings */
5519 int response
, asked
=-1;
5524 buts
[0] = _("Yes"); buts
[1] = _("Yes to _All");
5525 buts
[2] = _("No _to All"); buts
[3] = _("No");
5529 for ( gid
= 0 ; gid
<sf
->glyphcnt
; ++gid
) if ( (sc
=sf
->glyphs
[gid
])!=NULL
) {
5530 if ( sc
->name
!=NULL
&&
5531 strcmp(sc
->name
,".null")!=0 &&
5532 strcmp(sc
->name
,"nonmarkingreturn")!=0 &&
5533 (uni
= UniFromName(sc
->name
,sf
->uni_interp
,map
==NULL
? &custom
: map
->enc
))!= -1 &&
5534 sc
->unicodeenc
!= uni
) {
5536 if ( uni
>=0xe000 && uni
<=0xf8ff )
5537 /* Don't complain about adobe's old PUA assignments for things like "eight.oldstyle" */;
5538 else if ( uni
<0x20 )
5539 /* Nor about control characters */;
5540 else if ( sc
->unicodeenc
==-1 ) {
5542 LogError(_("The glyph named %.30s is not mapped to any unicode code point.\nBut its name indicates it should be mapped to U+%04X.\n"),
5546 /* Ah, but suppose there's an altuni? */
5548 for ( alt
= sc
->altuni
; alt
!=NULL
&& alt
->unienc
!=uni
; alt
=alt
->next
);
5550 LogError( _("The glyph named %.30s is mapped to U+%04X.\nBut its name indicates it should be mapped to U+%04X.\n"),
5551 sc
->name
,sc
->unicodeenc
, uni
);
5552 else if ( alt
->vs
==0 ) {
5553 alt
->unienc
= sc
->unicodeenc
;
5554 sc
->unicodeenc
= uni
;
5560 else if ( sc
->unicodeenc
==-1 )
5561 response
= ff_ask(_("Bad glyph name"),(const char **) buts
,1,1,_("The glyph named %.30s is not mapped to any unicode code point. But its name indicates it should be mapped to U+%04X.\nWould you like to retain the name in spite of this?"),
5564 response
= ff_ask(_("Bad glyph name"),(const char **) buts
,1,1,_("The glyph named %.30s is mapped to U+%04X.\nBut its name indicates it should be mapped to U+%04X.\nWould you like to retain the name in spite of this?"),
5565 sc
->name
,sc
->unicodeenc
, uni
);
5567 asked
= response
= 0;
5568 else if ( response
==2 )
5569 asked
= response
= 3;
5570 if ( response
==3 ) {
5572 if ( sc
->unicodeenc
==-1 )
5573 sc
->name
= StdGlyphName(buffer
,sc
->unicodeenc
,sf
->uni_interp
,NULL
);
5575 sprintf( buffer
, "glyph%d", gid
);
5576 sc
->name
= copy( buffer
);
5584 static void UseGivenEncoding(SplineFont
*sf
,struct ttfinfo
*info
) {
5586 RefChar
*rf
, *prev
, *next
;
5589 sf
->glyphs
= info
->chars
;
5590 sf
->glyphcnt
= sf
->glyphmax
= info
->glyph_cnt
;
5591 for ( i
=0; i
<sf
->glyphcnt
; ++i
)
5592 if ( (sc
= sf
->glyphs
[i
])!=NULL
) {
5593 sc
->layers
[ly_fore
].order2
= sc
->layers
[ly_back
].order2
= info
->to_order2
;
5597 /* A CFF font could contain type1 charstrings, or a type2 font could use */
5598 /* the depreciated convention that endchar =~ seac */
5599 if ( info
->cff_length
!=0 )
5600 SFInstanciateRefs(sf
);
5602 for ( i
=0; i
<sf
->glyphcnt
; ++i
) if ( sf
->glyphs
[i
]!=NULL
) {
5603 for ( rf
= sf
->glyphs
[i
]->layers
[ly_fore
].refs
, prev
=NULL
; rf
!=NULL
; rf
= next
) {
5605 if ( rf
->sc
==NULL
) {
5606 if ( prev
==NULL
) sf
->glyphs
[i
]->layers
[ly_fore
].refs
= next
;
5607 else prev
->next
= next
;
5610 rf
->orig_pos
= rf
->sc
->orig_pos
;
5611 rf
->unicode_enc
= rf
->sc
->unicodeenc
;
5616 sf
->map
= info
->map
;
5617 sf
->uni_interp
= info
->uni_interp
;
5618 NameConsistancyCheck(sf
, sf
->map
);
5621 static void SFRelativeWinAsDs(SplineFont
*sf
) {
5622 if ( !sf
->pfminfo
.winascent_add
|| !sf
->pfminfo
.windescent_add
||
5623 !sf
->pfminfo
.hheadascent_add
|| !sf
->pfminfo
.hheaddescent_add
) {
5625 CIDLayerFindBounds(sf
,ly_fore
,&b
);
5626 if ( !sf
->pfminfo
.winascent_add
) {
5627 sf
->pfminfo
.winascent_add
= true;
5628 if ( sf
->pfminfo
.os2_winascent
< sf
->ascent
/8 ) {
5629 /* There was a bug for a while which gave us really bad values */
5630 sf
->pfminfo
.os2_winascent
= 0;
5631 sf
->pfminfo
.windescent_add
= true;
5632 sf
->pfminfo
.os2_windescent
= 0;
5634 sf
->pfminfo
.os2_winascent
-= b
.maxy
;
5636 if ( !sf
->pfminfo
.windescent_add
) {
5637 sf
->pfminfo
.windescent_add
= true;
5638 sf
->pfminfo
.os2_windescent
+= b
.miny
;
5640 if ( !sf
->pfminfo
.hheadascent_add
) {
5641 sf
->pfminfo
.hheadascent_add
= true;
5642 sf
->pfminfo
.hhead_ascent
-= b
.maxy
;
5644 if ( !sf
->pfminfo
.hheaddescent_add
) {
5645 sf
->pfminfo
.hheaddescent_add
= true;
5646 sf
->pfminfo
.hhead_descent
-= b
.miny
;
5649 if ( !sf
->pfminfo
.typoascent_add
) {
5650 sf
->pfminfo
.typoascent_add
= true;
5651 sf
->pfminfo
.os2_typoascent
-= sf
->ascent
;
5653 if ( !sf
->pfminfo
.typodescent_add
) {
5654 sf
->pfminfo
.typodescent_add
= true;
5655 sf
->pfminfo
.os2_typodescent
-= -sf
->descent
;
5659 static void PsuedoEncodeUnencoded(EncMap
*map
,struct ttfinfo
*info
) {
5663 for ( i
=0; i
<info
->glyph_cnt
; ++i
)
5664 if ( info
->chars
[i
]!=NULL
)
5665 info
->chars
[i
]->ticked
= false;
5666 for ( i
=0; i
<map
->enccount
; ++i
)
5667 if ( map
->map
[i
]!=-1 )
5668 info
->chars
[map
->map
[i
]]->ticked
= true;
5670 for ( i
=0; i
<info
->glyph_cnt
; ++i
)
5671 if ( info
->chars
[i
]!=NULL
&& !info
->chars
[i
]->ticked
)
5674 /* UnicodeBmp has its own Private Use Areas */
5675 /* if (strcmp(map->enc_name","UnicodeBmp")==0) { */
5676 /* if ( (info->glyph_cnt < 0x18FF) && (map->enccount<0xE000)) */
5678 /* else if ( map->enccount<0xF0000 ) */
5679 /* base = 0xF0000; */
5680 /* else if ( map->enccount<0x100000 ) */
5681 /* base = 0x100000; */
5683 /* base = map->enccount; */
5685 if ( map
->enccount
<=256 )
5687 else if ( map
->enccount
<=65536 )
5689 else if ( map
->enccount
<=17*65536 )
5692 base
= map
->enccount
;
5693 if ( base
+extras
>map
->encmax
) {
5694 map
->map
= grealloc(map
->map
,(base
+extras
)*sizeof(int));
5695 memset(map
->map
+map
->enccount
,-1,(base
+extras
-map
->enccount
)*sizeof(int));
5696 map
->encmax
= base
+extras
;
5698 map
->enccount
= base
+extras
;
5700 for ( i
=0; i
<info
->glyph_cnt
; ++i
)
5701 if ( info
->chars
[i
]!=NULL
&& !info
->chars
[i
]->ticked
)
5702 map
->map
[base
+extras
++] = i
;
5706 static void MapDoBack(EncMap
*map
,struct ttfinfo
*info
) {
5709 if ( map
==NULL
) /* CID fonts */
5711 free(map
->backmap
); /* CFF files have this */
5712 map
->backmax
= info
->glyph_cnt
;
5713 map
->backmap
= galloc(info
->glyph_cnt
*sizeof(int));
5714 memset(map
->backmap
,-1,info
->glyph_cnt
*sizeof(int));
5715 for ( i
= map
->enccount
-1; i
>=0; --i
)
5716 if ( map
->map
[i
]>=0 && map
->map
[i
]<info
->glyph_cnt
)
5717 if ( map
->backmap
[map
->map
[i
]]==-1 )
5718 map
->backmap
[map
->map
[i
]] = i
;
5721 static SplineFont
*SFFillFromTTF(struct ttfinfo
*info
) {
5722 SplineFont
*sf
, *_sf
;
5725 struct ttf_table
*last
[2], *tab
, *next
;
5728 sf
= SplineFontEmpty();
5729 sf
->display_size
= -default_fv_font_size
;
5731 sf
->units_per_em
= info
->emsize
;
5733 sf
->display_antialias
= default_fv_antialias
;
5734 sf
->fontname
= info
->fontname
;
5735 sf
->fullname
= info
->fullname
;
5736 sf
->familyname
= info
->familyname
;
5737 sf
->chosenname
= info
->chosenname
;
5738 sf
->onlybitmaps
= info
->onlystrikes
;
5739 sf
->layers
[ly_fore
].order2
= info
->to_order2
;
5740 sf
->layers
[ly_back
].order2
= info
->to_order2
;
5741 sf
->comments
= info
->fontcomments
;
5742 sf
->fontlog
= info
->fontlog
;
5743 sf
->cvt_names
= info
->cvt_names
;
5745 sf
->creationtime
= info
->creationtime
;
5746 sf
->modificationtime
= info
->modificationtime
;
5748 sf
->design_size
= info
->design_size
;
5749 sf
->design_range_bottom
= info
->design_range_bottom
;
5750 sf
->design_range_top
= info
->design_range_top
;
5751 sf
->fontstyle_id
= info
->fontstyle_id
;
5752 sf
->fontstyle_name
= info
->fontstyle_name
;
5754 sf
->gasp_cnt
= info
->gasp_cnt
;
5755 sf
->gasp
= info
->gasp
;
5756 sf
->MATH
= info
->math
;
5758 sf
->texdata
= info
->texdata
;
5760 sf
->mark_class_cnt
= info
->mark_class_cnt
;
5761 sf
->mark_classes
= info
->mark_classes
;
5762 sf
->mark_class_names
= info
->mark_class_names
;
5764 if ( info
->fd
!=NULL
) { /* Special hack for type42 fonts */
5765 sf
->fontname
= copy(info
->fd
->fontname
);
5766 sf
->uniqueid
= info
->fd
->uniqueid
;
5767 sf
->xuid
= XUIDFromFD(info
->fd
->xuid
);
5768 if ( info
->fd
->fontinfo
!=NULL
) {
5769 sf
->familyname
= utf8_verify_copy(info
->fd
->fontinfo
->familyname
);
5770 sf
->fullname
= utf8_verify_copy(info
->fd
->fontinfo
->fullname
);
5771 sf
->copyright
= utf8_verify_copy(info
->fd
->fontinfo
->notice
);
5772 sf
->weight
= utf8_verify_copy(info
->fd
->fontinfo
->weight
);
5773 sf
->version
= utf8_verify_copy(info
->fd
->fontinfo
->version
);
5774 sf
->italicangle
= info
->fd
->fontinfo
->italicangle
;
5775 sf
->upos
= info
->fd
->fontinfo
->underlineposition
*(sf
->ascent
+sf
->descent
);
5776 sf
->uwidth
= info
->fd
->fontinfo
->underlinethickness
*(sf
->ascent
+sf
->descent
);
5780 if ( sf
->fontname
==NULL
) {
5781 sf
->fontname
= EnforcePostScriptName(sf
->fullname
);
5782 if ( sf
->fontname
==NULL
)
5783 sf
->fontname
= EnforcePostScriptName(sf
->familyname
);
5784 if ( sf
->fontname
==NULL
) sf
->fontname
= EnforcePostScriptName("UntitledTTF");
5786 if ( sf
->fullname
==NULL
) sf
->fullname
= copy( sf
->fontname
);
5787 if ( sf
->familyname
==NULL
) sf
->familyname
= copy( sf
->fontname
);
5788 if ( sf
->weight
==NULL
) {
5789 if ( info
->weight
!= NULL
)
5790 sf
->weight
= info
->weight
;
5791 else if ( info
->pfminfo
.pfmset
)
5792 sf
->weight
= copy( info
->pfminfo
.weight
<= 100 ? "Thin" :
5793 info
->pfminfo
.weight
<= 200 ? "Extra-Light" :
5794 info
->pfminfo
.weight
<= 300 ? "Light" :
5795 info
->pfminfo
.weight
<= 400 ? "Book" :
5796 info
->pfminfo
.weight
<= 500 ? "Medium" :
5797 info
->pfminfo
.weight
<= 600 ? "Demi" :
5798 info
->pfminfo
.weight
<= 700 ? "Bold" :
5799 info
->pfminfo
.weight
<= 800 ? "Heavy" :
5802 sf
->weight
= copy("");
5804 free( info
->weight
);
5805 if ( sf
->copyright
==NULL
)
5806 sf
->copyright
= info
->copyright
;
5808 free( info
->copyright
);
5809 sf
->version
= info
->version
;
5810 sf
->italicangle
= info
->italicAngle
;
5811 sf
->strokewidth
= info
->strokewidth
;
5812 sf
->strokedfont
= info
->strokedfont
;
5813 sf
->upos
= info
->upos
;
5814 sf
->uwidth
= info
->uwidth
;
5815 sf
->ascent
= info
->ascent
;
5816 if ( info
->vhea_start
!=0 && info
->vmetrics_start
!=0 )
5817 sf
->hasvmetrics
= true;
5818 sf
->descent
= info
->descent
;
5819 sf
->private = info
->private;
5820 sf
->xuid
= info
->xuid
;
5821 sf
->uniqueid
= info
->uniqueid
;
5822 sf
->pfminfo
= info
->pfminfo
;
5823 sf
->os2_version
= info
->os2_version
;
5824 sf
->use_typo_metrics
= info
->use_typo_metrics
;
5825 sf
->weight_width_slope_only
= info
->weight_width_slope_only
;
5826 sf
->head_optimized_for_cleartype
= info
->optimized_for_cleartype
;
5827 sf
->gasp_version
= info
->gasp_version
;
5828 sf
->names
= info
->names
;
5829 sf
->anchor
= info
->ahead
;
5830 sf
->kerns
= info
->khead
;
5831 sf
->vkerns
= info
->vkhead
;
5832 sf
->possub
= info
->possub
;
5833 sf
->gpos_lookups
= info
->gpos_lookups
;
5834 sf
->gsub_lookups
= info
->gsub_lookups
;
5836 last
[0] = sf
->ttf_tables
;
5838 for ( tab
=info
->tabs
; tab
!=NULL
; tab
= next
) {
5840 if ( tab
->tag
==CHR('f','p','g','m') || tab
->tag
==CHR('p','r','e','p') ||
5841 tab
->tag
==CHR('c','v','t',' ') || tab
->tag
==CHR('m','a','x','p')) {
5842 if ( last
[0]==NULL
)
5843 sf
->ttf_tables
= tab
;
5845 last
[0]->next
= tab
;
5848 if ( last
[1]==NULL
)
5849 sf
->ttf_tab_saved
= tab
;
5851 last
[1]->next
= tab
;
5857 if ( info
->twobytesymbol
)
5858 /* rework ms symbol encodings */
5860 if ( info
->map
==NULL
&& info
->subfonts
==NULL
) /* Can happen when reading a ttf from a pdf */
5861 info
->map
= EncMapFromEncoding(sf
,FindOrMakeEncoding("original"));
5862 if ( info
->subfontcnt
==0 )
5863 PsuedoEncodeUnencoded(info
->map
,info
);
5864 MapDoBack(info
->map
,info
);
5865 sf
->map
= info
->map
;
5866 sf
->cidregistry
= info
->cidregistry
;
5867 sf
->ordering
= info
->ordering
;
5868 sf
->supplement
= info
->supplement
;
5869 sf
->cidversion
= info
->cidfontversion
;
5870 sf
->bitmaps
= info
->bitmaps
;
5871 sf
->grid
= info
->guidelines
;
5872 sf
->horiz_base
= info
->horiz_base
;
5873 sf
->vert_base
= info
->vert_base
;
5874 if ( info
->layers
!=NULL
) {
5875 info
->layers
[ly_fore
] = sf
->layers
[ly_fore
];
5876 sf
->layers
[ly_fore
].name
= NULL
;
5877 if ( info
->layers
[ly_back
].name
==NULL
)
5878 info
->layers
[ly_back
].name
= sf
->layers
[ly_back
].name
;
5880 free( sf
->layers
[ly_back
].name
);
5882 sf
->layers
= info
->layers
;
5883 sf
->layer_cnt
= info
->layer_cnt
;
5887 for ( i
=0; i
<info
->glyph_cnt
; ++i
) if ( info
->chars
[i
]!=NULL
) {
5888 SCOrderAP(info
->chars
[i
]);
5891 if ( info
->subfontcnt
== 0 ) {
5892 UseGivenEncoding(sf
,info
);
5894 sf
->subfontcnt
= info
->subfontcnt
;
5895 sf
->subfonts
= info
->subfonts
;
5896 free(info
->chars
); /* This is the GID->char index, don't need it now */
5897 for ( i
=0; i
<sf
->subfontcnt
; ++i
) {
5898 sf
->subfonts
[i
]->cidmaster
= sf
;
5899 sf
->subfonts
[i
]->hasvmetrics
= sf
->hasvmetrics
;
5903 /* I thought the languages were supposed to be ordered, but it seems */
5904 /* that is not always the case. Order everything, just in case */
5905 { int isgpos
; OTLookup
*otl
;
5906 for ( isgpos
=0; isgpos
<2; ++isgpos
)
5907 for ( otl
= isgpos
? sf
->gpos_lookups
:sf
->gsub_lookups
; otl
!=NULL
; otl
=otl
->next
)
5908 otl
->features
= FLOrder(otl
->features
);
5911 if ( info
->cff_length
!=0 && !sf
->layers
[ly_fore
].order2
) {
5912 /* Clean up the hint masks, We create an initial hintmask whether we */
5913 /* need it or not */
5916 _sf
= k
<sf
->subfontcnt
?sf
->subfonts
[k
]:sf
;
5917 for ( i
=0; i
<sf
->glyphcnt
; ++i
) {
5918 if ( (sc
= _sf
->glyphs
[i
])!=NULL
&& !sc
->hconflicts
&& !sc
->vconflicts
&&
5919 sc
->layers
[ly_fore
].splines
!=NULL
) {
5920 chunkfree( sc
->layers
[ly_fore
].splines
->first
->hintmask
,sizeof(HintMask
) );
5921 sc
->layers
[ly_fore
].splines
->first
->hintmask
= NULL
;
5925 } while ( k
<sf
->subfontcnt
);
5928 sf
->units_per_em
= info
->emsize
;
5929 sf
->pfminfo
= info
->pfminfo
;
5930 sf
->names
= info
->names
;
5932 SFRelativeWinAsDs(sf
);
5933 free(info
->savetab
);
5934 /*if (info->chars) {
5936 for(i=0; info->chars[i]; i++)
5937 if (info->chars[i]->name)
5938 free(info->chars[i]->name);
5940 sf
->loadvalidation_state
=
5941 (info
->bad_ps_fontname
?lvs_bad_ps_fontname
:0) |
5942 (info
->bad_glyph_data
?lvs_bad_glyph_table
:0) |
5943 (info
->bad_cff
?lvs_bad_cff_table
:0) |
5944 (info
->bad_metrics
?lvs_bad_metrics_table
:0) |
5945 (info
->bad_cmap
?lvs_bad_cmap_table
:0) |
5946 (info
->bad_embedded_bitmap
?lvs_bad_bitmaps_table
:0) |
5947 (info
->bad_gx
?lvs_bad_gx_table
:0) |
5948 (info
->bad_ot
?lvs_bad_ot_table
:0) |
5949 (info
->bad_os2_version
?lvs_bad_os2_version
:0)|
5950 (info
->bad_sfnt_header
?lvs_bad_sfnt_header
:0);
5954 SplineFont
*_SFReadTTF(FILE *ttf
, int flags
,enum openflags openflags
, char *filename
,struct fontdict
*fd
) {
5955 struct ttfinfo info
;
5958 memset(&info
,'\0',sizeof(struct ttfinfo
));
5959 info
.onlystrikes
= (flags
&ttf_onlystrikes
)?1:0;
5960 info
.onlyonestrike
= (flags
&ttf_onlyonestrike
)?1:0;
5961 info
.use_typo_metrics
= true;
5962 info
.openflags
= openflags
;
5964 ret
= readttf(ttf
,&info
,filename
);
5967 return( SFFillFromTTF(&info
));
5970 SplineFont
*SFReadTTF(char *filename
, int flags
, enum openflags openflags
) {
5973 char *temp
=filename
, *pt
, *lparen
, *rparen
;
5975 pt
= strrchr(filename
,'/');
5976 if ( pt
==NULL
) pt
= filename
;
5977 if ( (lparen
= strrchr(pt
,'('))!=NULL
&&
5978 (rparen
= strrchr(lparen
,')'))!=NULL
&&
5980 temp
= copy(filename
);
5981 pt
= temp
+ (lparen
-filename
);
5984 ttf
= fopen(temp
,"rb");
5985 if ( temp
!=filename
) free(temp
);
5989 sf
= _SFReadTTF(ttf
,flags
,openflags
,filename
,NULL
);
5996 static int readttfinfo(FILE *ttf
, struct ttfinfo
*info
, char *filename
) {
5998 if ( !readttfheader(ttf
,info
,filename
,&info
->chosenname
)) {
6001 readttfpreglyph(ttf
,info
);
6002 if ( info
->os2_start
!=0 )
6003 readttfos2metrics(ttf
,info
);
6004 if ( info
->postscript_start
!=0 ) {
6005 fseek(ttf
,info
->postscript_start
,SEEK_SET
);
6007 info
->italicAngle
= getfixed(ttf
);
6012 /* I am not sure what happens to the ttinfo struct's members.
6013 perhaps some need free()-ing
6016 void THPatchSplineChar (SplineChar
*sc
)
6019 if (sc
->layers
!=NULL
&& sc
->layers
[ly_fore
].splines
!= NULL
) {
6020 if (sc
->xmax
==0 && sc
->ymax
==0 && sc
->xmin
==0 && sc
->ymin
==0) {
6021 SplineCharFindBounds(sc
,&bb
);
6027 /* free the curves */
6028 SplinePointListsFree(sc
->layers
[ly_fore
].splines
);
6029 sc
->layers
[ly_fore
].splines
=NULL
;
6031 if (sc
->layers
[ly_fore
].refs
!=NULL
) {
6032 RefCharsFree(sc
->layers
[ly_fore
].refs
);
6033 sc
->layers
[ly_fore
].refs
= NULL
;
6038 static SplineFont
*SFFillFromTTFInfo(struct ttfinfo
*info
) {
6041 sf
= SplineFontEmpty();
6043 sf
->fontname
= info
->fontname
;
6044 sf
->fullname
= info
->fullname
;
6045 sf
->familyname
= info
->familyname
;
6047 if ( info
->fd
!=NULL
) { /* Special hack for type42 fonts */
6048 sf
->fontname
= copy(info
->fd
->fontname
);
6049 if ( info
->fd
->fontinfo
!=NULL
) {
6050 sf
->familyname
= utf8_verify_copy(info
->fd
->fontinfo
->familyname
);
6051 sf
->fullname
= utf8_verify_copy(info
->fd
->fontinfo
->fullname
);
6052 sf
->weight
= utf8_verify_copy(info
->fd
->fontinfo
->weight
);
6055 if ( sf
->fontname
==NULL
) sf
->fontname
= EnforcePostScriptName(sf
->fullname
);
6056 if ( sf
->fontname
==NULL
) sf
->fontname
= EnforcePostScriptName(sf
->familyname
);
6057 if ( sf
->fontname
==NULL
) sf
->fontname
= EnforcePostScriptName("UntitledTTF");
6059 if ( sf
->fullname
==NULL
) sf
->fullname
= copy( sf
->fontname
);
6060 if ( sf
->familyname
==NULL
) sf
->familyname
= copy( sf
->fontname
);
6061 if ( sf
->weight
==NULL
) {
6062 if ( info
->weight
!= NULL
)
6063 sf
->weight
= info
->weight
;
6064 else if ( info
->pfminfo
.pfmset
)
6065 sf
->weight
= copy( info
->pfminfo
.weight
<= 100 ? "Thin" :
6066 info
->pfminfo
.weight
<= 200 ? "Extra-Light" :
6067 info
->pfminfo
.weight
<= 300 ? "Light" :
6068 info
->pfminfo
.weight
<= 400 ? "Book" :
6069 info
->pfminfo
.weight
<= 500 ? "Medium" :
6070 info
->pfminfo
.weight
<= 600 ? "Demi" :
6071 info
->pfminfo
.weight
<= 700 ? "Bold" :
6072 info
->pfminfo
.weight
<= 800 ? "Heavy" :
6075 sf
->weight
= copy("");
6077 free( info
->weight
);
6078 sf
->version
= info
->version
;
6079 sf
->italicangle
= info
->italicAngle
;
6080 sf
->names
= info
->names
;
6081 sf
->units_per_em
= info
->emsize
;
6082 sf
->pfminfo
= info
->pfminfo
;
6084 free(info
->savetab
);
6085 if (info
->chosenname
)
6086 free(info
->chosenname
);
6087 if ( sf
->copyright
==NULL
)
6088 sf
->copyright
= info
->copyright
;
6090 free( info
->copyright
);
6094 SplineFont
*_SFReadTTFInfo(FILE *ttf
, int flags
,enum openflags openflags
, char *filename
,struct fontdict
*fd
) {
6095 struct ttfinfo info
;
6097 (void)openflags
; /* for -Wall */
6098 memset(&info
,'\0',sizeof(struct ttfinfo
));
6099 info
.onlystrikes
= (flags
&ttf_onlystrikes
)?1:0;
6100 info
.onlyonestrike
= (flags
&ttf_onlyonestrike
)?1:0;
6101 info
.use_typo_metrics
= true;
6103 ret
= readttfinfo(ttf
,&info
,filename
);
6106 return( SFFillFromTTFInfo(&info
));
6109 SplineFont
*SFReadTTFInfo(char *filename
, int flags
, enum openflags openflags
) {
6112 char *temp
=filename
, *pt
, *lparen
, *rparen
;
6114 pt
= strrchr(filename
,'/');
6115 if ( pt
==NULL
) pt
= filename
;
6116 if ( (lparen
= strrchr(pt
,'('))!=NULL
&&
6117 (rparen
= strrchr(lparen
,')'))!=NULL
&&
6119 temp
= copy(filename
);
6120 pt
= temp
+ (lparen
-filename
);
6123 ttf
= fopen(temp
,"rb");
6124 if ( temp
!=filename
) free(temp
);
6128 sf
= _SFReadTTFInfo(ttf
,flags
,openflags
,filename
,NULL
);
6134 SplineFont
*_CFFParse(FILE *temp
,int len
, char *fontsetname
) {
6135 struct ttfinfo info
;
6136 (void)fontsetname
; /* for -Wall */
6138 memset(&info
,'\0',sizeof(info
));
6140 info
.cff_length
= len
;
6141 info
.barecff
= true;
6142 if ( !readcffglyphs(temp
,&info
) )
6144 return( SFFillFromTTF(&info
));
6147 SplineFont
*CFFParse(char *filename
) {
6148 FILE *cff
= fopen(filename
,"r");
6154 fseek(cff
,0,SEEK_END
);
6156 fseek(cff
,0,SEEK_SET
);
6157 sf
= _CFFParse(cff
,len
,NULL
);
6162 char **NamesReadCFF(char *filename
) {
6163 FILE *cff
= fopen(filename
,"rb");
6164 int32 hdrsize
, offsize
;
6169 if ( getc(cff
)!='\1' ) { /* Major version */
6170 LogError( _("CFF version mismatch\n") );
6174 getc(cff
); /* Minor version */
6175 hdrsize
= getc(cff
);
6176 offsize
= getc(cff
);
6178 fseek(cff
,hdrsize
,SEEK_SET
);
6179 fontnames
= readcfffontnames(cff
,NULL
,NULL
);
6181 return( fontnames
);
6184 char **NamesReadTTF(char *filename
) {
6185 FILE *ttf
= fopen(filename
,"rb");
6186 int32 version
, cnt
, *offsets
;
6193 version
=getlong(ttf
);
6194 if ( version
==CHR('t','t','c','f')) {
6195 /* TTCF version = */ getlong(ttf
);
6197 offsets
= galloc(cnt
*sizeof(int32
));
6198 for ( i
=0; i
<cnt
; ++i
)
6199 offsets
[i
] = getlong(ttf
);
6200 ret
= galloc((cnt
+1)*sizeof(char *));
6201 for ( i
=j
=0; i
<cnt
; ++i
) {
6202 temp
= TTFGetFontName(ttf
,offsets
[i
],0);
6209 temp
= TTFGetFontName(ttf
,0,0);
6211 ret
= galloc(2*sizeof(char *));