github.com/gop9/olt@v0.0.0-20200202132135-d956aad50b08/gio/unit/unit.go (about)

     1  // SPDX-License-Identifier: Unlicense OR MIT
     2  
     3  /*
     4  
     5  Package unit implements device independent units and values.
     6  
     7  A Value is a value with a Unit attached.
     8  
     9  Device independent pixel, or dp, is the unit for sizes independent of
    10  the underlying display device.
    11  
    12  Scaled pixels, or sp, is the unit for text sizes. An sp is like dp with
    13  text scaling applied.
    14  
    15  Finally, pixels, or px, is the unit for display dependent pixels. Their
    16  size vary between platforms and displays.
    17  
    18  To maintain a constant visual size across platforms and displays, always
    19  use dps or sps to define user interfaces. Only use pixels for derived
    20  values.
    21  
    22  */
    23  package unit
    24  
    25  import "fmt"
    26  
    27  // Value is a value with a unit.
    28  type Value struct {
    29  	V float32
    30  	U Unit
    31  }
    32  
    33  // Unit represents a unit for a Value.
    34  type Unit uint8
    35  
    36  // Converter converts Values to pixels.
    37  type Converter interface {
    38  	Px(v Value) int
    39  }
    40  
    41  const (
    42  	// UnitPx represent device pixels in the resolution of
    43  	// the underlying display.
    44  	UnitPx Unit = iota
    45  	// UnitDp represents device independent pixels. 1 dp will
    46  	// have the same apparent size across platforms and
    47  	// display resolutions.
    48  	UnitDp
    49  	// UnitSp is like UnitDp but for font sizes.
    50  	UnitSp
    51  )
    52  
    53  // Px returns the Value for v device pixels.
    54  func Px(v float32) Value {
    55  	return Value{V: v, U: UnitPx}
    56  }
    57  
    58  // Px returns the Value for v device independent
    59  // pixels.
    60  func Dp(v float32) Value {
    61  	return Value{V: v, U: UnitDp}
    62  }
    63  
    64  // Sp returns the Value for v scaled dps.
    65  func Sp(v float32) Value {
    66  	return Value{V: v, U: UnitSp}
    67  }
    68  
    69  // Scale returns the value scaled by s.
    70  func (v Value) Scale(s float32) Value {
    71  	v.V *= s
    72  	return v
    73  }
    74  
    75  func (v Value) String() string {
    76  	return fmt.Sprintf("%g%s", v.V, v.U)
    77  }
    78  
    79  func (u Unit) String() string {
    80  	switch u {
    81  	case UnitPx:
    82  		return "px"
    83  	case UnitDp:
    84  		return "dp"
    85  	case UnitSp:
    86  		return "sp"
    87  	default:
    88  		panic("unknown unit")
    89  	}
    90  }
    91  
    92  // Add a list of Values.
    93  func Add(c Converter, values ...Value) Value {
    94  	var sum Value
    95  	for _, v := range values {
    96  		sum, v = compatible(c, sum, v)
    97  		sum.V += v.V
    98  	}
    99  	return sum
   100  }
   101  
   102  // Max returns the maximum of a list of Values.
   103  func Max(c Converter, values ...Value) Value {
   104  	var max Value
   105  	for _, v := range values {
   106  		max, v = compatible(c, max, v)
   107  		if v.V > max.V {
   108  			max.V = v.V
   109  		}
   110  	}
   111  	return max
   112  }
   113  
   114  func compatible(c Converter, v1, v2 Value) (Value, Value) {
   115  	if v1.U == v2.U {
   116  		return v1, v2
   117  	}
   118  	if v1.V == 0 {
   119  		v1.U = v2.U
   120  		return v1, v2
   121  	}
   122  	if v2.V == 0 {
   123  		v2.U = v1.U
   124  		return v1, v2
   125  	}
   126  	return Px(float32(c.Px(v1))), Px(float32(c.Px(v2)))
   127  }