draw.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  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. struct Draw
  15. {
  16. Point deltas;
  17. Point deltam;
  18. Memlayer *dstlayer;
  19. Memimage *src;
  20. Memimage *mask;
  21. int op;
  22. };
  23. static
  24. void
  25. ldrawop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
  26. {
  27. struct Draw *d;
  28. Point p0, p1;
  29. Rectangle oclipr, srcr, r, mr;
  30. int ok;
  31. d = etc;
  32. if(insave && d->dstlayer->save==nil)
  33. return;
  34. p0 = addpt(screenr.min, d->deltas);
  35. p1 = addpt(screenr.min, d->deltam);
  36. if(insave){
  37. r = rectsubpt(screenr, d->dstlayer->delta);
  38. clipr = rectsubpt(clipr, d->dstlayer->delta);
  39. }else
  40. r = screenr;
  41. /* now in logical coordinates */
  42. /* clipr may have narrowed what we should draw on, so clip if necessary */
  43. if(!rectinrect(r, clipr)){
  44. oclipr = dst->clipr;
  45. dst->clipr = clipr;
  46. ok = drawclip(dst, &r, d->src, &p0, d->mask, &p1, &srcr, &mr);
  47. dst->clipr = oclipr;
  48. if(!ok)
  49. return;
  50. }
  51. memdraw(dst, r, d->src, p0, d->mask, p1, d->op);
  52. }
  53. void
  54. memdraw(Memimage *dst, Rectangle r, Memimage *src, Point p0, Memimage *mask, Point p1, int op)
  55. {
  56. struct Draw d;
  57. Rectangle srcr, tr, mr;
  58. Memlayer *dl, *sl;
  59. if(drawdebug)
  60. iprint("memdraw %p %R %p %P %p %P\n", dst, r, src, p0, mask, p1);
  61. if(mask == nil)
  62. mask = memopaque;
  63. if(mask->layer){
  64. if(drawdebug) iprint("mask->layer != nil\n");
  65. return; /* too hard, at least for now */
  66. }
  67. Top:
  68. if(dst->layer==nil && src->layer==nil){
  69. memimagedraw(dst, r, src, p0, mask, p1, op);
  70. return;
  71. }
  72. if(drawclip(dst, &r, src, &p0, mask, &p1, &srcr, &mr) == 0){
  73. if(drawdebug) iprint("drawclip dstcr %R srccr %R maskcr %R\n", dst->clipr, src->clipr, mask->clipr);
  74. return;
  75. }
  76. /*
  77. * Convert to screen coordinates.
  78. */
  79. dl = dst->layer;
  80. if(dl != nil){
  81. r.min.x += dl->delta.x;
  82. r.min.y += dl->delta.y;
  83. r.max.x += dl->delta.x;
  84. r.max.y += dl->delta.y;
  85. }
  86. Clearlayer:
  87. if(dl!=nil && dl->clear){
  88. if(src == dst){
  89. p0.x += dl->delta.x;
  90. p0.y += dl->delta.y;
  91. src = dl->screen->image;
  92. }
  93. dst = dl->screen->image;
  94. goto Top;
  95. }
  96. sl = src->layer;
  97. if(sl != nil){
  98. p0.x += sl->delta.x;
  99. p0.y += sl->delta.y;
  100. srcr.min.x += sl->delta.x;
  101. srcr.min.y += sl->delta.y;
  102. srcr.max.x += sl->delta.x;
  103. srcr.max.y += sl->delta.y;
  104. }
  105. /*
  106. * Now everything is in screen coordinates.
  107. * mask is an image. dst and src are images or obscured layers.
  108. */
  109. /*
  110. * if dst and src are the same layer, just draw in save area and expose.
  111. */
  112. if(dl!=nil && dst==src){
  113. if(dl->save == nil)
  114. return; /* refresh function makes this case unworkable */
  115. if(rectXrect(r, srcr)){
  116. tr = r;
  117. if(srcr.min.x < tr.min.x){
  118. p1.x += tr.min.x - srcr.min.x;
  119. tr.min.x = srcr.min.x;
  120. }
  121. if(srcr.min.y < tr.min.y){
  122. p1.y += tr.min.x - srcr.min.x;
  123. tr.min.y = srcr.min.y;
  124. }
  125. if(srcr.max.x > tr.max.x)
  126. tr.max.x = srcr.max.x;
  127. if(srcr.max.y > tr.max.y)
  128. tr.max.y = srcr.max.y;
  129. memlhide(dst, tr);
  130. }else{
  131. memlhide(dst, r);
  132. memlhide(dst, srcr);
  133. }
  134. memdraw(dl->save, rectsubpt(r, dl->delta), dl->save,
  135. subpt(srcr.min, src->layer->delta), mask, p1, op);
  136. memlexpose(dst, r);
  137. return;
  138. }
  139. if(sl){
  140. if(sl->clear){
  141. src = sl->screen->image;
  142. if(dl != nil){
  143. r.min.x -= dl->delta.x;
  144. r.min.y -= dl->delta.y;
  145. r.max.x -= dl->delta.x;
  146. r.max.y -= dl->delta.y;
  147. }
  148. goto Top;
  149. }
  150. /* relatively rare case; use save area */
  151. if(sl->save == nil)
  152. return; /* refresh function makes this case unworkable */
  153. memlhide(src, srcr);
  154. /* convert back to logical coordinates */
  155. p0.x -= sl->delta.x;
  156. p0.y -= sl->delta.y;
  157. srcr.min.x -= sl->delta.x;
  158. srcr.min.y -= sl->delta.y;
  159. srcr.max.x -= sl->delta.x;
  160. srcr.max.y -= sl->delta.y;
  161. src = src->layer->save;
  162. }
  163. /*
  164. * src is now an image. dst may be an image or a clear layer
  165. */
  166. if(dst->layer==nil)
  167. goto Top;
  168. if(dst->layer->clear)
  169. goto Clearlayer;
  170. /*
  171. * dst is an obscured layer
  172. */
  173. d.deltas = subpt(p0, r.min);
  174. d.deltam = subpt(p1, r.min);
  175. d.dstlayer = dl;
  176. d.src = src;
  177. d.op = op;
  178. d.mask = mask;
  179. _memlayerop(ldrawop, dst, r, r, &d);
  180. }