forked from joejulian/gio
all: [API] change clip.RRect and UniformRRect to take integer coordinates
Like the change to op.Offset before this, clip.RRect and UniformRRect is usually used with integer coordinates. Change to integer coordinates to eliminate many useless conversions to float32. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -7,7 +7,6 @@ import (
|
||||
"image/color"
|
||||
"testing"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/op"
|
||||
"gioui.org/op/clip"
|
||||
@@ -50,20 +49,14 @@ func TestClipping(t *testing.T) {
|
||||
var ops op.Ops
|
||||
paint.ColorOp{Color: col}.Add(&ops)
|
||||
clip.RRect{
|
||||
Rect: f32.Rectangle{
|
||||
Min: f32.Point{X: 50, Y: 50},
|
||||
Max: f32.Point{X: 250, Y: 250},
|
||||
},
|
||||
SE: 75,
|
||||
Rect: image.Rect(50, 50, 250, 250),
|
||||
SE: 75,
|
||||
}.Push(&ops)
|
||||
paint.PaintOp{}.Add(&ops)
|
||||
paint.ColorOp{Color: col2}.Add(&ops)
|
||||
clip.RRect{
|
||||
Rect: f32.Rectangle{
|
||||
Min: f32.Point{X: 100, Y: 100},
|
||||
Max: f32.Point{X: 350, Y: 350},
|
||||
},
|
||||
NW: 75,
|
||||
Rect: image.Rect(100, 100, 350, 350),
|
||||
NW: 75,
|
||||
}.Push(&ops)
|
||||
paint.PaintOp{}.Add(&ops)
|
||||
if err := w.Frame(&ops); err != nil {
|
||||
|
||||
@@ -161,7 +161,7 @@ func draw1000Circles(gtx layout.Context) {
|
||||
for y := 0; y < 10; y++ {
|
||||
paint.FillShape(ops,
|
||||
color.NRGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120},
|
||||
clip.RRect{Rect: f32.Rect(0, 0, 10, 10), NE: 5, SE: 5, SW: 5, NW: 5}.Op(ops),
|
||||
clip.RRect{Rect: image.Rect(0, 0, 10, 10), NE: 5, SE: 5, SW: 5, NW: 5}.Op(ops),
|
||||
)
|
||||
op.Offset(image.Pt(0, 100)).Add(ops)
|
||||
}
|
||||
@@ -172,7 +172,7 @@ func draw1000CirclesInstanced(gtx layout.Context) {
|
||||
ops := gtx.Ops
|
||||
|
||||
r := op.Record(ops)
|
||||
cl := clip.RRect{Rect: f32.Rect(0, 0, 10, 10), NE: 5, SE: 5, SW: 5, NW: 5}.Push(ops)
|
||||
cl := clip.RRect{Rect: image.Rect(0, 0, 10, 10), NE: 5, SE: 5, SW: 5, NW: 5}.Push(ops)
|
||||
paint.PaintOp{}.Add(ops)
|
||||
cl.Pop()
|
||||
c := r.Stop()
|
||||
@@ -207,7 +207,7 @@ func drawIndividualShapes(gtx layout.Context, th *material.Theme) chan op.CallOp
|
||||
for y := 0; y < 9; y++ {
|
||||
paint.FillShape(ops,
|
||||
color.NRGBA{R: 100 + uint8(x), G: 100 + uint8(y), B: 100, A: 120},
|
||||
clip.RRect{Rect: f32.Rect(0, 0, 25, 25), NE: 10, SE: 10, SW: 10, NW: 10}.Op(ops),
|
||||
clip.RRect{Rect: image.Rect(0, 0, 25, 25), NE: 10, SE: 10, SW: 10, NW: 10}.Op(ops),
|
||||
)
|
||||
op.Offset(image.Pt(0, 50)).Add(ops)
|
||||
}
|
||||
@@ -224,7 +224,7 @@ func drawShapeInstances(gtx layout.Context, th *material.Theme) chan op.CallOp {
|
||||
co := op.Record(ops)
|
||||
|
||||
r := op.Record(ops)
|
||||
cl := clip.RRect{Rect: f32.Rect(0, 0, 25, 25), NE: 10, SE: 10, SW: 10, NW: 10}.Push(ops)
|
||||
cl := clip.RRect{Rect: image.Rect(0, 0, 25, 25), NE: 10, SE: 10, SW: 10, NW: 10}.Push(ops)
|
||||
paint.PaintOp{}.Add(ops)
|
||||
cl.Pop()
|
||||
c := r.Stop()
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestPaintRect(t *testing.T) {
|
||||
|
||||
func TestPaintClippedRect(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
defer clip.RRect{Rect: f32.Rect(25, 25, 60, 60)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(25, 25, 60, 60)}.Push(o).Pop()
|
||||
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 50, 50)).Op())
|
||||
}, func(r result) {
|
||||
r.expect(0, 0, transparent)
|
||||
@@ -42,8 +42,8 @@ func TestPaintClippedRect(t *testing.T) {
|
||||
|
||||
func TestPaintClippedCircle(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
r := float32(10)
|
||||
defer clip.RRect{Rect: f32.Rect(20, 20, 40, 40), SE: r, SW: r, NW: r, NE: r}.Push(o).Pop()
|
||||
const r = 10
|
||||
defer clip.RRect{Rect: image.Rect(20, 20, 40, 40), SE: r, SW: r, NW: r, NE: r}.Push(o).Pop()
|
||||
defer clip.Rect(image.Rect(0, 0, 30, 50)).Push(o).Pop()
|
||||
paint.Fill(o, red)
|
||||
}, func(r result) {
|
||||
@@ -126,10 +126,10 @@ func TestTexturedStrokeClipped(t *testing.T) {
|
||||
smallSquares.Add(o)
|
||||
defer op.Offset(image.Pt(50, 50)).Push(o).Pop()
|
||||
defer clip.Stroke{
|
||||
Path: clip.RRect{Rect: f32.Rect(0, 0, 30, 30)}.Path(o),
|
||||
Path: clip.RRect{Rect: image.Rect(0, 0, 30, 30)}.Path(o),
|
||||
Width: 10,
|
||||
}.Op().Push(o).Pop()
|
||||
defer clip.RRect{Rect: f32.Rect(-30, -30, 60, 60)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(-30, -30, 60, 60)}.Push(o).Pop()
|
||||
defer op.Offset(image.Pt(-10, -10)).Push(o).Pop()
|
||||
paint.PaintOp{}.Add(o)
|
||||
}, func(r result) {
|
||||
@@ -141,7 +141,7 @@ func TestTexturedStroke(t *testing.T) {
|
||||
smallSquares.Add(o)
|
||||
defer op.Offset(image.Pt(50, 50)).Push(o).Pop()
|
||||
defer clip.Stroke{
|
||||
Path: clip.RRect{Rect: f32.Rect(0, 0, 30, 30)}.Path(o),
|
||||
Path: clip.RRect{Rect: image.Rect(0, 0, 30, 30)}.Path(o),
|
||||
Width: 10,
|
||||
}.Op().Push(o).Pop()
|
||||
defer op.Offset(image.Pt(-10, -10)).Push(o).Pop()
|
||||
@@ -153,7 +153,7 @@ func TestTexturedStroke(t *testing.T) {
|
||||
func TestPaintClippedTexture(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
squares.Add(o)
|
||||
defer clip.RRect{Rect: f32.Rect(0, 0, 40, 40)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(0, 0, 40, 40)}.Push(o).Pop()
|
||||
defer scale(80.0/512, 80.0/512).Push(o).Pop()
|
||||
paint.PaintOp{}.Add(o)
|
||||
}, func(r result) {
|
||||
|
||||
@@ -143,7 +143,7 @@ func constSqPath() clip.Op {
|
||||
|
||||
func constSqCirc() clip.Op {
|
||||
innerOps := new(op.Ops)
|
||||
return clip.RRect{Rect: f32.Rect(0, 0, 40, 40),
|
||||
return clip.RRect{Rect: image.Rect(0, 0, 40, 40),
|
||||
NW: 20, NE: 20, SW: 20, SE: 20}.Op(innerOps)
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ func TestBuildOffscreen(t *testing.T) {
|
||||
|
||||
func TestNegativeOverlaps(t *testing.T) {
|
||||
run(t, func(ops *op.Ops) {
|
||||
defer clip.RRect{Rect: f32.Rect(50, 50, 100, 100)}.Push(ops).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(50, 50, 100, 100)}.Push(ops).Pop()
|
||||
clip.Rect(image.Rect(0, 120, 100, 122)).Push(ops).Pop()
|
||||
paint.PaintOp{}.Add(ops)
|
||||
}, func(r result) {
|
||||
@@ -257,7 +257,7 @@ func TestLinearGradient(t *testing.T) {
|
||||
Stop2: f32.Pt(gr.Max.X, gr.Min.Y),
|
||||
Color2: g.To,
|
||||
}.Add(ops)
|
||||
cl := clip.RRect{Rect: gr}.Push(ops)
|
||||
cl := clip.RRect{Rect: gr.Round()}.Push(ops)
|
||||
t1 := op.Affine(f32.Affine2D{}.Offset(pixelAligned.Min)).Push(ops)
|
||||
t2 := scale(pixelAligned.Dx()/128, 1).Push(ops)
|
||||
paint.PaintOp{}.Add(ops)
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestPaintShear(t *testing.T) {
|
||||
|
||||
func TestClipPaintOffset(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
defer clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(10, 10, 30, 30)}.Push(o).Pop()
|
||||
defer op.Offset(image.Pt(20, 20)).Push(o).Pop()
|
||||
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
|
||||
}, func(r result) {
|
||||
@@ -66,7 +66,7 @@ func TestClipPaintOffset(t *testing.T) {
|
||||
func TestClipOffset(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
defer op.Offset(image.Pt(20, 20)).Push(o).Pop()
|
||||
defer clip.RRect{Rect: f32.Rect(10, 10, 30, 30)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(10, 10, 30, 30)}.Push(o).Pop()
|
||||
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 100, 100)).Op())
|
||||
}, func(r result) {
|
||||
r.expect(0, 0, transparent)
|
||||
@@ -81,7 +81,7 @@ func TestClipScale(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
a := f32.Affine2D{}.Scale(f32.Point{}, f32.Pt(2, 2)).Offset(f32.Pt(10, 10))
|
||||
defer op.Affine(a).Push(o).Pop()
|
||||
defer clip.RRect{Rect: f32.Rect(10, 10, 20, 20)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(10, 10, 20, 20)}.Push(o).Pop()
|
||||
paint.FillShape(o, red, clip.Rect(image.Rect(0, 0, 1000, 1000)).Op())
|
||||
}, func(r result) {
|
||||
r.expect(19+10, 19+10, transparent)
|
||||
@@ -94,7 +94,7 @@ func TestClipScale(t *testing.T) {
|
||||
func TestClipRotate(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
defer op.Affine(f32.Affine2D{}.Rotate(f32.Pt(40, 40), -math.Pi/4)).Push(o).Pop()
|
||||
defer clip.RRect{Rect: f32.Rect(30, 30, 50, 50)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(30, 30, 50, 50)}.Push(o).Pop()
|
||||
paint.FillShape(o, red, clip.Rect(image.Rect(0, 40, 100, 100)).Op())
|
||||
}, func(r result) {
|
||||
r.expect(39, 39, transparent)
|
||||
@@ -148,7 +148,7 @@ func TestRotateClipTexture(t *testing.T) {
|
||||
squares.Add(o)
|
||||
a := f32.Affine2D{}.Rotate(f32.Pt(40, 40), math.Pi/8)
|
||||
defer op.Affine(a).Push(o).Pop()
|
||||
defer clip.RRect{Rect: f32.Rect(30, 30, 50, 50)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(30, 30, 50, 50)}.Push(o).Pop()
|
||||
defer op.Affine(f32.Affine2D{}.Offset(f32.Pt(10, 10))).Push(o).Pop()
|
||||
defer scale(60.0/512, 60.0/512).Push(o).Pop()
|
||||
paint.PaintOp{}.Add(o)
|
||||
@@ -166,11 +166,11 @@ func TestComplicatedTransform(t *testing.T) {
|
||||
run(t, func(o *op.Ops) {
|
||||
squares.Add(o)
|
||||
|
||||
defer clip.RRect{Rect: f32.Rect(0, 0, 100, 100), SE: 50, SW: 50, NW: 50, NE: 50}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(0, 0, 100, 100), SE: 50, SW: 50, NW: 50, NE: 50}.Push(o).Pop()
|
||||
|
||||
a := f32.Affine2D{}.Shear(f32.Point{}, math.Pi/4, 0)
|
||||
defer op.Affine(a).Push(o).Pop()
|
||||
defer clip.RRect{Rect: f32.Rect(0, 0, 50, 40)}.Push(o).Pop()
|
||||
defer clip.RRect{Rect: image.Rect(0, 0, 50, 40)}.Push(o).Pop()
|
||||
|
||||
defer scale(50.0/512, 50.0/512).Push(o).Pop()
|
||||
paint.PaintOp{}.Add(o)
|
||||
|
||||
@@ -741,7 +741,7 @@ func TestEllipse(t *testing.T) {
|
||||
var ops op.Ops
|
||||
|
||||
h := new(int)
|
||||
cl := clip.Ellipse(f32.Rect(0, 0, 100, 100)).Push(&ops)
|
||||
cl := clip.Ellipse(image.Rect(0, 0, 100, 100)).Push(&ops)
|
||||
pointer.InputOp{Tag: h, Types: pointer.Press}.Add(&ops)
|
||||
cl.Pop()
|
||||
var r Router
|
||||
|
||||
+13
-24
@@ -37,7 +37,7 @@ func (r Rect) Path() PathSpec {
|
||||
|
||||
// UniformRRect returns an RRect with all corner radii set to the
|
||||
// provided radius.
|
||||
func UniformRRect(rect f32.Rectangle, radius float32) RRect {
|
||||
func UniformRRect(rect image.Rectangle, radius int) RRect {
|
||||
return RRect{
|
||||
Rect: rect,
|
||||
SE: radius,
|
||||
@@ -53,22 +53,15 @@ func UniformRRect(rect f32.Rectangle, radius float32) RRect {
|
||||
// Specify a square with corner radii equal to half the square size to
|
||||
// construct a circular clip area.
|
||||
type RRect struct {
|
||||
Rect f32.Rectangle
|
||||
Rect image.Rectangle
|
||||
// The corner radii.
|
||||
SE, SW, NW, NE float32
|
||||
SE, SW, NW, NE int
|
||||
}
|
||||
|
||||
// Op returns the op for the rounded rectangle.
|
||||
func (rr RRect) Op(ops *op.Ops) Op {
|
||||
if rr.SE == 0 && rr.SW == 0 && rr.NW == 0 && rr.NE == 0 {
|
||||
r := image.Rectangle{
|
||||
Min: image.Point{X: int(rr.Rect.Min.X), Y: int(rr.Rect.Min.Y)},
|
||||
Max: image.Point{X: int(rr.Rect.Max.X), Y: int(rr.Rect.Max.Y)},
|
||||
}
|
||||
// Only use Rect if rr is pixel-aligned, as Rect is guaranteed to be.
|
||||
if fPt(r.Min) == rr.Rect.Min && fPt(r.Max) == rr.Rect.Max {
|
||||
return Rect(r).Op()
|
||||
}
|
||||
return Rect(rr.Rect).Op()
|
||||
}
|
||||
return Outline{Path: rr.Path(ops)}.Op()
|
||||
}
|
||||
@@ -87,8 +80,9 @@ func (rr RRect) Path(ops *op.Ops) PathSpec {
|
||||
const q = 4 * (math.Sqrt2 - 1) / 3
|
||||
const iq = 1 - q
|
||||
|
||||
se, sw, nw, ne := rr.SE, rr.SW, rr.NW, rr.NE
|
||||
w, n, e, s := rr.Rect.Min.X, rr.Rect.Min.Y, rr.Rect.Max.X, rr.Rect.Max.Y
|
||||
se, sw, nw, ne := float32(rr.SE), float32(rr.SW), float32(rr.NW), float32(rr.NE)
|
||||
rrf := frect(rr.Rect)
|
||||
w, n, e, s := rrf.Min.X, rrf.Min.Y, rrf.Max.X, rrf.Max.Y
|
||||
|
||||
p.MoveTo(f32.Point{X: w + nw, Y: n})
|
||||
p.LineTo(f32.Point{X: e - ne, Y: n}) // N
|
||||
@@ -117,7 +111,7 @@ func (rr RRect) Path(ops *op.Ops) PathSpec {
|
||||
|
||||
// Ellipse represents the largest axis-aligned ellipse that
|
||||
// is contained in its bounds.
|
||||
type Ellipse f32.Rectangle
|
||||
type Ellipse image.Rectangle
|
||||
|
||||
// Op returns the op for the filled ellipse.
|
||||
func (e Ellipse) Op(ops *op.Ops) Op {
|
||||
@@ -131,7 +125,7 @@ func (e Ellipse) Push(ops *op.Ops) Stack {
|
||||
|
||||
// Path constructs a path for the ellipse.
|
||||
func (e Ellipse) Path(o *op.Ops) PathSpec {
|
||||
bounds := f32.Rectangle(e)
|
||||
bounds := image.Rectangle(e)
|
||||
if bounds.Dx() == 0 || bounds.Dy() == 0 {
|
||||
return PathSpec{shape: ops.Rect}
|
||||
}
|
||||
@@ -139,12 +133,13 @@ func (e Ellipse) Path(o *op.Ops) PathSpec {
|
||||
var p Path
|
||||
p.Begin(o)
|
||||
|
||||
center := bounds.Max.Add(bounds.Min).Mul(.5)
|
||||
diam := bounds.Dx()
|
||||
bf := frect(bounds)
|
||||
center := bf.Max.Add(bf.Min).Mul(.5)
|
||||
diam := bf.Dx()
|
||||
r := diam * .5
|
||||
// We'll model the ellipse as a circle scaled in the Y
|
||||
// direction.
|
||||
scale := bounds.Dy() / diam
|
||||
scale := bf.Dy() / diam
|
||||
|
||||
// https://pomax.github.io/bezierinfo/#circles_cubic.
|
||||
const q = 4 * (math.Sqrt2 - 1) / 3
|
||||
@@ -177,9 +172,3 @@ func (e Ellipse) Path(o *op.Ops) PathSpec {
|
||||
ellipse.shape = ops.Ellipse
|
||||
return ellipse
|
||||
}
|
||||
|
||||
func fPt(p image.Point) f32.Point {
|
||||
return f32.Point{
|
||||
X: float32(p.X), Y: float32(p.Y),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
package clip_test
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"testing"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/op"
|
||||
"gioui.org/op/clip"
|
||||
"gioui.org/op/paint"
|
||||
)
|
||||
|
||||
func TestZeroEllipse(t *testing.T) {
|
||||
p := f32.Pt(1.0, 2.0)
|
||||
p := image.Pt(1.0, 2.0)
|
||||
e := clip.Ellipse{Min: p, Max: p}
|
||||
ops := new(op.Ops)
|
||||
paint.FillShape(ops, color.NRGBA{R: 255, A: 255}, e.Op(ops))
|
||||
|
||||
+7
-7
@@ -3,9 +3,9 @@
|
||||
package widget
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op/clip"
|
||||
"gioui.org/op/paint"
|
||||
@@ -21,21 +21,21 @@ type Border struct {
|
||||
|
||||
func (b Border) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions {
|
||||
dims := w(gtx)
|
||||
sz := layout.FPt(dims.Size)
|
||||
sz := dims.Size
|
||||
|
||||
rr := float32(gtx.Px(b.CornerRadius))
|
||||
width := float32(gtx.Px(b.Width))
|
||||
rr := gtx.Px(b.CornerRadius)
|
||||
width := gtx.Px(b.Width)
|
||||
sz.X -= width
|
||||
sz.Y -= width
|
||||
|
||||
r := f32.Rectangle{Max: sz}
|
||||
r = r.Add(f32.Point{X: width * 0.5, Y: width * 0.5})
|
||||
r := image.Rectangle{Max: sz}
|
||||
r = r.Add(image.Point{X: width / 2, Y: width / 2})
|
||||
|
||||
paint.FillShape(gtx.Ops,
|
||||
b.Color,
|
||||
clip.Stroke{
|
||||
Path: clip.UniformRRect(r, rr).Path(gtx.Ops),
|
||||
Width: width,
|
||||
Width: float32(width),
|
||||
}.Op(),
|
||||
)
|
||||
|
||||
|
||||
+14
-23
@@ -7,7 +7,6 @@ import (
|
||||
"image/color"
|
||||
"math"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/io/semantic"
|
||||
"gioui.org/layout"
|
||||
@@ -130,11 +129,8 @@ func (b ButtonLayoutStyle) Layout(gtx layout.Context, w layout.Widget) layout.Di
|
||||
semantic.Button.Add(gtx.Ops)
|
||||
return layout.Stack{Alignment: layout.Center}.Layout(gtx,
|
||||
layout.Expanded(func(gtx layout.Context) layout.Dimensions {
|
||||
rr := float32(gtx.Px(b.CornerRadius))
|
||||
defer clip.UniformRRect(f32.Rectangle{Max: f32.Point{
|
||||
X: float32(gtx.Constraints.Min.X),
|
||||
Y: float32(gtx.Constraints.Min.Y),
|
||||
}}, rr).Push(gtx.Ops).Pop()
|
||||
rr := gtx.Px(b.CornerRadius)
|
||||
defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop()
|
||||
background := b.Background
|
||||
switch {
|
||||
case gtx.Queue == nil:
|
||||
@@ -165,12 +161,8 @@ func (b IconButtonStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
}
|
||||
return layout.Stack{Alignment: layout.Center}.Layout(gtx,
|
||||
layout.Expanded(func(gtx layout.Context) layout.Dimensions {
|
||||
sizex, sizey := gtx.Constraints.Min.X, gtx.Constraints.Min.Y
|
||||
sizexf, sizeyf := float32(sizex), float32(sizey)
|
||||
rr := (sizexf + sizeyf) * .25
|
||||
defer clip.UniformRRect(f32.Rectangle{
|
||||
Max: f32.Point{X: sizexf, Y: sizeyf},
|
||||
}, rr).Push(gtx.Ops).Pop()
|
||||
rr := (gtx.Constraints.Min.X + gtx.Constraints.Min.Y) / 4
|
||||
defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops).Pop()
|
||||
background := b.Background
|
||||
switch {
|
||||
case gtx.Queue == nil:
|
||||
@@ -199,7 +191,7 @@ func (b IconButtonStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
)
|
||||
})
|
||||
c := m.Stop()
|
||||
bounds := f32.Rectangle{Max: layout.FPt(dims.Size)}
|
||||
bounds := image.Rectangle{Max: dims.Size}
|
||||
defer clip.Ellipse(bounds).Push(gtx.Ops).Pop()
|
||||
c.Add(gtx.Ops)
|
||||
return dims
|
||||
@@ -282,25 +274,24 @@ func drawInk(gtx layout.Context, c widget.Press) {
|
||||
// Beziér ease-in curve.
|
||||
alphaBezier := t2 * t2 * (3.0 - 2.0*t2)
|
||||
sizeBezier := sizet * sizet * (3.0 - 2.0*sizet)
|
||||
size := float32(gtx.Constraints.Min.X)
|
||||
if h := float32(gtx.Constraints.Min.Y); h > size {
|
||||
size := gtx.Constraints.Min.X
|
||||
if h := gtx.Constraints.Min.Y; h > size {
|
||||
size = h
|
||||
}
|
||||
// Cover the entire constraints min rectangle.
|
||||
size *= 2 * float32(math.Sqrt(2))
|
||||
// Apply curve values to size and color.
|
||||
size *= sizeBezier
|
||||
// Cover the entire constraints min rectangle and
|
||||
// apply curve values to size and color.
|
||||
size = int(float32(size) * 2 * float32(math.Sqrt(2)) * sizeBezier)
|
||||
alpha := 0.7 * alphaBezier
|
||||
const col = 0.8
|
||||
ba, bc := byte(alpha*0xff), byte(col*0xff)
|
||||
rgba := f32color.MulAlpha(color.NRGBA{A: 0xff, R: bc, G: bc, B: bc}, ba)
|
||||
ink := paint.ColorOp{Color: rgba}
|
||||
ink.Add(gtx.Ops)
|
||||
rr := size * .5
|
||||
rr := size / 2
|
||||
defer op.Offset(c.Position.Add(image.Point{
|
||||
X: -int(rr),
|
||||
Y: -int(rr),
|
||||
X: -rr,
|
||||
Y: -rr,
|
||||
})).Push(gtx.Ops).Pop()
|
||||
defer clip.UniformRRect(f32.Rectangle{Max: f32.Pt(size, size)}, rr).Push(gtx.Ops).Pop()
|
||||
defer clip.UniformRRect(image.Rectangle{Max: image.Pt(size, size)}, rr).Push(gtx.Ops).Pop()
|
||||
paint.PaintOp{}.Add(gtx.Ops)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op/clip"
|
||||
@@ -50,7 +49,7 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim
|
||||
|
||||
background := f32color.MulAlpha(c.IconColor, 70)
|
||||
|
||||
b := f32.Rectangle{Max: f32.Pt(float32(size), float32(size))}
|
||||
b := image.Rectangle{Max: image.Pt(size, size)}
|
||||
paint.FillShape(gtx.Ops, background, clip.Ellipse(b).Op(gtx.Ops))
|
||||
|
||||
return dims
|
||||
|
||||
@@ -144,19 +144,18 @@ func minimizeWindow(gtx layout.Context) layout.Dimensions {
|
||||
// maximizeWindow draws a rectangle representing the maximize action.
|
||||
func maximizeWindow(gtx layout.Context) layout.Dimensions {
|
||||
size := gtx.Px(winIconSize)
|
||||
size32 := float32(size)
|
||||
margin := float32(gtx.Px(winIconMargin))
|
||||
width := float32(gtx.Px(winIconStroke))
|
||||
margin := gtx.Px(winIconMargin)
|
||||
width := gtx.Px(winIconStroke)
|
||||
r := clip.RRect{
|
||||
Rect: f32.Rect(margin, margin, size32-margin, size32-margin),
|
||||
Rect: image.Rect(margin, margin, size-margin, size-margin),
|
||||
}
|
||||
st := clip.Stroke{
|
||||
Path: r.Path(gtx.Ops),
|
||||
Width: width,
|
||||
Width: float32(width),
|
||||
}.Op().Push(gtx.Ops)
|
||||
paint.PaintOp{}.Add(gtx.Ops)
|
||||
st.Pop()
|
||||
r.Rect.Max = f32.Pt(size32-margin, 2*margin)
|
||||
r.Rect.Max = image.Pt(size-margin, 2*margin)
|
||||
st = clip.Outline{
|
||||
Path: r.Path(gtx.Ops),
|
||||
}.Op().Push(gtx.Ops)
|
||||
@@ -168,24 +167,23 @@ func maximizeWindow(gtx layout.Context) layout.Dimensions {
|
||||
// maximizedWindow draws interleaved rectangles representing the un-maximize action.
|
||||
func maximizedWindow(gtx layout.Context) layout.Dimensions {
|
||||
size := gtx.Px(winIconSize)
|
||||
size32 := float32(size)
|
||||
margin := float32(gtx.Px(winIconMargin))
|
||||
width := float32(gtx.Px(winIconStroke))
|
||||
margin := gtx.Px(winIconMargin)
|
||||
width := gtx.Px(winIconStroke)
|
||||
r := clip.RRect{
|
||||
Rect: f32.Rect(margin, margin, size32-2*margin, size32-2*margin),
|
||||
Rect: image.Rect(margin, margin, size-2*margin, size-2*margin),
|
||||
}
|
||||
st := clip.Stroke{
|
||||
Path: r.Path(gtx.Ops),
|
||||
Width: width,
|
||||
Width: float32(width),
|
||||
}.Op().Push(gtx.Ops)
|
||||
paint.PaintOp{}.Add(gtx.Ops)
|
||||
st.Pop()
|
||||
r = clip.RRect{
|
||||
Rect: f32.Rect(2*margin, 2*margin, size32-margin, size32-margin),
|
||||
Rect: image.Rect(2*margin, 2*margin, size-margin, size-margin),
|
||||
}
|
||||
st = clip.Stroke{
|
||||
Path: r.Path(gtx.Ops),
|
||||
Width: width,
|
||||
Width: float32(width),
|
||||
}.Op().Push(gtx.Ops)
|
||||
paint.PaintOp{}.Add(gtx.Ops)
|
||||
st.Pop()
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"image/color"
|
||||
"math"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/io/pointer"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op"
|
||||
@@ -188,15 +187,14 @@ func (s ScrollbarStyle) layout(gtx layout.Context, axis layout.Axis, viewportSta
|
||||
X: indicatorLen,
|
||||
Y: gtx.Px(s.Indicator.MinorWidth),
|
||||
})
|
||||
indicatorDimsF := layout.FPt(indicatorDims)
|
||||
radius := float32(gtx.Px(s.Indicator.CornerRadius))
|
||||
radius := gtx.Px(s.Indicator.CornerRadius)
|
||||
|
||||
// Lay out the indicator.
|
||||
offset := axis.Convert(image.Pt(viewStart, 0))
|
||||
defer op.Offset(offset).Push(gtx.Ops).Pop()
|
||||
paint.FillShape(gtx.Ops, s.Indicator.Color, clip.RRect{
|
||||
Rect: f32.Rectangle{
|
||||
Max: indicatorDimsF,
|
||||
Rect: image.Rectangle{
|
||||
Max: indicatorDims,
|
||||
},
|
||||
SW: radius,
|
||||
NW: radius,
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op/clip"
|
||||
@@ -29,27 +28,26 @@ func ProgressBar(th *Theme, progress float32) ProgressBarStyle {
|
||||
}
|
||||
|
||||
func (p ProgressBarStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
shader := func(width float32, color color.NRGBA) layout.Dimensions {
|
||||
maxHeight := unit.Dp(4)
|
||||
rr := float32(gtx.Px(unit.Dp(2)))
|
||||
shader := func(width int, color color.NRGBA) layout.Dimensions {
|
||||
var maxHeight = unit.Dp(4)
|
||||
rr := gtx.Px(unit.Dp(2))
|
||||
|
||||
d := image.Point{X: int(width), Y: gtx.Px(maxHeight)}
|
||||
d := image.Point{X: width, Y: gtx.Px(maxHeight)}
|
||||
|
||||
height := float32(gtx.Px(maxHeight))
|
||||
defer clip.UniformRRect(f32.Rectangle{Max: f32.Pt(width, height)}, rr).Push(gtx.Ops).Pop()
|
||||
defer clip.UniformRRect(image.Rectangle{Max: image.Pt(width, d.Y)}, rr).Push(gtx.Ops).Pop()
|
||||
paint.ColorOp{Color: color}.Add(gtx.Ops)
|
||||
paint.PaintOp{}.Add(gtx.Ops)
|
||||
|
||||
return layout.Dimensions{Size: d}
|
||||
}
|
||||
|
||||
progressBarWidth := float32(gtx.Constraints.Max.X)
|
||||
progressBarWidth := gtx.Constraints.Max.X
|
||||
return layout.Stack{Alignment: layout.W}.Layout(gtx,
|
||||
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
|
||||
return shader(progressBarWidth, p.TrackColor)
|
||||
}),
|
||||
layout.Stacked(func(gtx layout.Context) layout.Dimensions {
|
||||
fillWidth := progressBarWidth * clamp1(p.Progress)
|
||||
fillWidth := int(float32(progressBarWidth) * clamp1(p.Progress))
|
||||
fillColor := p.Color
|
||||
if gtx.Queue == nil {
|
||||
fillColor = f32color.Disabled(fillColor)
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/layout"
|
||||
"gioui.org/op"
|
||||
@@ -78,9 +77,9 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
|
||||
// Draw thumb.
|
||||
pt := axis.Convert(image.Pt(thumbPos, sizeCross/2))
|
||||
thumb := f32.Rectangle{
|
||||
Min: f32.Pt(float32(pt.X-thumbRadius), float32(pt.Y-thumbRadius)),
|
||||
Max: f32.Pt(float32(pt.X+thumbRadius), float32(pt.Y+thumbRadius)),
|
||||
thumb := image.Rectangle{
|
||||
Min: image.Pt(pt.X-thumbRadius, pt.Y-thumbRadius),
|
||||
Max: image.Pt(pt.X+thumbRadius, pt.Y+thumbRadius),
|
||||
}
|
||||
paint.FillShape(gtx.Ops, color, clip.Ellipse(thumb).Op(gtx.Ops))
|
||||
|
||||
|
||||
+16
-17
@@ -6,7 +6,6 @@ import (
|
||||
"image"
|
||||
"image/color"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/io/semantic"
|
||||
"gioui.org/layout"
|
||||
@@ -47,10 +46,10 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
trackOff := (thumbSize - trackHeight) / 2
|
||||
|
||||
// Draw track.
|
||||
trackCorner := float32(trackHeight) / 2
|
||||
trackRect := f32.Rectangle{Max: f32.Point{
|
||||
X: float32(trackWidth),
|
||||
Y: float32(trackHeight),
|
||||
trackCorner := trackHeight / 2
|
||||
trackRect := image.Rectangle{Max: image.Point{
|
||||
X: trackWidth,
|
||||
Y: trackHeight,
|
||||
}}
|
||||
col := s.Color.Disabled
|
||||
if s.Switch.Value {
|
||||
@@ -69,14 +68,14 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
|
||||
// Draw thumb ink.
|
||||
inkSize := gtx.Px(unit.Dp(44))
|
||||
rr := float32(inkSize) * .5
|
||||
rr := inkSize / 2
|
||||
inkOff := image.Point{
|
||||
X: trackWidth/2 - int(rr),
|
||||
Y: -int(rr) + trackHeight/2 + trackOff,
|
||||
X: trackWidth/2 - rr,
|
||||
Y: -rr + trackHeight/2 + trackOff,
|
||||
}
|
||||
t = op.Offset(inkOff).Push(gtx.Ops)
|
||||
gtx.Constraints.Min = image.Pt(inkSize, inkSize)
|
||||
cl = clip.UniformRRect(f32.Rectangle{Max: layout.FPt(gtx.Constraints.Min)}, rr).Push(gtx.Ops)
|
||||
cl = clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, rr).Push(gtx.Ops)
|
||||
for _, p := range s.Switch.History() {
|
||||
drawInk(gtx, p)
|
||||
}
|
||||
@@ -89,18 +88,18 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
defer op.Offset(image.Point{X: xoff}).Push(gtx.Ops).Pop()
|
||||
}
|
||||
|
||||
thumbRadius := float32(thumbSize) / 2
|
||||
thumbRadius := thumbSize / 2
|
||||
|
||||
circle := func(x, y, r float32) clip.Op {
|
||||
b := f32.Rectangle{
|
||||
Min: f32.Pt(x-r, y-r),
|
||||
Max: f32.Pt(x+r, y+r),
|
||||
circle := func(x, y, r int) clip.Op {
|
||||
b := image.Rectangle{
|
||||
Min: image.Pt(x-r, y-r),
|
||||
Max: image.Pt(x+r, y+r),
|
||||
}
|
||||
return clip.Ellipse(b).Op(gtx.Ops)
|
||||
}
|
||||
// Draw hover.
|
||||
if s.Switch.Hovered() || s.Switch.Focused() {
|
||||
r := 1.7 * thumbRadius
|
||||
r := thumbRadius * 10 / 17
|
||||
background := f32color.MulAlpha(s.Color.Enabled, 70)
|
||||
paint.FillShape(gtx.Ops, background, circle(thumbRadius, thumbRadius, r))
|
||||
}
|
||||
@@ -108,7 +107,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
// Draw thumb shadow, a translucent disc slightly larger than the
|
||||
// thumb itself.
|
||||
// Center shadow horizontally and slightly adjust its Y.
|
||||
paint.FillShape(gtx.Ops, argb(0x55000000), circle(thumbRadius, thumbRadius+.25, thumbRadius+1))
|
||||
paint.FillShape(gtx.Ops, argb(0x55000000), circle(thumbRadius, thumbRadius+gtx.Px(unit.Dp(.25)), thumbRadius+1))
|
||||
|
||||
// Draw thumb.
|
||||
paint.FillShape(gtx.Ops, col, circle(thumbRadius, thumbRadius, thumbRadius))
|
||||
@@ -121,7 +120,7 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||
}
|
||||
defer op.Offset(clickOff).Push(gtx.Ops).Pop()
|
||||
sz := image.Pt(clickSize, clickSize)
|
||||
defer clip.Ellipse(f32.Rectangle{Max: layout.FPt(sz)}).Push(gtx.Ops).Pop()
|
||||
defer clip.Ellipse(image.Rectangle{Max: sz}).Push(gtx.Ops).Pop()
|
||||
s.Switch.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
|
||||
if d := s.Description; d != "" {
|
||||
semantic.DescriptionOp(d).Add(gtx.Ops)
|
||||
|
||||
Reference in New Issue
Block a user