func showAll() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } for i := 0; i < len(testImages); i++ { fname := testImages[i] fmt.Printf("%d Working on %s\n", i, fname) file, err := os.Open(testDir + fname) if err != nil { continue } defer file.Close() var img image.Image // Decode the image. // using true forces bmp decoder, otherwise whatever is registered for ext is used // result slightly different if non-bmps fed to it if true { img, err = bmp.Decode(file) } else { img, _, err = image.Decode(file) } if err != nil { continue } ximg := xgraphics.NewConvert(X, img) ximg.XShowExtra(fname, true) time.Sleep(1 * time.Second) } xevent.Main(X) time.Sleep(4 * time.Second) xevent.Quit(X) }
// Create a new Icon from an image, with a given X11 window parent func NewIcon(X *xgbutil.XUtil, img image.Image, parent xproto.Window) *Icon { ximg := xgraphics.NewConvert(X, img) win := ximg.Window(parent) fader := fadeImage{img, 1.0} icn := Icon{&fader, parent, win, ximg, StateNormal, color.RGBA{0xcc, 0xcc, 0xcc, 0xff}} return &icn }
func showOne(testNum int) { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } fname := testImages[testNum] fmt.Printf("Working on %s\n", fname) file, err := os.Open(testDir + fname) if err != nil { log.Fatal(err) } defer file.Close() // Decode the image. img, _, err := image.Decode(file) if err != nil { log.Fatal(err) } ximg := xgraphics.NewConvert(X, img) ximg.XShowExtra(fname, true) xevent.Main(X) time.Sleep(4 * time.Second) xevent.Quit(X) }
func (c *client) Icon(width, height int) *xgraphics.Image { ximg, err := xgraphics.FindIcon(X, c.Id(), width, height) if err != nil { logger.Message.Printf("Could not find icon for '%s': %s", c, err) ximg = xgraphics.NewConvert(X, wingo.theme.defaultIcon) } return ximg }
func main() { X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } keybind.Initialize(X) // call once before using keybind package // Read an example gopher image into a regular png image. img, _, err := image.Decode(bytes.NewBuffer(gopher.GopherPng())) if err != nil { log.Fatal(err) } // Now convert it into an X image. ximg := xgraphics.NewConvert(X, img) // Now show it in a new window. // We set the window title and tell the program to quit gracefully when // the window is closed. // There is also a convenience method, XShow, that requires no parameters. win := showImage(ximg, "The Go Gopher!", true) // Listen for key press events. win.Listen(xproto.EventMaskKeyPress) err = keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { println("fullscreen!") err := ewmh.WmStateReq(X, win.Id, ewmh.StateToggle, "_NET_WM_STATE_FULLSCREEN") if err != nil { log.Fatal(err) } }).Connect(X, win.Id, "f", false) if err != nil { log.Fatal(err) } err = keybind.KeyPressFun( func(X *xgbutil.XUtil, ev xevent.KeyPressEvent) { println("quit fullscreen!") err := ewmh.WmStateReq(X, win.Id, ewmh.StateToggle, "_NET_WM_STATE_FULLSCREEN") if err != nil { log.Fatal(err) } }).Connect(X, win.Id, "Escape", false) if err != nil { log.Fatal(err) } // If we don't block, the program will end and the window will disappear. // We could use a 'select{}' here, but xevent.Main will emit errors if // something went wrong, so use that instead. xevent.Main(X) }
func (c *Client) Icon(width, height int) *xgraphics.Image { ximg, err := xgraphics.FindIcon(wm.X, c.Id(), width, height) if err != nil { logger.Message.Printf("Could not find icon for '%s': %s", c, err) ximg = xgraphics.NewConvert(wm.X, wm.Theme.DefaultIcon) ximg = ximg.Scale(width, height) } return ximg }
// newImage is meant to be run as a goroutine and loads a decoded image into // an xgraphics.Image value and draws it to an X pixmap. // The loading doesn't start until this image's corresponding imgLoadChan // has been pinged. // This implies that all images are decoded on start-up and are converted // and drawn to an X pixmap on-demand. I am still deliberating on whether this // is a smart decision. // Note that this process, particularly image conversion, can be quite // costly for large images. func newImage(X *xgbutil.XUtil, name string, img image.Image, index int, imgLoadChan chan struct{}, imgChan chan imageLoaded) { // Don't start loading until we're told to do so. <-imgLoadChan // We send this when we're done processing this image, whether its // an error or not. loaded := imageLoaded{index: index} start := time.Now() reg := xgraphics.NewConvert(X, img) lg("Converted '%s' to an xgraphics.Image type (%s).", name, time.Since(start)) // Only blend a checkered background if the image *may* have an alpha // channel. If we want to be a bit more efficient, we could type switch // on all image types use Opaque, but this may add undesirable overhead. // (Where the overhead is scanning the image for opaqueness.) switch img.(type) { case *image.Gray: case *image.Gray16: case *image.YCbCr: default: start = time.Now() blendCheckered(reg) lg("Blended '%s' into a checkered background (%s).", name, time.Since(start)) } if err := reg.CreatePixmap(); err != nil { // TODO: We should display a "Could not load image" image instead // of dying. However, creating a pixmap rarely fails, unless we have // a *ton* of images. (In all likelihood, we'll run out of memory // before a new pixmap cannot be created.) errLg.Fatal(err) } else { start = time.Now() reg.XDraw() lg("Drawn '%s' to an X pixmap (%s).", name, time.Since(start)) } loaded.img = &vimage{ Image: reg, name: name, } // Tell the canvas that this image has been loaded. imgChan <- loaded }
// newImage loads a decodes an image into an xgraphics.Image value and draws it // to an X pixmap. func newImage(img *Img) *vimage { start := time.Now() file, err := os.Open(img.name) if err != nil { errLg.Printf("Error opening '%s': %s", img.name, err) return &vimage{nil, err} } im, kind, err := image.Decode(file) if err != nil { errLg.Printf("Error decoding '%s': %s", img.name, err) return &vimage{nil, err} } lg("Decoded '%s' into image type '%s' (%s).", img.name, kind, time.Since(start)) // im = scale(im, window.Geom.Width(), window.Geom.Height()) start = time.Now() reg := xgraphics.NewConvert(window.X, im) lg("Converted '%s' to an xgraphics.Image type (%s).", img.name, time.Since(start)) // Only blend a checkered background if the image *may* have an alpha // channel. If we want to be a bit more efficient, we could type switch // on all image types use Opaque, but this may add undesirable overhead. // (Where the overhead is scanning the image for opaqueness.) switch im.(type) { case *image.Gray: case *image.Gray16: case *image.YCbCr: default: start = time.Now() blendCheckered(reg) lg("Blended '%s' into checkered background (%s).", img.name, time.Since(start)) } if err = reg.CreatePixmap(); err != nil { // TODO: We should display a "Could not load image" image instead // of dying. However, creating a pixmap rarely fails, unless we have // a *ton* of images. (In all likelihood, we'll run out of memory // before a new pixmap cannot be created.) errLg.Fatal(err) } reg.XDraw() return &vimage{reg, err} }
func showNamed(fname string) { fmt.Printf("Working on %s\n", fname) file, err := os.Open(fname) if err != nil { log.Fatal(err) } defer file.Close() X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } // Decode the image. img, _, err := image.Decode(file) if err != nil { log.Fatal(err) } ximg := xgraphics.NewConvert(X, img) ximg.XShowExtra(fname, true) xevent.Main(X) time.Sleep(4 * time.Second) xevent.Quit(X) }
func SetupDisplay() (ctrlChan chan interface{}) { ctrlChan = make(chan interface{}) X, err := xgbutil.NewConn() if err != nil { log.Fatal(err) } fontReader, err := os.Open(fontPath) if err != nil { log.Fatal(err) } // Now parse the font. font, err := xgraphics.ParseFont(fontReader) if err != nil { log.Fatal(err) } img, gc := initGc(width+border*2, height+heading+border*2) ximg := xgraphics.NewConvert(X, img) wid := ximg.XShowExtra("Regiment", true) circle := new(draw2d.PathStorage) ctr := 0 fps := 0 go func() { for { c := <-ctrlChan switch c := c.(type) { case *generals.Regiment: c.Step() rp := c.Position() gc.SetFillColor(image.Black) gc.SetStrokeColor(image.Black) for i := 0; i < len(rp.RowPath); i++ { x, y := rp.RowPath[i].X, rp.RowPath[i].Y circle = new(draw2d.PathStorage) circle.ArcTo(x+border, y+border+heading, 1, 1, 0, 2*math.Pi) gc.FillStroke(circle) } for i := 0; i < len(rp.ColPath); i++ { x, y := rp.ColPath[i].X, rp.ColPath[i].Y circle = new(draw2d.PathStorage) circle.ArcTo(x+border, y+border+heading, 1, 1, 0, 2*math.Pi) gc.FillStroke(circle) } case *Frame: for xp := border; xp < (width + border); xp++ { for yp := border; yp < (height + border + heading); yp++ { ximg.Set(xp, yp, img.At(xp, yp)) } } _, _, err = ximg.Text(10, 0, fg, size, font, fmt.Sprintf("FPS: %v", fps)) if err != nil { log.Fatal(err) } ximg.XDraw() ximg.XPaint(wid.Id) ctr++ gc.SetFillColor(image.White) // fill the background gc.Clear() case *Timing: fps = ctr _, _, err = ximg.Text(10, 0, fg, size, font, fmt.Sprintf("FPS: %v", fps)) ctr = 0 default: fmt.Println(reflect.TypeOf(c)) } } }() go func() { xevent.Main(X) }() return ctrlChan }