draw.c 4.0 KB

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