summaryrefslogtreecommitdiff
path: root/packages/fpvectorial
diff options
context:
space:
mode:
authorsekelsenmat <sekelsenmat@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-08-31 09:48:27 +0000
committersekelsenmat <sekelsenmat@3ad0048d-3df7-0310-abae-a5850022a9f2>2010-08-31 09:48:27 +0000
commita5eb413d44cac3c3521c066f4455d3f73ad0c8bc (patch)
tree8379de90a2d81a30ef72caf2b95cb153becbdb28 /packages/fpvectorial
parent1dccd3178ec46921bbd161e0b8f534870e24270a (diff)
downloadfpc-a5eb413d44cac3c3521c066f4455d3f73ad0c8bc.tar.gz
Patch from JiXian, advances the implementation of text rendering and bezier drawing for the svg writer in fpvectorial
git-svn-id: http://svn.freepascal.org/svn/fpc/trunk@15923 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'packages/fpvectorial')
-rw-r--r--packages/fpvectorial/src/fpvectorial.pas53
-rw-r--r--packages/fpvectorial/src/svgvectorialwriter.pas130
2 files changed, 163 insertions, 20 deletions
diff --git a/packages/fpvectorial/src/fpvectorial.pas b/packages/fpvectorial/src/fpvectorial.pas
index 71e8d096ab..1b2a7cb0d5 100644
--- a/packages/fpvectorial/src/fpvectorial.pas
+++ b/packages/fpvectorial/src/fpvectorial.pas
@@ -41,7 +41,7 @@ const
type
TSegmentType = (
st2DLine, st2DBezier,
- st3DLine, st3DBezier);
+ st3DLine, st3DBezier, stMoveTo);
{@@
The coordinates in fpvectorial are given in millimiters and
@@ -69,8 +69,12 @@ type
At the moment fonts are unsupported, only simple texts
up to 255 chars are supported.
}
+
TvText = record
- Value: array[0..255] of Char;
+ X, Y, Z: Double; // Z is ignored in 2D formats
+ FontSize: integer;
+ FontName: utf8string;
+ Value: utf8string;
end;
PText = ^TvText;
@@ -87,6 +91,7 @@ type
FPaths: TFPList;
FTexts: TFPList;
FTmpPath: TPath;
+ FTmpText: TvText;
procedure RemoveCallback(data, arg: pointer);
function CreateVectorialWriter(AFormat: TvVectorialFormat): TvCustomVectorialWriter;
function CreateVectorialReader(AFormat: TvVectorialFormat): TvCustomVectorialReader;
@@ -121,8 +126,8 @@ type
procedure AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double); overload;
procedure AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double); overload;
procedure EndPath();
- procedure AddText(AText: TvText); overload;
- procedure AddText(AStr: utf8string); overload;
+ procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
+ procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload;
{ properties }
property PathCount: Integer read GetPathCount;
property Paths[Index: Cardinal]: TPath read GetPath;
@@ -338,7 +343,7 @@ end;
procedure TvVectorialDocument.StartPath(AX, AY: Double);
begin
FTmpPath.Len := 1;
- FTmpPath.Points[0].SegmentType := st2DLine;
+ FTmpPath.Points[0].SegmentType := stMoveTo;
FTmpPath.Points[0].X := AX;
FTmpPath.Points[0].Y := AY;
end;
@@ -394,8 +399,21 @@ end;
procedure TvVectorialDocument.AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2,
AX3, AY3, AZ3: Double);
+var
+ L: Integer;
begin
-
+ L := FTmPPath.Len;
+ Inc(FTmPPath.Len);
+ FTmPPath.Points[L].SegmentType := st3DBezier;
+ FTmPPath.Points[L].X := AX3;
+ FTmPPath.Points[L].Y := AY3;
+ FTmPPath.Points[L].Z := AZ3;
+ FTmPPath.Points[L].X2 := AX1;
+ FTmPPath.Points[L].Y2 := AY1;
+ FTmPPath.Points[L].Z2 := AZ1;
+ FTmPPath.Points[L].X3 := AX2;
+ FTmPPath.Points[L].Y3 := AY2;
+ FTmPPath.Points[L].Z3 := AZ2;
end;
{@@
@@ -415,23 +433,26 @@ begin
FTmPPath.Len := 0;
end;
-procedure TvVectorialDocument.AddText(AText: TvText);
+procedure TvVectorialDocument.AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string);
var
lText: PText;
- Len: Integer;
begin
- Len := SizeOf(TvText);
- lText := GetMem(Len);
- Move(AText, lText^, Len);
+ lText := GetMem(SizeOf(TvText));
+ SetLength(lText.Value, Length(AText));
+ Move(AText[1], lText.Value[1], Length(AText));
+ lText.X:=AX;
+ lText.Y:=AY;
+ lText.Z:=AZ;
+ //lText.FontName:=FontName;
+ SetLength(lText.FontName, Length(FontName));
+ Move(FontName[1], lText.FontName[1], Length(FontName));
+ lText.FontSize:=FontSize;
FTexts.Add(lText);
end;
-procedure TvVectorialDocument.AddText(AStr: utf8string);
-var
- lText: TvText;
+procedure TvVectorialDocument.AddText(AX, AY, AZ: Double; AStr: utf8string);
begin
- lText.Value := AStr;
- AddText(lText);
+ AddText(AX, AY, AZ, 'Arial', 10, AStr);
end;
{@@
diff --git a/packages/fpvectorial/src/svgvectorialwriter.pas b/packages/fpvectorial/src/svgvectorialwriter.pas
index 1ffc9cb451..cae34de19b 100644
--- a/packages/fpvectorial/src/svgvectorialwriter.pas
+++ b/packages/fpvectorial/src/svgvectorialwriter.pas
@@ -13,8 +13,7 @@ unit svgvectorialwriter;
interface
uses
- Classes, SysUtils,
- fpvectorial;
+ Classes, SysUtils, math, fpvectorial;
type
{ TvSVGVectorialWriter }
@@ -25,6 +24,8 @@ type
procedure WriteDocumentSize(AStrings: TStrings; AData: TvVectorialDocument);
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);
@@ -81,8 +82,13 @@ begin
lPath := AData.GetPath(i);
for j := 0 to lPath.Len - 1 do
begin
- if lPath.Points[j].SegmentType <> st2DLine then Break; // unsupported line type
-
+ if (lPath.Points[j].SegmentType <> st2DLine)
+ and (lPath.Points[j].SegmentType <> stMoveTo)
+ 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);
@@ -142,12 +148,128 @@ begin
// Now data
AStrings.Add(' <g id="layer1">');
WritePaths(AStrings, AData);
+ WriteTexts(AStrings, AData);
+ WriteBeziers(AStrings, AData);
AStrings.Add(' </g>');
// finalization
AStrings.Add('</svg>');
end;
+procedure TvSVGVectorialWriter.WriteTexts(AStrings: TStrings; AData: TvVectorialDocument);
+var
+ i, j, FontSize: Integer;
+ TextStr, FontName: string;
+ ltest: TvText;
+ PtX, PtY: double;
+begin
+ for i := 0 to AData.GetTextCount() - 1 do
+ begin
+ TextStr := '';
+ ltest := AData.GetText(i);
+ //PtX := ltest.X;
+ //PtY := ltest.Y;
+ ConvertFPVCoordinatesToSVGCoordinates(
+ AData, ltest.X, ltest.Y, PtX, PtY);
+ TextStr := ltest.Value;
+ FontSize:= ceil(ltest.FontSize / FLOAT_MILIMETERS_PER_PIXEL);
+ FontName:=ltest.FontName;
+ AStrings.Add(' <text');
+ AStrings.Add(' style="font-size:'
+ +IntToStr(FontSize)+'px;font-style:normal;font-weight:normal;line-height:125%;'
+ +'letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;'
+ +'font-family:'+FontName+'"><tspan');
+ AStrings.Add(' x="' + FloatToStr(PtX, FPointSeparator) + '"');
+ AStrings.Add(' y="' + FloatToStr(PtY, FPointSeparator) + '"');
+ AStrings.Add(' id="tspan3071">' + TextStr + '</tspan></text>');
+ 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 <> st3DBezier)
+ and (BezierType<> st2DLine)
+ then Break; // unsupported Bezier type
+
+ //ConvertFPVCoordinatesToSVGCoordinates(
+ // AData, lPath.Points[j].X, lPath.Points[j].Y, PtX, PtY);
+
+ if (BezierType = st2DBezier) or (BezierType = stMoveTo) then
+ begin
+ PtX := lPath.Points[j].X / FLOAT_MILIMETERS_PER_PIXEL;
+ PtY := (AData.Height - lPath.Points[j].Y) / FLOAT_MILIMETERS_PER_PIXEL;
+ PtX2 := lPath.Points[j].X2 / FLOAT_MILIMETERS_PER_PIXEL;
+ PtY2 := (AData.Height - lPath.Points[j].Y2) / FLOAT_MILIMETERS_PER_PIXEL;
+ PtX3 := lPath.Points[j].X3 / FLOAT_MILIMETERS_PER_PIXEL;
+ PtY3 := (AData.Height - lPath.Points[j].Y3) / FLOAT_MILIMETERS_PER_PIXEL;
+
+ 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
+ // if BezierType = st2DBezier then
+ 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(' <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="Bezier' + IntToStr(i) + '" />');
+ end;
+end;
+
initialization
RegisterVectorialWriter(TvSVGVectorialWriter, vfSVG);