Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
static void
bezctx_ff_quadto(bezctx *z, double xm, double ym, double x3, double y3)
{
    bezctx_ff *bc = (bezctx_ff *)z;
    double x0, y0;
    double x1, y1;
    double x2, y2;
    SplinePoint *sp;

    if ( !finite(xm) || !finite(ym) || !finite(x3) || !finite(y3)) {
	nancheck(bc);
	xm = ym = x3 = y3 = 0;
    }
    sp = SplinePointCreate(x3,y3);
    x0 = bc->ss->last->me.x;
    y0 = bc->ss->last->me.y;
    x1 = xm + (1./3) * (x0 - xm);
    y1 = ym + (1./3) * (y0 - ym);
    x2 = xm + (1./3) * (x3 - xm);
    y2 = ym + (1./3) * (y3 - ym);
    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;
}
Ejemplo n.º 4
0
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 );
}
Ejemplo n.º 5
0
/* This routine creates a linear spline from the previous point specified to this one */
static void bezctx_ff_lineto(bezctx *z,double x,double y) {
   bezctx_ff *bc=(bezctx_ff *) z;
   SplinePoint *sp;

   if (!isfinite(x) || !isfinite(y)) {
      nancheck(bc);
      x=y=0;
   }
   sp=SplinePointCreate(x, y);
   if (sp != NULL && SplineMake3(bc->ss->last, sp) != NULL)
      bc->ss->last=sp;
}
Ejemplo n.º 6
0
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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
/* So we allocate a new SplineSet, and then add the first point to it */
static void bezctx_ff_moveto(bezctx *z,double x,double y,int is_open) {
   bezctx_ff *bc=(bezctx_ff *) z;

   if (!isfinite(x) || !isfinite(y)) {	/* Protection against NaNs */
      nancheck(bc);
      x=y=0;
   }
   if (!bc->is_open) {
      SplineSet *ss;

      if ((ss=(SplineSet *) calloc(1, sizeof(SplineSet)))==NULL)
	 return;
      ss->next=bc->ss;
      bc->ss=ss;
   }
   bc->ss->first=bc->ss->last=SplinePointCreate(x, y);
   bc->is_open=is_open;
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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 );
}
Ejemplo n.º 11
0
/* 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;
}