PageRenderTime 27ms CodeModel.GetById 13ms app.highlight 13ms RepoModel.GetById 0ms app.codeStats 0ms

/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
Possible License(s): LGPL-2.0, LGPL-2.1, LGPL-3.0
  1{
  2    This file is part of the Free Pascal run time library.
  3    Copyright (c) 2003 by the Free Pascal development team
  4
  5    Clipping support.
  6
  7    See the file COPYING.FPC, included in this distribution,
  8    for details about the copyright.
  9
 10    This program is distributed in the hope that it will be useful,
 11    but WITHOUT ANY WARRANTY; without even the implied warranty of
 12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 13
 14 **********************************************************************}
 15{$mode objfpc}{$h+}
 16unit Clipping;
 17
 18interface
 19
 20uses classes;
 21
 22procedure SortRect (var rect : TRect);
 23procedure SortRect (var left,top, right,bottom : integer);
 24function PointInside (const x,y:integer; bounds:TRect) : boolean;
 25
 26procedure CheckRectClipping (ClipRect:TRect; var Rect:Trect);
 27procedure CheckRectClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
 28procedure CheckLineClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
 29
 30implementation
 31
 32procedure SortRect (var rect : TRect);
 33begin
 34  with rect do
 35    SortRect (left,top, right,bottom);
 36end;
 37
 38procedure SortRect (var left,top, right,bottom : integer);
 39var r : integer;
 40begin
 41  if left > right then
 42    begin
 43    r := left;
 44    left := right;
 45    right := r;
 46    end;
 47  if top > bottom then
 48    begin
 49    r := top;
 50    top := bottom;
 51    bottom := r;
 52    end;
 53end;
 54
 55function PointInside (const x,y:integer; bounds:TRect) : boolean;
 56begin
 57  SortRect (bounds);
 58  with Bounds do
 59    result := (x >= left) and (x <= right) and
 60              (y >= bottom) and (y <= top);
 61end;
 62
 63procedure CheckRectClipping (ClipRect:TRect; var Rect:Trect);
 64begin
 65  with ClipRect do
 66    CheckRectClipping (ClipRect, left,top,right,bottom);
 67end;
 68
 69procedure CheckRectClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
 70  procedure ClearRect;
 71  begin
 72    x1 := -1;
 73    x2 := -1;
 74    y1 := -1;
 75    y2 := -1;
 76  end;
 77begin
 78  SortRect (ClipRect);
 79  SortRect (x1,y1, x2,y2);
 80  with ClipRect do
 81    begin
 82    if ( x1 < Left ) then // left side needs to be clipped
 83      x1 := left;
 84    if ( x2 > right ) then // right side needs to be clipped
 85      x2 := right;
 86    if ( y1 < top ) then // top side needs to be clipped
 87      y1 := top;
 88    if ( y2 > bottom ) then // bottom side needs to be clipped
 89      y2 := bottom;
 90    if (x1 > x2) or (y1 < y2) then
 91      ClearRect;
 92    end;
 93end;
 94
 95procedure CheckLineClipping (ClipRect:TRect; var x1,y1, x2,y2 : integer);
 96var a,b : single;
 97    Calculated : boolean;
 98    xdiff,n : integer;
 99  procedure CalcLine;
100    begin
101    if not Calculated then
102      begin
103      xdiff := (x1-x2);
104      a := (y1-y2) / xdiff;
105      b := (x1*y2 - x2*y1) / xdiff;
106      Calculated := true;
107      end;
108    end;
109  procedure ClearLine;
110    begin
111    x1 := -1;
112    y1 := -1;
113    x2 := -1;
114    y2 := -1;
115    end;
116begin
117  Calculated := false;
118  SortRect (ClipRect);
119  xdiff := (x1-x2);
120  with ClipRect do
121    if xdiff = 0 then
122      begin  // vertical line
123      if y1 > bottom then
124        y1 := bottom
125      else if y1 < top then
126        y1 := top;
127      if y2 > bottom then
128        y2 := bottom
129      else if y2 < top then
130        y2 := top;
131      end
132    else if (y1-y2) = 0 then
133      begin  // horizontal line
134      if x1 < left then
135        x1 := left
136      else if x1 > right then
137        x1 := right;
138      if x2 < left then
139        x2 := left
140      else if x2 > right then
141        x2 := right;
142      end
143    else
144      if ( (y1 < top) and (y2 < top) ) or
145         ( (y1 > bottom) and (y2 > bottom) ) or
146         ( (x1 > right) and (x2 > right) ) or
147         ( (x1 < left) and (x2 < left) ) then
148        ClearLine // completely outside ClipRect
149      else
150        begin
151        if (y1 < top) or (y2 < top) then
152          begin
153          CalcLine;
154          n := round ((top - b) / a);
155          if (n >= left) and (n <= right) then
156            if (y1 < top) then
157              begin
158              x1 := n;
159              y1 := top;
160              end
161            else
162              begin
163              x2 := n;
164              y2 := top;
165              end;
166          end;
167        if (y1 > bottom) or (y2 > bottom) then
168          begin
169          CalcLine;
170          n := round ((bottom - b) / a);
171          if (n >= left) and (n <= right) then
172            if (y1 > bottom) then
173              begin
174              x1 := n;
175              y1 := bottom;
176              end
177            else
178              begin
179              x2 := n;
180              y2 := bottom;
181              end;
182          end;
183        if (x1 < left) or (x2 < left) then
184          begin
185          CalcLine;
186          n := round ((left * a) + b);
187          if (n <= bottom) and (n >= top) then
188            if (x1 < left) then
189              begin
190              x1 := left;
191              y1 := n;
192              end
193            else
194              begin
195              x2 := left;
196              y2 := n;
197              end;
198          end;
199        if (x1 > right) or (x2 > right) then
200          begin
201          CalcLine;
202          n := round ((right * a) + b);
203          if (n <= bottom) and (n >= top) then
204            if (x1 > right) then
205              begin
206              x1 := right;
207              y1 := n;
208              end
209            else
210              begin
211              x2 := right;
212              y2 := n;
213              end;
214          end;
215        end;
216end;
217
218end.