diff --git a/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas b/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas index b1c9cad5a..d61b28e72 100644 --- a/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas +++ b/applications/fpvviewer/fpvectorialsrc/fpvectorial.pas @@ -1130,6 +1130,8 @@ begin Points := APath.Points; PointsEnd := APath.PointsEnd; CurPoint := APath.CurPoint; + Pen := APath.Pen; + Brush := APath.Brush; end; function TPath.Count(): TPathSegment; diff --git a/applications/fpvviewer/fpvectorialsrc/fpvtocanvas.pas b/applications/fpvviewer/fpvectorialsrc/fpvtocanvas.pas index 16c3a5126..fa0c4e798 100644 --- a/applications/fpvviewer/fpvectorialsrc/fpvtocanvas.pas +++ b/applications/fpvviewer/fpvectorialsrc/fpvtocanvas.pas @@ -42,14 +42,6 @@ begin end; {$endif} -function VColorToFPColor(AVColor: TvColor): TFPColor; inline; -begin - Result.Red := AVColor.Red; - Result.Green := AVColor.Green; - Result.Blue := AVColor.Blue; - Result.Alpha := AVColor.Alpha; -end; - function Rotate2DPoint(P,Fix :TPoint; alpha:double): TPoint; var sinus, cosinus : Extended; diff --git a/applications/fpvviewer/fpvectorialsrc/fpvutils.pas b/applications/fpvviewer/fpvectorialsrc/fpvutils.pas new file mode 100644 index 000000000..f389df7e2 --- /dev/null +++ b/applications/fpvviewer/fpvectorialsrc/fpvutils.pas @@ -0,0 +1,53 @@ +{ +fpvutils.pas + +Vector graphics document + +License: The same modified LGPL as the Free Pascal RTL + See the file COPYING.modifiedLGPL for more details + +AUTHORS: Felipe Monteiro de Carvalho + Pedro Sol Pegorini L de Lima +} +unit fpvutils; + +{$ifdef fpc} + {$mode delphi} +{$endif} + +interface + +uses + Classes, SysUtils, Math, + fpvectorial, fpimage; + +// Color Conversion routines +function VColorToFPColor(AVColor: TvColor): TFPColor; inline; +function VColorToRGBHexString(AVColor: TvColor): string; +function RGBToVColor(AR, AG, AB: Byte): TvColor; inline; + +implementation + +function VColorToFPColor(AVColor: TvColor): TFPColor; inline; +begin + Result.Red := AVColor.Red; + Result.Green := AVColor.Green; + Result.Blue := AVColor.Blue; + Result.Alpha := AVColor.Alpha; +end; + +function VColorToRGBHexString(AVColor: TvColor): string; +begin + Result := Format('%.2x%.2x%.2x', [AVColor.Red, AVColor.Green, AVColor.Blue]); +end; + +function RGBToVColor(AR, AG, AB: Byte): TvColor; inline; +begin + Result.Red := AR; + Result.Green := AG; + Result.Blue := AB; + Result.Alpha := 255; +end; + +end. + diff --git a/applications/fpvviewer/fpvectorialsrc/svgvectorialwriter.pas b/applications/fpvviewer/fpvectorialsrc/svgvectorialwriter.pas index a1ae21495..65a42f5f8 100644 --- a/applications/fpvviewer/fpvectorialsrc/svgvectorialwriter.pas +++ b/applications/fpvviewer/fpvectorialsrc/svgvectorialwriter.pas @@ -13,7 +13,7 @@ unit svgvectorialwriter; interface uses - Classes, SysUtils, math, fpvectorial; + Classes, SysUtils, math, fpvectorial, fpvutils; type { TvSVGVectorialWriter } @@ -24,6 +24,7 @@ type procedure WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument); procedure WriteDocumentName(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 ConvertFPVCoordinatesToSVGCoordinates( const AData: TvVectorialDocument; @@ -60,6 +61,19 @@ begin AStrings.Add(' sodipodi:docname="New document 1">'); 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 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 "." 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 - i, j: Integer; + j: Integer; PathStr: string; - lPath: TPath; PtX, PtY, OldPtX, OldPtY: double; BezierCP1X, BezierCP1Y, BezierCP2X, BezierCP2Y: double; segment: TPathSegment; l2DSegment: T2DSegment absolute segment; l2DBSegment: T2DBezierSegment absolute segment; + // Pen properties + lPenWidth: Integer; + lPenColor: string; 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 - OldPtX := 0; - OldPtY := 0; + segment := TPathSegment(APath.Next()); - PathStr := ''; - lPath := AData.GetPath(i); - lPath.PrepareForSequentialReading; + if (segment.SegmentType <> st2DLine) + and (segment.SegmentType <> stMoveTo) + 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 - 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 + PathStr := PathStr + 'm ' + + FloatToStr(PtX, FPointSeparator) + ',' + + FloatToStr(PtY, FPointSeparator) + ' '; + 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, l2DSegment.X, l2DSegment.Y, PtX, PtY); - PtX := PtX - OldPtX; - PtY := PtY - OldPtY; + AData, l2DBSegment.X2, l2DBSegment.Y2, BezierCP1X, BezierCP1Y); + ConvertFPVCoordinatesToSVGCoordinates( + AData, l2DBSegment.X3, l2DBSegment.Y3, BezierCP2X, BezierCP2Y); - if (segment.SegmentType = stMoveTo) then - begin - PathStr := PathStr + 'm ' - + FloatToStr(PtX, FPointSeparator) + ',' - + FloatToStr(PtY, FPointSeparator) + ' '; - 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 + BezierCP1X := BezierCP1X - OldPtX; + BezierCP1Y := BezierCP1Y - OldPtY; + BezierCP2X := BezierCP2X - OldPtX; + BezierCP2Y := BezierCP2Y - OldPtY; - // Transforms them into values relative to the initial point - BezierCP1X := BezierCP1X - OldPtX; - BezierCP1Y := BezierCP1Y - OldPtY; - BezierCP2X := BezierCP2X - OldPtX; - BezierCP2Y := BezierCP2Y - OldPtY; + // PtX and PtY already contains the destination point - // PtX and PtY already contains the destination point - - // Now render our 2D cubic bezier - PathStr := PathStr + 'c ' - + FloatToStr(BezierCP1X, FPointSeparator) + ',' - + FloatToStr(BezierCP1Y, FPointSeparator) + ' ' - + FloatToStr(BezierCP2X, FPointSeparator) + ',' - + FloatToStr(BezierCP2Y, FPointSeparator) + ' ' - + FloatToStr(PtX, FPointSeparator) + ',' - + FloatToStr(PtY, FPointSeparator) + ' ' - ; - end; - - // Store the current position for future points - OldPtX := OldPtX + PtX; - OldPtY := OldPtY + PtY; + // Now render our 2D cubic bezier + PathStr := PathStr + 'c ' + + FloatToStr(BezierCP1X, FPointSeparator) + ',' + + FloatToStr(BezierCP1Y, FPointSeparator) + ' ' + + FloatToStr(BezierCP2X, FPointSeparator) + ',' + + FloatToStr(BezierCP2Y, FPointSeparator) + ' ' + + FloatToStr(PtX, FPointSeparator) + ',' + + FloatToStr(PtY, FPointSeparator) + ' ' + ; end; - AStrings.Add(' '); + // Store the current position for future points + OldPtX := OldPtX + PtX; + OldPtY := OldPtY + PtY; 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(' '); end; procedure TvSVGVectorialWriter.ConvertFPVCoordinatesToSVGCoordinates(