mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-22 16:11:44 +02:00
Initial transformation of fpvectorial segments in classes, as well as making the number of segments dynamic
git-svn-id: trunk@16202 -
This commit is contained in:
parent
1811234b72
commit
cc2da23316
@ -10,26 +10,28 @@ object formVectorialConverter: TformVectorialConverter
|
||||
LCLVersion = '0.9.29'
|
||||
object Label1: TLabel
|
||||
Left = 8
|
||||
Height = 14
|
||||
Top = 104
|
||||
Width = 123
|
||||
Height = 17
|
||||
Top = 112
|
||||
Width = 160
|
||||
Caption = 'Location of the Input file:'
|
||||
ParentColor = False
|
||||
end
|
||||
object Label2: TLabel
|
||||
Left = 11
|
||||
Height = 96
|
||||
Height = 104
|
||||
Top = 8
|
||||
Width = 224
|
||||
Width = 229
|
||||
AutoSize = False
|
||||
Caption = 'This converter application use the fpvectorial library to convert between various different vectorial graphics formats. The type is detected from the extension and the supported types are: PDF (*.pdf), SVG (*.svg) and Corel Draw file (*.cdr).'
|
||||
Font.Height = -12
|
||||
ParentColor = False
|
||||
ParentFont = False
|
||||
WordWrap = True
|
||||
end
|
||||
object editInput: TFileNameEdit
|
||||
Left = 8
|
||||
Height = 21
|
||||
Top = 120
|
||||
Height = 22
|
||||
Top = 128
|
||||
Width = 192
|
||||
DialogOptions = []
|
||||
FilterIndex = 0
|
||||
@ -41,16 +43,16 @@ object formVectorialConverter: TformVectorialConverter
|
||||
end
|
||||
object Label3: TLabel
|
||||
Left = 8
|
||||
Height = 14
|
||||
Top = 144
|
||||
Width = 132
|
||||
Height = 17
|
||||
Top = 152
|
||||
Width = 173
|
||||
Caption = 'Full path of the Output file:'
|
||||
ParentColor = False
|
||||
end
|
||||
object editOutput: TFileNameEdit
|
||||
Left = 8
|
||||
Height = 21
|
||||
Top = 160
|
||||
Height = 22
|
||||
Top = 168
|
||||
Width = 192
|
||||
DialogOptions = []
|
||||
FilterIndex = 0
|
||||
|
@ -8,6 +8,7 @@
|
||||
<AlwaysBuild Value="False"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<MainUnit Value="0"/>
|
||||
<Title Value="fpvectorialconverter"/>
|
||||
<UseXPManifest Value="True"/>
|
||||
<Icon Value="0"/>
|
||||
@ -18,6 +19,9 @@
|
||||
<VersionInfo>
|
||||
<StringTable ProductVersion=""/>
|
||||
</VersionInfo>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
|
||||
@ -55,7 +59,7 @@
|
||||
<Filename Value="fpvectorialconverter"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)\"/>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Linking>
|
||||
|
@ -48,37 +48,79 @@ type
|
||||
the starting point is in the bottom-left corner of the document.
|
||||
The X grows to the right and the Y grows to the top.
|
||||
}
|
||||
TPathSegment = record
|
||||
{ TPathSegment }
|
||||
|
||||
TPathSegment = class
|
||||
public
|
||||
SegmentType: TSegmentType;
|
||||
X, Y, Z: Double; // Z is ignored in 2D segments
|
||||
X2, Y2, Z2: Double; // Z is ignored in 2D segments
|
||||
X3, Y3, Z3: Double; // Z is ignored in 2D segments
|
||||
// Fields for linking the list
|
||||
Previous: TPathSegment;
|
||||
Next: TPathSegment;
|
||||
end;
|
||||
|
||||
TPath = record
|
||||
{@@
|
||||
In a 2D segment, the X and Y coordinates represent usually the
|
||||
final point of the segment, being that it starts where the previous
|
||||
segment ends. The exception is for the first segment of all, which simply
|
||||
holds the starting point for the drawing and should always be of the type
|
||||
stMoveTo.
|
||||
}
|
||||
T2DSegment = class(TPathSegment)
|
||||
public
|
||||
X, Y: Double;
|
||||
end;
|
||||
|
||||
{@@
|
||||
In Bezier segments, we remain using the X and Y coordinates for the ending point.
|
||||
The starting point is where the previous segment ended, so that the intermediary
|
||||
bezier control points are [X2, Y2] and [X3, Y3].
|
||||
}
|
||||
T2DBezierSegment = class(T2DSegment)
|
||||
public
|
||||
X2, Y2: Double;
|
||||
X3, Y3: Double;
|
||||
end;
|
||||
|
||||
T3DSegment = class(TPathSegment)
|
||||
public
|
||||
{@@
|
||||
Coordinates of the end of the segment.
|
||||
For the first segment, this is the starting point.
|
||||
}
|
||||
X, Y, Z: Double;
|
||||
end;
|
||||
|
||||
T3DBezierSegment = class(T3DSegment)
|
||||
public
|
||||
X2, Y2, Z2: Double;
|
||||
X3, Y3, Z3: Double;
|
||||
end;
|
||||
|
||||
TPath = class
|
||||
Len: Integer;
|
||||
// ToDo: make the array dynamic
|
||||
Points: array[0..255] of TPathSegment;
|
||||
Points: TPathSegment; // Beginning of the double-linked list
|
||||
PointsEnd: TPathSegment; // End of the double-linked list
|
||||
CurPoint: TPathSegment; // Used in PrepareForSequentialReading and Next
|
||||
procedure Assign(APath: TPath);
|
||||
function Count(): TPathSegment;
|
||||
procedure PrepareForSequentialReading;
|
||||
function Next(): TPathSegment;
|
||||
end;
|
||||
|
||||
PPath = ^TPath;
|
||||
|
||||
{@@
|
||||
TvText represents a text in memory.
|
||||
|
||||
At the moment fonts are unsupported, only simple texts
|
||||
up to 255 chars are supported.
|
||||
}
|
||||
|
||||
TvText = record
|
||||
TvText = class
|
||||
public
|
||||
X, Y, Z: Double; // Z is ignored in 2D formats
|
||||
FontSize: integer;
|
||||
FontName: utf8string;
|
||||
Value: utf8string;
|
||||
end;
|
||||
|
||||
PText = ^TvText;
|
||||
|
||||
type
|
||||
|
||||
TvCustomVectorialWriter = class;
|
||||
@ -95,6 +137,8 @@ type
|
||||
procedure RemoveCallback(data, arg: pointer);
|
||||
function CreateVectorialWriter(AFormat: TvVectorialFormat): TvCustomVectorialWriter;
|
||||
function CreateVectorialReader(AFormat: TvVectorialFormat): TvCustomVectorialReader;
|
||||
procedure ClearTmpPath();
|
||||
procedure AppendSegmentToTmpPath(ASegment: TPathSegment);
|
||||
public
|
||||
Name: string;
|
||||
Width, Height: Double; // in millimeters
|
||||
@ -185,6 +229,9 @@ procedure RegisterVectorialWriter(
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
Str_Error_Nil_Path = ' The program attempted to add a segment before creating a path';
|
||||
|
||||
{@@
|
||||
Registers a new reader for a format
|
||||
}
|
||||
@ -276,7 +323,11 @@ end;
|
||||
}
|
||||
procedure TvVectorialDocument.RemoveCallback(data, arg: pointer);
|
||||
begin
|
||||
if data <> nil then FreeMem(data);
|
||||
{ if data <> nil then
|
||||
begin
|
||||
ldata := PObject(data);
|
||||
ldata^.Free;
|
||||
end;}
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -288,6 +339,7 @@ begin
|
||||
|
||||
FPaths := TFPList.Create;
|
||||
FTexts := TFPList.Create;
|
||||
FTmpPath := TPath.Create;
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -308,28 +360,27 @@ end;
|
||||
}
|
||||
procedure TvVectorialDocument.RemoveAllPaths;
|
||||
begin
|
||||
FPaths.ForEachCall(RemoveCallback, nil);
|
||||
// FPaths.ForEachCall(RemoveCallback, nil);
|
||||
FPaths.Clear;
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.RemoveAllTexts;
|
||||
begin
|
||||
FTexts.ForEachCall(RemoveCallback, nil);
|
||||
// FTexts.ForEachCall(RemoveCallback, nil);
|
||||
FTexts.Clear;
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddPath(APath: TPath);
|
||||
var
|
||||
Path: PPath;
|
||||
lPath: TPath;
|
||||
Len: Integer;
|
||||
begin
|
||||
Len := SizeOf(TPath);
|
||||
lPath := TPath.Create;
|
||||
lPath.Assign(APath);
|
||||
FPaths.Add(Pointer(lPath));
|
||||
//WriteLn(':>TvVectorialDocument.AddPath 1 Len = ', Len);
|
||||
Path := GetMem(Len);
|
||||
//WriteLn(':>TvVectorialDocument.AddPath 2');
|
||||
Move(APath, Path^, Len);
|
||||
//WriteLn(':>TvVectorialDocument.AddPath 3');
|
||||
FPaths.Add(Path);
|
||||
//WriteLn(':>TvVectorialDocument.AddPath 4');
|
||||
end;
|
||||
|
||||
@ -341,11 +392,19 @@ end;
|
||||
@see StartPath, AddPointToPath
|
||||
}
|
||||
procedure TvVectorialDocument.StartPath(AX, AY: Double);
|
||||
var
|
||||
segment: T2DSegment;
|
||||
begin
|
||||
ClearTmpPath();
|
||||
|
||||
FTmpPath.Len := 1;
|
||||
FTmpPath.Points[0].SegmentType := stMoveTo;
|
||||
FTmpPath.Points[0].X := AX;
|
||||
FTmpPath.Points[0].Y := AY;
|
||||
segment := T2DSegment.Create;
|
||||
segment.SegmentType := stMoveTo;
|
||||
segment.X := AX;
|
||||
segment.Y := AY;
|
||||
|
||||
FTmpPath.Points := segment;
|
||||
FTmpPath.PointsEnd := segment;
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -360,60 +419,69 @@ end;
|
||||
}
|
||||
procedure TvVectorialDocument.AddLineToPath(AX, AY: Double);
|
||||
var
|
||||
L: Integer;
|
||||
segment: T2DSegment;
|
||||
begin
|
||||
L := FTmpPath.Len;
|
||||
Inc(FTmpPath.Len);
|
||||
FTmpPath.Points[L].SegmentType := st2DLine;
|
||||
FTmpPath.Points[L].X := AX;
|
||||
FTmpPath.Points[L].Y := AY;
|
||||
segment := T2DSegment.Create;
|
||||
segment.SegmentType := st2DLine;
|
||||
segment.X := AX;
|
||||
segment.Y := AY;
|
||||
|
||||
AppendSegmentToTmpPath(segment);
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddLineToPath(AX, AY, AZ: Double);
|
||||
var
|
||||
L: Integer;
|
||||
segment: T3DSegment;
|
||||
begin
|
||||
L := FTmPPath.Len;
|
||||
Inc(FTmPPath.Len);
|
||||
FTmPPath.Points[L].SegmentType := st3DLine;
|
||||
FTmPPath.Points[L].X := AX;
|
||||
FTmPPath.Points[L].Y := AY;
|
||||
FTmPPath.Points[L].Z := AZ;
|
||||
segment := T3DSegment.Create;
|
||||
segment.SegmentType := st3DLine;
|
||||
segment.X := AX;
|
||||
segment.Y := AY;
|
||||
segment.Z := AZ;
|
||||
|
||||
AppendSegmentToTmpPath(segment);
|
||||
end;
|
||||
|
||||
{@@
|
||||
Adds a bezier element to the path. It starts where the previous element ended
|
||||
and it goes throw the control points [AX1, AY1] and [AX2, AY2] and ends
|
||||
in [AX3, AY3].
|
||||
}
|
||||
procedure TvVectorialDocument.AddBezierToPath(AX1, AY1, AX2, AY2, AX3,
|
||||
AY3: Double);
|
||||
var
|
||||
L: Integer;
|
||||
segment: T2DBezierSegment;
|
||||
begin
|
||||
L := FTmPPath.Len;
|
||||
Inc(FTmPPath.Len);
|
||||
FTmPPath.Points[L].SegmentType := st2DBezier;
|
||||
FTmPPath.Points[L].X := AX3;
|
||||
FTmPPath.Points[L].Y := AY3;
|
||||
FTmPPath.Points[L].X2 := AX1;
|
||||
FTmPPath.Points[L].Y2 := AY1;
|
||||
FTmPPath.Points[L].X3 := AX2;
|
||||
FTmPPath.Points[L].Y3 := AY2;
|
||||
segment := T2DBezierSegment.Create;
|
||||
segment.SegmentType := st2DBezier;
|
||||
segment.X := AX3;
|
||||
segment.Y := AY3;
|
||||
segment.X2 := AX1;
|
||||
segment.Y2 := AY1;
|
||||
segment.X3 := AX2;
|
||||
segment.Y3 := AY2;
|
||||
|
||||
AppendSegmentToTmpPath(segment);
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2,
|
||||
AX3, AY3, AZ3: Double);
|
||||
var
|
||||
L: Integer;
|
||||
segment: T3DBezierSegment;
|
||||
begin
|
||||
L := FTmPPath.Len;
|
||||
Inc(FTmPPath.Len);
|
||||
FTmPPath.Points[L].SegmentType := st3DBezier;
|
||||
FTmPPath.Points[L].X := AX3;
|
||||
FTmPPath.Points[L].Y := AY3;
|
||||
FTmPPath.Points[L].Z := AZ3;
|
||||
FTmPPath.Points[L].X2 := AX1;
|
||||
FTmPPath.Points[L].Y2 := AY1;
|
||||
FTmPPath.Points[L].Z2 := AZ1;
|
||||
FTmPPath.Points[L].X3 := AX2;
|
||||
FTmPPath.Points[L].Y3 := AY2;
|
||||
FTmPPath.Points[L].Z3 := AZ2;
|
||||
segment := T3DBezierSegment.Create;
|
||||
segment.SegmentType := st3DBezier;
|
||||
segment.X := AX3;
|
||||
segment.Y := AY3;
|
||||
segment.Z := AZ3;
|
||||
segment.X2 := AX1;
|
||||
segment.Y2 := AY1;
|
||||
segment.Z2 := AZ1;
|
||||
segment.X3 := AX2;
|
||||
segment.Y3 := AY2;
|
||||
segment.Z3 := AZ2;
|
||||
|
||||
AppendSegmentToTmpPath(segment);
|
||||
end;
|
||||
|
||||
{@@
|
||||
@ -430,15 +498,14 @@ procedure TvVectorialDocument.EndPath();
|
||||
begin
|
||||
if FTmPPath.Len = 0 then Exit;
|
||||
AddPath(FTmPPath);
|
||||
FTmPPath.Len := 0;
|
||||
ClearTmpPath();
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string);
|
||||
var
|
||||
lText: PText;
|
||||
lText: TvText;
|
||||
begin
|
||||
lText := GetMem(SizeOf(TvText));
|
||||
FillChar(lText^, SizeOf(TvText), 0);
|
||||
lText := TvText.Create;
|
||||
lText.Value := AText;
|
||||
lText.X := AX;
|
||||
lText.Y := AY;
|
||||
@ -495,6 +562,40 @@ begin
|
||||
if Result = nil then raise Exception.Create('Unsuported vector graphics format.');
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.ClearTmpPath();
|
||||
var
|
||||
segment, oldsegment: TPathSegment;
|
||||
begin
|
||||
// segment := FTmpPath.Points;
|
||||
// Don't free segments, because they are used when the path is added
|
||||
// while segment <> nil do
|
||||
// begin
|
||||
// oldsegment := segment;
|
||||
// segment := segment^.Next;
|
||||
// oldsegment^.Free;
|
||||
// end;
|
||||
|
||||
FTmpPath.Points := nil;
|
||||
FTmpPath.PointsEnd := nil;
|
||||
FTmpPath.Len := 0;
|
||||
end;
|
||||
|
||||
procedure TvVectorialDocument.AppendSegmentToTmpPath(ASegment: TPathSegment);
|
||||
var
|
||||
L: Integer;
|
||||
begin
|
||||
if FTmpPath.PointsEnd = nil then
|
||||
Exception.Create('[TvVectorialDocument.AppendSegmentToTmpPath]' + Str_Error_Nil_Path);
|
||||
|
||||
L := FTmpPath.Len;
|
||||
Inc(FTmpPath.Len);
|
||||
|
||||
// Adds the element to the end of the list
|
||||
FTmpPath.PointsEnd.Next := ASegment;
|
||||
ASegment.Previous := FTmpPath.PointsEnd;
|
||||
FTmpPath.PointsEnd := ASegment;
|
||||
end;
|
||||
|
||||
{@@
|
||||
Writes the document to a file.
|
||||
|
||||
@ -624,7 +725,7 @@ begin
|
||||
|
||||
if FPaths.Items[ANum] = nil then raise Exception.Create('TvVectorialDocument.GetPath: Invalid Path number');
|
||||
|
||||
Result := PPath(FPaths.Items[ANum])^;
|
||||
Result := TPath(FPaths.Items[ANum]);
|
||||
end;
|
||||
|
||||
function TvVectorialDocument.GetPathCount: Integer;
|
||||
@ -638,7 +739,7 @@ begin
|
||||
|
||||
if FTexts.Items[ANum] = nil then raise Exception.Create('TvVectorialDocument.GetText: Invalid Text number');
|
||||
|
||||
Result := PText(FTexts.Items[ANum])^;
|
||||
Result := TvText(FTexts.Items[ANum]);
|
||||
end;
|
||||
|
||||
function TvVectorialDocument.GetTextCount: Integer;
|
||||
@ -751,6 +852,34 @@ begin
|
||||
|
||||
end;
|
||||
|
||||
{ TPath }
|
||||
|
||||
procedure TPath.Assign(APath: TPath);
|
||||
begin
|
||||
Len := APath.Len;
|
||||
Points := APath.Points;
|
||||
PointsEnd := APath.PointsEnd;
|
||||
CurPoint := APath.CurPoint;
|
||||
end;
|
||||
|
||||
function TPath.Count(): TPathSegment;
|
||||
begin
|
||||
|
||||
end;
|
||||
|
||||
procedure TPath.PrepareForSequentialReading;
|
||||
begin
|
||||
CurPoint := nil;
|
||||
end;
|
||||
|
||||
function TPath.Next(): TPathSegment;
|
||||
begin
|
||||
if CurPoint = nil then Result := Points
|
||||
else Result := CurPoint.Next;
|
||||
|
||||
CurPoint := Result;
|
||||
end;
|
||||
|
||||
finalization
|
||||
|
||||
SetLength(GvVectorialFormats, 0);
|
||||
|
@ -34,6 +34,8 @@ var
|
||||
i, j, k: Integer;
|
||||
PosX, PosY: Integer; // Not modified by ADestX, etc
|
||||
CurSegment: TPathSegment;
|
||||
Cur2DSegment: T2DSegment absolute CurSegment;
|
||||
Cur2DBSegment: T2DBezierSegment absolute CurSegment;
|
||||
// For bezier
|
||||
CurX, CurY: Integer; // Not modified by ADestX, etc
|
||||
CurveLength: Integer;
|
||||
@ -51,15 +53,18 @@ begin
|
||||
for i := 0 to ASource.PathCount - 1 do
|
||||
begin
|
||||
//WriteLn('i = ', i);
|
||||
for j := 0 to Length(ASource.Paths[i].Points) - 1 do
|
||||
ASource.Paths[i].PrepareForSequentialReading;
|
||||
|
||||
for j := 0 to ASource.Paths[i].Len - 1 do
|
||||
begin
|
||||
//WriteLn('j = ', j);
|
||||
CurSegment := ASource.Paths[i].Points[j];
|
||||
CurSegment := TPathSegment(ASource.Paths[i].Next());
|
||||
|
||||
case CurSegment.SegmentType of
|
||||
st2DLine, st3DLine:
|
||||
begin
|
||||
PosX := Round(CurSegment.X);
|
||||
PosY := Round(CurSegment.Y);
|
||||
PosX := Round(Cur2DSegment.X);
|
||||
PosY := Round(Cur2DSegment.Y);
|
||||
ADest.LineTo(
|
||||
Round(ADestX + AMulX * PosX),
|
||||
Round(ADestY + AMulY * PosY)
|
||||
@ -70,21 +75,21 @@ begin
|
||||
st2DBezier, st3DBezier:
|
||||
begin
|
||||
CurveLength :=
|
||||
Round(sqrt(sqr(CurSegment.X3 - PosX) + sqr(CurSegment.Y3 - PosY))) +
|
||||
Round(sqrt(sqr(CurSegment.X2 - CurSegment.X3) + sqr(CurSegment.Y2 - CurSegment.Y3))) +
|
||||
Round(sqrt(sqr(CurSegment.X - CurSegment.X3) + sqr(CurSegment.Y - CurSegment.Y3)));
|
||||
Round(sqrt(sqr(Cur2DBSegment.X3 - PosX) + sqr(Cur2DBSegment.Y3 - PosY))) +
|
||||
Round(sqrt(sqr(Cur2DBSegment.X2 - Cur2DBSegment.X3) + sqr(Cur2DBSegment.Y2 - Cur2DBSegment.Y3))) +
|
||||
Round(sqrt(sqr(Cur2DBSegment.X - Cur2DBSegment.X3) + sqr(Cur2DBSegment.Y - Cur2DBSegment.Y3)));
|
||||
|
||||
for k := 1 to CurveLength do
|
||||
begin
|
||||
t := k / CurveLength;
|
||||
CurX := Round(sqr(1 - t) * (1 - t) * PosX + 3 * t * sqr(1 - t) * CurSegment.X2 + 3 * t * t * (1 - t) * CurSegment.X3 + t * t * t * CurSegment.X);
|
||||
CurY := Round(sqr(1 - t) * (1 - t) * PosY + 3 * t * sqr(1 - t) * CurSegment.Y2 + 3 * t * t * (1 - t) * CurSegment.Y3 + t * t * t * CurSegment.Y);
|
||||
CurX := Round(sqr(1 - t) * (1 - t) * PosX + 3 * t * sqr(1 - t) * Cur2DBSegment.X2 + 3 * t * t * (1 - t) * Cur2DBSegment.X3 + t * t * t * Cur2DBSegment.X);
|
||||
CurY := Round(sqr(1 - t) * (1 - t) * PosY + 3 * t * sqr(1 - t) * Cur2DBSegment.Y2 + 3 * t * t * (1 - t) * Cur2DBSegment.Y3 + t * t * t * Cur2DBSegment.Y);
|
||||
ADest.LineTo(
|
||||
Round(ADestX + AMulX * CurX),
|
||||
Round(ADestY + AMulY * CurY));
|
||||
end;
|
||||
PosX := Round(CurSegment.X);
|
||||
PosY := Round(CurSegment.Y);
|
||||
PosX := Round(Cur2DBSegment.X);
|
||||
PosY := Round(Cur2DBSegment.Y);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
@ -81,6 +81,9 @@ var
|
||||
lPath: TPath;
|
||||
PtX, PtY, OldPtX, OldPtY: double;
|
||||
BezierCP1X, BezierCP1Y, BezierCP2X, BezierCP2Y: double;
|
||||
segment: TPathSegment;
|
||||
l2DSegment: T2DSegment absolute segment;
|
||||
l2DBSegment: T2DBezierSegment absolute segment;
|
||||
begin
|
||||
for i := 0 to AData.GetPathCount() - 1 do
|
||||
begin
|
||||
@ -89,38 +92,42 @@ begin
|
||||
|
||||
PathStr := '';
|
||||
lPath := AData.GetPath(i);
|
||||
lPath.PrepareForSequentialReading;
|
||||
|
||||
for j := 0 to lPath.Len - 1 do
|
||||
begin
|
||||
if (lPath.Points[j].SegmentType <> st2DLine)
|
||||
and (lPath.Points[j].SegmentType <> stMoveTo)
|
||||
and (lPath.Points[j].SegmentType <> st2DBezier)
|
||||
segment := TPathSegment(lPath.Next());
|
||||
|
||||
if (segment.SegmentType <> st2DLine)
|
||||
and (segment.SegmentType <> stMoveTo)
|
||||
and (segment.SegmentType <> st2DBezier)
|
||||
then Break; // unsupported line type
|
||||
|
||||
// Coordinate conversion from fpvectorial to SVG
|
||||
ConvertFPVCoordinatesToSVGCoordinates(
|
||||
AData, lPath.Points[j].X, lPath.Points[j].Y, PtX, PtY);
|
||||
AData, l2DSegment.X, l2DSegment.Y, PtX, PtY);
|
||||
PtX := PtX - OldPtX;
|
||||
PtY := PtY - OldPtY;
|
||||
|
||||
if (lPath.Points[j].SegmentType = stMoveTo) then
|
||||
if (segment.SegmentType = stMoveTo) then
|
||||
begin
|
||||
PathStr := PathStr + 'm '
|
||||
+ FloatToStr(PtX, FPointSeparator) + ','
|
||||
+ FloatToStr(PtY, FPointSeparator) + ' ';
|
||||
end
|
||||
else if (lPath.Points[j].SegmentType = st2DLine) then
|
||||
else if (segment.SegmentType = st2DLine) then
|
||||
begin
|
||||
PathStr := PathStr + 'l '
|
||||
+ FloatToStr(PtX, FPointSeparator) + ','
|
||||
+ FloatToStr(PtY, FPointSeparator) + ' ';
|
||||
end
|
||||
else if (lPath.Points[j].SegmentType = st2DBezier) then
|
||||
else if (segment.SegmentType = st2DBezier) then
|
||||
begin
|
||||
// Converts all coordinates to absolute values
|
||||
ConvertFPVCoordinatesToSVGCoordinates(
|
||||
AData, lPath.Points[j].X2, lPath.Points[j].Y2, BezierCP1X, BezierCP1Y);
|
||||
AData, l2DBSegment.X2, l2DBSegment.Y2, BezierCP1X, BezierCP1Y);
|
||||
ConvertFPVCoordinatesToSVGCoordinates(
|
||||
AData, lPath.Points[j].X3, lPath.Points[j].Y3, BezierCP2X, BezierCP2Y);
|
||||
AData, l2DBSegment.X3, l2DBSegment.Y3, BezierCP2X, BezierCP2Y);
|
||||
|
||||
// Transforms them into values relative to the initial point
|
||||
BezierCP1X := BezierCP1X - OldPtX;
|
||||
|
Loading…
Reference in New Issue
Block a user