Output to Scalable Vector Graphics (SVG) File
We show you how to install the fpVectorial component and to use it to create a vector graphic and save it in a new .svg file. Some of the code is derived from the supplied example fpvwritetest. These instructions include the installation of the package fpvectorialpkg (which you might have already installed in order to write to a new .docx file). The component has been described as a "pre-alpha" version but it is fine for demonstrating the ability to generate scalable images from Pascal code.
Alternatively, you can:
- use a graphics application such as Inkscape to create your own SVG files by dropping and dragging shapes;
- create and/or edit a .svg file (such as the one produced by this demo) in a text editor;
- embed SVG code in an HTML5 file; the code between svg tags is easy to read and write.
- Select menu item Package > Install/Uninstall Package ... and select from the right panel fpvectorialpkg 0.0.
-
Click the "Install selection" button and then the "Save and rebuild IDE" button and accept the invitation to continue.
Lazarus will close and then reopen with the newly installed component.
- Select menu item Project > New Project and create a new simple program.
- Select menu item File > Save As ... and save the project as SVG_Demo.
- Select menu item Project > Project Inspector and click on the Add (+) icon.
- In the Project Inspector, select the New Requirement tab and then select fpvectorialpkg from the drop-down list.
-
Click on the "Create New Requirement" button and then paste this code to replace the existing code in the editor.
program SVG_Demo; {$mode objfpc}{$H+} uses fpvectorial, svgvectorialwriter, fpvutils, fpvectorialpkg, fpCanvas; const TextYOffset = -12; TextXOffset = -1; var Vec: TvVectorialDocument; Page: TvVectorialPage; LastCircle, NewCircle: tvCircle; NewRect: TvRectangle; LastPath: TPath; i: integer; begin Vec := TvVectorialDocument.Create; try Vec.Width := 120; Vec.Height := 110; Page := Vec.AddPage; with Page do begin Height := Vec.Height; Width := Vec.Width; StartPath; AddMoveToPath(0, 0); AddLineToPath(0, 100); AddMoveToPath(0, 0); AddLineToPath(100, 0); SetPenWidth(2); SetPenColor(RGBToFPColor(0, 0, 0)); EndPath; // Y axis AddText(0, 20 + TextYOffset, 0, '', 8, '_20'); AddText(0, 40 + TextYOffset, 0, '', 8, '_40'); AddText(0, 60 + TextYOffset, 0, '', 8, '_60'); AddText(0, 80 + TextYOffset, 0, '', 8, '_80'); // X axis StartPath; for i := 1 to 5 do begin AddMoveToPath(20 * i, -2); AddLineToPath(20 * i, 2); end; SetPenWidth(1); SetPenColor(RGBToFPColor(0, 0, 0)); EndPath; AddText(0 + TextXOffset, -9 + TextYOffset, 0, '', 8, '0'); AddText(20 + TextXOffset, -9 + TextYOffset, 0, '', 8, '20'); AddText(40 + TextXOffset, -9 + TextYOffset, 0, '', 8, '40'); AddText(60 + TextXOffset, -9 + TextYOffset, 0, '', 8, '60'); AddText(80 + TextXOffset, -9 + TextYOffset, 0, '', 8, '80'); AddText(100 + TextXOffset, -9 + TextYOffset, 0, '', 8, '100'); AddCircle(50, 50, 30); // Modify properties of added circle LastCircle := tvCircle(GetLastEntity); LastCircle.Pen.Color := RGBToFPColor(255, 50, 50); LastCircle.Pen.Width := 3; // Create new circle and assign properties NewCircle := tvCircle.Create(Page); NewCircle.X := 30; NewCircle.Y := 30; NewCircle.Radius := 13; NewCircle.Brush.Style:= bsSolid; // necessary to enable fill NewCircle.Brush.Color := RGBToFPColor(100, 255, 100); NewCircle.Pen.Color := RGBToFPColor(0, 0, 255); AddEntity(NewCircle); // Draw pentagon (irregular) StartPath; AddMoveToPath(60, 70); AddLineToPath(60, 80); AddLineToPath(67.5, 90); AddLineToPath(75, 80); AddLineToPath(75, 70); AddLineToPath(60, 70); SetPenWidth(2); SetPenColor(RGBToFPColor(0, 250, 0)); EndPath; // Change properties of pentagon LastPath := TPath(GetLastEntity); LastPath.Brush.Style := bsSolid; LastPath.Brush.Color := RGBToFPColor(240, 250, 0); end; Vec.WriteToFile('svgdemo.svg', vfSVG); finally Vec.Free; end; end.
The text in the resultant SVG file follows. Note the following points.- Coordinates supplied in mm with y increasing up the page have been converted to pixels with y increasing downwards. Procedure ConvertFPVCoordinatesToSVGCoordinates in the svgvectorialwriter unit divides values by the number of mm per pixel (0.2822) so that 100 mm converts to 100/0.2833 = 354.358610914245 pixels. This matches the dots per inch (DPI) used by Opera and Inkscape.
- The initial m is for relative move and l is for line to relative position.
- Colours given as RGB values in denary are converted to hex, so that, for example LastCircle.Pen.Color := RGBToFPColor(255, 50, 50); translates to stroke="#FF3232".
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <!-- Created with fpVectorial (http://wiki.lazarus.freepascal.org/fpvectorial) --> <svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" width="120mm" height="110mm" id="svg2" version="1.1" sodipodi:docname="New document 1"> <g id="layer1"> <path style="fill:none;stroke:#000000;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;" d="m 0,389.79447200567 l 0,-354.358610914245 m 0,354.358610914245 l 354.358610914245,0 " id="path0" /> <text x="4" y="313.44578313253" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > _20 </tspan></text> <text x="4" y="242.574060949681" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > _40 </tspan></text> <text x="4" y="171.702338766832" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > _60 </tspan></text> <text x="4" y="100.830616583983" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > _80 </tspan></text> <path style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;" d="m 70.871722182849,396.881644223955 l 0,-14.1743444365698 m 70.871722182849,14.1743444365698 l 0,-14.1743444365698 m 70.8717221828491,14.1743444365698 l 0,-14.1743444365698 m 70.871722182849,14.1743444365698 l 0,-14.1743444365698 m 70.8717221828491,14.1743444365698 l 0,-14.1743444365698 " id="path5" /> <text x="0.456413890857548" y="416.209780297661" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > 0 </tspan></text> <text x="71.3281360737066" y="416.209780297661" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > 20 </tspan></text> <text x="142.199858256556" y="416.209780297661" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > 40 </tspan></text> <text x="213.071580439405" y="416.209780297661" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > 60 </tspan></text> <text x="283.943302622254" y="416.209780297661" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > 80 </tspan></text> <text x="354.815024805103" y="416.209780297661" font-family="Arial, sans-serif"> <tspan style="font-size:29" fill="#000000" > 100 </tspan></text> <circle cx="177.179305457123" cy="212.615166548547" r="106.307583274274" stroke="#FF3232" stroke-width="3" fill="none"/> <circle cx="106.307583274274" cy="283.486888731396" r="46.0666194188519" stroke="#0000FF" stroke-width="1" fill="#64FF64"/> <path style="fill:#F0FA00;stroke:#00FA00;stroke-width:2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;" d="m 212.615166548547,141.743444365698 l 0,-35.4358610914245 l 26.5768958185684,-35.4358610914245 l 26.5768958185684,35.4358610914245 l 0,35.4358610914245 l -53.1537916371368,0 " id="path14" /> </g> </svg>
-
Execute the program and open svgdemo.svg (which should be in your program folder) with an application such as Opera, Chrome, Firefox, Internet Explorer or Inkscape.
You should see something like this image (now viewed in your current browser):
svgdemo.svg
The generated image shows the input coordinate system with the circle centres at the points 30, 30 and 50, 50.