Преглед на файлове

add convert shape to curve

Johann преди 6 години
родител
ревизия
02d598beb1

+ 7 - 1
lazpaint/lazpaintmainform.lfm

@@ -8562,7 +8562,7 @@ object FMain: TFMain
     object ToolSpline: TAction
       Category = 'Tool'
       Caption = 'Curve'
-      Hint = 'Spline'
+      Hint = 'Curve'
       ImageIndex = 22
       OnExecute = ToolAnyExecute
     end
@@ -8710,6 +8710,12 @@ object FMain: TFMain
       OnExecute = EditShapeAlignBottomExecute
       OnUpdate = EditShapeAlignBottomUpdate
     end
+    object EditShapeToCurve: TAction
+      Category = 'Edit'
+      Hint = 'Convert shape to curve'
+      OnExecute = EditShapeToCurveExecute
+      OnUpdate = EditShapeToCurveUpdate
+    end
   end
   object ColorDialog1: TColorDialog
     Title = 'Choose color'

+ 14 - 0
lazpaint/lazpaintmainform.pas

@@ -28,6 +28,7 @@ type
   { TFMain }
 
   TFMain = class(TForm)
+    EditShapeToCurve: TAction;
     EditShapeAlignBottom: TAction;
     EditShapeCenterVertically: TAction;
     EditShapeAlignTop: TAction;
@@ -463,6 +464,8 @@ type
     procedure EditShapeCenterHorizontallyUpdate(Sender: TObject);
     procedure EditShapeCenterVerticallyExecute(Sender: TObject);
     procedure EditShapeCenterVerticallyUpdate(Sender: TObject);
+    procedure EditShapeToCurveExecute(Sender: TObject);
+    procedure EditShapeToCurveUpdate(Sender: TObject);
     procedure FileChooseEntryExecute(Sender: TObject);
     procedure FileChooseEntryUpdate(Sender: TObject);
     procedure FileImport3DUpdate(Sender: TObject);
@@ -2980,6 +2983,17 @@ begin
   EditShapeCenterVertically.Enabled := ToolManager.ToolProvideCommand(tcCenterVertically);
 end;
 
+procedure TFMain.EditShapeToCurveExecute(Sender: TObject);
+begin
+  if ToolManager.CurrentTool is TVectorialTool then ChooseTool(ptEditShape);
+  ToolManager.ToolCommand(tcShapeToSpline);
+end;
+
+procedure TFMain.EditShapeToCurveUpdate(Sender: TObject);
+begin
+  EditShapeToCurve.Enabled := ToolManager.ToolProvideCommand(tcShapeToSpline);
+end;
+
 procedure TFMain.FileChooseEntryExecute(Sender: TObject);
 var
   openParams: TVariableSet;

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.ar.po

@@ -217,6 +217,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "تراجع"
@@ -1218,9 +1222,10 @@ msgid "Curve"
 msgstr "منحنى"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "رتب"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "منحنى"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.cs.po

@@ -213,6 +213,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Vrátit zpět"
@@ -1215,9 +1219,10 @@ msgid "Curve"
 msgstr "Křivka"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Spline"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Křivka"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.de.po

@@ -228,6 +228,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Rückgängig"
@@ -1230,9 +1234,10 @@ msgid "Curve"
 msgstr "Kurve"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Polynomzug (Spline)"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Kurve"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 9 - 3
lazpaint/release/bin/i18n/lazpaint.es.po

@@ -210,6 +210,10 @@ msgstr "Centrar la forma horizontalmente"
 msgid "Center shape vertically"
 msgstr "Centrar la forma verticalmente"
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr "Convertir forma a curva"
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Deshacer"
@@ -1209,9 +1213,10 @@ msgid "Curve"
 msgstr "Curva"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Ranura"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Curva"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"
@@ -2314,3 +2319,4 @@ msgstr "Capa vectorial"
 #: uresourcestrings.rsyes
 msgid "Yes"
 msgstr "Sí"
+

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.fi.po

@@ -202,6 +202,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Kumoa"
@@ -1205,9 +1209,10 @@ msgid "Curve"
 msgstr "Muodokas"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr ""
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Muodokas"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.fr.po

@@ -217,6 +217,10 @@ msgstr "Centrer la forme horizontalement"
 msgid "Center shape vertically"
 msgstr "Centrer la forme verticalement"
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr "Convertir la forme en courbe"
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Annuler"
@@ -1219,9 +1223,10 @@ msgid "Curve"
 msgstr "Courbe"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Éclisse"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Courbe"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.ja.po

@@ -217,6 +217,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "アンドゥ"
@@ -1218,9 +1222,10 @@ msgid "Curve"
 msgstr "カーブ"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "スプライン曲線"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "カーブ"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 7 - 3
lazpaint/release/bin/i18n/lazpaint.lv.po

@@ -215,6 +215,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Atsaukt"
@@ -1216,9 +1220,9 @@ msgstr "Līknes"
 
 #: tfmain.toolspline.hint
 #, fuzzy
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Pielāgots"
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Līknes"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.nl.po

@@ -237,6 +237,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Ongedaan maken"
@@ -1240,9 +1244,10 @@ msgid "Curve"
 msgstr "Kromme"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Spline"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Kromme"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 6 - 2
lazpaint/release/bin/i18n/lazpaint.po

@@ -200,6 +200,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr ""
@@ -1199,8 +1203,8 @@ msgid "Curve"
 msgstr ""
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
 msgstr ""
 
 #: tfmain.tooltext.hint

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.pt_BR.po

@@ -221,6 +221,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Desfazer"
@@ -1220,9 +1224,10 @@ msgid "Curve"
 msgstr "Curva"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Ranhura"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Curva"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.ru.po

@@ -217,6 +217,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Отменить"
@@ -1218,9 +1222,10 @@ msgid "Curve"
 msgstr "Кривая"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Сплайн"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Кривая"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 8 - 3
lazpaint/release/bin/i18n/lazpaint.sv.po

@@ -201,6 +201,10 @@ msgstr ""
 msgid "Center shape vertically"
 msgstr ""
 
+#: tfmain.editshapetocurve.hint
+msgid "Convert shape to curve"
+msgstr ""
+
 #: tfmain.editundo.caption
 msgid "Undo"
 msgstr "Ångra"
@@ -1202,9 +1206,10 @@ msgid "Curve"
 msgstr "Kurva"
 
 #: tfmain.toolspline.hint
-msgctxt "TFMAIN.TOOLSPLINE.HINT"
-msgid "Spline"
-msgstr "Spline"
+#, fuzzy
+msgctxt "tfmain.toolspline.hint"
+msgid "Curve"
+msgstr "Kurva"
 
 #: tfmain.tooltext.hint
 msgctxt "TFMAIN.TOOLTEXT.HINT"

+ 2 - 1
lazpaint/tools/utool.pas

@@ -40,7 +40,8 @@ type
 
   TEraserMode = (emEraseAlpha, emSoften);
   TToolCommand = (tcCut, tcCopy, tcPaste, tcDelete, tcMoveUp, tcMoveDown, tcMoveToFront, tcMoveToBack,
-    tcAlignLeft, tcCenterHorizontally, tcAlignRight, tcAlignTop, tcCenterVertically, tcAlignBottom);
+    tcAlignLeft, tcCenterHorizontally, tcAlignRight, tcAlignTop, tcCenterVertically, tcAlignBottom,
+    tcShapeToSpline);
 
 function GradientColorSpaceToDisplay(AValue: TBGRAColorInterpolation): string;
 function DisplayToGradientColorSpace(AValue: string): TBGRAColorInterpolation;

+ 27 - 0
lazpaint/tools/utoolvectorial.pas

@@ -119,6 +119,7 @@ type
     function GetCurrentSplineMode: TToolSplineMode;
     procedure SetCurrentSplineMode(AMode: TToolSplineMode);
     function IsGradientShape(AShape: TVectorShape): boolean;
+    function ConvertToSpline: boolean;
   public
     constructor Create(AManager: TToolManager); override;
     destructor Destroy; override;
@@ -891,6 +892,26 @@ begin
         (not (vsfOutlineFill in AShape.Fields) or (AShape.OutlineFill.FillType = vftNone));
 end;
 
+function TEditShapeTool.ConvertToSpline: boolean;
+var
+  shapeBefore: TVectorShape;
+  orig: TVectorOriginal;
+  shapeAfter: TCurveShape;
+begin
+  if IsVectorOriginal and Assigned(GetVectorOriginal.SelectedShape) and
+    TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape) then
+  begin
+    orig := GetVectorOriginal;
+    shapeBefore:= orig.SelectedShape;
+    shapeAfter := TCurveShape.CreateFrom(orig, shapeBefore);
+    shapeAfter.JoinStyle := pjsRound;
+    orig.ReplaceShape(orig.IndexOfShape(shapeBefore), shapeAfter);
+    orig.SelectShape(shapeAfter);
+    result := true;
+  end else
+    result := false;
+end;
+
 constructor TEditShapeTool.Create(AManager: TToolManager);
 begin
   inherited Create(AManager);
@@ -1116,6 +1137,7 @@ begin
         tcAlignLeft..tcAlignBottom: AlignShape(GetVectorOriginal.SelectedShape, ACommand,
                      Manager.Image.LayerOriginalMatrix[Manager.Image.CurrentLayerIndex],
                      rect(0,0,Manager.Image.Width,Manager.Image.Height));
+        tcShapeToSpline: result := ConvertToSpline;
         else result := false;
       end;
       BindOriginalEvent(false);
@@ -1153,6 +1175,9 @@ begin
   case ACommand of
   tcCut,tcCopy,tcDelete: result:= IsVectorOriginal and not Assigned(FSelectionRect)
                                   and Assigned(GetVectorOriginal.SelectedShape);
+  tcShapeToSpline: result:= IsVectorOriginal and not Assigned(FSelectionRect)
+                            and Assigned(GetVectorOriginal.SelectedShape)
+                            and TCurveShape.CanCreateFrom(GetVectorOriginal.SelectedShape);
   tcAlignLeft..tcAlignBottom: result:= (IsVectorOriginal and not Assigned(FSelectionRect)
                                         and Assigned(GetVectorOriginal.SelectedShape)) or
                                        (Assigned(FOriginalRect) or Assigned(FSelectionRect));
@@ -1789,6 +1814,8 @@ function TVectorialTool.ToolProvideCommand(ACommand: TToolCommand): boolean;
 begin
   case ACommand of
   tcCopy,tcCut: Result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape);
+  tcShapeToSpline: result:= not IsSelectingTool and not FQuickDefine and Assigned(FShape)
+                            and TCurveShape.CanCreateFrom(FShape);
   tcAlignLeft..tcAlignBottom: Result:= not FQuickDefine and Assigned(FShape);
   tcMoveDown,tcMoveToBack: result := not IsSelectingTool and not FQuickDefine and Assigned(FShape)
           and not AlwaysRasterizeShape and Manager.Image.SelectionMaskEmpty and not FLayerWasEmpty;

+ 1 - 1
lazpaint/umenu.pas

@@ -380,7 +380,7 @@ begin
     if (Caption = '') and (Hint <> '') then Caption := Hint;
 
   AddMenus('MenuFile',   'FileNew,FileOpen,LayerFromFile,FileChooseEntry,FileReload,MenuRecentFiles,-,FileSave,FileSaveAsInSameFolder,FileSaveAs,-,FileImport3D,-,FilePrint,-,'+ImageBrowser+'FileRememberSaveFormat,ForgetDialogAnswers,MenuLanguage,*');
-  AddMenus('MenuEdit',   'EditUndo,EditRedo,-,EditCut,EditCopy,EditPaste,EditPasteAsNew,EditPasteAsNewLayer,EditDeleteSelection,-,EditMoveUp,EditMoveToFront,EditMoveDown,EditMoveToBack,EditShapeAlign,-,EditSelectAll,EditInvertSelection,EditSelectionFit,EditDeselect');
+  AddMenus('MenuEdit',   'EditUndo,EditRedo,-,EditCut,EditCopy,EditPaste,EditPasteAsNew,EditPasteAsNewLayer,EditDeleteSelection,-,EditMoveUp,EditMoveToFront,EditMoveDown,EditMoveToBack,EditShapeAlign,EditShapeToCurve,-,EditSelectAll,EditInvertSelection,EditSelectionFit,EditDeselect');
   AddMenus('MenuSelect', 'EditSelection,FileLoadSelection,FileSaveSelectionAs,-,EditSelectAll,EditInvertSelection,EditSelectionFit,EditDeselect,-,ToolSelectRect,ToolSelectEllipse,ToolSelectPoly,ToolSelectSpline,-,ToolMoveSelection,ToolRotateSelection,SelectionHorizontalFlip,SelectionVerticalFlip,-,ToolSelectPen,ToolMagicWand');
   AddMenus('MenuView',   'ViewGrid,ViewZoomOriginal,ViewZoomIn,ViewZoomOut,ViewZoomFit,-,ViewToolBox,ViewColors,ViewPalette,ViewLayerStack,ViewImageList,ViewStatusBar,-,*,-,ViewDarkTheme,ViewWorkspaceColor,MenuIconSize');
   AddMenus('MenuImage',  'ImageCrop,ImageCropLayer,ImageFlatten,MenuRemoveTransparency,-,ImageNegative,ImageLinearNegative,ImageSwapRedBlue,-,ImageChangeCanvasSize,ImageRepeat,-,ImageResample,ImageSmartZoom3,-,ImageRotateCW,ImageRotateCCW,ImageHorizontalFlip,ImageVerticalFlip');

+ 74 - 2
lazpaintcontrols/lcvectorpolyshapes.pas

@@ -171,7 +171,10 @@ type
   public
     class function Usermodes: TVectorShapeUsermodes; override;
     constructor Create(AContainer: TVectorOriginal); override;
-    function AddPoint(const APoint: TPointF): integer; override;
+    constructor CreateFrom(AContainer: TVectorOriginal; AShape: TVectorShape);
+    class function CanCreateFrom(AShape: TVectorShape): boolean;
+    function AddPoint(const APoint: TPointF): integer; overload; override;
+    function AddPoint(const APoint: TPointF; AMode: TEasyBezierCurveMode): integer; overload;
     procedure KeyPress(UTF8Key: string; var AHandled: boolean); override;
     procedure LoadFromStorage(AStorage: TBGRACustomOriginalStorage); override;
     procedure SaveToStorage(AStorage: TBGRACustomOriginalStorage); override;
@@ -186,7 +189,7 @@ procedure ApplyArrowStyle(AArrow: TBGRACustomArrow; AStart: boolean; AKind: TArr
 implementation
 
 uses BGRAPen, BGRAFillInfo, BGRAPath, math, LCVectorialFill,
-  BGRAArrow;
+  BGRAArrow, LCVectorRectShapes;
 
 function StrToArrowKind(AStr: string): TArrowKind;
 var
@@ -1138,6 +1141,69 @@ begin
   FSplineStyle:= ssEasyBezier;
 end;
 
+constructor TCurveShape.CreateFrom(AContainer: TVectorOriginal;
+  AShape: TVectorShape);
+var
+  r: TCustomRectShape;
+  u, v: TPointF;
+  p: TCustomPolypointShape;
+  i: Integer;
+  f: TVectorShapeFields;
+  sq2m1: single;
+begin
+  Create(AContainer);
+  if AShape is TEllipseShape then
+  begin
+    r := AShape as TCustomRectShape;
+    u := r.XAxis-r.Origin;
+    v := r.YAxis-r.Origin;
+    sq2m1 := sqrt(2)-1;
+    AddPoint(r.Origin-v+u*sq2m1);
+    AddPoint(r.Origin-v*sq2m1+u);
+    AddPoint(r.Origin+v*sq2m1+u);
+    AddPoint(r.Origin+v+u*sq2m1);
+    AddPoint(r.Origin+v-u*sq2m1);
+    AddPoint(r.Origin+v*sq2m1-u);
+    AddPoint(r.Origin-v*sq2m1-u);
+    AddPoint(r.Origin-v-u*sq2m1);
+    Closed := true;
+  end else
+  if AShape is TRectShape then
+  begin
+    r := AShape as TCustomRectShape;
+    u := r.XAxis-r.Origin;
+    v := r.YAxis-r.Origin;
+    AddPoint(r.Origin-v-u, cmAngle);
+    AddPoint(r.Origin-v+u, cmAngle);
+    AddPoint(r.Origin+v+u, cmAngle);
+    AddPoint(r.Origin+v-u, cmAngle);
+    Closed := true;
+  end else
+  if AShape is TPolylineShape then
+  begin
+    p := AShape as TCustomPolypointShape;
+    for i := 0 to p.PointCount-1 do
+      AddPoint(p.Points[i], cmAngle);
+    Closed := p.Closed;
+  end else
+    raise exception.Create('Shape not handled');
+
+  f := AShape.Fields;
+  if vsfPenFill in f then PenFill.Assign(AShape.PenFill);
+  if vsfPenWidth in f then PenWidth := AShape.PenWidth;
+  if vsfPenStyle in f then PenStyle := AShape.PenStyle;
+  if vsfJoinStyle in f then JoinStyle := AShape.JoinStyle;
+  if vsfBackFill in f then BackFill.Assign(AShape.BackFill);
+end;
+
+class function TCurveShape.CanCreateFrom(AShape: TVectorShape): boolean;
+begin
+  result := (AShape is TEllipseShape) or
+    (AShape is TRectShape) or
+    ((AShape is TPolylineShape) and not
+     (AShape is TCurveShape));
+end;
+
 function TCurveShape.AddPoint(const APoint: TPointF): integer;
 begin
   if (PointCount > 1) and (APoint = Points[PointCount-1]) then
@@ -1150,6 +1216,12 @@ begin
   else Result:=inherited AddPoint(APoint);
 end;
 
+function TCurveShape.AddPoint(const APoint: TPointF; AMode: TEasyBezierCurveMode): integer;
+begin
+  result := inherited AddPoint(APoint);
+  CurveMode[result] := AMode;
+end;
+
 procedure TCurveShape.KeyPress(UTF8Key: string; var AHandled: boolean);
 var
   targetPoint: Integer;