static void CVMouseMoveSpiroPoint(CharView *cv, PressedOn *p) { spiro_cp *active = cv->active_cp, *merge = p->spiro; SplineSet *activess = cv->active_spl; int active_index; if ( active==NULL ) return; if ( cv->info.x==active->x && cv->info.y==active->y ) return; if ( !cv->recentchange ) CVPreserveState(&cv->b); active->x = cv->info.x; active->y = cv->info.y; CVSetCharChanged(cv,true); active_index = active-activess->spiros; if ( active!=merge && merge!=NULL && p->spl!=NULL && SPIRO_SPL_OPEN(activess) && SPIRO_SPL_OPEN(p->spl) && (active_index==0 || active_index==activess->spiro_cnt-2) && ((merge-p->spl->spiros)==0 || (merge-p->spl->spiros)==p->spl->spiro_cnt-2) ) { SplinePoint *activesp = active_index==0 ? activess->first : activess->last; SplinePoint *mergesp = (merge-p->spl->spiros)==0 ? p->spl->first : p->spl->last; CVMergeSplineSets(cv,activesp,activess,mergesp,p->spl); } SSRegenerateFromSpiros(activess); SCUpdateAll(cv->b.sc); }
void SSRegenerateFromSpiros(SplineSet *spl) { SplineSet *temp; if ( spl->spiro_cnt<=1 ) return; if ( !has_spiro) return; SplineSetBeziersClear(spl); temp = SpiroCP2SplineSet(spl->spiros); if ( temp!=NULL ) { spl->first = temp->first; spl->last = temp->last; chunkfree(temp,sizeof(SplineSet)); } else { /* didn't converge... or something */ int i; SplinePoint *sp, *last; last = spl->first = SplinePointCreate(spl->spiros[0].x, spl->spiros[0].y); for ( i=1; i<spl->spiro_cnt; ++i ) { sp = SplinePointCreate(spl->spiros[i].x, spl->spiros[i].y); SplineMake3(last,sp); last = sp; } if ( SPIRO_SPL_OPEN(spl)) spl->last = last; else { SplineMake3(last,spl->first); spl->last = spl->first; } } spl->beziers_need_optimizer = true; }
SplinePointList *CVAnySelPointList(CharView *cv) { /* if there is exactly one point selected and it is on an open splineset */ /* and it is one of the endpoints of the splineset, then return that */ /* splineset */ SplinePointList *spl, *found=NULL; Spline *spline, *first; int i; for ( spl= cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL; spl=spl->next ) { if ( cv->b.sc->inspiro && hasspiro()) { for ( i = 0; i<spl->spiro_cnt-1; ++i ) { if ( SPIRO_SELECTED(&spl->spiros[i])) { /* Only interesting if the single selection is at the */ /* start/end of an open contour */ if (( i!=0 && i!=spl->spiro_cnt-2 ) || !SPIRO_SPL_OPEN(spl)) return( NULL ); else if ( found==NULL ) found = spl; else return( NULL ); } } } else { if ( spl->first->selected ) { if ( found!=NULL ) return( NULL ); /* At least two points */ if ( spl->first->prev!=NULL ) return( NULL ); /* Not an open splineset */ found = spl; } first = NULL; for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) { if ( spline->to->selected ) { if ( found!=NULL ) return( NULL ); if ( spline->to->next!=NULL ) return( NULL ); /* Selected point is not at end of a splineset */ found = spl; } if ( first==NULL ) first = spline; } } } return( found ); }
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 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); }