Renamed Image{,s} to Texture{,s}.

This commit is contained in:
Sander Schobers 2020-05-12 23:03:43 +02:00
parent 2c9007ce9b
commit 48aaf30182
14 changed files with 216 additions and 216 deletions

View File

@ -7,24 +7,24 @@ import (
"opslag.de/schobers/zntg/ui"
)
var _ ui.Image = &uiImage{}
var _ ui.Texture = &texture{}
type uiImage struct {
type texture struct {
bmp *allg5.Bitmap
}
func (i *uiImage) Destroy() {
i.bmp.Destroy()
func (t *texture) Destroy() {
t.bmp.Destroy()
}
func (i *uiImage) Height() float32 {
return float32(i.bmp.Height())
func (t *texture) Height() float32 {
return float32(t.bmp.Height())
}
func (i *uiImage) Image() image.Image {
return i.bmp.Image()
func (t *texture) Texture() image.Image {
return t.bmp.Image()
}
func (i *uiImage) Width() float32 {
return float32(i.bmp.Width())
func (t *texture) Width() float32 {
return float32(t.bmp.Width())
}

View File

@ -130,44 +130,44 @@ func (r *Renderer) Clear(c color.Color) {
allg5.ClearToColor(newColor(c))
}
func (r *Renderer) CreateImage(im image.Image) (ui.Image, error) {
func (r *Renderer) CreateTexture(im image.Image) (ui.Texture, error) {
bmp, err := allg5.NewBitmapFromImage(im, true)
if err != nil {
return nil, err
}
return &uiImage{bmp}, nil
return &texture{bmp}, nil
}
func (r *Renderer) CreateImagePath(path string) (ui.Image, error) {
func (r *Renderer) CreateTexturePath(path string) (ui.Texture, error) {
bmp, err := allg5.LoadBitmap(path)
if err != nil {
return nil, err
}
return &uiImage{bmp}, nil
return &texture{bmp}, nil
}
func (r *Renderer) CreateImageSize(w, h float32) (ui.Image, error) {
func (r *Renderer) CreateTextureSize(w, h float32) (ui.Texture, error) {
bmp, err := allg5.NewVideoBitmap(int(w), int(h))
if err != nil {
return nil, err
}
return &uiImage{bmp}, nil
return &texture{bmp}, nil
}
func (r *Renderer) DefaultTarget() ui.Image {
return &uiImage{r.disp.Target()}
func (r *Renderer) DefaultTarget() ui.Texture {
return &texture{r.disp.Target()}
}
func (r *Renderer) Display() *allg5.Display { return r.disp }
func (r *Renderer) DrawImage(im ui.Image, p geom.PointF32) {
bmp := r.mustGetBitmap(im)
func (r *Renderer) DrawTexture(texture ui.Texture, p geom.PointF32) {
bmp := r.mustGetBitmap(texture)
x, y := snap(p)
bmp.Draw(x, y)
}
func (r *Renderer) DrawImageOptions(im ui.Image, p geom.PointF32, opts ui.DrawOptions) {
bmp := r.mustGetBitmap(im)
func (r *Renderer) DrawTextureOptions(texture ui.Texture, p geom.PointF32, opts ui.DrawOptions) {
bmp := r.mustGetBitmap(texture)
var o allg5.DrawOptions
if opts.Tint != nil {
tint := newColor(opts.Tint)
@ -188,12 +188,12 @@ func (r *Renderer) Font(name string) ui.Font {
return r.ft[name]
}
func (r *Renderer) mustGetBitmap(im ui.Image) *allg5.Bitmap {
m, ok := im.(*uiImage)
func (r *Renderer) mustGetBitmap(t ui.Texture) *allg5.Bitmap {
texture, ok := t.(*texture)
if !ok {
panic("image must be created on same renderer")
}
return m.bmp
return texture.bmp
}
func (r *Renderer) Rectangle(rect geom.RectangleF32, c color.Color, thickness float32) {
@ -225,8 +225,8 @@ func (r *Renderer) RegisterFonts(path string, fonts ...FontDefinition) error {
return nil
}
func (r *Renderer) RenderTo(im ui.Image) {
bmp := r.mustGetBitmap(im)
func (r *Renderer) RenderTo(texture ui.Texture) {
bmp := r.mustGetBitmap(texture)
bmp.SetAsTarget()
}
@ -238,8 +238,8 @@ func (r *Renderer) Size() geom.PointF32 {
return geom.PtF32(float32(r.disp.Width()), float32(r.disp.Height()))
}
func (r *Renderer) SetIcon(im ui.Image) {
bmp := r.mustGetBitmap(im)
func (r *Renderer) SetIcon(texture ui.Texture) {
bmp := r.mustGetBitmap(texture)
r.disp.SetIcon(bmp)
}
@ -255,8 +255,8 @@ func (r *Renderer) SetWindowTitle(t string) {
r.disp.SetWindowTitle(t)
}
func (r *Renderer) Target() ui.Image {
return &uiImage{allg5.CurrentTarget()}
func (r *Renderer) Target() ui.Texture {
return &texture{allg5.CurrentTarget()}
}
func (r *Renderer) text(p geom.PointF32, font string, c color.Color, t string, align allg5.HorizontalAlignment) {

View File

@ -5,38 +5,38 @@ import "opslag.de/schobers/geom"
type RenderBufferFn func(ctx Context, size geom.PointF32)
type Buffer struct {
im Image
texture Texture
size geom.PointF32
}
func (b *Buffer) Update(ctx Context, size geom.PointF32) error {
if b.im != nil {
if b.texture != nil {
if size == b.size {
return nil
}
b.im.Destroy()
b.im = nil
b.texture.Destroy()
b.texture = nil
b.size = geom.ZeroPtF32
}
im, err := ctx.Renderer().CreateImageSize(size.X, size.Y)
texture, err := ctx.Renderer().CreateTextureSize(size.X, size.Y)
if err != nil {
return err
}
b.im = im
b.texture = texture
b.size = size
return nil
}
func (b *Buffer) Render(ctx Context, pos geom.PointF32, fn RenderBufferFn) {
if b.im == nil {
if b.texture == nil {
return
}
renderer := ctx.Renderer()
currTarget := renderer.Target()
renderer.RenderTo(b.im)
renderer.RenderTo(b.texture)
fn(ctx, b.size)
renderer.RenderTo(currTarget)
renderer.DrawImage(b.im, pos)
renderer.DrawTexture(b.texture, pos)
}
type BufferControl struct {

View File

@ -10,7 +10,7 @@ type Button struct {
ControlBase
HoverColor color.Color
Icon Image
Icon Texture
IconScale float32
Text string
Type ButtonType
@ -27,8 +27,8 @@ const (
func BuildButton(text string, fn func(b *Button)) *Button { return BuildIconButton(nil, text, fn) }
func BuildIconButton(i Image, text string, fn func(b *Button)) *Button {
var b = &Button{Text: text, Icon: i}
func BuildIconButton(icon Texture, text string, fn func(b *Button)) *Button {
var b = &Button{Text: text, Icon: icon}
if fn != nil {
fn(b)
}
@ -133,9 +133,9 @@ func (b *Button) Render(ctx Context) {
bounds = bounds.Inset(pad)
pos := bounds.Min
if b.Icon != nil && b.Icon.Height() > 0 {
icon, _ := ctx.Images().ScaledHeight(b.Icon, b.scale(bounds.Dy()))
icon, _ := ctx.Textures().ScaledHeight(b.Icon, b.scale(bounds.Dy()))
if icon != nil {
ctx.Renderer().DrawImageOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: textColor})
ctx.Renderer().DrawTextureOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: textColor})
pos.X += icon.Width() + pad
}
}

View File

@ -30,12 +30,12 @@ func (c *Checkbox) desiredSize(ctx Context) geom.PointF32 {
if len(c.Text) != 0 {
w += pad + font.WidthOf(c.Text)
}
icon, _ := ctx.Images().ScaledHeight(c.getOrCreateNormalIcon(ctx), h)
icon, _ := ctx.Textures().ScaledHeight(c.getOrCreateNormalIcon(ctx), h)
w += pad + icon.Width()
return geom.PtF32(w+pad, pad+h+pad)
}
func (c *Checkbox) icon(ctx Context) Image {
func (c *Checkbox) icon(ctx Context) Texture {
if c.Selected {
return GetOrCreateIcon(ctx, "ui-default-checkbox-selected", c.selectedIcon)
} else if c.over {
@ -44,7 +44,7 @@ func (c *Checkbox) icon(ctx Context) Image {
return c.getOrCreateNormalIcon(ctx)
}
func (c *Checkbox) getOrCreateNormalIcon(ctx Context) Image {
func (c *Checkbox) getOrCreateNormalIcon(ctx Context) Texture {
return GetOrCreateIcon(ctx, "ui-default-checkbox", c.normalIcon)
}
@ -125,13 +125,13 @@ func (c *Checkbox) Render(ctx Context) {
var pad = style.Dimensions.TextPadding
bounds = bounds.Inset(pad)
pos := bounds.Min
icon, _ := ctx.Images().ScaledHeight(c.icon(ctx), bounds.Dy())
icon, _ := ctx.Textures().ScaledHeight(c.icon(ctx), bounds.Dy())
if icon != nil {
iconColor := fore
if c.Selected && c.Font.Color == nil {
iconColor = palette.Primary
}
ctx.Renderer().DrawImageOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: iconColor})
ctx.Renderer().DrawTextureOptions(icon, geom.PtF32(pos.X, pos.Y+.5*(bounds.Dy()-icon.Height())), DrawOptions{Tint: iconColor})
pos.X += icon.Width() + pad
}
if len(c.Text) != 0 {

View File

@ -3,7 +3,7 @@ package ui
type Context interface {
Animate()
HasQuit() bool
Images() *Images
Textures() *Textures
Quit()
Renderer() Renderer
Style() *Style
@ -17,7 +17,7 @@ type context struct {
quit chan struct{}
r Renderer
view Control
ims *Images
textures *Textures
style *Style
}
@ -32,7 +32,7 @@ func (c *context) HasQuit() bool {
}
}
func (c *context) Images() *Images { return c.ims }
func (c *context) Textures() *Textures { return c.textures }
func (c *context) Quit() {
if !c.HasQuit() {

View File

@ -13,7 +13,7 @@ import (
type basic struct {
ui.StackPanel
plus ui.Image
plus ui.Texture
}
func (b *basic) Init(ctx ui.Context) error {
@ -73,7 +73,7 @@ func run() error {
if err != nil {
return err
}
plus, err := render.CreateImagePath("../resources/images/plus.png")
plus, err := render.CreateTexturePath("../resources/images/plus.png")
if err != nil {
return err
}

View File

@ -10,27 +10,27 @@ import (
type ImagePixelTestFn func(geom.PointF32) bool
type ImageAlphaPixelTestFn func(geom.PointF32) uint8
func createImage(ctx Context, image image.Image) Image {
im, err := ctx.Renderer().CreateImage(image)
func createTexture(ctx Context, image image.Image) Texture {
texture, err := ctx.Renderer().CreateTexture(image)
if err != nil {
return nil
}
return im
return texture
}
func CreateIcon(ctx Context, test ImagePixelTestFn) Image {
func CreateIcon(ctx Context, test ImagePixelTestFn) Texture {
icon := DrawIcon(test)
return createImage(ctx, icon)
return createTexture(ctx, icon)
}
func CreateImage(ctx Context, size geom.Point, test ImagePixelTestFn) Image {
func CreateTexture(ctx Context, size geom.Point, test ImagePixelTestFn) Texture {
image := DrawImage(size, test)
return createImage(ctx, image)
return createTexture(ctx, image)
}
func CreateImageAlpha(ctx Context, size geom.Point, test ImageAlphaPixelTestFn) Image {
func CreateTextureAlpha(ctx Context, size geom.Point, test ImageAlphaPixelTestFn) Texture {
image := DrawImageAlpha(size, test)
return createImage(ctx, image)
return createTexture(ctx, image)
}
func DrawIcon(test ImagePixelTestFn) image.Image {
@ -66,18 +66,18 @@ func DrawImageAlpha(size geom.Point, test ImageAlphaPixelTestFn) image.Image {
return icon
}
func GetOrCreateIcon(ctx Context, name string, testFactory func() ImagePixelTestFn) Image {
im := ctx.Images().Image(name)
if im != nil {
return im
func GetOrCreateIcon(ctx Context, name string, testFactory func() ImagePixelTestFn) Texture {
texture := ctx.Textures().Texture(name)
if texture != nil {
return texture
}
test := testFactory()
im = CreateIcon(ctx, test)
if im == nil {
texture = CreateIcon(ctx, test)
if texture == nil {
return nil
}
ctx.Images().AddImage(name, im)
return im
ctx.Textures().AddTexture(name, texture)
return texture
}
func IconSize() geom.Point {

View File

@ -1,123 +0,0 @@
package ui
import (
"image"
"github.com/nfnt/resize"
"opslag.de/schobers/geom"
)
type CreateImageFn func() (image.Image, error)
func ScaleImage(render Renderer, im Image, scale float32) Image {
w := uint(im.Width() * scale)
if w == 0 {
return nil
}
scaled := resize.Resize(w, 0, im.Image(), resize.Bilinear)
res, err := render.CreateImage(scaled)
if err != nil {
return nil
}
return res
}
type Images struct {
render Renderer
ims map[string]Image
scaled map[Image]ScaledImages
}
func NewImages(render Renderer) *Images {
return &Images{render, map[string]Image{}, map[Image]ScaledImages{}}
}
func (i *Images) AddImage(name string, im Image) {
curr := i.ims[name]
if curr != nil {
curr.Destroy()
}
i.ims[name] = im
}
func (i *Images) AddImageFn(name string, create CreateImageFn) error {
im, err := create()
if err != nil {
return err
}
return i.AddImageNative(name, im)
}
func (i *Images) AddImageNative(name string, im image.Image) error {
m, err := i.render.CreateImage(im)
if err != nil {
return err
}
i.AddImage(name, m)
return nil
}
func (i *Images) Destroy() {
for _, im := range i.ims {
im.Destroy()
}
i.ims = nil
for _, ims := range i.scaled {
ims.Destroy()
}
i.scaled = nil
}
func (i *Images) Image(name string) Image {
im, ok := i.ims[name]
if ok {
return im
}
return nil
}
func (i *Images) Scaled(im Image, scale float32) Image {
if scale <= 0 {
return nil
}
if scale == 1 {
return im
}
ims := i.scaled[im]
if ims == nil {
ims = make(ScaledImages)
} else {
scaled := ims[scale]
if scaled != nil {
return scaled
}
}
scaled := ScaleImage(i.render, im, scale)
ims[scale] = scaled
i.scaled[im] = ims
return scaled
}
func (i *Images) ScaledHeight(im Image, height float32) (Image, float32) {
scale := height / im.Height()
if geom.IsNaN32(scale) {
return nil, 0
}
return i.Scaled(im, scale), scale
}
func (i *Images) ScaledByName(name string, scale float32) Image {
im := i.Image(name)
if im == nil {
return nil
}
return i.Scaled(im, scale)
}
type ScaledImages map[float32]Image
func (i ScaledImages) Destroy() {
for _, im := range i {
im.Destroy()
}
}

View File

@ -17,21 +17,21 @@ type Renderer interface {
// Drawing
Clear(c color.Color)
CreateImage(m image.Image) (Image, error)
CreateImagePath(path string) (Image, error)
CreateImageSize(w, h float32) (Image, error)
DefaultTarget() Image
DrawImage(im Image, p geom.PointF32)
DrawImageOptions(im Image, p geom.PointF32, opts DrawOptions)
CreateTexture(m image.Image) (Texture, error)
CreateTexturePath(path string) (Texture, error)
CreateTextureSize(w, h float32) (Texture, error)
DefaultTarget() Texture
DrawTexture(t Texture, p geom.PointF32)
DrawTextureOptions(t Texture, p geom.PointF32, opts DrawOptions)
FillRectangle(r geom.RectangleF32, c color.Color)
Font(name string) Font
Rectangle(r geom.RectangleF32, c color.Color, thickness float32)
RegisterFont(name, path string, size int) error
RenderTo(Image)
RenderTo(Texture)
RenderToDisplay()
SetMouseCursor(c MouseCursor)
Size() geom.PointF32
Target() Image
Target() Texture
Text(p geom.PointF32, font string, color color.Color, text string)
TextAlign(p geom.PointF32, font string, color color.Color, text string, align HorizontalAlignment)
}

View File

@ -134,17 +134,17 @@ func (s *Slider) OnValueChanged(fn func(float32)) {
type sliderHandle struct {
ControlBase
handle Image
handle Texture
}
func (h *sliderHandle) im(ctx Context) Image {
func (h *sliderHandle) texture(ctx Context) Texture {
if h.handle != nil {
return h.handle
}
size := h.Bounds().Size()
center := geom.PtF32(.5*size.X-.5, .5*size.Y-.5)
radius := 0.5 * geom.Min32(size.X, size.Y)
h.handle = CreateImageAlpha(ctx, geom.Pt(int(size.X), int(size.Y)), func(p geom.PointF32) uint8 {
h.handle = CreateTextureAlpha(ctx, geom.Pt(int(size.X), int(size.Y)), func(p geom.PointF32) uint8 {
dist := center.Distance(p)
if dist < radius {
if dist < (radius - 1) {
@ -169,5 +169,5 @@ func (h *sliderHandle) Render(ctx Context) {
if h.IsOver() {
color = ctx.Style().Palette.PrimaryLight
}
ctx.Renderer().DrawImageOptions(h.im(ctx), h.Bounds().Min, DrawOptions{Tint: color})
ctx.Renderer().DrawTextureOptions(h.texture(ctx), h.Bounds().Min, DrawOptions{Tint: color})
}

View File

@ -2,9 +2,9 @@ package ui
import "image"
type Image interface {
type Texture interface {
Destroy()
Height() float32
Image() image.Image
Texture() image.Image
Width() float32
}

123
ui/textures.go Normal file
View File

@ -0,0 +1,123 @@
package ui
import (
"image"
"github.com/nfnt/resize"
"opslag.de/schobers/geom"
)
type CreateImageFn func() (image.Image, error)
func ScaleTexture(render Renderer, texture Texture, scale float32) Texture {
w := uint(texture.Width() * scale)
if w == 0 {
return nil
}
scaled := resize.Resize(w, 0, texture.Texture(), resize.Bilinear)
res, err := render.CreateTexture(scaled)
if err != nil {
return nil
}
return res
}
type Textures struct {
render Renderer
textures map[string]Texture
scaled map[Texture]ScaledTextures
}
func NewTextures(render Renderer) *Textures {
return &Textures{render, map[string]Texture{}, map[Texture]ScaledTextures{}}
}
func (t *Textures) AddTexture(name string, texture Texture) {
curr := t.textures[name]
if curr != nil {
curr.Destroy()
}
t.textures[name] = texture
}
func (t *Textures) AddTextureFn(name string, create CreateImageFn) error {
im, err := create()
if err != nil {
return err
}
return t.AddTextureNative(name, im)
}
func (t *Textures) AddTextureNative(name string, im image.Image) error {
texture, err := t.render.CreateTexture(im)
if err != nil {
return err
}
t.AddTexture(name, texture)
return nil
}
func (t *Textures) Destroy() {
for _, texture := range t.textures {
texture.Destroy()
}
t.textures = nil
for _, textures := range t.scaled {
textures.Destroy()
}
t.scaled = nil
}
func (t *Textures) Texture(name string) Texture {
texture, ok := t.textures[name]
if ok {
return texture
}
return nil
}
func (t *Textures) Scaled(texture Texture, scale float32) Texture {
if scale <= 0 {
return nil
}
if scale == 1 {
return texture
}
textures := t.scaled[texture]
if textures == nil {
textures = make(ScaledTextures)
} else {
scaled := textures[scale]
if scaled != nil {
return scaled
}
}
scaled := ScaleTexture(t.render, texture, scale)
textures[scale] = scaled
t.scaled[texture] = textures
return scaled
}
func (t *Textures) ScaledHeight(textures Texture, height float32) (Texture, float32) {
scale := height / textures.Height()
if geom.IsNaN32(scale) {
return nil, 0
}
return t.Scaled(textures, scale), scale
}
func (t *Textures) ScaledByName(name string, scale float32) Texture {
textures := t.Texture(name)
if textures == nil {
return nil
}
return t.Scaled(textures, scale)
}
type ScaledTextures map[float32]Texture
func (t ScaledTextures) Destroy() {
for _, textures := range t {
textures.Destroy()
}
}

View File

@ -13,7 +13,7 @@ func Run(r Renderer, s *Style, view Control) error {
// RunWait runs the application loop and conditionally waits on events before rendering.
func RunWait(r Renderer, s *Style, view Control, wait bool) error {
ctx := &context{quit: make(chan struct{}), r: r, style: s, view: view, ims: NewImages(r)}
ctx := &context{quit: make(chan struct{}), r: r, style: s, view: view, textures: NewTextures(r)}
root, ok := view.(RootControl)
if ok {
err := root.Init(ctx)