mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-19 23:49:36 +02:00
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:
parent
0ea790b8d3
commit
0f4ab685b0
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user