-
Notifications
You must be signed in to change notification settings - Fork 42
/
fenster.go
100 lines (86 loc) · 2.1 KB
/
fenster.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package fenster
/*
#cgo linux LDFLAGS: -lX11
#cgo darwin LDFLAGS: -framework Cocoa
#cgo windows LDFLAGS: -static -lgdi32
#include "fenster.h"
*/
import "C"
import (
"fmt"
"image"
"image/color"
"image/draw"
"runtime"
"time"
"unsafe"
)
func init() {
// Ensure that main.main is called from the main thread
runtime.LockOSThread()
}
type Fenster interface {
Loop(d time.Duration) bool
Close()
Key(byte) bool
Mod() Mods
draw.Image
}
// RGB Color 00RRGGBB
type RGB uint32
func (c RGB) RGBA() (r uint32, g uint32, b uint32, a uint32) {
r = uint32(c>>16) & 0xff
r |= r << 8
g = uint32(c>>8) & 0xff
g |= g << 8
b = uint32(c) & 0xff
b |= b << 8
a = 0xffff
return r, g, b, a
}
var RGBModel = color.ModelFunc(rgbModel)
func rgbModel(c color.Color) color.Color {
if _, ok := c.(RGB); ok {
return c
}
r, g, b, _ := c.RGBA()
return RGB((r>>8)<<16 | (g>>8)<<8 | (b >> 8))
}
type Mods int
type fenster struct {
f C.struct_fenster
buf []uint32
lastFrame time.Time
}
func (f *fenster) ColorModel() color.Model { return RGBModel }
func (f *fenster) Bounds() image.Rectangle {
return image.Rect(0, 0, int(f.f.width), int(f.f.height))
}
func New(w, h int, title string) (Fenster, error) {
f := new(fenster)
f.f.title = C.CString(title)
f.f.width = C.int(w)
f.f.height = C.int(h)
f.f.buf = (*C.uint32_t)(C.malloc(C.size_t(w * h * 4)))
f.buf = unsafe.Slice((*uint32)(f.f.buf), w*h)
f.lastFrame = time.Now()
res := C.fenster_open(&f.f)
if res != 0 {
return nil, fmt.Errorf("failed to open window: %d", res)
}
return f, nil
}
func (f *fenster) Close() { C.fenster_close(&f.f) }
func (f *fenster) Loop(d time.Duration) bool {
if sleep := d - time.Since(f.lastFrame); sleep > 0 {
time.Sleep(sleep)
}
f.lastFrame = time.Now()
return C.fenster_loop(&f.f) == 0
}
func (f *fenster) Key(code byte) bool { return f.f.keys[code] != 0 }
func (f *fenster) Mod() Mods { return Mods(f.f.mod) }
func (f *fenster) At(x, y int) color.Color { return RGB(f.buf[y*int(f.f.width)+x]) }
func (f *fenster) Set(x, y int, c color.Color) {
f.buf[y*int(f.f.width)+x] = uint32(f.ColorModel().Convert(c).(RGB))
}