fpvectorial-svg: Fixes the start position of secondary paths inside a path, improves file alarm.svg

git-svn-id: trunk@55389 -
This commit is contained in:
sekelsenmat 2017-06-23 11:54:43 +00:00
parent 41c18b95d6
commit 9b325e675c
3 changed files with 64 additions and 46 deletions

View File

@ -7,7 +7,6 @@ License: The same modified LGPL as the Free Pascal RTL
See the file COPYING.modifiedLGPL for more details See the file COPYING.modifiedLGPL for more details
AUTHORS: Felipe Monteiro de Carvalho AUTHORS: Felipe Monteiro de Carvalho
Pedro Sol Pegorini L de Lima
} }
unit fpvectorial; unit fpvectorial;
@ -5092,7 +5091,7 @@ begin
begin begin
if (Brush.Style = bsSolid) and (Length(FPolyStarts) > 1) then if (Brush.Style = bsSolid) and (Length(FPolyStarts) > 1) then
// Non-contiguous polygon (polygon with "holes") --> use special procedure // Non-contiguous polygon (polygon with "holes") --> use special procedure
// Disadvantage: it can oly do solid fills! // Disadvantage: it can only do solid fills!
DrawPolygon(ADest, ARenderInfo, FPolyPoints, FPolyStarts, lRect) DrawPolygon(ADest, ARenderInfo, FPolyPoints, FPolyStarts, lRect)
else else
{$IFDEF USE_LCL_CANVAS} {$IFDEF USE_LCL_CANVAS}

View File

@ -637,39 +637,39 @@ begin
case curSegment.SegmentType of case curSegment.SegmentType of
stMoveTo: stMoveTo:
begin begin
// Store current length of points array as polygon start index // Store current length of points array as polygon start index
if numPolygons >= Length(PolygonStartIndexes) then if numPolygons >= Length(PolygonStartIndexes) then
SetLength(PolygonstartIndexes, Length(PolygonStartIndexes) + POINT_BUFFER); SetLength(PolygonstartIndexes, Length(PolygonStartIndexes) + POINT_BUFFER);
PolygonStartIndexes[numPolygons] := numPoints; PolygonStartIndexes[numPolygons] := numPoints;
inc(numPolygons); inc(numPolygons);
// Store current point as first point of a new polygon // Store current point as first point of a new polygon
coordX := CoordToCanvasX(cur2DSegment.X, ADestX, AMulX); coordX := CoordToCanvasX(cur2DSegment.X, ADestX, AMulX);
coordY := CoordToCanvasY(cur2DSegment.Y, ADestY, AMulY); coordY := CoordToCanvasY(cur2DSegment.Y, ADestY, AMulY);
if numPoints >= Length(PolygonPoints) then if numPoints >= Length(PolygonPoints) then
SetLength(PolygonPoints, Length(PolygonPoints) + POINT_BUFFER); SetLength(PolygonPoints, Length(PolygonPoints) + POINT_BUFFER);
PolygonPoints[numPoints] := Point(coordX, coordY); PolygonPoints[numPoints] := Point(coordX, coordY);
inc(numPoints); inc(numPoints);
end; end;
st2DLine, st3DLine, st2DLineWithPen: st2DLine, st3DLine, st2DLineWithPen:
begin begin
// Add current point to current polygon // Add current point to current polygon
coordX := CoordToCanvasX(cur2DSegment.X, ADestX, AMulX); coordX := CoordToCanvasX(cur2DSegment.X, ADestX, AMulX);
coordY := CoordToCanvasY(cur2DSegment.Y, ADestY, AMulY); coordY := CoordToCanvasY(cur2DSegment.Y, ADestY, AMulY);
if numPoints >= Length(PolygonPoints) then if numPoints >= Length(PolygonPoints) then
SetLength(PolygonPoints, Length(PolygonPoints) + POINT_BUFFER); SetLength(PolygonPoints, Length(PolygonPoints) + POINT_BUFFER);
PolygonPoints[numPoints] := Point(coordX, coordY); PolygonPoints[numPoints] := Point(coordX, coordY);
inc(numPoints); inc(numPoints);
end; end;
st2DBezier, st3DBezier, st2DEllipticalArc: st2DBezier, st3DBezier, st2DEllipticalArc:
begin begin
SetLength(PolygonPoints, numPoints); SetLength(PolygonPoints, numPoints);
curSegment.AddToPoints(ADestX, ADestY, AMulX, AMulY, PolygonPoints); curSegment.AddToPoints(ADestX, ADestY, AMulX, AMulY, PolygonPoints);
numPoints := Length(PolygonPoints); numPoints := Length(PolygonPoints);
end; end;
end; end;
end; end;
SetLength(PolygonPoints, numPoints); SetLength(PolygonPoints, numPoints);
@ -763,7 +763,8 @@ begin
list := TFPList.Create; list := TFPList.Create;
if ACoordIsX then if ACoordIsX then
begin begin
for p := 0 to High(APolyStarts) do begin for p := 0 to High(APolyStarts) do
begin
firstj := APolyStarts[p]; firstj := APolyStarts[p];
lastj := IfThen(p = High(APolyStarts), High(APoints), APolyStarts[p+1]-1); lastj := IfThen(p = High(APolyStarts), High(APoints), APolyStarts[p+1]-1);
// Skip non-closed polygons // Skip non-closed polygons

View File

@ -145,6 +145,8 @@ type
CurX, CurY: Double; CurX, CurY: Double;
Data: TvVectorialPage; Data: TvVectorialPage;
Doc: TvVectorialDocument; Doc: TvVectorialDocument;
// Path support for multiple polygons
LastPathStart: T2DPoint;
function GetPath(AIndex: Integer): TPath; function GetPath(AIndex: Integer): TPath;
end; end;
@ -152,7 +154,7 @@ type
TvSVGVectorialReader = class(TvCustomVectorialReader) TvSVGVectorialReader = class(TvCustomVectorialReader)
private private
FPointSeparator, FCommaSeparator: TFormatSettings; FPointSeparator: TFormatSettings;
FSVGPathTokenizer: TSVGPathTokenizer; FSVGPathTokenizer: TSVGPathTokenizer;
FLayerStylesKeys, FLayerStylesValues: TFPList; // of TStringList; FLayerStylesKeys, FLayerStylesValues: TFPList; // of TStringList;
// View box adjustment // View box adjustment
@ -163,8 +165,6 @@ type
FCSSDefs: TFPList; // of TSVG_CSS_Style; FCSSDefs: TFPList; // of TSVG_CSS_Style;
// debug symbols // debug symbols
FPathNumber: Integer; FPathNumber: Integer;
// Path support for multiple polygons
FPathStart: T2DPoint;
// BrushDefs functions // BrushDefs functions
function FindBrushDef_WithName(AName: string): TvEntityWithPenAndBrush; function FindBrushDef_WithName(AName: string): TvEntityWithPenAndBrush;
// //
@ -2309,12 +2309,18 @@ begin
lCurPath.Brush.Style := bsClear; lCurPath.Brush.Style := bsClear;
// Apply the layer style // Apply the layer style
ApplyLayerStyles(AData, lCurPath); ApplyLayerStyles(AData, lCurPath);
// name
if lPaths.Count > 1 then
lCurPath.Name := Format('[%d]', [i]);
// Add the pen/brush/name // Add the pen/brush/name
for i := 0 to ANode.Attributes.Length - 1 do for i := 0 to ANode.Attributes.Length - 1 do
begin begin
lNodeName := ANode.Attributes.Item[i].NodeName; lNodeName := ANode.Attributes.Item[i].NodeName;
if lNodeName = 'id' then if lNodeName = 'id' then
lCurPath.Name := ANode.Attributes.Item[i].NodeValue begin
if lPaths.Count = 1 then
lCurPath.Name := ANode.Attributes.Item[i].NodeValue;
end
else if lNodeName = 'style' then else if lNodeName = 'style' then
ReadSVGStyle(AData, ANode.Attributes.Item[i].NodeValue, lCurPath) ReadSVGStyle(AData, ANode.Attributes.Item[i].NodeValue, lCurPath)
else if IsAttributeFromStyle(lNodeName) then else if IsAttributeFromStyle(lNodeName) then
@ -2333,14 +2339,23 @@ begin
begin begin
Result := lPaths.GetPath(0); Result := lPaths.GetPath(0);
end end
else else if lPaths.Count > 1 then
begin begin
Result := TvEntityWithSubEntities.Create(nil); Result := TvEntityWithSubEntities.Create(nil);
for j := 0 to lPaths.Count-1 do for j := 0 to lPaths.Count-1 do
begin begin
lCurPath := lPaths.GetPath(j); lCurPath := lPaths.GetPath(j);
TvEntityWithSubEntities(Result).AddEntity(lCurPath); TvEntityWithSubEntities(Result).AddEntity(lCurPath);
end; end;
// Add thename
for i := 0 to ANode.Attributes.Length - 1 do
begin
lNodeName := ANode.Attributes.Item[i].NodeName;
if lNodeName = 'id' then
TvEntityWithSubEntities(Result).Name := ANode.Attributes.Item[i].NodeValue;
end;
end; end;
end; end;
@ -2348,11 +2363,8 @@ end;
function TvSVGVectorialReader.ReadPathFromString(AStr: string; function TvSVGVectorialReader.ReadPathFromString(AStr: string;
AData: TvVectorialPage; ADoc: TvVectorialDocument): TvSVGPathList; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvSVGPathList;
var var
X, Y, X2, Y2, X3, Y3: Double;
lCurTokenType, lLastCommandToken: TSVGTokenType; lCurTokenType, lLastCommandToken: TSVGTokenType;
lDebugStr: String;
lTmpTokenType: TSVGTokenType; lTmpTokenType: TSVGTokenType;
lIsFirstPathMove, lLastPathClosed: Boolean;
begin begin
Result := TvSVGPathList.Create; Result := TvSVGPathList.Create;
FSVGPathTokenizer.ClearTokens; FSVGPathTokenizer.ClearTokens;
@ -2394,9 +2406,9 @@ procedure TvSVGVectorialReader.ReadNextPathCommand(ACurTokenType: TSVGTokenType;
APaths: TvSVGPathList; var CurX, CurY: Double); APaths: TvSVGPathList; var CurX, CurY: Double);
var var
X, Y, X2, Y2, X3, Y3, XQ, YQ, Xnew, Ynew, cx, cy, phi, tmp: Double; X, Y, X2, Y2, X3, Y3, XQ, YQ, Xnew, Ynew, cx, cy, phi, tmp: Double;
PathEndX, PathEndY: Double;
LargeArcFlag, SweepFlag, LeftmostEllipse, ClockwiseArc: Boolean; LargeArcFlag, SweepFlag, LeftmostEllipse, ClockwiseArc: Boolean;
lCurTokenType: TSVGTokenType; lCurTokenType: TSVGTokenType;
lDebugStr: String;
lToken5Before, lToken7Before: TSVGTokenType; lToken5Before, lToken7Before: TSVGTokenType;
lCorrectPreviousToken: Boolean; lCorrectPreviousToken: Boolean;
lPrevRelative, lCurRelative: Boolean; lPrevRelative, lCurRelative: Boolean;
@ -2435,9 +2447,10 @@ begin
// to close the subpolygon correctly later. // to close the subpolygon correctly later.
if APaths.IsFirstPathMove then if APaths.IsFirstPathMove then
begin begin
FPathStart.X := APaths.CurX; APaths.LastPathStart.X := APaths.CurX;
FPathStart.Y := APaths.CurY; APaths.LastPathStart.Y := APaths.CurY;
APaths.IsFirstPathMove := false; APaths.IsFirstPathMove := False;
APaths.LastPathClosed := False;
end; end;
Inc(APaths.CurTokenIndex, 3); Inc(APaths.CurTokenIndex, 3);
@ -2448,10 +2461,15 @@ begin
else if lCurTokenType = sttClosePath then else if lCurTokenType = sttClosePath then
begin begin
// Repeat the first point of the subpolygon // Repeat the first point of the subpolygon
CurX := FPathStart.X; PathEndX := APaths.LastPathStart.X;
CurY := FPathStart.Y; PathEndY := APaths.LastPathStart.Y;
APaths.Data.AddLineToPath(CurX, CurY); CurX := PathEndX;
CurY := PathEndY;
APaths.LastPathStart.X := 0;
APaths.LastPathStart.Y := 0;
APaths.Data.AddLineToPath(PathEndX, PathEndY);
APaths.LastPathClosed := True; APaths.LastPathClosed := True;
APaths.IsFirstPathMove := True;
APaths.Add(AData.EndPath(True)); APaths.Add(AData.EndPath(True));
AData.StartPath(); AData.StartPath();