summaryrefslogtreecommitdiff
path: root/packages/fpvectorial/src/fpvtocanvas.pas
diff options
context:
space:
mode:
Diffstat (limited to 'packages/fpvectorial/src/fpvtocanvas.pas')
-rw-r--r--packages/fpvectorial/src/fpvtocanvas.pas209
1 files changed, 185 insertions, 24 deletions
diff --git a/packages/fpvectorial/src/fpvtocanvas.pas b/packages/fpvectorial/src/fpvtocanvas.pas
index 6893c3b115..456a656382 100644
--- a/packages/fpvectorial/src/fpvtocanvas.pas
+++ b/packages/fpvectorial/src/fpvtocanvas.pas
@@ -11,7 +11,7 @@ uses
{$ifdef USE_LCL_CANVAS}
Graphics, LCLIntf,
{$else}
- fpcanvas,
+ fpcanvas, fpimage,
{$endif}
fpvectorial;
@@ -25,6 +25,10 @@ procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument;
implementation
+{$ifndef Windows}
+{$define FPVECTORIALDEBUG}
+{$endif}
+
function Rotate2DPoint(P,Fix :TPoint; alpha:double): TPoint;
var
sinus, cosinus : Extended;
@@ -97,6 +101,17 @@ procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument;
ADest: TFPCustomCanvas;
{$endif}
ADestX: Integer = 0; ADestY: Integer = 0; AMulX: Double = 1.0; AMulY: Double = 1.0);
+
+ function CoordToCanvasX(ACoord: Double): Integer;
+ begin
+ Result := Round(ADestX + AmulX * ACoord);
+ end;
+
+ function CoordToCanvasY(ACoord: Double): Integer;
+ begin
+ Result := Round(ADestY + AmulY * ACoord);
+ end;
+
var
i, j, k: Integer;
PosX, PosY: Integer; // Not modified by ADestX, etc
@@ -113,7 +128,15 @@ var
CurEntity: TvEntity;
CurCircle: TvCircle;
CurEllipse: TvEllipse;
+ //
CurArc: TvCircularArc;
+ FinalStartAngle, FinalEndAngle, tmpAngle: double;
+ BoundsLeft, BoundsTop, BoundsRight, BoundsBottom,
+ IntStartAngle, IntAngleLength, IntTmp: Integer;
+ //
+ CurDim: TvAlignedDimension;
+ Points: array of TPoint;
+ UpperDim, LowerDim: T3DPoint;
begin
{$ifdef FPVECTORIALDEBUG}
WriteLn(':>DrawFPVectorialToCanvas');
@@ -121,6 +144,7 @@ begin
PosX := 0;
PosY := 0;
+ ADest.Brush.Style := bsClear;
ADest.MoveTo(ADestX, ADestY);
@@ -138,17 +162,11 @@ begin
case CurSegment.SegmentType of
stMoveTo:
begin
- ADest.MoveTo(
- Round(ADestX + AMulX * Cur2DSegment.X),
- Round(ADestY + AMulY * Cur2DSegment.Y)
- );
+ ADest.MoveTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
end;
st2DLine, st3DLine:
begin
- ADest.LineTo(
- Round(ADestX + AMulX * Cur2DSegment.X),
- Round(ADestY + AMulY * Cur2DSegment.Y)
- );
+ ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
end;
{ To draw a bezier we need to divide the interval in parts and make
lines between this parts }
@@ -164,9 +182,7 @@ begin
t := k / CurveLength;
CurX := Round(sqr(1 - t) * (1 - t) * PosX + 3 * t * sqr(1 - t) * Cur2DBSegment.X2 + 3 * t * t * (1 - t) * Cur2DBSegment.X3 + t * t * t * Cur2DBSegment.X);
CurY := Round(sqr(1 - t) * (1 - t) * PosY + 3 * t * sqr(1 - t) * Cur2DBSegment.Y2 + 3 * t * t * (1 - t) * Cur2DBSegment.Y3 + t * t * t * Cur2DBSegment.Y);
- ADest.LineTo(
- Round(ADestX + AMulX * CurX),
- Round(ADestY + AMulY * CurY));
+ ADest.LineTo(CoordToCanvasX(CurX), CoordToCanvasY(CurY));
end;
PosX := Round(Cur2DBSegment.X);
PosY := Round(Cur2DBSegment.Y);
@@ -183,10 +199,10 @@ begin
begin
CurCircle := CurEntity as TvCircle;
ADest.Ellipse(
- Round(ADestX + AmulX * (CurCircle.CenterX - CurCircle.Radius)),
- Round(ADestY + AMulY * (CurCircle.CenterY - CurCircle.Radius)),
- Round(ADestX + AmulX * (CurCircle.CenterX + CurCircle.Radius)),
- Round(ADestY + AMulY * (CurCircle.CenterY + CurCircle.Radius))
+ CoordToCanvasX(CurCircle.CenterX - CurCircle.Radius),
+ CoordToCanvasY(CurCircle.CenterY - CurCircle.Radius),
+ CoordToCanvasX(CurCircle.CenterX + CurCircle.Radius),
+ CoordToCanvasY(CurCircle.CenterY + CurCircle.Radius)
);
end
else if CurEntity is TvEllipse then
@@ -198,16 +214,155 @@ begin
begin
CurArc := CurEntity as TvCircularArc;
{$ifdef USE_LCL_CANVAS}
+ // ToDo: Consider a X axis inversion
+ // If the Y axis is inverted, then we need to mirror our angles as well
+ BoundsLeft := CoordToCanvasX(CurArc.CenterX - CurArc.Radius);
+ BoundsTop := CoordToCanvasY(CurArc.CenterY - CurArc.Radius);
+ BoundsRight := CoordToCanvasX(CurArc.CenterX + CurArc.Radius);
+ BoundsBottom := CoordToCanvasY(CurArc.CenterY + CurArc.Radius);
+ {if AMulY > 0 then
+ begin}
+ FinalStartAngle := CurArc.StartAngle;
+ FinalEndAngle := CurArc.EndAngle;
+ {end
+ else // AMulY is negative
+ begin
+ // Inverting the angles generates the correct result for Y axis inversion
+ if CurArc.EndAngle = 0 then FinalStartAngle := 0
+ else FinalStartAngle := 360 - 1* CurArc.EndAngle;
+ if CurArc.StartAngle = 0 then FinalEndAngle := 0
+ else FinalEndAngle := 360 - 1* CurArc.StartAngle;
+ end;}
+ IntStartAngle := Round(16*FinalStartAngle);
+ IntAngleLength := Round(16*(FinalEndAngle - FinalStartAngle));
+ // On Gtk2 and Carbon, the Left really needs to be to the Left of the Right position
+ // The same for the Top and Bottom
+ // On Windows it works fine either way
+ // On Gtk2 if the positions are inverted then the arcs are screwed up
+ // In Carbon if the positions are inverted, then the arc is inverted
+ if BoundsLeft > BoundsRight then
+ begin
+ IntTmp := BoundsLeft;
+ BoundsLeft := BoundsRight;
+ BoundsRight := IntTmp;
+ end;
+ if BoundsTop > BoundsBottom then
+ begin
+ IntTmp := BoundsTop;
+ BoundsTop := BoundsBottom;
+ BoundsBottom := IntTmp;
+ end;
// Arc(ALeft, ATop, ARight, ABottom, Angle16Deg, Angle16DegLength: Integer);
+ {$ifdef FPVECTORIALDEBUG}
+ WriteLn(Format('Drawing Arc Center=%f,%f Radius=%f StartAngle=%f AngleLength=%f',
+ [CurArc.CenterX, CurArc.CenterY, CurArc.Radius, IntStartAngle/16, IntAngleLength/16]));
+ {$endif}
ADest.Arc(
- Round(ADestX + AmulX * (CurArc.CenterX - CurArc.Radius)),
- Round(ADestY + AmulY * (CurArc.CenterY - CurArc.Radius)),
- Round(ADestX + AmulX * (CurArc.CenterX + CurArc.Radius)),
- Round(ADestY + AmulY * (CurArc.CenterY + CurArc.Radius)),
- Round(16*CurArc.StartAngle),
- Round(16*CurArc.EndAngle - CurArc.StartAngle)
+ BoundsLeft, BoundsTop, BoundsRight, BoundsBottom,
+ IntStartAngle, IntAngleLength
);
+ // Debug info
+// {$define FPVECTORIALDEBUG}
+// {$ifdef FPVECTORIALDEBUG}
+// WriteLn(Format('Drawing Arc x1y1=%d,%d x2y2=%d,%d start=%d end=%d',
+// [BoundsLeft, BoundsTop, BoundsRight, BoundsBottom, IntStartAngle, IntAngleLength]));
+// {$endif}
+{ ADest.TextOut(CoordToCanvasX(CurArc.CenterX), CoordToCanvasY(CurArc.CenterY),
+ Format('R=%d S=%d L=%d', [Round(CurArc.Radius*AMulX), Round(FinalStartAngle),
+ Abs(Round((FinalEndAngle - FinalStartAngle)))]));
+ ADest.Pen.Color := TColor($DDDDDD);
+ ADest.Rectangle(
+ BoundsLeft, BoundsTop, BoundsRight, BoundsBottom);
+ ADest.Pen.Color := clBlack;}
{$endif}
+ end
+ else if CurEntity is TvAlignedDimension then
+ begin
+ CurDim := CurEntity as TvAlignedDimension;
+ //
+ // Draws this shape:
+ // vertical horizontal
+ // ___
+ // | | or ---| X cm
+ // | --|
+ // Which marks the dimension
+ ADest.MoveTo(CoordToCanvasX(CurDim.BaseRight.X), CoordToCanvasY(CurDim.BaseRight.Y));
+ ADest.LineTo(CoordToCanvasX(CurDim.DimensionRight.X), CoordToCanvasY(CurDim.DimensionRight.Y));
+ ADest.LineTo(CoordToCanvasX(CurDim.DimensionLeft.X), CoordToCanvasY(CurDim.DimensionLeft.Y));
+ ADest.LineTo(CoordToCanvasX(CurDim.BaseLeft.X), CoordToCanvasY(CurDim.BaseLeft.Y));
+ // Now the arrows
+ // horizontal
+ SetLength(Points, 3);
+ if CurDim.DimensionRight.Y = CurDim.DimensionLeft.Y then
+ begin
+ {$ifdef USE_LCL_CANVAS}
+ ADest.Brush.Color := clBlack;
+ {$else}
+ ADest.Brush.FPColor := colBlack;
+ {$endif}
+ ADest.Brush.Style := bsSolid;
+ // Left arrow
+ Points[0] := Point(CoordToCanvasX(CurDim.DimensionLeft.X), CoordToCanvasY(CurDim.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);
+ // Right arrow
+ Points[0] := Point(CoordToCanvasX(CurDim.DimensionRight.X), CoordToCanvasY(CurDim.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);
+ ADest.Brush.Style := bsClear;
+ // Dimension text
+ Points[0].X := CoordToCanvasX((CurDim.DimensionLeft.X+CurDim.DimensionRight.X)/2);
+ Points[0].Y := CoordToCanvasY(CurDim.DimensionLeft.Y);
+ LowerDim.X := CurDim.DimensionRight.X-CurDim.DimensionLeft.X;
+ ADest.Font.Size := 10;
+ ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [LowerDim.X]));
+ end
+ else
+ begin
+ {$ifdef USE_LCL_CANVAS}
+ ADest.Brush.Color := clBlack;
+ {$else}
+ ADest.Brush.FPColor := colBlack;
+ {$endif}
+ ADest.Brush.Style := bsSolid;
+ // There is no upper/lower preference for DimensionLeft/Right, so we need to check
+ if CurDim.DimensionLeft.Y > CurDim.DimensionRight.Y then
+ begin
+ UpperDim := CurDim.DimensionLeft;
+ LowerDim := CurDim.DimensionRight;
+ end
+ else
+ begin
+ UpperDim := CurDim.DimensionRight;
+ LowerDim := CurDim.DimensionLeft;
+ end;
+ // Upper arrow
+ 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);
+ // 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);
+ ADest.Brush.Style := bsClear;
+ // Dimension text
+ Points[0].X := CoordToCanvasX(CurDim.DimensionLeft.X);
+ Points[0].Y := CoordToCanvasY((CurDim.DimensionLeft.Y+CurDim.DimensionRight.Y)/2);
+ LowerDim.Y := CurDim.DimensionRight.Y-CurDim.DimensionLeft.Y;
+ if LowerDim.Y < 0 then LowerDim.Y := -1 * LowerDim.Y;
+ ADest.Font.Size := 10;
+ ADest.TextOut(Points[0].X, Points[0].Y, Format('%.1f', [LowerDim.Y]));
+ end;
+ SetLength(Points, 0);
+{ // Debug info
+ ADest.TextOut(CoordToCanvasX(CurDim.BaseRight.X), CoordToCanvasY(CurDim.BaseRight.Y), 'BR');
+ ADest.TextOut(CoordToCanvasX(CurDim.DimensionRight.X), CoordToCanvasY(CurDim.DimensionRight.Y), 'DR');
+ ADest.TextOut(CoordToCanvasX(CurDim.DimensionLeft.X), CoordToCanvasY(CurDim.DimensionLeft.Y), 'DL');
+ ADest.TextOut(CoordToCanvasX(CurDim.BaseLeft.X), CoordToCanvasY(CurDim.BaseLeft.Y), 'BL');}
end;
end;
@@ -215,10 +370,16 @@ begin
for i := 0 to ASource.GetTextCount - 1 do
begin
CurText := ASource.GetText(i);
- ADest.Font.Height := Round(AmulY * CurText.FontSize);
+ ADest.Font.Size := Round(AmulX * CurText.FontSize);
ADest.Pen.Style := psSolid;
+ {$ifdef USE_LCL_CANVAS}
ADest.Pen.Color := clBlack;
- ADest.TextOut(Round(CurText.X), Round(CurText.Y), CurText.Value);
+ {$else}
+ ADest.Pen.FPColor := colBlack;
+ {$endif}
+ ADest.Brush.Style := bsClear;
+ LowerDim.Y := CurText.Y + CurText.FontSize;
+ ADest.TextOut(CoordToCanvasX(CurText.X), CoordToCanvasY(LowerDim.Y), CurText.Value);
end;
{$ifdef FPVECTORIALDEBUG}