Compare commits
5 Commits
main
...
image-buff
Author | SHA1 | Date | |
---|---|---|---|
bbf067d463 | |||
32d95b338b | |||
ef1e1f4ac2 | |||
db20ea707d | |||
0fb6d8a6b2 |
@ -11,6 +11,7 @@ type Application struct {
|
||||
backend Backend
|
||||
config Config
|
||||
callbackManager CallbackManager
|
||||
imageManager ImageManager
|
||||
}
|
||||
|
||||
// Run initializes the application, starts it, and then returns a channel that
|
||||
@ -120,3 +121,21 @@ func (application *Application) Config () (config *Config) {
|
||||
config = &application.config
|
||||
return
|
||||
}
|
||||
|
||||
// AddImage adds a new image buffer and returns a pointer to it.
|
||||
func (application *Application) NewImage () (im *ColorImage) {
|
||||
cellWidth, cellHeight := application.backend.CellMetrics()
|
||||
im = &ColorImage {
|
||||
cellWidth: cellWidth,
|
||||
cellHeight: cellHeight,
|
||||
}
|
||||
application.imageManager.Add(im)
|
||||
return
|
||||
}
|
||||
|
||||
// Remove removes the specified image buffer, if the application has it. If the
|
||||
// image was found and removed, removed will be true.
|
||||
func (application *Application) RemoveImage (im *ColorImage) (removed bool) {
|
||||
removed = application.imageManager.Remove(im)
|
||||
return
|
||||
}
|
||||
|
@ -8,11 +8,13 @@ type Backend interface {
|
||||
SetTitle (title string) (err error)
|
||||
SetIcon (icons []image.Image) (err error)
|
||||
Draw ()
|
||||
CellMetrics () (width, height int)
|
||||
}
|
||||
|
||||
type BackendFactory func (
|
||||
application *Application,
|
||||
callbackManager *CallbackManager,
|
||||
imageManager *ImageManager,
|
||||
) (
|
||||
backend Backend,
|
||||
err error,
|
||||
@ -27,7 +29,10 @@ func RegisterBackend (factory BackendFactory) {
|
||||
func instantiateBackend (application *Application) (backend Backend, err error) {
|
||||
// find a suitable backend
|
||||
for _, factory := range factories {
|
||||
backend, err = factory(application, &application.callbackManager)
|
||||
backend, err = factory (
|
||||
application,
|
||||
&application.callbackManager,
|
||||
&application.imageManager)
|
||||
if err == nil && backend != nil { return }
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import "github.com/flopp/go-findfont"
|
||||
func factory (
|
||||
application *stone.Application,
|
||||
callbackManager *stone.CallbackManager,
|
||||
imageManager *stone.ImageManager,
|
||||
) (
|
||||
output stone.Backend,
|
||||
err error,
|
||||
@ -29,6 +30,7 @@ func factory (
|
||||
application: application,
|
||||
config: application.Config(),
|
||||
callbackManager: callbackManager,
|
||||
imageManager: imageManager,
|
||||
}
|
||||
|
||||
// load font
|
||||
|
@ -17,6 +17,7 @@ type Backend struct {
|
||||
application *stone.Application
|
||||
config *stone.Config
|
||||
callbackManager *stone.CallbackManager
|
||||
imageManager *stone.ImageManager
|
||||
connection *xgbutil.XUtil
|
||||
window *xwindow.Window
|
||||
canvas *xgraphics.Image
|
||||
@ -88,6 +89,12 @@ func (backend *Backend) SetIcon (icons []image.Image) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (backend *Backend) CellMetrics () (width, height int) {
|
||||
width = backend.metrics.cellWidth
|
||||
height = backend.metrics.cellHeight
|
||||
return
|
||||
}
|
||||
|
||||
// calculateWindowSize calculates window bounds based on the internal buffer
|
||||
// size.
|
||||
func (backend *Backend) calculateWindowSize () (x, y int) {
|
||||
|
142
image.go
Normal file
142
image.go
Normal file
@ -0,0 +1,142 @@
|
||||
package stone
|
||||
|
||||
import "sync"
|
||||
import "image"
|
||||
import "image/color"
|
||||
|
||||
type ImageManager struct {
|
||||
lock sync.RWMutex
|
||||
images []*ColorImage
|
||||
}
|
||||
|
||||
func (manager *ImageManager) For (callback func (im *ColorImage)) {
|
||||
manager.lock.RLock()
|
||||
defer manager.lock.RUnlock()
|
||||
|
||||
for _, im := range manager.images {
|
||||
callback(im)
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *ImageManager) Add (im *ColorImage) {
|
||||
manager.lock.Lock()
|
||||
defer manager.lock.Unlock()
|
||||
|
||||
manager.images = append(manager.images, im)
|
||||
}
|
||||
|
||||
func (manager *ImageManager) Size () (size int) {
|
||||
manager.lock.RLock()
|
||||
defer manager.lock.RUnlock()
|
||||
|
||||
size = len(manager.images)
|
||||
return
|
||||
}
|
||||
|
||||
func (manager *ImageManager) At (index int) (im *ColorImage) {
|
||||
manager.lock.RLock()
|
||||
defer manager.lock.RUnlock()
|
||||
|
||||
if index < 0 || index > len(manager.images) { return }
|
||||
im = manager.images[index]
|
||||
return
|
||||
}
|
||||
|
||||
func (manager *ImageManager) Remove (im *ColorImage) (removed bool) {
|
||||
manager.lock.Lock()
|
||||
defer manager.lock.Unlock()
|
||||
|
||||
index := 0
|
||||
for manager.images[index] != im && index < len(manager.images) {
|
||||
index ++
|
||||
}
|
||||
|
||||
if index >= len(manager.images) { return }
|
||||
|
||||
manager.images = append (
|
||||
manager.images[:index],
|
||||
manager.images[index + 1:]...)
|
||||
removed = true
|
||||
return
|
||||
}
|
||||
|
||||
type ColorImage struct {
|
||||
x, y int
|
||||
width, height int
|
||||
bufferWidth, bufferHeight int
|
||||
cellWidth, cellHeight int
|
||||
buffer []color.RGBA
|
||||
|
||||
clean bool
|
||||
}
|
||||
|
||||
func (im *ColorImage) Model () (model color.Model) {
|
||||
model = color.RGBAModel
|
||||
return
|
||||
}
|
||||
|
||||
func (im *ColorImage) Bounds () (bounds image.Rectangle) {
|
||||
bounds.Max.X = im.width
|
||||
bounds.Max.Y = im.height
|
||||
return
|
||||
}
|
||||
|
||||
func (im *ColorImage) Size () (width, height int) {
|
||||
width = im.width
|
||||
height = im.height
|
||||
return
|
||||
}
|
||||
|
||||
func (im *ColorImage) SetSize (width, height int) {
|
||||
im.width = width
|
||||
im.height = height
|
||||
im.bufferWidth = im.cellWidth * im.width
|
||||
im.bufferHeight = im.cellHeight * im.height
|
||||
im.buffer = make([]color.RGBA, im.bufferWidth * im.bufferHeight)
|
||||
im.clean = false
|
||||
}
|
||||
|
||||
func (im *ColorImage) At (x, y int) (pixel color.Color) {
|
||||
if im.outOfBounds(x, y) { return }
|
||||
pixel = im.buffer[x + y * im.width]
|
||||
return
|
||||
}
|
||||
|
||||
func (im *ColorImage) AtRGBA (x, y int) (pixel color.RGBA) {
|
||||
if im.outOfBounds(x, y) { return }
|
||||
pixel = im.buffer[x + y * im.width]
|
||||
return
|
||||
}
|
||||
|
||||
func (im *ColorImage) Set (x, y int, pixel color.Color) {
|
||||
if im.outOfBounds(x, y) { return }
|
||||
r, g, b, a := pixel.RGBA()
|
||||
im.buffer[x + y * im.width] = color.RGBA {
|
||||
R: uint8(r >> 8),
|
||||
G: uint8(g >> 8),
|
||||
B: uint8(b >> 8),
|
||||
A: uint8(a >> 8),
|
||||
}
|
||||
|
||||
im.clean = false
|
||||
return
|
||||
}
|
||||
|
||||
func (im *ColorImage) SetRGBA (x, y int, pixel color.RGBA) {
|
||||
if im.outOfBounds(x, y) { return }
|
||||
im.buffer[x + y * im.width] = pixel
|
||||
return
|
||||
}
|
||||
|
||||
func (im *ColorImage) MarkClean () {
|
||||
im.clean = true
|
||||
}
|
||||
|
||||
func (im *ColorImage) outOfBounds (x, y int) (outOfBounds bool) {
|
||||
outOfBounds =
|
||||
x >= im.width ||
|
||||
y >= im.height ||
|
||||
x < 0 ||
|
||||
y < 0
|
||||
return
|
||||
}
|
Loading…
Reference in New Issue
Block a user