diff --git a/ui/app/os_wayland.go b/ui/app/os_wayland.go index 1eaa5a97..f4f6e83f 100644 --- a/ui/app/os_wayland.go +++ b/ui/app/os_wayland.go @@ -237,8 +237,8 @@ func createNativeWindow(opts *WindowOptions) (*window, error) { C.free(unsafe.Pointer(title)) _, _, cfg := w.config() - w.width = int(cfg.Val(opts.Width) + .5) - w.height = int(cfg.Val(opts.Height) + .5) + w.width = cfg.Val(opts.Width) + w.height = cfg.Val(opts.Height) if conn.decor != nil { // Request server side decorations. w.decor = C.zxdg_decoration_manager_v1_get_toplevel_decoration(conn.decor, w.topLvl) diff --git a/ui/gesture/gestures.go b/ui/gesture/gestures.go index 7ea1f3de..26e657be 100644 --- a/ui/gesture/gestures.go +++ b/ui/gesture/gestures.go @@ -165,9 +165,9 @@ func (s *Scroll) Scroll(cfg *ui.Config, q input.Events, axis Axis) int { break } fling := s.estimator.Estimate() - if slop, d := cfg.Val(touchSlop), fling.Distance; d >= slop || -slop >= d { - if min, v := cfg.Val(minFlingVelocity), fling.Velocity; v >= min || -min >= v { - max := cfg.Val(maxFlingVelocity) + if slop, d := float32(cfg.Val(touchSlop)), fling.Distance; d >= slop || -slop >= d { + if min, v := float32(cfg.Val(minFlingVelocity)), fling.Velocity; v >= min || -min >= v { + max := float32(cfg.Val(maxFlingVelocity)) if v > max { v = max } else if v < -max { @@ -201,7 +201,7 @@ func (s *Scroll) Scroll(cfg *ui.Config, q input.Events, axis Axis) int { dist := s.last - v if e.Priority < pointer.Grabbed { slop := cfg.Val(touchSlop) - if dist := float32(dist); dist >= slop || -slop >= dist { + if dist := dist; dist >= slop || -slop >= dist { s.grab = true } } else { diff --git a/ui/measure/measure.go b/ui/measure/measure.go index 33346c37..b1c87223 100644 --- a/ui/measure/measure.go +++ b/ui/measure/measure.go @@ -102,7 +102,7 @@ func (f *Faces) init() { } func (f *textFace) Layout(str string, opts text.LayoutOptions) *text.Layout { - ppem := fixed.Int26_6(f.faces.Config.Val(f.size)*64 + .5) + ppem := fixed.Int26_6(f.faces.Config.Val(f.size) * 64) lk := layoutKey{ f: f.font.Font, ppem: ppem, @@ -120,7 +120,7 @@ func (f *textFace) Layout(str string, opts text.LayoutOptions) *text.Layout { } func (f *textFace) Path(str text.String) ui.BlockOp { - ppem := fixed.Int26_6(f.faces.Config.Val(f.size)*64 + .5) + ppem := fixed.Int26_6(f.faces.Config.Val(f.size) * 64) pk := pathKey{ f: f.font.Font, ppem: ppem, diff --git a/ui/text/editor.go b/ui/text/editor.go index 206b6fbe..2dea373a 100644 --- a/ui/text/editor.go +++ b/ui/text/editor.go @@ -153,7 +153,7 @@ func (e *Editor) Next() (EditorEvent, bool) { } func (e *Editor) caretWidth() fixed.Int26_6 { - oneDp := int(e.Config.Val(ui.Dp(1)) + .5) + oneDp := e.Config.Val(ui.Dp(1)) return fixed.Int26_6(oneDp * 64) } @@ -167,7 +167,7 @@ func (e *Editor) Layout(ops *ui.Ops, cs layout.Constraints) layout.Dimens { break } } - twoDp := int(e.Config.Val(ui.Dp(2)) + 0.5) + twoDp := e.Config.Val(ui.Dp(2)) e.padLeft, e.padRight = twoDp, twoDp maxWidth := cs.Width.Max if e.SingleLine { diff --git a/ui/ui.go b/ui/ui.go index aaa03ea4..f8fd5c77 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -23,27 +23,29 @@ type Config struct { } // Dp converts a value in dp units to pixels. -func (c *Config) Dp(dp float32) float32 { - return c.PxPerDp * dp +func (c *Config) Dp(dp float32) int { + return c.Val(Dp(dp)) } // Sp converts a value in sp units to pixels. -func (c *Config) Sp(sp float32) float32 { - return c.PxPerSp * sp +func (c *Config) Sp(sp float32) int { + return c.Val(Sp(sp)) } // Val converts a value to pixels. -func (c *Config) Val(v Value) float32 { +func (c *Config) Val(v Value) int { + var r float32 switch v.U { case UnitPx: - return v.V + r = v.V case UnitDp: - return c.PxPerDp * v.V + r = c.PxPerDp * v.V case UnitSp: - return c.PxPerSp * v.V + r = c.PxPerSp * v.V default: panic("unknown unit") } + return int(math.Round(float64(r))) } // LayerOp represents a semantic layer of UI. diff --git a/ui/widget/image.go b/ui/widget/image.go index ffffed84..dc706b56 100644 --- a/ui/widget/image.go +++ b/ui/widget/image.go @@ -25,12 +25,14 @@ type Image struct { func (im Image) Layout(c *ui.Config, ops *ui.Ops, cs layout.Constraints) layout.Dimens { size := im.Src.Bounds() - scale := im.Scale - if scale == 0 { + wf, hf := float32(size.Dx()), float32(size.Dy()) + var w, h int + if im.Scale == 0 { const dpPrPx = 160 / 72 - scale = c.Val(ui.Dp(dpPrPx)) + w, h = c.Dp(wf*dpPrPx), c.Dp(hf*dpPrPx) + } else { + w, h = int(wf*im.Scale+.5), int(hf*im.Scale+.5) } - w, h := int(float32(size.Dx())*scale+.5), int(float32(size.Dy())*scale+.5) d := image.Point{X: cs.Width.Constrain(w), Y: cs.Height.Constrain(h)} aspect := float32(w) / float32(h) dw, dh := float32(d.X), float32(d.Y)