void SSRegenerateFromSpiros(SplineSet *spl) { /* Regenerate an updated SplineSet from SpiroCPs after edits are done. */ if ( spl->spiro_cnt<=1 || !has_spiro ) return; SplineSet *temp = SpiroCP2SplineSet(spl->spiros); if ( temp!=NULL ) { /* Regenerated new SplineSet. Discard old copy. Keep new copy. */ SplineSetBeziersClear(spl); spl->first = temp->first; spl->last = temp->last; chunkfree(temp,sizeof(SplineSet)); } else { /* Didn't converge... or something ...therefore let's fake-it. */ int i; SplinePoint *sp, *first, *last; if ( (last=first=SplinePointCreate(spl->spiros[0].x,spl->spiros[0].y))==NULL ) return; for ( i=1; i<spl->spiro_cnt; ++i ) { if ( (sp=SplinePointCreate(spl->spiros[i].x,spl->spiros[i].y)) ) { SplineMake3(last,sp); last = sp; } else break; /* ...have problem, but keep what we got so far */ } /* dump the prior SplineSet and now show this line-art instead */ SplineSetBeziersClear(spl); spl->first = first; if ( SPIRO_SPL_OPEN(spl)) spl->last = last; else { SplineMake3(last,spl->first); spl->last = spl->first; } } spl->beziers_need_optimizer = true; }
static void bezctx_ff_curveto(bezctx *z, double x1, double y1, double x2, double y2, double x3, double y3) { bezctx_ff *bc = (bezctx_ff *)z; SplinePoint *sp; if ( !finite(x1) || !finite(y1) || !finite(x2) || !finite(y2) || !finite(x3) || !finite(y3)) { nancheck(bc); x1 = y1 = x2 = y2 = x3 = y3 = 0; } sp = SplinePointCreate(x3,y3); bc->ss->last->nextcp.x = x1; bc->ss->last->nextcp.y = y1; bc->ss->last->nonextcp = false; sp->prevcp.x = x2; sp->prevcp.y = y2; sp->noprevcp = false; SplineMake3(bc->ss->last,sp); bc->ss->last = sp; }
/* Finishes an old FontAnvil bezier context, and returns the contour which was created */ struct splinepointlist *bezctx_ff_close(bezctx * z) { bezctx_ff *bc=(bezctx_ff *) z; SplineSet *ss=bc->ss; if (!bc->is_open && ss != NULL) { if (ss->first != ss->last && RealNear(ss->first->me.x, ss->last->me.x) && RealNear(ss->first->me.y, ss->last->me.y)) { ss->first->prevcp=ss->last->prevcp; ss->first->noprevcp=ss->last->noprevcp; ss->first->prev=ss->last->prev; ss->first->prev->to=ss->first; SplinePointFree(ss->last); ss->last=ss->first; } else { if (SplineMake3(ss->last, ss->first) != NULL) ss->last=ss->first; } } free(bc); return (ss); }
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 ); }