diff options
| author | sekelsenmat <sekelsenmat@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2010-08-31 09:48:27 +0000 |
|---|---|---|
| committer | sekelsenmat <sekelsenmat@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2010-08-31 09:48:27 +0000 |
| commit | a5eb413d44cac3c3521c066f4455d3f73ad0c8bc (patch) | |
| tree | 8379de90a2d81a30ef72caf2b95cb153becbdb28 /packages/fpvectorial | |
| parent | 1dccd3178ec46921bbd161e0b8f534870e24270a (diff) | |
| download | fpc-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.pas | 53 | ||||
| -rw-r--r-- | packages/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(' <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); |
