fpc/fcl/image/fpcanvas.inc
michael cf95b53b8f Fix for bug #4218
git-svn-id: trunk@744 -
2005-07-25 14:58:53 +00:00

608 lines
13 KiB
PHP

{%MainUnit fpcanvas.pp}
{
This file is part of the Free Pascal run time library.
Copyright (c) 2003 by the Free Pascal development team
TFPCustomCanvas implementation.
See the file COPYING.FPC, 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.
**********************************************************************}
{ TFPCustomCanvas }
constructor TFPCustomCanvas.Create;
begin
inherited create;
FClipRect := Rect(-1,-1,-1,-1);
FClipping := false;
FRemovingHelpers := false;
FHelpers := TList.Create;
FDefaultFont := CreateDefaultFont;
FDefaultPen := CreateDefaultPen;
FDefaultBrush := CreateDefaultBrush;
end;
destructor TFPCustomCanvas.Destroy;
begin
FRemovingHelpers := True;
// first remove all helper references
RemoveHelpers;
// then free helpers
FDefaultFont.Free;
FDefaultBrush.Free;
FDefaultPen.Free;
FHelpers.Free;
FRemovingHelpers := False;
inherited;
end;
procedure TFPCustomCanvas.CheckHelper (AHelper:TFPCanvasHelper);
// remove references to AHelper
begin
if AHelper = FPen then
FPen := nil
else if AHelper = FFont then
FFont := nil
else if AHelper = FBrush then
FBrush := nil;
if not FRemovingHelpers then
begin
if AHelper = FDefaultFont then
FDefaultFont := CreateDefaultFont
else if AHelper = FDefaultPen then
FDefaultPen := CreateDefaultPen
else if AHelper = FDefaultBrush then
FDefaultBrush := CreateDefaultBrush;
end;
FHelpers.Remove (AHelper);
end;
procedure TFPCustomCanvas.RemoveHelpers;
var r : integer;
OldState : boolean;
begin
for r := FHelpers.count-1 downto 0 do
with TFPCanvasHelper(FHelpers[r]) do
if FCanvas = self then
if FFixedCanvas then
DeallocateResources
else
FCanvas := nil;
FHelpers.Clear;
end;
procedure TFPCustomCanvas.AddHelper (AHelper : TFPCanvasHelper);
var r : integer;
begin
r := FHelpers.IndexOf (AHelper);
if r < 0 then
FHelpers.Add (AHelper);
end;
function TFPCustomCanvas.CreateDefaultFont : TFPCustomFont;
begin
result := DoCreateDefaultFont;
if not assigned (result) then
raise TFPCanvasException.CreateFmt (ErrCouldNotCreate, [EPen])
else
begin
result.AllocateResources (self);
FHelpers.Add (result);
end;
end;
function TFPCustomCanvas.CreateDefaultPen : TFPCustomPen;
begin
result := DoCreateDefaultPen;
if not assigned (result) then
raise TFPCanvasException.CreateFmt (ErrCouldNotCreate, [EPen])
else
begin
result.AllocateResources (self);
FHelpers.Add (result);
end;
end;
function TFPCustomCanvas.CreateDefaultBrush : TFPCustomBrush;
begin
result := DoCreateDefaultBrush;
if not assigned (result) then
raise TFPCanvasException.CreateFmt (ErrCouldNotCreate, [EPen])
else
begin
result.AllocateResources (self);
FHelpers.Add (result);
end;
end;
function TFPCustomCanvas.GetClipRect: TRect;
begin
Result:=FClipRect;
end;
function TFPCustomCanvas.CreateFont : TFPCustomFont;
begin
result := DoCreateDefaultFont;
end;
function TFPCustomCanvas.CreatePen : TFPCustomPen;
begin
result := DoCreateDefaultPen;
end;
function TFPCustomCanvas.CreateBrush : TFPCustomBrush;
begin
result := DoCreateDefaultBrush;
end;
function TFPCustomCanvas.AllowFont (AFont : TFPCustomFont) : boolean;
begin
if AFont is TFPCustomDrawFont then
result := true
else
result := DoAllowFont (AFont);
end;
procedure TFPCustomCanvas.SetFont (AValue:TFPCustomFont);
begin
if (AValue <> FFont) and AllowFont(AValue) then
begin
if FManageResources then
FFont.Assign(AValue)
else
begin
AValue.AllocateResources (self);
FFont := AValue;
AddHelper (AValue);
end;
end;
end;
function TFPCustomCanvas.GetFont : TFPCustomFont;
begin
if assigned (FFont) then
result := FFont
else
result := FDefaultFont;
end;
function TFPCustomCanvas.DoAllowFont (AFont : TFPCustomFont) : boolean;
begin
result := false;
end;
function TFPCustomCanvas.AllowBrush (ABrush : TFPCustomBrush) : boolean;
begin
if ABrush is TFPCustomDrawBrush then
result := true
else
result := DoAllowBrush (ABrush);
end;
procedure TFPCustomCanvas.SetBrush (AValue:TFPCustomBrush);
begin
if (AValue <> FBrush) and AllowBrush(AValue) then
begin
if FManageResources then
FBrush.Assign(AValue)
else
begin
AValue.AllocateResources (self);
FBrush := AValue;
AddHelper (AValue);
end;
end;
end;
function TFPCustomCanvas.GetBrush : TFPCustomBrush;
begin
if assigned (FBrush) then
result := FBrush
else
result := FDefaultBrush
end;
function TFPCustomCanvas.DoAllowBrush (ABrush : TFPCustomBrush) : boolean;
begin
result := false;
end;
function TFPCustomCanvas.AllowPen (APen : TFPCustomPen) : boolean;
begin
if APen is TFPCustomDrawPen then
result := true
else
result := DoAllowPen (APen);
end;
procedure TFPCustomCanvas.SetPen (AValue:TFPCustomPen);
begin
if (AValue <> FPen) and AllowPen (AValue) then
begin
if FManageResources then
FPen.Assign(AValue)
else
begin
AValue.AllocateResources (self);
FPen := AValue;
AddHelper (AValue);
end;
end;
end;
function TFPCustomCanvas.GetPen : TFPCustomPen;
begin
if assigned (FPen) then
result := FPen
else
result := FDefaultPen;
end;
procedure TFPCustomCanvas.SetClipRect(const AValue: TRect);
begin
FClipRect:=AValue;
end;
procedure TFPCustomCanvas.SetPenPos(const AValue: TPoint);
begin
FPenPos:=AValue;
end;
function TFPCustomCanvas.DoAllowPen (APen : TFPCustomPen) : boolean;
begin
result := false;
end;
procedure TFPCustomCanvas.DoLockCanvas;
begin
end;
procedure TFPCustomCanvas.DoUnlockCanvas;
begin
end;
procedure TFPCustomCanvas.LockCanvas;
begin
if FLocks = 0 then
DoLockCanvas;
inc (FLocks);
end;
procedure TFPCustomCanvas.UnlockCanvas;
begin
if FLocks > 0 then
begin
dec (FLocks);
if FLocks = 0 then
DoUnlockCanvas;
end
else
raise TFPCanvasException.Create (ErrNoLock);
end;
function TFPCustomCanvas.Locked: boolean;
begin
Result:=FLocks>0;
end;
procedure TFPCustomCanvas.TextOut (x,y:integer;text:string);
begin
if Font is TFPCustomDrawFont then
TFPCustomDrawFont(Font).DrawText(x,y, text)
else
DoTextOut (x,y, text);
end;
procedure TFPCustomCanvas.GetTextSize (text:string; var w,h:integer);
begin
if Font is TFPCustomDrawFont then
TFPCustomDrawFont(Font).GetTextSize (text, w, h)
else
DoGetTextSize (Text, w, h);
end;
function TFPCustomCanvas.GetTextHeight (text:string) : integer;
begin
if Font is TFPCustomDrawFont then
result := TFPCustomDrawFont(Font).GetTextHeight (text)
else
result := DoGetTextHeight (Text);
end;
function TFPCustomCanvas.GetTextWidth (text:string) : integer;
begin
if Font is TFPCustomDrawFont then
result := TFPCustomDrawFont(Font).GetTextWidth (text)
else
result := DoGetTextWidth (Text);
end;
procedure TFPCustomCanvas.DoMoveTo (x,y:integer);
begin
end;
procedure TFPCustomCanvas.DoLineTo (x,y:integer);
begin
DoLine (FPenPos.X,FPenPos.y, x,y);
end;
procedure TFPCustomCanvas.MoveTo (x,y:integer);
begin
FPenPos.x := x;
FPenPos.y := y;
DoMoveTo (x,y);
end;
procedure TFPCustomCanvas.MoveTo (p:TPoint);
begin
FPenPos := p;
DoMoveTo (p.x,p.y);
end;
procedure TFPCustomCanvas.LineTo (x,y:integer);
begin
if Pen.Style <> psClear then
if Pen is TFPCustomDrawPen then
TFPCustomDrawPen(Pen).DrawLine (FPenPos.x, FPenPos.y, x, y)
else
DoLineTo (x,y);
FPenPos.x := x;
FPenPos.y := y;
end;
procedure TFPCustomCanvas.LineTo (p:TPoint);
begin
LineTo (p.x, p.y);
end;
procedure TFPCustomCanvas.Line (x1,y1,x2,y2:integer);
begin
if Pen.Style <> psClear then
if Pen is TFPCustomDrawPen then
TFPCustomDrawPen(Pen).DrawLine (x1,y1, x2,y2)
else
DoLine (x1,y1, x2,y2);
FPenPos.x := x2;
FPenPos.y := y2;
end;
procedure TFPCustomCanvas.Line (const p1,p2:TPoint);
begin
Line (p1.x,p1.y,p2.x,p2.y);
end;
procedure TFPCustomCanvas.Line (const points:TRect);
begin
with points do
Line (left,top, right,bottom);
end;
procedure TFPCustomCanvas.Polyline (Const points:array of TPoint);
begin
if Pen.Style <> psClear then
if Pen is TFPCustomDrawPen then
TFPCustomDrawPen(Pen).Polyline (points,false)
else
DoPolyline (points);
FPenPos := points[high(points)];
end;
procedure TFPCustomCanvas.Clear;
var r : TRect;
begin
if Brush.Style <> bsClear then
begin
if Brush is TFPCustomDrawBrush then
TFPCustomDrawBrush(Brush).Rectangle(0,0, width, height)
else
begin
r := Rect(0,0, width, height);
DoRectangleFill (r);
end;
end;
end;
procedure TFPCustomCanvas.Erase;
var
x,y:Integer;
begin
for x:=0 to Width-1 do
for y:=0 to Height-1 do
Colors[x,y]:=colTransparent;
end;
procedure TFPCustomCanvas.DoRectangleAndFill (const Bounds:TRect);
begin
DoRectangleFill (Bounds);
DoRectangle (Bounds);
end;
procedure TFPCustomCanvas.DoEllipseAndFill (const Bounds:TRect);
begin
DoEllipseFill (Bounds);
DoEllipse (Bounds);
end;
procedure TFPCustomCanvas.DoPolygonAndFill (const points:array of TPoint);
begin
DoPolygonFill (points);
DoPolygon (points);
end;
procedure TFPCustomCanvas.Ellipse (const Bounds:TRect);
var p,b,dp,db,pb : boolean;
begin
p := Pen.style <> psClear;
b := Brush.style <> bsClear;
pb := false;
dp:=False;
db:=False;
if p and (Pen is TFPCustomDrawPen) then
begin
p := false;
dp := true;
end;
if b and (Brush is TFPCustomDrawBrush) then
begin
b := false;
db := true;
end;
if p and b then
begin
p := false;
b := false;
pb := true;
end;
if pb then
DoEllipseAndFill (bounds)
else
begin
if p then
DoEllipse (bounds)
else if dp then
with bounds do
TFPCustomDrawPen(Pen).Ellipse (left,top,right,bottom);
if b then
DoEllipseFill (bounds)
else if db then
with bounds do
TFPCustomDrawBrush(Brush).Ellipse (left,top,right,bottom);
end;
end;
procedure TFPCustomCanvas.Ellipse (left,top,right,bottom:integer);
begin
Ellipse (Rect(left,top,right,bottom));
end;
procedure TFPCustomCanvas.EllipseC (x,y:integer; rx,ry:longword);
begin
Ellipse (Rect(x-rx,y-ry,x+rx,y+ry));
end;
procedure TFPCustomCanvas.Rectangle (left,top,right,bottom:integer);
begin
Rectangle (Rect(left,top,right,bottom));
end;
procedure TFPCustomCanvas.Rectangle (const Bounds:TRect);
var np,nb,dp,db,pb : boolean;
begin
np:= Pen.style <> psClear; // Need pen ?
nb:= Brush.style <> bsClear; // Need brush ?
dp:=(pen is TFPCustomDrawPen); // Pen draws ?
db:=(brush is TFPCustomDrawBrush); // Brush draws ?
if (np and nb) and not (db or db) then
DoRectangleAndFill (bounds)
else
begin
if np then
begin
If not dp then
DoRectangle (bounds)
else
with bounds do
TFPCustomDrawPen(Pen).Rectangle (left,top,right,bottom);
end;
if Nb then
begin
if not db then
DoRectangleFill (bounds)
else
with bounds do
TFPCustomDrawBrush(Brush).Rectangle (left,top,right,bottom);
end;
end;
end;
procedure TFPCustomCanvas.FloodFill (x,y:integer);
begin
if Brush.Style <> bsClear then
begin
if Brush is TFPCustomDrawBrush then
TFPCustomDrawBrush (Brush).FloodFill (x,y)
else
DoFloodFill (x,y);
end;
end;
procedure TFPCustomCanvas.Polygon (const points:array of TPoint);
var p,b,dp,db,pb : boolean;
begin
p := Pen.style <> psClear;
b := Brush.style <> bsClear;
dp:=false;
db:=false;
pb:=False;
if p and (pen is TFPCustomDrawPen) then
begin
p := false;
dp := true;
end;
if b and (brush is TFPCustomDrawBrush) then
begin
b := false;
db := true;
end;
if p and b then
begin
p := false;
b := false;
pb := true;
end;
if pb then
DoPolygonAndFill (points)
else
begin
if p then
DoPolygon (points)
else if dp then
TFPCustomDrawPen(Pen).Polyline (points, true);
if b then
DoPolygonFill (points)
else if db then
TFPCustomDrawBrush(Brush).Polygon (points);
end;
end;
procedure TFPCustomCanvas.CopyRect (x,y:integer; canvas:TFPCustomCanvas;
SourceRect:TRect);
var xx,r,t : integer;
begin
SortRect (SourceRect);
with SourceRect do
for r := left to right do
begin
xx := r - left + x;
for t := bottom to top do
colors[xx,(t - bottom + y)] := canvas.colors[r,t];
end;
end;
procedure TFPCustomCanvas.Draw (x,y:integer; image:TFPCustomImage);
var xx,xi,yi,xm,ym,r,t : integer;
begin
xm := x + image.width-1;
if xm >= width then
xm := width - 1;
ym := y + image.height-1;
if ym >= height then
ym := height - 1;
xi := x;
yi := y;
if clipping then
CheckRectClipping (ClipRect, xi,yi, xm,ym);
for r := xi to xm do
begin
xx := r - x;
for t := yi to ym do
colors [r,t] := image.colors[xx,t-y];
end;
end;