From 0fb6d8a6b2434dc5c78dcf169822e147a727d8d9 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 17 Nov 2022 14:09:31 -0500 Subject: [PATCH 1/2] Added an image struct --- image.go | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 image.go diff --git a/image.go b/image.go new file mode 100644 index 0000000..15a4aa8 --- /dev/null +++ b/image.go @@ -0,0 +1,85 @@ +package stone + +import "image" +import "image/color" + +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 +} From db20ea707d86c11869e0208a94bf13402589a458 Mon Sep 17 00:00:00 2001 From: Sasha Koshka Date: Thu, 17 Nov 2022 18:58:30 -0500 Subject: [PATCH 2/2] Create image manager and related stuff --- application.go | 19 +++++++++++++++ backend.go | 9 +++++-- backends/x/factory.go | 4 ++- backends/x/x.go | 7 ++++++ image.go | 57 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 3 deletions(-) diff --git a/application.go b/application.go index a97ccd3..1228970 100644 --- a/application.go +++ b/application.go @@ -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 @@ -114,3 +115,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 +} diff --git a/backend.go b/backend.go index d29e526..5c009f4 100644 --- a/backend.go +++ b/backend.go @@ -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, + 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 } } diff --git a/backends/x/factory.go b/backends/x/factory.go index bf0728b..8fc9267 100644 --- a/backends/x/factory.go +++ b/backends/x/factory.go @@ -19,8 +19,9 @@ import "github.com/flopp/go-findfont" // factory instantiates an X backend. func factory ( - application *stone.Application, + 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 diff --git a/backends/x/x.go b/backends/x/x.go index 74a7818..0eac148 100644 --- a/backends/x/x.go +++ b/backends/x/x.go @@ -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) { diff --git a/image.go b/image.go index 15a4aa8..5602dd9 100644 --- a/image.go +++ b/image.go @@ -1,8 +1,65 @@ 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