aboutsummaryrefslogtreecommitdiff
path: root/prototypes/xgb-draw.go
diff options
context:
space:
mode:
Diffstat (limited to 'prototypes/xgb-draw.go')
-rw-r--r--prototypes/xgb-draw.go58
1 files 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: