EncMap *CompactEncMap(EncMap *map, SplineFont *sf) { int i, inuse, gid; int32 *newmap; for ( i=inuse=0; i<map->enccount ; ++i ) if ( (gid = map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid])) ++inuse; newmap = galloc(inuse*sizeof(int32)); for ( i=inuse=0; i<map->enccount ; ++i ) if ( (gid = map->map[i])!=-1 && SCWorthOutputting(sf->glyphs[gid])) newmap[inuse++] = gid; free(map->map); map->map = newmap; map->enccount = inuse; map->encmax = inuse; map->enc = &custom; memset(map->backmap,-1,sf->glyphcnt*sizeof(int)); for ( i=inuse-1; i>=0; --i ) if ( (gid=map->map[i])!=-1 ) map->backmap[gid] = i; return( map ); }
int ContourPtNumMatch(MMSet *mm, int gid) { SplineFont *sf; int i; if ( !mm->apple ) return( false ); if ( gid>=mm->normal->glyphcnt ) return( false ); if ( !SCWorthOutputting(mm->normal->glyphs[gid] ) ) { for ( i=0; i<mm->instance_count; ++i ) { if ( gid>=mm->instances[i]->glyphcnt ) return( false ); if ( SCWorthOutputting(mm->instances[i]->glyphs[gid])) return( false ); } return( true ); /* None is not worth outputting, and that's ok, they match */ } else { for ( i=0; i<mm->instance_count; ++i ) { if ( gid>=mm->instances[i]->glyphcnt ) return( false ); if ( !SCWorthOutputting(mm->instances[i]->glyphs[gid])) return( false ); } /* All are worth outputting */ } if ( mm->normal->glyphs[gid]->layers[ly_fore].refs!=NULL && mm->normal->glyphs[gid]->layers[ly_fore].splines!=NULL ) return( false ); for ( i=0; i<mm->instance_count; ++i ) { if ( mm->instances[i]->glyphs[gid]->layers[ly_fore].refs!=NULL && mm->instances[i]->glyphs[gid]->layers[ly_fore].splines!=NULL ) return( false ); } if ( mm->normal->glyphs[gid]->layers[ly_fore].refs!=NULL ) { RefChar *r; int cnt, c; for ( r=mm->normal->glyphs[gid]->layers[ly_fore].refs, cnt=0; r!=NULL; r=r->next ) ++cnt; for ( i=0; i<mm->instance_count; ++i ) { for ( r=mm->instances[i]->glyphs[gid]->layers[ly_fore].refs, c=0; r!=NULL; r=r->next ) ++c; if ( c!=cnt ) return( false ); } } sf = NULL; if ( PtNumbersAreSet(mm->normal->glyphs[gid]) ) sf = mm->normal; else { for ( i=0; i<mm->instance_count; ++i ) { if ( PtNumbersAreSet(mm->instances[i]->glyphs[gid])) { sf = mm->instances[i]; break; } } } if ( sf==NULL ) /* No instance has fixed points. Make sure all fonts are consistent */ return( AssignPtNumbers(mm,gid)); if ( sf!=mm->normal && !MatchPoints(sf,mm->normal,gid)) return( false ); for ( i=0; i<mm->instance_count; ++i ) if ( sf!=mm->instances[i] ) { if ( !MatchPoints(sf, mm->instances[i],gid) ) return( false ); } return( true ); }
SplineChar *SCBuildDummy(SplineChar *dummy,SplineFont *sf,EncMap *map,int i) { static char namebuf[100]; static Layer layers[2]; memset(dummy,'\0',sizeof(*dummy)); dummy->color = COLOR_DEFAULT; dummy->layer_cnt = 2; dummy->layers = layers; if ( sf->cidmaster!=NULL ) { /* CID fonts don't have encodings, instead we must look up the cid */ if ( sf->cidmaster->loading_cid_map ) dummy->unicodeenc = -1; else dummy->unicodeenc = CID2NameUni(FindCidMap(sf->cidmaster->cidregistry,sf->cidmaster->ordering,sf->cidmaster->supplement,sf->cidmaster), i,namebuf,sizeof(namebuf)); } else dummy->unicodeenc = UniFromEnc(i,map->enc); if ( sf->cidmaster!=NULL ) dummy->name = namebuf; else if ( map->enc->psnames!=NULL && i<map->enc->char_cnt && map->enc->psnames[i]!=NULL ) dummy->name = map->enc->psnames[i]; else if ( dummy->unicodeenc==-1 ) dummy->name = NULL; else dummy->name = (char *) StdGlyphName(namebuf,dummy->unicodeenc,sf->uni_interp,sf->for_new_glyphs); if ( dummy->name==NULL ) { /*if ( dummy->unicodeenc!=-1 || i<256 ) dummy->name = ".notdef"; else*/ { int j; sprintf( namebuf, "NameMe.%d", i); j=0; while ( SFFindExistingSlot(sf,-1,namebuf)!=-1 ) sprintf( namebuf, "NameMe.%d.%d", i, ++j); dummy->name = namebuf; } } dummy->width = dummy->vwidth = sf->ascent+sf->descent; if ( dummy->unicodeenc>0 && dummy->unicodeenc<0x10000 && iscombining(dummy->unicodeenc)) { /* Mark characters should be 0 width */ dummy->width = 0; /* Except in monospaced fonts on windows, where they should be the */ /* same width as everything else */ } /* Actually, in a monospace font, all glyphs should be the same width */ /* whether mark or not */ if ( sf->pfminfo.panose_set && sf->pfminfo.panose[3]==9 && sf->glyphcnt>0 ) { for ( i=sf->glyphcnt-1; i>=0; --i ) if ( SCWorthOutputting(sf->glyphs[i])) { dummy->width = sf->glyphs[i]->width; break; } } dummy->parent = sf; dummy->orig_pos = 0xffff; return( dummy ); }
int IsntBDFChar(BDFChar *bdfc) { if ( bdfc==NULL ) return( true ); return( !SCWorthOutputting(bdfc->sc)); }
static char *_MMBlendChar(MMSet *mm, int gid) { int i, j, worthit = -1; int all, any, any2, all2, anyend, allend, diff; SplineChar *sc; SplinePointList *spls[MmMax], *spl, *spllast; SplinePoint *tos[MmMax], *to; RefChar *refs[MmMax], *ref, *reflast; KernPair *kp0, *kptest, *kp, *kplast; StemInfo *hs[MmMax], *h, *hlast; real width; for ( i=0; i<mm->instance_count; ++i ) { if ( mm->instances[i]->layers[ly_fore].order2 ) return( _("One of the multiple master instances contains quadratic splines. It must be converted to cubic splines before it can be used in a multiple master") ); if ( gid>=mm->instances[i]->glyphcnt ) return( _("The different instances of this mm have a different number of glyphs") ); if ( SCWorthOutputting(mm->instances[i]->glyphs[gid]) ) { if ( worthit == -1 ) worthit = true; else if ( worthit != true ) return( _("This glyph is defined in one instance font but not in another") ); } else { if ( worthit == -1 ) worthit = false; else if ( worthit != false ) return( _("This glyph is defined in one instance font but not in another") ); } } sc = mm->normal->glyphs[gid]; if ( sc!=NULL ) { SCClearContents(sc,ly_fore); KernPairsFree(sc->kerns); sc->kerns = NULL; KernPairsFree(sc->vkerns); sc->vkerns = NULL; } if ( !worthit ) return( 0 ); if ( sc==NULL ) sc = SFMakeGlyphLike(mm->normal,gid,mm->instances[0]); /* Blend references => blend transformation matrices */ diff = false; any = false; all = true; for ( i=0; i<mm->instance_count; ++i ) { refs[i] = mm->instances[i]->glyphs[gid]->layers[ly_fore].refs; if ( refs[i]!=NULL ) any = true; else all = false; } reflast = NULL; while ( all ) { ref = RefCharCreate(); *ref = *refs[0]; ref->layers[0].splines = NULL; ref->next = NULL; memset(ref->transform,0,sizeof(ref->transform)); ref->sc = mm->normal->glyphs[refs[0]->sc->orig_pos]; for ( i=0; i<mm->instance_count; ++i ) { if ( ref->sc->orig_pos!=refs[i]->sc->orig_pos ) diff = true; for ( j=0; j<6; ++j ) ref->transform[j] += refs[i]->transform[j]*mm->defweights[i]; } if ( reflast==NULL ) sc->layers[ly_fore].refs = ref; else reflast->next = ref; reflast = ref; any = false; all = true; for ( i=0; i<mm->instance_count; ++i ) { refs[i] = refs[i]->next; if ( refs[i]!=NULL ) any = true; else all = false; } } if ( any ) return( _("This glyph contains a different number of references in different instances") ); if ( diff ) return( _("A reference in this glyph refers to a different encoding in different instances") ); /* Blend Width */ width = 0; for ( i=0; i<mm->instance_count; ++i ) width += mm->instances[i]->glyphs[gid]->width*mm->defweights[i]; sc->width = width; width = 0; for ( i=0; i<mm->instance_count; ++i ) width += mm->instances[i]->glyphs[gid]->vwidth*mm->defweights[i]; sc->vwidth = width; /* Blend Splines */ any = false; all = true; for ( i=0; i<mm->instance_count; ++i ) { spls[i] = mm->instances[i]->glyphs[gid]->layers[ly_fore].splines; if ( spls[i]!=NULL ) any = true; else all = false; } spllast = NULL; while ( all ) { spl = chunkalloc(sizeof(SplinePointList)); if ( spllast==NULL ) sc->layers[ly_fore].splines = spl; else spllast->next = spl; spllast = spl; for ( i=0; i<mm->instance_count; ++i ) tos[i] = spls[i]->first; all2 = true; spl->last = NULL; while ( all2 ) { to = chunkalloc(sizeof(SplinePoint)); to->nonextcp = tos[0]->nonextcp; to->noprevcp = tos[0]->noprevcp; to->nextcpdef = tos[0]->nextcpdef; to->prevcpdef = tos[0]->prevcpdef; to->pointtype = tos[0]->pointtype; if ( tos[0]->hintmask!=NULL ) { to->hintmask = chunkalloc(sizeof(HintMask)); memcpy(to->hintmask,tos[0]->hintmask,sizeof(HintMask)); } for ( i=0; i<mm->instance_count; ++i ) { to->me.x += tos[i]->me.x*mm->defweights[i]; to->me.y += tos[i]->me.y*mm->defweights[i]; to->nextcp.x += tos[i]->nextcp.x*mm->defweights[i]; to->nextcp.y += tos[i]->nextcp.y*mm->defweights[i]; to->prevcp.x += tos[i]->prevcp.x*mm->defweights[i]; to->prevcp.y += tos[i]->prevcp.y*mm->defweights[i]; } if ( spl->last==NULL ) spl->first = to; else SplineMake3(spl->last,to); spl->last = to; any2 = false; all2 = true; for ( i=0; i<mm->instance_count; ++i ) { if ( tos[i]->next==NULL ) tos[i] = NULL; else tos[i] = tos[i]->next->to; if ( tos[i]!=NULL ) any2 = true; else all2 = false; } if ( !all2 && any2 ) return( _("A contour in this glyph contains a different number of points in different instances") ); anyend = false; allend = true; for ( i=0; i<mm->instance_count; ++i ) { if ( tos[i]==spls[i]->first ) anyend = true; else allend = false; } if ( allend ) { SplineMake3(spl->last,spl->first); spl->last = spl->first; break; } if ( anyend ) return( _("A contour in this glyph contains a different number of points in different instances") ); } any = false; all = true; for ( i=0; i<mm->instance_count; ++i ) { spls[i] = spls[i]->next; if ( spls[i]!=NULL ) any = true; else all = false; } } if ( any ) return( _("This glyph contains a different number of contours in different instances") ); /* Blend hints */ for ( j=0; j<2; ++j ) { any = false; all = true; for ( i=0; i<mm->instance_count; ++i ) { hs[i] = j ? mm->instances[i]->glyphs[gid]->hstem : mm->instances[i]->glyphs[gid]->vstem; if ( hs[i]!=NULL ) any = true; else all = false; } hlast = NULL; while ( all ) { h = chunkalloc(sizeof(StemInfo)); *h = *hs[0]; h->where = NULL; h->next = NULL; h->start = h->width = 0; for ( i=0; i<mm->instance_count; ++i ) { h->start += hs[i]->start*mm->defweights[i]; h->width += hs[i]->width*mm->defweights[i]; } if ( hlast!=NULL ) hlast->next = h; else if ( j ) sc->hstem = h; else sc->vstem = h; hlast = h; any = false; all = true; for ( i=0; i<mm->instance_count; ++i ) { hs[i] = hs[i]->next; if ( hs[i]!=NULL ) any = true; else all = false; } } if ( any ) return( _("This glyph contains a different number of hints in different instances") ); } /* Blend kernpairs */ /* I'm not requiring ordered kerning pairs */ /* I'm not bothering with vertical kerning */ kp0 = mm->instances[0]->glyphs[gid]->kerns; kplast = NULL; while ( kp0!=NULL ) { int off = kp0->off*mm->defweights[0]; for ( i=1; i<mm->instance_count; ++i ) { for ( kptest=mm->instances[i]->glyphs[gid]->kerns; kptest!=NULL; kptest=kptest->next ) if ( kptest->sc->orig_pos==kp0->sc->orig_pos ) break; if ( kptest==NULL ) return( _("This glyph contains different kerning pairs in different instances") ); off += kptest->off*mm->defweights[i]; } kp = chunkalloc(sizeof(KernPair)); kp->sc = mm->normal->glyphs[kp0->sc->orig_pos]; kp->off = off; kp->subtable = kp0->subtable; if ( kplast!=NULL ) kplast->next = kp; else sc->kerns = kp; kplast = kp; kp0 = kp0->next; } return( 0 ); }