/* spline set... */ void CVMouseMovePoint(CharView *cv, PressedOn *p) { SplinePoint *active = cv->active_sp, *merge = p->sp; SplineSet *activess = cv->active_spl; if ( cv->b.sc->inspiro && hasspiro()) { CVMouseMoveSpiroPoint(cv,p); return; } if ( active==NULL ) return; if ( cv->info.x==active->me.x && cv->info.y==active->me.y ) return; if ( !cv->recentchange ) CVPreserveState(&cv->b); CVAdjustPoint(cv,active); SplineSetSpirosClear(activess); if (( active->next==NULL || active->prev==NULL ) && merge!=NULL && p->spl!=NULL && merge!=active && (merge->next==NULL || merge->prev==NULL )) { CVMergeSplineSets(cv,active,activess,merge,p->spl); } SCUpdateAll(cv->b.sc); }
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 ); }
int CVAnySelPoint(CharView *cv,SplinePoint **sp, spiro_cp **cp) { /* if there is exactly one point selected */ SplinePointList *spl; Spline *spline, *first; SplinePoint *found = NULL; spiro_cp *foundcp = NULL; int i; *sp = NULL; *cp = NULL; if ( cv->b.sc->inspiro && hasspiro()) { for ( spl= cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL; spl=spl->next ) { for ( i=0; i<spl->spiro_cnt-1; ++i ) if ( SPIRO_SELECTED( &spl->spiros[i]) ) { if ( foundcp ) return( false ); foundcp = &spl->spiros[i]; } } *cp = foundcp; return( foundcp!=NULL ); } else { for ( spl= cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL; spl=spl->next ) { if ( spl->first->selected ) { if ( found!=NULL ) return( false ); /* At least two points */ found = spl->first; } first = NULL; for ( spline = spl->first->next; spline!=NULL && spline!=first; spline=spline->to->next ) { if ( spline->to->selected ) { if ( found!=NULL ) return( false ); found = spline->to; } if ( first==NULL ) first = spline; } } *sp = found; return( found!=NULL ); } }
void CVMouseMovePen(CharView *cv, PressedOn *p, GEvent *event) { SplinePoint *active = cv->active_sp; 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)); if ( cv->b.sc->inspiro && hasspiro()) { CVMouseMoveSpiroPoint(cv,p); return; } if ( active==NULL ) return; if ( cv->info.x==active->nextcp.x && cv->info.y==active->nextcp.y ) return; /* In order2 fonts when the user clicks with the pen tool we'd like to */ /* leave it with the default cp (ie. the cp which makes the current point*/ /* implicit) rather than moving the cp to the base point and losing the */ /* curve */ if ( cv->info.x==active->me.x && cv->info.y==active->me.y && event->type==et_mouseup && cv->b.layerheads[cv->b.drawmode]->order2 ) return; SplineSetSpirosClear(cv->active_spl); cv->lastselpt = cv->active_sp; active->nextcp.x = cv->info.x; active->nextcp.y = cv->info.y; if ( order2_style && active->next==NULL ) { active->me.x = (active->nextcp.x + active->prevcp.x)/2; active->me.y = (active->nextcp.y + active->prevcp.y)/2; if ( active->me.x == active->nextcp.x && active->me.y == active->nextcp.y ) { active->nonextcp = active->noprevcp = true; } else { active->nonextcp = active->noprevcp = false; active->pointtype = pt_curve; } if ( active->prev!=NULL ) SplineRefigure(active->prev); SCUpdateAll(cv->b.sc); return; } else if ( active->nextcp.x==active->me.x && active->nextcp.y==active->me.y ) { active->prevcp = active->me; active->nonextcp = active->noprevcp = true; active->pointtype = pt_corner; } else { active->prevcp.x = active->me.x - (active->nextcp.x-active->me.x); active->prevcp.y = active->me.y - (active->nextcp.y-active->me.y); active->nonextcp = active->noprevcp = false; active->nextcpdef = active->prevcpdef = false; active->pointtype = pt_curve; } if ( cv->b.layerheads[cv->b.drawmode]->order2 ) { if ( active->prev!=NULL ) { if ( active->noprevcp ) active->prev->from->nonextcp = true; else { active->prev->from->nextcp = active->prevcp; active->prev->from->nonextcp = false; } SplinePointNextCPChanged2(active->prev->from); SplineRefigureFixup(active->prev); } if ( active->next!=NULL ) { if ( active->nonextcp ) active->next->to->noprevcp = true; else { active->next->to->prevcp = active->nextcp; active->next->to->noprevcp = false; } SplineRefigureFixup(active->next); } } else { if ( active->prev!=NULL ) SplineRefigure(active->prev); if ( active->next!=NULL ) SplineRefigure(active->next); } CPUpdateInfo(cv,event); SCUpdateAll(cv->b.sc); }
/* 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; }
int CVOneThingSel(CharView *cv, SplinePoint **sp, SplinePointList **_spl, RefChar **ref, ImageList **img, AnchorPoint **ap, spiro_cp **scp) { /* if there is exactly one thing selected return it */ SplinePointList *spl, *found=NULL; Spline *spline; SplinePoint *foundsp=NULL; RefChar *refs, *foundref=NULL; ImageList *imgs, *foundimg=NULL; AnchorPoint *aps, *foundap=NULL; spiro_cp *foundcp = NULL; int i; *sp = NULL; *_spl=NULL; *ref=NULL; *img = NULL; *scp = NULL; if ( ap ) *ap = NULL; for ( spl= cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL; spl=spl->next ) { if ( !cv->b.sc->inspiro || !hasspiro()) { if ( spl->first->selected ) { if ( found!=NULL ) return( 0 ); /* At least two points */ found = spl; foundsp = spl->first; } for ( spline = spl->first->next; spline!=NULL ; spline=spline->to->next ) { if ( spline->to==spl->first ) break; if ( spline->to->selected ) { if ( found!=NULL ) return( 0 ); found = spl; foundsp = spline->to; } } } else { for ( i=0; i<spl->spiro_cnt-1; ++i ) { if ( SPIRO_SELECTED(&spl->spiros[i])) { if ( found ) return( 0 ); found = spl; foundcp = &spl->spiros[i]; } } } } *sp = foundsp; *scp = foundcp; *_spl = found; if ( cv->b.drawmode!=dm_grid ) { for ( refs=cv->b.layerheads[cv->b.drawmode]->refs; refs!=NULL; refs = refs->next ) { if ( refs->selected ) { if ( found!=NULL || foundref!=NULL ) return( 0 ); foundref = refs; } } *ref = foundref; if ( cv->showanchor && ap!=NULL ) { for ( aps=cv->b.sc->anchor; aps!=NULL; aps=aps->next ) { if ( aps->selected ) { if ( found!=NULL || foundref!=NULL || foundap!=NULL ) return( 0 ); foundap = aps; } } *ap = foundap; } } for ( imgs=cv->b.layerheads[cv->b.drawmode]->images; imgs!=NULL; imgs = imgs->next ) { if ( imgs->selected ) { if ( found!=NULL || foundimg!=NULL ) return( 0 ); foundimg = imgs; } } *img = foundimg; if ( found ) return( foundimg==NULL && foundref==NULL && foundap==NULL ); else if ( foundref || foundimg || foundap ) return( true ); return( false ); }
int CVOneContourSel(CharView *cv, SplinePointList **_spl, RefChar **ref, ImageList **img) { /* if there is exactly one contour/image/reg selected return it */ SplinePointList *spl, *found=NULL; Spline *spline; RefChar *refs, *foundref=NULL; ImageList *imgs, *foundimg=NULL; int i; *_spl=NULL; *ref=NULL; *img = NULL; for ( spl= cv->b.layerheads[cv->b.drawmode]->splines; spl!=NULL; spl=spl->next ) { if ( !cv->b.sc->inspiro || !hasspiro()) { if ( spl->first->selected ) { if ( found!=NULL && found!=spl ) return( 0 ); /* At least two contours */ found = spl; } for ( spline = spl->first->next; spline!=NULL ; spline=spline->to->next ) { if ( spline->to==spl->first ) break; if ( spline->to->selected ) { if ( found!=NULL && found!=spl ) return( 0 ); found = spl; } } } else { for ( i=0; i<spl->spiro_cnt-1; ++i ) { if ( SPIRO_SELECTED(&spl->spiros[i])) { if ( found!=NULL && found!=spl ) return( 0 ); found = spl; } } } } *_spl = found; if ( cv->b.drawmode==dm_fore ) { for ( refs=cv->b.layerheads[cv->b.drawmode]->refs; refs!=NULL; refs = refs->next ) { if ( refs->selected ) { if ( found!=NULL || foundref!=NULL ) return( 0 ); foundref = refs; } } *ref = foundref; } for ( imgs=cv->b.layerheads[cv->b.drawmode]->images; imgs!=NULL; imgs = imgs->next ) { if ( imgs->selected ) { if ( found!=NULL || foundimg!=NULL ) return( 0 ); foundimg = imgs; } } *img = foundimg; if ( found ) return( foundimg==NULL && foundref==NULL ); else if ( foundref || foundimg ) return( true ); return( false ); }
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 }