aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/ml-line.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdraw/ml-line.c')
-rw-r--r--src/libdraw/ml-line.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/libdraw/ml-line.c b/src/libdraw/ml-line.c
new file mode 100644
index 00000000..8c09a535
--- /dev/null
+++ b/src/libdraw/ml-line.c
@@ -0,0 +1,122 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+#include <memdraw.h>
+#include <memlayer.h>
+
+struct Lline
+{
+ Point p0;
+ Point p1;
+ Point delta;
+ int end0;
+ int end1;
+ int radius;
+ Point sp;
+ Memlayer *dstlayer;
+ Memimage *src;
+ int op;
+};
+
+static void llineop(Memimage*, Rectangle, Rectangle, void*, int);
+
+static
+void
+_memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, Rectangle clipr, int op)
+{
+ Rectangle r;
+ struct Lline ll;
+ Point d;
+ int srcclipped;
+ Memlayer *dl;
+
+ if(radius < 0)
+ return;
+ if(src->layer) /* can't draw line with layered source */
+ return;
+ srcclipped = 0;
+
+ Top:
+ dl = dst->layer;
+ if(dl == nil){
+ _memimageline(dst, p0, p1, end0, end1, radius, src, sp, clipr, op);
+ return;
+ }
+ if(!srcclipped){
+ d = subpt(sp, p0);
+ if(rectclip(&clipr, rectsubpt(src->clipr, d)) == 0)
+ return;
+ if((src->flags&Frepl)==0 && rectclip(&clipr, rectsubpt(src->r, d))==0)
+ return;
+ srcclipped = 1;
+ }
+
+ /* dst is known to be a layer */
+ p0.x += dl->delta.x;
+ p0.y += dl->delta.y;
+ p1.x += dl->delta.x;
+ p1.y += dl->delta.y;
+ clipr.min.x += dl->delta.x;
+ clipr.min.y += dl->delta.y;
+ clipr.max.x += dl->delta.x;
+ clipr.max.y += dl->delta.y;
+ if(dl->clear){
+ dst = dst->layer->screen->image;
+ goto Top;
+ }
+
+ /* XXX */
+ /* this is not the correct set of tests */
+// if(log2[dst->depth] != log2[src->depth] || log2[dst->depth]!=3)
+// return;
+
+ /* can't use sutherland-cohen clipping because lines are wide */
+ r = memlinebbox(p0, p1, end0, end1, radius);
+ /*
+ * r is now a bounding box for the line;
+ * use it as a clipping rectangle for subdivision
+ */
+ if(rectclip(&r, clipr) == 0)
+ return;
+ ll.p0 = p0;
+ ll.p1 = p1;
+ ll.end0 = end0;
+ ll.end1 = end1;
+ ll.sp = sp;
+ ll.dstlayer = dst->layer;
+ ll.src = src;
+ ll.radius = radius;
+ ll.delta = dl->delta;
+ ll.op = op;
+ _memlayerop(llineop, dst, r, r, &ll);
+}
+
+static
+void
+llineop(Memimage *dst, Rectangle screenr, Rectangle clipr, void *etc, int insave)
+{
+ struct Lline *ll;
+ Point p0, p1;
+
+ USED(screenr.min.x);
+ ll = etc;
+ if(insave && ll->dstlayer->save==nil)
+ return;
+ if(!rectclip(&clipr, screenr))
+ return;
+ if(insave){
+ p0 = subpt(ll->p0, ll->delta);
+ p1 = subpt(ll->p1, ll->delta);
+ clipr = rectsubpt(clipr, ll->delta);
+ }else{
+ p0 = ll->p0;
+ p1 = ll->p1;
+ }
+ _memline(dst, p0, p1, ll->end0, ll->end1, ll->radius, ll->src, ll->sp, clipr, ll->op);
+}
+
+void
+memline(Memimage *dst, Point p0, Point p1, int end0, int end1, int radius, Memimage *src, Point sp, int op)
+{
+ _memline(dst, p0, p1, end0, end1, radius, src, sp, dst->clipr, op);
+}