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;
end;
TvPen = record
Color: TvColor;
Style: TFPPenStyle;
Width: Integer;
end;
TvBrush = record
Color: TvColor;
Style: TFPBrushStyle;
end;
const
FPValphaTransparent = $00;
FPValphaOpaque = $FF;
@ -59,7 +70,7 @@ type
P3DPoint = ^T3DPoint;
TSegmentType = (
st2DLine, st2DBezier,
st2DLine, st2DLineWithPen, st2DBezier,
st3DLine, st3DBezier, stMoveTo);
{@@
@ -75,10 +86,6 @@ type
// Fields for linking the list
Previous: TPathSegment;
Next: TPathSegment;
// Data fields
PenColor: TvColor;
PenStyle: TFPPenStyle;
PenWidth: Integer;
end;
{@@
@ -93,6 +100,11 @@ type
X, Y: Double;
end;
T2DSegmentWithPen = class(T2DSegment)
public
Pen: TvPen;
end;
{@@
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
@ -124,6 +136,9 @@ type
Points: TPathSegment; // Beginning of the double-linked list
PointsEnd: TPathSegment; // End of the double-linked list
CurPoint: TPathSegment; // Used in PrepareForSequentialReading and Next
Pen: TvPen;
Brush: TvBrush;
constructor Create();
procedure Assign(APath: TPath);
function Count(): TPathSegment;
procedure PrepareForSequentialReading;
@ -149,13 +164,8 @@ type
}
TvEntity = class
public
// Pen
PenColor: TvColor;
PenStyle: TFPPenStyle;
PenWidth: Integer;
// Brush
BrushStyle: TFPBrushStyle;
BrushColor: TvColor;
Pen: TvPen;
Brush: TvBrush;
end;
{@@
@ -253,6 +263,8 @@ type
procedure AddLineToPath(AX, AY, AZ: 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 SetBrushToPath(ABrush: TvBrush);
procedure SetPenToPath(APen: TvPen);
procedure EndPath();
procedure AddText(AX, AY, AZ: Double; FontName: string; FontSize: integer; AText: utf8string); overload;
procedure AddText(AX, AY, AZ: Double; AStr: utf8string); overload;
@ -550,20 +562,19 @@ begin
segment.SegmentType := st2DLine;
segment.X := AX;
segment.Y := AY;
segment.PenColor := clvBlack;
AppendSegmentToTmpPath(segment);
end;
procedure TvVectorialDocument.AddLineToPath(AX, AY: Double; AColor: TvColor);
var
segment: T2DSegment;
segment: T2DSegmentWithPen;
begin
segment := T2DSegment.Create;
segment.SegmentType := st2DLine;
segment := T2DSegmentWithPen.Create;
segment.SegmentType := st2DLineWithPen;
segment.X := AX;
segment.Y := AY;
segment.PenColor := AColor;
segment.Pen.Color := AColor;
AppendSegmentToTmpPath(segment);
end;
@ -623,6 +634,23 @@ begin
AppendSegmentToTmpPath(segment);
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
steps using StartPath and AddPointToPath,
@ -683,7 +711,7 @@ begin
lCircularArc.Radius := ARadius;
lCircularArc.StartAngle := AStartAngle;
lCircularArc.EndAngle := AEndAngle;
lCircularArc.PenColor := AColor;
lCircularArc.Pen.Color := AColor;
FEntities.Add(lCircularArc);
end;
@ -1073,6 +1101,12 @@ end;
{ TPath }
constructor TPath.Create();
begin
Brush.Style := bsClear;
inherited Create();
end;
procedure TPath.Assign(APath: TPath);
begin
Len := APath.Len;

View File

@ -187,15 +187,22 @@ begin
Write(Format(' M%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif}
end;
st2DLine, st3DLine:
st2DLineWithPen:
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));
{$ifdef USE_LCL_CANVAS}ADest.Pen.Color := clBlack;{$endif}
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
Write(Format(' L%d,%d', [CoordToCanvasX(Cur2DSegment.X), CoordToCanvasY(Cur2DSegment.Y)]));
{$endif}
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
lines between this parts }
st2DBezier, st3DBezier:
@ -321,7 +328,7 @@ begin
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.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(
BoundsLeft, BoundsTop, BoundsRight, BoundsBottom,
IntStartAngle, IntAngleLength