/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

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