lcvectorclipboard.pas 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. unit LCVectorClipboard;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Clipbrd, LCLType, LCVectorOriginal, BGRATransform, BGRABitmapTypes;
  6. function CopyShapesToClipboard(AShapes: array of TVectorShape; const AMatrix: TAffineMatrix): boolean;
  7. procedure PasteShapesFromClipboard(ATargetContainer: TVectorOriginal; const ATargetMatrix: TAffineMatrix; const ABounds: TRectF);
  8. function ClipboardHasShapes: boolean;
  9. implementation
  10. uses math;
  11. var
  12. vectorClipboardFormat : TClipboardFormat;
  13. function CopyShapesToClipboard(AShapes: array of TVectorShape; const AMatrix: TAffineMatrix): boolean;
  14. var
  15. tempContainer: TVectorOriginal;
  16. mem: TMemoryStream;
  17. i, j: Integer;
  18. s: TVectorShape;
  19. multiSel: IVectorMultishape;
  20. begin
  21. result:= false;
  22. if length(AShapes)=0 then exit;
  23. tempContainer := TVectorOriginal.Create;
  24. mem := TMemoryStream.Create;
  25. try
  26. for i := 0 to high(AShapes) do
  27. begin
  28. if AShapes[i] is VectorMultiselectionFactory then
  29. begin
  30. multiSel := AShapes[i].GetAsMultishape;
  31. for j := 0 to multiSel.ShapeCount-1 do
  32. begin
  33. s := multiSel.GetShape(j).Duplicate;
  34. s.Transform(AMatrix);
  35. tempContainer.AddShape(s);
  36. end;
  37. end else
  38. begin
  39. s := AShapes[i].Duplicate;
  40. s.Transform(AMatrix);
  41. tempContainer.AddShape(s);
  42. end;
  43. end;
  44. tempContainer.SaveToStream(mem);
  45. Clipboard.Clear;
  46. mem.Position:= 0;
  47. result := Clipboard.AddFormat(vectorClipboardFormat, mem);
  48. finally
  49. mem.Free;
  50. tempContainer.Free;
  51. end;
  52. end;
  53. procedure PasteShapesFromClipboard(ATargetContainer: TVectorOriginal; const ATargetMatrix: TAffineMatrix; const ABounds: TRectF);
  54. var
  55. tempContainer: TVectorOriginal;
  56. mem: TMemoryStream;
  57. i: Integer;
  58. pastedShape: TVectorShape;
  59. pastedShapes: TVectorShapes;
  60. invMatrix, m: TAffineMatrix;
  61. pastedBounds: TRectF;
  62. ofs: TPointF;
  63. begin
  64. if not IsAffineMatrixInversible(ATargetMatrix) then exit;
  65. invMatrix := AffineMatrixInverse(ATargetMatrix);
  66. if Clipboard.HasFormat(vectorClipboardFormat) then
  67. begin
  68. mem := TMemoryStream.Create;
  69. tempContainer := TVectorOriginal.Create;
  70. try
  71. if Clipboard.GetFormat(vectorClipboardFormat, mem) then
  72. begin
  73. mem.Position:= 0;
  74. tempContainer.LoadFromStream(mem);
  75. pastedBounds := EmptyRectF;
  76. ofs := PointF(0, 0);
  77. if not ABounds.IsEmpty then
  78. begin
  79. for i := 0 to tempContainer.ShapeCount-1 do
  80. pastedBounds := pastedBounds.Union(pastedBounds,
  81. tempContainer.Shape[i].GetAlignBounds(InfiniteRect, AffineMatrixIdentity), true);
  82. if (pastedBounds.Left < ABounds.Left) and (pastedBounds.Right < ABounds.Right) then
  83. ofs.x := ceil(ABounds.Left - pastedBounds.Left) else
  84. if (pastedBounds.Right > ABounds.Right) and (pastedBounds.Left > ABounds.Left) then
  85. ofs.x := floor(ABounds.Right - pastedBounds.Right);
  86. if (pastedBounds.Top < ABounds.Top) and (pastedBounds.Bottom < ABounds.Bottom) then
  87. ofs.y := ceil(ABounds.Top - pastedBounds.Top) else
  88. if (pastedBounds.Bottom > ABounds.Bottom) and (pastedBounds.Top > ABounds.Top) then
  89. ofs.y := floor(ABounds.Bottom - pastedBounds.Bottom);
  90. end;
  91. m := invMatrix*AffineMatrixTranslation(ofs.x,ofs.y);
  92. ATargetContainer.DeselectShapes;
  93. pastedShapes := TVectorShapes.Create;
  94. for i := 0 to tempContainer.ShapeCount-1 do
  95. begin
  96. pastedShape := tempContainer.Shape[i].Duplicate;
  97. pastedShape.Transform(m);
  98. pastedShapes.Add(pastedShape);
  99. end;
  100. ATargetContainer.AddShapes(pastedShapes);
  101. ATargetContainer.SelectShapes(pastedShapes);
  102. pastedShapes.Free;
  103. end;
  104. finally
  105. tempContainer.Free;
  106. mem.Free;
  107. end;
  108. end;
  109. end;
  110. function ClipboardHasShapes: boolean;
  111. begin
  112. result := Clipboard.HasFormat(vectorClipboardFormat);
  113. end;
  114. initialization
  115. vectorClipboardFormat := RegisterClipboardFormat('TVectorOriginal');
  116. end.