Example #1
0
// drawPencil takes an (x, y) position (from a MotionNotify event) and draws
// a rectangle of size pencilTip on to canvas.
func drawPencil(canvas *xgraphics.Image, win *xwindow.Window, x, y int) {
	// Create a subimage at (x, y) with pencilTip width and height from canvas.
	// Creating subimages is very cheap---no pixels are copied.
	// Moreover, when subimages are drawn to the screen, only the pixels in
	// the sub-image are sent to X.
	tipRect := midRect(x, y, pencilTip, pencilTip, width, height)

	// If the rectangle contains no pixels, don't draw anything.
	if tipRect.Empty() {
		return
	}

	// Output a little message.
	log.Printf("Drawing pencil point at (%d, %d)", x, y)

	// Create the subimage of the canvas to draw to.
	tip := canvas.SubImage(tipRect)
	fmt.Println(tip.Rect)

	// Now color each pixel in tip with the pencil color.
	tip.For(func(x, y int) xgraphics.BGRA {
		return xgraphics.BlendBGRA(tip.At(x, y).(xgraphics.BGRA), pencil)
	})

	// Now draw the changes to the pixmap.
	tip.XDraw()

	// And paint them to the window.
	tip.XPaint(win.Id)
}
Example #2
0
// This. This seems to be the solution. 0.72ns/op. RGBA -> RGBA is 0.02ns/op. Draw is 180ns/op.
// from https://github.com/BurntSushi/xgbutil/blob/master/xgraphics/convert.go
func convertRGBAtoXgb(dest *xgraphics.Image, src *image.RGBA) {
	var x, y, i, si int

	for x = dest.Rect.Min.X; x < dest.Rect.Max.X; x++ {
		for y = dest.Rect.Min.Y; y < dest.Rect.Max.Y; y++ {
			si = src.PixOffset(x, y)
			i = dest.PixOffset(x, y)
			dest.Pix[i+0] = src.Pix[si+2]
			dest.Pix[i+1] = src.Pix[si+1]
			dest.Pix[i+2] = src.Pix[si+0]
			dest.Pix[i+3] = src.Pix[si+3]
		}
	}
}
Example #3
0
File: win.go Project: uriel/vimg
// paint uses the xgbutil/xgraphics package to copy the area corresponding
// to ximg in its pixmap to the window. It will also issue a clear request
// before hand to try and avoid artifacts.
func (w *Window) paint(ximg *xgraphics.Image) {

	// If the image is bigger than the canvas, this is always (0, 0).
	// If the image is the same size, then it is also (0, 0).
	// If a dimension of the image is smaller than the canvas, then:
	// x = (canvas_width - image_width) / 2 and
	// y = (canvas_height - image_height) / 2
	xmargin, ymargin := 0, 0
	if ximg.Bounds().Dx() < w.Geom.Width() {
		xmargin = (w.Geom.Width() - ximg.Bounds().Dx()) / 2
	}
	if ximg.Bounds().Dy() < w.Geom.Height() {
		ymargin = (w.Geom.Height() - ximg.Bounds().Dy()) / 2
	}

	ximg.XExpPaint(w.Id, xmargin, ymargin)
}
Example #4
0
// vpCenter inspects the canvas and image geometry, and determines where the
// origin of the image should be painted into the canvas.
// If the image is bigger than the canvas, this is always (0, 0).
// If the image is the same size, then it is also (0, 0).
// If a dimension of the image is smaller than the canvas, then:
// x = (canvas_width - image_width) / 2 and
// y = (canvas_height - image_height) / 2
func vpCenter(ximg *xgraphics.Image, canWidth, canHeight int) image.Point {
	xmargin, ymargin := 0, 0
	if ximg.Bounds().Dx() < canWidth {
		xmargin = (canWidth - ximg.Bounds().Dx()) / 2
	}
	if ximg.Bounds().Dy() < canHeight {
		ymargin = (canHeight - ximg.Bounds().Dy()) / 2
	}
	return image.Point{xmargin, ymargin}
}
Example #5
0
// SetImageToBg sets the given image into the background at the proper location
// for the named output to display.
func SetImageToBg(X *xgbutil.XUtil,
	bg *xgraphics.Image,
	img image.Image,
	name string) error {

	output, err := util.GetOutputByName(X, name)
	if err != nil {
		return err
	}
	geom, err := util.OutputRect(X, output)
	if err != nil {
		return err
	}
	if err = bg.CreatePixmap(); err != nil {
		return err
	}
	bg.XDraw()
	draw.Draw(bg, geom, img, img.Bounds().Min, draw.Src)
	return nil
}
Example #6
0
func copyToXGraphicsImage(xs *xgraphics.Image, buffer *image.RGBA) {
	//Pix[(y-Rect.Min.Y)*Stride + (x-Rect.Min.X)*4]
	xdata := xs.Pix
	bdata := buffer.Pix
	if xs.Bounds() == buffer.Bounds() {
		copy(xdata, bdata)
	} else {

		xb := xs.Bounds()
		bb := buffer.Bounds()

		miny := xb.Min.Y
		if miny < bb.Min.Y {
			miny = bb.Min.Y
		}
		maxy := xb.Max.Y
		if maxy > bb.Max.Y {
			maxy = bb.Max.Y
		}

		xRowLen := (xb.Max.X - xb.Min.X)
		bRowLen := (bb.Max.X - bb.Min.X)
		rowLen := xRowLen
		if bRowLen < rowLen {
			rowLen = bRowLen
		}

		for y := miny; y < maxy; y++ {
			xstart := (y-xb.Min.Y)*xs.Stride - xb.Min.X*4
			bstart := (y-bb.Min.Y)*buffer.Stride - bb.Min.X*4
			xrow := xdata[xstart : xstart+rowLen*4]
			brow := bdata[bstart : bstart+rowLen*4]
			copy(xrow, brow)
		}
	}
	// xgraphics.Image is BGRA, not RGBA, so swap some bits
	for i := 0; i < len(xdata)/4; i++ {
		index := i * 4
		xdata[index], xdata[index+2] = xdata[index+2], xdata[index]
	}
}
Example #7
0
// blendCheckered is basically a copy of xgraphics.Blend with no interfaces.
// (It's faster.) Also, it is hardcoded to blend into a checkered background.
func blendCheckered(dest *xgraphics.Image) {
	dsrc := dest.Bounds()
	dmnx, dmxx, dmny, dmxy := dsrc.Min.X, dsrc.Max.X, dsrc.Min.Y, dsrc.Max.Y

	clr1 := xgraphics.BGRA{B: 0xff, G: 0xff, R: 0xff, A: 0xff}
	clr2 := xgraphics.BGRA{B: 0xde, G: 0xdc, R: 0xdf, A: 0xff}

	var dx, dy int
	var bgra, clr xgraphics.BGRA
	for dx = dmnx; dx < dmxx; dx++ {
		for dy = dmny; dy < dmxy; dy++ {
			if dx%30 >= 15 {
				if dy%30 >= 15 {
					clr = clr1
				} else {
					clr = clr2
				}
			} else {
				if dy%30 >= 15 {
					clr = clr2
				} else {
					clr = clr1
				}
			}

			bgra = dest.At(dx, dy).(xgraphics.BGRA)
			dest.SetBGRA(dx, dy, xgraphics.BlendBGRA(clr, bgra))
		}
	}
}
Example #8
0
func updater(img *xgraphics.Image, win *xwindow.Window) {
	//We keep track of times based on 1024 frames
	frame := 0
	start := time.Now()
	var genStart, drawStart time.Time
	var genTotal, drawTotal time.Duration

	for {
		frame = frame + 1
		if frame > 1024 {
			frame = 0
			log.Printf("Time elapsed: %s\n", time.Now().Sub(start))
			log.Printf("Time generate: %s\n", genTotal)
			log.Printf("Time drawing: %s\n", drawTotal)
			start = time.Now()
			drawTotal, genTotal = 0, 0
		}

		genStart = time.Now()
		var x, y, i int
		for y = 0; y < 768; y++ {
			//set last pixel back to black
			img.SetBGRA(frame-1, y, xgraphics.BGRA{0, 0, 0, 255})
			for i = 0; i < 10; i++ {
				x = i + frame
				if x > 1024 {
					x = 1024
				}
				img.SetBGRA(x, y, xgraphics.BGRA{0, 0, 255, 255})
			}
		}
		genTotal += time.Now().Sub(genStart)

		drawStart = time.Now()
		//hopefully using checked will block us from drawing again before x
		//draws although XDraw might block anyway, we can check for an error
		//here
		err := img.XDrawChecked()
		if err != nil {
			log.Println(err)
			return
		}
		//img.XDraw()

		img.XPaint(win.Id)
		drawTotal += time.Now().Sub(drawStart)
	}
}
Example #9
0
// clearCanvas erases all your pencil marks.
func clearCanvas(canvas *xgraphics.Image, win *xwindow.Window) {
	log.Println("Clearing canvas...")
	canvas.For(func(x, y int) xgraphics.BGRA {
		return bg
	})

	canvas.XDraw()
	canvas.XPaint(win.Id)
}
Example #10
0
// drawGopher draws the gopher image to the canvas.
func drawGopher(canvas *xgraphics.Image, gopher image.Image,
	win *xwindow.Window, x, y int) {

	// Find the rectangle of the canvas where we're going to draw the gopher.
	gopherRect := midRect(x, y, gopherWidth, gopherHeight, width, height)

	// If the rectangle contains no pixels, don't draw anything.
	if gopherRect.Empty() {
		return
	}

	// Output a little message.
	log.Printf("Drawing gopher at (%d, %d)", x, y)

	// Get a subimage of the gopher that's in sync with gopherRect.
	gopherPt := image.Pt(gopher.Bounds().Min.X, gopher.Bounds().Min.Y)
	if gopherRect.Min.X == 0 {
		gopherPt.X = gopherWidth - gopherRect.Dx()
	}
	if gopherRect.Min.Y == 0 {
		gopherPt.Y = gopherHeight - gopherRect.Dy()
	}

	// Create the canvas subimage.
	subCanvas := canvas.SubImage(gopherRect)

	// Blend the gopher image into the sub-canvas.
	// This does alpha blending.
	xgraphics.Blend(subCanvas, gopher, gopherPt)

	// Now draw the changes to the pixmap.
	subCanvas.XDraw()

	// And paint them to the window.
	subCanvas.XPaint(win.Id)
}
Example #11
0
// This is a slightly modified version of xgraphics.XShowExtra that does
// not set any resize constraints on the window (so that it can go
// fullscreen).
func showImage(im *xgraphics.Image, name string, quit bool) *xwindow.Window {
	if len(name) == 0 {
		name = "xgbutil Image Window"
	}
	w, h := im.Rect.Dx(), im.Rect.Dy()

	win, err := xwindow.Generate(im.X)
	if err != nil {
		xgbutil.Logger.Printf("Could not generate new window id: %s", err)
		return nil
	}

	// Create a very simple window with dimensions equal to the image.
	win.Create(im.X.RootWin(), 0, 0, w, h, 0)

	// Make this window close gracefully.
	win.WMGracefulClose(func(w *xwindow.Window) {
		xevent.Detach(w.X, w.Id)
		keybind.Detach(w.X, w.Id)
		mousebind.Detach(w.X, w.Id)
		w.Destroy()

		if quit {
			xevent.Quit(w.X)
		}
	})

	// Set WM_STATE so it is interpreted as a top-level window.
	err = icccm.WmStateSet(im.X, win.Id, &icccm.WmState{
		State: icccm.StateNormal,
	})
	if err != nil { // not a fatal error
		xgbutil.Logger.Printf("Could not set WM_STATE: %s", err)
	}

	// Set _NET_WM_NAME so it looks nice.
	err = ewmh.WmNameSet(im.X, win.Id, name)
	if err != nil { // not a fatal error
		xgbutil.Logger.Printf("Could not set _NET_WM_NAME: %s", err)
	}

	// Paint our image before mapping.
	im.XSurfaceSet(win.Id)
	im.XDraw()
	im.XPaint(win.Id)

	// Now we can map, since we've set all our properties.
	// (The initial map is when the window manager starts managing.)
	win.Map()

	return win
}
Example #12
0
func (p *piece) Create(act, inact *xgraphics.Image) {
	if act != nil {
		if p.active > 0 {
			xgraphics.FreePixmap(p.X, p.active)
		}
		act.CreatePixmap()
		act.XDraw()

		p.active = act.Pixmap
	}
	if inact != nil {
		if p.inactive > 0 {
			xgraphics.FreePixmap(p.X, p.inactive)
		}
		inact.CreatePixmap()
		inact.XDraw()

		p.inactive = inact.Pixmap
	}
}
Example #13
0
// SetRoot sets the given background as the root window background.
func SetRoot(X *xgbutil.XUtil, bg *xgraphics.Image) error {
	root := X.RootWin()
	if err := bg.XSurfaceSet(root); err != nil {
		return err
	}
	bg.XDraw()
	bg.XPaint(root)
	// FIXME: This doesn't set the pixmap persistently. As soon as the program
	// exits, the pixmap is destroyed. Find a way to make it persistent.
	xprop.ChangeProp32(X, root, "_XROOTPMAP_ID", "PIXMAP", uint(bg.Pixmap))
	xprop.ChangeProp32(X, root, "ESETROOT_PMAP_ID", "PIXMAP", uint(bg.Pixmap))
	return nil
}
Example #14
0
// paint uses the xgbutil/xgraphics package to copy the area corresponding
// to ximg in its pixmap to the window. It will also issue a clear request
// before hand to try and avoid artifacts.
func (w *window) paint(ximg *xgraphics.Image) {
	dst := vpCenter(ximg, w.Geom.Width(), w.Geom.Height())
	// UUU Commenting this out avoids flickering, and I see no artifacts!
	// w.ClearAll()
	ximg.XExpPaint(w.Id, dst.X, dst.Y)
}
Example #15
0
func makeWindow(ximage *xgraphics.Image) (*xwindow.Window, *bool) {
	w, h := ximage.Rect.Dx(), ximage.Rect.Dy()

	window, err := xwindow.Generate(ximage.X)
	if err != nil {
		xgbutil.Logger.Printf("Could not generate new window id: %s", err)
		return nil, nil
	}

	window.Create(ximage.X.RootWin(), 0, 0, w, h, xproto.CwBackPixel, 0x00000000)
	window.Listen(xproto.EventMaskExposure,
		xproto.EventMaskKeyPress,
		xproto.EventMaskStructureNotify,
		xproto.EventMaskVisibilityChange)

	window.WMGracefulClose(func(w *xwindow.Window) {
		xevent.Detach(w.X, w.Id)
		keybind.Detach(w.X, w.Id)
		mousebind.Detach(w.X, w.Id)
		w.Destroy()
		xevent.Quit(w.X)
	})

	err = icccm.WmStateSet(ximage.X, window.Id, &icccm.WmState{
		State: icccm.StateNormal,
	})
	if err != nil {
		xgbutil.Logger.Printf("Could not set WM_STATE: %s", err)
	}

	err = ewmh.WmNameSet(ximage.X, window.Id, "Computer System Monitor")
	if err != nil {
		xgbutil.Logger.Printf("Could not set _NET_WM_NAME: %s", err)
	}

	err = keybind.KeyPressFun(
		func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) {
			err := ewmh.WmStateReq(ximage.X, window.Id, ewmh.StateToggle,
				"_NET_WM_STATE_FULLSCREEN")
			if err != nil {
				log.Fatal(err)
			}
		}).Connect(ximage.X, window.Id, "f", false)
	if err != nil {
		log.Fatal(err)
	}

	xevent.ExposeFun(
		func(xu *xgbutil.XUtil, event xevent.ExposeEvent) {
			ximage.XExpPaint(window.Id, 0, 0)
		}).Connect(ximage.X, window.Id)

	obscured := false
	xevent.VisibilityNotifyFun(
		func(xu *xgbutil.XUtil, event xevent.VisibilityNotifyEvent) {
			obscured = event.State == xproto.VisibilityFullyObscured
		}).Connect(ximage.X, window.Id)

	window.Map()

	return window, &obscured
}