mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-26 19:43:48 +02:00
1629 lines
49 KiB
PHP
1629 lines
49 KiB
PHP
{%MainUnit ../graphics.pp}
|
||
{******************************************************************************
|
||
TCANVAS
|
||
******************************************************************************
|
||
|
||
*****************************************************************************
|
||
* *
|
||
* This file is part of the Lazarus Component Library (LCL) *
|
||
* *
|
||
* See the file COPYING.modifiedLGPL, included in this distribution, *
|
||
* for details about the copyright. *
|
||
* *
|
||
* This program is distributed in the hope that it will be useful, *
|
||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
|
||
* *
|
||
*****************************************************************************
|
||
}
|
||
|
||
const
|
||
csAllValid = [csHandleValid..csBrushValid];
|
||
|
||
{-----------------------------------------------}
|
||
{-- TCanvas.Draw --}
|
||
{-----------------------------------------------}
|
||
Procedure TCanvas.Draw(X, Y: Integer; SrcGraphic: TGraphic);
|
||
var
|
||
ARect: TRect;
|
||
begin
|
||
if not Assigned(SrcGraphic) then exit;
|
||
ARect:=Bounds(X,Y,SrcGraphic.Width,SrcGraphic.Height);
|
||
StretchDraw(ARect,SrcGraphic);
|
||
end;
|
||
|
||
{-----------------------------------------------}
|
||
{-- TCanvas.DrawFocusRect --}
|
||
{-----------------------------------------------}
|
||
procedure TCanvas.DrawFocusRect(const ARect: TRect);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid]);
|
||
LCLIntf.DrawFocusRect(FHandle, ARect);
|
||
Changed;
|
||
end;
|
||
|
||
{-----------------------------------------------}
|
||
{-- TCanvas.StretchDraw --}
|
||
{-----------------------------------------------}
|
||
procedure TCanvas.StretchDraw(const DestRect: TRect; SrcGraphic: TGraphic);
|
||
begin
|
||
if not Assigned(SrcGraphic) then exit;
|
||
Changing;
|
||
RequiredState([csHandleValid]);
|
||
SrcGraphic.Draw(Self, DestRect);
|
||
Changed;
|
||
end;
|
||
|
||
{-----------------------------------------------}
|
||
{-- TCanvas.GetClipRect --}
|
||
{-----------------------------------------------}
|
||
function TCanvas.GetClipRect: TRect;
|
||
begin
|
||
If GetClipBox(FHandle, @Result) = ERROR then
|
||
Result := Rect(0,0,2000,2000);{Just in Case}
|
||
end;
|
||
|
||
|
||
{-----------------------------------------------}
|
||
{-- TCanvas.CopyRect --}
|
||
{-----------------------------------------------}
|
||
Procedure TCanvas.CopyRect(const Dest: TRect; SrcCanvas: TCanvas;
|
||
const Source: TRect);
|
||
var
|
||
SH, SW, DH, DW: Integer;
|
||
Begin
|
||
if SrcCanvas= nil then exit;
|
||
|
||
SH := Source.Bottom - Source.Top;
|
||
SW := Source.Right - Source.Left;
|
||
if (SH=0) or (SW=0) then exit;
|
||
DH := Dest.Bottom - Dest.Top;
|
||
DW := Dest.Right - Dest.Left;
|
||
if (Dh=0) or (DW=0) then exit;
|
||
|
||
SrcCanvas.RequiredState([csHandleValid]);
|
||
Changing;
|
||
RequiredState([csHandleValid]);
|
||
|
||
//DebugLn('TCanvas.CopyRect ',ClassName,' SrcCanvas=',SrcCanvas.ClassName,' ',
|
||
// ' Src=',Source.Left,',',Source.Top,',',SW,',',SH,
|
||
// ' Dest=',Dest.Left,',',Dest.Top,',',DW,',',DH);
|
||
StretchBlt(FHandle, Dest.Left, Dest.Top, DW, DH,
|
||
SrcCanvas.FHandle, Source.Left, Source.Top, SW, SH, CopyMode);
|
||
Changed;
|
||
end;
|
||
{-----------------------------------------------}
|
||
{-- TCanvas.GetPixel --}
|
||
{-----------------------------------------------}
|
||
function TCanvas.GetPixel(X, Y: Integer): TColor;
|
||
begin
|
||
Result := WidgetSet.DCGetPixel(Self.Handle, X, Y);
|
||
end;
|
||
|
||
{-----------------------------------------------}
|
||
{-- TCanvas.SetPixel --}
|
||
{-----------------------------------------------}
|
||
procedure TCanvas.SetPixel(X, Y: Integer; Value: TColor);
|
||
begin
|
||
WidgetSet.DCSetPixel(Self.Handle, X, Y, Value);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.RealizeAutoRedraw;
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.RealizeAutoRedraw;
|
||
begin
|
||
if FAutoRedraw and HandleAllocated then
|
||
WidgetSet.DCRedraw(Handle);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.CreateBrush
|
||
Params: None
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.CreateBrush;
|
||
var OldHandle: HBRUSH;
|
||
begin
|
||
//DebugLn('[TCanvas.CreateBrush] ',Classname,' Self=',DbgS(Self)
|
||
// ,' Brush=',DbgS(Brush));
|
||
OldHandle:=SelectObject(FHandle, Brush.Handle);
|
||
//debugln('TCanvas.CreateBrush ',ClassName,' Self=',DbgS(Self),' OldHandle=',DbgS(OldHandle),8),' NewHandle=',DbgS(Brush.Handle),' FSavedBrushHandle=',DbgS(Cardinal(FSavedBrushHandle));
|
||
if (OldHandle<>Brush.Handle) and (FSavedBrushHandle=0) then
|
||
FSavedBrushHandle:=OldHandle;
|
||
Include(FState, csBrushValid);
|
||
SetBkColor(FHandle, Brush.Color);
|
||
if Brush.Style=bsSolid then
|
||
SetBkMode(FHandle, OPAQUE)
|
||
else
|
||
SetBkMode(FHandle, TRANSPARENT);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.CreatePen
|
||
Params: None
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.CreatePen;
|
||
var OldHandle: HPEN;
|
||
const PenModes:Array[TPenMode] of Integer =
|
||
( R2_BLACK, R2_WHITE, R2_NOP, R2_NOT, R2_COPYPEN, R2_NOTCOPYPEN, R2_MERGEPENNOT,
|
||
R2_MASKPENNOT, R2_MERGENOTPEN, R2_MASKNOTPEN, R2_MERGEPEN, R2_NOTMERGEPEN,
|
||
R2_MASKPEN, R2_NOTMASKPEN, R2_XORPEN, R2_NOTXORPEN );
|
||
{
|
||
TPenMode = (pmBlack, pmWhite, pmNop, pmNot, pmCopy, pmNotCopy, pmMergePenNot,
|
||
pmMaskPenNot, pmMergeNotPen, pmMaskNotPen, pmMerge,pmNotMerge,
|
||
pmMask, pmNotMask, pmXor, pmNotXor
|
||
}
|
||
begin
|
||
//DebugLn('[TCanvas.CreatePen] ',Classname,' Self=',DbgS(Self)
|
||
// ,' Pen=',DbgS(Pen));
|
||
OldHandle:=SelectObject(FHandle, Pen.Handle);
|
||
if (OldHandle<>Pen.Handle) and (FSavedPenHandle=0) then
|
||
FSavedPenHandle:=OldHandle;
|
||
MoveTo(PenPos.X,PenPos.Y);
|
||
Include(FState, csPenValid);
|
||
SetROP2(FHandle, PenModes[Pen.Mode]);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.CreateFont
|
||
Params: None
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.CreateFont;
|
||
var OldHandle: HFONT;
|
||
begin
|
||
// The first time the font handle is selected, the default font handle
|
||
// is returned. Save this font handle to restore it later in DeselectHandles.
|
||
// The TFont will call DeleteObject itself, so we never need to call it.
|
||
OldHandle:=SelectObject(FHandle, Font.Handle);
|
||
//DebugLn(['TCanvas.CreateFont OldHandle=',dbghex(OldHandle),' Font.Handle=',dbghex(Font.Handle)]);
|
||
if (OldHandle<>Font.Handle) and (FSavedFontHandle=0) then
|
||
FSavedFontHandle:=OldHandle;
|
||
Include(FState, csFontValid);
|
||
SetTextColor(FHandle, Font.Color);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.CreateRegion;
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.CreateRegion;
|
||
var OldHandle: HRGN;
|
||
begin
|
||
OldHandle:=SelectObject(FHandle, Region.Handle);
|
||
if (OldHandle<>Region.Handle) and (FSavedRegionHandle=0) then
|
||
FSavedRegionHandle:=OldHandle;
|
||
Include(FState, csRegionValid);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.SetAutoReDraw
|
||
Params: Value
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.SetAutoRedraw(Value : Boolean);
|
||
begin
|
||
if FAutoRedraw=Value then exit;
|
||
FAutoRedraw := Value;
|
||
RealizeAutoRedraw;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.SetInternalPenPos(const Value: TPoint);
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.SetInternalPenPos(const Value: TPoint);
|
||
begin
|
||
inherited SetPenPos(Value);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.SetLazBrush
|
||
Params: Value
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.SetLazBrush(Value : TBrush);
|
||
begin
|
||
FBrush.Assign(Value);
|
||
end;
|
||
|
||
procedure TCanvas.SetPenPos(const AValue: TPoint);
|
||
begin
|
||
MoveTo(AValue.X,AValue.Y);
|
||
// fpcanvas TODO
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.SetLazFont
|
||
Params: Value
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.SetLazFont(Value : TFont);
|
||
begin
|
||
FFont.Assign(Value);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.SetLazPen
|
||
Params: Value
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.SetLazPen(Value : TPen);
|
||
begin
|
||
FPen.Assign(Value);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.SetRegion
|
||
Params: Value
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
Procedure TCanvas.SetRegion(value : TRegion);
|
||
begin
|
||
FRegion.Assign(Value);
|
||
end;
|
||
|
||
function TCanvas.DoCreateDefaultFont: TFPCustomFont;
|
||
begin
|
||
Result:=TFont.Create;
|
||
end;
|
||
|
||
function TCanvas.DoCreateDefaultPen: TFPCustomPen;
|
||
begin
|
||
Result:=TPen.Create;
|
||
end;
|
||
|
||
function TCanvas.DoCreateDefaultBrush: TFPCustomBrush;
|
||
begin
|
||
Result:=TBrush.Create;
|
||
end;
|
||
|
||
procedure TCanvas.SetColor(x, y: integer; const Value: TFPColor);
|
||
begin
|
||
Pixels[x,y]:=FPColorToTColor(Value);
|
||
end;
|
||
|
||
function TCanvas.GetColor(x, y: integer): TFPColor;
|
||
begin
|
||
Result:=TColorToFPColor(Pixels[x,y]);
|
||
end;
|
||
|
||
procedure TCanvas.SetHeight(AValue: integer);
|
||
begin
|
||
RaiseGDBException('TCanvas.SetHeight not allowed for LCL canvas');
|
||
end;
|
||
|
||
function TCanvas.GetHeight: integer;
|
||
var
|
||
p: TPoint;
|
||
begin
|
||
if HandleAllocated then begin
|
||
GetDeviceSize(Handle,p);
|
||
Result:=p.y;
|
||
end else
|
||
Result:=0;
|
||
end;
|
||
|
||
procedure TCanvas.SetWidth(AValue: integer);
|
||
begin
|
||
RaiseGDBException('TCanvas.SetWidth not allowed for LCL canvas');
|
||
end;
|
||
|
||
function TCanvas.GetWidth: integer;
|
||
var
|
||
p: TPoint;
|
||
begin
|
||
if HandleAllocated then begin
|
||
GetDeviceSize(Handle,p);
|
||
Result:=p.x;
|
||
end else
|
||
Result:=0;
|
||
end;
|
||
|
||
procedure TCanvas.GradientFill(ARect: TRect; AStart, AStop: TColor;
|
||
ADirection: TGradientDirection);
|
||
var
|
||
RStart, RStop: Byte;
|
||
GStart, GStop: Byte;
|
||
BStart, BStop: Byte;
|
||
RDiff, GDiff, BDiff: Integer;
|
||
Count, I: Integer;
|
||
|
||
begin
|
||
RedGreenBlue(ColorToRGB(AStart), RStart, GStart, BStart);
|
||
RedGreenBlue(ColorToRGB(AStop), RStop, GStop, BStop);
|
||
|
||
if ADirection = gdVertical then Count := ARect.Bottom - ARect.Top
|
||
else Count := ARect.Right - ARect.Left;
|
||
|
||
RDiff := RStop - RStart;
|
||
GDiff := GStop - GStart;
|
||
BDiff := BStop - BStart;
|
||
|
||
Changing;
|
||
for I := 0 to Count do
|
||
begin
|
||
Pen.Color := RGBToColor(RStart + (i * RDiff) div Count,
|
||
GStart + (i * GDiff) div Count,
|
||
BStart + (i * BDiff) div Count);
|
||
|
||
RequiredState([csHandleValid, csPenValid]);
|
||
if ADirection = gdHorizontal
|
||
then begin
|
||
// draw top to bottom, because LineTo does not draw last pixel
|
||
LCLIntf.MoveToEx(FHandle, ARect.Left+I, ARect.Top, nil);
|
||
LCLIntf.LineTo(FHandle, ARect.Left+I, ARect.Bottom);
|
||
end
|
||
else begin
|
||
// draw left to right, because LineTo does not draw last pixel
|
||
LCLIntf.MoveToEx(FHandle, ARect.Left, ARect.Top+I, nil);
|
||
LCLIntf.LineTo(FHandle, ARect.Right, ARect.Top+I);
|
||
end;
|
||
end;
|
||
Changed;
|
||
end;
|
||
|
||
procedure TCanvas.DoLockCanvas;
|
||
begin
|
||
if FLock=0 then InitializeCriticalSection(FLock);
|
||
EnterCriticalSection(FLock);
|
||
inherited DoLockCanvas;
|
||
end;
|
||
|
||
procedure TCanvas.DoUnlockCanvas;
|
||
begin
|
||
LeaveCriticalSection(FLock);
|
||
inherited DoUnlockCanvas;
|
||
end;
|
||
|
||
procedure TCanvas.DoTextOut(x, y: integer; Text: string);
|
||
begin
|
||
TextOut(X,Y,Text);
|
||
end;
|
||
|
||
procedure TCanvas.DoGetTextSize(Text: string; var w, h: integer);
|
||
var
|
||
TxtSize: tagSIZE;
|
||
begin
|
||
TxtSize:=TextExtent(Text);
|
||
w:=TxtSize.cx;
|
||
h:=TxtSize.cy;
|
||
end;
|
||
|
||
function TCanvas.DoGetTextHeight(Text: string): integer;
|
||
begin
|
||
Result:=TextHeight(Text);
|
||
end;
|
||
|
||
function TCanvas.DoGetTextWidth(Text: string): integer;
|
||
begin
|
||
Result:=TextWidth(Text);
|
||
end;
|
||
|
||
procedure TCanvas.DoRectangle(const Bounds: TRect);
|
||
begin
|
||
Frame(Bounds);
|
||
end;
|
||
|
||
procedure TCanvas.DoRectangleFill(const Bounds: TRect);
|
||
begin
|
||
FillRect(Bounds);
|
||
end;
|
||
|
||
procedure TCanvas.DoRectangleAndFill(const Bounds: TRect);
|
||
begin
|
||
Rectangle(Bounds);
|
||
end;
|
||
|
||
procedure TCanvas.DoEllipse(const Bounds: TRect);
|
||
var
|
||
x1: Integer;
|
||
y1: Integer;
|
||
x2: Integer;
|
||
y2: Integer;
|
||
begin
|
||
if Bounds.Left < Bounds.Right then
|
||
begin
|
||
x1 := Bounds.Left;
|
||
x2 := Bounds.Right;
|
||
end else
|
||
begin
|
||
x1 := Bounds.Right;
|
||
x2 := Bounds.Left;
|
||
end;
|
||
if Bounds.Top < Bounds.Bottom then
|
||
begin
|
||
y1 := Bounds.Top;
|
||
y2 := Bounds.Bottom;
|
||
end else
|
||
begin
|
||
y1 := Bounds.Bottom;
|
||
y2 := Bounds.Top;
|
||
end;
|
||
Arc(x1, y1, x2, y2, 0, 360*16);
|
||
end;
|
||
|
||
procedure TCanvas.DoEllipseFill(const Bounds: TRect);
|
||
begin
|
||
Ellipse(Bounds);
|
||
end;
|
||
|
||
procedure TCanvas.DoEllipseAndFill(const Bounds: TRect);
|
||
begin
|
||
inherited DoEllipseAndFill(Bounds);
|
||
end;
|
||
|
||
procedure TCanvas.DoPolygon(const Points: array of TPoint);
|
||
begin
|
||
Polyline(Points);
|
||
end;
|
||
|
||
procedure TCanvas.DoPolygonFill(const Points: array of TPoint);
|
||
begin
|
||
Polygon(Points);
|
||
end;
|
||
|
||
procedure TCanvas.DoPolygonAndFill(const Points: array of TPoint);
|
||
begin
|
||
inherited DoPolygonAndFill(Points);
|
||
end;
|
||
|
||
procedure TCanvas.DoPolyline(const Points: array of TPoint);
|
||
begin
|
||
Polyline(Points);
|
||
end;
|
||
|
||
procedure TCanvas.DoFloodFill(x, y: integer);
|
||
begin
|
||
FloodFill(x, y, Brush.Color, fsSurface);
|
||
end;
|
||
|
||
procedure TCanvas.DoMoveTo(x, y: integer);
|
||
begin
|
||
MoveTo(X,Y);
|
||
end;
|
||
|
||
procedure TCanvas.DoLineTo(x, y: integer);
|
||
begin
|
||
LineTo(X,Y);
|
||
end;
|
||
|
||
procedure TCanvas.DoLine(x1, y1, x2, y2: integer);
|
||
begin
|
||
Line(x1,y1,x2,y2);
|
||
end;
|
||
|
||
procedure TCanvas.DoCopyRect(x, y: integer; SrcCanvas: TFPCustomCanvas;
|
||
const SourceRect: TRect);
|
||
|
||
Procedure WarnNotSupported;
|
||
begin
|
||
debugln('WARNING: TCanvas.DoCopyRect from ',DbgSName(SrcCanvas));
|
||
end;
|
||
|
||
var
|
||
SH: Integer;
|
||
SW: Integer;
|
||
Begin
|
||
if SrcCanvas=nil then exit;
|
||
if SrcCanvas is TCanvas then begin
|
||
SW := SourceRect.Right - SourceRect.Left;
|
||
SH := SourceRect.Bottom - SourceRect.Top;
|
||
if (SH=0) or (SW=0) then exit;
|
||
CopyRect(Rect(x,y,x+SW,y+SH),TCanvas(SrcCanvas),SourceRect);
|
||
end else begin
|
||
WarnNotSupported;
|
||
end;
|
||
end;
|
||
|
||
procedure TCanvas.DoDraw(x, y: integer; const Image: TFPCustomImage);
|
||
var
|
||
LazImg: TLazIntfImage;
|
||
BitmapHnd, DummyHnd: HBitmap;
|
||
begin
|
||
if Image=nil then exit;
|
||
|
||
BitmapHnd:=0;
|
||
try
|
||
if Image is TLazIntfImage
|
||
then begin
|
||
LazImg := TLazIntfImage(Image);
|
||
end
|
||
else begin
|
||
LazImg := TLazIntfImage.Create(0,0);
|
||
RequiredState([csHandleValid]);
|
||
LazImg.DataDescription := GetDescriptionFromDevice(Handle, 0, 0);
|
||
LazImg.Assign(Image);
|
||
end;
|
||
LazImg.CreateBitmaps(BitmapHnd, DummyHnd, True);
|
||
if BitmapHnd=0 then exit;
|
||
|
||
Changing;
|
||
RequiredState([csHandleValid]);
|
||
StretchBlt(FHandle,x,y,LazImg.Width,LazImg.Height,
|
||
BitmapHnd, 0,0,LazImg.Width,LazImg.Height, CopyMode);
|
||
Changed;
|
||
finally
|
||
if Image <> LazImg then LazImg.Free;
|
||
if BitmapHnd <> 0 then DeleteObject(BitmapHnd);
|
||
end;
|
||
end;
|
||
|
||
procedure TCanvas.CheckHelper(AHelper: TFPCanvasHelper);
|
||
begin
|
||
debugln('TCanvas.CheckHelper ignored for ',DbgSName(AHelper));
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Arc
|
||
Params: ALeft, ATop, ARight, ABottom, angle1, angle2
|
||
Returns: Nothing
|
||
|
||
Use Arc to draw an elliptically curved line with the current Pen.
|
||
The angles angle1 and angle2 are 1/16th of a degree. For example, a full
|
||
circle equals 5760 (16*360). Positive values of Angle and AngleLength mean
|
||
counter-clockwise while negative values mean clockwise direction.
|
||
Zero degrees is at the 3'o clock position.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Arc(ALeft, ATop, ARight, ABottom, angle1, angle2 : Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csPenValid]);
|
||
LCLIntf.Arc(FHandle, ALeft, ATop, ARight, ABottom, angle1, angle2);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Arc
|
||
Params: ALeft, ATop, ARight, ABottom, sx, sy, ex, ey
|
||
Returns: Nothing
|
||
|
||
Use Arc to draw an elliptically curved line with the current Pen. The
|
||
values sx,sy, and ex,ey represent the starting and ending radial-points
|
||
between which the Arc is drawn.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Arc(ALeft,ATop,ARight,ABottom,sx,sy,ex,ey : Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.RadialArc(FHandle, ALeft, ATop, ARight, ABottom, sx, sy, ex, ey);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.RadialPie
|
||
Params: x1, y1, x2, y2, StartAngle16Deg, EndAngle16Deg: Integer
|
||
Returns: Nothing
|
||
|
||
Use Pie to draw a filled pie-shaped wedge on the canvas.
|
||
The angles StartAngle16Deg and EndAngle16Deg are 1/16th of a degree.
|
||
For example, a full circle equals 5760 (16*360).
|
||
Positive values of Angle and AngleLength mean
|
||
counter-clockwise while negative values mean clockwise direction.
|
||
Zero degrees is at the 3'o clock position.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.RadialPie(x1, y1, x2, y2,
|
||
StartAngle16Deg, EndAngle16Deg: Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.RadialPie(FHandle, x1, y1, x2, y2, StartAngle16Deg,EndAngle16Deg);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Pie
|
||
Params: EllipseX1, EllipseY1, EllipseX2, EllipseY2,
|
||
StartX, StartY, EndX, EndY
|
||
Returns: Nothing
|
||
|
||
Use Pie to draw a filled Pie-shaped wedge on the canvas. The pie is part of
|
||
an ellipse between the points EllipseX1, EllipseY1, EllipseX2, EllipseY2.
|
||
The values StartX, StartY and EndX, EndY represent the starting and ending
|
||
radial-points between which the Bounding-Arc is drawn.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Pie(EllipseX1, EllipseY1, EllipseX2, EllipseY2,
|
||
StartX, StartY, EndX, EndY: Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.Pie(FHandle,EllipseX1,EllipseY1,EllipseX2,EllipseY2,
|
||
StartX,StartY,EndX,EndY);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.PolyBezier
|
||
Params: Points, Filled, Continous
|
||
Returns: Boolean
|
||
|
||
Use Polybezier to draw cubic B<EFBFBD>zier curves. The first curve is drawn from the
|
||
first point to the fourth point with the second and third points being the
|
||
control points. If the Continuous flag is TRUE then each subsequent curve
|
||
requires three more points, using the end-point of the previous Curve as its
|
||
starting point, the first and second points being used as its control points,
|
||
and the third point its end-point. If the continous flag is set to FALSE,
|
||
then each subsequent Curve requires 4 additional points, which are used
|
||
excatly as in the first curve. Any additonal points which do not add up to
|
||
a full bezier(4 for Continuous, 3 otherwise) are ingored. There must be at
|
||
least 4 points for an drawing to occur. If the Filled Flag is set to TRUE
|
||
then the resulting Poly-B<EFBFBD>zier will be drawn as a Polygon.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.PolyBezier(const Points: array of TPoint;
|
||
Filled: boolean = False;
|
||
Continuous: boolean = False);
|
||
var NPoints, i: integer;
|
||
PointArray: ^TPoint;
|
||
begin
|
||
NPoints:=High(Points)-Low(Points)+1;
|
||
if NPoints<=0 then exit;
|
||
GetMem(PointArray,SizeOf(TPoint)*NPoints);
|
||
for i:=0 to NPoints-1 do
|
||
PointArray[i]:=Points[i+Low(Points)];
|
||
PolyBezier(PointArray, NPoints, Filled, Continuous);
|
||
FreeMem(PointArray);
|
||
end;
|
||
|
||
procedure TCanvas.PolyBezier(Points: PPoint; NumPts: Integer;
|
||
Filled: boolean = False;
|
||
Continuous: boolean = False);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.PolyBezier(FHandle,Points,NumPts,Filled, Continuous);
|
||
Changed;
|
||
end;
|
||
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Polygon
|
||
Params: Points: array of TPoint; Winding: Boolean = False;
|
||
StartIndex: Integer = 0; NumPts: Integer = -1
|
||
Returns: Nothing
|
||
|
||
Use Polygon to draw a closed, many-sided shape on the canvas, using the value
|
||
of Pen. After drawing the complete shape, Polygon fills the shape using the
|
||
value of Brush.
|
||
The Points parameter is an array of points that give the vertices of the
|
||
polygon.
|
||
Winding determines how the polygon is filled. When Winding is True, Polygon
|
||
fills the shape using the Winding fill algorithm. When Winding is False,
|
||
Polygon uses the even-odd (alternative) fill algorithm.
|
||
StartIndex gives the index of the first point in the array to use. All points
|
||
before this are ignored.
|
||
NumPts indicates the number of points to use, starting at StartIndex.
|
||
If NumPts is -1 (the default), Polygon uses all points from StartIndex to the
|
||
end of the array.
|
||
The first point is always connected to the last point.
|
||
To draw a polygon on the canvas, without filling it, use the Polyline method,
|
||
specifying the first point a second time at the end.
|
||
}
|
||
procedure TCanvas.Polygon(const Points: array of TPoint; Winding: Boolean;
|
||
StartIndex: Integer; NumPts: Integer);
|
||
var
|
||
NPoints: integer;
|
||
begin
|
||
if NumPts<0 then
|
||
NPoints:=High(Points)-StartIndex+1
|
||
else
|
||
NPoints:=NumPts;
|
||
if NPoints<=0 then exit;
|
||
Polygon(@Points[StartIndex],NPoints,Winding);
|
||
end;
|
||
|
||
procedure TCanvas.Polygon(Points: PPoint; NumPts: Integer;
|
||
Winding: boolean = False);
|
||
begin
|
||
if NumPts<=0 then exit;
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.Polygon(FHandle,Points,NumPts,Winding);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Polygon
|
||
Params: Points
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Polygon(const Points: array of TPoint);
|
||
begin
|
||
Polygon(Points, True, Low(Points), High(Points) - Low(Points) + 1);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Polyline
|
||
Params: Points: array of TPoint;
|
||
StartIndex: Integer = 0; NumPts: Integer = -1
|
||
Returns: Nothing
|
||
|
||
Use Polyline to connect a set of points on the canvas. If you specify only two
|
||
points, Polyline draws a single line.
|
||
The Points parameter is an array of points to be connected.
|
||
StartIndex identifies the first point in the array to use.
|
||
NumPts indicates the number of points to use. If NumPts is -1 (the default),
|
||
PolyLine uses all the points from StartIndex to the end of the array.
|
||
Calling the MoveTo function with the value of the first point, and then
|
||
repeatedly calling LineTo with all subsequent points will draw the same image
|
||
on the canvas. However, unlike LineTo, Polyline does not change the value of
|
||
PenPos.
|
||
}
|
||
procedure TCanvas.Polyline(const Points: array of TPoint; StartIndex: Integer;
|
||
NumPts: Integer);
|
||
var
|
||
NPoints : integer;
|
||
begin
|
||
if NumPts<0 then
|
||
NPoints:=High(Points)-StartIndex+1
|
||
else
|
||
NPoints:=NumPts;
|
||
if NPoints<=0 then exit;
|
||
Polyline(@Points[StartIndex], NPoints);
|
||
end;
|
||
|
||
procedure TCanvas.Polyline(Points: PPoint; NumPts: Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csPenValid]);
|
||
LCLIntf.Polyline(FHandle,Points,NumPts);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Polyline
|
||
Params: Points
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Polyline(const Points: array of TPoint);
|
||
begin
|
||
Polyline(Points, Low(Points), High(Points) - Low(Points) + 1);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Ellipse
|
||
Params: X1, Y1, X2, Y2
|
||
Returns: Nothing
|
||
|
||
Use Ellipse to draw a filled circle or ellipse on the canvas.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Ellipse(x1, y1, x2, y2: Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.Ellipse(FHandle,x1,y1,x2,y2);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Ellipse
|
||
Params: ARect: TRect
|
||
Returns: Nothing
|
||
|
||
Use Ellipse to draw a filled circle or ellipse on the canvas.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Ellipse(const ARect: TRect);
|
||
begin
|
||
Ellipse(ARect.Left,ARect.Top,ARect.Right,ARect.Bottom);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.FillRect
|
||
Params: ARect
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.FillRect(const ARect : TRect);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid]);
|
||
LCLIntf.FillRect(FHandle, ARect, Brush.Handle);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.FillRect(X1,Y1,X2,Y2 : Integer);
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.FillRect(X1,Y1,X2,Y2 : Integer);
|
||
begin
|
||
FillRect(Rect(X1,Y1,X2,Y2));
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.FillRect
|
||
Params: X, Y: Integer; Color: TColor; FillStyle: TFillStyle
|
||
Returns: Nothing
|
||
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.FloodFill(X, Y: Integer; FillColor: TColor;
|
||
FillStyle: TFillStyle);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid]);
|
||
LCLIntf.FloodFill(FHandle, X, Y, FillColor, FillStyle, Brush.Handle);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Frame3d
|
||
Params: Rect
|
||
Returns: the inflated rectangle (the inner rectangle without the frame)
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Frame3d(var ARect: TRect; const FrameWidth : integer;
|
||
const Style : TGraphicsBevelCut);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid,csBrushValid,csPenValid]);
|
||
LCLIntf.Frame3d(FHandle, ARect, FrameWidth, Style);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.Frame(const ARect: TRect);
|
||
|
||
Drawing the border of a rectangle with the current pen
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Frame(const ARect: TRect);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csPenValid]);
|
||
LCLIntf.Frame(FHandle, ARect);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.Frame(const ARect: TRect);
|
||
|
||
Drawing the border of a rectangle with the current pen
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Frame(X1, Y1, X2, Y2: Integer);
|
||
begin
|
||
Frame(Rect(X1, Y1, X2, Y2));
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.FrameRect(const ARect: TRect);
|
||
|
||
Drawing the border of a rectangle with the current brush
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.FrameRect(const ARect: TRect);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid]);
|
||
LCLIntf.FrameRect(FHandle, ARect, Brush.GetHandle);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.FrameRect(const ARect: TRect);
|
||
|
||
Drawing the border of a rectangle with the current brush
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.FrameRect(X1, Y1, X2, Y2: Integer);
|
||
begin
|
||
FrameRect(Rect(X1, Y1, X2, Y2));
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Rectangle
|
||
Params: X1,Y1,X2,Y2
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Rectangle(X1,Y1,X2,Y2 : Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.Rectangle(FHandle, X1, Y1, X2, Y2);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Rectangle
|
||
Params: Rect
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Rectangle(const ARect: TRect);
|
||
begin
|
||
Rectangle(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.RoundRect
|
||
Params: X1, Y1, X2, Y2, RX, RY
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
Procedure TCanvas.RoundRect(X1, Y1, X2, Y2: Integer; RX,RY : Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.RoundRect(FHandle, X1, Y1, X2, Y2, RX, RY);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.RoundRect
|
||
Params: Rect, RX, RY
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
Procedure TCanvas.RoundRect(const Rect : TRect; RX,RY : Integer);
|
||
begin
|
||
RoundRect(Rect.Left, Rect.Top, Rect.Right, Rect.Bottom, RX, RY);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.TextRect
|
||
Params: ARect, X, Y, Text
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
Procedure TCanvas.TextRect(const ARect: TRect; X,Y : Integer;
|
||
const Text : String);
|
||
begin
|
||
TextRect(ARect,X,Y,Text,TextStyle);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.TextRect
|
||
Params: ARect, X, Y, Text, Style
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.TextRect(ARect: TRect; X, Y : Integer; const Text : String;
|
||
const Style : TTextStyle);
|
||
var
|
||
Options : Longint;
|
||
fRect : TRect;
|
||
DCIndex: Integer;
|
||
DC: HDC;
|
||
ReqState: TCanvasState;
|
||
|
||
procedure SaveState;
|
||
begin
|
||
if DCIndex<>0 then exit;
|
||
DCIndex:=SaveDC(DC);
|
||
end;
|
||
|
||
procedure RestoreState;
|
||
begin
|
||
if DCIndex=0 then exit;
|
||
RestoreDC(DC,DCIndex);
|
||
end;
|
||
|
||
begin
|
||
//debugln(['TCanvas.TextRect ',DbgSName(Self),' Text="',Text,'" ',dbgs(ARect),' X=',X,',Y=',Y]);
|
||
Changing;
|
||
|
||
Options := 0;
|
||
case Style.Alignment of
|
||
taRightJustify : Options := DT_RIGHT;
|
||
taCenter : Options := DT_CENTER;
|
||
end;
|
||
case Style.Layout of
|
||
tlCenter : Options := Options or DT_VCENTER;
|
||
tlBottom : Options := Options or DT_BOTTOM;
|
||
end;
|
||
If Style.WordBreak then
|
||
Options := Options or DT_WORDBREAK;
|
||
|
||
If Style.SingleLine then
|
||
Options := Options or DT_SINGLELINE;
|
||
|
||
If not Style.Clipping then
|
||
Options := Options or DT_NOCLIP;
|
||
|
||
If not Style.ShowPrefix then
|
||
Options := Options or DT_NOPREFIX;
|
||
|
||
If Style.RightToLeft then
|
||
Options := Options or DT_RTLREADING;
|
||
|
||
ReqState:=[csHandleValid];
|
||
if not Style.SystemFont then
|
||
Include(ReqState,csFontValid);
|
||
if Style.Opaque then
|
||
Include(ReqState,csBrushValid);
|
||
DC:=GetUpdatedHandle(ReqState);
|
||
|
||
DCIndex:=0;
|
||
if Style.SystemFont or Style.Clipping or (not Style.Opaque) then
|
||
SaveState;
|
||
|
||
if Style.SystemFont then
|
||
begin
|
||
Options := Options or DT_INTERNAL;
|
||
SelectObject(DC, GetStockObject(DEFAULT_GUI_FONT));
|
||
end;
|
||
|
||
// calculate text rectangle
|
||
fRect := ARect;
|
||
if Style.Alignment = taLeftJustify then
|
||
fRect.Left := X;
|
||
if Style.Layout = tlTop then
|
||
fRect.Top := Y;
|
||
|
||
if (Style.Alignment in [taRightJustify,taCenter]) or
|
||
(Style.Layout in [tlCenter,tlBottom]) then
|
||
begin
|
||
DrawText(DC, pChar(Text), Length(Text), fRect, DT_CALCRECT or Options);
|
||
case Style.Alignment of
|
||
taRightJustify : OffsetRect(fRect, ARect.Right - fRect.Right, 0);
|
||
taCenter : OffsetRect(fRect, (ARect.Right - fRect.Right) div 2, 0);
|
||
end;
|
||
case Style.Layout of
|
||
tlCenter : OffsetRect(fRect, 0,
|
||
((ARect.Bottom - ARect.Top) - (fRect.Bottom - fRect.Top)) div 2);
|
||
tlBottom : OffsetRect(fRect, 0, ARect.Bottom - fRect.Bottom);
|
||
end;
|
||
end;
|
||
|
||
if Style.Clipping then
|
||
begin
|
||
IntersectRect(ARect, ARect, fRect);
|
||
with ARect do
|
||
InterSectClipRect(DC, Left, Top, Right, Bottom);
|
||
Options := Options or DT_NOCLIP; // no clipping as we are handling it here
|
||
end;
|
||
|
||
if Style.Opaque then
|
||
FillRect(fRect)
|
||
else
|
||
SetBkMode(DC, TRANSPARENT);
|
||
|
||
if Style.SystemFont then
|
||
SetTextColor(DC, Font.Color);
|
||
//debugln('TCanvas.TextRect DRAW Text="',Text,'" ',dbgs(fRect));
|
||
DrawText(DC, pChar(Text), Length(Text), fRect, Options);
|
||
|
||
if Style.Opaque and (csBrushValid in FState) then
|
||
begin
|
||
if Brush.Style=bsSolid then // restore BKMode
|
||
SetBkMode(DC, OPAQUE)
|
||
end;
|
||
|
||
RestoreState;
|
||
|
||
Changed;
|
||
end;
|
||
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.TextOut
|
||
Params: X,Y,Text
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.TextOut(X,Y: Integer; const Text: String);
|
||
var
|
||
Flags : Cardinal;
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csFontValid, csBrushValid]);
|
||
Flags := 0;
|
||
If TextStyle.Opaque then
|
||
Flags := ETO_Opaque;
|
||
ExtUTF8Out(FHandle, X, Y, Flags, nil, PChar(Text), Length(Text), nil);
|
||
MoveTo(X + TextWidth(Text), Y);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
function TCanvas.HandleAllocated: boolean;
|
||
------------------------------------------------------------------------------}
|
||
function TCanvas.HandleAllocated: boolean;
|
||
begin
|
||
Result:=(FHandle<>0);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
function TCanvas.GetUpdatedHandle(ReqState: TCanvasState): HDC;
|
||
------------------------------------------------------------------------------}
|
||
function TCanvas.GetUpdatedHandle(ReqState: TCanvasState): HDC;
|
||
begin
|
||
RequiredState(ReqState+[csHandleValid]);
|
||
Result:=FHandle;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.MoveTo
|
||
Params: X1,Y1
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
Procedure TCanvas.MoveTo(X1, Y1: Integer);
|
||
begin
|
||
RequiredState([csHandleValid]);
|
||
if LCLIntf.MoveToEx(FHandle, X1, Y1, nil) then begin
|
||
SetInternalPenPos(Point(X1, Y1));
|
||
end;
|
||
End;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.LineTo
|
||
Params: X1,Y1
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.LineTo(X1, Y1 : Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csPenValid]);
|
||
if LCLIntf.LineTo(FHandle, X1, Y1) then
|
||
SetInternalPenPos(Point(X1, Y1));
|
||
Changed;
|
||
end;
|
||
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Line
|
||
Params: X1,Y1,X2,Y2
|
||
Returns: Nothing
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Line(X1,Y1,X2,Y2 : Integer);
|
||
begin
|
||
MoveTo(X1, Y1);
|
||
LineTo(X2, Y2);
|
||
end;
|
||
|
||
procedure TCanvas.Line(const p1, p2: TPoint);
|
||
begin
|
||
Line(p1.x,p1.y,p2.x,p2.y);
|
||
end;
|
||
|
||
procedure TCanvas.Line(const Points: TRect);
|
||
begin
|
||
with Points do
|
||
Line(Left,Top,Right,Bottom);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.BrushChanged
|
||
Params: ABrush: The changed brush
|
||
Returns: Nothing
|
||
|
||
Notify proc for a brush change
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.BrushChanged(ABrush: TObject);
|
||
begin
|
||
if csBrushValid in FState then begin
|
||
Exclude(FState, csBrushValid);
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.FontChanged
|
||
Params: AFont: the changed font
|
||
Returns: Nothing
|
||
|
||
Notify proc for a font change
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.FontChanged(AFont: TObject);
|
||
begin
|
||
if csFontValid in FState then begin
|
||
Exclude(FState, csFontValid);
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.PenChanging
|
||
Params: APen: The changing pen
|
||
Returns: Nothing
|
||
|
||
Notify proc for a pen change
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.PenChanging(APen: TObject);
|
||
begin
|
||
if [csPenValid, csHandleValid] * FState = [csPenValid, csHandleValid] then
|
||
begin
|
||
Exclude(FState, csPenValid);
|
||
SelectObject(FHandle, FSavedPenHandle);
|
||
FSavedPenHandle := 0;
|
||
end;
|
||
end;
|
||
|
||
procedure TCanvas.FontChanging(APen: TObject);
|
||
begin
|
||
if [csFontValid, csHandleValid] * FState = [csFontValid, csHandleValid] then
|
||
begin
|
||
Exclude(FState, csFontValid);
|
||
SelectObject(FHandle, FSavedFontHandle);
|
||
FSavedFontHandle := 0;
|
||
end;
|
||
end;
|
||
|
||
procedure TCanvas.BrushChanging(APen: TObject);
|
||
begin
|
||
if [csBrushValid, csHandleValid] * FState = [csBrushValid, csHandleValid] then
|
||
begin
|
||
Exclude(FState, csBrushValid);
|
||
SelectObject(FHandle, FSavedBrushHandle);
|
||
FSavedBrushHandle := 0;
|
||
end;
|
||
end;
|
||
|
||
procedure TCanvas.RegionChanging(APen: TObject);
|
||
begin
|
||
if [csRegionValid, csHandleValid] * FState = [csRegionValid, csHandleValid] then
|
||
begin
|
||
Exclude(FState, csRegionValid);
|
||
SelectObject(FHandle, FSavedRegionHandle);
|
||
FSavedRegionHandle := 0;
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.PenChanged
|
||
Params: APen: The changed pen
|
||
Returns: Nothing
|
||
|
||
Notify proc for a pen change
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.PenChanged(APen: TObject);
|
||
begin
|
||
if csPenValid in FState
|
||
then begin
|
||
Exclude(FState, csPenValid);
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.RegionChanged
|
||
Params: ARegion: The changed Region
|
||
Returns: Nothing
|
||
|
||
Notify proc for a region change
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.RegionChanged(ARegion: TObject);
|
||
begin
|
||
if csRegionValid in FState
|
||
then begin
|
||
Exclude(FState, csRegionValid);
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Create
|
||
Params: none
|
||
Returns: Nothing
|
||
|
||
Constructor for the class.
|
||
------------------------------------------------------------------------------}
|
||
constructor TCanvas.Create;
|
||
begin
|
||
FHandle := 0;
|
||
ManageResources := true;
|
||
inherited Create;
|
||
FFont := TFont(inherited Font);
|
||
FPen := TPen(inherited Pen);
|
||
FBrush := TBrush(inherited Brush);
|
||
FFont.OnChanging := @FontChanging;
|
||
FFont.OnChange := @FontChanged;
|
||
FSavedFontHandle := 0;
|
||
FPen.OnChanging := @PenChanging;
|
||
FPen.OnChange := @PenChanged;
|
||
FSavedPenHandle := 0;
|
||
FBrush.OnChanging := @BrushChanging;
|
||
FBrush.OnChange := @BrushChanged;
|
||
FSavedBrushHandle := 0;
|
||
FRegion := TRegion.Create;
|
||
FRegion.OnChanging := @RegionChanging;
|
||
FRegion.OnChange := @RegionChanged;
|
||
FSavedRegionHandle := 0;
|
||
FCopyMode := cmSrcCopy;
|
||
// FLock will be initialized on demand, because most canvas don't use it
|
||
With FTextStyle do begin
|
||
Alignment := taLeftJustify;
|
||
Layout := tlTop;
|
||
WordBreak := True;
|
||
SingleLine := True;
|
||
Clipping := True;
|
||
ShowPrefix := False;
|
||
Opaque := False;
|
||
end;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Chord
|
||
Params: x1, y1, x2, y2, StartAngle16Deg, EndAngle16Deg
|
||
Returns: Nothing
|
||
|
||
Use Chord to draw a filled Chord-shape on the canvas. The angles angle1 and
|
||
angle2 are 1/16th of a degree. For example, a full circle equals 5760(16*360).
|
||
Positive values of Angle and AngleLength mean counter-clockwise while negative
|
||
values mean clockwise direction. Zero degrees is at the 3'o clock position.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Chord(x1, y1, x2, y2,
|
||
StartAngle16Deg, EndAngle16Deg: Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.AngleChord(FHandle, x1, y1, x2, y2, StartAngle16Deg, EndAngle16Deg);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Chord
|
||
Params: x1, y1, x2, y2, sx, sy, ex, ey
|
||
Returns: Nothing
|
||
|
||
Use Chord to draw a filled Chord-shape on the canvas. The values sx,sy,
|
||
and ex,ey represent a starting and ending radial-points between which
|
||
the Arc is draw.
|
||
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Chord(x1, y1, x2, y2, sx, sy, ex, ey : Integer);
|
||
begin
|
||
Changing;
|
||
RequiredState([csHandleValid, csBrushValid, csPenValid]);
|
||
LCLIntf.RadialChord(FHandle, x1, y1, x2, y2, sx, sy, ex, ey);
|
||
Changed;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.Destroy
|
||
Params: None
|
||
Returns: Nothing
|
||
|
||
Destructor for the class.
|
||
------------------------------------------------------------------------------}
|
||
destructor TCanvas.Destroy;
|
||
begin
|
||
//DebugLn('[TCanvas.Destroy] ',ClassName,' Self=',DbgS(Self));
|
||
Handle := 0;
|
||
FreeThenNil(FRegion);
|
||
FreeThenNil(FSavedHandleStates);
|
||
if FLock <> 0 then
|
||
DeleteCriticalSection(FLock);
|
||
inherited Destroy;
|
||
// set resources to nil, so that dangling pointers are spotted early
|
||
FFont:=nil;
|
||
FPen:=nil;
|
||
FBrush:=nil;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Function: TCanvas.GetHandle
|
||
Params: None
|
||
Returns: A handle to the GUI object
|
||
|
||
Checks if a handle is allocated, otherwise create it
|
||
------------------------------------------------------------------------------}
|
||
function TCanvas.GetHandle : HDC;
|
||
begin
|
||
//DebugLn('[TCanvas.GetHandle] ',ClassName);
|
||
RequiredState(csAllValid);
|
||
Result := FHandle;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.SetHandle
|
||
Params: NewHandle - the new device context
|
||
Returns: nothing
|
||
|
||
Deselect sub handles and sets the Handle
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.SetHandle(NewHandle: HDC);
|
||
begin
|
||
if FHandle = NewHandle then Exit;
|
||
|
||
//DebugLn('[TCanvas.SetHandle] Self=',DbgS(Self),' Old=',DbgS(FHandle,8),' New=',DbgS(NewHandle,8));
|
||
if FHandle <> 0 then
|
||
begin
|
||
DeselectHandles;
|
||
Exclude(FState, csHandleValid);
|
||
end;
|
||
|
||
FHandle := NewHandle;
|
||
if FHandle <> 0 then
|
||
begin
|
||
Include(FState, csHandleValid);
|
||
end;
|
||
//DebugLn('[TCanvas.SetHandle] END Self=',DbgS(Self),' Handle=',DbgS(FHandle,8));
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.DeselectHandles
|
||
Params: none
|
||
Returns: nothing
|
||
|
||
Deselect all subhandles in the current device context
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.DeselectHandles;
|
||
begin
|
||
//debugln('TCanvas.DeselectHandles ',ClassName,' Self=',DbgS(Self),' Handle=',DbgS(FHandle),' FSavedBrushHandle=',DbgS(Cardinal(FSavedBrushHandle)));
|
||
if (FHandle<>0) then begin
|
||
// select default sub handles in the device context without deleting owns
|
||
if FSavedBrushHandle<>0 then
|
||
SelectObject(FHandle,FSavedBrushHandle);
|
||
if FSavedPenHandle<>0 then
|
||
SelectObject(FHandle,FSavedPenHandle);
|
||
if FSavedFontHandle<>0 then
|
||
SelectObject(FHandle,FSavedFontHandle);
|
||
FState := FState - [csPenValid, csBrushValid, csFontValid];
|
||
end;
|
||
FSavedBrushHandle:=0;
|
||
FSavedPenHandle:=0;
|
||
FSavedFontHandle:=0;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.CreateHandle
|
||
Params: None
|
||
Returns: Nothing
|
||
|
||
Creates the handle ( = object).
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.CreateHandle;
|
||
begin
|
||
// Plain canvas does nothing
|
||
end;
|
||
|
||
procedure TCanvas.FreeHandle;
|
||
begin
|
||
Handle:=0;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Method: TCanvas.RequiredState
|
||
Params: ReqState: The required state
|
||
Returns: Nothing
|
||
|
||
Ensures that all handles needed are valid;
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.RequiredState(ReqState: TCanvasState);
|
||
var
|
||
Needed: TCanvasState;
|
||
begin
|
||
Needed := ReqState - FState;
|
||
//DebugLn('[TCanvas.RequiredState] ',ClassName,' ',csHandleValid in ReqState,' ',csHandleValid in FState,' Needed=',Needed<>[]);
|
||
if Needed <> [] then
|
||
begin
|
||
//DebugLn('[TCanvas.RequiredState] B ',ClassName,' ',csHandleValid in Needed,',',csFontValid in Needed,',',csPenValid in Needed,',',csBrushValid in Needed);
|
||
if csHandleValid in Needed then
|
||
begin
|
||
CreateHandle;
|
||
if FHandle = 0 then
|
||
raise EInvalidOperation.Create(rsCanvasDoesNotAllowDrawing);
|
||
Include(FState, csHandleValid);
|
||
end;
|
||
if csFontValid in Needed then CreateFont;
|
||
if csPenValid in Needed then
|
||
begin
|
||
CreatePen;
|
||
if Pen.Style in [psDash, psDot, psDashDot, psDashDotDot]
|
||
then Include(Needed, csBrushValid);
|
||
end;
|
||
if csBrushValid in Needed then CreateBrush;
|
||
end;
|
||
end;
|
||
|
||
procedure TCanvas.Changed;
|
||
begin
|
||
if Assigned(FOnChange) then FOnChange(Self);
|
||
end;
|
||
|
||
procedure TCanvas.SaveHandleState;
|
||
var
|
||
DCIndex: LongInt;
|
||
begin
|
||
if FSavedHandleStates=nil then FSavedHandleStates:=TFPList.Create;
|
||
DeselectHandles;
|
||
RequiredState([csHandleValid]);
|
||
DCIndex:=SaveDC(Handle);
|
||
FSavedHandleStates.Add(Pointer(PtrInt(DCIndex)));
|
||
end;
|
||
|
||
procedure TCanvas.RestoreHandleState;
|
||
var
|
||
DCIndex: LongInt;
|
||
begin
|
||
DCIndex:=integer(PtrUInt(FSavedHandleStates[FSavedHandleStates.Count-1]));
|
||
FSavedHandleStates.Delete(FSavedHandleStates.Count-1);
|
||
DeselectHandles;
|
||
RestoreDC(Handle,DCIndex);
|
||
end;
|
||
|
||
procedure TCanvas.Changing;
|
||
begin
|
||
if Assigned(FOnChanging) then FOnChanging(Self);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Function: TCanvas.TextExtent
|
||
Params: Text: The text to measure
|
||
Returns: The size
|
||
|
||
Gets the width and height of a text
|
||
------------------------------------------------------------------------------}
|
||
function TCanvas.TextExtent(const Text: string): TSize;
|
||
begin
|
||
Result.cX := 0;
|
||
Result.cY := 0;
|
||
if Text='' then exit;
|
||
RequiredState([csHandleValid, csFontValid]);
|
||
GetTextExtentPoint(FHandle, PChar(Text), Length(Text), Result);
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Function: TCanvas.TextWidth
|
||
Params: Text: The text to measure
|
||
Returns: The width
|
||
|
||
Gets the width of a text
|
||
------------------------------------------------------------------------------}
|
||
function TCanvas.TextWidth(const Text: string): Integer;
|
||
begin
|
||
Result := TextExtent(Text).cX;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Function: TCanvas.TextHeight
|
||
Params: Text: The text to measure
|
||
Returns: A handle to the GUI object
|
||
|
||
Gets the height of a text
|
||
------------------------------------------------------------------------------}
|
||
function TCanvas.TextHeight(const Text: string): Integer;
|
||
begin
|
||
Result := TextExtent(Text).cY;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Function: TCanvas.Lock
|
||
Params: none
|
||
Returns: nothing
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Lock;
|
||
begin
|
||
LockCanvas;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
Function: TCanvas.Unlock
|
||
Params: none
|
||
Returns: nothing
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Unlock;
|
||
|
||
procedure RaiseTooManyUnlock;
|
||
begin
|
||
raise Exception.Create(
|
||
'TCanvas.Unlock '+DbgSName(Self)+': too many unlocks');
|
||
end;
|
||
|
||
begin
|
||
UnlockCanvas;
|
||
end;
|
||
|
||
{------------------------------------------------------------------------------
|
||
procedure TCanvas.Refresh;
|
||
------------------------------------------------------------------------------}
|
||
procedure TCanvas.Refresh;
|
||
begin
|
||
DeselectHandles;
|
||
end;
|