diff --git a/geometry.go b/geometry.go index 7e26f66659..d77f3e8527 100644 --- a/geometry.go +++ b/geometry.go @@ -49,6 +49,11 @@ func (p Position) Add(v Vector2) Position { return Position{p.X + x, p.Y + y} } +// AddXY returns a new Position by adding x and y to the current one. +func (p Position) AddXY(x, y float32) Position { + return Position{p.X + x, p.Y + y} +} + // Components returns the X and Y elements of this Position func (p Position) Components() (float32, float32) { return p.X, p.Y @@ -66,6 +71,11 @@ func (p Position) Subtract(v Vector2) Position { return Position{p.X - x, p.Y - y} } +// SubtractXY returns a new Position by subtracting x and y from the current one. +func (p Position) SubtractXY(x, y float32) Position { + return Position{p.X - x, p.Y - y} +} + // Size describes something with width and height. type Size struct { Width float32 // The number of units along the X axis. @@ -84,6 +94,11 @@ func (s Size) Add(v Vector2) Size { return Size{s.Width + w, s.Height + h} } +// AddWidthHeight returns a new Size by adding width and height to the current one. +func (s Size) AddWidthHeight(width, height float32) Size { + return Size{s.Width + width, s.Height + height} +} + // IsZero returns whether the Size has zero width and zero height. func (s Size) IsZero() bool { return s.Width == 0.0 && s.Height == 0.0 @@ -120,3 +135,8 @@ func (s Size) Subtract(v Vector2) Size { w, h := v.Components() return Size{s.Width - w, s.Height - h} } + +// SubtractWidthHeight returns a new Size by subtracting width and height from the current one. +func (s Size) SubtractWidthHeight(width, height float32) Size { + return Size{s.Width - width, s.Height - height} +} diff --git a/geometry_benchmark_test.go b/geometry_benchmark_test.go new file mode 100644 index 0000000000..2540ad3334 --- /dev/null +++ b/geometry_benchmark_test.go @@ -0,0 +1,129 @@ +// +build !ci + +package fyne_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "fyne.io/fyne/v2" +) + +func BenchmarkPosition_Add(b *testing.B) { + b.Run("Add()", benchmarkPositionAdd) + b.Run("AddXY()", benchmarkPositionAddXY) +} + +func BenchmarkPosition_Subtract(b *testing.B) { + b.Run("Subtract()", benchmarkPositionSubtract) + b.Run("SubtractXY()", benchmarkPositionSubtractXY) +} + +func BenchmarkSize_Add(b *testing.B) { + b.Run("Add()", benchmarkSizeAdd) + b.Run("AddWidthHeight()", benchmarkSizeAddWidthHeight) +} + +func BenchmarkSize_Subtract(b *testing.B) { + b.Run("Subtract()", benchmarkSizeSubtract) + b.Run("SubtractWidthHeight()", benchmarkSizeSubtractWidthHeight) +} + +// This test prevents Position.Add to be simplified to `return p.AddXY(v.Components())` +// because this slows down the speed by factor 10. +func TestPosition_Add_Speed(t *testing.T) { + add := testing.Benchmark(benchmarkPositionAdd) + addXY := testing.Benchmark(benchmarkPositionAddXY) + assert.Less(t, add.NsPerOp()/addXY.NsPerOp(), int64(5)) +} + +// This test prevents Position.Subtract to be simplified to `return p.SubtractXY(v.Components())` +// because this slows down the speed by factor 10. +func TestPosition_Subtract_Speed(t *testing.T) { + subtract := testing.Benchmark(benchmarkPositionSubtract) + subtractXY := testing.Benchmark(benchmarkPositionSubtractXY) + assert.Less(t, subtract.NsPerOp()/subtractXY.NsPerOp(), int64(5)) +} + +// This test prevents Size.Add to be simplified to `return s.AddWidthHeight(v.Components())` +// because this slows down the speed by factor 10. +func TestSize_Add_Speed(t *testing.T) { + add := testing.Benchmark(benchmarkSizeAdd) + addWidthHeight := testing.Benchmark(benchmarkSizeAddWidthHeight) + assert.Less(t, add.NsPerOp()/addWidthHeight.NsPerOp(), int64(5)) +} + +// This test prevents Size.Subtract to be simplified to `return s.SubtractWidthHeight(v.Components())` +// because this slows down the speed by factor 10. +func TestSize_Subtract_Speed(t *testing.T) { + subtract := testing.Benchmark(benchmarkSizeSubtract) + subtractWidthHeight := testing.Benchmark(benchmarkSizeSubtractWidthHeight) + assert.Less(t, subtract.NsPerOp()/subtractWidthHeight.NsPerOp(), int64(5)) +} + +var benchmarkResult interface{} + +func benchmarkPositionAdd(b *testing.B) { + pos := fyne.NewPos(10, 10) + for n := 0; n < b.N; n++ { + pos = pos.Add(fyne.NewPos(float32(n), float32(n))) + } + benchmarkResult = pos +} + +func benchmarkPositionAddXY(b *testing.B) { + pos := fyne.NewPos(10, 10) + for n := 0; n < b.N; n++ { + pos = pos.AddXY(float32(n), float32(n)) + } + benchmarkResult = pos +} + +func benchmarkPositionSubtract(b *testing.B) { + pos := fyne.NewPos(10, 10) + for n := 0; n < b.N; n++ { + pos = pos.Subtract(fyne.NewPos(float32(n), float32(n))) + } + benchmarkResult = pos +} + +func benchmarkPositionSubtractXY(b *testing.B) { + pos := fyne.NewPos(10, 10) + for n := 0; n < b.N; n++ { + pos = pos.SubtractXY(float32(n), float32(n)) + } + benchmarkResult = pos +} + +func benchmarkSizeAdd(b *testing.B) { + size := fyne.NewSize(10, 10) + for n := 0; n < b.N; n++ { + size = size.Add(fyne.NewPos(float32(n), float32(n))) + } + benchmarkResult = size +} + +func benchmarkSizeAddWidthHeight(b *testing.B) { + size := fyne.NewSize(10, 10) + for n := 0; n < b.N; n++ { + size = size.AddWidthHeight(float32(n), float32(n)) + } + benchmarkResult = size +} + +func benchmarkSizeSubtract(b *testing.B) { + size := fyne.NewSize(10, 10) + for n := 0; n < b.N; n++ { + size = size.Subtract(fyne.NewSize(float32(n), float32(n))) + } + benchmarkResult = size +} + +func benchmarkSizeSubtractWidthHeight(b *testing.B) { + size := fyne.NewSize(10, 10) + for n := 0; n < b.N; n++ { + size = size.SubtractWidthHeight(float32(n), float32(n)) + } + benchmarkResult = size +} diff --git a/geometry_test.go b/geometry_test.go index 34619d4569..7396d02b35 100644 --- a/geometry_test.go +++ b/geometry_test.go @@ -1,14 +1,15 @@ -package fyne +package fyne_test import ( "testing" + "fyne.io/fyne/v2" "github.com/stretchr/testify/assert" ) func TestPosition_Add(t *testing.T) { - pos1 := NewPos(10, 10) - pos2 := NewPos(25, 25) + pos1 := fyne.NewPos(10, 10) + pos2 := fyne.NewPos(25, 25) pos3 := pos1.Add(pos2) @@ -17,8 +18,8 @@ func TestPosition_Add(t *testing.T) { } func TestPosition_Add_Size(t *testing.T) { - pos1 := NewPos(10, 10) - s := NewSize(25, 25) + pos1 := fyne.NewPos(10, 10) + s := fyne.NewSize(25, 25) pos2 := pos1.Add(s) @@ -27,8 +28,8 @@ func TestPosition_Add_Size(t *testing.T) { } func TestPosition_Add_Vector(t *testing.T) { - pos1 := NewPos(10, 10) - v := NewDelta(25, 25) + pos1 := fyne.NewPos(10, 10) + v := fyne.NewDelta(25, 25) pos2 := pos1.Add(v) @@ -36,16 +37,25 @@ func TestPosition_Add_Vector(t *testing.T) { assert.Equal(t, float32(35), pos2.Y) } +func TestPosition_AddXY(t *testing.T) { + pos1 := fyne.NewPos(10, 10) + + pos2 := pos1.AddXY(25, 25) + + assert.Equal(t, float32(35), pos2.X) + assert.Equal(t, float32(35), pos2.Y) +} + func TestPosition_IsZero(t *testing.T) { for name, tt := range map[string]struct { - p Position + p fyne.Position want bool }{ - "zero value": {Position{}, true}, - "0,0": {NewPos(0, 0), true}, - "zero X": {NewPos(0, 42), false}, - "zero Y": {NewPos(17, 0), false}, - "non-zero X and Y": {NewPos(6, 9), false}, + "zero value": {fyne.Position{}, true}, + "0,0": {fyne.NewPos(0, 0), true}, + "zero X": {fyne.NewPos(0, 42), false}, + "zero Y": {fyne.NewPos(17, 0), false}, + "non-zero X and Y": {fyne.NewPos(6, 9), false}, } { t.Run(name, func(t *testing.T) { assert.Equal(t, tt.want, tt.p.IsZero()) @@ -54,8 +64,8 @@ func TestPosition_IsZero(t *testing.T) { } func TestPosition_Subtract(t *testing.T) { - pos1 := NewPos(25, 25) - pos2 := NewPos(10, 10) + pos1 := fyne.NewPos(25, 25) + pos2 := fyne.NewPos(10, 10) pos3 := pos1.Subtract(pos2) @@ -63,9 +73,18 @@ func TestPosition_Subtract(t *testing.T) { assert.Equal(t, float32(15), pos3.Y) } +func TestPosition_SubtractXY(t *testing.T) { + pos1 := fyne.NewPos(25, 25) + + pos2 := pos1.SubtractXY(10, 10) + + assert.Equal(t, float32(15), pos2.X) + assert.Equal(t, float32(15), pos2.Y) +} + func TestSize_Add(t *testing.T) { - size1 := NewSize(10, 10) - size2 := NewSize(25, 25) + size1 := fyne.NewSize(10, 10) + size2 := fyne.NewSize(25, 25) size3 := size1.Add(size2) @@ -74,8 +93,8 @@ func TestSize_Add(t *testing.T) { } func TestSize_Add_Position(t *testing.T) { - size1 := NewSize(10, 10) - p := NewSize(25, 25) + size1 := fyne.NewSize(10, 10) + p := fyne.NewSize(25, 25) size2 := size1.Add(p) @@ -84,8 +103,8 @@ func TestSize_Add_Position(t *testing.T) { } func TestSize_Add_Vector(t *testing.T) { - size1 := NewSize(10, 10) - v := NewDelta(25, 25) + size1 := fyne.NewSize(10, 10) + v := fyne.NewDelta(25, 25) size2 := size1.Add(v) @@ -93,16 +112,25 @@ func TestSize_Add_Vector(t *testing.T) { assert.Equal(t, float32(35), size2.Height) } +func TestSize_AddWidthHeight(t *testing.T) { + size1 := fyne.NewSize(10, 10) + + size2 := size1.AddWidthHeight(25, 25) + + assert.Equal(t, float32(35), size2.Width) + assert.Equal(t, float32(35), size2.Height) +} + func TestSize_IsZero(t *testing.T) { for name, tt := range map[string]struct { - s Size + s fyne.Size want bool }{ - "zero value": {Size{}, true}, - "0x0": {NewSize(0, 0), true}, - "zero width": {NewSize(0, 42), false}, - "zero height": {NewSize(17, 0), false}, - "non-zero area": {NewSize(6, 9), false}, + "zero value": {fyne.Size{}, true}, + "0x0": {fyne.NewSize(0, 0), true}, + "zero width": {fyne.NewSize(0, 42), false}, + "zero height": {fyne.NewSize(17, 0), false}, + "non-zero area": {fyne.NewSize(6, 9), false}, } { t.Run(name, func(t *testing.T) { assert.Equal(t, tt.want, tt.s.IsZero()) @@ -111,8 +139,8 @@ func TestSize_IsZero(t *testing.T) { } func TestSize_Max(t *testing.T) { - size1 := NewSize(10, 100) - size2 := NewSize(100, 10) + size1 := fyne.NewSize(10, 100) + size2 := fyne.NewSize(100, 10) size3 := size1.Max(size2) @@ -121,8 +149,8 @@ func TestSize_Max(t *testing.T) { } func TestSize_Min(t *testing.T) { - size1 := NewSize(10, 100) - size2 := NewSize(100, 10) + size1 := fyne.NewSize(10, 100) + size2 := fyne.NewSize(100, 10) size3 := size1.Min(size2) @@ -131,8 +159,8 @@ func TestSize_Min(t *testing.T) { } func TestSize_Subtract(t *testing.T) { - size1 := NewSize(25, 25) - size2 := NewSize(10, 10) + size1 := fyne.NewSize(25, 25) + size2 := fyne.NewSize(10, 10) size3 := size1.Subtract(size2) @@ -140,8 +168,17 @@ func TestSize_Subtract(t *testing.T) { assert.Equal(t, float32(15), size3.Height) } +func TestSize_SubtractWidthHeight(t *testing.T) { + size1 := fyne.NewSize(25, 25) + + size2 := size1.SubtractWidthHeight(10, 10) + + assert.Equal(t, float32(15), size2.Width) + assert.Equal(t, float32(15), size2.Height) +} + func TestVector_IsZero(t *testing.T) { - v := NewDelta(0, 0) + v := fyne.NewDelta(0, 0) assert.True(t, v.IsZero())