unit.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // SPDX-License-Identifier: Unlicense OR MIT
  2. /*
  3. Package unit implements device independent units.
  4. Device independent pixel, or dp, is the unit for sizes independent of
  5. the underlying display device.
  6. Scaled pixels, or sp, is the unit for text sizes. An sp is like dp with
  7. text scaling applied.
  8. Finally, pixels, or px, is the unit for display dependent pixels. Their
  9. size vary between platforms and displays.
  10. To maintain a constant visual size across platforms and displays, always
  11. use dps or sps to define user interfaces. Only use pixels for derived
  12. values.
  13. */
  14. package unit
  15. import (
  16. "math"
  17. )
  18. // Metric converts Values to device-dependent pixels, px. The zero
  19. // value represents a 1-to-1 scale from dp, sp to pixels.
  20. type Metric struct {
  21. // PxPerDp is the device-dependent pixels per dp.
  22. PxPerDp float32
  23. // PxPerSp is the device-dependent pixels per sp.
  24. PxPerSp float32
  25. }
  26. type (
  27. // Dp represents device independent pixels. 1 dp will
  28. // have the same apparent size across platforms and
  29. // display resolutions.
  30. Dp float32
  31. // Sp is like UnitDp but for font sizes.
  32. Sp float32
  33. )
  34. // Dp converts v to pixels, rounded to the nearest integer value.
  35. func (c Metric) Dp(v Dp) int {
  36. return int(math.Round(float64(nonZero(c.PxPerDp)) * float64(v)))
  37. }
  38. // Sp converts v to pixels, rounded to the nearest integer value.
  39. func (c Metric) Sp(v Sp) int {
  40. return int(math.Round(float64(nonZero(c.PxPerSp)) * float64(v)))
  41. }
  42. // DpToSp converts v dp to sp.
  43. func (c Metric) DpToSp(v Dp) Sp {
  44. return Sp(float32(v) * nonZero(c.PxPerDp) / nonZero(c.PxPerSp))
  45. }
  46. // SpToDp converts v sp to dp.
  47. func (c Metric) SpToDp(v Sp) Dp {
  48. return Dp(float32(v) * nonZero(c.PxPerSp) / nonZero(c.PxPerDp))
  49. }
  50. // PxToSp converts v px to sp.
  51. func (c Metric) PxToSp(v int) Sp {
  52. return Sp(float32(v) / nonZero(c.PxPerSp))
  53. }
  54. // PxToDp converts v px to dp.
  55. func (c Metric) PxToDp(v int) Dp {
  56. return Dp(float32(v) / nonZero(c.PxPerDp))
  57. }
  58. func nonZero(v float32) float32 {
  59. if v == 0. {
  60. return 1
  61. }
  62. return v
  63. }