You've already forked lazarus-ccr
fpvectorial: Implements support for clipping regions, specially for PostScript
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@1768 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -71,6 +71,8 @@ type
|
|||||||
public
|
public
|
||||||
Color: TFPColor;
|
Color: TFPColor;
|
||||||
TranslateX, TranslateY: Double;
|
TranslateX, TranslateY: Double;
|
||||||
|
ClipPath: TPath;
|
||||||
|
ClipMode: TvClipMode;
|
||||||
function Duplicate: TGraphicState;
|
function Duplicate: TGraphicState;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -144,6 +146,7 @@ begin
|
|||||||
Result.Color := Color;
|
Result.Color := Color;
|
||||||
Result.TranslateX := TranslateX;
|
Result.TranslateX := TranslateX;
|
||||||
Result.TranslateY := TranslateY;
|
Result.TranslateY := TranslateY;
|
||||||
|
Result.ClipPath := ClipPath;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TPSToken }
|
{ TPSToken }
|
||||||
@ -1467,6 +1470,7 @@ begin
|
|||||||
{$ifdef FPVECTORIALDEBUG_PATHS}
|
{$ifdef FPVECTORIALDEBUG_PATHS}
|
||||||
WriteLn('[TvEPSVectorialReader.ExecutePathConstructionOperator] newpath');
|
WriteLn('[TvEPSVectorialReader.ExecutePathConstructionOperator] newpath');
|
||||||
{$endif}
|
{$endif}
|
||||||
|
AData.SetClipPath(CurrentGraphicState.ClipPath, CurrentGraphicState.ClipMode);
|
||||||
AData.EndPath();
|
AData.EndPath();
|
||||||
AData.StartPath();
|
AData.StartPath();
|
||||||
|
|
||||||
@ -1611,6 +1615,10 @@ begin
|
|||||||
// – eoclip – Clip using even-odd rule
|
// – eoclip – Clip using even-odd rule
|
||||||
if AToken.StrValue = 'eoclip' then
|
if AToken.StrValue = 'eoclip' then
|
||||||
begin
|
begin
|
||||||
|
AData.SetPenStyle(psClear);
|
||||||
|
AData.EndPath();
|
||||||
|
CurrentGraphicState.ClipPath := AData.GetPath(AData.GetPathCount()-1);
|
||||||
|
CurrentGraphicState.ClipMode := vcmEvenOddRule;
|
||||||
Exit(True);
|
Exit(True);
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
@ -157,11 +157,15 @@ type
|
|||||||
constructor Create; virtual;
|
constructor Create; virtual;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TvClipMode = (vcmNonzeroWindingRule, vcmEvenOddRule);
|
||||||
|
|
||||||
TPath = class(TvEntity)
|
TPath = class(TvEntity)
|
||||||
Len: Integer;
|
Len: Integer;
|
||||||
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
|
||||||
|
ClipPath: TPath;
|
||||||
|
ClipMode: TvClipMode;
|
||||||
procedure Assign(ASource: TPath);
|
procedure Assign(ASource: TPath);
|
||||||
procedure PrepareForSequentialReading;
|
procedure PrepareForSequentialReading;
|
||||||
function Next(): TPathSegment;
|
function Next(): TPathSegment;
|
||||||
@ -303,6 +307,7 @@ type
|
|||||||
procedure SetPenColor(AColor: TFPColor);
|
procedure SetPenColor(AColor: TFPColor);
|
||||||
procedure SetPenStyle(AStyle: TFPPenStyle);
|
procedure SetPenStyle(AStyle: TFPPenStyle);
|
||||||
procedure SetPenWidth(AWidth: Integer);
|
procedure SetPenWidth(AWidth: Integer);
|
||||||
|
procedure SetClipPath(AClipPath: TPath; AClipMode: TvClipMode);
|
||||||
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;
|
||||||
@ -737,6 +742,13 @@ begin
|
|||||||
FTmPPath.Pen.Width := AWidth;
|
FTmPPath.Pen.Width := AWidth;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TvVectorialDocument.SetClipPath(AClipPath: TPath;
|
||||||
|
AClipMode: TvClipMode);
|
||||||
|
begin
|
||||||
|
FTmPPath.ClipPath := AClipPath;
|
||||||
|
FTmPPath.ClipMode := AClipMode;
|
||||||
|
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,
|
||||||
@ -885,15 +897,6 @@ procedure TvVectorialDocument.ClearTmpPath();
|
|||||||
var
|
var
|
||||||
segment, oldsegment: TPathSegment;
|
segment, oldsegment: TPathSegment;
|
||||||
begin
|
begin
|
||||||
// segment := FTmpPath.Points;
|
|
||||||
// Don't free segments, because they are used when the path is added
|
|
||||||
// while segment <> nil do
|
|
||||||
// begin
|
|
||||||
// oldsegment := segment;
|
|
||||||
// segment := segment^.Next;
|
|
||||||
// oldsegment^.Free;
|
|
||||||
// end;
|
|
||||||
|
|
||||||
FTmpPath.Points := nil;
|
FTmpPath.Points := nil;
|
||||||
FTmpPath.PointsEnd := nil;
|
FTmpPath.PointsEnd := nil;
|
||||||
FTmpPath.Len := 0;
|
FTmpPath.Len := 0;
|
||||||
@ -1240,6 +1243,8 @@ begin
|
|||||||
CurPoint := ASource.CurPoint;
|
CurPoint := ASource.CurPoint;
|
||||||
Pen := ASource.Pen;
|
Pen := ASource.Pen;
|
||||||
Brush := ASource.Brush;
|
Brush := ASource.Brush;
|
||||||
|
ClipPath := ASource.ClipPath;
|
||||||
|
ClipMode := ASource.ClipMode;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TPath.PrepareForSequentialReading;
|
procedure TPath.PrepareForSequentialReading;
|
||||||
|
@ -4,16 +4,16 @@ unit fpvtocanvas;
|
|||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
{.$define USE_LCL_CANVAS}
|
{$define USE_LCL_CANVAS}
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Math,
|
Classes, SysUtils, Math,
|
||||||
{$ifdef USE_LCL_CANVAS}
|
{$ifdef USE_LCL_CANVAS}
|
||||||
Graphics, LCLIntf,
|
Graphics, LCLIntf, LCLType,
|
||||||
{$endif}
|
{$endif}
|
||||||
fpcanvas,
|
fpcanvas,
|
||||||
fpimage,
|
fpimage,
|
||||||
fpvectorial;
|
fpvectorial, fpvutils;
|
||||||
|
|
||||||
procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument;
|
procedure DrawFPVectorialToCanvas(ASource: TvVectorialDocument;
|
||||||
ADest: TFPCustomCanvas;
|
ADest: TFPCustomCanvas;
|
||||||
@ -155,6 +155,11 @@ var
|
|||||||
t: Double;
|
t: Double;
|
||||||
// For polygons
|
// For polygons
|
||||||
Points: array of TPoint;
|
Points: array of TPoint;
|
||||||
|
// Clipping Region
|
||||||
|
{$ifdef USE_LCL_CANVAS}
|
||||||
|
ClipRegion, OldClipRegion: HRGN;
|
||||||
|
ACanvas: TCanvas absolute ADest;
|
||||||
|
{$endif}
|
||||||
begin
|
begin
|
||||||
PosX := 0;
|
PosX := 0;
|
||||||
PosY := 0;
|
PosY := 0;
|
||||||
@ -162,17 +167,29 @@ begin
|
|||||||
|
|
||||||
ADest.MoveTo(ADestX, ADestY);
|
ADest.MoveTo(ADestX, ADestY);
|
||||||
|
|
||||||
CurPath.PrepareForSequentialReading;
|
|
||||||
|
|
||||||
// Set the path Pen and Brush options
|
// Set the path Pen and Brush options
|
||||||
ADest.Pen.Style := CurPath.Pen.Style;
|
ADest.Pen.Style := CurPath.Pen.Style;
|
||||||
ADest.Pen.Width := CurPath.Pen.Width;
|
ADest.Pen.Width := CurPath.Pen.Width;
|
||||||
ADest.Pen.FPColor := CurPath.Pen.Color;
|
ADest.Pen.FPColor := CurPath.Pen.Color;
|
||||||
ADest.Brush.FPColor := CurPath.Brush.Color;
|
ADest.Brush.FPColor := CurPath.Brush.Color;
|
||||||
|
|
||||||
|
// Prepare the Clipping Region, if any
|
||||||
|
{$ifdef USE_LCL_CANVAS}
|
||||||
|
if CurPath.ClipPath <> nil then
|
||||||
|
begin
|
||||||
|
OldClipRegion := LCLIntf.CreateEmptyRegion();
|
||||||
|
GetClipRgn(ACanvas.Handle, OldClipRegion);
|
||||||
|
ClipRegion := ConvertPathToRegion(CurPath.ClipPath, ADestX, ADestY, AMulX, AMulY);
|
||||||
|
SelectClipRgn(ACanvas.Handle, ClipRegion);
|
||||||
|
DeleteObject(ClipRegion);
|
||||||
|
end;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
//
|
//
|
||||||
// For solid paths, draw a polygon instead
|
// For solid paths, draw a polygon instead
|
||||||
//
|
//
|
||||||
|
CurPath.PrepareForSequentialReading;
|
||||||
|
|
||||||
if CurPath.Brush.Style = bsSolid then
|
if CurPath.Brush.Style = bsSolid then
|
||||||
begin
|
begin
|
||||||
ADest.Brush.Style := CurPath.Brush.Style;
|
ADest.Brush.Style := CurPath.Brush.Style;
|
||||||
@ -281,6 +298,14 @@ begin
|
|||||||
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
|
{$ifdef FPVECTORIAL_TOCANVAS_DEBUG}
|
||||||
WriteLn('');
|
WriteLn('');
|
||||||
{$endif}
|
{$endif}
|
||||||
|
|
||||||
|
// Restores the previous Clip Region
|
||||||
|
{$ifdef USE_LCL_CANVAS}
|
||||||
|
if CurPath.ClipPath <> nil then
|
||||||
|
begin
|
||||||
|
SelectClipRgn(ACanvas.Handle, OldClipRegion); //Using OldClipRegion crashes in Qt
|
||||||
|
end;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure DrawFPVEntityToCanvas(ASource: TvVectorialDocument; CurEntity: TvEntity;
|
procedure DrawFPVEntityToCanvas(ASource: TvVectorialDocument; CurEntity: TvEntity;
|
||||||
|
@ -11,6 +11,8 @@ AUTHORS: Felipe Monteiro de Carvalho
|
|||||||
}
|
}
|
||||||
unit fpvutils;
|
unit fpvutils;
|
||||||
|
|
||||||
|
{$define USE_LCL_CANVAS}
|
||||||
|
|
||||||
{$ifdef fpc}
|
{$ifdef fpc}
|
||||||
{$mode delphi}
|
{$mode delphi}
|
||||||
{$endif}
|
{$endif}
|
||||||
@ -19,6 +21,9 @@ interface
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Math,
|
Classes, SysUtils, Math,
|
||||||
|
{$ifdef USE_LCL_CANVAS}
|
||||||
|
Graphics, LCLIntf, LCLType,
|
||||||
|
{$endif}
|
||||||
fpvectorial, fpimage;
|
fpvectorial, fpimage;
|
||||||
|
|
||||||
type
|
type
|
||||||
@ -27,13 +32,20 @@ type
|
|||||||
// Color Conversion routines
|
// Color Conversion routines
|
||||||
function FPColorToRGBHexString(AColor: TFPColor): string;
|
function FPColorToRGBHexString(AColor: TFPColor): string;
|
||||||
function RGBToFPColor(AR, AG, AB: byte): TFPColor; inline;
|
function RGBToFPColor(AR, AG, AB: byte): TFPColor; inline;
|
||||||
// Other routine
|
// Coordinate Conversion routines
|
||||||
function CanvasCoordsToFPVectorial(AY: Integer; AHeight: Integer): Integer; inline;
|
function CanvasCoordsToFPVectorial(AY: Integer; AHeight: Integer): Integer; inline;
|
||||||
function CanvasTextPosToFPVectorial(AY: Integer; ACanvasHeight, ATextHeight: Integer): Integer;
|
function CanvasTextPosToFPVectorial(AY: Integer; ACanvasHeight, ATextHeight: Integer): Integer;
|
||||||
|
function CoordToCanvasX(ACoord: Double; ADestX: Integer; AMulX: Double): Integer; inline;
|
||||||
|
function CoordToCanvasY(ACoord: Double; ADestY: Integer; AMulY: Double): Integer; inline;
|
||||||
|
// Other routines
|
||||||
function SeparateString(AString: string; ASeparator: char): T10Strings;
|
function SeparateString(AString: string; ASeparator: char): T10Strings;
|
||||||
// Mathematical routines
|
// Mathematical routines
|
||||||
procedure EllipticalArcToBezier(Xc, Yc, Rx, Ry, startAngle, endAngle: Double; var P1, P2, P3, P4: T3DPoint);
|
procedure EllipticalArcToBezier(Xc, Yc, Rx, Ry, startAngle, endAngle: Double; var P1, P2, P3, P4: T3DPoint);
|
||||||
procedure CircularArcToBezier(Xc, Yc, R, startAngle, endAngle: Double; var P1, P2, P3, P4: T3DPoint);
|
procedure CircularArcToBezier(Xc, Yc, R, startAngle, endAngle: Double; var P1, P2, P3, P4: T3DPoint);
|
||||||
|
// LCL-related routines
|
||||||
|
{$ifdef USE_LCL_CANVAS}
|
||||||
|
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -78,6 +90,16 @@ begin
|
|||||||
Result := CanvasCoordsToFPVectorial(AY, ACanvasHeight) - ATextHeight;
|
Result := CanvasCoordsToFPVectorial(AY, ACanvasHeight) - ATextHeight;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function CoordToCanvasX(ACoord: Double; ADestX: Integer; AMulX: Double): Integer;
|
||||||
|
begin
|
||||||
|
Result := Round(ADestX + AmulX * ACoord);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function CoordToCanvasY(ACoord: Double; ADestY: Integer; AMulY: Double): Integer;
|
||||||
|
begin
|
||||||
|
Result := Round(ADestY + AmulY * ACoord);
|
||||||
|
end;
|
||||||
|
|
||||||
{@@
|
{@@
|
||||||
Reads a string and separates it in substring
|
Reads a string and separates it in substring
|
||||||
using ASeparator to delimite them.
|
using ASeparator to delimite them.
|
||||||
@ -164,5 +186,38 @@ begin
|
|||||||
EllipticalArcToBezier(Xc, Yc, R, R, startAngle, endAngle, P1, P2, P3, P4);
|
EllipticalArcToBezier(Xc, Yc, R, R, startAngle, endAngle, P1, P2, P3, P4);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifdef USE_LCL_CANVAS}
|
||||||
|
function ConvertPathToRegion(APath: TPath; ADestX, ADestY: Integer; AMulX, AMulY: Double): HRGN;
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
WindingMode: Integer;
|
||||||
|
Points: array of TPoint;
|
||||||
|
CoordX, CoordY: Integer;
|
||||||
|
// Segments
|
||||||
|
CurSegment: TPathSegment;
|
||||||
|
Cur2DSegment: T2DSegment absolute CurSegment;
|
||||||
|
begin
|
||||||
|
APath.PrepareForSequentialReading;
|
||||||
|
|
||||||
|
SetLength(Points, APath.Len);
|
||||||
|
|
||||||
|
for i := 0 to APath.Len - 1 do
|
||||||
|
begin
|
||||||
|
CurSegment := TPathSegment(APath.Next());
|
||||||
|
|
||||||
|
CoordX := CoordToCanvasX(Cur2DSegment.X, ADestX, AMulX);
|
||||||
|
CoordY := CoordToCanvasY(Cur2DSegment.Y, ADestY, AMulY);
|
||||||
|
|
||||||
|
Points[i].X := CoordX;
|
||||||
|
Points[i].Y := CoordY;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if APath.ClipMode = vcmEvenOddRule then WindingMode := LCLType.ALTERNATE
|
||||||
|
else WindingMode := LCLType.WINDING;
|
||||||
|
|
||||||
|
Result := LCLIntf.CreatePolygonRgn(@Points[0], APath.Len, WindingMode);
|
||||||
|
end;
|
||||||
|
{$endif}
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user