draw.c 4.0 KB

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