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
AUTHORS: Felipe Monteiro de Carvalho
Pedro Sol Pegorini L de Lima
}
unit fpvectorial;
@ -5092,7 +5091,7 @@ begin
begin
if (Brush.Style = bsSolid) and (Length(FPolyStarts) > 1) then
// 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)
else
{$IFDEF USE_LCL_CANVAS}

View File

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

View File

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