line.c 2.5 KB

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