summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvisvgm/dvisvgm-src/libs/ff-woff/fontforge/tottfgpos.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvisvgm/dvisvgm-src/libs/ff-woff/fontforge/tottfgpos.c')
-rw-r--r--Build/source/texk/dvisvgm/dvisvgm-src/libs/ff-woff/fontforge/tottfgpos.c4613
1 files changed, 0 insertions, 4613 deletions
diff --git a/Build/source/texk/dvisvgm/dvisvgm-src/libs/ff-woff/fontforge/tottfgpos.c b/Build/source/texk/dvisvgm/dvisvgm-src/libs/ff-woff/fontforge/tottfgpos.c
deleted file mode 100644
index 607214a7ef9..00000000000
--- a/Build/source/texk/dvisvgm/dvisvgm-src/libs/ff-woff/fontforge/tottfgpos.c
+++ /dev/null
@@ -1,4613 +0,0 @@
-/* Copyright (C) 2000-2012 by George Williams */
-/*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
-
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
-
- * The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
-
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
- * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "fontforgevw.h"
-#include <utype.h>
-
-int coverageformatsallowed=3;
-int use_second_indic_scripts = false;
-
-#include "ttf.h"
-
-/* This file contains routines to create the otf gpos and gsub tables and their */
-/* attendant subtables */
-
-/* Undocumented fact: ATM (which does kerning for otf fonts in Word) can't handle features with multiple lookups */
-
-/* Undocumented fact: Only one feature with a given tag allowed per script/lang */
-/* So if we have multiple lookups with the same tag they must be merged into */
-/* one feature with many lookups */
-
-/* scripts (for opentype) that I understand */
- /* see also list in lookups.c mapping script tags to friendly names */
-
-static uint32 scripts[][15] = {
-/* Arabic */ { CHR('a','r','a','b'), 0x0600, 0x06ff, 0xfb50, 0xfdff, 0xfe70, 0xfefe },
-/* Aramaic */ { CHR('a','r','a','m'), 0x820, 0x83f },
-/* Armenian */ { CHR('a','r','m','n'), 0x0530, 0x058f, 0xfb13, 0xfb17 },
-/* Balinese */ { CHR('b','a','l','i'), 0x1b00, 0x1b7f },
-/* Bengali */ { CHR('b','e','n','g'), 0x0980, 0x09ff },
-/* Bliss symb */{ CHR('b','l','i','s'), 0x12200, 0x124ff },
-/* Bopomofo */ { CHR('b','o','p','o'), 0x3100, 0x312f, 0x31a0, 0x31bf },
-/* Braille */ { CHR('b','r','a','i'), 0x2800, 0x28ff },
-/* Buginese */ { CHR('b','u','g','i'), 0x1a00, 0x1a1f },
-/* Buhid */ { CHR('b','u','h','d'), 0x1740, 0x1753 },
-/* Byzantine M*/{ CHR('b','y','z','m'), 0x1d000, 0x1d0ff },
-/* Canadian Syl*/{CHR('c','a','n','s'), 0x1400, 0x167f },
-/* Carian */ {CHR('c','a','r','i'), 0x0, 0x0 },
-/* Cham */ {CHR('c','h','a','m'), 0x0, 0x0 },
-/* Cherokee */ { CHR('c','h','e','r'), 0x13a0, 0x13ff },
-/* Cirth */ { CHR('c','i','r','t'), 0x12080, 0x120ff },
-/* CJKIdeogra */{ CHR('h','a','n','i'), 0x3300, 0x9fff, 0xf900, 0xfaff, 0x020000, 0x02ffff },
-/* Coptic */ { CHR('c','o','p','t'), 0x2c80, 0x2cff },
-/* Cypriot */ { CHR('c','p','m','n'), 0x10800, 0x1083f },
-/* Cyrillic */ { CHR('c','y','r','l'), 0x0400, 0x052f, 0x1d2b, 0x1d2b, 0x1d78, 0x1d78,
- 0x2de0, 0x2dff, 0xa640, 0xa6ff },
-/* Deseret */ { CHR('d','s','r','t'), 0x10400, 0x1044f },
-/* Devanagari */{ CHR('d','e','v','a'), 0x0900, 0x097f },
-/* Ethiopic */ { CHR('e','t','h','i'), 0x1200, 0x139f },
-/* Georgian */ { CHR('g','e','o','r'), 0x1080, 0x10ff },
-/* Glagolitic */{ CHR('g','l','a','g'), 0x1080, 0x10ff },
-/* Gothic */ { CHR('g','o','t','h'), 0x10330, 0x1034a },
-/* Greek */ { CHR('g','r','e','k'), 0x0370, 0x03ff, 0x1f00, 0x1fff },
-/* Gujarati */ { CHR('g','u','j','r'), 0x0a80, 0x0aff },
-/* Gurmukhi */ { CHR('g','u','r','u'), 0x0a00, 0x0a7f },
-/* Hangul */ { CHR('h','a','n','g'), 0xac00, 0xd7af, 0x3130, 0x319f, 0xffa0, 0xff9f },
-/* Hanunoo */ { CHR('h','a','n','o'), 0x1720, 0x1734 },
- /* I'm not sure what the difference is between the 'hang' tag and the 'jamo' */
- /* tag. 'Jamo' is said to be the precomposed forms, but what's 'hang'? */
-/* Hebrew */ { CHR('h','e','b','r'), 0x0590, 0x05ff, 0xfb1e, 0xfb4f },
-/* Hiragana used to have its own tag 'hira', but has since been merged with katakana */
-/* Hangul Jamo*/{ CHR('j','a','m','o'), 0x1100, 0x11ff, 0x3130, 0x319f, 0xffa0, 0xffdf },
-/* Javanese */ { CHR('j','a','v','a'), 0 }, /* MS has a tag, but there is no unicode range */
-/* Katakana */ { CHR('k','a','n','a'), 0x3040, 0x30ff, 0xff60, 0xff9f },
-/* Kayah Li */ { CHR('k','a','l','i'), 0 },
-/* Kannada */ { CHR('k','n','d','a'), 0x0c80, 0x0cff },
-/* Kharosthi */ { CHR('k','h','a','r'), 0x10a00, 0x10a5f },
-/* Khmer */ { CHR('k','h','m','r'), 0x1780, 0x17ff },
-/* Latin */ { CHR('l','a','t','n'), 0x0041, 0x005a, 0x0061, 0x007a,
- 0x00c0, 0x02af, 0x1d00, 0x1eff, 0xfb00, 0xfb0f, 0xff00, 0xff5f, 0xa770, 0xa7ff },
-/* Lao */ { CHR('l','a','o',' '), 0x0e80, 0x0eff },
-/* Lepcha */ { CHR('l','e','p','c'), 0 },
-/* Limbu */ { CHR('l','i','m','b'), 0x1900, 0x194f },
-/* Linear A */ /*{ CHR('l','i','n','a'), 0x10180, 0x102cf },*/ /* What happened to linear A? */
-/* Linear B */ { CHR('l','i','n','b'), 0x10000, 0x100fa },
-/* Lycian */ { CHR('l','y','c','i'), 0 },
-/* Lydian */ { CHR('l','y','d','i'), 0 },
-/* Malayalam */ { CHR('m','l','y','m'), 0x0d00, 0x0d7f },
-/* Mathematical Alphanumeric Symbols */
- { CHR('m','a','t','h'), 0x1d400, 0x1d7ff },
-/* Mongolian */ { CHR('m','o','n','g'), 0x1800, 0x18af },
-/* Musical */ { CHR('m','u','s','c'), 0x1d100, 0x1d1ff },
-/* Myanmar */ { CHR('m','y','m','r'), 0x1000, 0x107f },
-/* New Tai Lue*/{ CHR('t','a','l','u'), 0 },
-/* N'Ko */ { CHR('n','k','o',' '), 0x07c0, 0x07fa },
-/* Ogham */ { CHR('o','g','a','m'), 0x1680, 0x169f },
-/* Ol Chiki */ { CHR('o','l','c','k'), 0 },
-/* Old Italic */{ CHR('i','t','a','l'), 0x10300, 0x1031e },
-/* Old Permic */{ CHR('p','e','r','m'), 0x10350, 0x1037f },
-/* Old Persian cuneiform */
- { CHR('x','p','e','o'), 0x103a0, 0x103df },
-/* Oriya */ { CHR('o','r','y','a'), 0x0b00, 0x0b7f },
-/* Osmanya */ { CHR('o','s','m','a'), 0x10480, 0x104a9 },
-/* Phags-pa */ { CHR('p','h','a','g'), 0xa840, 0xa87f },
-/* Phoenician */{ CHR('p','h','n','x'), 0x10900, 0x1091f },
-/* Pollard */ { CHR('p','l','r','d'), 0x104b0, 0x104d9 },
-/* Rejang */ { CHR('r','j','n','g'), 0 },
-/* Rongorongo */{ CHR('r','o','r','o'), 0 },
-/* Runic */ { CHR('r','u','n','r'), 0x16a0, 0x16ff },
-/* Saurashtra*/ { CHR('s','a','u','r'), 0 },
-/* Shavian */ { CHR('s','h','a','w'), 0x10450, 0x1047f },
-/* Sinhala */ { CHR('s','i','n','h'), 0x0d80, 0x0dff },
-/* Sumero-Akkadian Cuneiform */
- { CHR('x','s','u','x'), 0x12000, 0x1236e },
-/* Sundanese */ { CHR('s','u','n','d'), 0 },
-/* Syloti Nagri */
- { CHR('s','y','l','o'), 0xa800, 0xa82f },
-/* Syriac */ { CHR('s','y','r','c'), 0x0700, 0x074f },
-/* Tagalog */ { CHR('t','a','g','l'), 0x1700, 0x1714 },
-/* Tagbanwa */ { CHR('t','a','g','b'), 0x1760, 0x1773 },
-/* Tai Le */ { CHR('t','a','l','e'), 0x1950, 0x1974 },
-/* Tai Lu */ { CHR('t','a','l','u'), 0x1980, 0x19df },
-/* Tamil */ { CHR('t','a','m','l'), 0x0b80, 0x0bff },
-/* Telugu */ { CHR('t','e','l','u'), 0x0c00, 0x0c7f },
-/* Tengwar */ { CHR('t','e','n','g'), 0x12000, 0x1207f },
-/* Thaana */ { CHR('t','h','a','a'), 0x0780, 0x07bf },
-/* Thai */ { CHR('t','h','a','i'), 0x0e00, 0x0e7f },
-/* Tibetan */ { CHR('t','i','b','t'), 0x0f00, 0x0fff },
-/* Tifinagh */ { CHR('t','f','n','g'), 0x2d30, 0x2d7f },
-/* Ugaritic */ { CHR('u','g','a','r'), 0x10380, 0x1039d },
-/* Yi */ { CHR('y','i',' ',' '), 0xa000, 0xa4c6 },
- { 0 }
-};
-
-static SplineChar **SFOrderedGlyphs(SplineChar **glyphs);
-
-int ScriptIsRightToLeft(uint32 script) {
- if ( script==CHR('a','r','a','b') || script==CHR('h','e','b','r') ||
- script==CHR('c','p','m','n') || script==CHR('k','h','a','r') ||
- script==CHR('s','y','r','c') || script==CHR('t','h','a','a') ||
- script==CHR('n','k','o',' '))
-return( true );
-
-return( false );
-}
-
-uint32 ScriptFromUnicode(uint32 u,SplineFont *sf) {
- int s, k;
-
- if ( (int32)u!=-1 ) {
- for ( s=0; scripts[s][0]!=0; ++s ) {
- for ( k=1; scripts[s][k+1]!=0; k += 2 )
- if ( u>=scripts[s][k] && u<=scripts[s][k+1] )
- break;
- if ( scripts[s][k+1]!=0 )
- break;
- }
- if ( scripts[s][0]!=0 ) {
- uint32 script = scripts[s][0];
- if ( use_second_indic_scripts ) {
- /* MS has a parallel set of script tags for their new */
- /* Indic font shaper */
- if ( script == CHR('b','e','n','g' )) script = CHR('b','n','g','2');
- else if ( script == CHR('d','e','v','a' )) script = CHR('d','e','v','2');
- else if ( script == CHR('g','u','j','r' )) script = CHR('g','j','r','2');
- else if ( script == CHR('g','u','r','u' )) script = CHR('g','u','r','2');
- else if ( script == CHR('k','n','d','a' )) script = CHR('k','n','d','2');
- else if ( script == CHR('m','l','y','m' )) script = CHR('m','l','m','2');
- else if ( script == CHR('o','r','y','a' )) script = CHR('o','r','y','2');
- else if ( script == CHR('t','a','m','l' )) script = CHR('t','m','l','2');
- else if ( script == CHR('t','e','l','u' )) script = CHR('t','e','l','2');
- }
-return( script );
- }
- } else if ( sf!=NULL ) {
- if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) {
- if ( sf->cidmaster!=NULL ) sf = sf->cidmaster;
- if ( strmatch(sf->ordering,"Identity")==0 )
-return( DEFAULT_SCRIPT );
- else if ( strmatch(sf->ordering,"Korean")==0 )
-return( CHR('h','a','n','g'));
- else
-return( CHR('h','a','n','i') );
- }
- }
-
-return( DEFAULT_SCRIPT );
-}
-
-uint32 SCScriptFromUnicode(SplineChar *sc) {
- const char *pt;
- PST *pst;
- SplineFont *sf;
- int i; unsigned uni;
- FeatureScriptLangList *features;
-
- if ( sc==NULL )
-return( DEFAULT_SCRIPT );
-
- sf = sc->parent;
- if ( sc->unicodeenc!=-1 &&
- !(sc->unicodeenc>=0xe000 && sc->unicodeenc<0xf8ff) &&
- !(sc->unicodeenc>=0xf0000 && sc->unicodeenc<0x10ffff))
-return( ScriptFromUnicode( sc->unicodeenc,sf ));
-
- pt = sc->name;
- if ( *pt ) for ( ++pt; *pt!='\0' && *pt!='_' && *pt!='.'; ++pt );
- if ( *pt!='\0' ) {
- char *str = copyn(sc->name,pt-sc->name);
- int uni = UniFromName(str,ui_none,&custom);
- free(str);
- if ( uni!=-1 )
-return( ScriptFromUnicode( uni,sf ));
- }
- /* Adobe ligature uniXXXXXXXX */
- if ( strncmp(sc->name,"uni",3)==0 && sscanf(sc->name+3,"%4x", &uni)==1 )
-return( ScriptFromUnicode( uni,sf ));
-
- if ( sf==NULL )
-return( DEFAULT_SCRIPT );
-
- if ( sf->cidmaster ) sf=sf->cidmaster;
- else if ( sf->mm!=NULL ) sf=sf->mm->normal;
- for ( i=0; i<2; ++i ) {
- for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->type == pst_lcaret )
- continue;
- for ( features = pst->subtable->lookup->features; features!=NULL; features=features->next ) {
- if ( features->scripts!=NULL )
-return( features->scripts->script );
- }
- }
- }
-return( ScriptFromUnicode( sc->unicodeenc,sf ));
-}
-
-int SCRightToLeft(SplineChar *sc) {
-
- if ( sc->unicodeenc>=0x10800 && sc->unicodeenc<=0x10fff )
-return( true ); /* Supplemental Multilingual Plane, RTL scripts */
- if ( sc->unicodeenc!=-1 && sc->unicodeenc<0x10000 )
-return( isrighttoleft(sc->unicodeenc ));
-
-return( ScriptIsRightToLeft(SCScriptFromUnicode(sc)));
-}
-
-static void GlyphMapFree(SplineChar ***map) {
- int i;
-
- if ( map==NULL )
- return;
- for ( i=0; map[i]!=NULL; ++i )
- free(map[i]);
- free(map);
-}
-
-static SplineChar **FindSubs(SplineChar *sc,struct lookup_subtable *sub) {
- SplineChar *spc[30], **space = spc;
- int max = sizeof(spc)/sizeof(spc[0]);
- int cnt=0;
- char *pt, *start;
- SplineChar *subssc, **ret;
- PST *pst;
-
- for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->subtable==sub ) {
- pt = pst->u.subs.variant;
- while ( 1 ) {
- while ( *pt==' ' ) ++pt; // Burn leading spaces.
- // Start tokenizing the space-delimited list of references.
- start = pt; // Note the beginning of the current item.
- pt = strchr(start,' '); // Find the end of the current item.
- if ( pt!=NULL )
- *pt = '\0'; // Temporarily terminate the item.
- subssc = SFGetChar(sc->parent,-1,start); // Find the corresponding SplineChar.
- if ( subssc!=NULL && subssc->ttf_glyph!=-1 ) {
- // Extend the list if necessary.
- if ( cnt>=max ) {
- if ( spc==space ) {
- space = malloc((max+=30)*sizeof(SplineChar *));
- memcpy(space,spc,(max-30)*sizeof(SplineChar *));
- } else
- space = realloc(space,(max+=30)*sizeof(SplineChar *));
- }
- // Write the SplineChar to the list.
- space[cnt++] = subssc;
- }
- if ( pt==NULL )
- break; // No more items.
- *pt=' '; // Repair the string from the tokenization process.
- }
- }
- }
- // Returning NULL causes problems and seems to be unnecessary for now.
- ret = malloc((cnt+1)*sizeof(SplineChar *));
- memcpy(ret,space,cnt*sizeof(SplineChar *));
- ret[cnt] = NULL;
- if ( space!=spc )
- free(space); // Free the temp space only if it is dynamically allocated.
- return( ret );
-}
-
-static SplineChar ***generateMapList(SplineChar **glyphs, struct lookup_subtable *sub) {
- int cnt;
- SplineChar *sc;
- int i;
- SplineChar ***maps=NULL;
-
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt );
- maps = malloc((cnt+1)*sizeof(SplineChar **));
- for ( i=0; i<cnt; ++i ) {
- sc = glyphs[i];
- maps[i] = FindSubs(sc,sub);
- if (maps[i] == NULL) {
- fprintf( stderr, "maps[%d] is null; glyphs[%d] is \"%s\"; lookup name is \"%s\".\n" , i , i , (glyphs[i]->name ? glyphs[i]->name : ""), sub->subtable_name) ;
- }
- }
- maps[cnt] = NULL;
-return( maps );
-}
-
-void AnchorClassDecompose(SplineFont *sf,AnchorClass *_ac, int classcnt, int *subcnts,
- SplineChar ***marks,SplineChar ***base,
- SplineChar ***lig,SplineChar ***mkmk,
- struct glyphinfo *gi) {
- /* Run through the font finding all characters with this anchor class */
- /* (and the cnt-1 classes after it) */
- /* and distributing in the four possible anchor types */
- int i,j,k,gid, gmax;
- struct sclist { int cnt; SplineChar **glyphs; } heads[at_max];
- AnchorPoint *test;
- AnchorClass *ac;
-
- memset(heads,0,sizeof(heads));
- memset(subcnts,0,classcnt*sizeof(int));
- memset(marks,0,classcnt*sizeof(SplineChar **));
- gmax = gi==NULL ? sf->glyphcnt : gi->gcnt;
- for ( j=0; j<2; ++j ) {
- for ( i=0; i<gmax; ++i ) if ( (gid = gi==NULL ? i : gi->bygid[i])!=-1 && gid < sf->glyphcnt && sf->glyphs[gid]!=NULL ) {
- for ( ac = _ac, k=0; k<classcnt; ac=ac->next ) if ( ac->matches ) {
- for ( test=sf->glyphs[gid]->anchor; test!=NULL ; test=test->next ) {
- if ( test->anchor==ac ) {
- if ( test->type==at_mark ) {
- if ( j )
- marks[k][subcnts[k]] = sf->glyphs[gid];
- ++subcnts[k];
- if ( ac->type!=act_mkmk )
- break;
- } else if ( test->type!=at_centry && test->type!=at_cexit ) {
- if ( heads[test->type].glyphs!=NULL ) {
- /* If we have multiple mark classes, we may use the same base glyph */
- /* with more than one mark class. But it should only appear once in */
- /* the output */
- if ( heads[test->type].cnt==0 ||
- heads[test->type].glyphs[heads[test->type].cnt-1]!=sf->glyphs[gid] ) {
- heads[test->type].glyphs[heads[test->type].cnt] = sf->glyphs[gid];
- ++heads[test->type].cnt;
- }
- } else
- ++heads[test->type].cnt;
- if ( ac->type!=act_mkmk )
- break;
- }
- }
- }
- ++k;
- }
- }
- if ( j==1 )
- break;
- for ( i=0; i<4; ++i )
- if ( heads[i].cnt!=0 ) {
- heads[i].glyphs = malloc((heads[i].cnt+1)*sizeof(SplineChar *));
- /* I used to set glyphs[cnt] to NULL here. But it turns out */
- /* cnt may be an overestimate on the first pass. So we can */
- /* only set it at the end of the second pass */
- heads[i].cnt = 0;
- }
- for ( k=0; k<classcnt; ++k ) if ( subcnts[k]!=0 ) {
- marks[k] = malloc((subcnts[k]+1)*sizeof(SplineChar *));
- marks[k][subcnts[k]] = NULL;
- subcnts[k] = 0;
- }
- }
- for ( i=0; i<4; ++i ) {
- if ( heads[i].glyphs!=NULL )
- heads[i].glyphs[heads[i].cnt] = NULL;
- }
- for ( i=0; i<classcnt; ++i ) {
- if ( subcnts[k]!=0 )
- SFOrderedGlyphs(marks[i]);
- }
-
- *base = SFOrderedGlyphs(heads[at_basechar].glyphs);
- *lig = SFOrderedGlyphs(heads[at_baselig].glyphs);
- *mkmk = SFOrderedGlyphs(heads[at_basemark].glyphs);
-}
-
-SplineChar **EntryExitDecompose(SplineFont *sf,AnchorClass *ac,struct glyphinfo *gi) {
- /* Run through the font finding all characters with this anchor class */
- int i,j, cnt, gmax, gid;
- SplineChar **array;
- AnchorPoint *test;
-
- array=NULL;
- gmax = gi==NULL ? sf->glyphcnt : gi->gcnt;
- for ( j=0; j<2; ++j ) {
- cnt = 0;
- for ( i=0; i<gmax; ++i ) if ( (gid = gi==NULL ? i : gi->bygid[i])!=-1 && sf->glyphs[gid]!=NULL ) {
- for ( test=sf->glyphs[gid]->anchor; test!=NULL && test->anchor!=ac; test=test->next );
- if ( test!=NULL && (test->type==at_centry || test->type==at_cexit )) {
- if ( array!=NULL )
- array[cnt] = sf->glyphs[gid];
- ++cnt;
- }
- }
- if ( cnt==0 )
-return( NULL );
- if ( j==1 )
- break;
- array = malloc((cnt+1)*sizeof(SplineChar *));
- array[cnt] = NULL;
- }
-return( array );
-}
-
-static void AnchorGuessContext(SplineFont *sf,struct alltabs *at) {
- int i;
- int maxbase=0, maxmark=0, basec, markc;
- AnchorPoint *ap;
- int hascursive = 0;
-
- /* the order in which we examine the glyphs does not matter here, so */
- /* we needn't add the complexity running though in gid order */
- for ( i=0; i<sf->glyphcnt; ++i ) if ( sf->glyphs[i] ) {
- basec = markc = 0;
- for ( ap = sf->glyphs[i]->anchor; ap!=NULL; ap=ap->next )
- if ( ap->type==at_basemark )
- ++markc;
- else if ( ap->type==at_basechar || ap->type==at_baselig )
- ++basec;
- else if ( ap->type==at_centry )
- hascursive = true;
- if ( basec>maxbase ) maxbase = basec;
- if ( markc>maxmark ) maxmark = markc;
- }
-
- if ( maxbase*(maxmark+1)>at->os2.maxContext )
- at->os2.maxContext = maxbase*(maxmark+1);
- if ( hascursive && at->os2.maxContext<2 )
- at->os2.maxContext=2;
-}
-
-static void dumpcoveragetable(FILE *gpos,SplineChar **glyphs) {
- int i, last = -2, range_cnt=0, start, r;
- /* the glyph list should already be sorted */
- /* figure out whether it is better (smaller) to use an array of glyph ids */
- /* or a set of glyph id ranges */
-
- for ( i=0; glyphs[i]!=NULL; ++i ) {
- if ( glyphs[i]->ttf_glyph<=last )
- IError("Glyphs must be ordered when creating coverage table");
- if ( glyphs[i]->ttf_glyph!=last+1 )
- ++range_cnt;
- last = glyphs[i]->ttf_glyph;
- }
- /* I think Windows will only accept format 2 coverage tables? */
- if ( !(coverageformatsallowed&2) || ((coverageformatsallowed&1) && i<=3*range_cnt )) {
- /* We use less space with a list of glyphs than with a set of ranges */
- putshort(gpos,1); /* Coverage format=1 => glyph list */
- putshort(gpos,i); /* count of glyphs */
- for ( i=0; glyphs[i]!=NULL; ++i )
- putshort(gpos,glyphs[i]->ttf_glyph); /* array of glyph IDs */
- } else {
- putshort(gpos,2); /* Coverage format=2 => range list */
- putshort(gpos,range_cnt); /* count of ranges */
- last = -2; start = -2; /* start is a index in our glyph array, last is ttf_glyph */
- r = 0;
- for ( i=0; glyphs[i]!=NULL; ++i ) {
- if ( glyphs[i]->ttf_glyph!=last+1 ) {
- if ( last!=-2 ) {
- putshort(gpos,glyphs[start]->ttf_glyph); /* start glyph ID */
- putshort(gpos,last); /* end glyph ID */
- putshort(gpos,start); /* coverage index of start glyph */
- ++r;
- }
- start = i;
- }
- last = glyphs[i]->ttf_glyph;
- }
- if ( last!=-2 ) {
- putshort(gpos,glyphs[start]->ttf_glyph); /* start glyph ID */
- putshort(gpos,last); /* end glyph ID */
- putshort(gpos,start); /* coverage index of start glyph */
- ++r;
- }
- if ( r!=range_cnt )
- IError("Miscounted ranges in format 2 coverage table output");
- }
-}
-
-static int sc_ttf_order( const void *_sc1, const void *_sc2) {
- const SplineChar *sc1 = *(const SplineChar **) _sc1, *sc2 = *(const SplineChar **) _sc2;
-return( sc1->ttf_glyph - sc2->ttf_glyph );
-}
-
-static SplineChar **SFOrderedGlyphs(SplineChar **glyphs) {
- int cnt, i, k;
- if ( glyphs==NULL )
-return( NULL );
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt);
- qsort(glyphs,cnt,sizeof(SplineChar *),sc_ttf_order);
- if ( glyphs[0]->ttf_glyph==-1 ) {
- /* Not sure if this can happen, but it's easy to fix */
- for ( k=0; k<cnt && glyphs[k]->ttf_glyph==-1; ++k);
- for ( i=0; i<=cnt-k; ++i )
- glyphs[i] = glyphs[i+k];
- }
- for ( i=0; i<cnt-1; ++i )
- if (glyphs[i]->ttf_glyph==glyphs[i+1]->ttf_glyph) {
- memmove(glyphs+i, glyphs+i+1, (cnt-i)*sizeof(SplineChar *));
- --cnt;
- }
-return( glyphs );
-}
-
-static SplineChar **SFOrderedGlyphsWithPSTinSubtable(SplineFont *sf,struct lookup_subtable *sub) {
- SplineChar **glyphs = SFGlyphsWithPSTinSubtable(sf,sub);
- return SFOrderedGlyphs(glyphs);
-}
-
-SplineChar **SFGlyphsFromNames(SplineFont *sf,char *names) {
- int cnt, ch;
- char *pt, *end;
- SplineChar *sc, **glyphs;
-
- if ( names==NULL )
-return( calloc(1,sizeof(SplineChar *)) );
-
- cnt = 0;
- for ( pt = names; *pt; pt = end+1 ) {
- ++cnt;
- end = strchr(pt,' ');
- if ( end==NULL )
- break;
- }
-
- glyphs = malloc((cnt+1)*sizeof(SplineChar *));
- cnt = 0;
- for ( pt = names; *pt; pt = end+1 ) {
- end = strchr(pt,' ');
- if ( end==NULL )
- end = pt+strlen(pt);
- ch = *end;
- *end = '\0';
- sc = SFGetChar(sf,-1,pt);
- if ( sc!=NULL && sc->ttf_glyph!=-1 )
- glyphs[cnt++] = sc;
- *end = ch;
- if ( ch=='\0' )
- break;
- }
- glyphs[cnt] = NULL;
-return( glyphs );
-}
-
-static SplineChar **OrderedGlyphsFromNames(SplineFont *sf,char *names) {
- SplineChar **glyphs = SFGlyphsFromNames(sf,names);
- int i,j;
-
- if ( glyphs==NULL || glyphs[0]==NULL )
-return( glyphs );
-
- for ( i=0; glyphs[i+1]!=NULL; ++i ) for ( j=i+1; glyphs[j]!=NULL; ++j ) {
- if ( glyphs[i]->ttf_glyph > glyphs[j]->ttf_glyph ) {
- SplineChar *sc = glyphs[i];
- glyphs[i] = glyphs[j];
- glyphs[j] = sc;
- }
- }
- if ( glyphs[0]!=NULL ) { /* Glyphs should not appear twice in the name list, just just in case they do... */
- for ( i=0; glyphs[i+1]!=NULL; ++i ) {
- if ( glyphs[i]==glyphs[i+1] ) {
- for ( j=i+1; glyphs[j]!=NULL; ++j )
- glyphs[j] = glyphs[j+1];
- }
- }
- }
-return( glyphs );
-}
-
-static void gposvrmaskeddump(FILE *gpos,int vf1,int mask,int offset) {
- if ( vf1&1 ) putshort(gpos,mask&1 ? offset : 0 );
- if ( vf1&2 ) putshort(gpos,mask&2 ? offset : 0 );
- if ( vf1&4 ) putshort(gpos,mask&4 ? offset : 0 );
- if ( vf1&8 ) putshort(gpos,mask&8 ? offset : 0 );
-}
-
-static int devtaboffsetsize(DeviceTable *dt) {
- int type = 1, i;
-
- for ( i=dt->last_pixel_size-dt->first_pixel_size; i>=0; --i ) {
- if ( dt->corrections[i]>=8 || dt->corrections[i]<-8 )
-return( 3 );
- else if ( dt->corrections[i]>=2 || dt->corrections[i]<-2 )
- type = 2;
- }
-return( type );
-}
-
-static void dumpgposdevicetable(FILE *gpos,DeviceTable *dt) {
- int type;
- int i,cnt,b;
-
- if ( dt==NULL || dt->corrections==NULL )
-return;
- type = devtaboffsetsize(dt);
- putshort(gpos,dt->first_pixel_size);
- putshort(gpos,dt->last_pixel_size );
- putshort(gpos,type);
- cnt = dt->last_pixel_size - dt->first_pixel_size + 1;
- if ( type==3 ) {
- for ( i=0; i<cnt; ++i )
- putc(dt->corrections[i],gpos);
- if ( cnt&1 )
- putc(0,gpos);
- } else if ( type==2 ) {
- for ( i=0; i<cnt; i+=4 ) {
- int val = 0;
- for ( b=0; b<4 && i+b<cnt; ++b )
- val |= (dt->corrections[i+b]&0x000f)<<(12-b*4);
- putshort(gpos,val);
- }
- } else {
- for ( i=0; i<cnt; i+=8 ) {
- int val = 0;
- for ( b=0; b<8 && i+b<cnt; ++b )
- val |= (dt->corrections[i+b]&0x0003)<<(14-b*2);
- putshort(gpos,val);
- }
- }
-}
-
-static int DevTabLen(DeviceTable *dt) {
- int type;
- int cnt;
-
- if ( dt==NULL || dt->corrections==NULL )
-return( 0 );
- cnt = dt->last_pixel_size - dt->first_pixel_size + 1;
- type = devtaboffsetsize(dt);
- if ( type==3 )
- cnt = (cnt+1)/2;
- else if ( type==2 )
- cnt = (cnt+3)/4;
- else
- cnt = (cnt+7)/8;
- cnt += 3; /* first, last, type */
-return( sizeof(uint16)*cnt );
-}
-
-static int ValDevTabLen(ValDevTab *vdt) {
-
- if ( vdt==NULL )
-return( 0 );
-
-return( DevTabLen(&vdt->xadjust) + DevTabLen(&vdt->yadjust) +
- DevTabLen(&vdt->xadv) + DevTabLen(&vdt->yadv) );
-}
-
-static int gposdumpvaldevtab(FILE *gpos,ValDevTab *vdt,int bits,int next_dev_tab ) {
-
- if ( bits&0x10 ) {
- if ( vdt==NULL || vdt->xadjust.corrections==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(&vdt->xadjust);
- }
- }
- if ( bits&0x20 ) {
- if ( vdt==NULL || vdt->yadjust.corrections==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(&vdt->yadjust);
- }
- }
- if ( bits&0x40 ) {
- if ( vdt==NULL || vdt->xadv.corrections==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(&vdt->xadv);
- }
- }
- if ( bits&0x80 ) {
- if ( vdt==NULL || vdt->yadv.corrections==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(&vdt->yadv);
- }
- }
-return( next_dev_tab );
-}
-
-static int gposmaskeddumpdevtab(FILE *gpos,DeviceTable *dt,int bits,int mask,
- int next_dev_tab ) {
-
- if ( bits&0x10 ) {
- if ( !(mask&0x10) || dt==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(dt);
- }
- }
- if ( bits&0x20 ) {
- if ( !(mask&0x20) || dt==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(dt);
- }
- }
- if ( bits&0x40 ) {
- if ( !(mask&0x40) || dt==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(dt);
- }
- }
- if ( bits&0x80 ) {
- if ( !(mask&0x80) || dt==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,next_dev_tab);
- next_dev_tab += DevTabLen(dt);
- }
- }
-return( next_dev_tab );
-}
-
-static int DevTabsSame(DeviceTable *dt1, DeviceTable *dt2) {
- DeviceTable _dt;
- int i;
-
- if ( dt1==NULL && dt2==NULL )
-return( true );
- if ( dt1==NULL ) {
- memset(&_dt,0,sizeof(_dt));
- dt1 = &_dt;
- }
- if ( dt2==NULL ) {
- memset(&_dt,0,sizeof(_dt));
- dt2 = &_dt;
- }
- if ( dt1->corrections==NULL && dt2->corrections==NULL )
-return( true );
- if ( dt1->corrections==NULL || dt2->corrections==NULL )
-return( false );
- if ( dt1->first_pixel_size!=dt2->first_pixel_size ||
- dt1->last_pixel_size!=dt2->last_pixel_size )
-return( false );
- for ( i=dt2->last_pixel_size-dt1->first_pixel_size; i>=0; --i )
- if ( dt1->corrections[i]!=dt2->corrections[i] )
-return( false );
-
-return( true );
-}
-
-static int ValDevTabsSame(ValDevTab *vdt1, ValDevTab *vdt2) {
- ValDevTab _vdt;
-
- if ( vdt1==NULL && vdt2==NULL )
-return( true );
- if ( vdt1==NULL ) {
- memset(&_vdt,0,sizeof(_vdt));
- vdt1 = &_vdt;
- }
- if ( vdt2==NULL ) {
- memset(&_vdt,0,sizeof(_vdt));
- vdt2 = &_vdt;
- }
-return( DevTabsSame(&vdt1->xadjust,&vdt2->xadjust) &&
- DevTabsSame(&vdt1->yadjust,&vdt2->yadjust) &&
- DevTabsSame(&vdt1->xadv,&vdt2->xadv) &&
- DevTabsSame(&vdt1->yadv,&vdt2->yadv) );
-}
-
-static void dumpGPOSsimplepos(FILE *gpos,SplineFont *sf,struct lookup_subtable *sub ) {
- int cnt, cnt2;
- int32 coverage_pos, end;
- PST *pst, *first=NULL;
- int bits = 0, same=true;
- SplineChar **glyphs;
-
- glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
- for ( cnt=cnt2=0; glyphs[cnt]!=NULL; ++cnt) {
- for ( pst=glyphs[cnt]->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->subtable==sub && pst->type==pst_position ) {
- if ( first==NULL ) first = pst;
- else if ( same ) {
- if ( first->u.pos.xoff!=pst->u.pos.xoff ||
- first->u.pos.yoff!=pst->u.pos.yoff ||
- first->u.pos.h_adv_off!=pst->u.pos.h_adv_off ||
- first->u.pos.v_adv_off!=pst->u.pos.v_adv_off )
- same = false;
- if ( !ValDevTabsSame(pst->u.pos.adjust,first->u.pos.adjust))
- same = false;
- }
- if ( pst->u.pos.xoff!=0 ) bits |= 1;
- if ( pst->u.pos.yoff!=0 ) bits |= 2;
- if ( pst->u.pos.h_adv_off!=0 ) bits |= 4;
- if ( pst->u.pos.v_adv_off!=0 ) bits |= 8;
- if ( pst->u.pos.adjust!=NULL ) {
- if ( pst->u.pos.adjust->xadjust.corrections!=NULL ) bits |= 0x10;
- if ( pst->u.pos.adjust->yadjust.corrections!=NULL ) bits |= 0x20;
- if ( pst->u.pos.adjust->xadv.corrections!=NULL ) bits |= 0x40;
- if ( pst->u.pos.adjust->yadv.corrections!=NULL ) bits |= 0x80;
- }
- ++cnt2;
- break;
- }
- }
- }
- if ( bits==0 ) bits=1;
- if ( cnt!=cnt2 )
- IError( "Count mismatch in dumpGPOSsimplepos#1 %d vs %d\n", cnt, cnt2 );
-
- putshort(gpos,same?1:2); /* 1 means all value records same */
- coverage_pos = ftell(gpos);
- putshort(gpos,0); /* offset to coverage table */
- putshort(gpos,bits);
- if ( same ) {
- if ( bits&1 ) putshort(gpos,first->u.pos.xoff);
- if ( bits&2 ) putshort(gpos,first->u.pos.yoff);
- if ( bits&4 ) putshort(gpos,first->u.pos.h_adv_off);
- if ( bits&8 ) putshort(gpos,first->u.pos.v_adv_off);
- if ( bits&0xf0 ) {
- int next_dev_tab = ftell(gpos)-coverage_pos+2+
- sizeof(int16)*((bits&0x10?1:0) + (bits&0x20?1:0) + (bits&0x40?1:0) + (bits&0x80?1:0));
- if ( bits&0x10 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->xadjust); }
- if ( bits&0x20 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->yadjust); }
- if ( bits&0x40 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->xadv); }
- if ( bits&0x80 ) { putshort(gpos,next_dev_tab); next_dev_tab += DevTabLen(&first->u.pos.adjust->yadv); }
- if ( bits&0x10 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadjust);
- if ( bits&0x20 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadjust);
- if ( bits&0x40 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadv);
- if ( bits&0x80 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadv);
- if ( next_dev_tab!=ftell(gpos)-coverage_pos+2 )
- IError( "Device Table offsets wrong in simple positioning 2");
- }
- } else {
- int vr_size =
- sizeof(int16)*((bits&0x1?1:0) + (bits&0x2?1:0) + (bits&0x4?1:0) + (bits&0x8?1:0) +
- (bits&0x10?1:0) + (bits&0x20?1:0) + (bits&0x40?1:0) + (bits&0x80?1:0));
- int next_dev_tab = ftell(gpos)-coverage_pos+2+2+vr_size*cnt;
- putshort(gpos,cnt);
- for ( cnt2 = 0; glyphs[cnt2]!=NULL; ++cnt2 ) {
- for ( pst=glyphs[cnt2]->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->subtable==sub && pst->type==pst_position ) {
- if ( bits&1 ) putshort(gpos,pst->u.pos.xoff);
- if ( bits&2 ) putshort(gpos,pst->u.pos.yoff);
- if ( bits&4 ) putshort(gpos,pst->u.pos.h_adv_off);
- if ( bits&8 ) putshort(gpos,pst->u.pos.v_adv_off);
- next_dev_tab = gposdumpvaldevtab(gpos,pst->u.pos.adjust,bits,
- next_dev_tab);
- break;
- }
- }
- }
- if ( cnt!=cnt2 )
- IError( "Count mismatch in dumpGPOSsimplepos#3 %d vs %d\n", cnt, cnt2 );
- if ( bits&0xf0 ) {
- for ( cnt2 = 0; glyphs[cnt2]!=NULL; ++cnt2 ) {
- for ( pst=glyphs[cnt2]->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->subtable==sub && pst->type==pst_position ) {
- if ( bits&0x10 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadjust);
- if ( bits&0x20 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadjust);
- if ( bits&0x40 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->xadv);
- if ( bits&0x80 ) dumpgposdevicetable(gpos,&first->u.pos.adjust->yadv);
- }
- }
- }
- }
- if ( next_dev_tab!=ftell(gpos)-coverage_pos+2 )
- IError( "Device Table offsets wrong in simple positioning 2");
- }
- end = ftell(gpos);
- fseek(gpos,coverage_pos,SEEK_SET);
- putshort(gpos,end-coverage_pos+2);
- fseek(gpos,end,SEEK_SET);
- dumpcoveragetable(gpos,glyphs);
- fseek(gpos,0,SEEK_END);
- free(glyphs);
-}
-
-struct sckppst {
- uint16 samewas;
- uint16 devtablen;
- uint16 tot;
- uint8 isv;
- uint8 subtable_too_big;
-/* The first few fields are only meaningful in the first structure in the array*/
-/* and provide information about the entire rest of the array */
- uint16 other_gid;
- SplineChar *sc;
- KernPair *kp;
- PST *pst;
-};
-
-static int cmp_gid( const void *_s1, const void *_s2 ) {
- const struct sckppst *s1 = _s1, *s2 = _s2;
-return( ((int) s1->other_gid) - ((int) s2->other_gid) );
-}
-
-static void dumpGPOSpairpos(FILE *gpos,SplineFont *sf,struct lookup_subtable *sub) {
- int cnt;
- int32 coverage_pos, offset_pos, end, start, pos;
- PST *pst;
- KernPair *kp;
- int vf1 = 0, vf2=0, i, j, k, tot, bit_cnt, v;
- int start_cnt, end_cnt;
- int chunk_cnt, chunk_max;
- SplineChar *sc, **glyphs, *gtemp;
- struct sckppst **seconds;
- int devtablen;
- int next_dev_tab;
-
- /* Figure out all the data we need. First the glyphs with kerning info */
- /* then the glyphs to which they kern, and by how much */
- glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt);
- seconds = malloc(cnt*sizeof(struct sckppst *));
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt) {
- for ( k=0; k<2; ++k ) {
- devtablen = 0;
- tot = 0;
- for ( pst=glyphs[cnt]->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->subtable==sub && pst->type==pst_pair &&
- (sc = SFGetChar(sf,-1,pst->u.pair.paired))!=NULL &&
- sc->ttf_glyph!=-1 ) {
- if ( k ) {
- seconds[cnt][tot].sc = sc;
- seconds[cnt][tot].other_gid = sc->ttf_glyph;
- seconds[cnt][tot].pst = pst;
- devtablen += ValDevTabLen(pst->u.pair.vr[0].adjust) +
- ValDevTabLen(pst->u.pair.vr[1].adjust);
-
- }
- ++tot;
- }
- }
- for ( v=0; v<2; ++v ) {
- for ( kp = v ? glyphs[cnt]->vkerns : glyphs[cnt]->kerns; kp!=NULL; kp=kp->next ) {
- if( kp->subtable!=sub ) continue; // process only glyphs from the current subtable
- if ( kp->sc->ttf_glyph!=-1 ) {
- if ( k ) {
- seconds[cnt][tot].other_gid = kp->sc->ttf_glyph;
- seconds[cnt][tot].sc = kp->sc;
- seconds[cnt][tot].kp = kp;
- seconds[cnt][tot].isv = v;
- devtablen += DevTabLen(kp->adjust);
- }
- ++tot;
- }
- }
- }
- if ( k==0 ) {
- seconds[cnt] = calloc(tot+1,sizeof(struct sckppst));
- } else {
- qsort(seconds[cnt],tot,sizeof(struct sckppst),cmp_gid);
- seconds[cnt][0].tot = tot;
- /* Devtablen is 0 unless we are configured for device tables */
- seconds[cnt][0].devtablen = devtablen;
- seconds[cnt][0].samewas = 0xffff;
- }
- }
- }
-
- /* Some fonts do a primitive form of class based kerning, several glyphs */
- /* can share the same list of second glyphs & offsets */
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt) {
- struct sckppst *test = seconds[cnt], *test2;
- for ( i=cnt-1; i>=0; --i ) {
- test2 = seconds[i];
- if ( test[0].tot != test2[0].tot || test2[0].samewas!=0xffff )
- continue;
- for ( j=test[0].tot-1; j>=0; --j ) {
- if ( test[j].other_gid != test2[j].other_gid )
- break;
- if ( test[j].kp!=NULL && test2[j].kp!=NULL &&
- test[j].kp->off == test2[j].kp->off
- && DevTabsSame(test[j].kp->adjust,test2[j].kp->adjust)
- )
- /* So far, so good */;
- else if ( test[j].pst!=NULL && test2[j].pst!=NULL &&
- test[j].pst->u.pair.vr[0].xoff == test2[j].pst->u.pair.vr[0].xoff &&
- test[j].pst->u.pair.vr[0].yoff == test2[j].pst->u.pair.vr[0].yoff &&
- test[j].pst->u.pair.vr[0].h_adv_off == test2[j].pst->u.pair.vr[0].h_adv_off &&
- test[j].pst->u.pair.vr[0].v_adv_off == test2[j].pst->u.pair.vr[0].v_adv_off &&
- test[j].pst->u.pair.vr[1].xoff == test2[j].pst->u.pair.vr[1].xoff &&
- test[j].pst->u.pair.vr[1].yoff == test2[j].pst->u.pair.vr[1].yoff &&
- test[j].pst->u.pair.vr[1].h_adv_off == test2[j].pst->u.pair.vr[1].h_adv_off &&
- test[j].pst->u.pair.vr[1].v_adv_off == test2[j].pst->u.pair.vr[1].v_adv_off
- && ValDevTabsSame(test[j].pst->u.pair.vr[0].adjust,test2[j].pst->u.pair.vr[0].adjust)
- && ValDevTabsSame(test[j].pst->u.pair.vr[1].adjust,test2[j].pst->u.pair.vr[1].adjust)
- )
- /* That's ok too. */;
- else
- break;
- }
- if ( j>=0 )
- continue;
- test[0].samewas = i;
- break;
- }
- }
-
- /* Ok, how many offsets must we output? Normal kerning will just use */
- /* one offset (with perhaps a device table), but the standard allows */
- /* us to adjust 8 different values (with 8 different device tables) */
- /* Find out which we need */
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt) {
- for ( tot=0 ; tot<seconds[cnt][0].tot; ++tot ) {
- if ( (pst=seconds[cnt][tot].pst)!=NULL ) {
- if ( pst->subtable==sub && pst->type==pst_pair ) {
- if ( pst->u.pair.vr[0].xoff!=0 ) vf1 |= 1;
- if ( pst->u.pair.vr[0].yoff!=0 ) vf1 |= 2;
- if ( pst->u.pair.vr[0].h_adv_off!=0 ) vf1 |= 4;
- if ( pst->u.pair.vr[0].v_adv_off!=0 ) vf1 |= 8;
- if ( pst->u.pair.vr[0].adjust!=NULL ) {
- if ( pst->u.pair.vr[0].adjust->xadjust.corrections!=NULL ) vf1 |= 0x10;
- if ( pst->u.pair.vr[0].adjust->yadjust.corrections!=NULL ) vf1 |= 0x20;
- if ( pst->u.pair.vr[0].adjust->xadv.corrections!=NULL ) vf1 |= 0x40;
- if ( pst->u.pair.vr[0].adjust->yadv.corrections!=NULL ) vf1 |= 0x80;
- }
- if ( pst->u.pair.vr[1].xoff!=0 ) vf2 |= 1;
- if ( pst->u.pair.vr[1].yoff!=0 ) vf2 |= 2;
- if ( pst->u.pair.vr[1].h_adv_off!=0 ) vf2 |= 4;
- if ( pst->u.pair.vr[1].v_adv_off!=0 ) vf2 |= 8;
- if ( pst->u.pair.vr[1].adjust!=NULL ) {
- if ( pst->u.pair.vr[1].adjust->xadjust.corrections!=NULL ) vf2 |= 0x10;
- if ( pst->u.pair.vr[1].adjust->yadjust.corrections!=NULL ) vf2 |= 0x20;
- if ( pst->u.pair.vr[1].adjust->xadv.corrections!=NULL ) vf2 |= 0x40;
- if ( pst->u.pair.vr[1].adjust->yadv.corrections!=NULL ) vf2 |= 0x80;
- }
- }
- }
- if ( (kp = seconds[cnt][tot].kp)!=NULL ) {
- int mask = 0, mask2=0;
- if ( seconds[cnt][tot].isv )
- mask = 0x0008;
- else
- mask = 0x0004;
- if ( kp->adjust!=NULL ) {
- mask |= mask<<4;
- mask2 |= mask2<<4;
- }
- vf1 |= mask;
- vf2 |= mask2;
- }
- }
- }
- if ( vf1==0 && vf2==0 ) vf1=1;
- bit_cnt = 0;
- for ( i=0; i<8; ++i ) {
- if ( vf1&(1<<i) ) ++bit_cnt;
- if ( vf2&(1<<i) ) ++bit_cnt;
- }
-
- chunk_max = chunk_cnt = 0;
- for ( start_cnt=0; start_cnt<cnt; start_cnt=end_cnt ) {
- int len = 5*2; /* Subtable header */
- for ( end_cnt=start_cnt; end_cnt<cnt; ++end_cnt ) {
- int glyph_len = 2; /* For the glyph's offset */
- if ( seconds[end_cnt][0].samewas==0xffff || seconds[end_cnt][0].samewas<start_cnt )
- glyph_len += (bit_cnt*2+2)*seconds[end_cnt][0].tot +
- seconds[end_cnt][0].devtablen +
- 2; /* Number of secondary glyphs */
- if ( glyph_len>65535 && end_cnt==start_cnt ) {
- LogError(_("Lookup subtable %s contains a glyph %s whose kerning information takes up more than 64k bytes\n"),
- sub->subtable_name, glyphs[start_cnt]->name );
- len += glyph_len;
- } else if ( len+glyph_len>65535 ) {
- if( start_cnt==0 )
- LogError(_("Lookup subtable %s had to be split into several subtables\nbecause it was too big.\n"),
- sub->subtable_name );
- break;
- } else
- len += glyph_len;
- }
- if ( start_cnt!=0 || end_cnt!=cnt ) {
- if ( chunk_cnt>=chunk_max )
- sub->extra_subtables = realloc(sub->extra_subtables,((chunk_max+=10)+1)*sizeof(uint32));
- sub->extra_subtables[chunk_cnt++] = ftell(gpos);
- sub->extra_subtables[chunk_cnt] = -1;
- }
-
- start = ftell(gpos);
- putshort(gpos,1); /* 1 means char pairs (ie. not classes) */
- coverage_pos = ftell(gpos);
- putshort(gpos,0); /* offset to coverage table */
- putshort(gpos,vf1);
- putshort(gpos,vf2);
- putshort(gpos,end_cnt-start_cnt);
- offset_pos = ftell(gpos);
- for ( i=start_cnt; i<end_cnt; ++i )
- putshort(gpos,0); /* Fill in later */
- for ( i=start_cnt; i<end_cnt; ++i ) {
- if ( seconds[i][0].samewas>= start_cnt && seconds[i][0].samewas!=0xffff ) {
- /* It's the same as the glyph at samewas, so just copy the */
- /* offset from there. We don't need to do anything else */
- int offset;
- fseek(gpos,offset_pos+(seconds[i][0].samewas-start_cnt)*sizeof(uint16),SEEK_SET);
- offset = getushort(gpos);
- fseek(gpos,offset_pos+(i-start_cnt)*sizeof(uint16),SEEK_SET);
- putshort(gpos,offset);
- fseek(gpos,0,SEEK_END);
- continue;
- }
- next_dev_tab = ftell(gpos)-start;
- if ( (vf1&0xf0) || (vf2&0xf0) ) {
- for ( tot=0 ; tot<seconds[i][0].tot; ++tot ) {
- if ( (pst=seconds[i][tot].pst)!=NULL ) {
- if ( pst->u.pair.vr[0].adjust!=NULL ) {
- dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->xadjust);
- dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->yadjust);
- dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->xadv);
- dumpgposdevicetable(gpos,&pst->u.pair.vr[0].adjust->yadv);
- }
- if ( pst->u.pair.vr[1].adjust!=NULL ) {
- dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->xadjust);
- dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->yadjust);
- dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->xadv);
- dumpgposdevicetable(gpos,&pst->u.pair.vr[1].adjust->yadv);
- }
- }
- if ( (kp=seconds[i][tot].kp)!=NULL && kp->adjust!=NULL )
- dumpgposdevicetable(gpos,kp->adjust);
- }
- }
- pos = ftell(gpos);
- fseek(gpos,offset_pos+(i-start_cnt)*sizeof(uint16),SEEK_SET);
- putshort(gpos,pos-start);
- fseek(gpos,pos,SEEK_SET);
-
- putshort(gpos,seconds[i][0].tot);
- for ( tot=0 ; tot<seconds[i][0].tot; ++tot ) {
- putshort(gpos,seconds[i][tot].other_gid);
- if ( (pst=seconds[i][tot].pst)!=NULL ) {
- if ( vf1&1 ) putshort(gpos,pst->u.pair.vr[0].xoff);
- if ( vf1&2 ) putshort(gpos,pst->u.pair.vr[0].yoff);
- if ( vf1&4 ) putshort(gpos,pst->u.pair.vr[0].h_adv_off);
- if ( vf1&8 ) putshort(gpos,pst->u.pair.vr[0].v_adv_off);
- next_dev_tab = gposdumpvaldevtab(gpos,pst->u.pair.vr[0].adjust,vf1,
- next_dev_tab);
- if ( vf2&1 ) putshort(gpos,pst->u.pair.vr[1].xoff);
- if ( vf2&2 ) putshort(gpos,pst->u.pair.vr[1].yoff);
- if ( vf2&4 ) putshort(gpos,pst->u.pair.vr[1].h_adv_off);
- if ( vf2&8 ) putshort(gpos,pst->u.pair.vr[1].v_adv_off);
- next_dev_tab = gposdumpvaldevtab(gpos,pst->u.pair.vr[1].adjust,vf2,
- next_dev_tab);
- } else if ( (kp=seconds[i][tot].kp)!=NULL ) {
- int mask=0, mask2=0;
- if ( seconds[i][tot].isv )
- mask = 0x8;
- else
- mask = 0x4;
- gposvrmaskeddump(gpos,vf1,mask,kp->off);
- next_dev_tab = gposmaskeddumpdevtab(gpos,kp->adjust,vf1,mask<<4,
- next_dev_tab);
- gposvrmaskeddump(gpos,vf2,mask2,kp->off);
- next_dev_tab = gposmaskeddumpdevtab(gpos,kp->adjust,vf2,mask2<<4,
- next_dev_tab);
- }
- }
- }
- end = ftell(gpos);
- fseek(gpos,coverage_pos,SEEK_SET);
- if ( end-start>65535 )
- IError(_("I miscalculated the size of subtable %s, this means the kerning output is wrong."), sub->subtable_name );
- putshort(gpos,end-start);
- fseek(gpos,end,SEEK_SET);
- gtemp = glyphs[end_cnt]; glyphs[end_cnt] = NULL;
- dumpcoveragetable(gpos,glyphs+start_cnt);
- glyphs[end_cnt] = gtemp;
- }
- for ( i=0; i<cnt; ++i )
- free(seconds[i]);
- free(seconds);
- free(glyphs);
-}
-
-uint16 *ClassesFromNames(SplineFont *sf,char **classnames,int class_cnt,
- int numGlyphs, SplineChar ***glyphs, int apple_kc) {
- uint16 *class;
- int i;
- char *pt, *end, ch;
- SplineChar *sc, **gs=NULL;
- int offset = (apple_kc && classnames[0]!=NULL);
-
- class = calloc(numGlyphs,sizeof(uint16));
- if ( glyphs ) *glyphs = gs = calloc(numGlyphs,sizeof(SplineChar *));
- for ( i=0; i<class_cnt; ++i ) {
- if ( i==0 && classnames[0]==NULL )
- continue;
- for ( pt = classnames[i]; *pt; pt = end+1 ) {
- while ( *pt==' ' ) ++pt;
- if ( *pt=='\0' )
- break;
- end = strchr(pt,' ');
- if ( end==NULL )
- end = pt+strlen(pt);
- ch = *end;
- *end = '\0';
- sc = SFGetChar(sf,-1,pt);
- if ( sc!=NULL && sc->ttf_glyph!=-1 ) {
- class[sc->ttf_glyph] = i+offset;
- if ( gs!=NULL )
- gs[sc->ttf_glyph] = sc;
- }
- *end = ch;
- if ( ch=='\0' )
- break;
- }
- }
-return( class );
-}
-
-static SplineChar **GlyphsFromClasses(SplineChar **gs, int numGlyphs) {
- int i, cnt;
- SplineChar **glyphs;
-
- for ( i=cnt=0; i<numGlyphs; ++i )
- if ( gs[i]!=NULL ) ++cnt;
- glyphs = malloc((cnt+1)*sizeof(SplineChar *));
- for ( i=cnt=0; i<numGlyphs; ++i )
- if ( gs[i]!=NULL )
- glyphs[cnt++] = gs[i];
- glyphs[cnt++] = NULL;
- free(gs);
-return( glyphs );
-}
-
-static SplineChar **GlyphsFromInitialClasses(SplineChar **gs, int numGlyphs, uint16 *classes, uint16 *initial) {
- int i, j, cnt;
- SplineChar **glyphs;
-
- for ( i=cnt=0; i<numGlyphs; ++i ) {
- for ( j=0; initial[j]!=0xffff; ++j )
- if ( initial[j]==classes[i])
- break;
- if ( initial[j]!=0xffff && gs[i]!=NULL ) ++cnt;
- }
- glyphs = malloc((cnt+1)*sizeof(SplineChar *));
- for ( i=cnt=0; i<numGlyphs; ++i ) {
- for ( j=0; initial[j]!=0xffff; ++j )
- if ( initial[j]==classes[i])
- break;
- if ( initial[j]!=0xffff && gs[i]!=NULL )
- glyphs[cnt++] = gs[i];
- }
- glyphs[cnt++] = NULL;
-return( glyphs );
-}
-
-static void DumpClass(FILE *gpos,uint16 *class,int numGlyphs) {
- int ranges, i, cur, first= -1, last=-1, istart;
-
- for ( i=ranges=0; i<numGlyphs; ) {
- istart = i;
- cur = class[i];
- while ( i<numGlyphs && class[i]==cur )
- ++i;
- if ( cur!=0 ) {
- ++ranges;
- if ( first==-1 ) first = istart;
- last = i-1;
- }
- }
- if ( ranges*3+1>last-first+1+2 || first==-1 ) {
- if ( first==-1 ) first = last = 0;
- putshort(gpos,1); /* Format 1, list of all posibilities */
- putshort(gpos,first);
- putshort(gpos,last-first+1);
- for ( i=first; i<=last ; ++i )
- putshort(gpos,class[i]);
- } else {
- putshort(gpos,2); /* Format 2, series of ranges */
- putshort(gpos,ranges);
- for ( i=0; i<numGlyphs; ) {
- istart = i;
- cur = class[i];
- while ( i<numGlyphs && class[i]==cur )
- ++i;
- if ( cur!=0 ) {
- putshort(gpos,istart);
- putshort(gpos,i-1);
- putshort(gpos,cur);
- }
- }
- }
-}
-
-static void dumpgposkernclass(FILE *gpos,SplineFont *sf,
- struct lookup_subtable *sub, struct alltabs *at) {
- uint32 begin_off = ftell(gpos), pos;
- uint16 *class1, *class2;
- KernClass *kc = sub->kc, *test;
- SplineChar **glyphs;
- int i, isv;
- int anydevtab = false;
- int next_devtab;
-
- putshort(gpos,2); /* format 2 of the pair adjustment subtable */
- putshort(gpos,0); /* offset to coverage table */
- for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i ) {
- if ( kc->adjusts[i].corrections!=NULL ) {
- anydevtab = true;
- break;
- }
- }
-
- for ( test=sf->vkerns; test!=NULL && test!=kc; test=test->next );
- isv = test==kc;
-
- if ( isv ) {
- /* As far as I know there is no "bottom to top" writing direction */
- /* Oh. There is. Ogham, Runic */
- putshort(gpos,anydevtab?0x0088:0x0008); /* Alter YAdvance of first character */
- putshort(gpos,0x0000); /* leave second char alone */
- } else {
- putshort(gpos,anydevtab?0x0044:0x0004); /* Alter XAdvance of first character */
- putshort(gpos,0x0000); /* leave second char alone */
- }
- class1 = ClassesFromNames(sf,kc->firsts,kc->first_cnt,at->maxp.numGlyphs,&glyphs,false);
- glyphs = GlyphsFromClasses(glyphs,at->maxp.numGlyphs);
- class2 = ClassesFromNames(sf,kc->seconds,kc->second_cnt,at->maxp.numGlyphs,NULL,false);
- putshort(gpos,0); /* offset to first glyph classes */
- putshort(gpos,0); /* offset to second glyph classes */
- putshort(gpos,kc->first_cnt);
- putshort(gpos,kc->second_cnt);
- next_devtab = ftell(gpos)-begin_off + kc->first_cnt*kc->second_cnt*2*sizeof(uint16);
- for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i ) {
- putshort(gpos,kc->offsets[i]);
- if ( anydevtab && kc->adjusts[i].corrections!=NULL ) {
- putshort(gpos,next_devtab);
- next_devtab += DevTabLen(&kc->adjusts[i]);
- } else if ( anydevtab )
- putshort(gpos,0);
- }
- if ( anydevtab ) {
- for ( i=0; i<kc->first_cnt*kc->second_cnt; ++i ) {
- if ( kc->adjusts[i].corrections!=NULL )
- dumpgposdevicetable(gpos,&kc->adjusts[i]);
- }
- if ( next_devtab!=ftell(gpos)-begin_off )
- IError("Device table offsets screwed up in kerning class");
- }
- pos = ftell(gpos);
- fseek(gpos,begin_off+4*sizeof(uint16),SEEK_SET);
- putshort(gpos,pos-begin_off);
- fseek(gpos,pos,SEEK_SET);
- DumpClass(gpos,class1,at->maxp.numGlyphs);
-
- pos = ftell(gpos);
- fseek(gpos,begin_off+5*sizeof(uint16),SEEK_SET);
- putshort(gpos,pos-begin_off);
- fseek(gpos,pos,SEEK_SET);
- DumpClass(gpos,class2,at->maxp.numGlyphs);
-
- pos = ftell(gpos);
- fseek(gpos,begin_off+sizeof(uint16),SEEK_SET);
- putshort(gpos,pos-begin_off);
- fseek(gpos,pos,SEEK_SET);
- dumpcoveragetable(gpos,glyphs);
-
- free(glyphs);
- free(class1);
- free(class2);
-}
-
-static void dumpanchor(FILE *gpos,AnchorPoint *ap, int is_ttf ) {
- int base = ftell(gpos);
-
- if ( ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL )
- putshort(gpos,3); /* format 3 w/ device tables */
- else
- if ( ap->has_ttf_pt && is_ttf )
- putshort(gpos,2); /* format 2 w/ a matching ttf point index */
- else
- putshort(gpos,1); /* Anchor format 1 just location*/
- putshort(gpos,ap->me.x); /* X coord of attachment */
- putshort(gpos,ap->me.y); /* Y coord of attachment */
- if ( ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL ) {
- putshort(gpos,ap->xadjust.corrections==NULL?0:
- ftell(gpos)-base+4);
- putshort(gpos,ap->yadjust.corrections==NULL?0:
- ftell(gpos)-base+2+DevTabLen(&ap->xadjust));
- dumpgposdevicetable(gpos,&ap->xadjust);
- dumpgposdevicetable(gpos,&ap->yadjust);
- } else
- if ( ap->has_ttf_pt && is_ttf )
- putshort(gpos,ap->ttf_pt_index);
-}
-
-static void dumpgposCursiveAttach(FILE *gpos, SplineFont *sf,
- struct lookup_subtable *sub,struct glyphinfo *gi) {
- AnchorClass *ac, *testac;
- SplineChar **entryexit;
- int cnt, offset,j;
- AnchorPoint *ap, *entry, *exit;
- uint32 coverage_offset, start;
-
- ac = NULL;
- for ( testac=sf->anchor; testac!=NULL; testac = testac->next ) {
- if ( testac->subtable == sub ) {
- if ( ac==NULL )
- ac = testac;
- else {
- ff_post_error(_("Two cursive anchor classes"),_("Two cursive anchor classes in the same subtable, %s"),
- sub->subtable_name);
- break;
- }
- }
- }
- if ( ac==NULL ) {
- IError( "Missing anchor class for %s", sub->subtable_name );
-return;
- }
- entryexit = EntryExitDecompose(sf,ac,gi);
- if ( entryexit==NULL )
-return;
-
- for ( cnt=0; entryexit[cnt]!=NULL; ++cnt );
-
- start = ftell(gpos);
- putshort(gpos,1); /* format 1 for this subtable */
- putshort(gpos,0); /* Fill in later, offset to coverage table */
- putshort(gpos,cnt); /* number of glyphs */
-
- offset = 6+2*2*cnt;
- for ( j=0; j<cnt; ++j ) {
- entry = exit = NULL;
- for ( ap=entryexit[j]->anchor; ap!=NULL; ap=ap->next ) {
- if ( ap->anchor==ac && ap->type==at_centry ) entry = ap;
- if ( ap->anchor==ac && ap->type==at_cexit ) exit = ap;
- }
- if ( entry!=NULL ) {
- putshort(gpos,offset);
- offset += 6;
- if ( entry->xadjust.corrections!=NULL || entry->yadjust.corrections!=NULL )
- offset += 4 + DevTabLen(&entry->xadjust) + DevTabLen(&entry->yadjust);
- if ( gi->is_ttf && entry->has_ttf_pt )
- offset += 2;
- } else
- putshort(gpos,0);
- if ( exit!=NULL ) {
- putshort(gpos,offset);
- offset += 6;
- if ( exit->xadjust.corrections!=NULL || exit->yadjust.corrections!=NULL )
- offset += 4 + DevTabLen(&exit->xadjust) + DevTabLen(&exit->yadjust);
- else
- if ( gi->is_ttf && exit->has_ttf_pt )
- offset += 2;
- } else
- putshort(gpos,0);
- }
- for ( j=0; j<cnt; ++j ) {
- entry = exit = NULL;
- for ( ap=entryexit[j]->anchor; ap!=NULL; ap=ap->next ) {
- if ( ap->anchor==ac && ap->type==at_centry ) entry = ap;
- if ( ap->anchor==ac && ap->type==at_cexit ) exit = ap;
- }
- if ( entry!=NULL )
- dumpanchor(gpos,entry,gi->is_ttf);
- if ( exit!=NULL )
- dumpanchor(gpos,exit,gi->is_ttf);
- }
- coverage_offset = ftell(gpos);
- dumpcoveragetable(gpos,entryexit);
- fseek(gpos,start+2,SEEK_SET);
- putshort(gpos,coverage_offset-start);
- fseek(gpos,0,SEEK_END);
-
- free(entryexit);
-}
-
-static int orderglyph(const void *_sc1,const void *_sc2) {
- SplineChar * const *sc1 = _sc1, * const *sc2 = _sc2;
-
-return( (*sc1)->ttf_glyph - (*sc2)->ttf_glyph );
-}
-
-static SplineChar **allmarkglyphs(SplineChar ***glyphlist, int classcnt) {
- SplineChar **glyphs;
- int i, tot, k;
-
- if ( classcnt==1 )
-return( SFOrderedGlyphs(glyphlist[0]));
-
- for ( i=tot=0; i<classcnt; ++i ) {
- for ( k=0; glyphlist[i][k]!=NULL; ++k );
- tot += k;
- }
- glyphs = malloc((tot+1)*sizeof(SplineChar *));
- for ( i=tot=0; i<classcnt; ++i ) {
- for ( k=0; glyphlist[i][k]!=NULL; ++k )
- glyphs[tot++] = glyphlist[i][k];
- }
- qsort(glyphs,tot,sizeof(SplineChar *),orderglyph);
- for ( i=k=0; i<tot; ++i ) {
- while ( i+1<tot && glyphs[i]==glyphs[i+1]) ++i;
- glyphs[k++] = glyphs[i];
- }
- glyphs[k] = NULL;
-return( glyphs );
-}
-
-static void dumpgposAnchorData(FILE *gpos,AnchorClass *_ac,
- enum anchor_type at,
- SplineChar ***marks,SplineChar **base,
- int classcnt, struct glyphinfo *gi) {
- AnchorClass *ac=NULL;
- int j,cnt,k,l, pos, offset, tot, max;
- uint32 coverage_offset, markarray_offset, subtable_start;
- AnchorPoint *ap, **aps;
- SplineChar **markglyphs;
-
- for ( cnt=0; base[cnt]!=NULL; ++cnt );
-
- subtable_start = ftell(gpos);
- putshort(gpos,1); /* format 1 for this subtable */
- putshort(gpos,0); /* Fill in later, offset to mark coverage table */
- putshort(gpos,0); /* Fill in later, offset to base coverage table */
- putshort(gpos,classcnt);
- putshort(gpos,0); /* Fill in later, offset to mark array */
- putshort(gpos,12); /* Offset to base array */
- /* Base array */
- putshort(gpos,cnt); /* Number of entries in array */
- if ( at==at_basechar || at==at_basemark ) {
- offset = 2;
- for ( l=0; l<3; ++l ) {
- for ( j=0; j<cnt; ++j ) {
- for ( k=0, ac=_ac; k<classcnt; ac=ac->next ) if ( ac->matches ) {
- if ( !ac->has_mark || !ac->has_base )
- continue;
- for ( ap=base[j]->anchor; ap!=NULL && (ap->anchor!=ac || ap->type!=at);
- ap=ap->next );
- switch ( l ) {
- case 0:
- offset += 2;
- break;
- case 1:
- if ( ap==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,offset);
- offset += 6;
- if ( ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL )
- offset += 4 + DevTabLen(&ap->xadjust) + DevTabLen(&ap->yadjust);
- else
- if ( gi->is_ttf && ap->has_ttf_pt )
- offset += 2;
- }
- break;
- case 2:
- if ( ap!=NULL )
- dumpanchor(gpos,ap,gi->is_ttf);
- break;
- }
- ++k;
- }
- }
- }
- } else {
- offset = 2+2*cnt;
- max = 0;
- for ( j=0; j<cnt; ++j ) {
- putshort(gpos,offset);
- pos = tot = 0;
- for ( ap=base[j]->anchor; ap!=NULL ; ap=ap->next )
- for ( k=0, ac=_ac; k<classcnt; ac=ac->next ) if ( ac->matches ) {
- if ( ap->anchor==ac ) {
- if ( ap->lig_index>pos ) pos = ap->lig_index;
- ++tot;
- }
- ++k;
- }
- if ( pos>max ) max = pos;
- offset += 2+(pos+1)*classcnt*2+tot*6;
- /* 2 for component count, for each component an offset to an offset to an anchor record */
- }
- ++max;
- int special_ceiling = classcnt*max;
- aps = malloc((classcnt*max+max)*sizeof(AnchorPoint *));
- for ( j=0; j<cnt; ++j ) {
- memset(aps,0,(classcnt*max+max)*sizeof(AnchorPoint *));
- pos = 0;
- for ( ap=base[j]->anchor; ap!=NULL ; ap=ap->next )
- for ( k=0, ac=_ac; k<classcnt; ac=ac->next ) if ( ac->matches ) {
- if ( ap->anchor==ac ) {
- if ( ap->lig_index>pos ) pos = ap->lig_index;
- if (k*max+ap->lig_index > special_ceiling || k*max+ap->lig_index < 0) {
- fprintf(stderr, "A ligature index is invalid.\n");
- } else {
- aps[k*max+ap->lig_index] = ap;
- }
- }
- ++k;
- }
- ++pos;
- putshort(gpos,pos);
- offset = 2+2*pos*classcnt;
- for ( l=0; l<pos; ++l ) {
- for ( k=0; k<classcnt; ++k ) {
- if ( aps[k*max+l]==NULL )
- putshort(gpos,0);
- else {
- putshort(gpos,offset);
- offset += 6;
- if ( aps[k*max+l]->xadjust.corrections!=NULL || aps[k*max+l]->yadjust.corrections!=NULL )
- offset += 4 + DevTabLen(&aps[k*max+l]->xadjust) +
- DevTabLen(&aps[k*max+l]->yadjust);
- else
- if ( gi->is_ttf && aps[k*max+l]->has_ttf_pt )
- offset += 2;
- }
- }
- }
- for ( l=0; l<pos; ++l ) {
- for ( k=0; k<classcnt; ++k ) {
- if ( aps[k*max+l]!=NULL ) {
- dumpanchor(gpos,aps[k*max+l],gi->is_ttf);
- }
- }
- }
- }
- free(aps); aps = NULL;
- }
- coverage_offset = ftell(gpos);
- fseek(gpos,subtable_start+4,SEEK_SET);
- putshort(gpos,coverage_offset-subtable_start);
- fseek(gpos,0,SEEK_END);
- dumpcoveragetable(gpos,base);
-
- /* We tried sharing the mark table, (among all these sub-tables) but */
- /* that doesn't work because we need to be able to reorder the sub-tables */
- markglyphs = allmarkglyphs(marks,classcnt);
- coverage_offset = ftell(gpos);
- dumpcoveragetable(gpos,markglyphs);
- markarray_offset = ftell(gpos);
- for ( cnt=0; markglyphs[cnt]!=NULL; ++cnt );
- putshort(gpos,cnt);
- offset = 2+4*cnt;
- for ( j=0; j<cnt; ++j ) {
- if ( classcnt==0 ) {
- putshort(gpos,0); /* Only one class */
- ap = NULL;
- } else {
- for ( k=0, ac=_ac; k<classcnt; ac=ac->next ) {
- if ( ac->matches ) {
- for ( ap = markglyphs[j]->anchor; ap!=NULL && (ap->anchor!=ac || ap->type!=at_mark);
- ap=ap->next );
- if ( ap!=NULL )
- break;
- ++k;
- }
- }
- putshort(gpos,k);
- }
- putshort(gpos,offset);
- offset += 6;
- if ( ap!=NULL && (ap->xadjust.corrections!=NULL || ap->yadjust.corrections!=NULL ))
- offset += 4 + DevTabLen(&ap->xadjust) + DevTabLen(&ap->yadjust);
- else
- if ( gi->is_ttf && ap->has_ttf_pt )
- offset += 2;
- }
- for ( j=0; j<cnt; ++j ) {
- for ( k=0, ac=_ac; k<classcnt; ac=ac->next ) {
- if ( ac->matches ) {
- for ( ap = markglyphs[j]->anchor; ap!=NULL && (ap->anchor!=ac || ap->type!=at_mark);
- ap=ap->next );
- if ( ap!=NULL )
- break;
- ++k;
- }
- }
- dumpanchor(gpos,ap,gi->is_ttf);
- }
- if ( markglyphs!=marks[0] )
- free(markglyphs);
-
- fseek(gpos,subtable_start+2,SEEK_SET); /* mark coverage table offset */
- putshort(gpos,coverage_offset-subtable_start);
- fseek(gpos,4,SEEK_CUR);
- putshort(gpos,markarray_offset-subtable_start);
-
- fseek(gpos,0,SEEK_END);
-}
-
-static void dumpGSUBsimplesubs(FILE *gsub,SplineFont *sf,struct lookup_subtable *sub) {
- int cnt, diff, ok = true;
- int32 coverage_pos, end;
- SplineChar **glyphs, ***maps;
-
- glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
- maps = generateMapList(glyphs,sub);
-
- diff = (*maps[0])->ttf_glyph - glyphs[0]->ttf_glyph;
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt)
- if ( diff!= maps[cnt][0]->ttf_glyph-glyphs[cnt]->ttf_glyph ) ok = false;
-
- if ( ok ) {
- putshort(gsub,1); /* delta format */
- coverage_pos = ftell(gsub);
- putshort(gsub,0); /* offset to coverage table */
- putshort(gsub,diff);
- } else {
- putshort(gsub,2); /* glyph list format */
- coverage_pos = ftell(gsub);
- putshort(gsub,0); /* offset to coverage table */
- putshort(gsub,cnt);
- for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt )
- putshort(gsub,(*maps[cnt])->ttf_glyph);
- }
- end = ftell(gsub);
- fseek(gsub,coverage_pos,SEEK_SET);
- putshort(gsub,end-coverage_pos+2);
- fseek(gsub,end,SEEK_SET);
- dumpcoveragetable(gsub,glyphs);
-
- free(glyphs);
- GlyphMapFree(maps);
-}
-
-static void dumpGSUBmultiplesubs(FILE *gsub,SplineFont *sf,struct lookup_subtable *sub) {
- int cnt, offset;
- int32 coverage_pos, end;
- int gc;
- SplineChar **glyphs, ***maps;
-
- glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
- maps = generateMapList(glyphs,sub);
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt);
-
- putshort(gsub,1); /* glyph list format */
- coverage_pos = ftell(gsub);
- putshort(gsub,0); /* offset to coverage table */
- putshort(gsub,cnt);
- offset = 6+2*cnt;
- for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt ) {
- putshort(gsub,offset);
- if (maps[cnt] == NULL) {
- fprintf( stderr, "maps[%d] is null; glyphs[%d] is \"%s\"; lookup name is \"%s\".\n" , cnt , cnt , (glyphs[cnt]->name ? glyphs[cnt]->name : ""), sub->subtable_name) ;
- }
- for ( gc=0; maps[cnt][gc]!=NULL; ++gc );
- offset += 2+2*gc;
- }
- for ( cnt = 0; glyphs[cnt]!=NULL; ++cnt ) {
- for ( gc=0; maps[cnt][gc]!=NULL; ++gc );
- putshort(gsub,gc);
- for ( gc=0; maps[cnt][gc]!=NULL; ++gc )
- putshort(gsub,maps[cnt][gc]->ttf_glyph);
- }
- end = ftell(gsub);
- fseek(gsub,coverage_pos,SEEK_SET);
- putshort(gsub,end-coverage_pos+2);
- fseek(gsub,end,SEEK_SET);
- dumpcoveragetable(gsub,glyphs);
-
- free(glyphs);
- GlyphMapFree(maps);
-}
-
-static int AllToBeOutput(LigList *lig) {
- struct splinecharlist *cmp;
-
- if ( lig->lig->u.lig.lig->ttf_glyph==-1 ||
- lig->first->ttf_glyph==-1 )
-return( 0 );
- for ( cmp=lig->components; cmp!=NULL; cmp=cmp->next )
- if ( cmp->sc->ttf_glyph==-1 )
-return( 0 );
-return( true );
-}
-
-static void dumpGSUBligdata(FILE *gsub,SplineFont *sf,
- struct lookup_subtable *sub, struct alltabs *at) {
- int32 coverage_pos, next_val_pos, here, lig_list_start;
- int cnt, i, pcnt, lcnt, max=100, j;
- uint16 *offsets=NULL, *ligoffsets=malloc(max*sizeof(uint16));
- SplineChar **glyphs;
- LigList *ll;
- struct splinecharlist *scl;
-
- glyphs = SFOrderedGlyphsWithPSTinSubtable(sf,sub);
- cnt=0;
- if ( glyphs!=NULL ) for ( ; glyphs[cnt]!=NULL; ++cnt );
-
- putshort(gsub,1); /* only one format for ligatures */
- coverage_pos = ftell(gsub);
- putshort(gsub,0); /* offset to coverage table */
- putshort(gsub,cnt);
- next_val_pos = ftell(gsub);
- if ( glyphs!=NULL )
- offsets = malloc(cnt*sizeof(int16));
- for ( i=0; i<cnt; ++i )
- putshort(gsub,0);
- for ( i=0; i<cnt; ++i ) {
- offsets[i] = ftell(gsub)-coverage_pos+2;
- for ( pcnt = 0, ll = glyphs[i]->ligofme; ll!=NULL; ll=ll->next )
- if ( ll->lig->subtable==sub && AllToBeOutput(ll))
- ++pcnt;
- putshort(gsub,pcnt);
- if ( pcnt>=max ) {
- max = pcnt+100;
- ligoffsets = realloc(ligoffsets,max*sizeof(int));
- }
- lig_list_start = ftell(gsub);
- for ( j=0; j<pcnt; ++j )
- putshort(gsub,0); /* Place holders */
- for ( pcnt=0, ll = glyphs[i]->ligofme; ll!=NULL; ll=ll->next ) {
- if ( ll->lig->subtable==sub && AllToBeOutput(ll)) {
- ligoffsets[pcnt] = ftell(gsub)-lig_list_start+2;
- putshort(gsub,ll->lig->u.lig.lig->ttf_glyph);
- for ( lcnt=0, scl=ll->components; scl!=NULL; scl=scl->next ) ++lcnt;
- putshort(gsub, lcnt+1);
- if ( lcnt+1>at->os2.maxContext )
- at->os2.maxContext = lcnt+1;
- for ( scl=ll->components; scl!=NULL; scl=scl->next )
- putshort(gsub, scl->sc->ttf_glyph );
- ++pcnt;
- }
- }
- fseek(gsub,lig_list_start,SEEK_SET);
- for ( j=0; j<pcnt; ++j )
- putshort(gsub,ligoffsets[j]);
- fseek(gsub,0,SEEK_END);
- }
- free(ligoffsets);
- if ( glyphs!=NULL ) {
- here = ftell(gsub);
- fseek(gsub,coverage_pos,SEEK_SET);
- putshort(gsub,here-coverage_pos+2);
- fseek(gsub,next_val_pos,SEEK_SET);
- for ( i=0; i<cnt; ++i )
- putshort(gsub,offsets[i]);
- fseek(gsub,here,SEEK_SET);
- dumpcoveragetable(gsub,glyphs);
- free(glyphs);
- free(offsets);
- }
-}
-
-static int ui16cmp(const void *_i1, const void *_i2) {
- if ( *(const uint16 *) _i1 > *(const uint16 *) _i2 )
-return( 1 );
- if ( *(const uint16 *) _i1 < *(const uint16 *) _i2 )
-return( -1 );
-
-return( 0 );
-}
-
-static uint16 *FigureInitialClasses(FPST *fpst) {
- uint16 *initial = malloc((fpst->nccnt+1)*sizeof(uint16));
- int i, cnt, j;
-
- initial[fpst->nccnt] = 0xffff;
- for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
- for ( j=0; j<cnt ; ++j )
- if ( initial[j] == fpst->rules[i].u.class.nclasses[0] )
- break;
- if ( j==cnt )
- initial[cnt++] = fpst->rules[i].u.class.nclasses[0];
- }
- qsort(initial,cnt,sizeof(uint16),ui16cmp);
- initial[cnt] = 0xffff;
-return( initial );
-}
-
-static SplineChar **OrderedInitialGlyphs(SplineFont *sf,FPST *fpst) {
- SplineChar **glyphs, *sc;
- int i, j, cnt, ch;
- char *pt, *names;
-
- glyphs = malloc((fpst->rule_cnt+1)*sizeof(SplineChar *));
- for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
- names = fpst->rules[i].u.glyph.names;
- pt = strchr(names,' ');
- if ( pt==NULL ) pt = names+strlen(names);
- ch = *pt; *pt = '\0';
- sc = SFGetChar(sf,-1,names);
- *pt = ch;
- for ( j=0; j<cnt; ++j )
- if ( glyphs[j]==sc )
- break;
- if ( j==cnt && sc!=NULL )
- glyphs[cnt++] = sc;
- }
- glyphs[cnt] = NULL;
- if ( cnt==0 )
-return( glyphs );
-
- for ( i=0; glyphs[i+1]!=NULL; ++i ) for ( j=i+1; glyphs[j]!=NULL; ++j ) {
- if ( glyphs[i]->ttf_glyph > glyphs[j]->ttf_glyph ) {
- sc = glyphs[i];
- glyphs[i] = glyphs[j];
- glyphs[j] = sc;
- }
- }
-return( glyphs );
-}
-
-static int NamesStartWith(SplineChar *sc,char *names ) {
- char *pt;
-
- pt = strchr(names,' ');
- if ( pt==NULL ) pt = names+strlen(names);
- if ( pt-names!=strlen(sc->name))
-return( false );
-
-return( strncmp(sc->name,names,pt-names)==0 );
-}
-
-static int CntRulesStartingWith(FPST *fpst,SplineChar *sc) {
- int i, cnt;
-
- for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
- if ( NamesStartWith(sc,fpst->rules[i].u.glyph.names))
- ++cnt;
- }
-return( cnt );
-}
-
-static int CntRulesStartingWithClass(FPST *fpst,uint16 cval) {
- int i, cnt;
-
- for ( i=cnt=0; i<fpst->rule_cnt; ++i ) {
- if ( fpst->rules[i].u.class.nclasses[0]==cval )
- ++cnt;
- }
-return( cnt );
-}
-
-static void dumpg___ContextChainGlyphs(FILE *lfile,SplineFont *sf,
- struct lookup_subtable *sub, struct alltabs *at) {
- FPST *fpst = sub->fpst;
- int iscontext = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
- uint32 base = ftell(lfile);
- int i,cnt, subcnt, j,k,l, maxcontext,curcontext;
- SplineChar **glyphs, **subglyphs;
- int lc;
-
- glyphs = OrderedInitialGlyphs(sf,fpst);
- for ( cnt=0; glyphs[cnt]!=NULL; ++cnt );
-
- putshort(lfile,1); /* Sub format 1 => glyph lists */
- putshort(lfile,(3+cnt)*sizeof(short)); /* offset to coverage */
- putshort(lfile,cnt);
- for ( i=0; i<cnt; ++i )
- putshort(lfile,0); /* Offset to rule */
- dumpcoveragetable(lfile,glyphs);
-
- maxcontext = 0;
-
- for ( i=0; i<cnt; ++i ) {
- uint32 pos = ftell(lfile);
- fseek(lfile,base+(3+i)*sizeof(short),SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- subcnt = CntRulesStartingWith(fpst,glyphs[i]);
- putshort(lfile,subcnt);
- for ( j=0; j<subcnt; ++j )
- putshort(lfile,0);
- for ( j=k=0; k<fpst->rule_cnt; ++k ) if ( NamesStartWith(glyphs[i],fpst->rules[k].u.glyph.names )) {
- uint32 subpos = ftell(lfile);
- fseek(lfile,pos+(1+j)*sizeof(short),SEEK_SET);
- putshort(lfile,subpos-pos);
- fseek(lfile,subpos,SEEK_SET);
-
- for ( l=lc=0; l<fpst->rules[k].lookup_cnt; ++l )
- if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 )
- ++lc;
- if ( iscontext ) {
- subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.names);
- for ( l=0; subglyphs[l]!=NULL; ++l );
- putshort(lfile,l);
- curcontext = l;
- putshort(lfile,lc);
- for ( l=1; subglyphs[l]!=NULL; ++l )
- putshort(lfile,subglyphs[l]->ttf_glyph);
- free(subglyphs);
- } else {
- subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.back);
- for ( l=0; subglyphs[l]!=NULL; ++l );
- putshort(lfile,l);
- curcontext = l;
- for ( l=0; subglyphs[l]!=NULL; ++l )
- putshort(lfile,subglyphs[l]->ttf_glyph);
- free(subglyphs);
- subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.names);
- for ( l=0; subglyphs[l]!=NULL; ++l );
- putshort(lfile,l);
- curcontext += l;
- for ( l=1; subglyphs[l]!=NULL; ++l )
- putshort(lfile,subglyphs[l]->ttf_glyph);
- free(subglyphs);
- subglyphs = SFGlyphsFromNames(sf,fpst->rules[k].u.glyph.fore);
- for ( l=0; subglyphs[l]!=NULL; ++l );
- putshort(lfile,l);
- curcontext += l;
- for ( l=0; subglyphs[l]!=NULL; ++l )
- putshort(lfile,subglyphs[l]->ttf_glyph);
- free(subglyphs);
- putshort(lfile,lc);
- }
- for ( l=0; l<fpst->rules[k].lookup_cnt; ++l )
- if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 ) {
- putshort(lfile,fpst->rules[k].lookups[l].seq);
- putshort(lfile,fpst->rules[k].lookups[l].lookup->lookup_index);
- }
- ++j;
- if ( curcontext>maxcontext ) maxcontext = curcontext;
- }
- }
- free(glyphs);
-
- if ( maxcontext>at->os2.maxContext )
- at->os2.maxContext = maxcontext;
-}
-
-static void dumpg___ContextChainClass(FILE *lfile,SplineFont *sf,
- struct lookup_subtable *sub, struct alltabs *at) {
- FPST *fpst = sub->fpst;
- int iscontext = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
- uint32 base = ftell(lfile), rulebase, pos, subpos, npos;
- uint16 *initialclasses, *iclass, *bclass, *lclass;
- SplineChar **iglyphs, **bglyphs, **lglyphs, **glyphs;
- int i,ii,cnt, subcnt, j,k,l , maxcontext,curcontext;
- int lc;
-
- putshort(lfile,2); /* Sub format 2 => class */
- putshort(lfile,0); /* offset to coverage table */
- if ( iscontext )
- putshort(lfile,0); /* offset to input classdef */
- else {
- putshort(lfile,0); /* offset to backtrack classdef */
- putshort(lfile,0); /* offset to input classdef */
- putshort(lfile,0); /* offset to lookahead classdef */
- }
- initialclasses = FigureInitialClasses(fpst);
- putshort(lfile,fpst->nccnt);
- rulebase = ftell(lfile);
- for ( cnt=0; cnt<fpst->nccnt; ++cnt )
- putshort(lfile,0);
-
- iclass = ClassesFromNames(sf,fpst->nclass,fpst->nccnt,at->maxp.numGlyphs,&iglyphs,false);
- lglyphs = bglyphs = NULL; bclass = lclass = NULL;
- if ( !iscontext ) {
- bclass = ClassesFromNames(sf,fpst->bclass,fpst->bccnt,at->maxp.numGlyphs,&bglyphs,false);
- lclass = ClassesFromNames(sf,fpst->fclass,fpst->fccnt,at->maxp.numGlyphs,&lglyphs,false);
- }
- pos = ftell(lfile);
- fseek(lfile,base+sizeof(uint16),SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- glyphs = GlyphsFromInitialClasses(iglyphs,at->maxp.numGlyphs,iclass,initialclasses);
- dumpcoveragetable(lfile,glyphs);
- free(glyphs);
- free(iglyphs); free(bglyphs); free(lglyphs);
-
- if ( iscontext ) {
- pos = ftell(lfile);
- fseek(lfile,base+2*sizeof(uint16),SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- DumpClass(lfile,iclass,at->maxp.numGlyphs);
- free(iclass);
- } else {
- pos = ftell(lfile);
- fseek(lfile,base+2*sizeof(uint16),SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- DumpClass(lfile,bclass,at->maxp.numGlyphs);
- if ( ClassesMatch(fpst->bccnt,fpst->bclass,fpst->nccnt,fpst->nclass)) {
- npos = pos;
- fseek(lfile,base+3*sizeof(uint16),SEEK_SET);
- putshort(lfile,npos-base);
- fseek(lfile,0,SEEK_END);
- } else {
- npos = ftell(lfile);
- fseek(lfile,base+3*sizeof(uint16),SEEK_SET);
- putshort(lfile,npos-base);
- fseek(lfile,npos,SEEK_SET);
- DumpClass(lfile,iclass,at->maxp.numGlyphs);
- }
- if ( ClassesMatch(fpst->fccnt,fpst->fclass,fpst->bccnt,fpst->bclass)) {
- fseek(lfile,base+4*sizeof(uint16),SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,0,SEEK_END);
- } else if ( ClassesMatch(fpst->fccnt,fpst->fclass,fpst->nccnt,fpst->nclass)) {
- fseek(lfile,base+4*sizeof(uint16),SEEK_SET);
- putshort(lfile,npos-base);
- fseek(lfile,0,SEEK_END);
- } else {
- pos = ftell(lfile);
- fseek(lfile,base+4*sizeof(uint16),SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- DumpClass(lfile,lclass,at->maxp.numGlyphs);
- }
- free(iclass); free(bclass); free(lclass);
- }
-
- ii=0;
- for ( i=0; i<fpst->nccnt; ++i ) {
- if ( initialclasses[ii]!=i ) {
- /* This class isn't an initial one, so leave it's rule pointer NULL */
- } else {
- ++ii;
- pos = ftell(lfile);
- fseek(lfile,rulebase+i*sizeof(short),SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- subcnt = CntRulesStartingWithClass(fpst,i);
- putshort(lfile,subcnt);
- for ( j=0; j<subcnt; ++j )
- putshort(lfile,0);
- for ( j=k=0; k<fpst->rule_cnt; ++k ) if ( i==fpst->rules[k].u.class.nclasses[0] ) {
- subpos = ftell(lfile);
- fseek(lfile,pos+(1+j)*sizeof(short),SEEK_SET);
- putshort(lfile,subpos-pos);
- fseek(lfile,subpos,SEEK_SET);
-
- for ( l=lc=0; l<fpst->rules[k].lookup_cnt; ++l )
- if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 )
- ++lc;
- if ( iscontext ) {
- putshort(lfile,fpst->rules[k].u.class.ncnt);
- putshort(lfile,lc);
- for ( l=1; l<fpst->rules[k].u.class.ncnt; ++l )
- putshort(lfile,fpst->rules[k].u.class.nclasses[l]);
- } else {
- putshort(lfile,fpst->rules[k].u.class.bcnt);
- for ( l=0; l<fpst->rules[k].u.class.bcnt; ++l )
- putshort(lfile,fpst->rules[k].u.class.bclasses[l]);
- putshort(lfile,fpst->rules[k].u.class.ncnt);
- for ( l=1; l<fpst->rules[k].u.class.ncnt; ++l )
- putshort(lfile,fpst->rules[k].u.class.nclasses[l]);
- putshort(lfile,fpst->rules[k].u.class.fcnt);
- for ( l=0; l<fpst->rules[k].u.class.fcnt; ++l )
- putshort(lfile,fpst->rules[k].u.class.fclasses[l]);
- putshort(lfile,lc);
- }
- for ( l=0; l<fpst->rules[k].lookup_cnt; ++l )
- if ( fpst->rules[k].lookups[l].lookup->lookup_index!=-1 ) {
- putshort(lfile,fpst->rules[k].lookups[l].seq);
- putshort(lfile,fpst->rules[k].lookups[l].lookup->lookup_index);
- }
- ++j;
- }
- }
- }
- free(initialclasses);
-
- maxcontext = 0;
- for ( i=0; i<fpst->rule_cnt; ++i ) {
- curcontext = fpst->rules[i].u.class.ncnt+fpst->rules[i].u.class.bcnt+fpst->rules[i].u.class.fcnt;
- if ( curcontext>maxcontext ) maxcontext = curcontext;
- }
- if ( maxcontext>at->os2.maxContext )
- at->os2.maxContext = maxcontext;
-}
-
-static void dumpg___ContextChainCoverage(FILE *lfile,SplineFont *sf,
- struct lookup_subtable *sub, struct alltabs *at) {
- FPST *fpst = sub->fpst;
- int iscontext = fpst->type==pst_contextpos || fpst->type==pst_contextsub;
- uint32 base = ftell(lfile), ibase, lbase, bbase;
- int i, l;
- SplineChar **glyphs;
- int curcontext;
- int lc;
-
- if ( fpst->rule_cnt!=1 )
- IError("Bad rule cnt in coverage context lookup");
- if ( fpst->format==pst_reversecoverage && fpst->rules[0].u.rcoverage.always1!=1 )
- IError("Bad input count in reverse coverage lookup" );
-
- putshort(lfile,3); /* Sub format 3 => coverage */
- for ( l=lc=0; l<fpst->rules[0].lookup_cnt; ++l )
- if ( fpst->rules[0].lookups[l].lookup->lookup_index!=-1 )
- ++lc;
- if ( iscontext ) {
- putshort(lfile,fpst->rules[0].u.coverage.ncnt);
- putshort(lfile,lc);
- for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i )
- putshort(lfile,0);
- for ( i=0; i<fpst->rules[0].lookup_cnt; ++i )
- if ( fpst->rules[0].lookups[i].lookup->lookup_index!=-1 ) {
- putshort(lfile,fpst->rules[0].lookups[i].seq);
- putshort(lfile,fpst->rules[0].lookups[i].lookup->lookup_index);
- }
- for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i ) {
- uint32 pos = ftell(lfile);
- fseek(lfile,base+6+2*i,SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.ncovers[i]);
- dumpcoveragetable(lfile,glyphs);
- free(glyphs);
- }
- } else {
- if ( fpst->format==pst_reversecoverage ) {
- ibase = ftell(lfile);
- putshort(lfile,0);
- }
- putshort(lfile,fpst->rules[0].u.coverage.bcnt);
- bbase = ftell(lfile);
- for ( i=0; i<fpst->rules[0].u.coverage.bcnt; ++i )
- putshort(lfile,0);
- if ( fpst->format==pst_coverage ) {
- putshort(lfile,fpst->rules[0].u.coverage.ncnt);
- ibase = ftell(lfile);
- for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i )
- putshort(lfile,0);
- }
- putshort(lfile,fpst->rules[0].u.coverage.fcnt);
- lbase = ftell(lfile);
- for ( i=0; i<fpst->rules[0].u.coverage.fcnt; ++i )
- putshort(lfile,0);
- if ( fpst->format==pst_coverage ) {
- putshort(lfile,lc);
- for ( i=0; i<fpst->rules[0].lookup_cnt; ++i )
- if ( fpst->rules[0].lookups[i].lookup->lookup_index!=-1 ) {
- putshort(lfile,fpst->rules[0].lookups[i].seq);
- putshort(lfile,fpst->rules[0].lookups[i].lookup->lookup_index);
- }
- } else { /* reverse coverage */
- glyphs = SFGlyphsFromNames(sf,fpst->rules[0].u.rcoverage.replacements);
- for ( i=0; glyphs[i]!=0; ++i );
- putshort(lfile,i);
- for ( i=0; glyphs[i]!=0; ++i )
- putshort(lfile,glyphs[i]->ttf_glyph);
- }
- for ( i=0; i<fpst->rules[0].u.coverage.ncnt; ++i ) {
- uint32 pos = ftell(lfile);
- fseek(lfile,ibase+2*i,SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.ncovers[i]);
- dumpcoveragetable(lfile,glyphs);
- free(glyphs);
- }
- for ( i=0; i<fpst->rules[0].u.coverage.bcnt; ++i ) {
- uint32 pos = ftell(lfile);
- fseek(lfile,bbase+2*i,SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.bcovers[i]);
- dumpcoveragetable(lfile,glyphs);
- free(glyphs);
- }
- for ( i=0; i<fpst->rules[0].u.coverage.fcnt; ++i ) {
- uint32 pos = ftell(lfile);
- fseek(lfile,lbase+2*i,SEEK_SET);
- putshort(lfile,pos-base);
- fseek(lfile,pos,SEEK_SET);
- glyphs = OrderedGlyphsFromNames(sf,fpst->rules[0].u.coverage.fcovers[i]);
- dumpcoveragetable(lfile,glyphs);
- free(glyphs);
- }
- }
-
- curcontext = fpst->rules[0].u.coverage.ncnt+fpst->rules[0].u.coverage.bcnt+fpst->rules[0].u.coverage.fcnt;
- if ( curcontext>at->os2.maxContext )
- at->os2.maxContext = curcontext;
-}
-
-static void dumpg___ContextChain(FILE *lfile,SplineFont *sf,
- struct lookup_subtable *sub, struct alltabs *at) {
- FPST *fpst = sub->fpst;
-
- switch ( fpst->format ) {
- case pst_glyphs:
- dumpg___ContextChainGlyphs(lfile,sf,sub,at);
- break;
- case pst_class:
- dumpg___ContextChainClass(lfile,sf,sub,at);
- break;
- case pst_coverage:
- case pst_reversecoverage:
- dumpg___ContextChainCoverage(lfile,sf,sub,at);
- break;
- }
-
- fseek(lfile,0,SEEK_END);
-
-}
-
-static void AnchorsAway(FILE *lfile,SplineFont *sf,
- struct lookup_subtable *sub, struct glyphinfo *gi ) {
- SplineChar **base, **lig, **mkmk;
- AnchorClass *ac, *acfirst;
- SplineChar ***marks;
- int *subcnts;
- int cmax, classcnt;
- int i;
-
- marks = malloc((cmax=20)*sizeof(SplineChar **));
- subcnts = malloc(cmax*sizeof(int));
-
- classcnt = 0;
- acfirst = NULL;
- for ( ac=sf->anchor; ac!=NULL; ac = ac->next ) {
- ac->matches = false;
- if ( ac->subtable==sub && !ac->processed ) {
- if ( acfirst == NULL )
- acfirst = ac;
- if ( ac->type==act_curs )
- continue;
- else if ( ac->has_mark && ac->has_base ) {
- ac->matches = ac->processed = true;
- ++classcnt;
- }
- }
- }
- if ( classcnt>cmax ) {
- marks = realloc(marks,(cmax=classcnt+10)*sizeof(SplineChar **));
- subcnts = realloc(subcnts,cmax*sizeof(int));
- }
- AnchorClassDecompose(sf,acfirst,classcnt,subcnts,marks,&base,&lig,&mkmk,gi);
- switch ( sub->lookup->lookup_type ) {
- case gpos_mark2base:
- if ( marks[0]!=NULL && base!=NULL )
- dumpgposAnchorData(lfile,acfirst,at_basechar,marks,base,classcnt,gi);
- break;
- case gpos_mark2ligature:
- if ( marks[0]!=NULL && lig!=NULL )
- dumpgposAnchorData(lfile,acfirst,at_baselig,marks,lig,classcnt,gi);
- break;
- case gpos_mark2mark:
- if ( marks[0]!=NULL && mkmk!=NULL )
- dumpgposAnchorData(lfile,acfirst,at_basemark,marks,mkmk,classcnt,gi);
- break;
- default:;
- }
- for ( i=0; i<classcnt; ++i )
- free(marks[i]);
- free(base);
- free(lig);
- free(mkmk);
- free(marks);
- free(subcnts);
-}
-
-static int lookup_size_cmp(const void *_l1, const void *_l2) {
- const OTLookup *l1 = *(OTLookup **) _l1, *l2 = *(OTLookup **) _l2;
-return( l1->lookup_length-l2->lookup_length );
-}
-
-static int FPSTRefersToOTL(FPST *fpst,OTLookup *otl) {
- int i, j;
-
- if ( fpst==NULL || fpst->type == pst_reversesub )
-return( false );
- for ( i=0; i<fpst->rule_cnt; ++i ) {
- for ( j=0; j< fpst->rules[i].lookup_cnt; ++j )
- if ( fpst->rules[i].lookups[j].lookup == otl )
-return( true );
- }
-return( false );
-}
-
-static int OnlyMac(OTLookup *otl, OTLookup *all) {
- FeatureScriptLangList *features = otl->features;
- int anymac = 0;
- struct lookup_subtable *sub;
-
- switch ( otl->lookup_type ) {
- /* These two lookup types are mac only */
- case kern_statemachine: case morx_indic: case morx_context: case morx_insert:
- return( true );
- /* These lookup types are OpenType only */
- case gsub_multiple: case gsub_alternate: case gsub_context:
- case gsub_contextchain: case gsub_reversecchain:
- case gpos_single: case gpos_cursive: case gpos_mark2base:
- case gpos_mark2ligature: case gpos_mark2mark:
- case gpos_context: case gpos_contextchain:
- return( false );
- /* These two can be expressed in both, and might be either */
- case gpos_pair: case gsub_single: case gsub_ligature:
- for ( features = otl->features; features!=NULL; features = features->next ) {
- if ( !features->ismac )
- return( false );
- else
- anymac = true;
- }
- /* Either it has no features at all (nested), or all its features */
- /* are mac feature settings. Even if all are mac feature settings it */
- /* might still be used as under control of a contextual feature */
- /* so in both cases check for nested */
- while ( all!=NULL ) {
- if ( all!=otl && !all->unused &&
- (all->lookup_type==gpos_context ||
- all->lookup_type==gpos_contextchain ||
- all->lookup_type==gsub_context ||
- all->lookup_type==gsub_contextchain /*||
- all->lookup_type==gsub_reversecchain*/ )) {
- for ( sub=all->subtables; sub!=NULL; sub=sub->next ) if ( !sub->unused && sub->fpst!=NULL ) {
- if ( FPSTRefersToOTL(sub->fpst,otl) )
- return( false );
- }
- }
- all = all->next;
- }
- if ( anymac )
- return( true );
- /* As far as I can tell, this lookup isn't used at all */
- /* Let's output it anyway, just in case we ever support some other */
- /* table that uses GPOS/GSUB lookups (I think JUST) */
- return( false );
- default:;
- }
- /* Should never get here, but gcc probably thinks we might */
-return( true );
-}
-
-static void otf_dumpALookup(FILE *lfile, OTLookup *otl, SplineFont *sf,
- struct alltabs *at) {
- struct lookup_subtable *sub;
- int lookup_sub_table_contains_no_data_count = 0;
- int lookup_sub_table_is_too_big_count = 0;
-
- otl->lookup_offset = ftell(lfile);
- for ( sub = otl->subtables; sub!=NULL; sub=sub->next ) {
- sub->extra_subtables = NULL;
- if ( sub->unused )
- sub->subtable_offset = -1;
- else {
- sub->subtable_offset = ftell(lfile);
- switch ( otl->lookup_type ) {
- /* GPOS lookup types */
- case gpos_single:
- dumpGPOSsimplepos(lfile,sf,sub);
- break;
-
- case gpos_pair:
- if ( at->os2.maxContext<2 )
- at->os2.maxContext = 2;
- if ( sub->kc!=NULL )
- dumpgposkernclass(lfile,sf,sub,at);
- else
- dumpGPOSpairpos(lfile,sf,sub);
- break;
-
- case gpos_cursive:
- dumpgposCursiveAttach(lfile,sf,sub,&at->gi);
- break;
-
- case gpos_mark2base:
- case gpos_mark2ligature:
- case gpos_mark2mark:
- AnchorsAway(lfile,sf,sub,&at->gi);
- break;
-
- case gpos_contextchain:
- case gpos_context:
- dumpg___ContextChain(lfile,sf,sub,at);
- break;
-
- /* GSUB lookup types */
- case gsub_single:
- dumpGSUBsimplesubs(lfile,sf,sub);
- break;
-
- case gsub_multiple:
- case gsub_alternate:
- dumpGSUBmultiplesubs(lfile,sf,sub);
- break;
-
- case gsub_ligature:
- dumpGSUBligdata(lfile,sf,sub,at);
- break;
-
- case gsub_contextchain:
- case gsub_context:
- case gsub_reversecchain:
- dumpg___ContextChain(lfile,sf,sub,at);
- break;
- default:;
- }
- if ( ftell(lfile)-sub->subtable_offset==0 ) {
- if ( lookup_sub_table_contains_no_data_count < 32 ) {
- IError( "Lookup sub table, %s in %s, contains no data.\n",
- sub->subtable_name, sub->lookup->lookup_name );
- lookup_sub_table_contains_no_data_count ++;
- }
- sub->unused = true;
- sub->subtable_offset = -1;
- } else if ( sub->extra_subtables==NULL &&
- ftell(lfile)-sub->subtable_offset>65535 )
- if ( lookup_sub_table_is_too_big_count < 32 ) {
- IError( "Lookup sub table, %s in %s, is too big. Will not be useable.\n",
- sub->subtable_name, sub->lookup->lookup_name );
- lookup_sub_table_is_too_big_count ++;
- }
- }
- }
- otl->lookup_length = ftell(lfile)-otl->lookup_offset;
-}
-
-static FILE *G___figureLookups(SplineFont *sf,int is_gpos,
- struct alltabs *at) {
- OTLookup *otl;
- struct lookup_subtable *sub;
- int index, i,j;
- FILE *final;
- FILE *lfile = tmpfile2();
- OTLookup **sizeordered;
- OTLookup *all = is_gpos ? sf->gpos_lookups : sf->gsub_lookups;
- char *buffer;
- int len;
-
- index = 0;
- for ( otl=all; otl!=NULL; otl=otl->next ) {
- if ( otl->unused || OnlyMac(otl,all) || otl->only_jstf || otl->temporary_kern )
- otl->lookup_index = -1;
- else
- otl->lookup_index = index++;
- }
- for ( otl=all; otl!=NULL; otl=otl->next ) {
- if ( otl->lookup_index!=-1 ) {
- otf_dumpALookup(lfile, otl, sf, at );
- }
- }
- if ( is_gpos )
- AnchorGuessContext(sf,at);
-
- /* We don't need to reorder short files */
- if ( ftell(lfile)<65536 )
-return( lfile );
-
- /* Order the lookups so that the smallest ones come first */
- /* thus we are less likely to need extension tables */
- /* I think it's better to order the entire lookup rather than ordering the*/
- /* subtables -- since the extension subtable would be required for all */
- /* subtables in the lookup, so might as well keep them all together */
- sizeordered = malloc(index*sizeof(OTLookup *));
- for ( otl=is_gpos ? sf->gpos_lookups : sf->gsub_lookups; otl!=NULL; otl=otl->next )
- if ( otl->lookup_index!=-1 )
- sizeordered[ otl->lookup_index ] = otl;
- qsort(sizeordered,index,sizeof(OTLookup *),lookup_size_cmp);
-
- final = tmpfile2();
- buffer = malloc(32768);
- for ( i=0; i<index; ++i ) {
- uint32 diff;
- otl = sizeordered[i];
- fseek(lfile,otl->lookup_offset,SEEK_SET);
- diff = ftell(final) - otl->lookup_offset;
- otl->lookup_offset = ftell(final);
- len = otl->lookup_length;
- while ( len>=32768 ) {
- int done = fread(buffer,1,32768,lfile);
- if ( done==0 ) /* fread returns 0 on error, not EOF */
- break;
- fwrite(buffer,1,done,final);
- len -= done;
- }
- if ( len>0 && len<=32768 ) {
- int done = fread(buffer,1,len,lfile);
- if ( done==0 )
- break;
- fwrite(buffer,1,done,final);
- }
- for ( sub = otl->subtables; sub!=NULL; sub=sub->next ) {
- if ( !sub->unused ) {
- sub->subtable_offset += diff;
- if ( sub->extra_subtables!=NULL ) {
- for ( j=0; sub->extra_subtables[j]!=-1; ++j )
- sub->extra_subtables[j] += diff;
- }
- }
- }
- }
- free(buffer);
- free(sizeordered);
- fclose(lfile);
-return( final );
-}
-
-struct feat_lookups {
- uint32 tag;
- int lcnt;
- OTLookup **lookups;
- int feature_id; /* Initially consecutive, but may be rearranged by sorting */
- uint32 name_param_ptr;
-};
-
-struct langsys {
- uint32 lang;
- int fc;
- int *feature_id;
- int same_as;
- int32 offset;
-};
-
-struct scriptset {
- uint32 script;
- int lc;
- struct langsys *langsys;
-};
-
-struct ginfo {
- int fmax, fcnt;
- struct feat_lookups *feat_lookups;
- int sc;
- struct scriptset *scripts;
-};
-
-static int FindOrMakeNewFeatureLookup(struct ginfo *ginfo,OTLookup **lookups,
- uint32 tag) {
- int i, j;
-
- for ( i=0; i<ginfo->fcnt; ++i ) {
- if ( ginfo->feat_lookups[i].tag!= tag )
- continue;
- if ( lookups==NULL && ginfo->feat_lookups[i].lookups==NULL ) /* 'size' feature */
-return( i );
- if ( lookups==NULL || ginfo->feat_lookups[i].lookups==NULL )
- continue;
- for ( j=0; lookups[j]!=NULL && ginfo->feat_lookups[i].lookups[j]!=NULL; ++j )
- if ( ginfo->feat_lookups[i].lookups[j]!=lookups[j] )
- break;
- if ( ginfo->feat_lookups[i].lookups[j]==lookups[j] ) {
- free(lookups);
-return( i );
- }
- }
- if ( ginfo->fcnt>=ginfo->fmax )
- ginfo->feat_lookups = realloc(ginfo->feat_lookups,(ginfo->fmax+=20)*sizeof(struct feat_lookups));
- ginfo->feat_lookups[i].feature_id = i;
- ginfo->feat_lookups[i].tag = tag;
- ginfo->feat_lookups[i].lookups = lookups;
- j=0;
- if ( lookups!=NULL ) for ( ; lookups[j]!=NULL; ++j );
- ginfo->feat_lookups[i].lcnt = j;
- ++ginfo->fcnt;
-return( i );
-}
-
-static int feat_alphabetize(const void *_fl1, const void *_fl2) {
- const struct feat_lookups *fl1 = _fl1, *fl2 = _fl2;
-
- if ( fl1->tag<fl2->tag )
-return( -1 );
- if ( fl1->tag>fl2->tag )
-return( 1 );
-
-return( 0 );
-}
-
-static int numeric_order(const void *_i1, const void *_i2) {
- int i1 = *(const int *) _i1, i2 = *(const int *) _i2;
-
- if ( i1<i2 )
-return( -1 );
- if ( i1>i2 )
-return( 1 );
-
-return( 0 );
-}
-
-static int LangSysMatch(struct scriptset *s,int ils1, int ils2 ) {
- struct langsys *ls1 = &s->langsys[ils1], *ls2 = &s->langsys[ils2];
- int i;
-
- if ( ls1->fc!=ls2->fc )
-return( false );
- for ( i=0; i<ls1->fc; ++i )
- if ( ls1->feature_id[i]!=ls2->feature_id[i] )
-return( false );
-
-return( true );
-}
-
-static void FindFeatures(SplineFont *sf,int is_gpos,struct ginfo *ginfo) {
- uint32 *scripts, *langs, *features;
- OTLookup **lookups;
- int sc, lc, fc, j;
-
- memset(ginfo,0,sizeof(struct ginfo));
-
- scripts = SFScriptsInLookups(sf,is_gpos);
- if ( scripts==NULL ) /* All lookups unused */
-return;
- for ( sc=0; scripts[sc]!=0; ++sc );
- ginfo->scripts = malloc(sc*sizeof(struct scriptset));
- ginfo->sc = sc;
- for ( sc=0; scripts[sc]!=0; ++sc ) {
- langs = SFLangsInScript(sf,is_gpos,scripts[sc]);
- for ( lc=0; langs[lc]!=0; ++lc );
- ginfo->scripts[sc].script = scripts[sc];
- ginfo->scripts[sc].lc = lc;
- ginfo->scripts[sc].langsys = malloc(lc*sizeof(struct langsys));
- for ( lc=0; langs[lc]!=0; ++lc ) {
- features = SFFeaturesInScriptLang(sf,is_gpos,scripts[sc],langs[lc]);
- for ( fc=0; features[fc]!=0; ++fc );
- ginfo->scripts[sc].langsys[lc].lang = langs[lc];
- ginfo->scripts[sc].langsys[lc].fc = fc;
- ginfo->scripts[sc].langsys[lc].feature_id = malloc(fc*sizeof(int));
- ginfo->scripts[sc].langsys[lc].same_as = -1;
- for ( fc=0; features[fc]!=0; ++fc ) {
- lookups = SFLookupsInScriptLangFeature(sf,is_gpos,scripts[sc],langs[lc],features[fc]);
- ginfo->scripts[sc].langsys[lc].feature_id[fc] =
- FindOrMakeNewFeatureLookup(ginfo,lookups,features[fc]);
- /* lookups is freed or used by FindOrMakeNewFeatureLookup */
- }
- free(features);
- }
- free(langs);
- }
- free(scripts);
-
- qsort(ginfo->feat_lookups,ginfo->fcnt,sizeof(struct feat_lookups),feat_alphabetize);
-
- /* Now we've disordered the features. Find each feature_id and turn it back*/
- /* into a feature number */
- for ( sc=0; sc<ginfo->sc; ++sc ) {
- for ( lc=0; lc<ginfo->scripts[sc].lc; ++lc ) {
- int fcmax = ginfo->scripts[sc].langsys[lc].fc;
- int *feature_id = ginfo->scripts[sc].langsys[lc].feature_id;
- for ( fc=0; fc<fcmax; ++fc ) {
- int id = feature_id[fc];
- for ( j=0; j<ginfo->fcnt; ++j )
- if ( id==ginfo->feat_lookups[j].feature_id )
- break;
- feature_id[fc] = j;
- }
- qsort(feature_id,fcmax,sizeof(int),numeric_order);
- }
- /* See if there are langsys tables which use exactly the same features*/
- /* They can use the same entry in the file. This optimization seems */
- /* to be required for Japanese vertical writing to work in Uniscribe.*/
- for ( lc=0; lc<ginfo->scripts[sc].lc; ++lc ) {
- for ( j=0; j<lc; ++j )
- if ( LangSysMatch(&ginfo->scripts[sc],j,lc) ) {
- ginfo->scripts[sc].langsys[lc].same_as = j;
- break;
- }
- }
- }
-}
-
-
-static void dump_script_table(FILE *g___,struct scriptset *ss,struct ginfo *ginfo) {
- int i, lcnt, dflt_lang = -1;
- uint32 base;
- int j, req_index;
- uint32 offset;
-
- /* Count the languages, and find default */
- for ( lcnt=0; lcnt<ss->lc; ++lcnt )
- if ( ss->langsys[lcnt].lang==DEFAULT_LANG )
- dflt_lang = lcnt;
- if ( dflt_lang != -1 )
- --lcnt;
-
- base = ftell(g___);
- putshort(g___, 0 ); /* fill in later, Default Lang Sys */
- putshort(g___,lcnt);
- for ( i=0; i<ss->lc; ++i ) if ( i!=dflt_lang ) {
- putlong(g___,ss->langsys[i].lang); /* Language tag */
- putshort(g___,0); /* Fill in later, offset to langsys */
- }
-
- for ( lcnt=0; lcnt<ss->lc; ++lcnt ) {
- if ( ss->langsys[lcnt].same_as!=-1 )
- offset = ss->langsys[ ss->langsys[lcnt].same_as ].offset;
- else {
- offset = ftell(g___);
- ss->langsys[lcnt].offset = offset;
- }
- fseek(g___,lcnt==dflt_lang ? base :
- lcnt<dflt_lang || dflt_lang==-1 ? base + 4 + lcnt*6 +4 :
- base + 4 + (lcnt-1)*6 +4 ,
- SEEK_SET );
- putshort(g___,offset-base);
- fseek(g___,0,SEEK_END);
- if ( ss->langsys[lcnt].same_as==-1 ) {
- req_index = -1;
- for ( j=0; j<ss->langsys[lcnt].fc; ++j ) {
- if ( ginfo->feat_lookups[ ss->langsys[lcnt].feature_id[j] ].tag == REQUIRED_FEATURE ) {
- req_index = ss->langsys[lcnt].feature_id[j];
- break;
- }
- }
- putshort(g___,0); /* LookupOrder, always NULL */
- putshort(g___,req_index); /* index of required feature, if any */
- putshort(g___,ss->langsys[lcnt].fc - (req_index!=-1));
- /* count of non-required features */
- for ( j=0; j<ss->langsys[lcnt].fc; ++j ) if (ss->langsys[lcnt].feature_id[j]!=req_index )
- putshort(g___,ss->langsys[lcnt].feature_id[j]);
- }
- }
-}
-
-static FILE *g___FigureExtensionSubTables(OTLookup *all,int startoffset,int is_gpos) {
- OTLookup *otf;
- struct lookup_subtable *sub;
- int len, len2, gotmore;
- FILE *efile;
- int i, offset, cnt;
- int any= false;
-
- if ( all==NULL )
-return( NULL );
- gotmore = true; cnt=len=0;
- while ( gotmore ) {
- gotmore = false;
- offset = startoffset + 8*cnt;
- for ( otf=all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
- if ( otf->needs_extension )
- continue;
- for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
- if ( sub->subtable_offset==-1 )
- continue;
- if ( sub->extra_subtables!=NULL ) {
- for ( i=0; sub->extra_subtables[i]!=-1; ++i ) {
- if ( sub->extra_subtables[i]+offset>65535 )
- break;
- }
- if ( sub->extra_subtables[i]!=-1 )
- break;
- } else if ( sub->subtable_offset+offset>65535 )
- break;
- }
- if ( sub!=NULL ) {
- if ( !any ) {
- ff_post_notice(_("Lookup potentially too big"),
- _("Lookup %s has an\noffset bigger than 65535 bytes. This means\nFontForge must use an extension lookup to output it.\nNot all applications support extension lookups."),
- otf->lookup_name );
- any = true;
- }
- otf->needs_extension = true;
- gotmore = true;
- len += 8*otf->subcnt;
- ++cnt;
- }
- offset -= 6+2*otf->subcnt;
- }
- }
-
- if ( cnt==0 ) /* No offset overflows */
-return( NULL );
-
- /* Now we've worked out which lookups need extension tables and marked them*/
- /* Generate the extension tables, and update the offsets to reflect the size */
- /* of the extensions */
- efile = tmpfile2();
-
- len2 = 0;
- for ( otf=all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
- for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
- if ( sub->subtable_offset==-1 )
- continue;
- if ( sub->extra_subtables!=NULL ) {
- for ( i=0; sub->extra_subtables[i]!=-1; ++i ) {
- sub->extra_subtables[i] += len;
- if ( otf->needs_extension ) {
- int off = ftell(efile);
- putshort(efile,1); /* exten subtable format (there's only one) */
- putshort(efile,otf->lookup_type&0xff);
- putlong(efile,sub->extra_subtables[i]-len2);
- sub->extra_subtables[i] = off;
- len2+=8;
- }
- }
- } else {
- sub->subtable_offset += len;
- if ( otf->needs_extension ) {
- int off = ftell(efile);
- putshort(efile,1); /* exten subtable format (there's only one) */
- putshort(efile,otf->lookup_type&0xff);
- putlong(efile,sub->subtable_offset-len2);
- sub->subtable_offset = off;
- len2+=8;
- }
- }
- }
- }
-
-return( efile );
-}
-
-struct otffeatname *findotffeatname(uint32 tag,SplineFont *sf) {
- struct otffeatname *fn;
-
- for ( fn=sf->feat_names; fn!=NULL && fn->tag!=tag; fn=fn->next );
-return( fn );
-}
-
-static FILE *dumpg___info(struct alltabs *at, SplineFont *sf,int is_gpos) {
- /* Dump out either a gpos or a gsub table. gpos handles kerns, gsub ligs */
- /* we assume that SFFindUnusedLookups has been called */
- FILE *lfile, *g___, *efile;
- uint32 lookup_list_table_start, feature_list_table_start, here, scripts_start_offset;
- struct ginfo ginfo;
- int32 size_params_loc, size_params_ptr;
- int i,j, cnt, scnt, offset;
- OTLookup *otf, *all;
- struct lookup_subtable *sub;
- char *buf;
- struct otffeatname *fn;
-
- for ( fn=sf->feat_names; fn!=NULL; fn=fn->next )
- fn->nid = 0;
-
- FindFeatures(sf,is_gpos,&ginfo);
- if ( ginfo.sc==0 )
-return( NULL );
- lfile = G___figureLookups(sf,is_gpos,at);
-
- if ( ginfo.sc==0 && ftell(lfile)==0 ) {
- /* ftell(lfile)==0 => There are no lookups for this table */
- /* ginfo.sc==0 => There are no scripts. */
- /* If both are true then we don't need to output the table */
- /* It is perfectly possible to have lookups without scripts */
- /* (if some other table refered to them -- we don't currently */
- /* support this, but we might some day). */
- /* It is also possible to have scripts without lookups (to get */
- /* around a bug in Uniscribe which only processes some scripts */
- /* if both GPOS and GSUB entries are present. So we share scripts */
- /* between the two tables */
- fclose(lfile);
- /* if ginfo.sc==0 then there will be nothing to free in the ginfo struct*/
-return( NULL );
- }
-
- g___ = tmpfile2();
-
- putlong(g___,0x10000); /* version number */
- putshort(g___,10); /* offset to script table */
- putshort(g___,0); /* offset to features. Come back for this */
- putshort(g___,0); /* offset to lookups. Come back for this */
-/* Now the scripts */
- scripts_start_offset = ftell(g___);
- putshort(g___,ginfo.sc);
- for ( i=0; i<ginfo.sc; ++i ) {
- putlong(g___,ginfo.scripts[i].script);
- putshort(g___,0); /* fix up later */
- }
-
- /* Ok, that was the script_list_table which gives each script an offset */
- /* Now for each script we provide a Script table which contains an */
- /* offset to a bunch of features for the default language, and a */
- /* a more complex situation for non-default languages. */
- offset=2+4; /* To the script pointer at the start of table */
- for ( i=0; i<ginfo.sc; ++i ) {
- here = ftell(g___);
- fseek(g___,scripts_start_offset+offset,SEEK_SET);
- putshort(g___,here-scripts_start_offset);
- offset+=6;
- fseek(g___,here,SEEK_SET);
- dump_script_table(g___,&ginfo.scripts[i],&ginfo);
- }
- /* And that should finish all the scripts/languages */
-
- /* so free the ginfo script/lang data */
- for ( i=0; i<ginfo.sc; ++i ) {
- for ( j=0; j<ginfo.scripts[i].lc; ++j ) {
- free( ginfo.scripts[i].langsys[j].feature_id );
- }
- free( ginfo.scripts[i].langsys );
- }
- free( ginfo.scripts );
-
-/* Now the features */
- feature_list_table_start = ftell(g___);
- fseek(g___,6,SEEK_SET);
- putshort(g___,feature_list_table_start);
- fseek(g___,0,SEEK_END);
- putshort(g___,ginfo.fcnt); /* Number of features */
- offset = 2+6*ginfo.fcnt; /* Offset to start of first feature table from beginning of feature_list */
- for ( i=0; i<ginfo.fcnt; ++i ) {
- putlong(g___,ginfo.feat_lookups[i].tag);
- putshort(g___,offset);
- offset += 4+2*ginfo.feat_lookups[i].lcnt;
- }
- /* for each feature, one feature table */
- size_params_ptr = 0;
- for ( i=0; i<ginfo.fcnt; ++i ) {
- ginfo.feat_lookups[i].name_param_ptr = 0;
- if ( ginfo.feat_lookups[i].tag==CHR('s','i','z','e') )
- size_params_ptr = ftell(g___);
- else if ( ginfo.feat_lookups[i].tag>=CHR('s','s','0','1') && ginfo.feat_lookups[i].tag<=CHR('s','s','2','0'))
- ginfo.feat_lookups[i].name_param_ptr = ftell(g___);
- putshort(g___,0); /* No feature params (we'll come back for 'size') */
- putshort(g___,ginfo.feat_lookups[i].lcnt);/* this many lookups */
- for ( j=0; j<ginfo.feat_lookups[i].lcnt; ++j )
- putshort(g___,ginfo.feat_lookups[i].lookups[j]->lookup_index );
- /* index of each lookup */
- }
- if ( size_params_ptr!=0 ) {
- size_params_loc = ftell(g___);
- fseek(g___,size_params_ptr,SEEK_SET);
- putshort(g___,size_params_loc-size_params_ptr);
- fseek(g___,size_params_loc,SEEK_SET);
- putshort(g___,sf->design_size);
- if ( sf->fontstyle_id!=0 || sf->fontstyle_name!=NULL ) {
- putshort(g___,sf->fontstyle_id);
- at->fontstyle_name_strid = at->next_strid++;
- putshort(g___,at->fontstyle_name_strid);
- } else {
- putshort(g___,0);
- putshort(g___,0);
- }
- putshort(g___,sf->design_range_bottom);
- putshort(g___,sf->design_range_top);
- }
- for ( i=0; i<ginfo.fcnt; ++i ) {
- if ( ginfo.feat_lookups[i].name_param_ptr!=0 &&
- (fn = findotffeatname(ginfo.feat_lookups[i].tag,sf))!=NULL ) {
- if ( fn->nid==0 )
- fn->nid = at->next_strid++;
- uint32 name_param_loc = ftell(g___);
- fseek(g___,ginfo.feat_lookups[i].name_param_ptr,SEEK_SET);
- putshort(g___,name_param_loc-ginfo.feat_lookups[i].name_param_ptr);
- fseek(g___,name_param_loc,SEEK_SET);
- putshort(g___,0); /* Minor version number */
- putshort(g___,fn->nid);
- }
- }
- /* And that should finish all the features */
-
- /* so free the ginfo feature data */
- for ( i=0; i<ginfo.fcnt; ++i )
- free( ginfo.feat_lookups[i].lookups );
- free( ginfo.feat_lookups );
-
-/* Now the lookups */
- all = is_gpos ? sf->gpos_lookups : sf->gsub_lookups;
- for ( cnt=0, otf = all; otf!=NULL; otf=otf->next ) {
- if ( otf->lookup_index!=-1 )
- ++cnt;
- }
- lookup_list_table_start = ftell(g___);
- fseek(g___,8,SEEK_SET);
- putshort(g___,lookup_list_table_start);
- fseek(g___,0,SEEK_END);
- putshort(g___,cnt);
- offset = 2+2*cnt; /* Offset to start of first lookup table from beginning of lookup list */
- for ( otf = all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
- putshort(g___,offset);
- for ( scnt=0, sub = otf->subtables; sub!=NULL; sub=sub->next ) {
- if ( sub->subtable_offset==-1 )
- continue;
- else if ( sub->extra_subtables!=NULL ) {
- for ( i=0; sub->extra_subtables[i]!=-1; ++i )
- ++scnt;
- } else
- ++scnt;
- }
- otf->subcnt = scnt;
- offset += 6+2*scnt; /* 6 bytes header +2 per lookup */
- if ( otf->lookup_flags & pst_usemarkfilteringset )
- offset += 2; /* For mark filtering set, if used */
- }
- offset -= 2+2*cnt;
- /* now the lookup tables */
- /* do we need any extension sub-tables? */
- efile=g___FigureExtensionSubTables(all,offset,is_gpos);
- for ( otf = all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
- putshort(g___,!otf->needs_extension ? (otf->lookup_type&0xff)
- : is_gpos ? 9 : 7);
- putshort(g___,(otf->lookup_flags&0xffff));
- putshort(g___,otf->subcnt);
- for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
- if ( sub->subtable_offset==-1 )
- continue;
- else if ( sub->extra_subtables!=NULL ) {
- for ( i=0; sub->extra_subtables[i]!=-1; ++i )
- putshort(g___,offset+sub->extra_subtables[i]);
- } else
- putshort(g___,offset+sub->subtable_offset);
-
- /* Offset to lookup data which is in the temp file */
- /* we keep adjusting offset so it reflects the distance between */
- /* here and the place where the temp file will start, and then */
- /* we need to skip l->offset bytes in the temp file */
- /* If it's a big GPOS/SUB table we may also need some extension */
- /* pointers, but FigureExtension will adjust for that */
- }
- offset -= 6+2*otf->subcnt;
- if ( otf->lookup_flags & pst_usemarkfilteringset ) {
- putshort(g___,otf->lookup_flags>>16);
- offset -= 2;
- }
- }
-
- buf = malloc(8096);
- if ( efile!=NULL ) {
- rewind(efile);
- while ( (i=fread(buf,1,8096,efile))>0 )
- fwrite(buf,1,i,g___);
- fclose(efile);
- }
- rewind(lfile);
- while ( (i=fread(buf,1,8096,lfile))>0 )
- fwrite(buf,1,i,g___);
- fclose(lfile);
- free(buf);
- for ( otf = all; otf!=NULL; otf=otf->next ) if ( otf->lookup_index!=-1 ) {
- for ( sub = otf->subtables; sub!=NULL; sub=sub->next ) {
- free(sub->extra_subtables);
- sub->extra_subtables = NULL;
- }
- otf->needs_extension = false;
- }
-return( g___ );
-}
-
-void otf_dumpgpos(struct alltabs *at, SplineFont *sf) {
- /* Open Type, bless its annoying little heart, doesn't store kern info */
- /* in the kern table. Of course not, how silly of me to think it might */
- /* be consistent. It stores it in the much more complicated gpos table */
- AnchorClass *ac;
-
- for ( ac=sf->anchor; ac!=NULL; ac=ac->next )
- ac->processed = false;
-
- at->gpos = dumpg___info(at, sf,true);
- if ( at->gpos!=NULL ) {
- at->gposlen = ftell(at->gpos);
- if ( at->gposlen&1 ) putc('\0',at->gpos);
- if ( (at->gposlen+1)&2 ) putshort(at->gpos,0);
- }
-}
-
-void otf_dumpgsub(struct alltabs *at, SplineFont *sf) {
- /* substitutions such as: Ligatures, cjk vertical rotation replacement, */
- /* arabic forms, small caps, ... */
- SFLigaturePrepare(sf);
- at->gsub = dumpg___info(at, sf, false);
- if ( at->gsub!=NULL ) {
- at->gsublen = ftell(at->gsub);
- if ( at->gsublen&1 ) putc('\0',at->gsub);
- if ( (at->gsublen+1)&2 ) putshort(at->gsub,0);
- }
- SFLigatureCleanup(sf);
-}
-
-int LigCaretCnt(SplineChar *sc) {
- PST *pst;
- int j, cnt;
-
- for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->type == pst_lcaret ) {
- if ( sc->lig_caret_cnt_fixed )
-return( pst->u.lcaret.cnt );
- else {
- /* only output non-zero carets */
- cnt=0;
- for ( j=pst->u.lcaret.cnt-1; j>=0 ; --j )
- if ( pst->u.lcaret.carets[j]!=0 )
- ++cnt;
-return( cnt );
- }
- }
- }
-return( 0 );
-}
-
-static void DumpLigCarets(FILE *gdef,SplineChar *sc) {
- PST *pst;
- int i, j, offset, cnt;
-
- for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->type == pst_lcaret )
- break;
- }
- if ( pst==NULL )
-return;
- cnt = LigCaretCnt(sc);
- if ( cnt==0 )
-return;
-
- if ( SCRightToLeft(sc) ) {
- for ( i=0; i<pst->u.lcaret.cnt-1; ++i )
- for ( j=i+1; j<pst->u.lcaret.cnt; ++j )
- if ( pst->u.lcaret.carets[i]<pst->u.lcaret.carets[j] ) {
- int16 temp = pst->u.lcaret.carets[i];
- pst->u.lcaret.carets[i] = pst->u.lcaret.carets[j];
- pst->u.lcaret.carets[j] = temp;
- }
- } else {
- for ( i=0; i<pst->u.lcaret.cnt-1; ++i )
- for ( j=i+1; j<pst->u.lcaret.cnt; ++j )
- if ( pst->u.lcaret.carets[i]>pst->u.lcaret.carets[j] ) {
- int16 temp = pst->u.lcaret.carets[i];
- pst->u.lcaret.carets[i] = pst->u.lcaret.carets[j];
- pst->u.lcaret.carets[j] = temp;
- }
- }
-
- putshort(gdef,cnt); /* this many carets */
- offset = sizeof(uint16) + sizeof(uint16)*cnt;
- for ( i=0; i<cnt; ++i ) {
- putshort(gdef,offset);
- offset+=4;
- }
- for ( i=0; i<pst->u.lcaret.cnt; ++i ) {
- if ( sc->lig_caret_cnt_fixed || pst->u.lcaret.carets[i]!=0 ) {
- putshort(gdef,1); /* Format 1 */
- putshort(gdef,pst->u.lcaret.carets[i]);
- }
- }
-}
-
-static int glyphnameinlist(char *haystack,char *name) {
- char *start, *pt;
- int ch, match, slen = strlen(name);
-
- for ( pt=haystack ; ; ) {
- while ( *pt==' ' ) ++pt;
- if ( *pt=='\0' )
-return( false );
- start=pt;
- while ( *pt!=' ' && *pt!='\0' ) ++pt;
- if ( pt-start==slen ) {
- ch = *pt; *pt='\0';
- match = strcmp(start,name);
- *pt = ch;
- if ( match==0 )
-return( true );
- }
- }
-}
-
-static int ReferencedByGSUB(SplineChar *sc) {
- PST *pst;
- SplineFont *sf = sc->parent;
- int gid;
- SplineChar *testsc;
- char *name = sc->name;
-
- /* If it is itself a ligature it will be referenced by GSUB */
- /* (because we store ligatures on the glyph generated) */
- for ( pst=sc->possub; pst!=NULL; pst=pst->next )
- if ( pst->type == pst_ligature )
-return( true );
-
- for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( (testsc=sf->glyphs[gid])!=NULL ) {
- for ( pst=testsc->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->type==pst_substitution || pst->type==pst_alternate ||
- pst->type==pst_multiple ) {
- if ( glyphnameinlist(pst->u.mult.components,name) )
-return( true );
- }
- }
- }
-return( false );
-}
-
-int gdefclass(SplineChar *sc) {
- PST *pst;
- AnchorPoint *ap;
-
- if ( sc->glyph_class!=0 )
-return( sc->glyph_class-1 );
-
- if ( strcmp(sc->name,".notdef")==0 )
-return( 0 );
-
- /* It isn't clear to me what should be done if a glyph is both a ligature */
- /* and a mark (There are some greek accent ligatures, it is probably more*/
- /* important that they be indicated as marks). Here I chose mark rather */
- /* than ligature as the mark class is far more likely to be used */
- ap=sc->anchor;
- while ( ap!=NULL && (ap->type==at_centry || ap->type==at_cexit) )
- ap = ap->next;
- if ( ap!=NULL && (ap->type==at_mark || ap->type==at_basemark) )
-return( 3 );
-
- for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
- if ( pst->type == pst_ligature )
-return( 2 ); /* Ligature */
- }
-
- /* I not quite sure what a componant glyph is. Probably something */
- /* that is not in the cmap table and is referenced in other glyphs */
- /* (I've never seen it used by others) */
- /* (Note: No glyph in a CID font can be components as all CIDs mean */
- /* something) (I think) */
- if ( sc->unicodeenc==-1 && sc->dependents!=NULL &&
- sc->parent->cidmaster!=NULL && !ReferencedByGSUB(sc))
-return( 4 );
- else
-return( 1 );
-}
-
-void otf_dumpgdef(struct alltabs *at, SplineFont *sf) {
- /* In spite of what the open type docs say, this table does appear to be */
- /* required (at least the glyph class def table) if we do mark to base */
- /* positioning */
- /* I was wondering at the apperant contradiction: something can be both a */
- /* base glyph and a ligature component, but it appears that the component*/
- /* class is unused and everything is a base unless it is a ligature or */
- /* mark */
- /* All my example fonts ignore the attachment list subtable and the mark */
- /* attach class def subtable, so I shall too */
- /* Ah. Some indic fonts need the mark attach class subtable for greater */
- /* control of lookup flags */
- /* All my example fonts contain a ligature caret list subtable, which is */
- /* empty. Odd, but perhaps important */
- int i,j,k, lcnt, needsclass;
- int pos, offset;
- int cnt, start, last, lastval;
- SplineChar **glyphs, *sc;
-
- /* Don't look in the cidmaster if we are only dumping one subfont */
- if ( sf->cidmaster && sf->cidmaster->glyphs!=NULL ) sf = sf->cidmaster;
- else if ( sf->mm!=NULL ) sf=sf->mm->normal;
-
- glyphs = NULL;
- for ( k=0; k<2; ++k ) {
- lcnt = 0;
- needsclass = false;
- for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
- SplineChar *sc = sf->glyphs[at->gi.bygid[i]];
- if ( sc->glyph_class!=0 || gdefclass(sc)!=1 )
- needsclass = true;
- if ( LigCaretCnt(sc)!=0 ) {
- if ( glyphs!=NULL ) glyphs[lcnt] = sc;
- ++lcnt;
- }
- }
- if ( lcnt==0 )
- break;
- if ( glyphs!=NULL )
- break;
- glyphs = malloc((lcnt+1)*sizeof(SplineChar *));
- glyphs[lcnt] = NULL;
- }
- if ( !needsclass && lcnt==0 && sf->mark_class_cnt==0 && sf->mark_set_cnt==0 )
-return; /* No anchor positioning, no ligature carets */
-
- at->gdef = tmpfile2();
- if ( sf->mark_set_cnt==0 ) {
- putlong(at->gdef,0x00010000); /* Version */
- putshort(at->gdef, needsclass ? 12 : 0 ); /* glyph class defn table */
- } else {
- putlong(at->gdef,0x00010002); /* Version with mark sets */
- putshort(at->gdef, needsclass ? 14 : 0 ); /* glyph class defn table */
- }
- putshort(at->gdef, 0 ); /* attachment list table */
- putshort(at->gdef, 0 ); /* ligature caret table (come back and fix up later) */
- putshort(at->gdef, 0 ); /* mark attachment class table */
- if ( sf->mark_set_cnt>0 ) {
- putshort(at->gdef, 0 ); /* mark attachment set table only meaningful if version is 0x10002*/
- }
-
- /* Glyph class subtable */
- if ( needsclass ) {
- /* Mark shouldn't conflict with anything */
- /* Ligature is more important than Base */
- /* Component is not used */
- /* ttx can't seem to support class format type 1 so let's output type 2 */
- for ( j=0; j<2; ++j ) {
- cnt = 0;
- for ( i=0; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
- sc = sf->glyphs[at->gi.bygid[i]];
- if ( sc!=NULL && sc->ttf_glyph!=-1 ) {
- lastval = gdefclass(sc);
- start = last = i;
- for ( ; i<at->gi.gcnt; ++i ) if ( at->gi.bygid[i]!=-1 ) {
- sc = sf->glyphs[at->gi.bygid[i]];
- if ( gdefclass(sc)!=lastval )
- break;
- last = i;
- }
- --i;
- if ( lastval!=0 ) {
- if ( j==1 ) {
- putshort(at->gdef,start);
- putshort(at->gdef,last);
- putshort(at->gdef,lastval);
- }
- ++cnt;
- }
- }
- }
- if ( j==0 ) {
- putshort(at->gdef,2); /* class format 2, range list by class */
- putshort(at->gdef,cnt);
- }
- }
- }
-
- /* Ligature caret subtable. Always include this if we have a GDEF */
- pos = ftell(at->gdef);
- fseek(at->gdef,8,SEEK_SET); /* location of lig caret table offset */
- putshort(at->gdef,pos);
- fseek(at->gdef,0,SEEK_END);
- if ( lcnt==0 ) {
- /* It always seems to be present, even if empty */
- putshort(at->gdef,4); /* Offset to (empty) coverage table */
- putshort(at->gdef,0); /* no ligatures */
- putshort(at->gdef,2); /* coverage table format 2 */
- putshort(at->gdef,0); /* no ranges in coverage table */
- } else {
- pos = ftell(at->gdef); /* coverage location */
- putshort(at->gdef,0); /* Offset to coverage table (fix up later) */
- putshort(at->gdef,lcnt);
- offset = 2*lcnt+4;
- for ( i=0; i<lcnt; ++i ) {
- putshort(at->gdef,offset);
- offset+=2+6*LigCaretCnt(glyphs[i]);
- }
- for ( i=0; i<lcnt; ++i )
- DumpLigCarets(at->gdef,glyphs[i]);
- offset = ftell(at->gdef);
- fseek(at->gdef,pos,SEEK_SET);
- putshort(at->gdef,offset-pos);
- fseek(at->gdef,0,SEEK_END);
- dumpcoveragetable(at->gdef,glyphs);
- }
-
- /* Mark Attachment Class Subtable */
- if ( sf->mark_class_cnt>0 ) {
- uint16 *mclasses = ClassesFromNames(sf,sf->mark_classes,sf->mark_class_cnt,at->maxp.numGlyphs,NULL,false);
- pos = ftell(at->gdef);
- fseek(at->gdef,10,SEEK_SET); /* location of mark attach table offset */
- putshort(at->gdef,pos);
- fseek(at->gdef,0,SEEK_END);
- DumpClass(at->gdef,mclasses,at->maxp.numGlyphs);
- free(mclasses);
- }
-
- /* Mark Attachment Class Subtable */
- if ( sf->mark_set_cnt>0 ) {
- pos = ftell(at->gdef);
- fseek(at->gdef,12,SEEK_SET); /* location of mark attach table offset */
- putshort(at->gdef,pos);
- fseek(at->gdef,0,SEEK_END);
- putshort(at->gdef,1); /* Version number */
- putshort(at->gdef,sf->mark_set_cnt);
- for ( i=0; i<sf->mark_set_cnt; ++i )
- putlong(at->gdef,0);
- for ( i=0; i<sf->mark_set_cnt; ++i ) {
- int here = ftell(at->gdef);
- fseek(at->gdef,pos+4+4*i,SEEK_SET);
- putlong(at->gdef,here-pos);
- fseek(at->gdef,0,SEEK_END);
- glyphs = OrderedGlyphsFromNames(sf,sf->mark_sets[i]);
- dumpcoveragetable(at->gdef,glyphs);
- free(glyphs);
- }
- }
-
- at->gdeflen = ftell(at->gdef);
- if ( at->gdeflen&1 ) putc('\0',at->gdef);
- if ( (at->gdeflen+1)&2 ) putshort(at->gdef,0);
-}
-
-/******************************************************************************/
-/* ******************************* MATH Table ******************************* */
-/* ********************** (Not strictly OpenType yet) *********************** */
-/******************************************************************************/
-enum math_bits { mb_constants=0x01, mb_italic=0x02, mb_topaccent=0x04,
- mb_extended=0x08, mb_mathkern=0x10, mb_vertvariant=0x20,
- mb_horizvariant=0x40,
- mb_all = 0x7f,
- mb_gi=(mb_italic|mb_topaccent|mb_extended|mb_mathkern),
- mb_gv=(mb_vertvariant|mb_horizvariant) };
-
-static int MathBits(struct alltabs *at, SplineFont *sf) {
- int i, gid, ret;
- SplineChar *sc;
-
- ret = sf->MATH ? mb_constants : 0;
-
- for ( i=0; i<at->gi.gcnt; ++i ) {
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
- if ( sc->italic_correction!=TEX_UNDEF )
- ret |= mb_italic;
- if ( sc->top_accent_horiz!=TEX_UNDEF )
- ret |= mb_topaccent;
- if ( sc->is_extended_shape )
- ret |= mb_extended;
- if ( sc->mathkern!=NULL )
- ret |= mb_mathkern;
- if ( sc->vert_variants!=NULL )
- ret |= mb_vertvariant;
- if ( sc->horiz_variants!=NULL )
- ret |= mb_horizvariant;
- if ( ret==mb_all )
-return( mb_all );
- }
- }
-return( ret );
-}
-
-static void ttf_math_dump_italic_top(FILE *mathf,struct alltabs *at, SplineFont *sf, int is_italic) {
- int i, gid, len;
- SplineChar *sc, **glyphs;
- uint32 coverage_pos, coverage_table;
- uint32 devtab_offset;
- DeviceTable *devtab;
-
- /* Figure out our glyph list (and count) */
- for ( i=len=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL )
- if ( (is_italic && sc->italic_correction!=TEX_UNDEF) || (!is_italic && sc->top_accent_horiz!=TEX_UNDEF))
- ++len;
- glyphs = malloc((len+1)*sizeof(SplineChar *));
- for ( i=len=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL )
- if ( (is_italic && sc->italic_correction!=TEX_UNDEF) || (!is_italic && sc->top_accent_horiz!=TEX_UNDEF))
- glyphs[len++] = sc;
- glyphs[len] = NULL;
-
- coverage_pos = ftell(mathf);
- putshort(mathf,0); /* Coverage table, return to this */
- putshort(mathf,len);
- devtab_offset = 4 + 4*len;
- for ( i=0; i<len; ++i ) {
- putshort(mathf,is_italic ? glyphs[i]->italic_correction : glyphs[i]->top_accent_horiz );
- devtab = is_italic ? glyphs[i]->italic_adjusts : glyphs[i]->top_accent_adjusts;
- if ( devtab!=NULL ) {
- putshort(mathf,devtab_offset);
- devtab_offset += DevTabLen(devtab);
- } else
- putshort(mathf,0);
- }
- for ( i=0; i<len; ++i ) {
- devtab = is_italic ? glyphs[i]->italic_adjusts : glyphs[i]->top_accent_adjusts;
- if ( devtab!=NULL )
- dumpgposdevicetable(mathf,devtab);
- }
- if ( devtab_offset!=ftell(mathf)-coverage_pos )
- IError("Actual end did not match expected end in %s table, expected=%d, actual=%d",
- is_italic ? "italic" : "top accent", devtab_offset, ftell(mathf)-coverage_pos );
- coverage_table = ftell(mathf);
- fseek( mathf, coverage_pos, SEEK_SET);
- putshort(mathf,coverage_table-coverage_pos);
- fseek(mathf,coverage_table,SEEK_SET);
- dumpcoveragetable(mathf,glyphs);
- free(glyphs);
-}
-
-static void ttf_math_dump_extended(FILE *mathf,struct alltabs *at, SplineFont *sf) {
- int i, gid, len;
- SplineChar *sc, **glyphs;
-
- for ( i=len=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL )
- if ( sc->is_extended_shape )
- ++len;
- glyphs = malloc((len+1)*sizeof(SplineChar *));
- for ( i=len=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL )
- if ( sc->is_extended_shape )
- glyphs[len++] = sc;
- glyphs[len] = NULL;
- dumpcoveragetable(mathf,glyphs);
- free(glyphs);
-}
-
-static int mkv_len(struct mathkernvertex *mkv) {
-return( 2+8*mkv->cnt-4 );
-}
-
-static int ttf_math_dump_mathkernvertex(FILE *mathf,struct mathkernvertex *mkv,
- int devtab_pos) {
- int i;
- uint32 here = ftell(mathf);
-
- putshort(mathf,mkv->cnt-1);
-
- for ( i=0; i<mkv->cnt-1; ++i ) {
- putshort(mathf,mkv->mkd[i].height);
- if ( mkv->mkd[i].height_adjusts!=NULL ) {
- putshort(mathf,devtab_pos-here);
- devtab_pos += DevTabLen(mkv->mkd[i].height_adjusts);
- } else
- putshort(mathf,0);
- }
- for ( i=0; i<mkv->cnt; ++i ) {
- putshort(mathf,mkv->mkd[i].kern);
- if ( mkv->mkd[i].kern_adjusts!=NULL ) {
- putshort(mathf,devtab_pos-here);
- devtab_pos += DevTabLen(mkv->mkd[i].kern_adjusts);
- } else
- putshort(mathf,0);
- }
-return( devtab_pos );
-}
-
-static void ttf_math_dump_mathkerndevtab(FILE *mathf,struct mathkernvertex *mkv) {
- int i;
-
- for ( i=0; i<mkv->cnt-1; ++i )
- if ( mkv->mkd[i].height_adjusts!=NULL )
- dumpgposdevicetable(mathf,mkv->mkd[i].height_adjusts);
- for ( i=0; i<mkv->cnt; ++i )
- if ( mkv->mkd[i].kern_adjusts!=NULL )
- dumpgposdevicetable(mathf,mkv->mkd[i].kern_adjusts);
-}
-
-static void ttf_math_dump_mathkern(FILE *mathf,struct alltabs *at, SplineFont *sf) {
- int i, gid, len;
- SplineChar *sc, **glyphs;
- uint32 coverage_pos, coverage_table, kr_pos, midpos2;
-
- /* Figure out our glyph list (and count) */
- for ( i=len=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL )
- if ( sc->mathkern!=NULL )
- ++len;
- glyphs = malloc((len+1)*sizeof(SplineChar *));
- for ( i=len=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL )
- if ( sc->mathkern!=NULL )
- glyphs[len++] = sc;
- glyphs[len] = NULL;
-
- coverage_pos = ftell(mathf);
- putshort(mathf,0); /* Coverage table, return to this */
- putshort(mathf,len);
- kr_pos = coverage_pos + 4 + 8*len;
- for ( i=0; i<len; ++i ) {
- struct mathkern *mk = glyphs[i]->mathkern;
- if ( mk->top_right.cnt==0 )
- putshort(mathf,0);
- else {
- putshort(mathf,kr_pos-coverage_pos);
- kr_pos += mkv_len(&mk->top_right);
- }
- if ( mk->top_left.cnt==0 )
- putshort(mathf,0);
- else {
- putshort(mathf,kr_pos-coverage_pos);
- kr_pos += mkv_len(&mk->top_left);
- }
- if ( mk->bottom_right.cnt==0 )
- putshort(mathf,0);
- else {
- putshort(mathf,kr_pos-coverage_pos);
- kr_pos += mkv_len(&mk->bottom_right);
- }
- if ( mk->bottom_left.cnt==0 )
- putshort(mathf,0);
- else {
- putshort(mathf,kr_pos-coverage_pos);
- kr_pos += mkv_len(&mk->bottom_left);
- }
- }
- if ( ftell(mathf)!=coverage_pos + 4 + 8*len )
- IError("Actual midpoint1 did not match expected midpoint1 in mathkern table, expected=%d, actual=%d",
- coverage_pos + 4 + 8*len, ftell(mathf) );
-
- midpos2 = kr_pos;
- for ( i=0; i<len; ++i ) {
- struct mathkern *mk = glyphs[i]->mathkern;
- if ( mk->top_right.cnt!=0 )
- kr_pos = ttf_math_dump_mathkernvertex(mathf,&mk->top_right,kr_pos);
- if ( mk->top_left.cnt!=0 )
- kr_pos = ttf_math_dump_mathkernvertex(mathf,&mk->top_left,kr_pos);
- if ( mk->bottom_right.cnt!=0 )
- kr_pos = ttf_math_dump_mathkernvertex(mathf,&mk->bottom_right,kr_pos);
- if ( mk->bottom_left.cnt!=0 )
- kr_pos = ttf_math_dump_mathkernvertex(mathf,&mk->bottom_left,kr_pos);
- }
- if ( ftell(mathf)!=midpos2)
- IError("Actual midpoint2 did not match expected midpoint2 in mathkern table, expected=%d, actual=%d",
- midpos2, ftell(mathf) );
-
- for ( i=0; i<len; ++i ) {
- struct mathkern *mk = glyphs[i]->mathkern;
- if ( mk->top_right.cnt!=0 )
- ttf_math_dump_mathkerndevtab(mathf,&mk->top_right);
- if ( mk->top_left.cnt!=0 )
- ttf_math_dump_mathkerndevtab(mathf,&mk->top_left);
- if ( mk->bottom_right.cnt!=0 )
- ttf_math_dump_mathkerndevtab(mathf,&mk->bottom_right);
- if ( mk->bottom_left.cnt!=0 )
- ttf_math_dump_mathkerndevtab(mathf,&mk->bottom_left);
- }
- if ( kr_pos!=ftell(mathf) )
- IError("Actual end did not match expected end in mathkern table, expected=%d, actual=%d",
- kr_pos, ftell(mathf) );
-
- coverage_table = ftell(mathf);
- fseek( mathf, coverage_pos, SEEK_SET);
- putshort(mathf,coverage_table-coverage_pos);
- fseek(mathf,coverage_table,SEEK_SET);
- dumpcoveragetable(mathf,glyphs);
- free(glyphs);
-}
-
-static int gv_len(SplineFont *sf, struct glyphvariants *gv) {
- char *pt, *start;
- int ch, cnt;
- SplineChar *sc;
-
- if ( gv==NULL || (gv->variants==NULL && gv->part_cnt==0))
-return( 0 );
- if ( gv->variants==NULL )
-return( 4 ); /* No variants, but we've got parts to assemble */
- cnt = 0;
- for ( start=gv->variants ;; ) {
- while ( *start==' ' ) ++start;
- if ( *start=='\0' )
-return( 4+4*cnt ); /* MathGlyphConstructionTable */
- for ( pt = start ; *pt!=' ' && *pt!='\0'; ++pt );
- ch = *pt; *pt = '\0';
- sc = SFGetChar(sf,-1,start);
- *pt = ch;
- if ( sc!=NULL )
- ++cnt;
- start = pt;
- }
-}
-
-static int gvc_len(struct glyphvariants *gv) {
- if ( gv->part_cnt==0 )
-return( 0 );
-
-return( 6+10*gv->part_cnt );
-}
-
-static uint32 ttf_math_dump_mathglyphconstructiontable(FILE *mathf,
- struct glyphvariants *gv,SplineFont *sf, uint32 pos,int is_v) {
- char *pt, *start;
- int ch, cnt;
- SplineChar *sc;
- uint32 here = ftell(mathf);
- DBounds b;
-
- putshort(mathf,gv->part_cnt==0? 0 : pos-here);
- if ( gv->variants==NULL ) {
- putshort(mathf,0);
- } else {
- cnt = 0;
- for ( start=gv->variants ;; ) {
- while ( *start==' ' ) ++start;
- if ( *start=='\0' )
- break;
- for ( pt = start ; *pt!=' ' && *pt!='\0'; ++pt );
- ch = *pt; *pt = '\0';
- sc = SFGetChar(sf,-1,start);
- *pt = ch;
- if ( sc!=NULL )
- ++cnt;
- start = pt;
- }
- putshort(mathf,cnt);
- for ( start=gv->variants ;; ) {
- while ( *start==' ' ) ++start;
- if ( *start=='\0' )
- break;
- for ( pt = start ; *pt!=' ' && *pt!='\0'; ++pt );
- ch = *pt; *pt = '\0';
- sc = SFGetChar(sf,-1,start);
- *pt = ch;
- if ( sc!=NULL ) {
- putshort(mathf,sc->ttf_glyph);
- SplineCharFindBounds(sc,&b);
- /* Don't ask me why I have a plus one here. In the MS font */
- /* CambriaMath all of these values are one more than I would */
- /* expect */
- if ( is_v )
- putshort(mathf,b.maxy-b.miny +1);
- else
- putshort(mathf,b.maxx-b.minx +1);
- }
- start=pt;
- }
- }
-return( pos + gvc_len(gv));
-}
-
-static uint32 ttf_math_dump_mathglyphassemblytable(FILE *mathf,
- struct glyphvariants *gv,SplineFont *sf, uint32 devtab_pos) {
- SplineChar *sc;
- uint32 here = ftell(mathf);
- int i;
-
- if ( gv->part_cnt==0 )
-return( devtab_pos );
- putshort(mathf,gv->italic_correction);
- if ( gv->italic_adjusts!=NULL ) {
- putshort(mathf,devtab_pos-here);
- devtab_pos += DevTabLen(gv->italic_adjusts);
- } else
- putshort(mathf,0);
- putshort(mathf,gv->part_cnt);
- for ( i=0; i<gv->part_cnt; ++i ) {
- sc = SFGetChar(sf,-1,gv->parts[i].component);
- if ( sc==NULL )
- putshort(mathf,0); /* .notdef */
- else
- putshort(mathf,sc->ttf_glyph);
- putshort(mathf,gv->parts[i].startConnectorLength);
- putshort(mathf,gv->parts[i].endConnectorLength);
- putshort(mathf,gv->parts[i].fullAdvance);
- putshort(mathf,gv->parts[i].is_extender);
- }
-return(devtab_pos);
-}
-
-static void ttf_math_dump_glyphvariant(FILE *mathf,struct alltabs *at, SplineFont *sf) {
- int i, gid, vlen, hlen;
- SplineChar *sc, **vglyphs, **hglyphs;
- uint32 coverage_pos, coverage_table, offset, pos, assembly_pos;
-
- /* Figure out our glyph list (and count) */
- for ( i=vlen=hlen=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
- if ( sc->vert_variants!=NULL )
- ++vlen;
- if ( sc->horiz_variants!=NULL )
- ++hlen;
- }
-
- vglyphs = malloc((vlen+1)*sizeof(SplineChar *));
- hglyphs = malloc((hlen+1)*sizeof(SplineChar *));
- for ( i=vlen=hlen=0; i<at->gi.gcnt; ++i )
- if ( (gid=at->gi.bygid[i])!=-1 && (sc=sf->glyphs[gid])!=NULL ) {
- if ( sc->vert_variants!=NULL )
- vglyphs[vlen++] = sc;
- if ( sc->horiz_variants!=NULL )
- hglyphs[hlen++] = sc;
- }
- vglyphs[vlen] = NULL;
- hglyphs[hlen] = NULL;
-
- putshort(mathf,sf->MATH==NULL?(sf->ascent+sf->descent)/50 : sf->MATH->MinConnectorOverlap );
- coverage_pos = ftell(mathf);
- putshort(mathf,0); /* Vertical Coverage table, return to this */
- putshort(mathf,0); /* Horizontal Coverage table, return to this */
- putshort(mathf,vlen);
- putshort(mathf,hlen);
- offset = 5*2+vlen*2+hlen*2;
- for ( i=0; i<vlen; ++i ) {
- putshort(mathf,offset);
- offset += gv_len(sf,vglyphs[i]->vert_variants);
- }
- for ( i=0; i<hlen; ++i ) {
- putshort(mathf,offset);
- offset += gv_len(sf,hglyphs[i]->horiz_variants);
- }
- assembly_pos = pos = (coverage_pos-2)+offset;
- for ( i=0; i<vlen; ++i ) {
- /*uint32 start = ftell(mathf);*/
- pos = ttf_math_dump_mathglyphconstructiontable(mathf,
- vglyphs[i]->vert_variants,sf,pos,true);
- /*if ( ftell(mathf)-start != gv_len(sf,vglyphs[i]->vert_variants))*/
- /*IError("v gv_len incorrect");*/
- }
- for ( i=0; i<hlen; ++i ) {
- /*uint32 start = ftell(mathf);*/
- pos = ttf_math_dump_mathglyphconstructiontable(mathf,
- hglyphs[i]->horiz_variants,sf,pos,false);
- /*if ( ftell(mathf)-start != gv_len(sf,hglyphs[i]->horiz_variants))*/
- /*IError("h gv_len incorrect: %s", hglyphs[i]->name);*/
- }
- if ( ftell(mathf)!=assembly_pos )
- IError("assembly tables at wrong place");
-
- for ( i=0; i<vlen; ++i )
- pos = ttf_math_dump_mathglyphassemblytable(mathf,
- vglyphs[i]->vert_variants,sf,pos);
- for ( i=0; i<hlen; ++i )
- pos = ttf_math_dump_mathglyphassemblytable(mathf,
- hglyphs[i]->horiz_variants,sf,pos);
- for ( i=0; i<vlen; ++i )
- if ( vglyphs[i]->vert_variants->part_cnt!=0 &&
- vglyphs[i]->vert_variants->italic_adjusts!=NULL )
- dumpgposdevicetable(mathf,vglyphs[i]->vert_variants->italic_adjusts);
- for ( i=0; i<hlen; ++i )
- if ( hglyphs[i]->horiz_variants->part_cnt!=0 &&
- hglyphs[i]->horiz_variants->italic_adjusts!=NULL )
- dumpgposdevicetable(mathf,hglyphs[i]->horiz_variants->italic_adjusts);
- if ( vlen!=0 ) {
- coverage_table = ftell(mathf);
- fseek( mathf, coverage_pos, SEEK_SET);
- putshort(mathf,coverage_table-(coverage_pos-2));
- fseek(mathf,coverage_table,SEEK_SET);
- dumpcoveragetable(mathf,vglyphs);
- }
- free(vglyphs);
- if ( hlen!=0 ) {
- coverage_table = ftell(mathf);
- fseek( mathf, coverage_pos+2, SEEK_SET);
- putshort(mathf,coverage_table-(coverage_pos-2));
- fseek(mathf,coverage_table,SEEK_SET);
- dumpcoveragetable(mathf,hglyphs);
- }
- free(hglyphs);
-}
-
-void otf_dump_math(struct alltabs *at, SplineFont *sf) {
- FILE *mathf;
- int i;
- uint32 devtab_offsets[60], const_start, gi_start, v_start;
- int bits = MathBits(at,sf);
-
- if ( sf->MATH==NULL )
-return;
-
- at->math = mathf = tmpfile2();
-
- putlong(mathf, 0x00010000 ); /* Version 1 */
- putshort(mathf, 10); /* Offset to constants */
- putshort(mathf, 0); /* GlyphInfo, fix later */
- putshort(mathf, 0); /* Variants, fix later */
-
- /* Start on constants */
- memset(devtab_offsets,0,sizeof(devtab_offsets));
- const_start = ftell(mathf);
- for ( i=0; math_constants_descriptor[i].script_name!=NULL; ++i ) {
- int16 *pos = (int16 *) (((char *) (sf->MATH)) + math_constants_descriptor[i].offset );
- if ( pos == (int16 *) &sf->MATH->MinConnectorOverlap )
- continue; /* Actually lives in the Variant table, not here */
- putshort(mathf, *pos);
- if ( math_constants_descriptor[i].devtab_offset != -1 ) {
- devtab_offsets[i] = ftell(mathf);
- putshort(mathf, 0); /* Fix up later if we support device tables */
- }
- }
- for ( i=0; math_constants_descriptor[i].script_name!=NULL; ++i ) {
- int16 *pos = (int16 *) (((char *) (sf->MATH)) + math_constants_descriptor[i].offset );
- DeviceTable **devtab = (DeviceTable **) (((char *) (sf->MATH)) + math_constants_descriptor[i].devtab_offset );
- if ( pos == (int16 *) &sf->MATH->MinConnectorOverlap )
- continue; /* Actually lives in the Variant table, not here */
- if ( math_constants_descriptor[i].devtab_offset >= 0 && *devtab!=NULL ) {
- uint32 here = ftell(mathf);
- fseek(mathf,devtab_offsets[i],SEEK_SET);
- putshort(mathf, here-const_start);
- fseek(mathf,here,SEEK_SET);
- dumpgposdevicetable(mathf,*devtab);
- }
- }
-
- /* The spec does not say this can be NULL */
- if ( 1 /* bits&mb_gi*/ ) {
- gi_start = ftell(mathf);
- fseek(mathf,6,SEEK_SET);
- putshort(mathf,gi_start);
- fseek(mathf,gi_start,SEEK_SET);
-
- putshort(mathf,0); /* Italics correction */
- putshort(mathf,0); /* top accent */
- putshort(mathf,0); /* is extended shape */
- putshort(mathf,0); /* math kern info */
-
- if ( bits&mb_italic ) {
- v_start = ftell(mathf);
- fseek(mathf,gi_start,SEEK_SET);
- putshort(mathf,v_start-gi_start);
- fseek(mathf,v_start,SEEK_SET);
-
- ttf_math_dump_italic_top(mathf,at,sf,true);
- }
-
- if ( bits&mb_topaccent ) {
- v_start = ftell(mathf);
- fseek(mathf,gi_start+2,SEEK_SET);
- putshort(mathf,v_start-gi_start);
- fseek(mathf,v_start,SEEK_SET);
-
- ttf_math_dump_italic_top(mathf,at,sf,false);
- }
-
- if ( bits&mb_extended ) {
- v_start = ftell(mathf);
- fseek(mathf,gi_start+4,SEEK_SET);
- putshort(mathf,v_start-gi_start);
- fseek(mathf,v_start,SEEK_SET);
-
- ttf_math_dump_extended(mathf,at,sf);
- }
-
- if ( bits&mb_mathkern ) {
- v_start = ftell(mathf);
- fseek(mathf,gi_start+6,SEEK_SET);
- putshort(mathf,v_start-gi_start);
- fseek(mathf,v_start,SEEK_SET);
-
- ttf_math_dump_mathkern(mathf,at,sf);
- }
- }
-
- /* The spec does not say this can be NULL */
- if ( 1 /* bits&mb_gv*/ ) {
- v_start = ftell(mathf);
- fseek(mathf,8,SEEK_SET);
- putshort(mathf,v_start);
- fseek(mathf,v_start,SEEK_SET);
-
- ttf_math_dump_glyphvariant(mathf,at,sf);
- }
-
- at->mathlen = ftell(mathf);
- if ( ftell(mathf)&1 )
- putc('\0',mathf);
- if ( ftell(mathf)&2 )
- putshort(mathf,0);
-}
-
-struct taglist {
- uint32 tag;
- struct taglist *next;
-};
-
-static int taglistcompar(const void *_cv1, const void *_cv2) {
- const struct taglist *const *tl1 = _cv1, *const *tl2 = _cv2;
-
- if ( (*tl1)->tag==(*tl2)->tag )
-return( 0 );
- if ( (*tl1)->tag>(*tl2)->tag )
-return( 1 );
-
-return( -1 );
-}
-
-static int langlistcompar(const void *_cv1, const void *_cv2) {
- const struct taglist *const *tl1 = _cv1, *const *tl2 = _cv2;
-
- if ( (*tl1)->tag==(*tl2)->tag )
-return( 0 );
- if ( (*tl1)->tag == DEFAULT_LANG )
-return( -1 );
- if ( (*tl2)->tag == DEFAULT_LANG )
-return( 1 );
- if ( (*tl1)->tag>(*tl2)->tag )
-return( 1 );
-
-return( -1 );
-}
-
-static struct taglist *sorttaglist(struct taglist *list,int (*compar)(const void *,const void*)) {
- struct taglist *t, **array;
- int i,cnt;
-
- if ( list==NULL || list->next==NULL )
-return( list );
-
- for ( t=list, cnt=0; t!=NULL; t=t->next, ++cnt );
- array = malloc(cnt*sizeof(struct taglist *));
- for ( t=list, cnt=0; t!=NULL; t=t->next, ++cnt )
- array[cnt] = t;
- qsort(array,cnt,sizeof(struct taglist *),compar);
- for ( i=1; i<cnt; ++i )
- array[i-1]->next = array[i];
- array[cnt-1]->next = NULL;
- list = array[0];
- free( array );
-return( list );
-}
-
-static void _base_sort(struct Base *base) {
- /* Sort the base lines. Which can reorder the def_baseline index in the */
- /* script, and the baseline_pos lists */
- /* Sort the script list */
- /* Sort the language lists in each script */
- /* Sort the feature lists in each language */
- int i,j,pos, tag;
- struct basescript *bs;
- struct baselangextent *langs;
-
- if ( base==NULL )
-return;
-
- if ( base->baseline_cnt!=0 ) {
- for ( i=0; i<base->baseline_cnt; ++i )
- for ( j=i+1; j<base->baseline_cnt; ++j ) {
- if ( base->baseline_tags[i]>base->baseline_tags[j] ) {
- tag = base->baseline_tags[i];
- base->baseline_tags[i] = base->baseline_tags[j];
- base->baseline_tags[j] = tag;
- for ( bs=base->scripts ; bs!=NULL; bs=bs->next ) {
- if ( bs->def_baseline==i )
- bs->def_baseline = j;
- else if ( bs->def_baseline==j )
- bs->def_baseline = i;
- pos = bs->baseline_pos[i];
- bs->baseline_pos[i] = bs->baseline_pos[j];
- bs->baseline_pos[j] = pos;
- }
- }
- }
- }
- base->scripts = (struct basescript *) sorttaglist((struct taglist *) base->scripts,taglistcompar);
- for ( bs=base->scripts ; bs!=NULL; bs=bs->next ) {
- bs->langs = (struct baselangextent *) sorttaglist((struct taglist *) bs->langs,langlistcompar);
- for ( langs = bs->langs; langs!=NULL; langs = langs->next )
- langs->features = (struct baselangextent *) sorttaglist((struct taglist *) langs->features,taglistcompar);
- }
-}
-
-void SFBaseSort(SplineFont *sf) {
- _base_sort(sf->horiz_base);
- _base_sort(sf->vert_base);
-}
-
-static void dump_minmax(FILE *basef,struct baselangextent *bl) {
- struct baselangextent *fl;
- int fcnt;
-
- putshort(basef,bl->descent);
- putshort(basef,bl->ascent);
- for ( fl=bl->features, fcnt=0; fl!=NULL; fl=fl->next, ++fcnt );
- putshort(basef,fcnt);
- for ( fl=bl->features; fl!=NULL; fl=fl->next ) {
- putlong(basef,fl->lang); /* feature tag really */
- putshort(basef,fl->descent);
- putshort(basef,fl->ascent);
- }
-}
-
-void otf_dumpbase(struct alltabs *at, SplineFont *sf) {
- FILE *basef;
- int i,j, cnt, lcnt;
- uint32 here, bsl;
- struct basescript *bs;
- struct baselangextent *bl, *dflt;
- int offset;
-
- if ( sf->horiz_base==NULL && sf->vert_base==NULL )
-return;
-
- SFBaseSort(sf);
-
- at->base = basef = tmpfile2();
-
- putlong(basef, 0x00010000 ); /* Version 1 */
- putshort(basef, 0 ); /* offset to horizontal baselines, fill in later */
- putshort(basef, 0 ); /* offset to vertical baselines, fill in later */
-
- for ( i=0; i<2; ++i ) {
- struct Base *base = i==0 ? sf->horiz_base : sf->vert_base;
- if ( base==NULL )
- continue;
- here = ftell(basef);
- fseek(basef,4+2*i,SEEK_SET);
- putshort(basef,here-0);
- fseek(basef,here,SEEK_SET);
-
- /* axis table */
- putshort(basef,base->baseline_cnt==0 ? 0 : 4 );
- putshort(basef,base->baseline_cnt==0 ? 4 :
- 4+2+4*base->baseline_cnt );
-
- if ( base->baseline_cnt!=0 ) {
- /* BaseTagList table */
- putshort(basef,base->baseline_cnt);
- for ( j=0; j<base->baseline_cnt; ++j )
- putlong(basef,base->baseline_tags[j]);
- }
-
- /* BaseScriptList table */
- bsl = ftell(basef);
- for ( bs=base->scripts, cnt=0; bs!=NULL; bs=bs->next, ++cnt );
- putshort(basef,cnt);
- for ( bs=base->scripts; bs!=NULL; bs=bs->next ) {
- putlong(basef,bs->script);
- putshort(basef,0);
- }
-
- /* BaseScript table */
- for ( bs=base->scripts, cnt=0; bs!=NULL; bs=bs->next, ++cnt ) {
- uint32 bst = ftell(basef);
- fseek(basef,bsl+2+6*cnt+4,SEEK_SET);
- putshort(basef,bst-bsl);
- fseek(basef,bst,SEEK_SET);
-
- for ( bl=bs->langs, dflt=NULL, lcnt=0; bl!=NULL; bl=bl->next ) {
- if ( bl->lang==DEFAULT_LANG )
- dflt = bl;
- else
- ++lcnt;
- }
- offset = 6+6*lcnt;
- putshort(basef,base->baseline_cnt==0?0:offset);
- if ( base->baseline_cnt!=0 )
- offset += 4+2*base->baseline_cnt+4*base->baseline_cnt;
- putshort(basef,dflt==NULL ? 0 : offset);
- putshort(basef,lcnt);
- for ( bl=bs->langs; bl!=NULL; bl=bl->next ) if ( bl->lang!=DEFAULT_LANG ) {
- putlong(basef,bl->lang);
- putshort(basef,0);
- }
-
- /* Base Values table */
- if ( base->baseline_cnt!=0 ) {
- offset = 4+2*base->baseline_cnt;
- putshort(basef,bs->def_baseline);
- putshort(basef,base->baseline_cnt);
- for ( j=0; j<base->baseline_cnt; ++j ) {
- putshort(basef,offset);
- offset += 2*2;
- }
- for ( j=0; j<base->baseline_cnt; ++j ) {
- putshort(basef,1); /* format 1 */
- putshort(basef,bs->baseline_pos[j]);
- }
- }
-
- if ( dflt!=NULL )
- dump_minmax(basef,dflt);
- for ( bl=bs->langs, dflt=NULL, lcnt=0; bl!=NULL; bl=bl->next ) if ( bl->lang!=DEFAULT_LANG ) {
- uint32 here = ftell(basef);
- fseek(basef,bst+6+6*lcnt+4,SEEK_SET);
- putshort(basef,here-bst);
- fseek(basef,here,SEEK_SET);
- dump_minmax(basef,bl);
- }
- }
- }
-
- at->baselen = ftell(basef);
- if ( ftell(basef)&1 )
- putc('\0',basef);
- if ( ftell(basef)&2 )
- putshort(basef,0);
-}
-
-static int jscriptsort(const void *_s1,const void *_s2) {
- const Justify * const * __s1 = (const Justify * const *) _s1;
- const Justify * const * __s2 = (const Justify * const *) _s2;
- const Justify *s1 = *__s1;
- const Justify *s2 = *__s2;
-
- if ( s1->script>s2->script )
-return( 1 );
- else if ( s1->script<s2->script )
-return( -1 );
- else
-return( 0 );
-}
-
-static int jlangsort(const void *_s1,const void *_s2) {
- const struct jstf_lang * const * __s1 = (const struct jstf_lang * const *) _s1;
- const struct jstf_lang * const * __s2 = (const struct jstf_lang * const *) _s2;
- const struct jstf_lang *s1 = *__s1;
- const struct jstf_lang *s2 = *__s2;
-
- if ( s1->lang==s2->lang )
-return( 0 );
-
- if ( s1->lang==DEFAULT_LANG )
-return( -1 );
- if ( s2->lang==DEFAULT_LANG )
-return( 1 );
-
- if ( s1->lang>s2->lang )
-return( 1 );
- else
-return( -1 );
-}
-
-static int lookup_order(const void *_s1,const void *_s2) {
- const OTLookup * const * __s1 = (const OTLookup * const *) _s1;
- const OTLookup * const * __s2 = (const OTLookup * const *) _s2;
- const OTLookup *s1 = *__s1;
- const OTLookup *s2 = *__s2;
-
- if ( s1->lookup_index>s2->lookup_index )
-return( 1 );
- else if ( s1->lookup_index<s2->lookup_index )
-return( -1 );
- else
-return( 0 );
-}
-
-static void SFJstfSort(SplineFont *sf) {
- /* scripts must be ordered */
- /* languages must be ordered within scripts */
- /* lookup lists must be ordered */
- Justify *jscript, **scripts;
- int i,cnt,lmax;
- struct jstf_lang **langs;
-
- for ( cnt=0, jscript= sf->justify; jscript!=NULL; ++cnt, jscript=jscript->next );
- if ( cnt>1 ) {
- scripts = malloc(cnt*sizeof(Justify *));
- for ( i=0, jscript= sf->justify; jscript!=NULL; ++i, jscript=jscript->next )
- scripts[i] = jscript;
- qsort(scripts,cnt,sizeof(Justify *),jscriptsort);
- for ( i=1; i<cnt; ++i )
- scripts[i-1]->next = scripts[i];
- scripts[cnt-1]->next = NULL;
- sf->justify = scripts[0];
- free(scripts);
- }
-
- langs = NULL; lmax=0;
- for ( jscript= sf->justify; jscript!=NULL; jscript=jscript->next ) {
- struct jstf_lang *jlang;
- for ( cnt=0, jlang=jscript->langs; jlang!=NULL; ++cnt, jlang=jlang->next );
- if ( cnt>1 ) {
- if ( cnt>lmax )
- langs = realloc(langs,(lmax=cnt+10)*sizeof(struct jstf_lang *));
- for ( i=0, jlang=jscript->langs; jlang!=NULL; ++i, jlang=jlang->next )
- langs[i] = jlang;
- qsort(langs,cnt,sizeof(Justify *),jlangsort);
- for ( i=1; i<cnt; ++i )
- langs[i-1]->next = langs[i];
- langs[cnt-1]->next = NULL;
- jscript->langs = langs[0];
- }
- }
- free(langs);
-
- /* don't bother to sort the lookup lists yet. We need to separate them into*/
- /* GPOS/GSUB first, might as well do it all at once later */
-}
-
-static void jstf_SplitTables(OTLookup **mixed,OTLookup ***_SUB,OTLookup ***_POS) {
- /* (later is now, see comment above) */
- /* mixed contains both gsub and gpos lookups. put them into their own */
- /* lists, and then sort them */
- int cnt, s, p;
- OTLookup **SUB, **POS;
-
- if ( mixed==NULL || mixed[0]==NULL ) {
- *_SUB = NULL;
- *_POS = NULL;
-return;
- }
-
- for ( cnt=0; mixed[cnt]!=NULL; ++cnt);
- SUB = malloc((cnt+1)*sizeof(OTLookup *));
- POS = malloc((cnt+1)*sizeof(OTLookup *));
- for ( cnt=s=p=0; mixed[cnt]!=NULL; ++cnt) {
- if ( mixed[cnt]->lookup_index==-1 ) /* Not actually used */
- continue;
- if ( mixed[cnt]->lookup_type>=gpos_start )
- POS[p++] = mixed[cnt];
- else
- SUB[s++] = mixed[cnt];
- }
- POS[p] = SUB[s] = NULL;
-
- if ( p>1 )
- qsort(POS,p,sizeof(OTLookup *),lookup_order);
- if ( s>1 )
- qsort(SUB,s,sizeof(OTLookup *),lookup_order);
- if ( p==0 ) {
- free(POS);
- POS=NULL;
- }
- if ( s==0 ) {
- free(SUB);
- SUB=NULL;
- }
- *_SUB = SUB;
- *_POS = POS;
-}
-
-static uint32 jstf_dumplklist(FILE *jstf,OTLookup **PS,uint32 base) {
- uint32 here;
- int i;
-
- if ( PS==NULL )
-return( 0 );
-
- here = ftell(jstf);
- for ( i=0; PS[i]!=NULL; ++i );
- putshort(jstf,i); /* Lookup cnt */
- for ( i=0; PS[i]!=NULL; ++i )
- putshort( jstf, PS[i]->lookup_index );
- free(PS);
-return( here - base );
-}
-
-static uint32 jstf_dumpmaxlookups(FILE *jstf,SplineFont *sf,struct alltabs *at,
- OTLookup **maxes,uint32 base) {
- uint32 here, lbase;
- int cnt,i;
- int scnt, j;
- struct lookup_subtable *sub;
-
- if ( maxes==NULL )
-return( 0 );
-
- for ( cnt=i=0; maxes[i]!=NULL; ++i )
- if ( !maxes[i]->unused )
- ++cnt;
- if ( cnt==0 )
-return( 0 );
-
- if ( (here=ftell(jstf))<0 )
-return( 0 );
-
- putshort( jstf,cnt );
- for ( i=0; maxes[i]!=NULL; ++i ) if ( !maxes[i]->unused )
- putshort( jstf,0 );
- for ( cnt=i=0; maxes[i]!=NULL; ++i ) if ( !maxes[i]->unused ) {
- if ( (lbase=ftell(jstf))<0 )
-return( 0 );
- fseek(jstf,here+2+2*cnt,SEEK_SET);
- putshort(jstf,lbase-here);
- fseek(jstf,lbase,SEEK_SET);
-
- putshort(jstf,maxes[i]->lookup_type - gpos_start );
- putshort(jstf,maxes[i]->lookup_flags);
-
- for ( scnt=0, sub=maxes[i]->subtables; sub!=NULL; sub=sub->next )
- if ( !sub->unused )
- ++scnt;
- putshort( jstf,scnt );
- for ( j=0; j<scnt; ++j )
- putshort( jstf,0 );
- /* I don't think extension lookups get a MarkAttachmentType, I guess */
- /* that inherits from the parent? */
-
- otf_dumpALookup(jstf, maxes[i], sf, at);
- fseek(jstf,lbase+6,SEEK_SET);
- for ( sub=maxes[i]->subtables; sub!=NULL; sub=sub->next )
- if ( !sub->unused )
- putshort(jstf,sub->subtable_offset-lbase);
- ++cnt;
- }
-
-return( here - base );
-}
-
-void otf_dumpjstf(struct alltabs *at, SplineFont *sf) {
- FILE *jstf;
- int i, cnt, lcnt, offset;
- uint32 here, base;
- Justify *jscript;
- struct jstf_lang *jlang;
-
- if ( sf->justify==NULL )
-return;
-
- SFJstfSort(sf);
- for ( jscript=sf->justify, cnt=0; jscript!=NULL; jscript=jscript->next, ++cnt );
-
- at->jstf = jstf = tmpfile2();
-
- putlong(jstf, 0x00010000 ); /* Version 1 */
- putshort(jstf, cnt ); /* script count */
- for ( jscript=sf->justify; jscript!=NULL; jscript=jscript->next ) {
- putlong(jstf, jscript->script);
- putshort(jstf, 0); /* Come back to this later */
- }
- for ( jscript=sf->justify, cnt=0; jscript!=NULL; jscript=jscript->next, ++cnt ) {
- base = ftell(jstf);
- if ( base>0xffff )
- ff_post_error(_("Failure"),_("Offset in JSTF table is too big. The resultant font will not work."));
- fseek(jstf, 6+6*cnt+4,SEEK_SET);
- putshort(jstf,base);
- fseek(jstf, base, SEEK_SET);
-
- putshort(jstf,0); /* extender glyphs */
- putshort(jstf,0); /* default lang */
- for ( jlang=jscript->langs, lcnt=0; jlang!=NULL; jlang=jlang->next, ++lcnt );
- if ( lcnt>0 && jscript->langs->lang==DEFAULT_LANG )
- --lcnt;
- putshort(jstf,lcnt); /* count of non-default languages */
- jlang = jscript->langs;
- if ( jlang!=NULL && jlang->lang==DEFAULT_LANG )
- jlang=jlang->next;
- for ( ; jlang!=NULL; jlang=jlang->next ) {
- putlong(jstf, jlang->lang);
- putshort(jstf, 0); /* Come back to this later */
- }
-
- if ( jscript->extenders!=NULL ) {
- SplineChar **glyphs;
- int gcnt,g;
-
- here = ftell(jstf);
- fseek(jstf,base,SEEK_SET);
- putshort(jstf,here-base);
- fseek(jstf,here,SEEK_SET);
-
- glyphs = OrderedGlyphsFromNames(sf,jscript->extenders);
- if ( glyphs==NULL )
- gcnt=0;
- else
- for ( gcnt=0; glyphs[gcnt]!=NULL; ++gcnt);
- putshort(jstf,gcnt);
- for ( g=0; g<gcnt; ++g )
- putshort(jstf,glyphs[g]->ttf_glyph);
- free(glyphs);
- }
-
- offset=0;
- for ( jlang=jscript->langs, lcnt=0; jlang!=NULL; jlang=jlang->next, ++lcnt ) {
- here = ftell(jstf);
- if ( jlang->lang==DEFAULT_LANG ) {
- fseek(jstf,base+2,SEEK_SET);
- offset = -6;
- } else
- fseek(jstf,base+offset+10+lcnt*6,SEEK_SET);
- putshort(jstf,here-base);
- fseek(jstf,here,SEEK_SET);
-
- putshort(jstf,jlang->cnt);
- for ( i=0; i<jlang->cnt; ++i )
- putshort(jstf,0);
- for ( i=0; i<jlang->cnt; ++i ) {
- OTLookup **enSUB, **enPOS, **disSUB, **disPOS;
- uint32 enSUBoff, enPOSoff, disSUBoff, disPOSoff, maxOff;
- uint32 pbase;
- pbase = ftell(jstf);
- fseek(jstf,here+2+i*2,SEEK_SET);
- putshort(jstf,pbase-here);
- fseek(jstf,pbase,SEEK_SET);
-
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
- putshort(jstf,0);
-
- jstf_SplitTables(jlang->prios[i].enableShrink,&enSUB,&enPOS);
- jstf_SplitTables(jlang->prios[i].disableShrink,&disSUB,&disPOS);
- enSUBoff = jstf_dumplklist(jstf,enSUB, pbase);
- disSUBoff = jstf_dumplklist(jstf,disSUB,pbase);
- enPOSoff = jstf_dumplklist(jstf,enPOS, pbase);
- disPOSoff = jstf_dumplklist(jstf,disPOS,pbase);
- maxOff = jstf_dumpmaxlookups(jstf,sf,at,jlang->prios[i].maxShrink,pbase);
-
- fseek(jstf,pbase,SEEK_SET);
- putshort(jstf,enSUBoff);
- putshort(jstf,disSUBoff);
- putshort(jstf,enPOSoff);
- putshort(jstf,disPOSoff);
- putshort(jstf,maxOff);
-
- fseek(jstf,0,SEEK_END);
- jstf_SplitTables(jlang->prios[i].enableExtend,&enSUB,&enPOS);
- jstf_SplitTables(jlang->prios[i].disableExtend,&disSUB,&disPOS);
- enSUBoff = jstf_dumplklist(jstf,enSUB, pbase);
- disSUBoff = jstf_dumplklist(jstf,disSUB,pbase);
- enPOSoff = jstf_dumplklist(jstf,enPOS, pbase);
- disPOSoff = jstf_dumplklist(jstf,disPOS,pbase);
- maxOff = jstf_dumpmaxlookups(jstf,sf,at,jlang->prios[i].maxExtend,pbase);
-
- fseek(jstf,pbase+10,SEEK_SET);
- putshort(jstf,enSUBoff);
- putshort(jstf,disSUBoff);
- putshort(jstf,enPOSoff);
- putshort(jstf,disPOSoff);
- putshort(jstf,maxOff);
- fseek(jstf,0,SEEK_END);
- }
- }
- }
-
- fseek(jstf,0,SEEK_END);
- at->jstflen = ftell(jstf);
- if ( ftell(jstf)&1 )
- putc('\0',jstf);
- if ( ftell(jstf)&2 )
- putshort(jstf,0);
-}
-
-void otf_dump_dummydsig(struct alltabs *at, SplineFont *sf) {
- FILE *dsigf;
-
- /* I think the DSIG table is a big crock. At best the most it can do is */
- /* tell you that the font hasn't changed since it was signed. It gives */
- /* no guarantee that the data are reasonable. I think it's stupid. */
- /* I think it is even more stupid that MS choses this useless table as a*/
- /* mark of whether a ttf font is OpenType or not. */
- /* But users want their fonts to show up as OpenType under MS. And I'm */
- /* told an empty DSIG table works for that. So... a truely pointless */
- /* instance of a pointless table. I suppose that's a bit ironic. */
-
- at->dsigf = dsigf = tmpfile2();
- putlong(dsigf,0x00000001); /* Standard version (and why isn't it 0x10000 like everything else?) */
- putshort(dsigf,0); /* No signatures in my signature table*/
- putshort(dsigf,0); /* No flags */
-
- at->dsiglen = ftell(dsigf);
- if ( ftell(dsigf)&1 )
- putc('\0',dsigf);
- if ( ftell(dsigf)&2 )
- putshort(dsigf,0);
-}