static FeatureScriptLangList *FeaturesFromTagSli(uint32_t tag,int sli, SplineFont1*sf) { FeatureScriptLangList *fl; struct script_record *sr; struct scriptlanglist *cur, *last; int i; fl=chunkalloc(sizeof(FeatureScriptLangList)); fl->featuretag=tag; if (sli==SLI_NESTED || sli<0 || sli >= sf->sli_cnt) return (fl); last=NULL; for (sr=sf->script_lang[sli]; sr->script != 0; ++sr) { cur=chunkalloc(sizeof(struct scriptlanglist)); cur->script=sr->script; for (i=0; sr->langs[i] != 0; ++i); cur->lang_cnt=i; if (i>MAX_LANG) cur->morelangs=malloc((i-MAX_LANG)*sizeof(uint32_t)); for (i=0; sr->langs[i] != 0; ++i) { if (i<MAX_LANG) cur->langs[i]=sr->langs[i]; else cur->morelangs[i-MAX_LANG]=sr->langs[i]; } if (last==NULL) fl->scripts=cur; else last->next=cur; last=cur; } return (fl); }
void AW_AutoKern(WidthInfo *wi) { struct charpair *cp; SplineChar *lsc, *rsc; int i, diff; KernPair *kp; for ( i=0; i<wi->pcnt; ++i ) { cp = wi->pairs[i]; diff = rint( wi->spacing-(cp->left->sc->width-cp->left->rmax+cp->right->lbearing+cp->visual)); if ( wi->threshold!=0 && diff>-wi->threshold && diff<wi->threshold ) diff = 0; if ( wi->onlynegkerns && diff>0 ) diff = 0; lsc = cp->left->sc; rsc = cp->right->sc; for ( kp = lsc->kerns; kp!=NULL && kp->sc!=rsc; kp = kp->next ); if ( kp!=NULL ) { if ( kp->off!=diff ) { kp->off = diff; wi->sf->changed = true; } } else if ( diff!=0 ) { kp = chunkalloc(sizeof(KernPair)); kp->sc = rsc; kp->off = diff; kp->subtable = wi->subtable; kp->next = lsc->kerns; lsc->kerns = kp; wi->sf->changed = true; } } MVReKernAll(wi->fv->sf); }
static int JSTF_Script_OK(GGadget *g, GEvent *e) { if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) { Jstf_Dlg *jd = GDrawGetUserData(GGadgetGetWindow(g)); SplineFont *sf = jd->sf; Justify *head=NULL, *last=NULL, *cur; int rows, i; int cols = GMatrixEditGetColCnt(GWidgetGetControl(jd->gw,CID_Scripts)); struct matrix_data *strings = GMatrixEditGet(GWidgetGetControl(jd->gw,CID_Scripts), &rows); for ( i=0; i<rows; ++i ) { cur = chunkalloc(sizeof(Justify)); cur->script = Str2Tag(strings[cols*i+0].u.md_str); cur->extenders = copy(strings[cols*i+1].u.md_str); cur->langs = strings[cols*i+3].u.md_addr; if ( head==NULL ) head = cur; else last->next = cur; last = cur; } JustifyFree(sf->justify); sf->justify = head; jd->done = true; } return( true ); }
static void IkarusAddContour(SplineChar *sc,int npts,BasePoint *bps, uint8 *ptype, int nesting) { SplinePointList *spl; SplinePoint *last, *next; int i, cw; spl = chunkalloc(sizeof(SplinePointList)); spl->next = sc->layers[ly_fore].splines; sc->layers[ly_fore].splines = spl; spl->first = spl->last = last = SplinePointCreate(bps[0].x,bps[0].y); last->pointtype = ptype[npts-1]; last->nextcpdef = last->prevcpdef = true; for ( i=1; i<npts-1; ++i ) { next = SplinePointCreate(bps[i].x,bps[i].y); next->nextcpdef = next->prevcpdef = true; next->pointtype = ptype[i]; SplineMake3(last,next); last = next; } SplineMake3(last,spl->last); last = spl->first; for ( i=1; i<npts; ++i ) { SplineCharDefaultPrevCP(last); SplineCharDefaultNextCP(last); last=last->next->to; } cw = SplinePointListIsClockwise(spl)==1; if ( ((nesting&1) && cw) || (!(nesting&1) && !cw) ) SplineSetReverse(spl); }
static OTLookup *CreateLookup(SplineFont1 *sf,uint32_t tag,int sli, int flags, enum possub_type type) { OTLookup *otl=chunkalloc(sizeof(OTLookup)); otl->lookup_type = type==pst_position?gpos_single : type==pst_pair?gpos_pair : type==pst_contextpos?gpos_context : type==pst_chainpos?gpos_contextchain : type==pst_substitution?gsub_single : type==pst_alternate?gsub_alternate : type==pst_multiple?gsub_multiple : type==pst_ligature?gsub_ligature : type==pst_contextsub?gsub_context : type==pst_chainsub?gsub_contextchain:ot_undef; if (otl->lookup_type==ot_undef) ErrorMsg(2,"Unknown lookup type\n"); otl->next=sf->sf.gsplookups[(otl->lookup_type<gpos_single)?0:1]; sf->sf.gsplookups[(otl->lookup_type<gpos_single)?0:1]=otl; otl->lookup_flags=flags; otl->features=FeaturesFromTagSli(tag, sli, sf); /* We will set the lookup_index after we've ordered the list */ /* We will set the lookup_name after we've assigned the index */ /* We will add subtables as we need them */ return (otl); }
static struct lookup_subtable *CreateSubtable(OTLookup *otl, SplineFont1*sf) { struct lookup_subtable *cur, *prev; cur=chunkalloc(sizeof(struct lookup_subtable)); if (otl->subtables==NULL) otl->subtables=cur; else { for (prev=otl->subtables; prev->next != NULL; prev=prev->next); prev->next=cur; } cur->lookup=otl; if (otl->lookup_type==gsub_single || otl->lookup_type==gsub_multiple || otl->lookup_type==gsub_alternate || otl->lookup_type==gsub_ligature || otl->lookup_type==gpos_single || otl->lookup_type==gpos_pair) cur->per_glyph_pst_or_kern=true; else if (otl->lookup_type==gpos_cursive || otl->lookup_type==gpos_mark2base || otl->lookup_type==gpos_mark2ligature || otl->lookup_type==gpos_mark2mark) cur->anchor_classes=true; if (otl->lookup_type==gpos_pair) { if (otl->features != NULL && otl->features->featuretag==CHR('v', 'k', 'r', 'n')) cur->vertical_kerning=true; } return (cur); }
static OTLookup *CreateMacLookup(SplineFont1 *sf,ASM1 *sm) { OTLookup *otl=chunkalloc(sizeof(OTLookup)); int i, ch; char *pt, *start; SplineChar *sc; otl->features=chunkalloc(sizeof(FeatureScriptLangList)); if (sm->sm.type==asm_kern) { otl->lookup_type=kern_statemachine; otl->next=sf->sf.gsplookups[1]; sf->sf.gsplookups[1]=otl; otl->features->featuretag = (sm->sm.flags&0x8000)?CHR('v', 'k', 'r', 'n'):CHR('k', 'e', 'r', 'n'); } else { otl->lookup_type = sm->sm.type==asm_indic?morx_indic:sm->sm.type == asm_context?morx_context:morx_insert; otl->next=sf->sf.gsplookups[0]; sf->sf.gsplookups[0]=otl; otl->features->featuretag=(sm->feature << 16)|(sm->setting); otl->features->ismac=true; } otl->lookup_flags=0; for (i=4; i<sm->sm.class_cnt; ++i) { for (start=sm->sm.classes[i];; start=pt) { while (*start==' ') ++start; if (*start=='\0') break; for (pt=start; *pt != '\0' && *pt != ' '; ++pt); ch=*pt; *pt='\0'; sc=SFGetChar(&sf->sf, -1, start); if (sc != NULL) FListAppendScriptLang(otl->features, SCScriptFromUnicode(sc), DEFAULT_LANG); *pt=ch; } } /* We will set the lookup_index after we've ordered the list */ /* We will set the lookup_name after we've assigned the index */ /* We will add one subtable soon */ return (otl); }
void DelayEvent(void (*func)(void *), void *data) { struct delayed_event *info = chunkalloc(sizeof(struct delayed_event)); info->data = data; info->func = func; gtk_timeout_add(100,DoDelayedEvents,info); }
/* * 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 "pfaeditui.h" #include <math.h> #if defined(KNIFE_CONTINUOUS) /* Use this code to do cuts as we move along. Probably a bad idea, let's wait till the end */ static void ProcessKnife(CharView *cv, PressedOn *p) { real dx, dy; SplinePoint *n; /* If we've already made a cut, don't make another cut too close to it */ /* ie. if the hand shakes over a cut let's not get about six tiny cut */ /* segments adjacent to one another */ if ( (dx=cv->info.x-cv->lastknife.x)<0 ) dx=-dx; if ( (dy=cv->info.y-cv->lastknife.y)<0 ) dy=-dy; if ( (dx+dy)/cv->scale <= 6 ) return; if ( p->sp==NULL && p->spline==NULL ) return; /* Nothing to cut */ if ( p->spline!=NULL ) p->sp = SplineBisect(p->spline,p->t); if ( p->spl==NULL ) /* Kanou says this can happen. It doesn't hurt to check for it */ return; if ( p->spl->first!=p->spl->last ) if ( p->sp==p->spl->first || p->sp==p->spl->last ) return; /* Already cut here */ n = chunkalloc(sizeof(SplinePoint)); p->sp->pointtype = pt_corner; *n = *p->sp; n->hintmask = NULL; p->sp->next = NULL; n->prev = NULL; n->next->from = n; if ( p->spl->first==p->spl->last ) { p->spl->first = n; p->spl->last = p->sp; } else { SplinePointList *nspl = chunkalloc(sizeof(SplinePointList)); nspl->next = p->spl->next; p->spl->next = nspl; nspl->first = n; nspl->last = p->spl->last; p->spl->last = p->sp; } cv->lastknife.x = cv->info.x; cv->lastknife.y = cv->info.y; CVSetCharChanged(cv,true); SCUpdateAll(cv->b.sc); }
SplineSet *SpiroCP2SplineSet(spiro_cp *spiros) { int n; int any = 0; spiro_cp *nspiros; SplineSet *ss; int lastty = 0; if ( spiros==NULL ) return( NULL ); for ( n=0; spiros[n].ty!=SPIRO_END; ++n ) if ( SPIRO_SELECTED(&spiros[n]) ) ++any; if ( n==0 ) return( NULL ); if ( n==1 ) { ss = chunkalloc(sizeof(SplineSet)); ss->first = ss->last = SplinePointCreate(spiros[0].x,spiros[0].y); } else { bezctx *bc = new_bezctx_ff(); if ( (spiros[0].ty&0x7f)=='{' ) { lastty = spiros[n-1].ty; spiros[n-1].ty = '}'; } if ( !any ) { #if _LIBSPIRO_FUN if ( TaggedSpiroCPsToBezier0(spiros,bc)==0 ) { return( NULL ); } #else TaggedSpiroCPsToBezier(spiros,bc); #endif } else { nspiros = galloc((n+1)*sizeof(spiro_cp)); memcpy(nspiros,spiros,(n+1)*sizeof(spiro_cp)); for ( n=0; nspiros[n].ty!=SPIRO_END; ++n ) nspiros[n].ty &= ~0x80; #if _LIBSPIRO_FUN if ( TaggedSpiroCPsToBezier0(nspiros,bc)==0 ) { free(nspiros); return( NULL ); } #else TaggedSpiroCPsToBezier(nspiros,bc); #endif free(nspiros); } ss = bezctx_ff_close(bc); if ( (spiros[0].ty&0x7f)=='{' ) spiros[n-1].ty = lastty; } ss->spiros = spiros; ss->spiro_cnt = ss->spiro_max = n+1; SPLCatagorizePoints(ss); return( ss ); }
static Group *_LoadGroupList(FILE *file, Group *parent, int expected_indent, struct gcontext *gc) { Group *g; char *n; int i, ch; Group **glist=NULL; int gmax = 0; if ( expected_indent!=gc->found_indent ) return( NULL ); n = loadString(file,gc); if ( n==NULL ) return( NULL ); g = chunkalloc(sizeof(Group)); g->parent = parent; g->name = n; if ( (ch = getc(file))==':' ) ch = getc(file); while ( ch==' ' ) ch = getc(file); if ( ch=='1' ) g->unique = true; else if ( ch!='0' ) { GroupFree(g); return( NULL ); } while ( (ch = getc(file))==' ' ); if ( ch=='"' ) { ungetc(ch,file); g->glyphs = loadString(file,gc); if ( g->glyphs==NULL ) { GroupFree(g); return( NULL ); } lineCountIndent(file,gc); } else if ( ch=='\n' || ch=='\r' ) { ungetc(ch,file); lineCountIndent(file,gc); for ( i=0 ;; ++i ) { if ( i>=gmax ) { gmax += 10; glist = realloc(glist,gmax*sizeof(Group *)); } glist[i] = _LoadGroupList(file, g, expected_indent+1, gc); if ( glist[i]==NULL ) break; } g->kid_cnt = i; if ( i!=0 ) { g->kids = malloc(i*sizeof(Group *)); memcpy(g->kids,glist,i*sizeof(Group *)); free(glist); } } return( g ); }
SFUndoes* SFUndoCreateSFD( enum sfundotype t, char* staticmsg, char* sfdfrag ) { SFUndoes* undo = chunkalloc(sizeof(SFUndoes)); undo->ln.next = 0; undo->ln.prev = 0; undo->msg = staticmsg; undo->type = t; undo->sfdchunk = sfdfrag; return undo; }
static void ACDisassociateLigatures(SplineFont1 *sf,AnchorClass1 *ac) { int gid, k; SplineFont1 *subsf; SplineChar *sc; AnchorPoint *ap, *lap; AnchorClass1 *lac; char *format; lac=chunkalloc(sizeof(AnchorClass1)); *lac=*ac; lac->ac.type=act_mklg; ac->ac.next=(AnchorClass *) lac; /* GT: Need to split some AnchorClasses into two classes, one for normal */ /* GT: base letters, and one for ligatures. So create a new AnchorClass */ /* GT: name for the ligature version */ format="Ligature %s"; lac->ac.name=malloc(strlen(ac->ac.name)+strlen(format)+1); sprintf(lac->ac.name, format, ac->ac.name); k=0; do { subsf = sf->sf.subfontcnt==0?sf:(SplineFont1 *) (sf->sf.subfonts[k]); for (gid=0; gid<subsf->sf.glyphcnt; ++gid) if ((sc=subsf->sf.glyphs[gid]) != NULL) { for (ap=sc->anchor; ap != NULL; ap=ap->next) { if (ap->anchor != (AnchorClass *) ac) continue; if (ap->type==at_mark) { lap=chunkalloc(sizeof(AnchorPoint)); *lap=*ap; ap->next=lap; lap->anchor=(AnchorClass *) lac; } else if (ap->type==at_baselig) { ap->anchor=(AnchorClass *) lac; } } } ++k; } while (k<sf->sf.subfontcnt); }
static int JSTF_Language_OK(GGadget *g, GEvent *e) { if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) { Jstf_Dlg *jd = GDrawGetUserData(GGadgetGetWindow(g)); int rows, i, j, k, cnt; struct matrix_data *strings = GMatrixEditGet(GWidgetGetControl(jd->lgw,CID_Languages), &rows); int cols = GMatrixEditGetColCnt(GWidgetGetControl(jd->lgw,CID_Languages)); struct jstf_lang *head=NULL, *last=NULL, *cur; for ( i=0; i<rows; ++i ) if ( !(strings[i*cols+0].u.md_str[0]&0x80) ) { for ( j=i, cnt=0; j<rows; ++j ) if ( strcmp(strings[j*cols+0].u.md_str, strings[i*cols+0].u.md_str)==0 ) ++cnt; cur = chunkalloc(sizeof(struct jstf_lang)); if ( head==NULL ) head = cur; else last->next = cur; last = cur; cur->lang = Str2Tag(strings[i*cols+0].u.md_str); cur->cnt = cnt; cur->prios=gcalloc(cnt,sizeof(struct jstf_prio)); for ( j=i, cnt=0; j<rows; ++j ) { if ( strcmp(strings[j*cols+0].u.md_str, strings[i*cols+0].u.md_str)==0 ) { cur->prios[cnt].enableExtend = Str2OTLList(jd->sf,strings[j*cols+1].u.md_str ); cur->prios[cnt].disableExtend = Str2OTLList(jd->sf,strings[j*cols+2].u.md_str ); cur->prios[cnt].maxExtend = Str2OTLList(jd->sf,strings[j*cols+3].u.md_str ); cur->prios[cnt].enableShrink = Str2OTLList(jd->sf,strings[j*cols+4].u.md_str ); cur->prios[cnt].disableShrink = Str2OTLList(jd->sf,strings[j*cols+5].u.md_str ); cur->prios[cnt].maxShrink = Str2OTLList(jd->sf,strings[j*cols+6].u.md_str ); if ( cur->prios[cnt].enableExtend == (OTLookup **) -1 || cur->prios[cnt].disableExtend == (OTLookup **) -1 || cur->prios[cnt].maxExtend == (OTLookup **) -1 || cur->prios[cnt].enableShrink == (OTLookup **) -1 || cur->prios[cnt].disableShrink == (OTLookup **) -1 || cur->prios[cnt].maxShrink == (OTLookup **) -1 ) { JstfLangFree(head); for ( k=0; k<rows; ++k ) strings[k*cols+0].u.md_str[0] &= ~0x80; return( true ); } ++cnt; } } for ( j=rows-1; j>=i; --j ) if ( strcmp(strings[j*cols+0].u.md_str, strings[i*cols+0].u.md_str)==0 ) strings[j*cols+0].u.md_str[0] |= 0x80; } JstfLangFree( *jd->here ); *jd->here = head; jd->ldone = true; } return( true ); }
void AltUniAdd_DontCheckDups(SplineChar *sc,int uni) { struct altuni *altuni; if ( sc!=NULL && uni!=-1 && uni!=sc->unicodeenc ) { altuni = chunkalloc(sizeof(struct altuni)); altuni->next = sc->altuni; sc->altuni = altuni; altuni->unienc = uni; altuni->vs = -1; altuni->fid = 0; } }
bezctx * new_bezctx_ff(void) { bezctx_ff *result = chunkalloc(sizeof(bezctx_ff)); result->base.moveto = bezctx_ff_moveto; result->base.lineto = bezctx_ff_lineto; result->base.quadto = bezctx_ff_quadto; result->base.curveto = bezctx_ff_curveto; result->base.mark_knot = NULL; result->is_open = 0; result->gotnans = 0; result->ss = NULL; return &result->base; }
static void bezctx_ff_moveto(bezctx *z, double x, double y, int is_open) { bezctx_ff *bc = (bezctx_ff *)z; if ( !finite(x) || !finite(y)) { nancheck(bc); x = y = 0; } if (!bc->is_open) { SplineSet *ss = chunkalloc(sizeof(SplineSet)); ss->next = bc->ss; bc->ss = ss; } bc->ss->first = bc->ss->last = SplinePointCreate(x,y); bc->is_open = is_open; }
void AltUniAdd(SplineChar *sc,int uni) { struct altuni *altuni; if ( sc!=NULL && uni!=-1 && uni!=sc->unicodeenc ) { for ( altuni = sc->altuni; altuni!=NULL && (altuni->unienc!=uni || altuni->vs!=-1 || altuni->fid); altuni=altuni->next ); if ( altuni==NULL ) { altuni = chunkalloc(sizeof(struct altuni)); altuni->next = sc->altuni; sc->altuni = altuni; altuni->unienc = uni; altuni->vs = -1; altuni->fid = 0; } } }
Group *GroupCopy(Group *g) { int i; Group *gp; if ( g==NULL ) return( NULL ); gp = chunkalloc(sizeof(Group)); gp->name = copy(g->name); gp->glyphs = copy(g->glyphs); if ( g->kid_cnt!=0 ) { gp->kids = malloc((gp->kid_cnt=g->kid_cnt)*sizeof(Group *)); for ( i=0; i<g->kid_cnt; ++i ) { gp->kids[i] = GroupCopy(g->kids[i]); gp->kids[i]->parent = gp; } } return( gp ); }
void MMKern(SplineFont *sf,SplineChar *first,SplineChar *second,int diff, struct lookup_subtable *sub,KernPair *oldkp) { MMSet *mm = sf->mm; KernPair *kp; int i; /* If the user creates a kern pair in one font of a multiple master set */ /* then we should create the same kern pair in all the others. Similarly */ /* if s/he modifies a kern pair in the weighted version then apply that */ /* mod to all the others */ if ( mm==NULL ) return; if ( sf==mm->normal || oldkp==NULL ) { for ( i= -1; i<mm->instance_count; ++i ) { SplineFont *cur = i==-1 ? mm->normal : mm->instances[i]; SplineChar *psc, *ssc; if ( cur==sf ) /* Done in caller */ continue; psc = cur->glyphs[first->orig_pos]; ssc = cur->glyphs[second->orig_pos]; if ( psc==NULL || ssc==NULL ) /* Should never happen*/ continue; for ( kp = psc->kerns; kp!=NULL && kp->sc!=ssc; kp = kp->next ); /* No mm support for vertical kerns */ if ( kp==NULL ) { kp = chunkalloc(sizeof(KernPair)); if ( oldkp!=NULL ) *kp = *oldkp; else { kp->off = diff; if ( sub==NULL ) sub = SFSubTableFindOrMake(cur, CHR('k','e','r','n'), SCScriptFromUnicode(psc), gpos_pair); kp->subtable = sub; } kp->sc = ssc; kp->next = psc->kerns; psc->kerns = kp; } else kp->off += diff; } } }
static int CH_OK(GGadget *g, GEvent *e) { if ( e->type==et_controlevent && e->u.control.subtype == et_buttonactivate ) { CreateHintData *hd = GDrawGetUserData(GGadgetGetWindow(g)); real base, width; int err = 0; StemInfo *h; int layer = CVLayer((CharViewBase *) hd->cv); base = GetReal8(hd->gw,CID_Base,_("Base:"),&err); width = GetReal8(hd->gw,CID_Width,_("Size:"),&err); if ( err ) return(true); if ( hd->preservehints ) { SCPreserveHints(hd->cv->b.sc,layer); SCHintsChanged(hd->cv->b.sc); } h = chunkalloc(sizeof(StemInfo)); if ( width==-21 || width==-20 ) { base += width; width = -width; h->ghost = true; } h->start = base; h->width = width; if ( hd->ishstem ) { SCGuessHHintInstancesAndAdd(hd->cv->b.sc,layer,h,0x80000000,0x80000000); hd->cv->b.sc->hconflicts = StemListAnyConflicts(hd->cv->b.sc->hstem); } else { SCGuessVHintInstancesAndAdd(hd->cv->b.sc,layer,h,0x80000000,0x80000000); hd->cv->b.sc->vconflicts = StemListAnyConflicts(hd->cv->b.sc->vstem); } hd->cv->b.sc->manualhints = true; if ( h!=NULL && hd->cv->b.sc->parent->mm==NULL ) SCModifyHintMasksAdd(hd->cv->b.sc,layer,h); else SCClearHintMasks(hd->cv->b.sc,layer,true); SCOutOfDateBackground(hd->cv->b.sc); SCUpdateAll(hd->cv->b.sc); hd->done = true; } return( true ); }
static void VaryCvt(struct tuples *tuple,int *points, int *deltas, int pcnt, struct ttf_table *orig_cvt) { struct ttf_table *cvt; int i; if ( (cvt = tuple->cvt)==NULL ) { cvt = tuple->cvt = chunkalloc(sizeof(struct ttf_table)); cvt->tag = orig_cvt->tag; cvt->len = cvt->maxlen = orig_cvt->len; cvt->data = malloc(cvt->len); memcpy(cvt->data,orig_cvt->data,cvt->len); } if ( points[0]==ALL_POINTS ) { for ( i=0; i<pcnt; ++i ) AlterEntry(cvt,i,deltas[i]); } else { for ( i=0; i<pcnt; ++i ) AlterEntry(cvt,points[i],deltas[i]); } }
static OTLookup *CreateACLookup(SplineFont1 *sf,AnchorClass1 *ac) { OTLookup *otl=chunkalloc(sizeof(OTLookup)); otl->lookup_type = ac->ac.type==act_mark?gpos_mark2base : ac->ac.type==act_mkmk?gpos_mark2mark : ac->ac.type==act_curs?gpos_cursive : ac->ac.type==act_mklg?gpos_mark2ligature:ot_undef; if (otl->lookup_type==ot_undef) ErrorMsg(2,"Unknown AnchorClass type\n"); otl->next=sf->sf.gsplookups[1]; sf->sf.gsplookups[1]=otl; otl->lookup_flags=ac->flags; otl->features = FeaturesFromTagSli(ac->feature_tag, ac->script_lang_index, sf); /* We will set the lookup_index after we've ordered the list */ /* We will set the lookup_name after we've assigned the index */ /* We will add one subtable soon */ return (otl); }
static int AnchorD_ChangeGlyph(AnchorDlg *a, SplineChar *sc, AnchorPoint *ap) { char buf[32]; struct state *old; if ( ap==NULL || sc==NULL ) return( true ); if ( a->ap==ap ) return( true ); /* Do we already have an entry for the current anchor? */ for ( old = a->orig_vals; old!=NULL && old->ap_pt!=a->ap; old=old->next ); /* If so we've already noted its original state and need do nothing more */ /* but otherwise we must store the current state */ if ( old==NULL ) { old = chunkalloc(sizeof(struct state)); old->sc = a->sc; old->changed = a->sc->changed; old->ap_pt = a->ap; old->ap_vals = *a->ap; memset(&a->ap->xadjust,0,sizeof(DeviceTable)); memset(&a->ap->yadjust,0,sizeof(DeviceTable)); old->next = a->orig_vals; a->orig_vals = old; } AnchorD_Apply(a); AnchorD_FreeChar(a); a->ap = ap; a->sc = sc; a->apos = ap->me; sprintf( buf, "%d", (int) rint(ap->me.x) ); GGadgetSetTitle8(GWidgetGetControl(a->gw,CID_X),buf); sprintf( buf, "%d", (int) rint(ap->me.y) ); GGadgetSetTitle8(GWidgetGetControl(a->gw,CID_Y),buf); AnchorD_FindComplements(a); AnchorD_SetDevTabs(a); AnchorD_ChangeSize(a); AnchorD_SetTitle(a); return( true ); }
SplineSet *SpiroCP2SplineSet(spiro_cp *spiros) { /* Create a SplineSet from the given spiros_code_points.*/ int n; int any = 0; SplineSet *ss; int lastty = 0; if ( spiros==NULL ) return( NULL ); for ( n=0; spiros[n].ty!=SPIRO_END; ++n ) if ( SPIRO_SELECTED(&spiros[n]) ) ++any; if ( n==0 ) return( NULL ); if ( n==1 ) { /* Spiro only haS 1 code point sofar (no conversion needed yet) */ if ( (ss=chunkalloc(sizeof(SplineSet)))==NULL || \ (ss->first=ss->last=SplinePointCreate(spiros[0].x,spiros[0].y))==NULL ) { chunkfree(ss,sizeof(SplineSet)); return( NULL ); } } else { /* Spiro needs to be converted to bezier curves using libspiro. */ bezctx *bc; if ( (bc=new_bezctx_ff())==NULL ) return( NULL ); if ( (spiros[0].ty&0x7f)=='{' ) { lastty = spiros[n-1].ty; spiros[n-1].ty = '}'; } if ( !any ) { #if _LIBSPIRO_FUN if ( TaggedSpiroCPsToBezier0(spiros,bc)==0 ) { if ( lastty ) spiros[n-1].ty = lastty; free(bc); return( NULL ); } #else TaggedSpiroCPsToBezier(spiros,bc); #endif } else { int i; spiro_cp *nspiros; if ( (nspiros=malloc((n+1)*sizeof(spiro_cp)))==NULL ) { if ( lastty ) spiros[n-1].ty = lastty; free(bc); return( NULL ); } memcpy(nspiros,spiros,(n+1)*sizeof(spiro_cp)); for ( i=0; nspiros[i].ty!=SPIRO_END; ++i ) nspiros[i].ty &= ~0x80; #if _LIBSPIRO_FUN if ( TaggedSpiroCPsToBezier0(nspiros,bc)==0 ) { if ( lastty ) spiros[n-1].ty = lastty; free(nspiros); free(bc); return( NULL ); } #else TaggedSpiroCPsToBezier(nspiros,bc); #endif free(nspiros); } if ( lastty ) spiros[n-1].ty = lastty; if ( (ss=bezctx_ff_close(bc))==NULL ) return( NULL ); } ss->spiros = spiros; ss->spiro_cnt = ss->spiro_max = n+1; SPLCatagorizePoints(ss); return( ss ); }
/* When the user tries to add a point (by doing a mouse down with a point tool selected) there are several cases to be looked at: If there is a single point selected and it is at the begining/end of an open spline set if we clicked on another point which is the begining/end of an open splineset draw a spline connecting the two spline sets and merge them (or if it's the same spline set, then close it) else create a new point where we clicked draw a spline between the selected point and the new one deselect the old point select the new one endif else if they clicked on a spline split the spline into two bits at the point where they clicked else create a new point where they clicked put it on a new splineset select it endif and, if the old point is a tangent, we may need to adjust its control pt With the introduction of spiro mode (Raph Levien's clothoid splines) we've got to worry about all the above cases for spiro points too. */ void CVMouseDownPoint(CharView *cv, GEvent *event) { SplineSet *sel, *ss; SplinePoint *sp, *base = NULL; SplineChar *sc = cv->b.sc; enum pointtype ptype = (cv->active_tool==cvt_curve?pt_curve: cv->active_tool==cvt_hvcurve?pt_hvcurve: cv->active_tool==cvt_corner?pt_corner: cv->active_tool==cvt_tangent?pt_tangent: /*cv->active_tool==cvt_pen?*/pt_corner); int order2 = cv->b.layerheads[cv->b.drawmode]->order2; int order2_style = (order2 && !(event->u.mouse.state&ksm_meta)) || (!order2 && (event->u.mouse.state&ksm_meta)); cv->active_spl = NULL; cv->active_sp = NULL; if ( cv->b.sc->inspiro && hasspiro()) { CVMouseDownSpiroPoint(cv, event); return; } sel = CVAnySelPointList(cv); if ( sel!=NULL ) { if ( sel->first->selected ) base = sel->first; else base = sel->last; if ( base==cv->p.sp ) return; /* We clicked on the active point, that's a no-op */ } CVPreserveState(&cv->b); CVClearSel(cv); if ( sel!=NULL ) { sp = cv->p.sp; cv->lastselpt = base; ss = sel; if ( base->next!=NULL ) SplineSetReverse(sel); if ( base->next!=NULL ) IError("Base point not at end of splineset in CVMouseDownPoint"); if ( sp==NULL || (sp->next!=NULL && sp->prev!=NULL) || sp==base ) { /* Add a new point */ SplineSetSpirosClear(sel); sp = SplinePointCreate( cv->p.cx, cv->p.cy ); sp->noprevcp = sp->nonextcp = 1; sp->nextcpdef = sp->prevcpdef = 1; sp->pointtype = ptype; sp->selected = true; if ( !base->nonextcp && order2_style && cv->active_tool==cvt_pen ) { sp->prevcp = base->nextcp; sp->noprevcp = false; sp->me.x = ( sp->prevcp.x + sp->nextcp.x )/2; sp->me.y = ( sp->prevcp.y + sp->nextcp.y )/2; sp->nonextcp = false; sp->pointtype = pt_curve; } else if ( order2 && !base->nonextcp ) { sp->prevcp = base->nextcp; sp->noprevcp = false; if ( cv->active_tool==cvt_pen ) { sp->nextcp.x = sp->me.x - (sp->prevcp.x-sp->me.x); sp->nextcp.y = sp->me.y - (sp->prevcp.y-sp->me.y); sp->nonextcp = false; sp->pointtype = pt_curve; } } if ( base->nonextcp ) base->nextcpdef = true; SplineMake(base,sp,order2); if ( cv->active_tool!=cvt_pen ) { SplineCharDefaultNextCP(base); SplineCharDefaultPrevCP(sp); } ss->last = sp; } else if ( cv->p.spl==sel ) { /* Close the current spline set */ SplineSetSpirosClear(sel); cv->joinvalid = true; cv->joinpos = *sp; cv->joinpos.selected = false; if ( order2 ) { if ( base->nonextcp || sp->noprevcp ) { base->nonextcp = sp->noprevcp = true; base->nextcp = base->me; sp->prevcp = sp->me; } else { base->nextcp.x = sp->prevcp.x = (base->nextcp.x+sp->prevcp.x)/2; base->nextcp.y = sp->prevcp.y = (base->nextcp.y+sp->prevcp.y)/2; } base->nextcpdef = sp->prevcpdef = true; } SplineMake(base,sp,order2); if ( cv->active_tool!=cvt_pen ) SplineCharDefaultNextCP(base); SplineCharDefaultPrevCP(sp); ss->last = sp; if ( sp->pointtype==pt_tangent ) { SplineCharTangentNextCP(sp); if ( sp->next ) SplineRefigure(sp->next ); } } else { /* Merge two spline sets */ SplineSetSpirosClear(sel); CVMergeSPLS(cv,sel, base,sp); } sp->selected = true; if ( base->pointtype==pt_tangent ) { SplineCharTangentPrevCP(base); if ( base->prev!=NULL ) SplineRefigure(base->prev); } } else if ( cv->p.spline!=NULL ) { sp = SplineBisect(cv->p.spline,cv->p.t); cv->joinvalid = true; cv->joinpos = *sp; cv->joinpos.selected = false; if ( cv->active_tool==cvt_pen ) ptype = pt_curve; sp->pointtype = ptype; if ( ptype==pt_hvcurve ) { SPHVCurveForce(sp); } sp->selected = true; ss = cv->p.spl; } else { ss = chunkalloc(sizeof(SplineSet)); sp = SplinePointCreate( cv->p.cx, cv->p.cy ); ss->first = ss->last = sp; ss->next = cv->b.layerheads[cv->b.drawmode]->splines; cv->b.layerheads[cv->b.drawmode]->splines = ss; sp->nonextcp = sp->noprevcp = 1; sp->nextcpdef = sp->prevcpdef = 1; sp->pointtype = ptype; sp->selected = true; } cv->active_spl = ss; cv->active_sp = sp; CVSetCharChanged(cv,true); CVInfoDraw(cv,cv->gw); SCUpdateAll(sc); if ( cv->active_tool == cvt_pen ) cv->p.constrain = sp->me; }
static void CVMouseDownSpiroPoint(CharView *cv, GEvent *event) { SplineSet *sel, *ss; SplineChar *sc = cv->b.sc; spiro_cp *base, *cp; int base_index, cp_index, i; char ty = (cv->active_tool==cvt_curve?SPIRO_G4: cv->active_tool==cvt_hvcurve?SPIRO_G2: cv->active_tool==cvt_corner?SPIRO_CORNER: cv->active_tool==cvt_tangent?SPIRO_LEFT: /*cv->active_tool==cvt_pen?*/SPIRO_RIGHT); cv->active_spl = NULL; cv->active_sp = NULL; sel = CVAnySelPointList(cv); if ( sel!=NULL ) { if ( SPIRO_SELECTED(&sel->spiros[0]) ) base_index = 0; else base_index = sel->spiro_cnt-2; base = &sel->spiros[base_index]; if ( base==cv->p.spiro ) return; /* We clicked on the active point, that's a no-op */ } CVPreserveState(&cv->b); CVClearSel(cv); if ( sel!=NULL ) { if ( (cp = cv->p.spiro)!=NULL ) cp_index = cp-cv->p.spl->spiros; cv->lastselcp = base; ss = sel; if ( base_index!=sel->spiro_cnt-2 ) { SplineSetReverse(sel); base = &sel->spiros[sel->spiro_cnt-2]; if ( cv->p.spl==sel ) { cp_index = sel->spiro_cnt-2-cp_index; cp = &sel->spiros[cp_index]; } } if ( cp==NULL || (cp_index!=0 && cp_index!=cv->p.spl->spiro_cnt-2) || cp==base || !SPIRO_SPL_OPEN(cv->p.spl)) { /* Add a new point */ if ( sel->spiro_cnt>=sel->spiro_max ) sel->spiros = realloc(sel->spiros,(sel->spiro_max += 10)*sizeof(spiro_cp)); cp = &sel->spiros[sel->spiro_cnt-1]; cp[1] = cp[0]; /* Move the final 'z' */ cp->x = cv->p.cx; cp->y = cv->p.cy; cp->ty = ty; SPIRO_DESELECT(cp-1); ++sel->spiro_cnt; } else if ( cv->p.spl==sel ) { /* Close the current spline set */ sel->spiros[0].ty = ty; cv->joinvalid = true; cv->joincp = *cp; SPIRO_DESELECT(&cv->joincp); } else { /* Merge two spline sets */ SplinePoint *sp = cp_index==0 ? cv->p.spl->first : cv->p.spl->last; SplinePoint *basesp = base_index==0 ? sel->first : sel->last; cv->joincp = *cp; SPIRO_DESELECT(&cv->joincp); CVMergeSPLS(cv,ss,basesp,sp); } } else if ( cv->p.spline!=NULL ) { /* Add an intermediate point on an already existing spline */ ss = cv->p.spl; if ( ss->spiro_cnt>=ss->spiro_max ) ss->spiros = realloc(ss->spiros,(ss->spiro_max += 10)*sizeof(spiro_cp)); for ( i=ss->spiro_cnt-1; i>cv->p.spiro_index; --i ) ss->spiros[i+1] = ss->spiros[i]; ++ss->spiro_cnt; cp = &ss->spiros[cv->p.spiro_index+1]; cp->x = cv->p.cx; cp->y = cv->p.cy; cp->ty = ty; ss = cv->p.spl; cv->joinvalid = true; cv->joincp = *cp; SPIRO_DESELECT(&cv->joincp); } else { /* A new point on a new (open) contour */ ss = chunkalloc(sizeof(SplineSet)); ss->next = cv->b.layerheads[cv->b.drawmode]->splines; cv->b.layerheads[cv->b.drawmode]->splines = ss; ss->spiros = malloc((ss->spiro_max=10)*sizeof(spiro_cp)); cp = &ss->spiros[0]; cp->x = cv->p.cx; cp->y = cv->p.cy; cp->ty = SPIRO_OPEN_CONTOUR; cp[1].x = cp[1].y = 0; cp[1].ty = 'z'; ss->spiro_cnt = 2; } SPIRO_SELECT(cp); SSRegenerateFromSpiros(ss); cv->active_spl = ss; cv->active_cp = cp; CVSetCharChanged(cv,true); CVInfoDraw(cv,cv->gw); SCUpdateAll(sc); }
static struct lookup_subtable *VSubtableFromH(struct lookupmap *lookupmap,struct lookup_subtable *sub) { int i, lc, sc; OTLookup *otl; struct lookup_subtable *nsub, *prev, *test, *ls; FeatureScriptLangList *fl; for ( i=0 ; i<lookupmap->sc; ++i ) if ( lookupmap->smap[i].from == sub ) return( lookupmap->smap[i].to ); if ( lookupmap->lmap==NULL ) { for ( otl = lookupmap->sf->gpos_lookups, lc=sc=0; otl!=NULL; otl=otl->next ) { if ( otl->lookup_type==gpos_pair ) { ++lc; for ( ls=otl->subtables; ls!=NULL; ls=ls->next ) ++sc; } } lookupmap->lmap = malloc(lc*sizeof(struct otlmap)); lookupmap->smap = malloc(sc*sizeof(struct submap)); } for ( i=0 ; i<lookupmap->lc; ++i ) if ( lookupmap->lmap[i].from == sub->lookup ) break; if ( i==lookupmap->lc ) { ++lookupmap->lc; lookupmap->lmap[i].from = sub->lookup; lookupmap->lmap[i].to = otl = chunkalloc(sizeof(OTLookup)); otl->lookup_type = gpos_pair; otl->features = FeatureListCopy(sub->lookup->features); for ( fl=otl->features; fl!=NULL; fl=fl->next ) if ( fl->featuretag == CHR('k','e','r','n') ) fl->featuretag = CHR('v','k','r','n'); otl->lookup_name = strconcat("V",sub->lookup->lookup_name); otl->next = sub->lookup->next; sub->lookup->next = otl; } else otl = lookupmap->lmap[i].to; sc = lookupmap->sc++; lookupmap->smap[sc].from = sub; lookupmap->smap[sc].to = nsub = chunkalloc(sizeof(struct lookup_subtable)); nsub->subtable_name = strconcat("V",sub->subtable_name); nsub->per_glyph_pst_or_kern = sub->per_glyph_pst_or_kern; nsub->vertical_kerning = true; nsub->lookup = otl; /* Order the subtables of the new lookup the same way they are ordered */ /* in the old. However there may be holes (subtables which don't get */ /* converted) */ prev = NULL; for ( test=sub->lookup->subtables; test!=NULL && test!=sub; test=test->next ) { for ( i=0 ; i<lookupmap->sc; ++i ) if ( lookupmap->smap[i].from == test ) { prev = lookupmap->smap[i].to; break; } } if ( prev!=NULL ) { nsub->next = prev->next; prev->next = nsub; } else { nsub->next = otl->subtables; otl->subtables = nsub; } return( nsub ); }
void FVVKernFromHKern(FontViewBase *fv) { int i,j; KernPair *kp, *vkp; SplineChar *sc1, *sc2; KernClass *kc, *vkc; SplineChar ***firsts, ***seconds; int any1, any2; SplineFont *sf = fv->sf; int *map1, *map2; struct lookupmap lookupmap; FVRemoveVKerns(fv); if ( sf->cidmaster ) sf = sf->cidmaster; if ( !sf->hasvmetrics ) return; memset(&lookupmap,0,sizeof(lookupmap)); lookupmap.sf = sf; for ( i=0; i<sf->glyphcnt; ++i ) { if ( (sc1 = SCHasVertVariant(sf->glyphs[i]))!=NULL ) { for ( kp = sf->glyphs[i]->kerns; kp!=NULL; kp=kp->next ) { if ( (sc2 = SCHasVertVariant(kp->sc))!=NULL ) { vkp = chunkalloc(sizeof(KernPair)); *vkp = *kp; vkp->subtable = VSubtableFromH(&lookupmap,kp->subtable); vkp->adjust = DeviceTableCopy(vkp->adjust); vkp->sc = sc2; vkp->next = sc1->vkerns; sc1->vkerns = vkp; } } } } for ( kc = sf->kerns; kc!=NULL; kc=kc->next ) { firsts = malloc(kc->first_cnt*sizeof(SplineChar *)); map1 = calloc(kc->first_cnt,sizeof(int)); seconds = malloc(kc->second_cnt*sizeof(SplineChar *)); map2 = calloc(kc->second_cnt,sizeof(int)); any1=0; for ( i=1; i<kc->first_cnt; ++i ) { if ( (firsts[i] = CharNamesToVertSC(sf,kc->firsts[i]))!=NULL ) map1[i] = ++any1; } any2 = 0; for ( i=1; i<kc->second_cnt; ++i ) { if ((seconds[i] = CharNamesToVertSC(sf,kc->seconds[i]))!=NULL ) map2[i] = ++any2; } if ( any1 && any2 ) { vkc = chunkalloc(sizeof(KernClass)); *vkc = *kc; vkc->subtable = VSubtableFromH(&lookupmap,kc->subtable); vkc->subtable->kc = vkc; vkc->next = sf->vkerns; sf->vkerns = vkc; vkc->first_cnt = any1+1; vkc->second_cnt = any2+1; vkc->firsts = calloc(any1+1,sizeof(char *)); for ( i=0; i<kc->first_cnt; ++i ) if ( map1[i]!=0 ) vkc->firsts[map1[i]] = SCListToName(firsts[i]); vkc->seconds = calloc(any2+1,sizeof(char *)); for ( i=0; i<kc->second_cnt; ++i ) if ( map2[i]!=0 ) vkc->seconds[map2[i]] = SCListToName(seconds[i]); vkc->offsets = calloc((any1+1)*(any2+1),sizeof(int16)); vkc->adjusts = calloc((any1+1)*(any2+1),sizeof(DeviceTable)); for ( i=0; i<kc->first_cnt; ++i ) if ( map1[i]!=0 ) { for ( j=0; j<kc->second_cnt; ++j ) if ( map2[j]!=0 ) { int n=map1[i]*vkc->second_cnt+map2[j], o = i*kc->second_cnt+j; vkc->offsets[n] = kc->offsets[o]; if ( kc->adjusts[o].corrections!=NULL ) { int len = kc->adjusts[o].last_pixel_size - kc->adjusts[o].first_pixel_size + 1; vkc->adjusts[n] = kc->adjusts[o]; vkc->adjusts[n].corrections = malloc(len); memcpy(vkc->adjusts[n].corrections,kc->adjusts[o].corrections,len); } } } } free(map1); free(map2); for ( i=1; i<kc->first_cnt; ++i ) free(firsts[i]); for ( i=1; i<kc->second_cnt; ++i ) free(seconds[i]); free(firsts); free(seconds); } free( lookupmap.lmap ); free( lookupmap.smap ); }
void CVMouseUpKnife(CharView *cv, GEvent *event) { #if !defined(KNIFE_CONTINUOUS) /* draw a line from (cv->p.cx,cv->p.cy) to (cv->info.x,cv->info.y) */ /* and cut anything intersected by it */ SplineSet *spl, *spl2; Spline *s, *nexts; Spline dummy; SplinePoint dummyfrom, dummyto, *mid, *mid2; BasePoint inters[9]; extended t1s[10], t2s[10]; int foundsomething = true, ever = false; int i; int spiro_index = 0; memset(&dummy,0,sizeof(dummy)); memset(&dummyfrom,0,sizeof(dummyfrom)); memset(&dummyto,0,sizeof(dummyto)); dummyfrom.me.x = cv->p.cx; dummyfrom.me.y = cv->p.cy; dummyto.me.x = cv->info.x; dummyto.me.y = cv->info.y; dummyfrom.nextcp = dummyfrom.prevcp = dummyfrom.me; dummyto.nextcp = dummyto.prevcp = dummyto.me; dummyfrom.nonextcp = dummyfrom.noprevcp = dummyto.nonextcp = dummyto.noprevcp = true; dummy.splines[0].d = cv->p.cx; dummy.splines[0].c = cv->info.x-cv->p.cx; dummy.splines[1].d = cv->p.cy; dummy.splines[1].c = cv->info.y-cv->p.cy; dummy.from = &dummyfrom; dummy.to = &dummyto; dummy.islinear = dummy.knownlinear = true; dummyfrom.next = dummyto.prev = &dummy; for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL ; spl = spl->next ) spl->ticked = false; while ( foundsomething ) { foundsomething = false; for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL && !foundsomething; spl = spl->next ) { for ( s = spl->first->next; s!=NULL ; ) { nexts = NULL; if ( s->to!=spl->first ) nexts = s->to->next; if ( SplinesIntersect(s,&dummy,inters,t1s,t2s)>0 ) { if ( event->u.mouse.state&ksm_meta ) { for ( i=0; i<4 && t1s[i]!=-1 && (t1s[i]<.0001 || t1s[i]>1-.0001); ++i ); if ( i<4 && t1s[i]!=-1 ) { /* With meta down we just remove the spline rather than */ /* cutting it */ foundsomething = true; nexts = NULL; if ( !ever ) CVPreserveState(&cv->b); ever = true; if ( spl->first==spl->last ) { spl->first = s->to; spl->last = s->from; } else { spl2 = chunkalloc(sizeof(SplineSet)); spl2->next = spl->next; spl->next = spl2; spl2->first = s->to; spl2->last = spl->last; spl->last = s->from; } s->to->prev = s->from->next = NULL; SplineFree(s); SplineSetSpirosClear(spl); } } else { for ( i=0; i<4 && t1s[i]!=-1 && (( t1s[i]<.001 && s->from->prev==NULL ) || ( t1s[i]>1-.001 && s->to->next == NULL )); ++i ); if ( i<4 && t1s[i]!=-1 ) { foundsomething = true; nexts = NULL; if ( !ever ) CVPreserveState(&cv->b); ever = true; spiro_index = -1; if ( cv->b.sc->inspiro && hasspiro()) { if ( spl->spiro_cnt!=0 ) spiro_index = SplineT2SpiroIndex(s,t1s[i],spl); } else SplineSetSpirosClear(spl); if ( t1s[i]<.001 ) { mid = s->from; } else if ( t1s[i]>1-.001 ) { mid = s->to; } else mid = SplineBisect(s,t1s[i]); /* if the intersection is close to an end point */ /* cut at the end point, else break in the middle */ /* Cut here, and then */ /* start all over again (we may need to alter the */ /* splineset structure so drastically that we just */ /* can't continue these loops) */ mid->pointtype = pt_corner; mid2 = chunkalloc(sizeof(SplinePoint)); *mid2 = *mid; mid2->hintmask = NULL; mid->next = NULL; mid2->prev = NULL; mid2->next->from = mid2; spl->ticked = true; if ( spl->first==spl->last ) { spl->first = mid2; spl->last = mid; if ( spiro_index!=-1 ) ReorderSpirosAndAddAndCut(spl,spiro_index); } else { spl2 = chunkalloc(sizeof(SplineSet)); spl2->next = spl->next; spl->next = spl2; spl2->first = mid2; spl2->last = spl->last; spl->last = mid; if ( spiro_index!=-1 ) SplitSpirosAndAddAndCut(spl,spl2,spiro_index); spl2->ticked = true; } } } } s = nexts; } } } if ( ever ) { for ( spl = cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL ; spl = spl->next ) { if ( spl->ticked && spl->spiros!=NULL && cv->b.sc->inspiro && hasspiro()) SSRegenerateFromSpiros(spl); spl->ticked = false; } CVCharChangedUpdate(&cv->b); } #endif }