layerop.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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 <u.h>
  10. #include <libc.h>
  11. #include <draw.h>
  12. #include <memdraw.h>
  13. #include <memlayer.h>
  14. #define RECUR(a,b,c,d) _layerop(fn, i, Rect(a.x, b.y, c.x, d.y), clipr, etc, front->layer->rear);
  15. static void
  16. _layerop(
  17. void (*fn)(Memimage*, Rectangle, Rectangle, void*, int),
  18. Memimage *i,
  19. Rectangle r,
  20. Rectangle clipr,
  21. void *etc,
  22. Memimage *front)
  23. {
  24. Rectangle fr;
  25. Top:
  26. if(front == i){
  27. /* no one is in front of this part of window; use the screen */
  28. fn(i->layer->screen->image, r, clipr, etc, 0);
  29. return;
  30. }
  31. fr = front->layer->screenr;
  32. if(rectXrect(r, fr) == 0){
  33. /* r doesn't touch this window; continue on next rearmost */
  34. // assert(front && front->layer && front->layer->screen && front->layer->rear);
  35. front = front->layer->rear;
  36. goto Top;
  37. }
  38. if(fr.max.y < r.max.y){
  39. RECUR(r.min, fr.max, r.max, r.max);
  40. r.max.y = fr.max.y;
  41. }
  42. if(r.min.y < fr.min.y){
  43. RECUR(r.min, r.min, r.max, fr.min);
  44. r.min.y = fr.min.y;
  45. }
  46. if(fr.max.x < r.max.x){
  47. RECUR(fr.max, r.min, r.max, r.max);
  48. r.max.x = fr.max.x;
  49. }
  50. if(r.min.x < fr.min.x){
  51. RECUR(r.min, r.min, fr.min, r.max);
  52. r.min.x = fr.min.x;
  53. }
  54. /* r is covered by front, so put in save area */
  55. (*fn)(i->layer->save, r, clipr, etc, 1);
  56. }
  57. /*
  58. * Assumes incoming rectangle has already been clipped to i's logical r and clipr
  59. */
  60. void
  61. _memlayerop(
  62. void (*fn)(Memimage*, Rectangle, Rectangle, void*, int),
  63. Memimage *i,
  64. Rectangle screenr, /* clipped to window boundaries */
  65. Rectangle clipr, /* clipped also to clipping rectangles of hierarchy */
  66. void *etc)
  67. {
  68. Memlayer *l;
  69. Rectangle r, scr;
  70. l = i->layer;
  71. if(!rectclip(&screenr, l->screenr))
  72. return;
  73. if(l->clear){
  74. fn(l->screen->image, screenr, clipr, etc, 0);
  75. return;
  76. }
  77. r = screenr;
  78. scr = l->screen->image->clipr;
  79. /*
  80. * Do the piece on the screen
  81. */
  82. if(rectclip(&screenr, scr))
  83. _layerop(fn, i, screenr, clipr, etc, l->screen->frontmost);
  84. if(rectinrect(r, scr))
  85. return;
  86. /*
  87. * Do the piece off the screen
  88. */
  89. if(!rectXrect(r, scr)){
  90. /* completely offscreen; easy */
  91. fn(l->save, r, clipr, etc, 1);
  92. return;
  93. }
  94. if(r.min.y < scr.min.y){
  95. /* above screen */
  96. fn(l->save, Rect(r.min.x, r.min.y, r.max.x, scr.min.y), clipr, etc, 1);
  97. r.min.y = scr.min.y;
  98. }
  99. if(r.max.y > scr.max.y){
  100. /* below screen */
  101. fn(l->save, Rect(r.min.x, scr.max.y, r.max.x, r.max.y), clipr, etc, 1);
  102. r.max.y = scr.max.y;
  103. }
  104. if(r.min.x < scr.min.x){
  105. /* left of screen */
  106. fn(l->save, Rect(r.min.x, r.min.y, scr.min.x, r.max.y), clipr, etc, 1);
  107. r.min.x = scr.min.x;
  108. }
  109. if(r.max.x > scr.max.x){
  110. /* right of screen */
  111. fn(l->save, Rect(scr.max.x, r.min.y, r.max.x, r.max.y), clipr, etc, 1);
  112. }
  113. }