You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Region.cxx 6.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. *
  3. * This is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License as published by
  5. * the Free Software Foundation; either version 2 of the License, or
  6. * (at your option) any later version.
  7. *
  8. * This software is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU General Public License
  14. * along with this software; if not, write to the Free Software
  15. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  16. * USA.
  17. */
  18. // Cross-platform Region class based on the X11 region implementation. Note
  19. // that for efficiency this code manipulates the Xlib region structure
  20. // directly. Apart from the layout of the structure, there is one other key
  21. // assumption made: a Region returned from XCreateRegion must always have its
  22. // rects member allocated so that there is space for at least one rectangle.
  23. //
  24. #include <rfb/Region.h>
  25. #include <assert.h>
  26. #include <stdio.h>
  27. extern "C" {
  28. #include <Xregion/Xlibint.h>
  29. #include <Xregion/Xutil.h>
  30. #include <Xregion/Xregion.h>
  31. }
  32. // A _RectRegion must never be passed as a return parameter to the Xlib region
  33. // operations. This is because for efficiency its "rects" member has not been
  34. // allocated with Xmalloc. It is however safe to pass it as an input
  35. // parameter.
  36. class _RectRegion {
  37. public:
  38. _RectRegion(const rfb::Rect& r) {
  39. region.rects = &region.extents;
  40. region.numRects = 1;
  41. region.extents.x1 = r.tl.x;
  42. region.extents.y1 = r.tl.y;
  43. region.extents.x2 = r.br.x;
  44. region.extents.y2 = r.br.y;
  45. region.size = 1;
  46. if (r.is_empty())
  47. region.numRects = 0;
  48. }
  49. REGION region;
  50. };
  51. rfb::Region::Region() {
  52. xrgn = XCreateRegion();
  53. assert(xrgn);
  54. }
  55. rfb::Region::Region(const Rect& r) {
  56. xrgn = XCreateRegion();
  57. assert(xrgn);
  58. reset(r);
  59. }
  60. rfb::Region::Region(const rfb::Region& r) {
  61. xrgn = XCreateRegion();
  62. assert(xrgn);
  63. XUnionRegion(xrgn, r.xrgn, xrgn);
  64. }
  65. rfb::Region::~Region() {
  66. XDestroyRegion(xrgn);
  67. }
  68. rfb::Region& rfb::Region::operator=(const rfb::Region& r) {
  69. clear();
  70. XUnionRegion(xrgn, r.xrgn, xrgn);
  71. return *this;
  72. }
  73. void rfb::Region::clear() {
  74. xrgn->numRects = 0;
  75. xrgn->extents.x1 = 0;
  76. xrgn->extents.y1 = 0;
  77. xrgn->extents.x2 = 0;
  78. xrgn->extents.y2 = 0;
  79. }
  80. void rfb::Region::reset(const Rect& r) {
  81. if (r.is_empty()) {
  82. clear();
  83. } else {
  84. xrgn->numRects = 1;
  85. xrgn->rects[0].x1 = xrgn->extents.x1 = r.tl.x;
  86. xrgn->rects[0].y1 = xrgn->extents.y1 = r.tl.y;
  87. xrgn->rects[0].x2 = xrgn->extents.x2 = r.br.x;
  88. xrgn->rects[0].y2 = xrgn->extents.y2 = r.br.y;
  89. }
  90. }
  91. void rfb::Region::translate(const Point& delta) {
  92. XOffsetRegion(xrgn, delta.x, delta.y);
  93. }
  94. void rfb::Region::setOrderedRects(const std::vector<Rect>& rects) {
  95. clear();
  96. std::vector<Rect>::const_iterator i;
  97. for (i=rects.begin(); i != rects.end(); i++) {
  98. _RectRegion rr(*i);
  99. XUnionRegion(xrgn, &rr.region, xrgn);
  100. }
  101. }
  102. void rfb::Region::setExtentsAndOrderedRects(const ShortRect* extents,
  103. int nRects, const ShortRect* rects)
  104. {
  105. if (xrgn->size < nRects)
  106. {
  107. BOX* prevRects = xrgn->rects;
  108. xrgn->rects = (BOX*)Xrealloc((char*)xrgn->rects, nRects * sizeof(BOX));
  109. if (!xrgn->rects) {
  110. fprintf(stderr,"Xrealloc failed\n");
  111. Xfree(prevRects);
  112. return;
  113. }
  114. xrgn->size = nRects;
  115. }
  116. xrgn->numRects = nRects;
  117. xrgn->extents.x1 = extents->x1;
  118. xrgn->extents.y1 = extents->y1;
  119. xrgn->extents.x2 = extents->x2;
  120. xrgn->extents.y2 = extents->y2;
  121. for (int i = 0; i < nRects; i++) {
  122. xrgn->rects[i].x1 = rects[i].x1;
  123. xrgn->rects[i].y1 = rects[i].y1;
  124. xrgn->rects[i].x2 = rects[i].x2;
  125. xrgn->rects[i].y2 = rects[i].y2;
  126. }
  127. }
  128. void rfb::Region::assign_intersect(const rfb::Region& r) {
  129. XIntersectRegion(xrgn, r.xrgn, xrgn);
  130. }
  131. void rfb::Region::assign_union(const rfb::Region& r) {
  132. XUnionRegion(xrgn, r.xrgn, xrgn);
  133. }
  134. void rfb::Region::assign_subtract(const rfb::Region& r) {
  135. XSubtractRegion(xrgn, r.xrgn, xrgn);
  136. }
  137. rfb::Region rfb::Region::intersect(const rfb::Region& r) const {
  138. rfb::Region ret;
  139. XIntersectRegion(xrgn, r.xrgn, ret.xrgn);
  140. return ret;
  141. }
  142. rfb::Region rfb::Region::union_(const rfb::Region& r) const {
  143. rfb::Region ret;
  144. XUnionRegion(xrgn, r.xrgn, ret.xrgn);
  145. return ret;
  146. }
  147. rfb::Region rfb::Region::subtract(const rfb::Region& r) const {
  148. rfb::Region ret;
  149. XSubtractRegion(xrgn, r.xrgn, ret.xrgn);
  150. return ret;
  151. }
  152. bool rfb::Region::equals(const rfb::Region& r) const {
  153. return XEqualRegion(xrgn, r.xrgn);
  154. }
  155. int rfb::Region::numRects() const {
  156. return xrgn->numRects;
  157. }
  158. bool rfb::Region::get_rects(std::vector<Rect>* rects,
  159. bool left2right, bool topdown, int maxArea) const
  160. {
  161. int nRects = xrgn->numRects;
  162. int xInc = left2right ? 1 : -1;
  163. int yInc = topdown ? 1 : -1;
  164. int i = topdown ? 0 : nRects-1;
  165. rects->clear();
  166. rects->reserve(nRects);
  167. while (nRects > 0) {
  168. int firstInNextBand = i;
  169. int nRectsInBand = 0;
  170. while (nRects > 0 && xrgn->rects[firstInNextBand].y1 == xrgn->rects[i].y1)
  171. {
  172. firstInNextBand += yInc;
  173. nRects--;
  174. nRectsInBand++;
  175. }
  176. if (xInc != yInc)
  177. i = firstInNextBand - yInc;
  178. while (nRectsInBand > 0) {
  179. int y = xrgn->rects[i].y1;
  180. int h = maxArea / (xrgn->rects[i].x2 - xrgn->rects[i].x1);
  181. if (!h) h = xrgn->rects[i].y2 - y;
  182. do {
  183. if (h > xrgn->rects[i].y2 - y)
  184. h = xrgn->rects[i].y2 - y;
  185. Rect r(xrgn->rects[i].x1, y, xrgn->rects[i].x2, y+h);
  186. rects->push_back(r);
  187. y += h;
  188. } while (y < xrgn->rects[i].y2);
  189. i += xInc;
  190. nRectsInBand--;
  191. }
  192. i = firstInNextBand;
  193. }
  194. return !rects->empty();
  195. }
  196. rfb::Rect rfb::Region::get_bounding_rect() const {
  197. return Rect(xrgn->extents.x1, xrgn->extents.y1,
  198. xrgn->extents.x2, xrgn->extents.y2);
  199. }
  200. void rfb::Region::debug_print(const char* prefix) const
  201. {
  202. fprintf(stderr,"%s num rects %3ld extents %3d,%3d %3dx%3d\n",
  203. prefix, xrgn->numRects, xrgn->extents.x1, xrgn->extents.y1,
  204. xrgn->extents.x2-xrgn->extents.x1,
  205. xrgn->extents.y2-xrgn->extents.y1);
  206. for (int i = 0; i < xrgn->numRects; i++) {
  207. fprintf(stderr," rect %3d,%3d %3dx%3d\n",
  208. xrgn->rects[i].x1, xrgn->rects[i].y1,
  209. xrgn->rects[i].x2-xrgn->rects[i].x1,
  210. xrgn->rects[i].y2-xrgn->rects[i].y1);
  211. }
  212. }