From e8381d86ce4fb13b83e85b4554143efa8c8620ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Wed, 5 Sep 2018 12:03:05 +0200 Subject: [PATCH] xgb-draw: point interpolation --- prototypes/xgb-draw.go | 58 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/prototypes/xgb-draw.go b/prototypes/xgb-draw.go index 53eb727..7a1bdfc 100644 --- a/prototypes/xgb-draw.go +++ b/prototypes/xgb-draw.go @@ -1,7 +1,6 @@ // Network-friendly drawing application based on XRender. // // TODO -// - interpolate motion between points // - use double buffering to remove flicker // (more pronounced over X11 forwarding) // - maybe keep the pixmap as large as the window @@ -183,7 +182,7 @@ func main() { // - http://ssp.impulsetrain.com/porterduff.html // - https://keithp.com/~keithp/talks/renderproblems/renderproblems/render-title.html // - https://keithp.com/~keithp/talks/cairo2003.pdf - drawLineTo := func(x, y int16) { + drawPointAt := func(x, y int16) { _ = render.Composite(X, render.PictOpConjointOver, brushid, render.PictureNone, pixmaskpictid, 0, 0, 0, 0, x-brushRadius, y-brushRadius, @@ -203,6 +202,55 @@ func main() { pixWidth, pixHeight) } + // Integer version of Bresenham's line drawing algorithm + drawLine := func(x0, y0, x1, y1 int16) { + dx, dy := x1-x0, y1-y0 + if dx < 0 { + dx = -dx + } + if dy < 0 { + dy = -dy + } + + steep := dx < dy + if steep { + // Flip the coordinate system on input + x0, y0 = y0, x0 + x1, y1 = y1, x1 + dx, dy = dy, dx + } + + var stepX, stepY int16 = 1, 1 + if x0 > x1 { + stepX = -1 + } + if y0 > y1 { + stepY = -1 + } + + dpr := dy * 2 + delta := dpr - dx + dpru := delta - dx + + for ; dx > 0; dx-- { + // Unflip the coordinate system on output + if steep { + drawPointAt(y0, x0) + } else { + drawPointAt(x0, y0) + } + + x0 += stepX + if delta > 0 { + y0 += stepY + delta += dpru + } else { + delta += dpr + } + } + } + + var startX, startY int16 = 0, 0 drawing := false for { ev, xerr := X.WaitForEvent() @@ -242,12 +290,14 @@ func main() { []xproto.Rectangle{{Width: pixWidth, Height: pixHeight}}) drawing = true - drawLineTo(e.EventX, e.EventY) + drawPointAt(e.EventX, e.EventY) + startX, startY = e.EventX, e.EventY } case xproto.MotionNotifyEvent: if drawing { - drawLineTo(e.EventX, e.EventY) + drawLine(startX, startY, e.EventX, e.EventY) + startX, startY = e.EventX, e.EventY } case xproto.ButtonReleaseEvent: