rlist.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "vnc.h"
  10. #include "vncs.h"
  11. static int tot;
  12. static void rprint(Rlist*);
  13. static void
  14. growrlist(Rlist *rlist, int n)
  15. {
  16. int old;
  17. if(rlist->nrect+n <= rlist->maxrect)
  18. return;
  19. old = rlist->maxrect;
  20. while(rlist->nrect+n > rlist->maxrect){
  21. if(rlist->maxrect == 0)
  22. rlist->maxrect = 16;
  23. else
  24. rlist->maxrect *= 2;
  25. }
  26. tot += rlist->maxrect - old;
  27. if(tot > 10000)
  28. sysfatal("too many rectangles");
  29. rlist->rect = realloc(rlist->rect, rlist->maxrect*sizeof(rlist->rect[0]));
  30. if(rlist->rect == nil)
  31. sysfatal("realloc failed in growrlist");
  32. }
  33. static void
  34. rappend(Rlist *rl, Rectangle r)
  35. {
  36. growrlist(rl, 1);
  37. rl->rect[rl->nrect++] = r;
  38. }
  39. /* remove rectangle i from the list */
  40. static int
  41. rtrim(Rlist *r, int i)
  42. {
  43. if(i < 0 || i >= r->nrect)
  44. return 0;
  45. if(i == r->nrect-1){
  46. r->nrect--;
  47. return 1;
  48. }
  49. r->rect[i] = r->rect[--r->nrect];
  50. return 1;
  51. }
  52. static int
  53. rectadjacent(Rectangle r, Rectangle s)
  54. {
  55. return r.min.x<=s.max.x && s.min.x<=r.max.x &&
  56. r.min.y<=s.max.y && s.min.y<=r.max.y;
  57. }
  58. /*
  59. * If s shares three edges with r, compute the
  60. * rectangle r - s and return 1.
  61. * Else return 0.
  62. */
  63. static int
  64. rectubr(Rectangle *r, Rectangle s)
  65. {
  66. if(r->min.y==s.min.y && r->max.y==s.max.y){
  67. if(r->min.x == s.min.x){
  68. r->min.x = s.max.x;
  69. assert(r->max.x > r->min.x);
  70. return 1;
  71. }
  72. if(r->max.x == s.max.x){
  73. r->max.x = s.min.x;
  74. assert(r->max.x > r->min.x);
  75. return 1;
  76. }
  77. }
  78. if(r->min.x==s.min.x && r->max.x==s.max.x){
  79. if(r->min.y == s.min.y){
  80. r->min.y = s.max.y;
  81. assert(r->max.y > r->min.y);
  82. return 1;
  83. }
  84. if(r->max.y == s.max.y){
  85. r->max.y = s.min.y;
  86. assert(r->max.y > r->min.y);
  87. return 1;
  88. }
  89. }
  90. return 0;
  91. }
  92. /*
  93. * If s is a corner of r, remove s from r, yielding
  94. * two rectangles r and rr. R holds the part with
  95. * smaller coordinates.
  96. */
  97. static int
  98. rectcornersubr(Rectangle *r, Rectangle s, Rectangle *rr)
  99. {
  100. # define UPRIGHT(r) Pt((r).max.x, (r).min.y)
  101. # define LOWLEFT(r) Pt((r).min.x, (r).max.y)
  102. *rr = *r;
  103. if(s.min.x == r->min.x){
  104. if(s.min.y == r->min.y){ // upper left
  105. *rr = Rpt(UPRIGHT(s), r->max);
  106. *r = Rpt(LOWLEFT(s), LOWLEFT(*rr));
  107. return 1;
  108. }
  109. if(s.max.y == r->max.y){ // lower left
  110. *rr = Rpt(Pt(s.max.x, r->min.y), r->max);
  111. *r = Rpt(r->min, UPRIGHT(s));
  112. return 1;
  113. }
  114. }
  115. if(s.max.x == r->max.x){
  116. if(s.max.y == r->max.y){ // lower right
  117. *rr = Rpt(Pt(s.min.x, r->min.y), UPRIGHT(s));
  118. *r = Rpt(r->min, LOWLEFT(s));
  119. return 1;
  120. }
  121. if(s.min.y == r->min.y){ // upper right
  122. *rr = Rpt(LOWLEFT(s), r->max);
  123. *r = Rpt(r->min, LOWLEFT(*rr));
  124. return 1;
  125. }
  126. }
  127. return 0;
  128. }
  129. /*
  130. * If s is a band cutting r into two pieces, set r to one piece
  131. * and rr to the other.
  132. */
  133. static int
  134. recttridesubr(Rectangle *nr, Rectangle s, Rectangle *rr)
  135. {
  136. *rr = *nr;
  137. if((nr->min.x == s.min.x && nr->max.x == s.max.x) &&
  138. (nr->min.y < s.min.y && s.max.y < nr->max.y)){
  139. nr->max.y = s.min.y;
  140. rr->min.y = s.max.y;
  141. return 1;
  142. }
  143. if((nr->min.y == s.min.y && nr->max.y == s.max.y) &&
  144. (nr->min.x < s.min.x && s.max.x < nr->max.x)){
  145. nr->max.x = s.min.x;
  146. rr->min.x = s.max.x;
  147. return 1;
  148. }
  149. return 0;
  150. }
  151. void
  152. addtorlist(Rlist *rlist, Rectangle r)
  153. {
  154. int i, j;
  155. Rectangle ir, cr, rr;
  156. Rlist tmp;
  157. if(r.min.x >= r.max.x || r.min.y >= r.max.y)
  158. return;
  159. memset(&tmp, 0, sizeof tmp);
  160. rappend(&tmp, r);
  161. if(verbose > 5)
  162. fprint(2, "region union add %R:\n", r);
  163. combinerect(&rlist->bbox, r); // must do this first
  164. for(j = 0; j < tmp.nrect; j++){
  165. r = tmp.rect[j];
  166. for(i=0; i < rlist->nrect; i++){
  167. ir = rlist->rect[i];
  168. if(verbose > 5)
  169. fprint(2, "checking %R against %R\n", r, ir);
  170. if(!rectadjacent(ir, r))
  171. continue;
  172. /* r is covered by ir? */
  173. if(rectinrect(r, ir))
  174. break;
  175. /* r covers ir? */
  176. if(rectinrect(ir, r)){
  177. rtrim(rlist, i);
  178. i--;
  179. continue;
  180. }
  181. /* aligned and overlapping? */
  182. if((ir.min.y == r.min.y && ir.max.y == r.max.y) ||
  183. (ir.min.x == r.min.x && ir.max.x == r.max.x)){
  184. combinerect(&r, ir);
  185. rtrim(rlist, i);
  186. i--;
  187. continue;
  188. }
  189. /* not aligned */
  190. if(verbose > 5)
  191. fprint(2, "break up rect %R and %R\n", ir, r);
  192. /* 2->2 breakup */
  193. cr = ir;
  194. if (!rectclip(&cr, r)) /* share only one point */
  195. continue;
  196. if(rectubr(&r, cr))
  197. continue;
  198. if(rectubr(&rlist->rect[i], cr))
  199. continue;
  200. /* 2 -> 3 breakup */
  201. /* stride across */
  202. if(recttridesubr(&r, cr, &rr)){
  203. rappend(&tmp, rr);
  204. continue;
  205. }
  206. /* corner overlap */
  207. if(rectcornersubr(&r, cr, &rr)){
  208. rappend(&tmp, rr);
  209. continue;
  210. }
  211. abort();
  212. }
  213. if(i == rlist->nrect)
  214. rappend(rlist, r);
  215. }
  216. freerlist(&tmp);
  217. if(verbose > 5)
  218. rprint(rlist);
  219. }
  220. void
  221. freerlist(Rlist *r)
  222. {
  223. free(r->rect);
  224. tot -= r->maxrect;
  225. r->nrect = 0;
  226. r->maxrect = 0;
  227. r->rect = nil;
  228. }
  229. static void
  230. rprint(Rlist *r)
  231. {
  232. int i;
  233. fprint(2, "rlist %p:", r);
  234. for(i=0; i<r->nrect; i++)
  235. fprint(2, " %R", r->rect[i]);
  236. fprint(2, "\n");
  237. }
  238. #ifdef REGION_DEBUG
  239. int verbose = 10;
  240. void main(int argc, char * argv[])
  241. {
  242. Rectangle r1 = Rect(0, 0, 300, 200);
  243. Rectangle r2 = Rect(100, 100, 400, 300);
  244. Rectangle r3 = Rect(200, 100, 500, 300);
  245. Region reg;
  246. initdraw(0, 0, "vncviewer");
  247. region_init(&reg);
  248. region_union(&reg, r1, r1);
  249. region_union(&reg, r2, r2);
  250. region_union(&reg, r3, r3);
  251. }
  252. #endif