Recent

Author Topic: BeginPath/EndPath/FlattenPath/GetPath in Linux  (Read 4582 times)

typo

  • Hero Member
  • *****
  • Posts: 3051
BeginPath/EndPath/FlattenPath/GetPath in Linux
« on: April 17, 2015, 09:25:55 pm »
Does anyone know?
« Last Edit: April 17, 2015, 09:43:02 pm by typo »

Blaazen

  • Hero Member
  • *****
  • Posts: 2838
  • POKE 54296,15
    • Eye-Candy Controls
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #1 on: April 18, 2015, 12:16:18 am »
What should it do?
Lazarus 2.1.0 r63594 FPC 3.3.1 r40507 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/


typo

  • Hero Member
  • *****
  • Posts: 3051
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #3 on: April 18, 2015, 03:06:46 am »
I use BeginPath and EndPath to "select" a series of points which are part of a certain number of curves. Then I use FlattenPath to make the curves as simple lines and generate a new series of points, because I need these new points to draw the curves again, but this time as a series of short lines.

I would like to do the same in Linux.
« Last Edit: April 18, 2015, 03:13:34 am by typo »

Signal

  • New Member
  • *
  • Posts: 41
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #4 on: April 18, 2015, 03:39:19 am »
If the curves are arcs, you should be able to mathematically calculate the points.

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #5 on: April 18, 2015, 11:17:28 am »
They are bézier curves.

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #6 on: April 18, 2015, 11:30:40 am »
not quite the same as the gdi, it does not fall 100% on top of the gdi drawn bezier curves but here it is.

Code: [Select]
  TPoints = array of TPoint;

  PFloatPoint = ^TFloatPoint;
  TFloat = Single;
  TFloatPoint = record
    X, Y: TFloat;
  end;

function GetBezierPolyline(Control_Points: array of TPoint): TPoints;
const
  cBezierTolerance = 0.00001;
  half = 0.5;
var
   I, J, ArrayLen, ResultCnt: Integer;
   CtrlPts: array[0..3] of TFloatPoint;

  function FixedPoint(const FP: TFloatPoint): TPoint;
  begin
    Result.X := Round(FP.X * 65536);
    Result.Y := Round(FP.Y * 65536);
  end;

  function FloatPoint(const P: TPoint): TFloatPoint;overload;
  const
    F = 1 / 65536;
  begin
    with P do
    begin
      Result.X := X * F;
      Result.Y := Y * F;
    end;
  end;

  procedure RecursiveCBezier(const p1, p2, p3, p4: TFloatPoint);
   var
     p12, p23, p34, p123, p234, p1234: TFloatPoint;
   begin
     // assess flatness of curve ...
     // http://groups.google.com/group/comp.graphics.algorithms/tree/browse_frm/thread/d85ca902fdbd746e
     if abs(p1.x + p3.x - 2*p2.x) + abs(p2.x + p4.x - 2*p3.x) +
       abs(p1.y + p3.y - 2*p2.y) + abs(p2.y + p4.y - 2*p3.y) < cBezierTolerance then
     begin
       if ResultCnt = Length(Result) then
         SetLength (Result, Length(Result) + 128);
       Result[ResultCnt] := FixedPoint(p4);
       Inc(ResultCnt);
     end else
     begin
       p12.X := (p1.X + p2.X) *half;
       p12.Y := (p1.Y + p2.Y) *half;
       p23.X := (p2.X + p3.X) *half;
       p23.Y := (p2.Y + p3.Y) *half;
       p34.X := (p3.X + p4.X) *half;
       p34.Y := (p3.Y + p4.Y) *half;
       p123.X := (p12.X + p23.X) *half;
       p123.Y := (p12.Y + p23.Y) *half;
       p234.X := (p23.X + p34.X) *half;
       p234.Y := (p23.Y + p34.Y) *half;
       p1234.X := (p123.X + p234.X) *half;
       p1234.Y := (p123.Y + p234.Y) *half;
       RecursiveCBezier(p1, p12, p123, p1234);
       RecursiveCBezier(p1234, p234, p34, p4);
     end;
   end;

begin
   //first check that the 'control_points' count is valid ...
   ArrayLen := Length(Control_Points);
   if (ArrayLen < 4) or ((ArrayLen -1) mod 3 <> 0) then Exit;

   SetLength(Result, 128);
   Result[0] := Control_Points[0];
   ResultCnt := 1;
   for I := 0 to (ArrayLen div 3)-1 do
   begin
     for J := 0 to 3 do
       CtrlPts[J] := FloatPoint(Control_Points[I*3 +J]);
     RecursiveCBezier(CtrlPts[0], CtrlPts[1], CtrlPts[2], CtrlPts[3]);
   end;
   SetLength(Result, ResultCnt);
end;
based on code posted on the embarcadero newsgroups from AngusJ .
« Last Edit: April 18, 2015, 11:34:37 am by taazz »
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #7 on: April 18, 2015, 05:42:00 pm »
This seems to work until now, but causes an external SIGSEGV when app closes. Exception occurs on TControl.Destructor procedure at the line:

Code: [Select]
FreeThenNil(FAccessibleObject);
« Last Edit: April 18, 2015, 05:45:05 pm by typo »

taazz

  • Hero Member
  • *****
  • Posts: 5365
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #8 on: April 18, 2015, 06:05:40 pm »
can you post a small test case that shows the problem? I have used it my self with out any problems so far but I only used on one curve not multiple (ee 4 points). A test case will help me debug any memory leaks that might exists.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

typo

  • Hero Member
  • *****
  • Posts: 3051
Re: BeginPath/EndPath/FlattenPath/GetPath in Linux
« Reply #9 on: April 18, 2015, 06:47:55 pm »
I can not have the same error on a separate project. Thanks.

 

TinyPortal © 2005-2018