فهرست منبع

fpvectorial: Improves the svg reader and adds a file modification example

git-svn-id: trunk@17441 -
sekelsenmat 14 سال پیش
والد
کامیت
01e916e6f5

+ 2 - 0
.gitattributes

@@ -2582,6 +2582,8 @@ packages/fpvectorial/examples/fpvc_mainform.pas svneol=native#text/plain
 packages/fpvectorial/examples/fpvectorialconverter.ico -text
 packages/fpvectorial/examples/fpvectorialconverter.lpi svneol=native#text/plain
 packages/fpvectorial/examples/fpvectorialconverter.lpr svneol=native#text/plain
+packages/fpvectorial/examples/fpvmodifytest.lpi svneol=native#text/plain
+packages/fpvectorial/examples/fpvmodifytest.pas svneol=native#text/plain
 packages/fpvectorial/examples/fpvwritetest.lpi svneol=native#text/plain
 packages/fpvectorial/examples/fpvwritetest.pas svneol=native#text/plain
 packages/fpvectorial/fpmake.pp svneol=native#text/plain

+ 9 - 9
packages/fpvectorial/examples/fpce_mainform.lfm

@@ -6,12 +6,12 @@ object formCorelExplorer: TformCorelExplorer
   Caption = 'FP Corel Explorer'
   ClientHeight = 345
   ClientWidth = 466
-  LCLVersion = '0.9.29'
+  LCLVersion = '0.9.31'
   object Label1: TLabel
     Left = 8
-    Height = 14
+    Height = 17
     Top = 40
-    Width = 123
+    Width = 160
     Caption = 'Location of the Input file:'
     ParentColor = False
   end
@@ -37,25 +37,25 @@ object formCorelExplorer: TformCorelExplorer
   end
   object labelFilename: TLabel
     Left = 256
-    Height = 14
+    Height = 17
     Top = 65
-    Width = 47
+    Width = 61
     Caption = 'Filename:'
     ParentColor = False
   end
   object labelVersion: TLabel
     Left = 256
-    Height = 14
+    Height = 17
     Top = 88
-    Width = 40
+    Width = 53
     Caption = 'Version:'
     ParentColor = False
   end
   object labelSize: TLabel
     Left = 256
-    Height = 14
+    Height = 17
     Top = 112
-    Width = 24
+    Width = 31
     Caption = 'Size:'
     ParentColor = False
   end

+ 5 - 4
packages/fpvectorial/examples/fpcorelexplorer.lpi

@@ -4,10 +4,8 @@
     <Version Value="9"/>
     <PathDelim Value="\"/>
     <General>
-      <Flags>
-        <AlwaysBuild Value="False"/>
-      </Flags>
       <SessionStorage Value="InProjectDir"/>
+      <MainUnit Value="0"/>
       <Title Value="fpcorelexplorer"/>
       <UseXPManifest Value="True"/>
       <Icon Value="0"/>
@@ -18,6 +16,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 +56,7 @@
       <Filename Value="fpcorelexplorer"/>
     </Target>
     <SearchPaths>
-      <IncludeFiles Value="$(ProjOutDir)\"/>
+      <IncludeFiles Value="$(ProjOutDir)"/>
       <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
     </SearchPaths>
     <Linking>

+ 201 - 0
packages/fpvectorial/examples/fpvmodifytest.lpi

@@ -0,0 +1,201 @@
+<?xml version="1.0"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="9"/>
+    <General>
+      <Flags>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+      </Flags>
+      <MainUnit Value="0"/>
+      <Title Value="fpvmodifytest"/>
+      <ResourceType Value="res"/>
+      <UseXPManifest Value="True"/>
+      <Icon Value="0"/>
+      <ActiveWindowIndexAtStart Value="0"/>
+    </General>
+    <i18n>
+      <EnableI18N LFM="False"/>
+    </i18n>
+    <VersionInfo>
+      <StringTable ProductVersion=""/>
+    </VersionInfo>
+    <BuildModes Count="1" Active="Default">
+      <Item1 Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <IncludeFileFilter Value="*.(pas|pp|inc|lfm|lpr|lrs|lpi|lpk|sh|xml)"/>
+      <ExcludeFileFilter Value="*.(bak|ppu|o|so);*~;backup"/>
+    </PublishOptions>
+    <RunParams>
+      <local>
+        <FormatVersion Value="1"/>
+      </local>
+    </RunParams>
+    <Units Count="4">
+      <Unit0>
+        <Filename Value="fpvmodifytest.pas"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="fpvmodifytest"/>
+        <IsVisibleTab Value="True"/>
+        <EditorIndex Value="0"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="1"/>
+        <CursorPos X="1" Y="10"/>
+        <UsageCount Value="22"/>
+        <Loaded Value="True"/>
+      </Unit0>
+      <Unit1>
+        <Filename Value="fpvectorial.pas"/>
+        <UnitName Value="fpvectorial"/>
+        <EditorIndex Value="3"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="135"/>
+        <CursorPos X="18" Y="148"/>
+        <UsageCount Value="11"/>
+        <Loaded Value="True"/>
+      </Unit1>
+      <Unit2>
+        <Filename Value="svgvectorialwriter.pas"/>
+        <UnitName Value="svgvectorialwriter"/>
+        <EditorIndex Value="2"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="14"/>
+        <CursorPos X="1" Y="32"/>
+        <UsageCount Value="11"/>
+        <Loaded Value="True"/>
+      </Unit2>
+      <Unit3>
+        <Filename Value="svgvectorialreader.pas"/>
+        <UnitName Value="svgvectorialreader"/>
+        <EditorIndex Value="1"/>
+        <WindowIndex Value="0"/>
+        <TopLine Value="250"/>
+        <CursorPos X="1" Y="263"/>
+        <UsageCount Value="11"/>
+        <Loaded Value="True"/>
+      </Unit3>
+    </Units>
+    <JumpHistory Count="23" HistoryIndex="22">
+      <Position1>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="301" Column="1" TopLine="297"/>
+      </Position1>
+      <Position2>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="269" Column="1" TopLine="249"/>
+      </Position2>
+      <Position3>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="232" Column="74" TopLine="219"/>
+      </Position3>
+      <Position4>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="51" Column="30" TopLine="36"/>
+      </Position4>
+      <Position5>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="297" Column="45" TopLine="296"/>
+      </Position5>
+      <Position6>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="53" Column="19" TopLine="38"/>
+      </Position6>
+      <Position7>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="236" Column="3" TopLine="226"/>
+      </Position7>
+      <Position8>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="240" Column="1" TopLine="226"/>
+      </Position8>
+      <Position9>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="241" Column="1" TopLine="226"/>
+      </Position9>
+      <Position10>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="242" Column="1" TopLine="226"/>
+      </Position10>
+      <Position11>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="51" Column="50" TopLine="36"/>
+      </Position11>
+      <Position12>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="54" Column="39" TopLine="38"/>
+      </Position12>
+      <Position13>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="272" Column="1" TopLine="252"/>
+      </Position13>
+      <Position14>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="271" Column="44" TopLine="246"/>
+      </Position14>
+      <Position15>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="257" Column="1" TopLine="246"/>
+      </Position15>
+      <Position16>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="258" Column="1" TopLine="246"/>
+      </Position16>
+      <Position17>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="259" Column="1" TopLine="246"/>
+      </Position17>
+      <Position18>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="260" Column="1" TopLine="246"/>
+      </Position18>
+      <Position19>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="261" Column="1" TopLine="246"/>
+      </Position19>
+      <Position20>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="262" Column="1" TopLine="246"/>
+      </Position20>
+      <Position21>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="275" Column="1" TopLine="250"/>
+      </Position21>
+      <Position22>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="265" Column="1" TopLine="250"/>
+      </Position22>
+      <Position23>
+        <Filename Value="svgvectorialreader.pas"/>
+        <Caret Line="266" Column="1" TopLine="250"/>
+      </Position23>
+    </JumpHistory>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="10"/>
+    <Target>
+      <Filename Value="fpvmodifytest"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+    <Other>
+      <CompilerPath Value="$(CompPath)"/>
+    </Other>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions Count="3">
+      <Item1>
+        <Name Value="EAbort"/>
+      </Item1>
+      <Item2>
+        <Name Value="ECodetoolError"/>
+      </Item2>
+      <Item3>
+        <Name Value="EFOpenError"/>
+      </Item3>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 62 - 0
packages/fpvectorial/examples/fpvmodifytest.pas

@@ -0,0 +1,62 @@
+{
+Author: Felipe Monteiro de Carvalho
+
+License: Public Domain
+}
+program fpvmodifytest;
+
+{$mode objfpc}{$H+}
+
+uses
+  fpvectorial, svgvectorialwriter, svgvectorialreader, fpvutils;
+
+const
+  cFormat = vfSVG;
+  cExtension = '.svg';
+var
+  Vec: TvVectorialDocument;
+  Path: TPath;
+  i: Integer;
+  Segment: TPathSegment;
+  _2DSegment: T2DSegment;
+  BezSegment: T2DBezierSegment;
+begin
+  Vec := TvVectorialDocument.Create;
+  try
+    // Read the file
+    Vec.ReadFromFile('bezier_1.svg');
+
+    // Now add 10 to the Y coordinate of all elements
+    for i := 0 to Vec.GetPathCount() - 1 do
+    begin
+      Path := Vec.GetPath(i);
+      Path.PrepareForSequentialReading();
+      Path.Next();
+      while Path.CurPoint <> nil do
+      begin
+        Segment := Path.CurPoint;
+
+        if Segment is T2DBezierSegment then
+        begin
+          BezSegment := Segment as T2DBezierSegment;
+          BezSegment.Y := BezSegment.Y + 10;
+          BezSegment.Y2 := BezSegment.Y2 + 10;
+          BezSegment.Y3 := BezSegment.Y3 + 10;
+        end
+        else if Segment is T2DSegment then
+        begin
+          _2DSegment := Segment as T2DSegment;
+          _2DSegment.Y := _2DSegment.Y + 10;
+        end;
+
+        Path.Next();
+      end;
+    end;
+
+    // Write the changed file to disk
+    Vec.WriteToFile('bezier_1_mod' + cExtension, cFormat);
+  finally
+    Vec.Free;
+  end;
+end.
+

+ 67 - 2
packages/fpvectorial/src/svgvectorialreader.pas

@@ -47,6 +47,13 @@ type
     FSVGPathTokenizer: TSVGPathTokenizer;
     procedure ReadPathFromNode(APath: TDOMNode; AData: TvVectorialDocument);
     procedure ReadPathFromString(AStr: string; AData: TvVectorialDocument);
+    function  StringWithUnitToFloat(AStr: string): Single;
+    procedure ConvertSVGCoordinatesToFPVCoordinates(
+      const AData: TvVectorialDocument;
+      const ASrcX, ASrcY: Float; var ADestX, ADestY: Float);
+    procedure ConvertSVGDeltaToFPVDelta(
+      const AData: TvVectorialDocument;
+      const ASrcX, ASrcY: Float; var ADestX, ADestY: Float);
   public
     { General reading methods }
     constructor Create; override;
@@ -101,7 +108,6 @@ begin
   begin
     lToken.TokenType := sttFloatValue;
     lToken.Value := StrToFloat(AStr, FPointSeparator);
-    lToken.Value := lToken.Value * FLOAT_MILIMETERS_PER_PIXEL;
   end;
 
   Tokens.Add(lToken);
@@ -211,7 +217,8 @@ procedure TvSVGVectorialReader.ReadPathFromString(AStr: string;
   AData: TvVectorialDocument);
 var
   i: Integer;
-  X, Y, CurX, CurY: Float;
+  X, Y, X2, Y2, X3, Y3: Float;
+  CurX, CurY: Float;
 begin
   FSVGPathTokenizer.Tokens.Clear;
   FSVGPathTokenizer.TokenizePathString(AStr);
@@ -225,6 +232,7 @@ begin
     begin
       CurX := FSVGPathTokenizer.Tokens.Items[i+1].Value;
       CurY := FSVGPathTokenizer.Tokens.Items[i+2].Value;
+      ConvertSVGCoordinatesToFPVCoordinates(AData, CurX, CurY, CurX, CurY);
 
       AData.AddMoveToPath(CurX, CurY);
 
@@ -234,6 +242,7 @@ begin
     begin
       X := FSVGPathTokenizer.Tokens.Items[i+1].Value;
       Y := FSVGPathTokenizer.Tokens.Items[i+2].Value;
+      ConvertSVGDeltaToFPVDelta(AData, X, Y, X, Y);
 
       // LineTo uses relative coordenates in SVG
       CurX := CurX + X;
@@ -243,6 +252,27 @@ begin
 
       Inc(i, 3);
     end
+    else if FSVGPathTokenizer.Tokens.Items[i].TokenType = sttBezierTo then
+    begin
+      X2 := FSVGPathTokenizer.Tokens.Items[i+1].Value;
+      Y2 := FSVGPathTokenizer.Tokens.Items[i+2].Value;
+      X3 := FSVGPathTokenizer.Tokens.Items[i+3].Value;
+      Y3 := FSVGPathTokenizer.Tokens.Items[i+4].Value;
+      X := FSVGPathTokenizer.Tokens.Items[i+5].Value;
+      Y := FSVGPathTokenizer.Tokens.Items[i+6].Value;
+
+      ConvertSVGDeltaToFPVDelta(AData, X2, Y2, X2, Y2);
+      ConvertSVGDeltaToFPVDelta(AData, X3, Y3, X3, Y3);
+      ConvertSVGDeltaToFPVDelta(AData, X, Y, X, Y);
+
+      AData.AddBezierToPath(X2 + CurX, Y2 + CurY, X3 + CurX, Y3 + CurY, X + CurX, Y + CurY);
+
+      // BezierTo uses relative coordenates in SVG
+      CurX := CurX + X;
+      CurY := CurY + Y;
+
+      Inc(i, 7);
+    end
     else
     begin
       Inc(i);
@@ -250,6 +280,37 @@ begin
   end;
 end;
 
+function TvSVGVectorialReader.StringWithUnitToFloat(AStr: string): Single;
+var
+  UnitStr, ValueStr: string;
+  Len: Integer;
+begin
+  // Check the unit
+  Len := Length(AStr);
+  UnitStr := Copy(AStr, Len-1, 2);
+  if UnitStr = 'mm' then
+  begin
+    ValueStr := Copy(AStr, 1, Len-2);
+    Result := StrToInt(ValueStr);
+  end;
+end;
+
+procedure TvSVGVectorialReader.ConvertSVGCoordinatesToFPVCoordinates(
+  const AData: TvVectorialDocument; const ASrcX, ASrcY: Float;
+  var ADestX,ADestY: Float);
+begin
+  ADestX := ASrcX * FLOAT_MILIMETERS_PER_PIXEL;
+  ADestY := AData.Height - ASrcY * FLOAT_MILIMETERS_PER_PIXEL;
+end;
+
+procedure TvSVGVectorialReader.ConvertSVGDeltaToFPVDelta(
+  const AData: TvVectorialDocument; const ASrcX, ASrcY: Float; var ADestX,
+  ADestY: Float);
+begin
+  ADestX := ASrcX * FLOAT_MILIMETERS_PER_PIXEL;
+  ADestY := - ASrcY * FLOAT_MILIMETERS_PER_PIXEL;
+end;
+
 constructor TvSVGVectorialReader.Create;
 begin
   inherited Create;
@@ -278,6 +339,10 @@ begin
     // Read in xml file from the stream
     ReadXMLFile(Doc, AStream);
 
+    // Read the properties of the <svg> tag
+    AData.Width := StringWithUnitToFloat(Doc.DocumentElement.GetAttribute('width'));
+    AData.Height := StringWithUnitToFloat(Doc.DocumentElement.GetAttribute('height'));
+
     // Now process the elements inside the first layer
     lFirstLayer := Doc.DocumentElement.FirstChild;
     lCurNode := lFirstLayer.FirstChild;