fpvectorial: Merges the implementation of pen, brush and updates the svg output to use the pen

git-svn-id: trunk@17382 -
This commit is contained in:
sekelsenmat 2011-04-29 11:30:16 +00:00
parent 576072dc17
commit bca76120f6
5 changed files with 229 additions and 99 deletions

View File

@ -13,7 +13,6 @@
<Title Value="fpvwritetest"/> <Title Value="fpvwritetest"/>
<ResourceType Value="res"/> <ResourceType Value="res"/>
<UseXPManifest Value="True"/> <UseXPManifest Value="True"/>
<Icon Value="0"/>
</General> </General>
<i18n> <i18n>
<EnableI18N LFM="False"/> <EnableI18N LFM="False"/>
@ -21,6 +20,9 @@
<VersionInfo> <VersionInfo>
<StringTable ProductVersion=""/> <StringTable ProductVersion=""/>
</VersionInfo> </VersionInfo>
<BuildModes Count="1">
<Item1 Name="default" Default="True"/>
</BuildModes>
<PublishOptions> <PublishOptions>
<Version Value="2"/> <Version Value="2"/>
<IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/> <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
@ -29,6 +31,7 @@
<RunParams> <RunParams>
<local> <local>
<FormatVersion Value="1"/> <FormatVersion Value="1"/>
<LaunchingApplication PathPlusParams="\usr\bin\xterm -T 'Lazarus Run Output' -e $(LazarusDir)\tools\runwait.sh $(TargetCmdLine)"/>
</local> </local>
</RunParams> </RunParams>
<Units Count="1"> <Units Count="1">
@ -40,13 +43,13 @@
</Units> </Units>
</ProjectOptions> </ProjectOptions>
<CompilerOptions> <CompilerOptions>
<Version Value="9"/> <Version Value="10"/>
<PathDelim Value="\"/> <PathDelim Value="\"/>
<Target> <Target>
<Filename Value="fpvwritetest"/> <Filename Value="fpvwritetest"/>
</Target> </Target>
<SearchPaths> <SearchPaths>
<IncludeFiles Value="$(ProjOutDir)\"/> <IncludeFiles Value="$(ProjOutDir)"/>
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
</SearchPaths> </SearchPaths>
<Other> <Other>

View File

@ -22,7 +22,7 @@ program fpvwritetest;
{$mode objfpc}{$H+} {$mode objfpc}{$H+}
uses uses
fpvectorial, svgvectorialwriter; fpvectorial, svgvectorialwriter, fpvutils;
const const
cFormat = vfSVG; cFormat = vfSVG;
@ -134,6 +134,51 @@ begin
Vec.AddText(20, 20, 0, '20, 20 Mówić, cześć, Włosku, Parabéns.'); Vec.AddText(20, 20, 0, '20, 20 Mówić, cześć, Włosku, Parabéns.');
Vec.AddText(30, 30, 0, '30, 30 森林,是一个高密'); Vec.AddText(30, 30, 0, '30, 30 森林,是一个高密');
Vec.WriteToFile('multi_test_1' + cExtension, cFormat); Vec.WriteToFile('multi_test_1' + cExtension, cFormat);
// pen_test_1 Tests the properties of the Pen
Vec.Clear;
Vec.StartPath(0, 20);
Vec.AddLineToPath(30, 30);
Vec.SetPenWidth(10);
Vec.EndPath();
Vec.StartPath(0, 0);
Vec.AddLineToPath(100, 0);
Vec.AddLineToPath(100, 100);
Vec.AddLineToPath(0, 100);
Vec.AddLineToPath(0, 0);
Vec.SetPenWidth(10);
Vec.EndPath();
Vec.StartPath(0, 0);
Vec.AddLineToPath(10, 10);
Vec.AddBezierToPath(10, 20, 20, 20, 20, 10);
Vec.AddLineToPath(30, 0);
Vec.SetPenWidth(10);
Vec.EndPath();
Vec.WriteToFile('pen_test_1' + cExtension, cFormat);
// pen_test_2 Tests the properties of the Pen
Vec.Clear;
Vec.StartPath(0, 20);
Vec.AddLineToPath(30, 30);
Vec.SetPenWidth(10);
Vec.SetPenColor(RGBToVColor(255, 0, 0));
Vec.EndPath();
Vec.StartPath(0, 0);
Vec.AddLineToPath(100, 0);
Vec.AddLineToPath(100, 100);
Vec.AddLineToPath(0, 100);
Vec.AddLineToPath(0, 0);
Vec.SetPenWidth(10);
Vec.SetPenColor(RGBToVColor(0, 255, 0));
Vec.EndPath();
Vec.StartPath(0, 0);
Vec.AddLineToPath(10, 10);
Vec.AddBezierToPath(10, 20, 20, 20, 20, 10);
Vec.AddLineToPath(30, 0);
Vec.SetPenWidth(10);
Vec.SetPenColor(RGBToVColor(0, 0, 255));
Vec.EndPath();
Vec.WriteToFile('pen_test_2' + cExtension, cFormat);
finally finally
Vec.Free; Vec.Free;
end; end;

View File

@ -45,6 +45,17 @@ type
Red, Green, Blue, Alpha: Byte; Red, Green, Blue, Alpha: Byte;
end; end;
TvPen = record
Color: TvColor;
Style: TFPPenStyle;
Width: Integer;
end;
TvBrush = record
Color: TvColor;
Style: TFPBrushStyle;
end;
const const
FPValphaTransparent = $00; FPValphaTransparent = $00;
FPValphaOpaque = $FF; FPValphaOpaque = $FF;
@ -59,7 +70,7 @@ type
P3DPoint = ^T3DPoint; P3DPoint = ^T3DPoint;
TSegmentType = ( TSegmentType = (
st2DLine, st2DBezier, st2DLine, st2DLineWithPen, st2DBezier,
st3DLine, st3DBezier, stMoveTo); st3DLine, st3DBezier, stMoveTo);
{@@ {@@
@ -75,10 +86,6 @@ type
// Fields for linking the list // Fields for linking the list
Previous: TPathSegment; Previous: TPathSegment;
Next: TPathSegment; Next: TPathSegment;
// Data fields
PenColor: TvColor;
PenStyle: TFPPenStyle;
PenWidth: Integer;
end; end;
{@@ {@@
@ -93,6 +100,11 @@ type
X, Y: Double; X, Y: Double;
end; end;
T2DSegmentWithPen = class(T2DSegment)
public
Pen: TvPen;
end;
{@@ {@@
In Bezier segments, we remain using the X and Y coordinates for the ending point. 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 The starting point is where the previous segment ended, so that the intermediary
@ -124,6 +136,13 @@ type
Points: TPathSegment; // Beginning of the double-linked list Points: TPathSegment; // Beginning of the double-linked list
PointsEnd: TPathSegment; // End of the double-linked list PointsEnd: TPathSegment; // End of the double-linked list
CurPoint: TPathSegment; // Used in PrepareForSequentialReading and Next CurPoint: TPathSegment; // Used in PrepareForSequentialReading and Next
{@@ The global Pen for the entire path. This Pen might be overriden by
individual elements of the polyline. }
Pen: TvPen;
{@@ Sets a Brush to paint the inner area inside the path.
There is no inner area if Brush.Style = bsClear, which is the default. }
Brush: TvBrush;
constructor Create();
procedure Assign(APath: TPath); procedure Assign(APath: TPath);
function Count(): TPathSegment; function Count(): TPathSegment;
procedure PrepareForSequentialReading; procedure PrepareForSequentialReading;
@ -139,23 +158,18 @@ type
TvText = class TvText = class
public public
X, Y, Z: Double; // Z is ignored in 2D formats X, Y, Z: Double; // Z is ignored in 2D formats
Value: utf8string;
FontColor: TvColor;
FontSize: integer; FontSize: integer;
FontName: utf8string; FontName: utf8string;
Value: utf8string;
Color: TvColor;
end; end;
{@@ {@@
} }
TvEntity = class TvEntity = class
public public
// Pen Pen: TvPen;
PenColor: TvColor; Brush: TvBrush;
PenStyle: TFPPenStyle;
PenWidth: Integer;
// Brush
BrushStyle: TFPBrushStyle;
BrushColor: TvColor;
end; end;
{@@ {@@
@ -253,6 +267,11 @@ type
procedure AddLineToPath(AX, AY, AZ: Double); overload; procedure AddLineToPath(AX, AY, AZ: Double); overload;
procedure AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double); overload; procedure AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double); overload;
procedure AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double); overload; procedure AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double); overload;
procedure SetBrushColor(AColor: TvColor);
procedure SetBrushStyle(AStyle: TFPBrushStyle);
procedure SetPenColor(AColor: TvColor);
procedure SetPenStyle(AStyle: TFPPenStyle);
procedure SetPenWidth(AWidth: Integer);
procedure EndPath(); procedure EndPath();
procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload; procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload; procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload;
@ -550,20 +569,19 @@ begin
segment.SegmentType := st2DLine; segment.SegmentType := st2DLine;
segment.X := AX; segment.X := AX;
segment.Y := AY; segment.Y := AY;
segment.PenColor := clvBlack;
AppendSegmentToTmpPath(segment); AppendSegmentToTmpPath(segment);
end; end;
procedure TvVectorialDocument.AddLineToPath(AX, AY: Double; AColor: TvColor); procedure TvVectorialDocument.AddLineToPath(AX, AY: Double; AColor: TvColor);
var var
segment: T2DSegment; segment: T2DSegmentWithPen;
begin begin
segment := T2DSegment.Create; segment := T2DSegmentWithPen.Create;
segment.SegmentType := st2DLine; segment.SegmentType := st2DLineWithPen;
segment.X := AX; segment.X := AX;
segment.Y := AY; segment.Y := AY;
segment.PenColor := AColor; segment.Pen.Color := AColor;
AppendSegmentToTmpPath(segment); AppendSegmentToTmpPath(segment);
end; end;
@ -623,6 +641,31 @@ begin
AppendSegmentToTmpPath(segment); AppendSegmentToTmpPath(segment);
end; end;
procedure TvVectorialDocument.SetBrushColor(AColor: TvColor);
begin
FTmPPath.Brush.Color := AColor;
end;
procedure TvVectorialDocument.SetBrushStyle(AStyle: TFPBrushStyle);
begin
FTmPPath.Brush.Style := AStyle;
end;
procedure TvVectorialDocument.SetPenColor(AColor: TvColor);
begin
FTmPPath.Pen.Color := AColor;
end;
procedure TvVectorialDocument.SetPenStyle(AStyle: TFPPenStyle);
begin
FTmPPath.Pen.Style := AStyle;
end;
procedure TvVectorialDocument.SetPenWidth(AWidth: Integer);
begin
FTmPPath.Pen.Width := AWidth;
end;
{@@ {@@
Finishes writing a Path, which was created in multiple Finishes writing a Path, which was created in multiple
steps using StartPath and AddPointToPath, steps using StartPath and AddPointToPath,
@ -683,7 +726,7 @@ begin
lCircularArc.Radius := ARadius; lCircularArc.Radius := ARadius;
lCircularArc.StartAngle := AStartAngle; lCircularArc.StartAngle := AStartAngle;
lCircularArc.EndAngle := AEndAngle; lCircularArc.EndAngle := AEndAngle;
lCircularArc.PenColor := AColor; lCircularArc.Pen.Color := AColor;
FEntities.Add(lCircularArc); FEntities.Add(lCircularArc);
end; end;
@ -728,12 +771,13 @@ begin
for i := 0 to Length(GvVectorialFormats) - 1 do for i := 0 to Length(GvVectorialFormats) - 1 do
if GvVectorialFormats[i].Format = AFormat then if GvVectorialFormats[i].Format = AFormat then
begin begin
Result := GvVectorialFormats[i].WriterClass.Create; if GvVectorialFormats[i].WriterClass <> nil then
Result := GvVectorialFormats[i].WriterClass.Create;
Break; Break;
end; end;
if Result = nil then raise Exception.Create('Unsuported vector graphics format.'); if Result = nil then raise Exception.Create('Unsupported vector graphics format.');
end; end;
{@@ {@@
@ -749,12 +793,13 @@ begin
for i := 0 to Length(GvVectorialFormats) - 1 do for i := 0 to Length(GvVectorialFormats) - 1 do
if GvVectorialFormats[i].Format = AFormat then if GvVectorialFormats[i].Format = AFormat then
begin begin
Result := GvVectorialFormats[i].ReaderClass.Create; if GvVectorialFormats[i].ReaderClass <> nil then
Result := GvVectorialFormats[i].ReaderClass.Create;
Break; Break;
end; end;
if Result = nil then raise Exception.Create('Unsuported vector graphics format.'); if Result = nil then raise Exception.Create('Unsupported vector graphics format.');
end; end;
procedure TvVectorialDocument.ClearTmpPath(); procedure TvVectorialDocument.ClearTmpPath();
@ -1073,12 +1118,20 @@ end;
{ TPath } { TPath }
constructor TPath.Create();
begin
Brush.Style := bsClear;
inherited Create();
end;
procedure TPath.Assign(APath: TPath); procedure TPath.Assign(APath: TPath);
begin begin
Len := APath.Len; Len := APath.Len;
Points := APath.Points; Points := APath.Points;
PointsEnd := APath.PointsEnd; PointsEnd := APath.PointsEnd;
CurPoint := APath.CurPoint; CurPoint := APath.CurPoint;
Pen := APath.Pen;
Brush := APath.Brush;
end; end;
function TPath.Count(): TPathSegment; function TPath.Count(): TPathSegment;

View File

@ -4,7 +4,7 @@ unit fpvtocanvas;
interface interface
{.$define USE_LCL_CANVAS} {$define USE_LCL_CANVAS}
uses uses
Classes, SysUtils, Math, Classes, SysUtils, Math,
@ -115,7 +115,7 @@ end;
DrawFPVectorialToCanvas(ASource, ADest, 0, ASource.Height, 1.0, -1.0); DrawFPVectorialToCanvas(ASource, ADest, 0, ASource.Height, 1.0, -1.0);
} }
{$define FPVECTORIAL_TOCANVAS_DEBUG} {.$define FPVECTORIAL_TOCANVAS_DEBUG}
procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument; procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument;
{$ifdef USE_LCL_CANVAS}ADest: TCanvas;{$else}ADest: TFPCustomCanvas;{$endif} {$ifdef USE_LCL_CANVAS}ADest: TCanvas;{$else}ADest: TFPCustomCanvas;{$endif}
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0);
@ -187,15 +187,22 @@ begin
Write(Format(' M%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)])); Write(Format(' M%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif} {$endif}
end; end;
st2DLine, st3DLine: st2DLineWithPen:
begin begin
{$ifdef USE_LCL_CANVAS}ADest.Pen.Color := VColorToTColor(Cur2DSegment.PenColor);{$endif} {$ifdef USE_LCL_CANVAS}ADest.Pen.Color := VColorToTColor(T2DSegmentWithPen(Cur2DSegment).Pen.Color);{$endif}
ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)); ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
{$ifdef USE_LCL_CANVAS}ADest.Pen.Color := clBlack;{$endif} {$ifdef USE_LCL_CANVAS}ADest.Pen.Color := clBlack;{$endif}
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG} {$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)])); Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif} {$endif}
end; end;
st2DLine, st3DLine:
begin
ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif}
end;
{ To draw a bezier we need to divide the interval in parts and make { To draw a bezier we need to divide the interval in parts and make
lines between this parts } lines between this parts }
st2DBezier, st3DBezier: st2DBezier, st3DBezier:
@ -321,7 +328,7 @@ begin
WriteLn(Format('Drawing Arc Center=%f,%f Radius=%f StartAngle=%f AngleLength=%f', WriteLn(Format('Drawing Arc Center=%f,%f Radius=%f StartAngle=%f AngleLength=%f',
[CurArc.CenterX, CurArc.CenterY, CurArc.Radius, IntStartAngle/16, IntAngleLength/16])); [CurArc.CenterX, CurArc.CenterY, CurArc.Radius, IntStartAngle/16, IntAngleLength/16]));
{$endif} {$endif}
ADest.Pen.Color := {$ifdef USE_LCL_CANVAS}VColorToTColor(CurArc.PenColor);{$else}VColorToFPColor(CurArc.PenColor);{$endif} ADest.Pen.Color := {$ifdef USE_LCL_CANVAS}VColorToTColor(CurArc.Pen.Color);{$else}VColorToFPColor(CurArc.Pen.Color);{$endif}
ADest.Arc( ADest.Arc(
BoundsLeft, BoundsTop, BoundsRight, BoundsBottom, BoundsLeft, BoundsTop, BoundsRight, BoundsBottom,
IntStartAngle, IntAngleLength IntStartAngle, IntAngleLength

View File

@ -13,7 +13,7 @@ unit svgvectorialwriter;
interface interface
uses uses
Classes, SysUtils, math, fpvectorial; Classes, SysUtils, math, fpvectorial, fpvutils;
type type
{ TvSVGVectorialWriter } { TvSVGVectorialWriter }
@ -24,6 +24,7 @@ type
procedure WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument); procedure WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
procedure WriteDocumentName(AStrings: TStrings; AData: TvVectorialDocument); procedure WriteDocumentName(AStrings: TStrings; AData: TvVectorialDocument);
procedure WritePaths(AStrings: TStrings; AData: TvVectorialDocument); procedure WritePaths(AStrings: TStrings; AData: TvVectorialDocument);
procedure WritePath(AIndex: Integer; APath: TPath; AStrings: TStrings; AData: TvVectorialDocument);
procedure WriteTexts(AStrings: TStrings; AData: TvVectorialDocument); procedure WriteTexts(AStrings: TStrings; AData: TvVectorialDocument);
procedure ConvertFPVCoordinatesToSVGCoordinates( procedure ConvertFPVCoordinatesToSVGCoordinates(
const AData: TvVectorialDocument; const AData: TvVectorialDocument;
@ -60,6 +61,19 @@ begin
AStrings.Add(' sodipodi:docname="New document 1">'); AStrings.Add(' sodipodi:docname="New document 1">');
end; end;
procedure TvSVGVectorialWriter.WritePaths(AStrings: TStrings; AData: TvVectorialDocument);
var
i: Integer;
lPath: TPath;
begin
for i := 0 to AData.GetPathCount() - 1 do
begin
lPath := AData.GetPath(i);
lPath.PrepareForSequentialReading;
WritePath(i ,lPath, AStrings, AData);
end;
end;
{@@ {@@
SVG Coordinate system measures things only in pixels, so that we have to SVG Coordinate system measures things only in pixels, so that we have to
hardcode a DPI value for the screen, which is usually 72. hardcode a DPI value for the screen, which is usually 72.
@ -74,90 +88,98 @@ end;
SVG uses commas "," to separate the X,Y coordinates, so it always uses points SVG uses commas "," to separate the X,Y coordinates, so it always uses points
"." as decimal separators and uses no thousand separators "." as decimal separators and uses no thousand separators
} }
procedure TvSVGVectorialWriter.WritePaths(AStrings: TStrings; AData: TvVectorialDocument); procedure TvSVGVectorialWriter.WritePath(AIndex: Integer; APath: TPath; AStrings: TStrings;
AData: TvVectorialDocument);
var var
i, j: Integer; j: Integer;
PathStr: string; PathStr: string;
lPath: TPath;
PtX, PtY, OldPtX, OldPtY: double; PtX, PtY, OldPtX, OldPtY: double;
BezierCP1X, BezierCP1Y, BezierCP2X, BezierCP2Y: double; BezierCP1X, BezierCP1Y, BezierCP2X, BezierCP2Y: double;
segment: TPathSegment; segment: TPathSegment;
l2DSegment: T2DSegment absolute segment; l2DSegment: T2DSegment absolute segment;
l2DBSegment: T2DBezierSegment absolute segment; l2DBSegment: T2DBezierSegment absolute segment;
// Pen properties
lPenWidth: Integer;
lPenColor: string;
begin begin
for i := 0 to AData.GetPathCount() - 1 do OldPtX := 0;
OldPtY := 0;
PathStr := '';
APath.PrepareForSequentialReading();
for j := 0 to APath.Len - 1 do
begin begin
OldPtX := 0; segment := TPathSegment(APath.Next());
OldPtY := 0;
PathStr := ''; if (segment.SegmentType <> st2DLine)
lPath := AData.GetPath(i); and (segment.SegmentType <> stMoveTo)
lPath.PrepareForSequentialReading; and (segment.SegmentType <> st2DBezier)
then Break; // unsupported line type
for j := 0 to lPath.Len - 1 do // Coordinate conversion from fpvectorial to SVG
ConvertFPVCoordinatesToSVGCoordinates(
AData, l2DSegment.X, l2DSegment.Y, PtX, PtY);
PtX := PtX - OldPtX;
PtY := PtY - OldPtY;
if (segment.SegmentType = stMoveTo) then
begin begin
segment := TPathSegment(lPath.Next()); PathStr := PathStr + 'm '
+ FloatToStr(PtX, FPointSeparator) + ','
if (segment.SegmentType <> st2DLine) + FloatToStr(PtY, FPointSeparator) + ' ';
and (segment.SegmentType <> stMoveTo) end
and (segment.SegmentType <> st2DBezier) else if (segment.SegmentType = st2DLine) then
then Break; // unsupported line type begin
PathStr := PathStr + 'l '
// Coordinate conversion from fpvectorial to SVG + FloatToStr(PtX, FPointSeparator) + ','
+ FloatToStr(PtY, FPointSeparator) + ' ';
end
else if (segment.SegmentType = st2DBezier) then
begin
// Converts all coordinates to absolute values
ConvertFPVCoordinatesToSVGCoordinates( ConvertFPVCoordinatesToSVGCoordinates(
AData, l2DSegment.X, l2DSegment.Y, PtX, PtY); AData, l2DBSegment.X2, l2DBSegment.Y2, BezierCP1X, BezierCP1Y);
PtX := PtX - OldPtX; ConvertFPVCoordinatesToSVGCoordinates(
PtY := PtY - OldPtY; AData, l2DBSegment.X3, l2DBSegment.Y3, BezierCP2X, BezierCP2Y);
if (segment.SegmentType = stMoveTo) then // Transforms them into values relative to the initial point
begin BezierCP1X := BezierCP1X - OldPtX;
PathStr := PathStr + 'm ' BezierCP1Y := BezierCP1Y - OldPtY;
+ FloatToStr(PtX, FPointSeparator) + ',' BezierCP2X := BezierCP2X - OldPtX;
+ FloatToStr(PtY, FPointSeparator) + ' '; BezierCP2Y := BezierCP2Y - OldPtY;
end
else if (segment.SegmentType = st2DLine) then
begin
PathStr := PathStr + 'l '
+ FloatToStr(PtX, FPointSeparator) + ','
+ FloatToStr(PtY, FPointSeparator) + ' ';
end
else if (segment.SegmentType = st2DBezier) then
begin
// Converts all coordinates to absolute values
ConvertFPVCoordinatesToSVGCoordinates(
AData, l2DBSegment.X2, l2DBSegment.Y2, BezierCP1X, BezierCP1Y);
ConvertFPVCoordinatesToSVGCoordinates(
AData, l2DBSegment.X3, l2DBSegment.Y3, BezierCP2X, BezierCP2Y);
// Transforms them into values relative to the initial point // PtX and PtY already contains the destination point
BezierCP1X := BezierCP1X - OldPtX;
BezierCP1Y := BezierCP1Y - OldPtY;
BezierCP2X := BezierCP2X - OldPtX;
BezierCP2Y := BezierCP2Y - OldPtY;
// PtX and PtY already contains the destination point // Now render our 2D cubic bezier
PathStr := PathStr + 'c '
// Now render our 2D cubic bezier + FloatToStr(BezierCP1X, FPointSeparator) + ','
PathStr := PathStr + 'c ' + FloatToStr(BezierCP1Y, FPointSeparator) + ' '
+ FloatToStr(BezierCP1X, FPointSeparator) + ',' + FloatToStr(BezierCP2X, FPointSeparator) + ','
+ FloatToStr(BezierCP1Y, FPointSeparator) + ' ' + FloatToStr(BezierCP2Y, FPointSeparator) + ' '
+ FloatToStr(BezierCP2X, FPointSeparator) + ',' + FloatToStr(PtX, FPointSeparator) + ','
+ FloatToStr(BezierCP2Y, FPointSeparator) + ' ' + FloatToStr(PtY, FPointSeparator) + ' '
+ FloatToStr(PtX, FPointSeparator) + ',' ;
+ FloatToStr(PtY, FPointSeparator) + ' '
;
end;
// Store the current position for future points
OldPtX := OldPtX + PtX;
OldPtY := OldPtY + PtY;
end; end;
AStrings.Add(' <path'); // Store the current position for future points
AStrings.Add(' style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"'); OldPtX := OldPtX + PtX;
AStrings.Add(' d="' + PathStr + '"'); OldPtY := OldPtY + PtY;
AStrings.Add(' id="path' + IntToStr(i) + '" />');
end; end;
// Get the Pen Width
if APath.Pen.Width >= 1 then lPenWidth := APath.Pen.Width
else lPenWidth := 1;
// Get the Pen Color
lPenColor := VColorToRGBHexString(APath.Pen.Color);
AStrings.Add(' <path');
AStrings.Add(Format(' style="fill:none;stroke:#%s;stroke-width:%dpx;'
+ 'stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"',
[lPenColor, lPenWidth]));
AStrings.Add(' d="' + PathStr + '"');
AStrings.Add(' id="path' + IntToStr(AIndex) + '" />');
end; end;
procedure TvSVGVectorialWriter.ConvertFPVCoordinatesToSVGCoordinates( procedure TvSVGVectorialWriter.ConvertFPVCoordinatesToSVGCoordinates(