clipperi.inc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. {
  2. Free Pascal port of the OpenPTC C++ library.
  3. Copyright (C) 2001-2003 Nikolay Nikolov ([email protected])
  4. Original C++ version by Glenn Fiedler ([email protected])
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. }
  17. { $INLINE ON}
  18. Class Function TPTCClipper.clip(Const _area, _clip : TPTCArea) : TPTCArea;
  19. Var
  20. left, top, right, bottom : Integer;
  21. clip_left, clip_top, clip_right, clip_bottom : Integer;
  22. Begin
  23. { get in coordinates }
  24. left := _area.left;
  25. top := _area.top;
  26. right := _area.right;
  27. bottom := _area.bottom;
  28. { get clip coordinates }
  29. clip_left := _clip.left;
  30. clip_top := _clip.top;
  31. clip_right := _clip.right;
  32. clip_bottom := _clip.bottom;
  33. { clip left }
  34. If left < clip_left Then
  35. left := clip_left;
  36. If left > clip_right Then
  37. left := clip_right;
  38. { clip top }
  39. If top < clip_top Then
  40. top := clip_top;
  41. If top > clip_bottom Then
  42. top := clip_bottom;
  43. { clip right }
  44. If right < clip_left Then
  45. right := clip_left;
  46. If right > clip_right Then
  47. right := clip_right;
  48. { clip bottom }
  49. If bottom < clip_top Then
  50. bottom := clip_top;
  51. If bottom > clip_bottom Then
  52. bottom := clip_bottom;
  53. clip := TPTCArea.Create(left, top, right, bottom);
  54. End;
  55. { clip floating point area against a floating point clip area }
  56. Procedure TPTCClipper_clip(Var left, top, right, bottom : Real;
  57. clip_left, clip_top, clip_right, clip_bottom : Real);{ Inline;}
  58. Begin
  59. { clip left }
  60. If left < clip_left Then
  61. left := clip_left;
  62. If left > clip_right Then
  63. left := clip_right;
  64. { clip top }
  65. If top < clip_top Then
  66. top := clip_top;
  67. If top > clip_bottom Then
  68. top := clip_bottom;
  69. { clip right }
  70. If right < clip_left Then
  71. right := clip_left;
  72. If right > clip_right Then
  73. right := clip_right;
  74. { clip bottom }
  75. If bottom < clip_top Then
  76. bottom := clip_top;
  77. If bottom > clip_bottom Then
  78. bottom := clip_bottom;
  79. End;
  80. { clip floating point area against clip area }
  81. Procedure TPTCClipper_clip(Var left, top, right, bottom : Real; Const _clip : TPTCArea);{ Inline;}
  82. Var
  83. clip_left, clip_top, clip_right, clip_bottom : Real;
  84. Begin
  85. { get floating point clip area }
  86. clip_left := _clip.left;
  87. clip_top := _clip.top;
  88. clip_right := _clip.right;
  89. clip_bottom := _clip.bottom;
  90. { clip floating point area against floating point clip area }
  91. TPTCClipper_clip(left, top, right, bottom, clip_left, clip_top, clip_right, clip_bottom);
  92. End;
  93. { snap a floating point area to integer coordinates }
  94. Procedure TPTCClipper_round(Var left, top, right, bottom : Real);{ Inline;}
  95. Begin
  96. left := Round(left);
  97. top := Round(top);
  98. right := Round(right);
  99. bottom := Round(bottom);
  100. End;
  101. Class Procedure TPTCClipper.clip(Const source, clip_source, clipped_source,
  102. destination, clip_destination,
  103. clipped_destination : TPTCArea);
  104. Var
  105. tmp1, tmp2 : TPTCArea;
  106. source_left, source_top, source_right, source_bottom : Real;
  107. clipped_source_left, clipped_source_top, clipped_source_right,
  108. clipped_source_bottom : Real;
  109. source_delta_left, source_delta_top, source_delta_right,
  110. source_delta_bottom : Real;
  111. source_to_destination_x, source_to_destination_y : Real;
  112. destination_left, destination_top, destination_right,
  113. destination_bottom : Real;
  114. adjusted_destination_left, adjusted_destination_top,
  115. adjusted_destination_right, adjusted_destination_bottom : Real;
  116. clipped_destination_left, clipped_destination_top,
  117. clipped_destination_right, clipped_destination_bottom : Real;
  118. destination_delta_left, destination_delta_top, destination_delta_right,
  119. destination_delta_bottom : Real;
  120. destination_to_source_x, destination_to_source_y : Real;
  121. adjusted_source_left, adjusted_source_top, adjusted_source_right,
  122. adjusted_source_bottom : Real;
  123. Begin
  124. tmp1 := Nil;
  125. tmp2 := Nil;
  126. Try
  127. { expand source area to floating point }
  128. source_left := source.left;
  129. source_top := source.top;
  130. source_right := source.right;
  131. source_bottom := source.bottom;
  132. { setup clipped source area }
  133. clipped_source_left := source_left;
  134. clipped_source_top := source_top;
  135. clipped_source_right := source_right;
  136. clipped_source_bottom := source_bottom;
  137. { perform clipping on floating point source area }
  138. TPTCClipper_clip(clipped_source_left, clipped_source_top, clipped_source_right,
  139. clipped_source_bottom, clip_source);
  140. { check for early source area clipping exit }
  141. If (clipped_source_left = clipped_source_right) Or
  142. (clipped_source_top = clipped_source_bottom) Then
  143. Begin
  144. { clipped area is zero }
  145. tmp1 := TPTCArea.Create(0, 0, 0, 0);
  146. clipped_source.ASSign(tmp1);
  147. clipped_destination.ASSign(tmp1);
  148. Exit;
  149. End;
  150. { calculate deltas in source clip }
  151. source_delta_left := clipped_source_left - source_left;
  152. source_delta_top := clipped_source_top - source_top;
  153. source_delta_right := clipped_source_right - source_right;
  154. source_delta_bottom := clipped_source_bottom - source_bottom;
  155. { calculate ratio of source area to destination area }
  156. source_to_destination_x := destination.width / source.width;
  157. source_to_destination_y := destination.height / source.height;
  158. { expand destination area to floating point }
  159. destination_left := destination.left;
  160. destination_top := destination.top;
  161. destination_right := destination.right;
  162. destination_bottom := destination.bottom;
  163. { calculate adjusted destination area }
  164. adjusted_destination_left := destination_left + source_delta_left * source_to_destination_x;
  165. adjusted_destination_top := destination_top + source_delta_top * source_to_destination_y;
  166. adjusted_destination_right := destination_right + source_delta_right * source_to_destination_x;
  167. adjusted_destination_bottom := destination_bottom + source_delta_bottom * source_to_destination_y;
  168. { setup clipped destination area }
  169. clipped_destination_left := adjusted_destination_left;
  170. clipped_destination_top := adjusted_destination_top;
  171. clipped_destination_right := adjusted_destination_right;
  172. clipped_destination_bottom := adjusted_destination_bottom;
  173. { perform clipping on floating point destination area }
  174. TPTCClipper_clip(clipped_destination_left, clipped_destination_top,
  175. clipped_destination_right, clipped_destination_bottom, clip_destination);
  176. { check for early destination area clipping exit }
  177. If (clipped_destination_left = clipped_destination_right) Or
  178. (clipped_destination_top = clipped_destination_bottom)
  179. Then
  180. Begin
  181. { clipped area is zero }
  182. tmp1 := TPTCArea.Create(0, 0, 0, 0);
  183. clipped_source.ASSign(tmp1);
  184. clipped_destination.ASSign(tmp1);
  185. Exit;
  186. End;
  187. { calculate deltas in destination clip }
  188. destination_delta_left := clipped_destination_left - adjusted_destination_left;
  189. destination_delta_top := clipped_destination_top - adjusted_destination_top;
  190. destination_delta_right := clipped_destination_right - adjusted_destination_right;
  191. destination_delta_bottom := clipped_destination_bottom - adjusted_destination_bottom;
  192. { calculate ratio of destination area to source area }
  193. destination_to_source_x := 1 / source_to_destination_x;
  194. destination_to_source_y := 1 / source_to_destination_y;
  195. { calculate adjusted source area }
  196. adjusted_source_left := clipped_source_left + destination_delta_left * destination_to_source_x;
  197. adjusted_source_top := clipped_source_top + destination_delta_top * destination_to_source_y;
  198. adjusted_source_right := clipped_source_right + destination_delta_right * destination_to_source_x;
  199. adjusted_source_bottom := clipped_source_bottom + destination_delta_bottom * destination_to_source_y;
  200. { assign adjusted source to clipped source }
  201. clipped_source_left := adjusted_source_left;
  202. clipped_source_top := adjusted_source_top;
  203. clipped_source_right := adjusted_source_right;
  204. clipped_source_bottom := adjusted_source_bottom;
  205. { round clipped areas to integer coordinates }
  206. TPTCClipper_round(clipped_source_left, clipped_source_top,
  207. clipped_source_right, clipped_source_bottom);
  208. TPTCClipper_round(clipped_destination_left, clipped_destination_top,
  209. clipped_destination_right, clipped_destination_bottom);
  210. { construct clipped area rectangles from rounded floating point areas }
  211. tmp1 := TPTCArea.Create(Trunc(clipped_source_left),
  212. Trunc(clipped_source_top),
  213. Trunc(clipped_source_right),
  214. Trunc(clipped_source_bottom));
  215. tmp2 := TPTCArea.Create(Trunc(clipped_destination_left),
  216. Trunc(clipped_destination_top),
  217. Trunc(clipped_destination_right),
  218. Trunc(clipped_destination_bottom));
  219. clipped_source.ASSign(tmp1);
  220. clipped_destination.ASSign(tmp2);
  221. Finally
  222. tmp1.Free;
  223. tmp2.Free;
  224. End;
  225. End;