Merged revision(s) 50768 #0f4cc7840e, 50807-50810 #478a6d00a4-#478a6d00a4, 50818-50819 #5fe2efae86-#5fe2efae86, 50875 #506bdbde54 from trunk:

fpvectorial: Fix text positioning issue when reading svg files.
........
fpvectorial: Fix calculation of bounding rectangle of all entities on a page
........
fpvectorial: Fix memory leak of svg tokenizer. Add ReadDefsFromNode to TvSVGVectorialReader.ReadEntityFromNode. Prepare reading of line styles for svg.
........
fpvectorial: Fix memory leak of TvEntityWithSubEntities due to not releasing items in FElements list.
........
fpvectorial: Fix bounding box of circle. Fix page bounding box in case of several top-level entities.
........
fpvectorial: Add parameter to Render method for calculation of bounding box without drawing. 
Fix svgreader crashing due to incorrect decimal separator in "stroke-opacity".
........
fpvectorial: Fix runtime error with fpc trunk due to duplicate application of ExtractFileExt returning no extension any more.
........
fpvectorial: svg reader detects pen styles & patterns now. Fix rendering of lines with the specified pen styles & patterns.
........

git-svn-id: branches/fixes_1_6@50877 -
This commit is contained in:
maxim 2015-12-17 21:54:46 +00:00
parent 0ea790b8d3
commit 0f4ab685b0
2 changed files with 360 additions and 194 deletions

View File

@ -117,6 +117,7 @@ type
Color: TFPColor;
Style: TFPPenStyle;
Width: Integer;
Pattern: array of LongWord;
end;
PvPen = ^TvPen;
@ -642,6 +643,7 @@ type
TvCircle = class(TvEntityWithPenAndBrush)
public
Radius: Double;
procedure CalculateBoundingBox(ADest: TFPCustomCanvas; var ALeft, ATop, ARight, ABottom: Double); override;
procedure Render(ADest: TFPCustomCanvas; var ARenderInfo: TvRenderInfo; ADestX: Integer = 0;
ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0; ADoDraw: Boolean = True); override;
end;
@ -1373,6 +1375,7 @@ type
MinX, MinY, MinZ, MaxX, MaxY, MaxZ: Double;
// Other basic document information
BackgroundColor: TFPColor;
AdjustPenColorToBackground: Boolean;
RenderInfo: TvRenderInfo; // Prepared by the reader with info on how to draw the page
{ Base methods }
constructor Create(AOwner: TvVectorialDocument); virtual;
@ -1398,7 +1401,8 @@ type
procedure RenderPageBorder(ADest: TFPCustomCanvas;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); virtual; abstract;
procedure Render(ADest: TFPCustomCanvas;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); virtual; abstract;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0;
ADoDraw: Boolean = true); virtual; abstract;
procedure AutoFit(ADest: TFPCustomCanvas; AWidth, AHeight: Integer; out ADeltaX, ADeltaY: Integer; out AZoom: Double); virtual; abstract;
{ Debug methods }
procedure GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer); virtual; abstract;
@ -1479,8 +1483,8 @@ type
procedure DrawBackground(ADest: TFPCustomCanvas); override;
procedure RenderPageBorder(ADest: TFPCustomCanvas;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
procedure Render(ADest: TFPCustomCanvas;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
procedure Render(ADest: TFPCustomCanvas; ADestX: Integer = 0; ADestY: Integer = 0;
AMulX: Double = 1.0; AMulY: Double = 1.0; ADoDraw: Boolean = true); override;
procedure AutoFit(ADest: TFPCustomCanvas; AWidth, AHeight: Integer; out ADeltaX, ADeltaY: Integer; out AZoom: Double); override;
{ Debug methods }
procedure GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer); override;
@ -1523,8 +1527,8 @@ type
procedure DrawBackground(ADest: TFPCustomCanvas); override;
procedure RenderPageBorder(ADest: TFPCustomCanvas;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
procedure Render(ADest: TFPCustomCanvas;
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0); override;
procedure Render(ADest: TFPCustomCanvas; ADestX: Integer = 0; ADestY: Integer = 0;
AMulX: Double = 1.0; AMulY: Double = 1.0; ADoDraw: Boolean = true); override;
procedure AutoFit(ADest: TFPCustomCanvas; AWidth, AHeight: Integer; out ADeltaX, ADeltaY: Integer; out AZoom: Double); override;
{ Debug methods }
procedure GenerateDebugTree(ADestRoutine: TvDebugAddItemProc; APageItem: Pointer); override;
@ -3168,7 +3172,7 @@ begin
ARenderInfo.EntityCanvasMinXY := Point(INVALID_RENDERINFO_CANVAS_XY, INVALID_RENDERINFO_CANVAS_XY);
ARenderInfo.EntityCanvasMaxXY := Point(INVALID_RENDERINFO_CANVAS_XY, INVALID_RENDERINFO_CANVAS_XY);
//ARenderInfo.BackgroundColor := colBlack; Don't change this because otherwise we lose the value set by the page
ARenderInfo.AdjustPenColorToBackground := True;
//ARenderInfo.AdjustPenColorToBackground := True; dto.
ARenderInfo.Selected := False;
ARenderInfo.ForceRenderBlock := False;
end;
@ -3340,8 +3344,15 @@ procedure TvEntityWithPen.ApplyPenToCanvas(ADest: TFPCustomCanvas;
ARenderInfo: TvRenderInfo; APen: TvPen);
begin
ADest.Pen.FPColor := AdjustColorToBackground(APen.Color, ARenderInfo);
ADest.Pen.Width := 1;//APen.Width;
ADest.Pen.Width := Max(1, APen.Width); // wp: why was here "1;//APen.Width;" ???
ADest.Pen.Style := APen.Style;
{$ifdef USE_LCL_CANVAS}
if (APen.Style = psPattern) then
begin
TCanvas(ADest).Pen.SetPattern(APen.Pattern);
if APen.Width = 1 then TCanvas(ADest).Pen.Cosmetic := false;
end;
{$endif}
end;
procedure TvEntityWithPen.AssignPen(APen: TvPen);
@ -3543,7 +3554,7 @@ procedure TvEntityWithPenBrushAndFont.Render(ADest: TFPCustomCanvas;
AMulY: Double; ADoDraw: Boolean);
begin
inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
ApplyFontToCanvas(ADest, ARenderInfo, AMulX);
ApplyFontToCanvas(ADest, ARenderInfo, AMulX); // wp: why not AMulY ?
end;
function TvEntityWithPenBrushAndFont.GenerateDebugTree(
@ -3939,12 +3950,14 @@ var
ACanvas: TCanvas absolute ADest;
{$endif}
begin
inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
PosX := 0;
PosY := 0;
ADest.Brush.Style := bsClear;
ADest.MoveTo(ADestX, ADestY);
{
// Set the path Pen and Brush options
ADest.Pen.Style := Pen.Style;
ADest.Pen.Width := Round(Pen.Width * AMulX);
@ -3952,8 +3965,12 @@ begin
if (Pen.Width <= 2) and (ADest.Pen.Width > 2) then ADest.Pen.Width := 2;
if (Pen.Width <= 5) and (ADest.Pen.Width > 5) then ADest.Pen.Width := 5;
ADest.Pen.FPColor := AdjustColorToBackground(Pen.Color, ARenderInfo);
{$ifdef USE_LCL_CANVAS}
if (Pen.Style = psPattern) then
ACanvas.Pen.SetPattern(Pen.Pattern);
{$endif}
ADest.Brush.FPColor := Brush.Color;
}
// Prepare the Clipping Region, if any
{$ifdef USE_CANVAS_CLIP_REGION}
if ClipPath <> nil then
@ -3972,7 +3989,8 @@ begin
{$endif}
// useful in some paths, like stars!
RenderInternalPolygon(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY);
if ADoDraw then
RenderInternalPolygon(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY);
//
// For other paths, draw more carefully
@ -3990,7 +4008,9 @@ begin
begin
CoordX := CoordToCanvasX(Cur2DSegment.X);
CoordY := CoordToCanvasY(Cur2DSegment.Y);
ADest.MoveTo(CoordX, CoordY);
if ADoDraw then
ADest.MoveTo(CoordX, CoordY);
CalcEntityCanvasMinMaxXY(ARenderInfo, CoordX, CoordY);
PosX := Cur2DSegment.X;
PosY := Cur2DSegment.Y;
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
@ -4118,20 +4138,21 @@ begin
ADest.Brush.Style := Brush.Style;
CalcEntityCanvasMinMaxXY_With2Points(ARenderInfo, CoordX, CoordY, CoordX4, CoordY4);
if ADoDraw then
begin
// Arc draws counterclockwise
if ADoDraw and Cur2DArcSegment.ClockwiseArcFlag then
begin
ACanvas.Arc(
EllipseRect.Left, EllipseRect.Top, EllipseRect.Right, EllipseRect.Bottom,
CoordX4, CoordY4, CoordX, CoordY);
end
else if ADoDraw then
begin
ACanvas.Arc(
EllipseRect.Left, EllipseRect.Top, EllipseRect.Right, EllipseRect.Bottom,
CoordX, CoordY, CoordX4, CoordY4);
if Cur2DArcSegment.ClockwiseArcFlag then
begin
ACanvas.Arc(
EllipseRect.Left, EllipseRect.Top, EllipseRect.Right, EllipseRect.Bottom,
CoordX4, CoordY4, CoordX, CoordY);
end else
begin
ACanvas.Arc(
EllipseRect.Left, EllipseRect.Top, EllipseRect.Right, EllipseRect.Bottom,
CoordX, CoordY, CoordX4, CoordY4);
end;
end;
PosX := Cur2DArcSegment.X;
PosY := Cur2DArcSegment.Y;
@ -4346,12 +4367,14 @@ procedure TvText.Render(ADest: TFPCustomCanvas; var ARenderInfo: TvRenderInfo; A
Result := Round(ADestY + AmulY * ACoord);
end;
const
LINE_SPACING = 0.2; // fraction of font height for line spacing
var
i: Integer;
//
LowerDim: T3DPoint;
XAnchorAdjustment: Integer;
lLongestLine, lLineWidth, lFontSizePx: Integer;
lLongestLine, lLineWidth, lFontSizePx, lFontDescenderPx: Integer;
lText: string;
{$ifdef USE_LCL_CANVAS}
ACanvas: TCanvas absolute ADest;
@ -4372,7 +4395,7 @@ begin
lLongestLine := 0;
for i := 0 to Value.Count - 1 do
begin
lLineWidth := ACanvas.TextWidth(Value.Strings[i]);
lLineWidth := ACanvas.TextWidth(Value.Strings[i]); // contains multiplier
if lLineWidth > lLongestLine then
lLongestLine := lLineWidth;
end;
@ -4386,15 +4409,15 @@ begin
// TvText supports multiple lines
for i := 0 to Value.Count - 1 do
begin
lFontSizePx := Font.Size;
lFontSizePx := Font.Size; // is without multiplier!
if lFontSizePx = 0 then lFontSizePx := 10;
// We need to keep the order of lines drawing correct regardless of
// the drawing direction
if AMulY < 0 then
LowerDim.Y := CoordToCanvasY(Y) + lFontSizePx * 1.2 * (Value.Count - i)
lowerDim.Y := CoordToCanvasY(Y) + lFontSizePx * (1 + LINE_SPACING) * (Value.Count - i) * AMulY
else
LowerDim.Y := CoordToCanvasY(Y) + lFontSizePx * 1.2 * i;
LowerDim.Y := CoordToCanvasY(Y) + lFontSizePx * (1 + LINE_SPACING) * i * AMulY;
ADest.Font.FPColor := AdjustColorToBackground(Font.Color, ARenderInfo);
lText := Value.Strings[i];
@ -4540,6 +4563,15 @@ end;
{ TvCircle }
procedure TvCircle.CalculateBoundingBox(ADest: TFPCustomCanvas;
var ALeft, ATop, ARight, ABottom: Double);
begin
ALeft := X - Radius;
ARight := X + Radius;
ATop := Y + Radius;
ABottom := Y - Radius;
end;
procedure TvCircle.Render(ADest: TFPCustomCanvas; var ARenderInfo: TvRenderInfo; ADestX: Integer;
ADestY: Integer; AMulX: Double; AMulY: Double; ADoDraw: Boolean);
@ -4553,14 +4585,18 @@ procedure TvCircle.Render(ADest: TFPCustomCanvas; var ARenderInfo: TvRenderInfo;
Result := Round(ADestY + AmulY * ACoord);
end;
var
x1, y1, x2, y2: Integer;
begin
inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
ADest.Ellipse(
CoordToCanvasX(X - Radius),
CoordToCanvasY(Y - Radius),
CoordToCanvasX(X + Radius),
CoordToCanvasY(Y + Radius)
);
x1 := CoordToCanvasX(X - Radius);
y1 := CoordToCanvasY(Y - Radius);
x2 := CoordToCanvasX(X + Radius);
y2 := CoordToCanvasY(Y + Radius);
ADest.Ellipse(x1, y1, x2, y2);
CalcEntityCanvasMinMaxXY_With2Points(ARenderInfo, x1, y1, x2, y2);
end;
{ TvCircularArc }
@ -4691,8 +4727,8 @@ begin
// First do the trivial
ALeft := X - HorzHalfAxis;
ARight := X + HorzHalfAxis;
ATop := Y - VertHalfAxis;
ABottom := Y + VertHalfAxis;
ATop := Y - VertHalfAxis; // wp: shouldn't this be "+" ...
ABottom := Y + VertHalfAxis; // ... and this "-" ?
{
To calculate the bounding rectangle we can do this:
@ -4771,12 +4807,13 @@ begin
// Conrollpoint of secondpart endpoint
PointList[6] := PointList[0]; // Endpoint of
// Back to the startpoint
ALCLDest.PolyBezier(Pointlist[0]);
if ADoDraw then
ALCLDest.PolyBezier(Pointlist[0]);
end
else
{$endif}
begin
ADest.Ellipse(x1, y1, x2, y2);
if ADoDraw then ADest.Ellipse(x1, y1, x2, y2);
end;
// Apply brush gradient
if x1 > x2 then
@ -4792,6 +4829,8 @@ begin
y2 := dk;
end;
DrawBrushGradient(ADest, ARenderInfo, x1, y1, x2, y2, ADestX, ADestY, AMulX, AMulY);
CalcEntityCanvasMinMaxXY_With2Points(ARenderInfo, x1, y1, x2, y2);
end;
{ TvRectangle }
@ -4830,14 +4869,19 @@ begin
y1 := CoordToCanvasY(fy1);
y2 := CoordToCanvasY(fy2);
{$ifdef USE_LCL_CANVAS}
if (RX = 0) and (RY = 0) then
if ADoDraw then
begin
{$ifdef USE_LCL_CANVAS}
if (RX = 0) and (RY = 0) then
ADest.Rectangle(x1, y1, x2, y2)
else
LCLIntf.RoundRect(TCanvas(ADest).Handle, x1, y1, x2, y2, Round(rx), Round(ry));
{$else}
ADest.Rectangle(x1, y1, x2, y2)
else
LCLIntf.RoundRect(TCanvas(ADest).Handle, x1, y1, x2, y2, Round(rx), Round(ry));
{$else}
ADest.Rectangle(x1, y1, x2, y2)
{$endif}
{$endif}
end;
CalcEntityCanvasMinMaxXY_With2Points(ARenderInfo, x1, y1, x2, y2);
end;
function TvRectangle.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
@ -4896,9 +4940,11 @@ begin
begin
lPoints[i].X := CoordToCanvasX(Points[i].X);
lPoints[i].Y := CoordToCanvasY(Points[i].Y);
CalcEntityCanvasMinMaxXY(ARenderInfo, lPoints[i].X, lPoints[i].Y);
end;
ADest.Polygon(lPoints);
if ADoDraw then
ADest.Polygon(lPoints);
end;
{ TvAlignedDimension }
@ -4922,6 +4968,7 @@ var
{$ifdef USE_LCL_CANVAS}
ALCLDest: TCanvas absolute ADest;
{$endif}
txt: String;
begin
ADest.Pen.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
ADest.Pen.Width := 1;
@ -4948,12 +4995,14 @@ begin
Points[0] := Point(CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
Points[1] := Point(Points[0].X + 7, Points[0].Y - 3);
Points[2] := Point(Points[0].X + 7, Points[0].Y + 3);
ADest.Polygon(Points);
CalcEntityCanvasMinMaxXY(ARenderInfo, Points[0].X, Points[1].Y);
if ADoDraw then ADest.Polygon(Points);
// Right arrow
Points[0] := Point(CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y));
Points[1] := Point(Points[0].X - 7, Points[0].Y - 3);
Points[2] := Point(Points[0].X - 7, Points[0].Y + 3);
ADest.Polygon(Points);
CalcEntityCanvasMinMaxXY(ARenderInfo, Points[0].X, Points[2].Y);
if ADoDraw then ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
// Dimension text
Points[0].X := CoordToCanvasX((DimensionLeft.X+DimensionRight.X)/2);
@ -4962,7 +5011,12 @@ begin
ADest.Font.Size := 10;
ADest.Font.Orientation := 0;
ADest.Font.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
ADest.TextOut(Points[0].X, Points[0].Y-Round(ADest.Font.Size*1.5), Format('%.1f', [LowerDim.X]));
txt := Format('%.1f', [LowerDim.X]);
if ADoDraw then
ADest.TextOut(Points[0].X, Points[0].Y-Round(ADest.Font.Size*1.5), txt);
CalcEntityCanvasMinMaxXY_With2Points(ARenderInfo,
Points[0].X, Points[0].Y - round(ADest.Font.Size*1.5),
Points[0].X + ADest.TextWidth(txt), Points[0].Y);
end
else
begin
@ -4983,12 +5037,14 @@ begin
Points[0] := Point(CoordToCanvasX(UpperDim.X), CoordToCanvasY(UpperDim.Y));
Points[1] := Point(Points[0].X + Round(AMulX), Points[0].Y - Round(AMulY*3));
Points[2] := Point(Points[0].X - Round(AMulX), Points[0].Y - Round(AMulY*3));
ADest.Polygon(Points);
if ADoDraw then ADest.Polygon(Points);
CalcEntityCanvasMinMaxXY(ARenderInfo, Points[1].X, Points[0].Y);
// Lower arrow
Points[0] := Point(CoordToCanvasX(LowerDim.X), CoordToCanvasY(LowerDim.Y));
Points[1] := Point(Points[0].X + Round(AMulX), Points[0].Y + Round(AMulY*3));
Points[2] := Point(Points[0].X - Round(AMulX), Points[0].Y + Round(AMulY*3));
ADest.Polygon(Points);
if ADoDraw then ADest.Polygon(Points);
CalcEntityCanvasMinMaxXY(ARenderInfo, Points[2].X, Points[0].Y);
ADest.Brush.Style := bsClear;
// Dimension text
Points[0].X := CoordToCanvasX(DimensionLeft.X);
@ -4998,8 +5054,14 @@ begin
ADest.Font.Size := 10;
ADest.Font.Orientation := 900;
ADest.Font.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
ADest.TextOut(Points[0].X-Round(ADest.Font.Size*1.5), Points[0].Y, Format('%.1f', [LowerDim.Y]));
txt := Format('%.1f', [LowerDim.Y]);
if ADoDraw then
ADest.TextOut(Points[0].X-Round(ADest.Font.Size*1.5), Points[0].Y, txt);
ADest.Font.Orientation := 0;
CalcEntityCanvasMinMaxXY_With2Points(ARenderInfo,
Points[0].X - Round(ADest.Font.Size*1.5), Points[0].Y,
Points[0].X, Points[0].Y + ADest.TextWidth(txt)
);
end;
SetLength(Points, 0);
@ -5074,51 +5136,54 @@ begin
Points[1] := Rotate2DPoint(Points[1], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle);
Points[2] := Rotate2DPoint(Points[2], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle);
if not IsDiameter then
if ADoDraw then
begin
// Basic line
ADest.MoveTo(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y));
ADest.LineTo(CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
if not IsDiameter then
begin
// Basic line
ADest.MoveTo(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y));
ADest.LineTo(CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
// Draw the arrow
ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
// Draw the arrow
ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
// Dimension text
Points[0].X := CoordToCanvasX(Center.X);
Points[0].Y := CoordToCanvasY(Center.Y);
ADest.Font.Size := 10;
ADest.Font.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [lRadius]));
end
else
begin
// Basic line
ADest.MoveTo(CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
ADest.LineTo(CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y));
// Dimension text
Points[0].X := CoordToCanvasX(Center.X);
Points[0].Y := CoordToCanvasY(Center.Y);
ADest.Font.Size := 10;
ADest.Font.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [lRadius]));
end
else
begin
// Basic line
ADest.MoveTo(CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
ADest.LineTo(CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y));
// Draw the first arrow
ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
// Draw the first arrow
ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
// And the second
Points[0] := Point(CoordToCanvasX(Center.X + lRadius), CoordToCanvasY(Center.Y));
Points[1] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y - lRadius*0.1));
Points[2] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y + lRadius*0.1));
// Now rotate it to the actual position
Points[0] := Rotate2DPoint(Points[0], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
Points[1] := Rotate2DPoint(Points[1], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
Points[2] := Rotate2DPoint(Points[2], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
//
ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
// And the second
Points[0] := Point(CoordToCanvasX(Center.X + lRadius), CoordToCanvasY(Center.Y));
Points[1] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y - lRadius*0.1));
Points[2] := Point(CoordToCanvasX(Center.X + lRadius*0.8), CoordToCanvasY(Center.Y + lRadius*0.1));
// Now rotate it to the actual position
Points[0] := Rotate2DPoint(Points[0], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
Points[1] := Rotate2DPoint(Points[1], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
Points[2] := Rotate2DPoint(Points[2], Point(CoordToCanvasX(Center.X), CoordToCanvasY(Center.Y)), lAngle + Pi);
//
ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
// Dimension text
Points[0].X := CoordToCanvasX(Center.X);
Points[0].Y := CoordToCanvasY(Center.Y);
ADest.Font.Size := 10;
ADest.Font.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [lRadius * 2]));
// Dimension text
Points[0].X := CoordToCanvasX(Center.X);
Points[0].Y := CoordToCanvasY(Center.Y);
ADest.Font.Size := 10;
ADest.Font.FPColor := AdjustColorToBackground(colBlack, ARenderInfo);
ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [lRadius * 2]));
end;
end;
SetLength(Points, 0);
@ -5163,6 +5228,7 @@ var
{$ifdef USE_LCL_CANVAS}
ALCLDest: TCanvas absolute ADest;
{$endif}
txt: String;
begin
ADest.Pen.FPColor := colYellow;//AdjustColorToBackground(colBlack, ARenderInfo);
ADest.Pen.Width := 1;
@ -5173,11 +5239,12 @@ begin
//ADest.Line(CoordToCanvasX(BaseRight.X), CoordToCanvasY(BaseRight.Y), CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y));
// Now the arc
ALCLDest.Arc(
CoordToCanvasX(BaseLeft.X - ArcRadius), CoordToCanvasY(BaseLeft.Y - ArcRadius),
CoordToCanvasX(BaseLeft.X + ArcRadius), CoordToCanvasY(BaseLeft.Y + ArcRadius),
CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y),
CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
if ADoDraw then
ALCLDest.Arc(
CoordToCanvasX(BaseLeft.X - ArcRadius), CoordToCanvasY(BaseLeft.Y - ArcRadius),
CoordToCanvasX(BaseLeft.X + ArcRadius), CoordToCanvasY(BaseLeft.Y + ArcRadius),
CoordToCanvasX(DimensionRight.X), CoordToCanvasY(DimensionRight.Y),
CoordToCanvasX(DimensionLeft.X), CoordToCanvasY(DimensionLeft.Y));
// Now the arrows
SetLength(Points, 3);
@ -5193,7 +5260,8 @@ begin
Points[1] := Point(CoordToCanvasX(lTriangleCorner.X), CoordToCanvasY(lTriangleCorner.Y));
lTriangleCorner := Rotate3DPointInXY(lTriangleCenter, ArcLeft, - Pi * 10 / 180);
Points[2] := Point(CoordToCanvasX(lTriangleCorner.X), CoordToCanvasY(lTriangleCorner.Y));
ADest.Polygon(Points);
if ADoDraw then
ADest.Polygon(Points);
// Right Arrow
Points[0] := Point(CoordToCanvasX(ArcRight.X), CoordToCanvasY(ArcRight.Y));
@ -5204,7 +5272,8 @@ begin
lTriangleCorner := Rotate3DPointInXY(lTriangleCenter, ArcRight, - Pi * 10 / 180);
Points[2] := Point(CoordToCanvasX(lTriangleCorner.X), CoordToCanvasY(lTriangleCorner.Y));
ADest.Polygon(Points);
ADest.Brush.Style := bsClear;
if ADoDraw then
ADest.Brush.Style := bsClear;
// Dimension text
Points[0].X := CoordToCanvasX(TextPos.X);
@ -5212,7 +5281,9 @@ begin
ADest.Font.Size := 10;
ADest.Font.Orientation := 0;
ADest.Font.FPColor := colYellow;//AdjustColorToBackground(colBlack, ARenderInfo);
ADest.TextOut(Points[0].X, Points[0].Y-Round(ADest.Font.Size*1.5), Format('%.1fº', [ArcValue]));
txt := Format('%.1fº', [ArcValue]);
if ADoDraw then
ADest.TextOut(Points[0].X, Points[0].Y-Round(ADest.Font.Size*1.5), txt);
end;
procedure TvArcDimension.CalculateExtraArcInfo;
@ -5412,7 +5483,8 @@ begin
if lFinalW < 0 then lFinalW := lFinalW * -1;
lFinalH := Round(Height * AMulY);
if lFinalH < 0 then lFinalH := lFinalH * -1;
TCanvas(ADest).StretchDraw(Bounds(lFinalX, lFinalY, lFinalW, lFinalH), lBitmap);
if ADoDraw then
TCanvas(ADest).StretchDraw(Bounds(lFinalX, lFinalY, lFinalW, lFinalH), lBitmap);
finally
lImageWriter.Free;
lMemoryStream.Free;
@ -5530,7 +5602,7 @@ begin
lPoints[1].Y := CoordToCanvasY(lPointE.Y);
lPoints[2].X := CoordToCanvasX(lPointF.X);
lPoints[2].Y := CoordToCanvasY(lPointF.Y);
ADest.Polygon(lPoints);
if ADoDraw then ADest.Polygon(lPoints);
end;
{ TvFormulaElement }
@ -5703,95 +5775,96 @@ begin
LeftC := CoordToCanvasX(Left);
TopC := CoordToCanvasY(Top);
case Kind of
fekVariable: ADest.TextOut(LeftC, TopC, Text);
fekEqual: ADest.TextOut(LeftC, TopC, '=');
fekSubtraction: ADest.TextOut(LeftC, TopC, '-');
fekMultiplication:
begin
// Don't draw anything, leave an empty space, it looks better
//ADest.TextOut(LeftC, TopC, 'x'); // × -> Unicode times symbol
end;
fekSum: ADest.TextOut(LeftC, TopC, '+');
fekPlusMinus:ADest.TextOut(LeftC, TopC, '±');
fekLessThan: ADest.TextOut(LeftC, TopC, '<');
fekLessOrEqualThan: ADest.TextOut(LeftC, TopC, '≤');
fekGreaterThan: ADest.TextOut(LeftC, TopC, '>');
fekGreaterOrEqualThan: ADest.TextOut(LeftC, TopC, '≥');
fekHorizontalLine: ADest.Line(LeftC, TopC, CoordToCanvasX(Left+Width), TopC);
// Complex ones
fekFraction:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
if ADoDraw then
case Kind of
fekVariable: ADest.TextOut(LeftC, TopC, Text);
fekEqual: ADest.TextOut(LeftC, TopC, '=');
fekSubtraction: ADest.TextOut(LeftC, TopC, '-');
fekMultiplication:
begin
// Don't draw anything, leave an empty space, it looks better
//ADest.TextOut(LeftC, TopC, 'x'); // × -> Unicode times symbol
end;
fekSum: ADest.TextOut(LeftC, TopC, '+');
fekPlusMinus:ADest.TextOut(LeftC, TopC, '±');
fekLessThan: ADest.TextOut(LeftC, TopC, '<');
fekLessOrEqualThan: ADest.TextOut(LeftC, TopC, '≤');
fekGreaterThan: ADest.TextOut(LeftC, TopC, '>');
fekGreaterOrEqualThan: ADest.TextOut(LeftC, TopC, '≥');
fekHorizontalLine: ADest.Line(LeftC, TopC, CoordToCanvasX(Left+Width), TopC);
// Complex ones
fekFraction:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// Division line
lPt[0].X := CoordToCanvasX(Formula.Left);
lPt[1].X := CoordToCanvasX(Formula.Left + Formula.Width);
lPt[0].Y := CoordToCanvasY(Formula.Top - Formula.Height);
lPt[1].Y := CoordToCanvasY(Formula.Top - Formula.Height);
ADest.Line(lPt[0].X, lPt[0].Y, lPt[1].X, lPt[1].Y);
end;
fekRoot:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// Division line
lPt[0].X := CoordToCanvasX(Formula.Left);
lPt[1].X := CoordToCanvasX(Formula.Left + Formula.Width);
lPt[0].Y := CoordToCanvasY(Formula.Top - Formula.Height);
lPt[1].Y := CoordToCanvasY(Formula.Top - Formula.Height);
ADest.Line(lPt[0].X, lPt[0].Y, lPt[1].X, lPt[1].Y);
end;
fekRoot:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// Root drawing
lPt[0].X := CoordToCanvasX(Left);
lPt[0].Y := CoordToCanvasY(Top - Formula.Height * 0.7 + 5);
// diagonal down
lPt[1].X := CoordToCanvasX(Left + 5);
lPt[1].Y := CoordToCanvasY(Top - Formula.Height * 0.7);
// up
lPt[2].X := CoordToCanvasX(Left + 5);
lPt[2].Y := CoordToCanvasY(Top);
// straight right
lPt[3].X := CoordToCanvasX(Left + Formula.Width);
lPt[3].Y := CoordToCanvasY(Top);
//
ADest.Polyline(lPt);
end;
fekPower:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// The superscripted power
lOldFontSize := ADest.Font.Size;
if lOldFontSize = 0 then ADest.Font.Size := 5
else ADest.Font.Size := lOldFontSize div 2;
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
ADest.Font.Size := lOldFontSize;
end;
fekSubscript:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// The subscripted item
lOldFontSize := ADest.Font.Size;
if lOldFontSize = 0 then ADest.Font.Size := 5
else ADest.Font.Size := lOldFontSize div 2;
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
ADest.Font.Size := lOldFontSize;
end;
fekSummation:
begin
// Draw the summation symbol
lOldFontSize := ADest.Font.Size;
ADest.Font.Size := 15;
lStr := #$E2#$88#$91; // Unicode Character 'N-ARY SUMMATION' (U+2211)
ADest.TextOut(LeftC, TopC, lStr);
ADest.Font.Size := lOldFontSize;
// Root drawing
lPt[0].X := CoordToCanvasX(Left);
lPt[0].Y := CoordToCanvasY(Top - Formula.Height * 0.7 + 5);
// diagonal down
lPt[1].X := CoordToCanvasX(Left + 5);
lPt[1].Y := CoordToCanvasY(Top - Formula.Height * 0.7);
// up
lPt[2].X := CoordToCanvasX(Left + 5);
lPt[2].Y := CoordToCanvasY(Top);
// straight right
lPt[3].X := CoordToCanvasX(Left + Formula.Width);
lPt[3].Y := CoordToCanvasY(Top);
//
ADest.Polyline(lPt);
end;
fekPower:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// The superscripted power
lOldFontSize := ADest.Font.Size;
if lOldFontSize = 0 then ADest.Font.Size := 5
else ADest.Font.Size := lOldFontSize div 2;
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
ADest.Font.Size := lOldFontSize;
end;
fekSubscript:
begin
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// The subscripted item
lOldFontSize := ADest.Font.Size;
if lOldFontSize = 0 then ADest.Font.Size := 5
else ADest.Font.Size := lOldFontSize div 2;
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
ADest.Font.Size := lOldFontSize;
end;
fekSummation:
begin
// Draw the summation symbol
lOldFontSize := ADest.Font.Size;
ADest.Font.Size := 15;
lStr := #$E2#$88#$91; // Unicode Character 'N-ARY SUMMATION' (U+2211)
ADest.TextOut(LeftC, TopC, lStr);
ADest.Font.Size := lOldFontSize;
// Draw the bottom/main formula
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// Draw the bottom/main formula
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// Draw the top formula
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
// Draw the top formula
AdjacentFormula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
end;
fekFormula:
begin
// Draw the formula
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
end;
end;
fekFormula:
begin
// Draw the formula
Formula.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
end;
end;
end;
procedure TvFormulaElement.GenerateDebugTree(ADestRoutine: TvDebugAddItemProc;
@ -6271,7 +6344,11 @@ begin
end;
destructor TvEntityWithSubEntities.Destroy;
var
i: Integer;
begin
for i:= FElements.Count-1 downto 0 do
TvEntity(FElements[i]).Free;
FElements.Free;
inherited Destroy;
end;
@ -6359,8 +6436,12 @@ procedure TvEntityWithSubEntities.Render(ADest: TFPCustomCanvas; var ARenderInfo
ADestX: Integer; ADestY: Integer; AMulX: Double; AMulY: Double; ADoDraw: Boolean);
var
lEntity: TvEntity;
rinfo: TvRenderInfo;
isFirst: Boolean;
begin
rinfo := ARenderInfo;
inherited Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
isFirst := true;
lEntity := GetFirstEntity();
while lEntity <> nil do
begin
@ -6372,8 +6453,22 @@ begin
// Render
lEntity.Render(ADest, ARenderInfo, ADestX, ADestY, AMulX, AMuly, ADoDraw);
if isFirst then
begin
rinfo := ARenderInfo;
isFirst := false;
end else
CalcEntityCanvasMinMaxXY_With2Points(rinfo,
ARenderInfo.EntityCanvasMinXY.X,
ARenderInfo.EntityCanvasMinXY.Y,
ARenderInfo.EntityCanvasMaxXY.X,
ARenderInfo.EntityCanvasMaxXY.Y
);
lEntity := GetNextEntity();
end;
ARenderInfo := rinfo;
end;
function TvEntityWithSubEntities.GenerateDebugTree(
@ -6694,7 +6789,7 @@ begin
if Style <> nil then
Style.ApplyIntoEntity(lText);
lText.Render(ADest, lEntityRenderInfo, CurX, ADestY + lHeight_px, AMulX, AMulY, ADoDraw);
lText.Render(ADest, lEntityRenderInfo, CurX, ADestY, AMulX, AMulY, ADoDraw);
lText.CalculateBoundingBox(ADest, lLeft, lTop, lRight, lBottom);
lCurWidth := lCurWidth + Abs(lRight - lLeft);
lFirstText := False;
@ -7043,6 +7138,7 @@ constructor TvPage.Create(AOwner: TvVectorialDocument);
begin
inherited Create;
FOwner := AOwner;
AdjustPenColorToBackground := true;
end;
destructor TvPage.Destroy;
@ -7770,12 +7866,17 @@ end;
use this function like this:
ASource.Render(ADest, 0, ASource.Height, 1.0, -1.0);
Set ADoDraw to falses in order to just get the bounding box of all entities
on the page in RenderInfo.EnitityCanvasMinXY/EntityCanvasMaxXY.
}
procedure TvVectorialPage.Render(ADest: TFPCustomCanvas;
ADestX: Integer; ADestY: Integer; AMulX: Double; AMulY: Double);
ADestX: Integer; ADestY: Integer; AMulX: Double; AMulY: Double;
ADoDraw: Boolean = true);
var
i: Integer;
CurEntity: TvEntity;
rinfo: TvRenderInfo;
begin
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
WriteLn(':>DrawFPVectorialToCanvas');
@ -7790,9 +7891,23 @@ begin
CurEntity := GetEntity(i);
RenderInfo.BackgroundColor := BackgroundColor;
CurEntity.Render(ADest, RenderInfo, ADestX, ADestY, AMulX, AMulY);
RenderInfo.AdjustPenColorToBackground := AdjustPenColorToBackground;
CurEntity.Render(ADest, RenderInfo, ADestX, ADestY, AMulX, AMulY, ADoDraw);
if i = 0 then
rInfo := RenderInfo
else
begin
rInfo.EntityCanvasMinXY.X := Min(rInfo.EntityCanvasMinXY.X, RenderInfo.EntityCanvasMinXY.X);
rInfo.EntityCanvasMinXY.Y := Min(rInfo.EntityCanvasMinXY.Y, RenderInfo.EntityCanvasMinXY.Y);
rInfo.EntityCanvasMaxXY.X := Max(rInfo.EntityCanvasMaxXY.X, RenderInfo.EntityCanvasMaxXY.X);
rInfo.EntityCanvasMaxXY.Y := Max(rInfo.EntityCanvasMaxXY.Y, RenderInfo.EntityCanvasMaxXY.Y);
end;
end;
RenderInfo := rInfo;
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
WriteLn(':<DrawFPVectorialToCanvas');
{$endif}
@ -7983,7 +8098,7 @@ begin
end;
procedure TvTextPageSequence.Render(ADest: TFPCustomCanvas; ADestX: Integer;
ADestY: Integer; AMulX: Double; AMulY: Double);
ADestY: Integer; AMulX: Double; AMulY: Double; ADoDraw: Boolean = true);
function CoordToCanvasX(ACoord: Double): Integer;
begin
@ -8019,7 +8134,7 @@ begin
CurEntity.Y := 0;
lHeight_px := CurEntity.GetEntityFeatures(ADest).DrawsUpwardHeightAdjustment;
RenderInfo.BackgroundColor := BackgroundColor;
CurEntity.Render(ADest, RenderInfo, ADestX, CurY_px + lHeight_px, AMulX, AMulY);
CurEntity.Render(ADest, RenderInfo, ADestX, CurY_px + lHeight_px, AMulX, AMulY, ADoDraw);
// Store the old position in X/Y but don't use it, we use this to debug out the position
CurEntity.X := ADestX;
CurEntity.Y := CurY_px;
@ -8233,7 +8348,7 @@ procedure TvVectorialDocument.ReadFromFile(AFileName: string);
var
lFormat: TvVectorialFormat;
begin
lFormat := GetFormatFromExtension(ExtractFileExt(AFileName));
lFormat := GetFormatFromExtension(AFileName);
ReadFromFile(AFileName, lFormat);
end;

View File

@ -130,9 +130,11 @@ type
function ReadTextFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
function ReadUseFromNode(ANode: TDOMNode; AData: TvVectorialPage; ADoc: TvVectorialDocument): TvEntity;
//
procedure StringToPenPattern(const AStr: String; var APen: TvPen);
function StringWithUnitToFloat(AStr: string; ACoordKind: TSVGCoordinateKind = sckUnknown;
ADefaultUnit: TSVGUnit = suPX; ATargetUnit: TSVGUnit = suPX): Double;
function StringFloatZeroToOneToWord(AStr: string): Word;
procedure ConvertSVGCoordinatesToFPVCoordinates(
const AData: TvVectorialPage;
const ASrcX, ASrcY: Double; var ADestX, ADestY: Double;
@ -147,6 +149,7 @@ type
ADoViewBoxAdjust: Boolean = True);
procedure AutoDetectDocSize(var ALeft, ATop, ARight, ABottom: Double; ABaseNode: TDOMNode);
function SVGColorValueStrToWord(AStr: string): Word;
public
{ General reading methods }
constructor Create; override;
@ -205,7 +208,11 @@ begin
end;
destructor TSVGPathTokenizer.Destroy;
var
i: Integer;
begin
for i:=Tokens.Count-1 downto 0 do
Tokens[i].Free;
Tokens.Free;
inherited Destroy;
@ -928,7 +935,7 @@ begin
end
else if AKey = 'stroke-opacity' then
begin
ADestEntity.Pen.Color.Alpha := Round(StrToFloat(AValue)*$FFFF);
ADestEntity.Pen.Color.Alpha := Round(StrToFloat(AValue, FPointSeparator)*$FFFF);
end
else if AKey = 'stroke-linecap' then
begin
@ -937,7 +944,9 @@ begin
'round':
'square': ADestEntity.Pen;
end;}
end;
end
else if AKey = 'stroke-dasharray' then
StringToPenPattern(AValue, ADestEntity.Pen);
end;
function TvSVGVectorialReader.ReadSVGBrushStyleWithKeyAndValue(AKey,
@ -1458,6 +1467,7 @@ begin
lEntityName := LowerCase(ANode.NodeName);
case lEntityName of
'circle': Result := ReadCircleFromNode(ANode, AData, ADoc);
'defs': ReadDefsFromNode(ANode, AData, ADoc);
'ellipse': Result := ReadEllipseFromNode(ANode, AData, ADoc);
'frame': Result := ReadFrameFromNode(ANode, AData, ADoc);
'g': ReadLayerFromNode(ANode, AData, ADoc);
@ -2841,6 +2851,47 @@ begin
Result := lInsert;
end;
procedure TvSVGVectorialReader.StringToPenPattern(const AStr: String;
var APen: TvPen);
var
float_patt: TDoubleArray;
patt: array of LongWord;
i: Integer;
begin
float_patt := ReadSpaceSeparatedFloats(AStr, ',');
if Length(float_patt) < 2 then
exit;
SetLength(patt, Length(float_patt));
for i:=0 to High(patt) do
begin
if float_patt[i] < 0 then
raise Exception.CreateFmt('Incorrect value in stroke-dasharray "%s"', [AStr]);
patt[i] := round(float_patt[i]);
end;
case Length(patt) of
2: if patt[1] = 5 then
case patt[0] of
3: begin APen.Style := psDot; exit; end; // stroke-dasharray: 3, 5
9: begin APen.Style := psDash; exit; end; // stroke-dasharray: 9, 5
end;
4: if (patt[0] = 9) and (patt[1] = 5) and (patt[2] = 3) and (patt[3] = 5) then
begin // stroke-dasharray: 9, 5, 3, 5
APen.Style := psDashDot;
exit;
end;
6: if (patt[0] = 9) and (patt[1] = 5) and (patt[2] = 3) and (patt[3] = 5) and
(patt[4] = 3) and (patt[5] = 5)
then begin // stroke-dasharray: 9, 5, 3, 5, 3, 5
APen.Style := psDashDotDot;
exit;
end;
end;
APen.Style := psPattern;
APen.Pattern := patt;
end;
function TvSVGVectorialReader.StringWithUnitToFloat(AStr: string;
ACoordKind: TSVGCoordinateKind = sckUnknown; ADefaultUnit: TSVGUnit = suPX;
ATargetUnit: TSVGUnit = suPX): Double;