123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607 |
- {%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;
|