diff --git a/components/fpvectorial/fpvectorial.pas b/components/fpvectorial/fpvectorial.pas index 77b40c5c8e..ca649a825d 100644 --- a/components/fpvectorial/fpvectorial.pas +++ b/components/fpvectorial/fpvectorial.pas @@ -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} diff --git a/components/fpvectorial/fpvutils.pas b/components/fpvectorial/fpvutils.pas index d2f2ad9bcb..aa795a07c1 100644 --- a/components/fpvectorial/fpvutils.pas +++ b/components/fpvectorial/fpvutils.pas @@ -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 diff --git a/components/fpvectorial/svgvectorialreader.pas b/components/fpvectorial/svgvectorialreader.pas index 0e9a5f5b3e..45880931eb 100644 --- a/components/fpvectorial/svgvectorialreader.pas +++ b/components/fpvectorial/svgvectorialreader.pas @@ -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();