/packages/fcl-image/src/clipping.pp
https://github.com/slibre/freepascal · Puppet · 218 lines · 202 code · 16 blank · 0 comment · 37 complexity · c3b255a2ed2a2c6dc4a1138c0f341ac6 MD5 · raw file
- {
- This file is part of the Free Pascal run time library.
- Copyright (c) 2003 by the Free Pascal development team
- Clipping support.
- 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.
- **********************************************************************}
- {$mode objfpc}{$h+}
- unit Clipping;
- interface
- uses classes;
- procedure SortRect (var rect : TRect);
- procedure SortRect (var left,top, right,bottom : integer);
- function PointInside (const x,y:integer; bounds:TRect) : boolean;
- procedure CheckRectClipping (ClipRect:TRect; var Rect:Trect);
- procedure CheckRectClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
- procedure CheckLineClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
- implementation
- procedure SortRect (var rect : TRect);
- begin
- with rect do
- SortRect (left,top, right,bottom);
- end;
- procedure SortRect (var left,top, right,bottom : integer);
- var r : integer;
- begin
- if left > right then
- begin
- r := left;
- left := right;
- right := r;
- end;
- if top > bottom then
- begin
- r := top;
- top := bottom;
- bottom := r;
- end;
- end;
- function PointInside (const x,y:integer; bounds:TRect) : boolean;
- begin
- SortRect (bounds);
- with Bounds do
- result := (x >= left) and (x <= right) and
- (y >= bottom) and (y <= top);
- end;
- procedure CheckRectClipping (ClipRect:TRect; var Rect:Trect);
- begin
- with ClipRect do
- CheckRectClipping (ClipRect, left,top,right,bottom);
- end;
- procedure CheckRectClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
- procedure ClearRect;
- begin
- x1 := -1;
- x2 := -1;
- y1 := -1;
- y2 := -1;
- end;
- begin
- SortRect (ClipRect);
- SortRect (x1,y1, x2,y2);
- with ClipRect do
- begin
- if ( x1 < Left ) then // left side needs to be clipped
- x1 := left;
- if ( x2 > right ) then // right side needs to be clipped
- x2 := right;
- if ( y1 < top ) then // top side needs to be clipped
- y1 := top;
- if ( y2 > bottom ) then // bottom side needs to be clipped
- y2 := bottom;
- if (x1 > x2) or (y1 < y2) then
- ClearRect;
- end;
- end;
- procedure CheckLineClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
- var a,b : single;
- Calculated : boolean;
- xdiff,n : integer;
- procedure CalcLine;
- begin
- if not Calculated then
- begin
- xdiff := (x1-x2);
- a := (y1-y2) / xdiff;
- b := (x1*y2 - x2*y1) / xdiff;
- Calculated := true;
- end;
- end;
- procedure ClearLine;
- begin
- x1 := -1;
- y1 := -1;
- x2 := -1;
- y2 := -1;
- end;
- begin
- Calculated := false;
- SortRect (ClipRect);
- xdiff := (x1-x2);
- with ClipRect do
- if xdiff = 0 then
- begin // vertical line
- if y1 > bottom then
- y1 := bottom
- else if y1 < top then
- y1 := top;
- if y2 > bottom then
- y2 := bottom
- else if y2 < top then
- y2 := top;
- end
- else if (y1-y2) = 0 then
- begin // horizontal line
- if x1 < left then
- x1 := left
- else if x1 > right then
- x1 := right;
- if x2 < left then
- x2 := left
- else if x2 > right then
- x2 := right;
- end
- else
- if ( (y1 < top) and (y2 < top) ) or
- ( (y1 > bottom) and (y2 > bottom) ) or
- ( (x1 > right) and (x2 > right) ) or
- ( (x1 < left) and (x2 < left) ) then
- ClearLine // completely outside ClipRect
- else
- begin
- if (y1 < top) or (y2 < top) then
- begin
- CalcLine;
- n := round ((top - b) / a);
- if (n >= left) and (n <= right) then
- if (y1 < top) then
- begin
- x1 := n;
- y1 := top;
- end
- else
- begin
- x2 := n;
- y2 := top;
- end;
- end;
- if (y1 > bottom) or (y2 > bottom) then
- begin
- CalcLine;
- n := round ((bottom - b) / a);
- if (n >= left) and (n <= right) then
- if (y1 > bottom) then
- begin
- x1 := n;
- y1 := bottom;
- end
- else
- begin
- x2 := n;
- y2 := bottom;
- end;
- end;
- if (x1 < left) or (x2 < left) then
- begin
- CalcLine;
- n := round ((left * a) + b);
- if (n <= bottom) and (n >= top) then
- if (x1 < left) then
- begin
- x1 := left;
- y1 := n;
- end
- else
- begin
- x2 := left;
- y2 := n;
- end;
- end;
- if (x1 > right) or (x2 > right) then
- begin
- CalcLine;
- n := round ((right * a) + b);
- if (n <= bottom) and (n >= top) then
- if (x1 > right) then
- begin
- x1 := right;
- y1 := n;
- end
- else
- begin
- x2 := right;
- y2 := n;
- end;
- end;
- end;
- end;
- end.