/* Copyright (C) 2000-2008 by George Williams */ /* * 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 "pfaedit.h" #include #include #include "splinefont.h" #ifdef HAVE_IEEEFP_H # include /* Solaris defines isnan in ieeefp rather than math.h */ #endif /* The slight errors introduced by the optimizer turn out to have nasty */ /* side effects. An error on the order of 7e-8 in splines[1].b caused */ /* the rasterizer to have kaniptions */ void SplineRefigure3(Spline *spline) { SplinePoint *from = spline->from, *to = spline->to; Spline1D *xsp = &spline->splines[0], *ysp = &spline->splines[1]; Spline old; #ifdef DEBUG if ( RealNear(from->me.x,to->me.x) && RealNear(from->me.y,to->me.y)) IError("Zero length spline created"); #endif if ( spline->acceptableextrema ) old = *spline; xsp->d = from->me.x; ysp->d = from->me.y; if ( from->nonextcp ) from->nextcp = from->me; else if ( from->nextcp.x==from->me.x && from->nextcp.y == from->me.y ) from->nonextcp = true; if ( to->noprevcp ) to->prevcp = to->me; else if ( to->prevcp.x==to->me.x && to->prevcp.y == to->me.y ) to->noprevcp = true; if ( from->nonextcp && to->noprevcp ) { spline->islinear = true; xsp->c = to->me.x-from->me.x; ysp->c = to->me.y-from->me.y; xsp->a = xsp->b = 0; ysp->a = ysp->b = 0; } else { /* from p. 393 (Operator Details, curveto) Postscript Lang. Ref. Man. (Red book) */ xsp->c = 3*(from->nextcp.x-from->me.x); ysp->c = 3*(from->nextcp.y-from->me.y); xsp->b = 3*(to->prevcp.x-from->nextcp.x)-xsp->c; ysp->b = 3*(to->prevcp.y-from->nextcp.y)-ysp->c; xsp->a = to->me.x-from->me.x-xsp->c-xsp->b; ysp->a = to->me.y-from->me.y-ysp->c-ysp->b; if ( RealNear(xsp->c,0)) xsp->c=0; if ( RealNear(ysp->c,0)) ysp->c=0; if ( RealNear(xsp->b,0)) xsp->b=0; if ( RealNear(ysp->b,0)) ysp->b=0; if ( RealNear(xsp->a,0)) xsp->a=0; if ( RealNear(ysp->a,0)) ysp->a=0; spline->islinear = false; if ( ysp->a==0 && xsp->a==0 && ysp->b==0 && xsp->b==0 ) spline->islinear = true; /* This seems extremely unlikely... */ } if ( !isfinite(ysp->a) || !isfinite(xsp->a) || !isfinite(ysp->c) || !isfinite(xsp->c) || !isfinite(ysp->d) || !isfinite(xsp->d)) IError("NaN value in spline creation"); LinearApproxFree(spline->approx); spline->approx = NULL; spline->knowncurved = false; spline->knownlinear = spline->islinear; SplineIsLinear(spline); spline->isquadratic = false; if ( !spline->knownlinear && xsp->a==0 && ysp->a==0 ) spline->isquadratic = true; /* Only likely if we read in a TTF */ spline->order2 = false; if ( spline->acceptableextrema ) { /* I don't check "d", because changes to that reflect simple */ /* translations which will not affect the shape of the spline */ if ( !RealNear(old.splines[0].a,spline->splines[0].a) || !RealNear(old.splines[0].b,spline->splines[0].b) || !RealNear(old.splines[0].c,spline->splines[0].c) || !RealNear(old.splines[1].a,spline->splines[1].a) || !RealNear(old.splines[1].b,spline->splines[1].b) || !RealNear(old.splines[1].c,spline->splines[1].c) ) spline->acceptableextrema = false; } }