From c2270697a8cefe437d151f5db4db3f6cd0d53919 Mon Sep 17 00:00:00 2001 From: sekelsenmat Date: Tue, 31 Aug 2010 09:48:27 +0000 Subject: [PATCH] Patch from JiXian, advances the implementation of text rendering and bezier drawing for the svg writer in fpvectorial git-svn-id: trunk@15923 - --- packages/fpvectorial/src/fpvectorial.pas | 53 ++++--- .../fpvectorial/src/svgvectorialwriter.pas | 130 +++++++++++++++++- 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(' '); WritePaths(AStrings, AData); + WriteTexts(AStrings, AData); + WriteBeziers(AStrings, AData); AStrings.Add(' '); // finalization AStrings.Add(''); 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(' ' + TextStr + ''); + 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(' '); + end; +end; + initialization RegisterVectorialWriter(TvSVGVectorialWriter, vfSVG);