fpc/packages/fpvectorial/src/svgvectorialwriter.pas
sekelsenmat 3708922b62 Now the SVG writer works for lines
git-svn-id: trunk@15801 -
2010-08-13 15:32:03 +00:00

128 lines
4.0 KiB
ObjectPascal

{
Writes an SVG Document
License: The same modified LGPL as the Free Pascal RTL
See the file COPYING.modifiedLGPL for more details
AUTHORS: Felipe Monteiro de Carvalho
}
unit svgvectorialwriter;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils,
fpvectorial;
type
{ TvSVGVectorialWriter }
TvSVGVectorialWriter = class(TvCustomVectorialWriter)
private
FPointSeparator, FCommaSeparator: TFormatSettings;
procedure WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
procedure WriteDocumentName(AStrings: TStrings; AData: TvVectorialDocument);
procedure WritePaths(AStrings: TStrings; AData: TvVectorialDocument);
public
{ General reading methods }
procedure WriteToStrings(AStrings: TStrings; AData: TvVectorialDocument); override;
end;
implementation
{ TvSVGVectorialWriter }
procedure TvSVGVectorialWriter.WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
begin
AStrings.Add(' width="' + FloatToStr(AData.Width, FPointSeparator) + 'mm"');
AStrings.Add(' height="' + FloatToStr(AData.Height, FPointSeparator) + 'mm"');
end;
procedure TvSVGVectorialWriter.WriteDocumentName(AStrings: TStrings; AData: TvVectorialDocument);
begin
AStrings.Add(' sodipodi:docname="New document 1">');
end;
{@@
SVG Coordinate system measures things in whatever unit we pass to it, so we
choose to pass in millimiters (mm), like FPVectorial uses.
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.
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);
var
i, j: Integer;
PathStr: string;
lPath: TPath;
PtX, PtY: double;
begin
for i := 0 to AData.GetPathCount() - 1 do
begin
PathStr := 'm ';
lPath := AData.GetPath(i);
for j := 0 to lPath.Len - 1 do
begin
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 ';
end;
AStrings.Add(' <path');
AStrings.Add(' style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"');
AStrings.Add(' d="' + PathStr + '"');
AStrings.Add(' id="path' + IntToStr(i) + '" />');
end;
end;
procedure TvSVGVectorialWriter.WriteToStrings(AStrings: TStrings;
AData: TvVectorialDocument);
begin
// Format seetings to convert a string to a float
FPointSeparator := DefaultFormatSettings;
FPointSeparator.DecimalSeparator := '.';
FPointSeparator.ThousandSeparator := '#';// disable the thousand separator
FCommaSeparator := DefaultFormatSettings;
FCommaSeparator.DecimalSeparator := ',';
FCommaSeparator.ThousandSeparator := '#';// disable the thousand separator
// Headers
AStrings.Add('<?xml version="1.0" encoding="UTF-8" standalone="no"?>');
AStrings.Add('<!-- Created with fpVectorial (http://wiki.lazarus.freepascal.org/fpvectorial) -->');
AStrings.Add('');
AStrings.Add('<svg');
AStrings.Add(' xmlns:dc="http://purl.org/dc/elements/1.1/"');
AStrings.Add(' xmlns:cc="http://creativecommons.org/ns#"');
AStrings.Add(' xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"');
AStrings.Add(' xmlns:svg="http://www.w3.org/2000/svg"');
AStrings.Add(' xmlns="http://www.w3.org/2000/svg"');
AStrings.Add(' xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"');
WriteDocumentSize(AStrings, AData);
AStrings.Add(' id="svg2"');
AStrings.Add(' version="1.1"');
WriteDocumentName(AStrings, AData);
// Now data
AStrings.Add(' <g id="layer1">');
WritePaths(AStrings, AData);
AStrings.Add(' </g>');
// finalization
AStrings.Add('</svg>');
end;
initialization
RegisterVectorialWriter(TvSVGVectorialWriter, vfSVG);
end.