diff --git a/packages/fpvectorial/src/svgvectorialwriter.pas b/packages/fpvectorial/src/svgvectorialwriter.pas index 76272a9697..57bbd7ee0b 100644 --- a/packages/fpvectorial/src/svgvectorialwriter.pas +++ b/packages/fpvectorial/src/svgvectorialwriter.pas @@ -25,7 +25,6 @@ type procedure WriteDocumentName(AStrings: TStrings; AData: TvVectorialDocument); procedure WritePaths(AStrings: TStrings; AData: TvVectorialDocument); procedure WriteTexts(AStrings: TStrings; AData: TvVectorialDocument); - procedure WriteBeziers(AStrings: TStrings; AData: TvVectorialDocument); procedure ConvertFPVCoordinatesToSVGCoordinates( const AData: TvVectorialDocument; const ASrcX, ASrcY: Double; var ADestX, ADestY: double); @@ -44,7 +43,9 @@ const // 1 Inch = 25.4 milimiters // 90 inches per pixel = (1 / 90) * 25.4 = 0.2822 // FLOAT_MILIMETERS_PER_PIXEL = 0.3528; // DPI 72 = 1 / 72 inches per pixel + FLOAT_MILIMETERS_PER_PIXEL = 0.2822; // DPI 90 = 1 / 90 inches per pixel + FLOAT_PIXELS_PER_MILIMETER = 3.5433; // DPI 90 = 1 / 90 inches per pixel { TvSVGVectorialWriter } @@ -79,18 +80,20 @@ var PathStr: string; lPath: TPath; PtX, PtY, OldPtX, OldPtY: double; + BezierCP1X, BezierCP1Y, BezierCP2X, BezierCP2Y: double; begin for i := 0 to AData.GetPathCount() - 1 do begin OldPtX := 0; OldPtY := 0; - PathStr := 'm '; + PathStr := ''; lPath := AData.GetPath(i); 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) then Break; // unsupported line type // Coordinate conversion from fpvectorial to SVG @@ -99,8 +102,44 @@ begin PtX := PtX - OldPtX; PtY := PtY - OldPtY; - PathStr := PathStr + FloatToStr(PtX, FPointSeparator) + ',' - + FloatToStr(PtY, FPointSeparator) + ' '; + if (lPath.Points[j].SegmentType = stMoveTo) then + begin + PathStr := PathStr + 'm ' + + FloatToStr(PtX, FPointSeparator) + ',' + + FloatToStr(PtY, FPointSeparator) + ' '; + end + else if (lPath.Points[j].SegmentType = st2DLine) then + begin + PathStr := PathStr + 'l ' + + FloatToStr(PtX, FPointSeparator) + ',' + + FloatToStr(PtY, FPointSeparator) + ' '; + end + else if (lPath.Points[j].SegmentType = st2DBezier) then + begin + // Converts all coordinates to absolute values + ConvertFPVCoordinatesToSVGCoordinates( + AData, lPath.Points[j].X2, lPath.Points[j].Y2, BezierCP1X, BezierCP1X); + ConvertFPVCoordinatesToSVGCoordinates( + AData, lPath.Points[j].X3, lPath.Points[j].Y3, BezierCP2X, BezierCP2Y); + + // 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 + + // 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; @@ -153,7 +192,6 @@ begin AStrings.Add(' '); WritePaths(AStrings, AData); WriteTexts(AStrings, AData); - WriteBeziers(AStrings, AData); AStrings.Add(' '); // finalization @@ -192,86 +230,6 @@ begin end; end; -procedure TvSVGVectorialWriter.WriteBeziers(AStrings: TStrings; AData: TvVectorialDocument); -var - i, j: Integer; - PathStr: string; - lPath: TPath; - PtX, PtY, OldPtX, OldPtY, PtX2, PtY2, OldPtX2, OldPtY2, - PtX3, PtY3, OldPtX3, OldPtY3: double; - BezierType: TSegmentType; -begin - for i := 0 to AData.GetPathCount() - 1 do - begin - OldPtX := 0; - OldPtY := 0; - OldPtX2 := 0; - OldPtY2 := 0; - OldPtX3 := 0; - OldPtY3 := 0; - - PathStr := 'm '; - lPath := AData.GetPath(i); - for j := 0 to lPath.Len - 1 do - begin - BezierType := lPath.Points[j].SegmentType; - if j>0 then - if (BezierType <> st2DBezier) and (BezierType <> stMoveTo) - and (BezierType <> st2DLine) - then Break; // unsupported Bezier type - - if (BezierType = st2DBezier) or (BezierType = stMoveTo) then - begin - ConvertFPVCoordinatesToSVGCoordinates( - AData, lPath.Points[j].X, lPath.Points[j].Y, PtX, PtY); - ConvertFPVCoordinatesToSVGCoordinates( - AData, lPath.Points[j].X2, lPath.Points[j].Y2, PtX2, PtY2); - ConvertFPVCoordinatesToSVGCoordinates( - AData, lPath.Points[j].X3, lPath.Points[j].Y3, PtX3, PtY3); - - PtX := PtX - OldPtX; - PtY := PtY - OldPtY; - PtX2 := PtX2 - OldPtX2; - PtY2 := PtY2 - OldPtY2; - PtX3 := PtX3 - OldPtX3; - PtY3 := PtY3 - OldPtY3; - - if j = 0 then - PathStr := PathStr + FloatToStr(PtX, FPointSeparator) + ',' - + FloatToStr(PtY, FPointSeparator) + ' '; - - if j = 0 then - begin - PathStr := PathStr + 'q'; -// if BezierType = st3DBezier then -// PathStr := PathStr + 'c'; - end; - - if j > 0 then - PathStr := PathStr + FloatToStr(PtX, FPointSeparator) + ',' - + FloatToStr(PtY, FPointSeparator) + ' ' - + FloatToStr(PtX2, FPointSeparator) + ',' - + FloatToStr(PtY2, FPointSeparator) + ' ' - + FloatToStr(PtX3, FPointSeparator) + ',' - + FloatToStr(PtY3, FPointSeparator) + ' '; - - // Store the current position for future points - OldPtX := OldPtX + PtX; - OldPtY := OldPtY + PtY; - OldPtX2 := OldPtX2 + PtX2; - OldPtY2 := OldPtY2 + PtY2; - OldPtX3 := OldPtX3 + PtX3; - OldPtY3 := OldPtY3 + PtY3; - end; - end; - - AStrings.Add(' '); - end; -end; - initialization RegisterVectorialWriter(TvSVGVectorialWriter, vfSVG);