Skip to content

Commit

Permalink
Updated surface
Browse files Browse the repository at this point in the history
  • Loading branch information
djthorpe committed Apr 6, 2021
1 parent 2307b02 commit 658673e
Show file tree
Hide file tree
Showing 16 changed files with 469 additions and 425 deletions.
14 changes: 7 additions & 7 deletions graphics.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,27 @@ type FontSize struct {
Unit FontSizeUnit
}

type SurfaceManagerCallback func(GraphicsContext) error
//type SurfaceManagerCallback func(GraphicsContext) error

////////////////////////////////////////////////////////////////////////////////
// INTERFACES

// SurfaceManager to manage graphics surfaces
// SurfaceManager manages graphics surfaces
type SurfaceManager interface {
//CreateBackground(GraphicsContext, SurfaceFlags) (Surface, error)
CreateSurface(GraphicsContext, SurfaceFlags, float32, uint16, Point, Size) (Surface, error)
//CreateSurface(GraphicsContext, SurfaceFlags, float32, uint16, Point, Size) (Surface, error)
//CreateSurfaceWithBitmap(GraphicsContext, SurfaceFlags, Bitmap, float32, uint16, Point, Size) (Surface, error)
DisposeSurface(GraphicsContext, Surface) error
//DisposeSurface(GraphicsContext, Surface) error

// CreateBitmap returns a new bitmap with a specific pixel format
// and size. The size cannot be zero
CreateBitmap(SurfaceFormat, Size) (Bitmap, error)

// DisposeBitmap frees resources for a bitmap
// DisposeBitmap discards a bitmap
DisposeBitmap(Bitmap) error

// Do method is used to make graphics updates
Do(SurfaceManagerCallback) error
//Do(SurfaceManagerCallback) error
}

// Surface is an on-screen surface, which embeds a drawable canvas
Expand All @@ -68,7 +68,7 @@ type Surface interface {
}

// GraphicsContext is an opaque type
type GraphicsContext interface{}
//type GraphicsContext interface{}

// Bitmap represents pixel-based images
type Bitmap interface {
Expand Down
53 changes: 44 additions & 9 deletions pkg/graphics/bitmap/bitmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ import (
// INTERFACE

type BitmapFactory interface {
New(fmt gopi.SurfaceFormat, w, h uint32) (gopi.Bitmap, error)
New(ColorModel, uint32, uint32) (gopi.Bitmap, error)
Dispose(gopi.Bitmap) error
}

type Manager struct {
type Bitmaps struct {
gopi.Unit
gopi.Platform
sync.Mutex
Expand All @@ -29,18 +29,19 @@ type Manager struct {
// CONSTANTS

var (
factories = make(map[gopi.SurfaceFormat]BitmapFactory)
factories = make(map[gopi.SurfaceFormat]BitmapFactory)
colormodels = make(map[gopi.SurfaceFormat]ColorModel)
)

////////////////////////////////////////////////////////////////////////////////
// LIFECYCLE

func (this *Manager) New(gopi.Config) error {
func (this *Bitmaps) New(gopi.Config) error {
this.Require(this.Platform)
return nil
}

func (this *Manager) Dispose() error {
func (this *Bitmaps) Dispose() error {
this.Mutex.Lock()
defer this.Mutex.Unlock()

Expand All @@ -61,24 +62,42 @@ func (this *Manager) Dispose() error {
return result
}

////////////////////////////////////////////////////////////////////////////////
// STRINGIFY

func (this *Bitmaps) String() string {
str := "<bitmaps models=["
for _, model := range colormodels {
str += fmt.Sprint(" ", model)
}
return str + " ]>"
}

////////////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS

func (this *Manager) NewBitmap(format gopi.SurfaceFormat, w, h uint32) (gopi.Bitmap, error) {
func (this *Bitmaps) NewBitmap(format gopi.SurfaceFormat, w, h uint32) (gopi.Bitmap, error) {
this.Mutex.Lock()
defer this.Mutex.Unlock()

// Get color model
model, exists := colormodels[format]
if exists == false {
return nil, gopi.ErrNotFound.WithPrefix(format)
}

// Create bitmap with factory
if factory, exists := factories[format]; exists == false {
return nil, gopi.ErrNotFound.WithPrefix(format)
} else if bitmap, err := factory.New(format, w, h); err != nil {
} else if bitmap, err := factory.New(model, w, h); err != nil {
return nil, err
} else {
this.bitmaps = append(this.bitmaps, bitmap)
return bitmap, nil
}
}

func (this *Manager) DisposeBitmap(bitmap gopi.Bitmap) error {
func (this *Bitmaps) DisposeBitmap(bitmap gopi.Bitmap) error {
this.Mutex.Lock()
defer this.Mutex.Unlock()

Expand All @@ -93,7 +112,7 @@ func (this *Manager) DisposeBitmap(bitmap gopi.Bitmap) error {
return gopi.ErrNotFound.WithPrefix("DisposeBitmap")
}

func (this *Manager) disposeBitmap(bitmap gopi.Bitmap) error {
func (this *Bitmaps) disposeBitmap(bitmap gopi.Bitmap) error {
if factory, exists := factories[bitmap.Format()]; exists == false {
return gopi.ErrInternalAppError.WithPrefix("Dispose")
} else {
Expand All @@ -114,6 +133,22 @@ func RegisterFactory(factory BitmapFactory, formats ...gopi.SurfaceFormat) {
}
}

func RegisterColorModel(format gopi.SurfaceFormat, model ColorModel) {
if _, exists := colormodels[format]; exists {
panic("RegisterColorModel: Duplicate: " + fmt.Sprint(format))
} else {
colormodels[format] = model
}
}

func GetColorModel(fmt gopi.SurfaceFormat) ColorModel {
if model, exists := colormodels[fmt]; exists {
return model
} else {
return nil
}
}

func AlignUp(v uint32, a uint32) uint32 {
// Align a value on a byte-bounrary
return ((v - 1) & ^(a - 1)) + a
Expand Down
10 changes: 5 additions & 5 deletions pkg/graphics/bitmap/bitmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

type App struct {
gopi.Unit
*bitmap.Manager
*bitmap.Bitmaps
}

const (
Expand All @@ -30,7 +30,7 @@ const (

func Test_Bitmap_001(t *testing.T) {
tool.Test(t, nil, new(App), func(app *App) {
app.Require(app.Manager)
app.Require(app.Bitmaps)

if bitmap, err := app.NewBitmap(gopi.SURFACE_FMT_RGBA32, 10, 10); err != nil {
t.Error(err)
Expand All @@ -42,7 +42,7 @@ func Test_Bitmap_001(t *testing.T) {

func Test_Bitmap_002(t *testing.T) {
tool.Test(t, nil, new(App), func(app *App) {
app.Require(app.Manager)
app.Require(app.Bitmaps)

bitmap, err := app.NewBitmap(gopi.SURFACE_FMT_RGBA32, 100, 100)
if err != nil {
Expand All @@ -62,7 +62,7 @@ func Test_Bitmap_002(t *testing.T) {

func Test_Bitmap_003(t *testing.T) {
tool.Test(t, nil, new(App), func(app *App) {
app.Require(app.Manager)
app.Require(app.Bitmaps)

reader, err := os.Open(PNG_FILEPATH)
if err != nil {
Expand All @@ -71,7 +71,7 @@ func Test_Bitmap_003(t *testing.T) {
defer reader.Close()
if bitmap, _, err := image.Decode(reader); err != nil {
t.Error(err)
} else if dest, err := app.Manager.NewBitmap(gopi.SURFACE_FMT_RGBA32, uint32(bitmap.Bounds().Dx()), uint32(bitmap.Bounds().Dy())); err != nil {
} else if dest, err := app.NewBitmap(gopi.SURFACE_FMT_RGBA32, uint32(bitmap.Bounds().Dx()), uint32(bitmap.Bounds().Dy())); err != nil {
t.Error(err)
} else {
bounds := bitmap.Bounds()
Expand Down
93 changes: 93 additions & 0 deletions pkg/graphics/bitmap/color.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package bitmap

import (
"fmt"
"image/color"

// Modules
gopi "github.com/djthorpe/gopi/v3"
)

////////////////////////////////////////////////////////////////////////////////
// INTERFACE

type ColorModel interface {
color.Model

Format() gopi.SurfaceFormat
BitsPerPixel() uint8
}

////////////////////////////////////////////////////////////////////////////////
// TYPES

type RGBA32 uint32

type model struct {
fmt gopi.SurfaceFormat
bpp uint8
fn func(color.Color) color.Color
}

////////////////////////////////////////////////////////////////////////////////
// INIT

func init() {
// Register Color Models
RegisterColorModel(gopi.SURFACE_FMT_RGBA32, NewModel(gopi.SURFACE_FMT_RGBA32, 32, toRGBA32))
}

////////////////////////////////////////////////////////////////////////////////
// LIFECYCLE

func NewModel(fmt gopi.SurfaceFormat, bpp uint8, fn func(color.Color) color.Color) ColorModel {
m := new(model)
m.fmt = fmt
m.fn = fn
m.bpp = bpp
return m
}

////////////////////////////////////////////////////////////////////////////////
// METHODS

func (this *model) Convert(c color.Color) color.Color {
return this.fn(c)
}

func (this *model) Format() gopi.SurfaceFormat {
return this.fmt
}

func (this *model) BitsPerPixel() uint8 {
return this.bpp
}

////////////////////////////////////////////////////////////////////////////////
// STRINGIFY

func (this *model) String() string {
str := "<bitmap.colormodel"
str += fmt.Sprint(" fmt=", this.Format())
str += fmt.Sprint(" bits_per_pixel=", this.BitsPerPixel())
return str + ">"
}

////////////////////////////////////////////////////////////////////////////////
// RGBA32

func toRGBA32(c color.Color) color.Color {
if c, ok := c.(RGBA32); ok {
return c
}
r, g, b, a := c.RGBA()
return RGBA32(r<<16&0xFF000000) | RGBA32(g<<8&0x00FF0000) | RGBA32(b<<0&0x0000FF00) | RGBA32(a>>8&0x000000FF)
}

func (p RGBA32) RGBA() (uint32, uint32, uint32, uint32) {
r := uint32(byte(p>>24)) * 0x0101
g := uint32(byte(p>>16)) * 0x0101
b := uint32(byte(p>>8)) * 0x0101
a := uint32(byte(p)) * 0x0101
return r, g, b, a
}
44 changes: 44 additions & 0 deletions pkg/graphics/bitmap/color_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package bitmap_test

import (
"image/color"
"testing"

// Frameworks
gopi "github.com/djthorpe/gopi/v3"
bitmap "github.com/djthorpe/gopi/v3/pkg/graphics/bitmap"
)

////////////////////////////////////////////////////////////////////////////////
// TESTS

func Test_Color_001(t *testing.T) {
tests := []struct {
c color.Color
r, g, b, a uint32
}{
{color.Black, 0x0000, 0x0000, 0x0000, 0xFFFF},
{color.White, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF},
{color.RGBA{0xFF, 0x00, 0x00, 0xFF}, 0xFFFF, 0x0000, 0x0000, 0xFFFF}, // Red
{color.RGBA{0x00, 0xFF, 0x00, 0xFF}, 0x0000, 0xFFFF, 0x0000, 0xFFFF}, // Green
{color.RGBA{0x00, 0x00, 0xFF, 0xFF}, 0x0000, 0x0000, 0xFFFF, 0xFFFF}, // Blue
}
for fmt := gopi.SURFACE_FMT_NONE; fmt <= gopi.SURFACE_FMT_MAX; fmt++ {
model := bitmap.GetColorModel(fmt)
if model == nil {
continue
}
if v := model.Format(); v != fmt {
t.Error("Unexpected return from Format()", v)
} else {
t.Log(model)
}
for _, test := range tests {
color := model.Convert(test.c)
r, g, b, a := color.RGBA()
if r != test.r || g != test.g || b != test.b || a != test.a {
t.Error("Unexpected return from Convert()", test.c, " != ", color)
}
}
}
}
Loading

0 comments on commit 658673e

Please sign in to comment.