--- a
+++ b/tags/15/Core/Bezier.pas
@@ -0,0 +1,94 @@
+unit Bezier;
+
+interface
+
+uses Math;
+
+
+type
+  BezierPoint = record
+    x, y: double;
+  end;
+  BezierRect = record
+    x0, y0, x1, y1: double;
+  end;
+
+  BezierPoints = array [0..3] of BezierPoint;
+  BezierWeights = array [0..3] of double;
+
+procedure BezierCopy(src: BezierPoints; var tgt: BezierPoints);
+procedure BezierSetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
+procedure BezierUnsetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
+
+procedure BezierSolve(t: double; src: BezierPoints; w: BezierWeights; var solution: BezierPoint);
+function  BezierFunc(t: double; src: BezierPoints; w: BezierWeights): double;
+
+implementation
+  procedure BezierCopy(src: BezierPoints; var tgt: BezierPoints);
+  var
+    i, n: integer;
+  begin
+    n := Length(src);
+    for i  := 0 to n - 1 do
+      tgt[i] := src[i];
+  end;
+  procedure BezierSetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
+  var
+    i, n: integer;
+    f: double;
+  begin
+    n := Length(points);
+    for i := 0 to n - 1 do
+    begin
+      if (flip) then f := 1 - points[i].y
+      else f := points[i].y;
+
+      points[i].x := points[i].x * (rect.x1 - rect.x0) + rect.x0;
+      points[i].y := f * (rect.y1 - rect.y0) + rect.y0;
+    end;
+  end;
+  procedure BezierUnsetRect(var points: BezierPoints; flip: boolean; rect: BezierRect);
+  var
+    i, n: integer;
+    f: double;
+  begin
+    if ((rect.x1 - rect.x0) = 0) or ((rect.y1 - rect.y0) = 0) then Exit;
+
+    n := Length(points);
+    for i := 0 to n - 1 do
+    begin
+      points[i].x := (points[i].x - rect.x0) / (rect.x1 - rect.x0);
+      points[i].y := (points[i].y - rect.y0) / (rect.y1 - rect.y0);
+
+      if (flip) then points[i].y := 1 - points[i].y;
+    end;
+  end;
+
+  procedure BezierSolve(t: double; src: BezierPoints; w: BezierWeights; var solution: BezierPoint);
+  var
+    s, s2, s3, t2, t3, nom_x, nom_y, denom: double;
+  begin
+    s := 1 - t;
+    s2 := s * s; s3 := s * s * s;
+    t2 := t * t; t3 := t * t * t;
+
+    nom_x := w[0] * s3 * src[0].x + w[1] * s2 * 3 * t * src[1].x +
+             w[2] * s * 3 * t2 * src[2].x + w[3] * t3 * src[3].x;
+    nom_y := w[0] * s3 * src[0].y + w[1] * s2 * 3 * t * src[1].y +
+             w[2] * s * 3 * t2 * src[2].y + w[3] * t3 * src[3].y;
+    denom := w[0] * s3 + w[1] * s2 * 3 * t + w[2] * s * 3 * t2 + w[3] * t3;
+
+    if (IsNaN(nom_x)) or (IsNaN(nom_y)) or (IsNaN(denom)) then Exit;
+    if denom = 0 then Exit;
+    
+    solution.x := nom_x / denom;
+    solution.y := nom_y / denom;
+  end;
+  function BezierFunc(t: double; src: BezierPoints; w: BezierWeights): double;
+  var
+    p: BezierPoint;
+  begin
+    BezierSolve(t, src, w, p);
+    Result := p.y;
+  end;
+end.