line.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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 Lline
  15. {
  16. Point p0;
  17. Point p1;
  18. Point delta;
  19. int end0;
  20. int end1;
  21. int radius;
  22. Point sp;
  23. Memlayer *dstlayer;
  24. Memimage *src;
  25. int op;
  26. };
  27. static void llineop(Memimage*, Rectangle, Rectangle, void*, int);
  28. static
  29. void
  30. _memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op)
  31. {
  32. Rectangle r;
  33. struct Lline ll;
  34. Point d;
  35. int srcclipped;
  36. Memlayer *dl;
  37. if(radius < 0)
  38. return;
  39. if(src->layer) /* can't draw line with layered source */
  40. return;
  41. srcclipped = 0;
  42. Top:
  43. dl = dst->layer;
  44. if(dl == nil){
  45. _memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op);
  46. return;
  47. }
  48. if(!srcclipped){
  49. d = subpt(sp, p0);
  50. if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
  51. return;
  52. if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
  53. return;
  54. srcclipped = 1;
  55. }
  56. /* dst is known to be a layer */
  57. p0.x += dl->delta.x;
  58. p0.y += dl->delta.y;
  59. p1.x += dl->delta.x;
  60. p1.y += dl->delta.y;
  61. clipr.min.x += dl->delta.x;
  62. clipr.min.y += dl->delta.y;
  63. clipr.max.x += dl->delta.x;
  64. clipr.max.y += dl->delta.y;
  65. if(dl->clear){
  66. dst = dst->layer->screen->image;
  67. goto Top;
  68. }
  69. /* XXX */
  70. /* this is not the correct set of tests */
  71. // if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3)
  72. // return;
  73. /* can't use sutherland-cohen clipping because lines are wide */
  74. r = memlinebbox(p0, p1, end0, end1, radius);
  75. /*
  76. * r is now a bounding box for the line;
  77. * use it as a clipping rectangle for subdivision
  78. */
  79. if(rectclip(&r, clipr) == 0)
  80. return;
  81. ll.p0 = p0;
  82. ll.p1 = p1;
  83. ll.end0 = end0;
  84. ll.end1 = end1;
  85. ll.sp = sp;
  86. ll.dstlayer = dst->layer;
  87. ll.src = src;
  88. ll.radius = radius;
  89. ll.delta = dl->delta;
  90. ll.op = op;
  91. _memlayerop(llineop, dst, r, r, &ll);
  92. }
  93. static
  94. void
  95. llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
  96. {
  97. struct Lline *ll;
  98. Point p0, p1;
  99. USED(screenr.min.x);
  100. ll = etc;
  101. if(insave && ll->dstlayer->save==nil)
  102. return;
  103. if(!rectclip(&clipr, screenr))
  104. return;
  105. if(insave){
  106. p0 = subpt(ll->p0, ll->delta);
  107. p1 = subpt(ll->p1, ll->delta);
  108. clipr = rectsubpt(clipr, ll->delta);
  109. }else{
  110. p0 = ll->p0;
  111. p1 = ll->p1;
  112. }
  113. _memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr, ll->op);
  114. }
  115. void
  116. memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op)
  117. {
  118. _memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op);
  119. }