diff options
| -rw-r--r-- | prototypes/xgb-draw.go | 58 | 
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: | 
