inline code for point-generation
authorClaus Gittinger <cg@exept.de>
Wed, 12 Feb 1997 19:15:05 +0100
changeset 492 56d74636cb69
parent 491 433097e01416
child 493 5e89f340db0f
inline code for point-generation
Bezier.st
--- a/Bezier.st	Wed Feb 12 15:17:03 1997 +0100
+++ b/Bezier.st	Wed Feb 12 19:15:05 1997 +0100
@@ -222,64 +222,206 @@
 addPointsFromStartX:p1X y:p1Y control1X:p2X y:p2Y control2X:p3X y:p3Y endX:p4X y:p4Y to:aCollection
     "actual workHorse for point computation"
 
-    |x0 y0 x1 y1 x2 y2 t d dist dx3 dy3
-      midX01 midY01 midX12 midY12 x1p y1p xm ym|
+    |x1 y1 x2 y2 x3 y3 t d dist dx3 dy3
+     midX12 midY12 midX23 midY23 x1p y1p xm ym|
+
+%{  /* OPTIONAL */
+
+    /*
+     * easy inlining; all math is done in smallIntegers
+     */
+    if (__bothSmallInteger(p1X, p1Y)
+     && __bothSmallInteger(p2X, p2Y)
+     && __bothSmallInteger(p3X, p3Y)
+     && __bothSmallInteger(p4X, p4Y)
+     && __isSmallInteger(@global(ScaledFlatness))
+     && __isFloat(@global(InverseScale))
+    ) {
+        int _x1 = __intVal(p1X);
+        int _y1 = __intVal(p1Y);
+        int _x2 = __intVal(p2X);
+        int _y2 = __intVal(p2Y);
+        int _x3 = __intVal(p3X);
+        int _y3 = __intVal(p3Y);
+        int _p4X = __intVal(p4X);
+        int _p4Y = __intVal(p4Y);
+        int _flatness = __intVal(@global(ScaledFlatness));
+        double _flatnessD = (double)_flatness;
+        double _invScaleD = __floatVal(@global(InverseScale));
+
+        for (;;) {
+            int _midX12, _midY12, _midX23, _midY23;
+            int _x1p, _y1p, _xm, _ym;
+            extern double sqrt(), ceil(), floor();
+#           define round(x)     (((x) < 0) ? ceil((x) - 0.5) : floor((x) + 0.5))
+
+            if (_p4X == _x1) {
+                int _dX1, _dX2;
+
+                _dX1 = _x2 - _x1; if (_dX1 < 0) _dX1 = -_dX1;
+                _dX2 = _x3 - _x1; if (_dX2 < 0) _dX2 = -_dX2;
+                if ((_dX1 <= _flatness) && (_dX2 <= _flatness)) break;
+            } else {
+                int _dX3, _dY3, _dX3Abs, _dY3Abs;
+
+                _dX3 = _dX3Abs = (_p4X - _x1); if (_dX3 < 0) _dX3Abs = -_dX3Abs;
+                _dY3 = _dY3Abs = (_p4Y - _y1); if (_dY3 < 0) _dY3Abs = -_dY3Abs;
+
+                if (_dX3Abs >= _dY3Abs) {
+                    double _slope = (double)_dY3 / (double)_dX3;
+                    double _t;
+                    int _d, _dist;
+
+                    _t = _slope*_slope + 1.0;
+                    _t = sqrt(_t) * _flatnessD;
+                    _t = round(_t);
+                    _d = _t;
+
+                    _t = _slope * (_x2-_x1);
+                    _t = round(_t);
+                    _dist = _t;
+                    _dist -= (_y2-_y1);
+                    if ((_dist >= 0) ? (_dist <= _d) : ((_dist + _d) >= 0)) {
+                        _t = _slope * (_x3-_x1);
+                        _t = round(_t);
+                        _dist = _t;
+                        _dist -= (_y3-_y1);
+                        if ((_dist >= 0) ? (_dist <= _d) : ((_dist + _d) >= 0)) break;
+                    }
+                } else {
+                    double _slope = (double)_dX3 / (double)_dY3;
+                    double _t;
+                    int _d, _dist;
 
-    x0 := p1X.  y0 := p1Y.
-    x1 := p2X.  y1 := p2Y.
-    x2 := p3X.  y2 := p3Y.
+                    _t = _slope*_slope + 1.0;
+                    _t = sqrt(_t) * _flatnessD;
+                    _t = round(_t);
+                    _d = _t;
+
+                    _t = _slope * (_y2-_y1);
+                    _t = round(_t);
+                    _dist = _t;
+                    _dist -= (_x2-_x1);
+                    if ((_dist >= 0) ? (_dist <= _d) : ((_dist + _d) >= 0)) {
+                        _t = _slope * (_y3-_y1);
+                        _t = round(_t);
+                        _dist = _t;
+                        _dist -= (_x3-_x1);
+                        if ((_dist >= 0) ? (_dist <= _d) : ((_dist + _d) >= 0)) break;
+                    }
+                }
+            }
+
+#           undef round
+
+            _midX12 = (_x1 + _x2) / 2;  
+            _midY12 = (_y1 + _y2) / 2;
+            _midX23 = (_x2 + _x3) / 2;  
+            _midY23 = (_y2 + _y3) / 2;
+
+            _x3 = (_x3 + _p4X) / 2;  
+            _y3 = (_y3 + _p4Y) / 2;
+            _x1p = (_midX12 + _midX23) / 2;  
+            _y1p = (_midY12 + _midY23) / 2;
+            _x2 = (_midX23 + _x3) / 2;  
+            _y2 = (_midY23 + _y3) / 2;
+            _xm = (_x1p + _x2) / 2;  
+            _ym = (_y1p + _y2) / 2;
+
+            {
+                static struct inlineCache addPoints = __ILC9(@line);
+
+                (*addPoints.ilc_func)(self, 
+                                      @symbol(addPointsFromStartX:y:control1X:y:control2X:y:endX:y:to:), 
+                                      nil, 
+                                      &addPoints, 
+                                      __MKSMALLINT(_x1), __MKSMALLINT(_y1),
+                                      __MKSMALLINT(_midX12), __MKSMALLINT(_midY12),
+                                      __MKSMALLINT(_x1p), __MKSMALLINT(_y1p),
+                                      __MKSMALLINT(_xm), __MKSMALLINT(_ym),
+                                      aCollection
+                                     );
+            }    
+
+            _x1 = _xm;  
+            _y1 = _ym;
+        }
+        {
+            static struct inlineCache add = __ILC1(@line);
+            OBJ newPoint;
+            double d_x, d_y;
+
+            d_x = _p4X * _invScaleD;
+            d_y = _p4Y * _invScaleD;
+            newPoint = __MKPOINT_DOUBLE( d_x, d_y);
+
+            (*add.ilc_func)(aCollection,
+                            @symbol(add:),
+                            nil,
+                            &add,
+                            newPoint
+                           );
+        }
+        RETURN (self);
+    }  
+%}.
+
+    x1 := p1X.  y1 := p1Y.
+    x2 := p2X.  y2 := p2Y.
+    x3 := p3X.  y3 := p3Y.
 
     [
-        p4X = x0 ifTrue:[
-            "p4X = x0, i.e. dx = 0"
-            (x1 - x0) abs <= ScaledFlatness and: [(x2 - x0) abs <= ScaledFlatness]
+        p4X = x1 ifTrue:[
+            "p4X = x1, i.e. dx = 0"
+            (x2 - x1) abs <= ScaledFlatness and: [(x3 - x1) abs <= ScaledFlatness]
         ] ifFalse:[
-            dx3 := p4X - x0.
-            dy3 := p4Y - y0.
+            dx3 := p4X - x1.
+            dy3 := p4Y - y1.
 
             (dx3 >= 0 ifTrue: [dx3] ifFalse: [0 - dx3]) >=
              (dy3 >= 0 ifTrue: [dy3] ifFalse: [0 - dy3])
             ifTrue:[
                 t := dy3 asFloat / dx3.
                 d := ((1.0 + (t * t)) sqrt * ScaledFlatness) rounded.
-                dist := (t * (x1 - x0)) rounded - (y1 - y0).
+                dist := (t * (x2 - x1)) rounded - (y2 - y1).
 
                 (dist >= 0 ifTrue: [dist <= d] ifFalse: [dist + d >= 0]) 
-                and:[dist := (t * (x2 - x0)) rounded - (y2 - y0).
+                and:[dist := (t * (x3 - x1)) rounded - (y3 - y1).
                      dist >= 0 ifTrue: [dist <= d] ifFalse: [dist + d >= 0]]
             ] ifFalse:[
                 t := dx3 asFloat / dy3.
                 d := ((1.0 + (t * t)) sqrt * ScaledFlatness) rounded.
-                dist := (t * (y1 - y0)) rounded - (x1 - x0).
+                dist := (t * (y2 - y1)) rounded - (x2 - x1).
                 (dist >= 0 ifTrue: [dist <= d] ifFalse: [dist + d >= 0]) 
-                and:[dist := (t * (y2 - y0)) rounded - (x2 - x0).
+                and:[dist := (t * (y3 - y1)) rounded - (x3 - x1).
                      dist >= 0 ifTrue: [dist <= d] ifFalse: [dist + d >= 0]]
             ]
         ]
     ] whileFalse:[
-        midX01 := (x0 + x1) // 2.  
-        midY01 := (y0 + y1) // 2.
         midX12 := (x1 + x2) // 2.  
         midY12 := (y1 + y2) // 2.
+        midX23 := (x2 + x3) // 2.  
+        midY23 := (y2 + y3) // 2.
 
-        x2 := (x2 + p4X) // 2.  
-        y2 := (y2 + p4Y) // 2.
-        x1p := (midX01 + midX12) // 2.  
-        y1p := (midY01 + midY12) // 2.
-        x1 := (midX12 + x2) // 2.  
-        y1 := (midY12 + y2) // 2.
-        xm := (x1p + x1) // 2.  
-        ym := (y1p + y1) // 2.
+        x3 := (x3 + p4X) // 2.  
+        y3 := (y3 + p4Y) // 2.
+        x1p := (midX12 + midX23) // 2.  
+        y1p := (midY12 + midY23) // 2.
+        x2 := (midX23 + x3) // 2.  
+        y2 := (midY23 + y3) // 2.
+        xm := (x1p + x2) // 2.  
+        ym := (y1p + y2) // 2.
 
         self
-            addPointsFromStartX:x0 y:y0
-                      control1X:midX01 y:midY01
+            addPointsFromStartX:x1 y:y1
+                      control1X:midX12 y:midY12
                       control2X:x1p y:y1p
                            endX:xm y:ym
                              to:aCollection.
-        x0 := xm.  
-        y0 := ym.
+        x1 := xm.  
+        y1 := ym.
     ].
+
     aCollection add: (p4X asFloat * InverseScale) @ (p4Y asFloat  * InverseScale)
 
     "Created: 12.2.1997 / 15:05:52 / cg"
@@ -367,6 +509,6 @@
 !Bezier class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic2/Bezier.st,v 1.1 1997-02-12 14:17:03 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/Bezier.st,v 1.2 1997-02-12 18:15:05 cg Exp $'
 ! !
 Bezier initialize!