diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/fvfonts.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/fvfonts.c | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/fvfonts.c b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/fvfonts.c new file mode 100644 index 00000000000..db709cea56e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/fvfonts.c @@ -0,0 +1,572 @@ +/* Copyright (C) 2000-2008 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 "ustring.h" +#include "utype.h" +#include "gfile.h" +#include "chardata.h" + +RefChar *RefCharsCopy(RefChar *ref) { + RefChar *rhead=NULL, *last=NULL, *cur; + + while ( ref!=NULL ) { + cur = RefCharCreate(); +#ifdef FONTFORGE_CONFIG_TYPE3 + { struct reflayer *layers = cur->layers; int layer; + layers = grealloc(layers,ref->layer_cnt*sizeof(struct reflayer)); + memcpy(layers,ref->layers,ref->layer_cnt*sizeof(struct reflayer)); + *cur = *ref; + cur->layers = layers; + for ( layer=0; layer<cur->layer_cnt; ++layer ) { + cur->layers[layer].splines = NULL; + cur->layers[layer].images = NULL; + } + } +#else + {struct reflayer *rl = cur->layers; + *cur = *ref; + cur->layers = rl; + } +#endif + if ( cur->sc!=NULL ) + cur->orig_pos = cur->sc->orig_pos; + cur->next = NULL; + if ( rhead==NULL ) + rhead = cur; + else + last->next = cur; + last = cur; + ref = ref->next; + } +return( rhead ); +} + +static OTLookup *MCConvertLookup(struct sfmergecontext *mc,OTLookup *otl) { + int l; + OTLookup *newotl; + + if ( mc==NULL || mc->sf_from==mc->sf_to ) +return( otl ); /* No translation needed */ + + for ( l=0; l<mc->lcnt; ++l ) { + if ( mc->lks[l].from == otl ) + break; + } + if ( l==mc->lcnt ) +return( NULL ); + if ( mc->lks[l].to!=NULL ) +return( mc->lks[l].to ); + + mc->lks[l].to = newotl = chunkalloc(sizeof(struct lookup_subtable)); + newotl->lookup_name = strconcat(mc->prefix,otl->lookup_name); + newotl->lookup_type = otl->lookup_type; + newotl->lookup_flags = otl->lookup_flags; + newotl->features = FeatureListCopy(otl->features); + newotl->store_in_afm = otl->store_in_afm; +return( newotl ); +} + +struct lookup_subtable *MCConvertSubtable(struct sfmergecontext *mc,struct lookup_subtable *sub) { + int s; + struct lookup_subtable *newsub; + + if ( mc==NULL || mc->sf_from==mc->sf_to ) +return( sub ); /* No translation needed */ + if ( mc->prefix==NULL ) { + int lcnt, scnt; + OTLookup *otl; + struct lookup_subtable *subs; + int isgpos, doit; + char *temp; + + /* Not initialized */ + if ( mc->sf_from->cidmaster ) mc->sf_from = mc->sf_from->cidmaster; + else if ( mc->sf_from->mm!=NULL ) mc->sf_from = mc->sf_from->mm->normal; + if ( mc->sf_to->cidmaster ) mc->sf_to = mc->sf_to->cidmaster; + else if ( mc->sf_to->mm!=NULL ) mc->sf_to = mc->sf_to->mm->normal; + if ( mc->sf_from == mc->sf_to ) +return( sub ); + mc->prefix = strconcat(mc->sf_from->fontname,"-"); + for ( doit = 0; doit<2; ++doit ) { + lcnt = scnt = 0; + for ( isgpos=0; isgpos<2; ++isgpos ) { + for ( otl = isgpos ? mc->sf_from->gpos_lookups : mc->sf_from->gsub_lookups; otl!=NULL; otl=otl->next ) { + if ( doit ) { + mc->lks[lcnt].from = otl; + temp = strconcat(mc->prefix,otl->lookup_name); + mc->lks[lcnt].to = SFFindLookup(mc->sf_to,temp); + free(temp); + mc->lks[lcnt].old = mc->lks[lcnt].to!=NULL; + } + ++lcnt; + for ( subs=otl->subtables; subs!=NULL; subs=subs->next ) { + if ( doit ) { + mc->subs[scnt].from = subs; + temp = strconcat(mc->prefix,subs->subtable_name); + mc->subs[scnt].to = SFFindLookupSubtable(mc->sf_to,temp); + free(temp); + mc->subs[scnt].old = mc->subs[scnt].to!=NULL; + } + ++scnt; + } + } + } + if ( !doit ) { + mc->lcnt = lcnt; mc->scnt = scnt; + mc->lks = gcalloc(lcnt,sizeof(struct lookup_cvt)); + mc->subs = gcalloc(scnt,sizeof(struct sub_cvt)); + } + } + } + + for ( s=0; s<mc->scnt; ++s ) { + if ( mc->subs[s].from == sub ) + break; + } + if ( s==mc->scnt ) +return( NULL ); + if ( mc->subs[s].to!=NULL ) +return( mc->subs[s].to ); + + mc->subs[s].to = newsub = chunkalloc(sizeof(struct lookup_subtable)); + newsub->subtable_name = strconcat(mc->prefix,sub->subtable_name); + newsub->lookup = MCConvertLookup(mc,sub->lookup); + newsub->anchor_classes = sub->anchor_classes; + newsub->per_glyph_pst_or_kern = sub->per_glyph_pst_or_kern; +return( newsub ); +} + +PST *PSTCopy(PST *base,SplineChar *sc,struct sfmergecontext *mc) { + PST *head=NULL, *last=NULL, *cur; + + for ( ; base!=NULL; base = base->next ) { + cur = chunkalloc(sizeof(PST)); + *cur = *base; + cur->subtable = MCConvertSubtable(mc,base->subtable); + if ( cur->type==pst_ligature ) { + cur->u.lig.components = copy(cur->u.lig.components); + cur->u.lig.lig = sc; + } else if ( cur->type==pst_pair ) { + cur->u.pair.paired = copy(cur->u.pair.paired); + cur->u.pair.vr = chunkalloc(sizeof( struct vr [2])); + memcpy(cur->u.pair.vr,base->u.pair.vr,sizeof(struct vr [2])); + } else if ( cur->type==pst_lcaret ) { + cur->u.lcaret.carets = galloc(cur->u.lcaret.cnt*sizeof(uint16)); + memcpy(cur->u.lcaret.carets,base->u.lcaret.carets,cur->u.lcaret.cnt*sizeof(uint16)); + } else if ( cur->type==pst_substitution || cur->type==pst_multiple || cur->type==pst_alternate ) + cur->u.subs.variant = copy(cur->u.subs.variant); + if ( head==NULL ) + head = cur; + else + last->next = cur; + last = cur; + } +return( head ); +} + +static AnchorPoint *AnchorPointsDuplicate(AnchorPoint *base,SplineChar *sc) { + AnchorPoint *head=NULL, *last=NULL, *cur; + AnchorClass *ac; + + for ( ; base!=NULL; base = base->next ) { + cur = chunkalloc(sizeof(AnchorPoint)); + *cur = *base; + cur->next = NULL; + for ( ac=sc->parent->anchor; ac!=NULL; ac=ac->next ) + if ( strcmp(ac->name,base->anchor->name)==0 ) + break; + cur->anchor = ac; + if ( ac==NULL ) { + LogError( "No matching AnchorClass for %s", base->anchor->name); + chunkfree(cur,sizeof(AnchorPoint)); + } else { + if ( head==NULL ) + head = cur; + else + last->next = cur; + last = cur; + } + } +return( head ); +} + +static struct altuni *AltUniCopy(struct altuni *altuni,SplineFont *noconflicts) { + struct altuni *head=NULL, *last=NULL, *cur; + + while ( altuni!=NULL ) { + if ( noconflicts==NULL || SFGetChar(noconflicts,altuni->unienc,NULL)==NULL ) { + cur = chunkalloc(sizeof(struct altuni)); + cur->unienc = altuni->unienc; + cur->vs = altuni->vs; + cur->fid = altuni->fid; + if ( head==NULL ) + head = cur; + else + last->next = cur; + last = cur; + } + altuni = altuni->next; + } +return( head ); +} + +SplineChar *SplineCharCopy(SplineChar *sc,SplineFont *into,struct sfmergecontext *mc) { + SplineChar *nsc; + Layer *layers; + int layer; + if (into==NULL) { + nsc = SplineCharCreate(2); + } else { + nsc = SFSplineCharCreate(into); + } + layers = nsc->layers; + *nsc = *sc; /* We copy the layers just below */ + if (into==NULL || sc->layer_cnt!=into->layer_cnt ) + layers = grealloc(layers,sc->layer_cnt*sizeof(Layer)); + memcpy(layers,sc->layers,sc->layer_cnt*sizeof(Layer)); + nsc->layers = layers; + for ( layer = ly_back; layer<sc->layer_cnt; ++layer ) { + layers[layer].splines = SplinePointListCopy(layers[layer].splines); + layers[layer].refs = RefCharsCopy(layers[layer].refs); + layers[layer].images = ImageListCopy(layers[layer].images); + layers[layer].undoes = NULL; + layers[layer].redoes = NULL; + } + nsc->parent = into; + nsc->orig_pos = -2; + nsc->name = copy(sc->name); + nsc->hstem = StemInfoCopy(nsc->hstem); + nsc->vstem = StemInfoCopy(nsc->vstem); + nsc->anchor = AnchorPointsDuplicate(nsc->anchor,nsc); + nsc->views = NULL; + nsc->changed = true; + nsc->dependents = NULL; /* Fix up later when we know more */ + nsc->layers[ly_fore].undoes = nsc->layers[ly_back].undoes = NULL; + nsc->layers[ly_fore].redoes = nsc->layers[ly_back].redoes = NULL; + if ( nsc->ttf_instrs_len!=0 ) { + nsc->ttf_instrs = galloc(nsc->ttf_instrs_len); + memcpy(nsc->ttf_instrs,sc->ttf_instrs,nsc->ttf_instrs_len); + } + nsc->kerns = NULL; + nsc->possub = PSTCopy(nsc->possub,nsc,mc); + nsc->altuni = AltUniCopy(nsc->altuni,into); +return(nsc); +} + +static int _SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ); + + +#define GN_HSIZE 257 + +struct glyphnamebucket { + SplineChar *sc; + struct glyphnamebucket *next; +}; + +struct glyphnamehash { + struct glyphnamebucket *table[GN_HSIZE]; +}; + +#ifndef __GNUC__ +# define __inline__ +#endif + +static __inline__ int hashname(const char *pt) { + int val = 0; + + while ( *pt ) { + val = (val<<3)|((val>>29)&0x7); + val ^= (unsigned char)(*pt-'!'); + pt++; + } + val ^= (val>>16); + val &= 0xffff; + val %= GN_HSIZE; +return( val ); +} + +static void _GlyphHashFree(SplineFont *sf) { + struct glyphnamebucket *test, *next; + int i; + + if ( sf->glyphnames==NULL ) +return; + for ( i=0; i<GN_HSIZE; ++i ) { + for ( test = sf->glyphnames->table[i]; test!=NULL; test = next ) { + next = test->next; + chunkfree(test,sizeof(struct glyphnamebucket)); + } + } + free(sf->glyphnames); + sf->glyphnames = NULL; +} + +void GlyphHashFree(SplineFont *sf) { + _GlyphHashFree(sf); + if ( sf->cidmaster ) + _GlyphHashFree(sf->cidmaster); +} + +static void GlyphHashCreate(SplineFont *sf) { + int i, k, hash; + SplineFont *_sf; + struct glyphnamehash *gnh; + struct glyphnamebucket *new; + + if ( sf->glyphnames!=NULL ) +return; + sf->glyphnames = gnh = gcalloc(1,sizeof(*gnh)); + k = 0; + do { + _sf = k<sf->subfontcnt ? sf->subfonts[k] : sf; + /* I walk backwards because there are some ttf files where multiple */ + /* glyphs get the same name. In the cases I've seen only one of these */ + /* has an encoding. That's the one we want. It will be earlier in the */ + /* font than the others. If we build the list backwards then it will */ + /* be the top name in the bucket, and will be the one we return */ + for ( i=_sf->glyphcnt-1; i>=0; --i ) if ( _sf->glyphs[i]!=NULL ) { + new = chunkalloc(sizeof(struct glyphnamebucket)); + new->sc = _sf->glyphs[i]; + hash = hashname(new->sc->name); + new->next = gnh->table[hash]; + gnh->table[hash] = new; + } + ++k; + } while ( k<sf->subfontcnt ); +} + +void SFHashGlyph(SplineFont *sf,SplineChar *sc) { + /* sc just got added to the font. Put it in the lookup */ + int hash; + struct glyphnamebucket *new; + + if ( sf->glyphnames==NULL ) +return; /* No hash table, nothing to update */ + + new = chunkalloc(sizeof(struct glyphnamebucket)); + new->sc = sc; + hash = hashname(sc->name); + new->next = sf->glyphnames->table[hash]; + sf->glyphnames->table[hash] = new; +} + +SplineChar *SFHashName(SplineFont *sf,const char *name) { + struct glyphnamebucket *test; + + if ( sf->glyphnames==NULL ) + GlyphHashCreate(sf); + + for ( test=sf->glyphnames->table[hashname(name)]; test!=NULL; test = test->next ) + if ( strcmp(test->sc->name,name)==0 ) +return( test->sc ); + +return( NULL ); +} + +/* Find the position in the glyph list where this code point/name is found. */ +/* Returns -1 else on error */ +int SFFindGID(SplineFont *sf, int unienc, const char *name ) { + struct altuni *altuni; + int gid; + SplineChar *sc; + + if ( unienc!=-1 ) { + for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( sf->glyphs[gid]!=NULL ) { + if ( sf->glyphs[gid]->unicodeenc == unienc ) +return( gid ); + for ( altuni = sf->glyphs[gid]->altuni; altuni!=NULL; altuni=altuni->next ) { + if ( altuni->unienc == unienc && altuni->vs==-1 && altuni->fid==0 ) +return( gid ); + } + } + } + if ( name!=NULL ) { + sc = SFHashName(sf,name); + if ( sc!=NULL ) +return( sc->orig_pos ); + } + +return ( -1 ); +} + +/* Find the position in the current encoding where this code point/name should*/ +/* be found. (or for unencoded glyphs where it is found). Returns -1 else */ +int SFFindSlot(SplineFont *sf, EncMap *map, int unienc, const char *name ) { + int index=-1, pos; + struct cidmap *cidmap; + + if ( sf->cidmaster!=NULL && !map->enc->is_compact && + (cidmap = FindCidMap(sf->cidmaster->cidregistry, + sf->cidmaster->ordering, + sf->cidmaster->supplement, + sf->cidmaster))!=NULL ) + index = NameUni2CID(cidmap,unienc,name); + if ( index!=-1 ) + /* All done */; + else if ( (map->enc->is_custom || map->enc->is_compact || + map->enc->is_original) && unienc!=-1 ) { + if ( unienc<map->enccount && map->map[unienc]!=-1 && + sf->glyphs[map->map[unienc]]!=NULL && + sf->glyphs[map->map[unienc]]->unicodeenc==unienc ) + index = unienc; + else for ( index = map->enccount-1; index>=0; --index ) { + if ( (pos = map->map[index])!=-1 && sf->glyphs[pos]!=NULL && + sf->glyphs[pos]->unicodeenc==unienc ) + break; + } + } else if ( unienc!=-1 && + ((unienc<0x10000 && map->enc->is_unicodebmp) || + (unienc<0x110000 && map->enc->is_unicodefull))) { + index = unienc; + } else if ( unienc!=-1 ) { + index = EncFromUni(unienc,map->enc); + if ( index<0 || index>=map->enccount ) { + for ( index=map->enc->char_cnt; index<map->enccount; ++index ) + if ( (pos = map->map[index])!=-1 && sf->glyphs[pos]!=NULL && + sf->glyphs[pos]->unicodeenc==unienc ) + break; + if ( index>=map->enccount ) + index = -1; + } + } + if ( index==-1 && name!=NULL ) { + SplineChar *sc = SFHashName(sf,name); + if ( sc!=NULL ) index = map->backmap[sc->orig_pos]; + if ( index==-1 ) { + unienc = UniFromName(name,sf->uni_interp,map->enc); + if ( unienc!=-1 ) +return( SFFindSlot(sf,map,unienc,NULL)); + if ( map->enc->psnames!=NULL ) { + for ( index = map->enc->char_cnt-1; index>=0; --index ) + if ( map->enc->psnames[index]!=NULL && + strcmp(map->enc->psnames[index],name)==0 ) +return( index ); + } + } + } + +return( index ); +} + +int SFCIDFindCID(SplineFont *sf, int unienc, const char *name ) { + int j,ret; + struct cidmap *cidmap; + + if ( sf->cidmaster!=NULL || sf->subfontcnt!=0 ) { + if ( sf->cidmaster!=NULL ) + sf=sf->cidmaster; + cidmap = FindCidMap(sf->cidregistry,sf->ordering,sf->supplement,sf); + ret = NameUni2CID(cidmap,unienc,name); + if ( ret!=-1 ) +return( ret ); + } + + if ( sf->subfonts==NULL && sf->cidmaster==NULL ) +return( SFFindGID(sf,unienc,name)); + + if ( sf->cidmaster!=NULL ) + sf=sf->cidmaster; + for ( j=0; j<sf->subfontcnt; ++j ) + if (( ret = SFFindGID(sf,unienc,name))!=-1 ) +return( ret ); + +return( -1 ); +} + +int SFHasCID(SplineFont *sf,int cid) { + int i; + /* What subfont (if any) contains this cid? */ + if ( sf->cidmaster!=NULL ) + sf=sf->cidmaster; + for ( i=0; i<sf->subfontcnt; ++i ) + if ( cid<sf->subfonts[i]->glyphcnt && + SCWorthOutputting(sf->subfonts[i]->glyphs[cid]) ) +return( i ); + for ( i=0; i<sf->subfontcnt; ++i ) + if ( cid<sf->subfonts[i]->glyphcnt && sf->subfonts[i]->glyphs[cid]!=NULL ) +return( i ); + +return( -1 ); +} + +SplineChar *SFGetChar(SplineFont *sf, int unienc, const char *name ) { + int ind; + int j; + + ind = SFCIDFindCID(sf,unienc,name); + if ( ind==-1 ) +return( NULL ); + + if ( sf->subfonts==NULL && sf->cidmaster==NULL ) +return( sf->glyphs[ind]); + + if ( sf->cidmaster!=NULL ) + sf=sf->cidmaster; + + j = SFHasCID(sf,ind); + if ( j==-1 ) +return( NULL ); + +return( sf->subfonts[j]->glyphs[ind] ); +} + +static int _SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) { + int gid = -1; + struct altuni *altuni; + + if ( unienc!=-1 ) { + for ( gid=sf->glyphcnt-1; gid>=0; --gid ) if ( sf->glyphs[gid]!=NULL ) { + if ( sf->glyphs[gid]->unicodeenc==unienc ) + break; + for ( altuni=sf->glyphs[gid]->altuni ; altuni!=NULL && + (altuni->unienc!=unienc || altuni->vs!=-1 || altuni->fid!=0); + altuni=altuni->next ); + if ( altuni!=NULL ) + break; + } + } + if ( gid==-1 && name!=NULL ) { + SplineChar *sc = SFHashName(sf,name); + if ( sc==NULL ) +return( -1 ); + gid = sc->orig_pos; + if ( gid<0 || gid>=sf->glyphcnt ) { + IError("Invalid glyph location when searching for %s", name ); +return( -1 ); + } + } +return( gid ); +} + +int SFFindExistingSlot(SplineFont *sf, int unienc, const char *name ) { + int gid = _SFFindExistingSlot(sf,unienc,name); + + if ( gid==-1 || !SCWorthOutputting(sf->glyphs[gid]) ) +return( -1 ); + +return( gid ); +} |