Watch, Follow, &
Connect with Us

For forums, blogs and more please visit our
Developer Tools Community.


Welcome, Guest
Guest Settings
Help

Thread: TGPGraphicsPath Writer and Reader for Serialization (Re-post as Question)


This question is answered. Helpful answers available: 2. Correct answers available: 1.


Permlink Replies: 3 - Last Post: Dec 8, 2016 7:27 AM Last Post By: Richard Zarr
Richard Zarr

Posts: 74
Registered: 7/1/98
TGPGraphicsPath Writer and Reader for Serialization (Re-post as Question)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 23, 2016 1:47 PM
Does anyone have an implementation for a writer and reader to copy a TGPGraphicsPath object to the clipboard and paste it back (as it was in the original object)?
Mitch Wolberg

Posts: 18
Registered: 6/9/97
Re: TGPGraphicsPath Writer and Reader for Serialization (Re-post as Question)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 27, 2016 10:14 AM   in response to: Richard Zarr in response to: Richard Zarr
You might try saving it to a stream with your own custom format. If
TGPGraphicsPath doesn't have stream methods you can write it yourself.

Copy:

strm := TMemoryStream.Create ;
try
ClipDoc.SaveToStream ( strm ) ;
mh := GlobalAlloc ( GMEM_MOVEABLE , Strm.Size ) ;
ptr := GlobalLock ( mh ) ;
MoveMemory ( ptr , strm.Memory , Strm.Size ) ;
ClipBoard.SetAsHandle ( CF_LP_ENTITY_XDATA , mh );
finally
GlobalUnlock ( mh ) ;
strm.Free ;
end;

Paste:

Clipboard.Open ;
try
mh := Clipboard.GetAsHandle ( CF_LP_ENTITY_XDATA ) ;
strm := TMemoryStream.Create ;
try
strm.Size := GlobalSize ( mh ) ;
ptr := GlobalLock ( mh ) ;
Movememory ( strm.Memory , ptr , strm.Size ) ;
strm.Seek ( 0 , soBeginning ) ;
ClipDoc.LoadFromStream ( strm ) ;

Mitch Wolberg,
Rockware, Inc.

On 6/23/2016 2:47 PM, Richard Zarr wrote:

Does anyone have an implementation for a writer and reader to copy a TGPGraphicsPath object to the clipboard and paste it back (as it was in the original object)?
Richard Zarr

Posts: 74
Registered: 7/1/98
Re: TGPGraphicsPath Writer and Reader for Serialization (Re-post as Question)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Jun 29, 2016 9:44 AM   in response to: Mitch Wolberg in response to: Mitch Wolberg
Mitch Wolberg wrote:
You might try saving it to a stream with your own custom format. If
TGPGraphicsPath doesn't have stream methods you can write it yourself.

Copy:

strm := TMemoryStream.Create ;
try
ClipDoc.SaveToStream ( strm ) ;
mh := GlobalAlloc ( GMEM_MOVEABLE , Strm.Size ) ;
ptr := GlobalLock ( mh ) ;
MoveMemory ( ptr , strm.Memory , Strm.Size ) ;
ClipBoard.SetAsHandle ( CF_LP_ENTITY_XDATA , mh );
finally
GlobalUnlock ( mh ) ;
strm.Free ;
end;

Paste:

Clipboard.Open ;
try
mh := Clipboard.GetAsHandle ( CF_LP_ENTITY_XDATA ) ;
strm := TMemoryStream.Create ;
try
strm.Size := GlobalSize ( mh ) ;
ptr := GlobalLock ( mh ) ;
Movememory ( strm.Memory , ptr , strm.Size ) ;
strm.Seek ( 0 , soBeginning ) ;
ClipDoc.LoadFromStream ( strm ) ;

Mitch Wolberg,
Rockware, Inc.

On 6/23/2016 2:47 PM, Richard Zarr wrote:

Does anyone have an implementation for a writer and reader to copy a TGPGraphicsPath object to the clipboard and paste it back (as it was in the original object)?

We didn't mention that this is a component property... so all the other properties are in TEXT format (integers, bytes, strings, etc). We have a custom property that uses the TGPGraphicsPath type and need to serialize it (as text) and then de-serialize it for the paste operation. Here's the writer code we have today, but are working on trying to restore it in the paste function:

procedure TDGShapePath.WritePath(Writer: TWriter);
var
 i : Integer;
 PD : TPathData;
 pPoints : PGPPointF;
 P : TGPPointF;
begin
 // write the colors in the dynamic array.
 Writer.WriteListBegin;
 // create a path data object to receive the path data from FPath
 PD := TPathData.Create;
 try
  // get the path data
  FPath.GetPathData(PD);
  // write closed state
  Writer.WriteBoolean(FClosed);
  // write how many points
  Writer.WriteInteger(PD.Count);
  // now write the points & types
  pPoints := pointer(PD.Points);
  for i := 0 to PD.Count-1 do
   begin
    Writer.WriteInteger(PD.Types[i]);
    P := TGPPointF(pPoints^);
    Writer.WriteFloat(P.X);
    Writer.WriteFloat(P.Y);
    inc(pPoints, 1);
   end;
 finally
  Writer.WriteListEnd;
  PD.Free;
 end;
end;


The writer function above will produce something like this:

  FPath = (
    True
    5
    0
    5.000000000000000000
    5.000000000000000000
    33
    165.000000000000000000
    5.000000000000000000
    1
    165.000000000000000000
    145.000000000000000000
    1
    5.000000000000000000
    145.000000000000000000
    129
    5.000000000000000000
    5.000000000000000000)


Now what we need to do in the paste (Reader) function is to take that text and set up the structure of the path data... but there is not a SetPathData (only th GetPathData) function... this is where we are stumped... for now.

* As of 11/30/2016 this has still gone unanswered... must be pretty challenging! Anyone know how to make this work? We're still trying to figure this out! *

Edited by: Richard Zarr on Nov 30, 2016 12:00 PM

Edited by: Richard Zarr on Nov 30, 2016 12:02 PM

Edited by: Richard Zarr on Nov 30, 2016 12:03 PM

UPDATE: We figured this out for ourselves... but we felt someone else might benefit from our solution... it can probably be improved... but here it is:

procedure TMyComponent.WritePath(Writer: TWriter);
var
 i : Integer;
 PD : TPathData;
 pPoints : PGPPointF;
 P : TGPPointF;
begin
 // write the colors in the dynamic array.
 Writer.WriteListBegin;
 // create a path data object to receive the path data from FPath
 PD := TPathData.Create;
 try
  // get the path data
  FPath.GetPathData(PD);
  // write how many points
  Writer.WriteInteger(PD.Count);
  // now write the points & types
  pPoints := pointer(PD.Points);
  for i := 0 to PD.Count-1 do
   begin
    Writer.WriteInteger(PD.Types[i]);
    P := TGPPointF(pPoints^);
    Writer.WriteFloat(P.X);
    Writer.WriteFloat(P.Y);
    inc(pPoints, 1);
   end;
 finally
  Writer.WriteListEnd;
  PD.Free;
 end;
end;
 
procedure TMyComponent.ReadPath(Reader: TReader);
var
 i : integer;
 c : integer;
 bpc : integer; // bezier point count (need 4 to complete the bezier curve)
 b : byte;
 t : byte;
 P : TGPPointF;
 P1 : TGPPointF;
 PB : array[0..3] of TGPPointF; // bezier points
 procedure ResetPoints;
 begin
  P1 := P;    // for start of lines
  PB[0] := P; // for start of beziers
  bpc := 1;
 end;
// main routine starts here
begin
 Reader.ReadListBegin;
 // read how many points
 c := Reader.ReadInteger;
 // clear any points in the current path
 FPath.Reset;
 // reset the bezier points and count
 bpc := 0;
 FillChar(PB, SizeOf(PB), 0);
 // now read a type and the points...
 for i := 0 to c-1 do
  begin
   // read command / point
   b := Reader.ReadInteger; // read the type
   P.X := Reader.ReadFloat; // X coordinate
   P.Y := Reader.ReadFloat; // Y coordinate
   // get the type
   t := (b AND PathPointTypePathTypeMask);
   // now figure out what to do
   case t of
    00 :  // Move
     begin
      ResetPoints;
     end;
    01 :  // Line
     begin
      FPath.AddLine(P1, P);
      ResetPoints;
     end;
    02 :; // (reserved)
    03 :  // Bezier
     begin
      PB[bpc] := P;
      inc(bpc);
      if (bpc > 3) then // add the curve
       begin
        FPath.AddBezier(PB[0], PB[1], PB[2], PB[3]);
        // save the state and starting point for the next line / bezier
        FillChar(PB, SizeOf(PB), 0);
        ResetPoints;
       end;
     end;
    04 :; // (reserved)
    05 :; // (reserved)
    06 :; // (reserved)
    07 :; // (reserved)
   end;
   if (b AND PathPointTypeCloseSubpath > 0) then FClosed := (FPath.CloseFigure = Ok);
  end;
 Reader.ReadListEnd;
end;


Edited by: Richard Zarr on Dec 8, 2016 7:21 AM
Richard Zarr

Posts: 74
Registered: 7/1/98
Re: TGPGraphicsPath Writer and Reader for Serialization (Re-post as Question)  
Click to report abuse...   Click to reply to this thread Reply
  Posted: Dec 8, 2016 7:27 AM   in response to: Richard Zarr in response to: Richard Zarr
We figured this out on our own...see the thread for the answer we used.
Legend
Helpful Answer (5 pts)
Correct Answer (10 pts)

Server Response from: ETNAJIVE02