1 /* Copyright (C) 2000-2008 by George Williams */
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "splinefont.h"
32 # include <ieeefp.h> /* Solaris defines isnan in ieeefp rather than math.h */
35 /* The slight errors introduced by the optimizer turn out to have nasty */
36 /* side effects. An error on the order of 7e-8 in splines[1].b caused */
37 /* the rasterizer to have kaniptions */
38 void SplineRefigure3(Spline
*spline
) {
39 SplinePoint
*from
= spline
->from
, *to
= spline
->to
;
40 Spline1D
*xsp
= &spline
->splines
[0], *ysp
= &spline
->splines
[1];
44 if ( RealNear(from
->me
.x
,to
->me
.x
) && RealNear(from
->me
.y
,to
->me
.y
))
45 IError("Zero length spline created");
47 if ( spline
->acceptableextrema
)
49 xsp
->d
= from
->me
.x
; ysp
->d
= from
->me
.y
;
50 if ( from
->nonextcp
) from
->nextcp
= from
->me
;
51 else if ( from
->nextcp
.x
==from
->me
.x
&& from
->nextcp
.y
== from
->me
.y
) from
->nonextcp
= true;
52 if ( to
->noprevcp
) to
->prevcp
= to
->me
;
53 else if ( to
->prevcp
.x
==to
->me
.x
&& to
->prevcp
.y
== to
->me
.y
) to
->noprevcp
= true;
54 if ( from
->nonextcp
&& to
->noprevcp
) {
55 spline
->islinear
= true;
56 xsp
->c
= to
->me
.x
-from
->me
.x
;
57 ysp
->c
= to
->me
.y
-from
->me
.y
;
61 /* from p. 393 (Operator Details, curveto) Postscript Lang. Ref. Man. (Red book) */
62 xsp
->c
= 3*(from
->nextcp
.x
-from
->me
.x
);
63 ysp
->c
= 3*(from
->nextcp
.y
-from
->me
.y
);
64 xsp
->b
= 3*(to
->prevcp
.x
-from
->nextcp
.x
)-xsp
->c
;
65 ysp
->b
= 3*(to
->prevcp
.y
-from
->nextcp
.y
)-ysp
->c
;
66 xsp
->a
= to
->me
.x
-from
->me
.x
-xsp
->c
-xsp
->b
;
67 ysp
->a
= to
->me
.y
-from
->me
.y
-ysp
->c
-ysp
->b
;
68 if ( RealNear(xsp
->c
,0)) xsp
->c
=0;
69 if ( RealNear(ysp
->c
,0)) ysp
->c
=0;
70 if ( RealNear(xsp
->b
,0)) xsp
->b
=0;
71 if ( RealNear(ysp
->b
,0)) ysp
->b
=0;
72 if ( RealNear(xsp
->a
,0)) xsp
->a
=0;
73 if ( RealNear(ysp
->a
,0)) ysp
->a
=0;
74 spline
->islinear
= false;
75 if ( ysp
->a
==0 && xsp
->a
==0 && ysp
->b
==0 && xsp
->b
==0 )
76 spline
->islinear
= true; /* This seems extremely unlikely... */
78 if ( !finite(ysp
->a
) || !finite(xsp
->a
) || !finite(ysp
->c
) || !finite(xsp
->c
) || !finite(ysp
->d
) || !finite(xsp
->d
))
79 IError("NaN value in spline creation");
80 LinearApproxFree(spline
->approx
);
81 spline
->approx
= NULL
;
82 spline
->knowncurved
= false;
83 spline
->knownlinear
= spline
->islinear
;
84 SplineIsLinear(spline
);
85 spline
->isquadratic
= false;
86 if ( !spline
->knownlinear
&& xsp
->a
==0 && ysp
->a
==0 )
87 spline
->isquadratic
= true; /* Only likely if we read in a TTF */
88 spline
->order2
= false;
90 if ( spline
->acceptableextrema
) {
91 /* I don't check "d", because changes to that reflect simple */
92 /* translations which will not affect the shape of the spline */
93 if ( !RealNear(old
.splines
[0].a
,spline
->splines
[0].a
) ||
94 !RealNear(old
.splines
[0].b
,spline
->splines
[0].b
) ||
95 !RealNear(old
.splines
[0].c
,spline
->splines
[0].c
) ||
96 !RealNear(old
.splines
[1].a
,spline
->splines
[1].a
) ||
97 !RealNear(old
.splines
[1].b
,spline
->splines
[1].b
) ||
98 !RealNear(old
.splines
[1].c
,spline
->splines
[1].c
) )
99 spline
->acceptableextrema
= false;