fpvectorial: Reworks the brush and pen design to be more efficient

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1589 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
sekelsenmat
2011-04-21 11:30:40 +00:00
parent bc0375d331
commit b4af90ab88
2 changed files with 62 additions and 21 deletions

View File

@ -45,6 +45,17 @@ type
Red, Green, Blue, Alpha: Byte; Red, Green, Blue, Alpha: Byte;
end; end;
TvPen = record
Color: TvColor;
Style: TFPPenStyle;
Width: Integer;
end;
TvBrush = record
Color: TvColor;
Style: TFPBrushStyle;
end;
const const
FPValphaTransparent = $00; FPValphaTransparent = $00;
FPValphaOpaque = $FF; FPValphaOpaque = $FF;
@ -59,7 +70,7 @@ type
P3DPoint = ^T3DPoint; P3DPoint = ^T3DPoint;
TSegmentType = ( TSegmentType = (
st2DLine, st2DBezier, st2DLine, st2DLineWithPen, st2DBezier,
st3DLine, st3DBezier, stMoveTo); st3DLine, st3DBezier, stMoveTo);
{@@ {@@
@ -75,10 +86,6 @@ type
// Fields for linking the list // Fields for linking the list
Previous: TPathSegment; Previous: TPathSegment;
Next: TPathSegment; Next: TPathSegment;
// Data fields
PenColor: TvColor;
PenStyle: TFPPenStyle;
PenWidth: Integer;
end; end;
{@@ {@@
@ -93,6 +100,11 @@ type
X, Y: Double; X, Y: Double;
end; end;
T2DSegmentWithPen = class(T2DSegment)
public
Pen: TvPen;
end;
{@@ {@@
In Bezier segments, we remain using the X and Y coordinates for the ending point. In Bezier segments, we remain using the X and Y coordinates for the ending point.
The starting point is where the previous segment ended, so that the intermediary The starting point is where the previous segment ended, so that the intermediary
@ -124,6 +136,9 @@ type
Points: TPathSegment; // Beginning of the double-linked list Points: TPathSegment; // Beginning of the double-linked list
PointsEnd: TPathSegment; // End of the double-linked list PointsEnd: TPathSegment; // End of the double-linked list
CurPoint: TPathSegment; // Used in PrepareForSequentialReading and Next CurPoint: TPathSegment; // Used in PrepareForSequentialReading and Next
Pen: TvPen;
Brush: TvBrush;
constructor Create();
procedure Assign(APath: TPath); procedure Assign(APath: TPath);
function Count(): TPathSegment; function Count(): TPathSegment;
procedure PrepareForSequentialReading; procedure PrepareForSequentialReading;
@ -149,13 +164,8 @@ type
} }
TvEntity = class TvEntity = class
public public
// Pen Pen: TvPen;
PenColor: TvColor; Brush: TvBrush;
PenStyle: TFPPenStyle;
PenWidth: Integer;
// Brush
BrushStyle: TFPBrushStyle;
BrushColor: TvColor;
end; end;
{@@ {@@
@ -253,6 +263,8 @@ type
procedure AddLineToPath(AX, AY, AZ: Double); overload; procedure AddLineToPath(AX, AY, AZ: Double); overload;
procedure AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double); overload; procedure AddBezierToPath(AX1, AY1, AX2, AY2, AX3, AY3: Double); overload;
procedure AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double); overload; procedure AddBezierToPath(AX1, AY1, AZ1, AX2, AY2, AZ2, AX3, AY3, AZ3: Double); overload;
procedure SetBrushToPath(ABrush: TvBrush);
procedure SetPenToPath(APen: TvPen);
procedure EndPath(); procedure EndPath();
procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload; procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload; procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload;
@ -550,20 +562,19 @@ begin
segment.SegmentType := st2DLine; segment.SegmentType := st2DLine;
segment.X := AX; segment.X := AX;
segment.Y := AY; segment.Y := AY;
segment.PenColor := clvBlack;
AppendSegmentToTmpPath(segment); AppendSegmentToTmpPath(segment);
end; end;
procedure TvVectorialDocument.AddLineToPath(AX, AY: Double; AColor: TvColor); procedure TvVectorialDocument.AddLineToPath(AX, AY: Double; AColor: TvColor);
var var
segment: T2DSegment; segment: T2DSegmentWithPen;
begin begin
segment := T2DSegment.Create; segment := T2DSegmentWithPen.Create;
segment.SegmentType := st2DLine; segment.SegmentType := st2DLineWithPen;
segment.X := AX; segment.X := AX;
segment.Y := AY; segment.Y := AY;
segment.PenColor := AColor; segment.Pen.Color := AColor;
AppendSegmentToTmpPath(segment); AppendSegmentToTmpPath(segment);
end; end;
@ -623,6 +634,23 @@ begin
AppendSegmentToTmpPath(segment); AppendSegmentToTmpPath(segment);
end; end;
{
Sets a Brush to paint the inner area inside the path.
}
procedure TvVectorialDocument.SetBrushToPath(ABrush: TvBrush);
begin
FTmPPath.Brush := ABrush;
end;
{
Sets a global Pen for the entire path. This Pen might be overriden by
individual elements of the polyline
}
procedure TvVectorialDocument.SetPenToPath(APen: TvPen);
begin
FTmPPath.Pen := APen;
end;
{@@ {@@
Finishes writing a Path, which was created in multiple Finishes writing a Path, which was created in multiple
steps using StartPath and AddPointToPath, steps using StartPath and AddPointToPath,
@ -683,7 +711,7 @@ begin
lCircularArc.Radius := ARadius; lCircularArc.Radius := ARadius;
lCircularArc.StartAngle := AStartAngle; lCircularArc.StartAngle := AStartAngle;
lCircularArc.EndAngle := AEndAngle; lCircularArc.EndAngle := AEndAngle;
lCircularArc.PenColor := AColor; lCircularArc.Pen.Color := AColor;
FEntities.Add(lCircularArc); FEntities.Add(lCircularArc);
end; end;
@ -1073,6 +1101,12 @@ end;
{ TPath } { TPath }
constructor TPath.Create();
begin
Brush.Style := bsClear;
inherited Create();
end;
procedure TPath.Assign(APath: TPath); procedure TPath.Assign(APath: TPath);
begin begin
Len := APath.Len; Len := APath.Len;

View File

@ -187,15 +187,22 @@ begin
Write(Format(' M%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)])); Write(Format(' M%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif} {$endif}
end; end;
st2DLine, st3DLine: st2DLineWithPen:
begin begin
{$ifdef USE_LCL_CANVAS}ADest.Pen.Color := VColorToTColor(Cur2DSegment.PenColor);{$endif} {$ifdef USE_LCL_CANVAS}ADest.Pen.Color := VColorToTColor(T2DSegmentWithPen(Cur2DSegment).Pen.Color);{$endif}
ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)); ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
{$ifdef USE_LCL_CANVAS}ADest.Pen.Color := clBlack;{$endif} {$ifdef USE_LCL_CANVAS}ADest.Pen.Color := clBlack;{$endif}
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG} {$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)])); Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif} {$endif}
end; end;
st2DLine, st3DLine:
begin
ADest.LineTo(CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y));
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif}
end;
{ To draw a bezier we need to divide the interval in parts and make { To draw a bezier we need to divide the interval in parts and make
lines between this parts } lines between this parts }
st2DBezier, st3DBezier: st2DBezier, st3DBezier:
@ -321,7 +328,7 @@ begin
WriteLn(Format('Drawing Arc Center=%f,%f Radius=%f StartAngle=%f AngleLength=%f', WriteLn(Format('Drawing Arc Center=%f,%f Radius=%f StartAngle=%f AngleLength=%f',
[CurArc.CenterX, CurArc.CenterY, CurArc.Radius, IntStartAngle/16, IntAngleLength/16])); [CurArc.CenterX, CurArc.CenterY, CurArc.Radius, IntStartAngle/16, IntAngleLength/16]));
{$endif} {$endif}
ADest.Pen.Color := {$ifdef USE_LCL_CANVAS}VColorToTColor(CurArc.PenColor);{$else}VColorToFPColor(CurArc.PenColor);{$endif} ADest.Pen.Color := {$ifdef USE_LCL_CANVAS}VColorToTColor(CurArc.Pen.Color);{$else}VColorToFPColor(CurArc.Pen.Color);{$endif}
ADest.Arc( ADest.Arc(
BoundsLeft, BoundsTop, BoundsRight, BoundsBottom, BoundsLeft, BoundsTop, BoundsRight, BoundsBottom,
IntStartAngle, IntAngleLength IntStartAngle, IntAngleLength