~eliasnaur/gio

b9f2e0fb41c008c222d50f8ab754aa1ad76dd18f — Egon Elbre 7 months ago ee8e267
widget/material: use clip.Circle to draw circles

Signed-off-by: Egon Elbre <egonelbre@gmail.com>
3 files changed, 30 insertions(+), 47 deletions(-)

M widget/material/checkable.go
M widget/material/slider.go
M widget/material/switch.go
M widget/material/checkable.go => widget/material/checkable.go +6 -16
@@ 5,7 5,6 @@ package material
import (
	"image"
	"image/color"
	"math"

	"gioui.org/f32"
	"gioui.org/internal/f32color"


@@ 52,10 51,12 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim

					background := f32color.MulAlpha(c.IconColor, 70)

					var p clip.Path
					p.Begin(gtx.Ops)
					addCircle(&p, float32(size)/2)
					paint.FillShape(gtx.Ops, background, clip.Outline{Path: p.End()}.Op())
					radius := float32(size) / 2
					paint.FillShape(gtx.Ops, background,
						clip.Circle{
							Center: f32.Point{X: radius, Y: radius},
							Radius: radius,
						}.Op(gtx.Ops))

					return dims
				}),


@@ 85,14 86,3 @@ func (c *checkable) layout(gtx layout.Context, checked, hovered bool) layout.Dim
	pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops)
	return dims
}

// addCircle adds the outline of a circle to a path.
func addCircle(p *clip.Path, r float32) {
	// https://pomax.github.io/bezierinfo/#circles_cubic.
	const c = 4 * (math.Sqrt2 - 1) / 3 // 4*(sqrt(2)-1)/3
	p.Move(f32.Point{X: 2 * r, Y: 2*r - r})
	p.Cube(f32.Point{X: 0, Y: r * c}, f32.Point{X: -r + r*c, Y: r}, f32.Point{X: -r, Y: r})
	p.Cube(f32.Point{X: -r * c, Y: 0}, f32.Point{X: -r, Y: -r + r*c}, f32.Point{X: -r, Y: -r})
	p.Cube(f32.Point{X: 0, Y: -r * c}, f32.Point{X: r - r*c, Y: -r}, f32.Point{X: r, Y: -r})
	p.Cube(f32.Point{X: r * c, Y: 0}, f32.Point{X: r, Y: r - r*c}, f32.Point{X: r, Y: r})
}

M widget/material/slider.go => widget/material/slider.go +6 -9
@@ 6,6 6,7 @@ import (
	"image"
	"image/color"

	"gioui.org/f32"
	"gioui.org/internal/f32color"
	"gioui.org/layout"
	"gioui.org/op"


@@ 83,16 84,12 @@ func (s SliderStyle) Layout(gtx layout.Context) layout.Dimensions {
	st.Load()

	// Draw thumb.
	st = op.Save(gtx.Ops)
	pt := axis.Convert(image.Pt(thumbPos, sizeCross/2))
	rpt := image.Pt(thumbRadius, thumbRadius)
	thumb := image.Rectangle{
		Min: pt.Sub(rpt),
		Max: pt.Add(rpt),
	}
	clip.UniformRRect(layout.FRect(thumb), float32(thumbRadius)).Add(gtx.Ops)
	paint.Fill(gtx.Ops, color)
	st.Load()
	paint.FillShape(gtx.Ops, color,
		clip.Circle{
			Center: f32.Point{X: float32(pt.X), Y: float32(pt.Y)},
			Radius: float32(thumbRadius),
		}.Op(gtx.Ops))

	return layout.Dimensions{Size: size}
}

M widget/material/switch.go => widget/material/switch.go +18 -22
@@ 88,30 88,34 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
		op.Offset(f32.Point{X: float32(off)}).Add(gtx.Ops)
	}

	thumbRadius := float32(thumbSize) / 2

	// Draw hover.
	if s.Switch.Hovered() {
		var p clip.Path
		r := 1.7 * float32(thumbSize) / 2
		p.Begin(gtx.Ops)
		//p.Move(f32.Pt(-float32(thumbSize)/2, -float32(thumbSize)/2))
		p.Move(f32.Pt(-r+float32(thumbSize)/2, -r+float32(thumbSize)/2))
		addCircle(&p, r)
		r := 1.7 * thumbRadius
		background := f32color.MulAlpha(s.Color.Enabled, 70)
		paint.FillShape(gtx.Ops, background, clip.Outline{Path: p.End()}.Op())
		paint.FillShape(gtx.Ops, background,
			clip.Circle{
				Center: f32.Point{X: thumbRadius, Y: thumbRadius},
				Radius: r,
			}.Op(gtx.Ops))
	}

	// Draw thumb shadow, a translucent disc slightly larger than the
	// thumb itself.
	shadowStack := op.Save(gtx.Ops)
	shadowSize := float32(2)
	// Center shadow horizontally and slightly adjust its Y.
	op.Offset(f32.Point{X: -shadowSize / 2, Y: -.75}).Add(gtx.Ops)
	drawDisc(gtx.Ops, float32(thumbSize)+shadowSize, argb(0x55000000))
	shadowStack.Load()
	paint.FillShape(gtx.Ops, argb(0x55000000),
		clip.Circle{
			Center: f32.Point{X: thumbRadius, Y: thumbRadius + .25},
			Radius: thumbRadius + 1,
		}.Op(gtx.Ops))

	// Draw thumb.
	drawDisc(gtx.Ops, float32(thumbSize), col)
	stack.Load()
	paint.FillShape(gtx.Ops, col,
		clip.Circle{
			Center: f32.Point{X: thumbRadius, Y: thumbRadius},
			Radius: thumbRadius,
		}.Op(gtx.Ops))

	// Set up click area.
	stack = op.Save(gtx.Ops)


@@ 130,11 134,3 @@ func (s SwitchStyle) Layout(gtx layout.Context) layout.Dimensions {
	dims := image.Point{X: trackWidth, Y: thumbSize}
	return layout.Dimensions{Size: dims}
}

func drawDisc(ops *op.Ops, sz float32, col color.NRGBA) {
	defer op.Save(ops).Load()
	rr := sz / 2
	clip.UniformRRect(f32.Rectangle{Max: f32.Pt(sz, sz)}, rr).Add(ops)
	paint.ColorOp{Color: col}.Add(ops)
	paint.PaintOp{}.Add(ops)
}