diff --git a/allegro5/bitmap.go b/allegro5/bitmap.go index 8460c12..eb1d0ee 100644 --- a/allegro5/bitmap.go +++ b/allegro5/bitmap.go @@ -6,6 +6,10 @@ import "C" import ( "fmt" + "image" + "image/png" + "io/ioutil" + "os" "unsafe" ) @@ -17,14 +21,36 @@ type Bitmap struct { } type DrawOptions struct { - Center bool - Scale *Scale - Tint *Color + Center bool + Scale Scale + Tint *Color + Rotation *Rotation } -type Scale struct { - Horizontal float32 - Vertical float32 +type Scale interface { + Horizontal() float32 + Vertical() float32 +} + +type scale struct { + horizontal float32 + vertical float32 +} + +func (s *scale) Horizontal() float32 { return s.horizontal } +func (s *scale) Vertical() float32 { return s.vertical } + +func NewScale(horizontal, vertical float32) Scale { + return &scale{horizontal, vertical} +} + +func NewUniformScale(s float32) Scale { + return &scale{s, s} +} + +type Rotation struct { + Angle float32 + Center bool } // NewBitmap creates a new bitmap of given width and height @@ -36,6 +62,29 @@ func NewBitmap(width, height int) (*Bitmap, error) { return &Bitmap{b, width, height}, nil } +func exportToPng(im image.Image) (string, error) { + tmp, err := ioutil.TempFile("", "galleg") + if nil != err { + return "", err + } + defer tmp.Close() + err = png.Encode(tmp, im) + if nil != err { + return "", err + } + return tmp.Name(), nil +} + +// NewBitmapFromImage creates a new bitmap starting from a Go native image (image.Image) +func NewBitmapFromImage(im image.Image) (*Bitmap, error) { + path, err := exportToPng(im) + if nil != err { + return nil, err + } + defer os.Remove(path) + return LoadBitmap(path) +} + // LoadBitmap tries to load the image at the specified path as a bitmap func LoadBitmap(path string) (*Bitmap, error) { p := C.CString(path) @@ -60,25 +109,48 @@ func (b *Bitmap) DrawOptions(left, top float32, options DrawOptions) { scale := nil != options.Scale if scale { - width *= options.Scale.Horizontal - height *= options.Scale.Vertical + width *= options.Scale.Horizontal() + height *= options.Scale.Vertical() } if options.Center { left -= width * 0.5 top -= height * 0.5 } + rotated := nil != options.Rotation + var centerX C.float + var centerY C.float + if rotated && options.Rotation.Center { + centerX = C.float(b.width) * 0.5 + centerY = C.float(b.height) * 0.5 + } if scale { - if nil == options.Tint { - C.al_draw_scaled_bitmap(b.bitmap, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0) - } else { - C.al_draw_tinted_scaled_bitmap(b.bitmap, options.Tint.color, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0) + if nil == options.Tint { // scaled + if rotated { // scaled & rotated + C.al_draw_scaled_rotated_bitmap(b.bitmap, centerX, centerY, C.float(left), C.float(top), C.float(options.Scale.Horizontal()), C.float(options.Scale.Vertical()), C.float(options.Rotation.Angle), 0) + } else { // scaled + C.al_draw_scaled_bitmap(b.bitmap, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0) + } + } else { // tinted & scaled + if rotated { // scaled, tinted & rotated + C.al_draw_tinted_scaled_rotated_bitmap(b.bitmap, options.Tint.color, centerX, centerY, C.float(left), C.float(top), C.float(options.Scale.Horizontal()), C.float(options.Scale.Vertical()), C.float(options.Rotation.Angle), 0) + } else { // tinted, scaled + C.al_draw_tinted_scaled_bitmap(b.bitmap, options.Tint.color, 0, 0, C.float(b.width), C.float(b.height), C.float(left), C.float(top), C.float(width), C.float(height), 0) + } } } else { if nil == options.Tint { - C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0) - } else { - C.al_draw_tinted_bitmap(b.bitmap, options.Tint.color, C.float(left), C.float(top), 0) + if rotated { // rotated + C.al_draw_rotated_bitmap(b.bitmap, centerX, centerY, C.float(left), C.float(top), C.float(options.Rotation.Angle), 0) + } else { + C.al_draw_bitmap(b.bitmap, C.float(left), C.float(top), 0) + } + } else { // tinted + if rotated { // tinted & rotated + C.al_draw_tinted_rotated_bitmap(b.bitmap, options.Tint.color, centerX, centerY, C.float(left), C.float(top), C.float(options.Rotation.Angle), 0) + } else { + C.al_draw_tinted_bitmap(b.bitmap, options.Tint.color, C.float(left), C.float(top), 0) + } } } }