static real SplineFindMinXAtY(Spline *spline,real y,real min) { extended t,t1,t2,tbase,val; Spline1D *xsp; if ( y>spline->from->me.y && y>spline->from->nextcp.y && y>spline->to->me.y && y>spline->to->prevcp.y ) return( min ); if ( y<spline->from->me.y && y<spline->from->nextcp.y && y<spline->to->me.y && y<spline->to->prevcp.y ) return( min ); if ( min!=NOTREACHED ) { if ( min<=spline->from->me.x && min<=spline->from->nextcp.x && min<=spline->to->me.x && min<=spline->to->prevcp.x ) return( min ); } xsp = &spline->splines[0]; SplineFindExtrema(&spline->splines[1], &t1, &t2 ); tbase = 0; if ( t1!=-1 ) { t = SplineSolve(&spline->splines[1],0,t1,y); if ( t>=0 && t<=1 ) { val = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d; if ( min==NOTREACHED || val<min ) min = val; } tbase = t1; } if ( t2!=-1 ) { t = SplineSolve(&spline->splines[1],tbase,t2,y); if ( t>=0 && t<=1 ) { val = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d; if ( min==NOTREACHED || val<min ) min = val; } tbase = t2; } t = SplineSolve(&spline->splines[1],tbase,1.0,y); if ( t>=0 && t<=1 ) { val = ((xsp->a*t+xsp->b)*t+xsp->c)*t + xsp->d; if ( min==NOTREACHED || val<min ) min = val; } return( min ); }
static void SplineFindEdges(Spline *spline,struct charone *ch, WidthInfo *wi) { Spline1D *xsp, *ysp; extended t1, t2; double t, toff, ymin, ymax; /* first try the end points */ PtFindEdges(spline->to->me.x,spline->to->me.y,ch,wi); PtFindEdges(spline->from->me.x,spline->from->me.y,ch,wi); /* then try the extrema of the spline (assuming they are between t=(0,1) */ xsp = &spline->splines[0]; ysp = &spline->splines[1]; SplineFindExtrema(xsp, &t1, &t2 ); if ( t1!=-1 ) PtFindEdges( ((xsp->a*t1+xsp->b)*t1+xsp->c)*t1+xsp->d, ((ysp->a*t1+ysp->b)*t1+ysp->c)*t1+ysp->d, ch,wi); if ( t2!=-1 ) PtFindEdges( ((xsp->a*t2+xsp->b)*t2+xsp->c)*t2+xsp->d, ((ysp->a*t2+ysp->b)*t2+ysp->c)*t2+ysp->d, ch,wi); ymin = ymax = spline->from->me.y; if ( spline->from->nextcp.y > ymax ) ymax = spline->from->nextcp.y; if ( spline->from->nextcp.y < ymin ) ymin = spline->from->nextcp.y; if ( spline->to->prevcp.y > ymax ) ymax = spline->to->prevcp.y; if ( spline->to->prevcp.y < ymin ) ymin = spline->to->prevcp.y; if ( spline->to->me.y > ymax ) ymax = spline->to->me.y; if ( spline->to->me.y < ymin ) ymin = spline->to->me.y; if ( ymin!=ymax ) { toff = wi->decimation/(2*(ymax-ymin)); for ( t=toff; t<1; t+=toff ) { PtFindEdges( ((xsp->a*t+xsp->b)*t+xsp->c)*t+xsp->d, ((ysp->a*t+ysp->b)*t+ysp->c)*t+ysp->d, ch,wi); } } }
static void AddSpline(EdgeList *es, Spline *sp ) { real t1=2, t2=2, t; real b2_fourac; real fm, tm; Spline1D *msp = &sp->splines[es->major], *osp = &sp->splines[es->other]; /* Find the points of extrema on the curve discribing y behavior */ if ( !RealNear(msp->a,0) ) { /* cubic, possibly 2 extrema (possibly none) */ b2_fourac = 4*msp->b*msp->b - 12*msp->a*msp->c; if ( b2_fourac>=0 ) { b2_fourac = sqrt(b2_fourac); t1 = CheckExtremaForSingleBitErrors(msp,(-2*msp->b - b2_fourac) / (6*msp->a)); t2 = CheckExtremaForSingleBitErrors(msp,(-2*msp->b + b2_fourac) / (6*msp->a)); if ( t1>t2 ) { real temp = t1; t1 = t2; t2 = temp; } else if ( t1==t2 ) t2 = 2.0; /* check for curves which have such a small slope they might */ /* as well be horizontal */ fm = es->major==1?sp->from->me.y:sp->from->me.x; tm = es->major==1?sp->to->me.y:sp->to->me.x; if ( fm==tm ) { real m1, m2, d1, d2; m1 = m2 = fm; if ( t1>0 && t1<1 ) m1 = ((msp->a*t1+msp->b)*t1+msp->c)*t1 + msp->d; if ( t2>0 && t2<1 ) m2 = ((msp->a*t2+msp->b)*t2+msp->c)*t2 + msp->d; d1 = (m1-fm)*es->scale; d2 = (m2-fm)*es->scale; if ( d1>-.5 && d1<.5 && d2>-.5 && d2<.5 ) { sp->ishorvert = true; if ( es->genmajoredges ) AddMajorEdge(es,sp); return; /* Pretend it's horizontal, ignore it */ } } } } else if ( !RealNear(msp->b,0) ) { /* Quadratic, at most one extremum */ t1 = -msp->c/(2.0*msp->b); } else if ( !RealNear(msp->c,0) ) { /* linear, no points of extrema */ } else { sp->ishorvert = true; if ( es->genmajoredges ) AddMajorEdge(es,sp); return; /* Horizontal line, ignore it */ } if ( RealNear(t1,0)) t1=0; if ( RealNear(t1,1)) t1=1; if ( RealNear(t2,0)) t2=0; if ( RealNear(t2,1)) t2=1; if ( RealNear(t1,t2)) t2=2; t=0; if ( t1>0 && t1<1 ) { AddEdge(es,sp,0,t1); t = t1; } if ( t2>0 && t2<1 ) { AddEdge(es,sp,t,t2); t = t2; } AddEdge(es,sp,t,1.0); if ( es->interesting ) { /* Also store up points of extrema in X as interesting (we got the endpoints, just internals now)*/ extended ot1, ot2; int mpos; SplineFindExtrema(osp,&ot1,&ot2); if ( ot1>0 && ot1<1 ) { mpos = (int) ceil( ( ((msp->a*ot1+msp->b)*ot1+msp->c)*ot1+msp->d )*es->scale-es->mmin ); es->interesting[mpos] = 1; } if ( ot2>0 && ot2<1 ) { mpos = (int) ceil( ( ((msp->a*ot2+msp->b)*ot2+msp->c)*ot2+msp->d )*es->scale-es->mmin ); es->interesting[mpos] = 1; } } }