Browse Source

Fixes the svg coordinates and svg path generation

git-svn-id: trunk@15915 -
sekelsenmat 15 years ago
parent
commit
51f23db4bd

+ 22 - 2
packages/fpvectorial/examples/fpvwritetest.pas

@@ -29,23 +29,43 @@ const
   cExtension = '.svg';
   cExtension = '.svg';
 var
 var
   Vec: TvVectorialDocument;
   Vec: TvVectorialDocument;
+
+{$R *.res}
+
 begin
 begin
   Vec := TvVectorialDocument.Create;
   Vec := TvVectorialDocument.Create;
   try
   try
+    // All documents are 10cm x 10cm
+    Vec.Width := 100;
+    Vec.Height := 100;
+
     // single_line_1    One line from (0, 20) to (30, 30)
     // single_line_1    One line from (0, 20) to (30, 30)
     Vec.StartPath(0, 20);
     Vec.StartPath(0, 20);
     Vec.AddLineToPath(30, 30);
     Vec.AddLineToPath(30, 30);
     Vec.EndPath();
     Vec.EndPath();
     Vec.WriteToFile('single_line_1' + cExtension, cFormat);
     Vec.WriteToFile('single_line_1' + cExtension, cFormat);
 
 
-    //    single_line_2    One line from (20, 30) to (30, 20)
+    // single_line_2    One line from (20, 30) to (30, 20)
     Vec.Clear;
     Vec.Clear;
     Vec.StartPath(20, 30);
     Vec.StartPath(20, 30);
     Vec.AddLineToPath(30, 20);
     Vec.AddLineToPath(30, 20);
     Vec.EndPath();
     Vec.EndPath();
     Vec.WriteToFile('single_line_2' + cExtension, cFormat);
     Vec.WriteToFile('single_line_2' + cExtension, cFormat);
 
 
-    //    polyline_1       One line from (0, 0) to (10, 10) to (20, 30) to (30, 20)
+    // single_line_3    One line from (0, 20) to (30, 30) + frame
+    Vec.Clear;
+    Vec.StartPath(0, 20);
+    Vec.AddLineToPath(30, 30);
+    Vec.EndPath();
+    Vec.StartPath(0, 0);
+    Vec.AddLineToPath(100, 0);
+    Vec.AddLineToPath(100, 100);
+    Vec.AddLineToPath(0, 100);
+    Vec.AddLineToPath(0, 0);
+    Vec.EndPath();
+    Vec.WriteToFile('single_line_3' + cExtension, cFormat);
+
+    // polyline_1       One line from (0, 0) to (10, 10) to (20, 30) to (30, 20)
     Vec.Clear;
     Vec.Clear;
     Vec.StartPath(0, 0);
     Vec.StartPath(0, 0);
     Vec.AddLineToPath(10, 10);
     Vec.AddLineToPath(10, 10);

+ 38 - 9
packages/fpvectorial/src/svgvectorialwriter.pas

@@ -25,6 +25,9 @@ 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 ConvertFPVCoordinatesToSVGCoordinates(
+      const AData: TvVectorialDocument;
+      const ASrcX, ASrcY: Double; var ADestX, ADestY: double);
   public
   public
     { General reading methods }
     { General reading methods }
     procedure WriteToStrings(AStrings: TStrings; AData: TvVectorialDocument); override;
     procedure WriteToStrings(AStrings: TStrings; AData: TvVectorialDocument); override;
@@ -32,6 +35,9 @@ type
 
 
 implementation
 implementation
 
 
+const
+  FLOAT_MILIMETERS_PER_PIXEL = 0.3528;
+
 { TvSVGVectorialWriter }
 { TvSVGVectorialWriter }
 
 
 procedure TvSVGVectorialWriter.WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
 procedure TvSVGVectorialWriter.WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
@@ -46,11 +52,15 @@ begin
 end;
 end;
 
 
 {@@
 {@@
-  SVG Coordinate system measures things in whatever unit we pass to it, so we
-  choose to pass in millimiters (mm), like FPVectorial uses.
+  SVG Coordinate system measures things only in pixels, so that we have to
+  hardcode a DPI value for the screen, which is usually 72.
+  FPVectorial uses only milimeters (mm).
 
 
-  The initial point is in the bottom-left corner of the document and it grows
-  to the top and to the right, just like in FPVectorial.
+  The initial point in FPVectorial is in the bottom-left corner of the document
+  and it grows to the top and to the right. In SVG, on the other hand, the
+  initial point is in the top-left corner, growing to the bottom and right.
+  Besides that, coordinates in SVG are also lengths in comparison to the
+  previous point and not absolute coordinates.
 
 
   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
@@ -60,20 +70,31 @@ var
   i, j: Integer;
   i, j: Integer;
   PathStr: string;
   PathStr: string;
   lPath: TPath;
   lPath: TPath;
-  PtX, PtY: double;
+  PtX, PtY, OldPtX, OldPtY: double;
 begin
 begin
   for i := 0 to AData.GetPathCount() - 1 do
   for i := 0 to AData.GetPathCount() - 1 do
   begin
   begin
+    OldPtX := 0;
+    OldPtY := 0;
+
     PathStr := 'm ';
     PathStr := 'm ';
     lPath := AData.GetPath(i);
     lPath := AData.GetPath(i);
     for j := 0 to lPath.Len - 1 do
     for j := 0 to lPath.Len - 1 do
     begin
     begin
       if lPath.Points[j].SegmentType <> st2DLine then Break; // unsupported line type
       if lPath.Points[j].SegmentType <> st2DLine then Break; // unsupported line type
 
 
-      PtX := lPath.Points[j].X;
-      PtY := lPath.Points[j].Y;
-      PathStr := PathStr + FloatToStr(PtX, FPointSeparator) + 'mm,'
-        + FloatToStr(PtY, FPointSeparator) + 'mm ';
+      // Coordinate conversion from fpvectorial to SVG
+      ConvertFPVCoordinatesToSVGCoordinates(
+        AData, lPath.Points[j].X, lPath.Points[j].Y, PtX, PtY);
+      PtX := PtX - OldPtX;
+      PtY := PtY - OldPtY;
+
+      PathStr := PathStr + FloatToStr(PtX, FPointSeparator) + ','
+        + FloatToStr(PtY, FPointSeparator) + ' ';
+
+      // Store the current position for future points
+      OldPtX := OldPtX + PtX;
+      OldPtY := OldPtY + PtY;
     end;
     end;
 
 
     AStrings.Add('  <path');
     AStrings.Add('  <path');
@@ -83,6 +104,14 @@ begin
   end;
   end;
 end;
 end;
 
 
+procedure TvSVGVectorialWriter.ConvertFPVCoordinatesToSVGCoordinates(
+  const AData: TvVectorialDocument; const ASrcX, ASrcY: Double; var ADestX,
+  ADestY: double);
+begin
+  ADestX := ASrcX / FLOAT_MILIMETERS_PER_PIXEL;
+  ADestY := (AData.Height - ASrcY) / FLOAT_MILIMETERS_PER_PIXEL;
+end;
+
 procedure TvSVGVectorialWriter.WriteToStrings(AStrings: TStrings;
 procedure TvSVGVectorialWriter.WriteToStrings(AStrings: TStrings;
   AData: TvVectorialDocument);
   AData: TvVectorialDocument);
 begin
 begin