// Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package unit defines units of length such as inches or pixels. // // Functions like Inches and Pixels return a Value in the corresponding unit. // For example: // // v := unit.Inches(4.5) // // represents four and a half inches. // // Converting between pixels (px), physical units (dp, pt, in, mm) and // font-face-relative measures (em, ex, ch) depends on the context, such as the // screen's DPI resolution and the active font face. That context is // represented by the Converter type. // // Conversions may be lossy. Converting 4.5 inches to pixels and back may // result in something slightly different than 4.5. Similarly, converting 4 // inches and 0.5 inches to pixels and then adding the results won't // necessarily equal the conversion of 4.5 inches to pixels. // // Note that what CSS (Cascading Style Sheets) calls "px" differs from what // this package calls "px". For legacy reasons, the CSS semantics are that 1 // inch should roughly equal 96csspx regardless of the actual DPI resolution, // as per https://developer.mozilla.org/en/docs/Web/CSS/length. This package's // semantics are that 1px means exactly one physical pixel, always. This // package represents 1csspx as 1.666666667dp, since there are 160 density // independent pixels per inch, the same definition as Android. package unit import ( "fmt" "golang.org/x/image/math/fixed" ) const ( DensityIndependentPixelsPerInch = 160 MillimetresPerInch = 25.4 PointsPerInch = 72 ) // Converter converts values from one unit to another. Conversions may be // lossy. type Converter interface { // Convert converts v to the given unit. Convert(v Value, to Unit) Value // Pixels converts v to a 26.6 fixed-point number of physical pixels. Pixels(v Value) fixed.Int26_6 } // Value is a number and a unit. type Value struct { F float64 U Unit } // String implements the fmt.Stringer interface. func (v Value) String() string { return fmt.Sprintf("%f%s", v.F, names[v.U]) } var names = [...]string{ Px: "px", Dp: "dp", Pt: "pt", In: "in", Mm: "mm", Em: "em", Ex: "ex", Ch: "ch", } // Unit is a unit of length, such as inches or pixels. type Unit uint8 const ( // Px is a physical pixel, regardless of the DPI resolution. Px Unit = iota // Dp is 1 density independent pixel: 1/160th of an inch. Dp // Pt is 1 point: 1/72th of an inch. Pt // Mm is 1 millimetre: 1/25.4th of an inch. Mm // In is 1 inch. // // If the context does not specify a DPI resolution, the recommended // fallback value for conversion is 72 pixels per inch. In // Em is the height of the active font face, disregarding extra leading // such as from double-spaced lines of text. // // If the context does not specify an active font face, the recommended // fallback value for conversion is 12pt. Em // Ex is the x-height of the active font face. // // If the context does not specify an x-height, the recommended fallback // value for conversion is 0.5em. Ex // Ch is the character width of the numeral zero glyph '0' of the active // font face. // // If the context does not specify a '0' glyph, the recommended fallback // value for conversion is 0.5em. Ch ) // Pixels returns the given number of Px as a Value. func Pixels(f float64) Value { return Value{f, Px} } // DIPs returns the given number of Dp as a Value. func DIPs(f float64) Value { return Value{f, Dp} } // Points returns the given number of Pt as a Value. func Points(f float64) Value { return Value{f, Pt} } // Millimetres returns the given number of Mm as a Value. func Millimetres(f float64) Value { return Value{f, Mm} } // Inches returns the given number of In as a Value. func Inches(f float64) Value { return Value{f, In} } // Ems returns the given number of Em as a Value. func Ems(f float64) Value { return Value{f, Em} } // Exs returns the given number of Ex as a Value. func Exs(f float64) Value { return Value{f, Ex} } // Chs returns the given number of Ch as a Value. func Chs(f float64) Value { return Value{f, Ch} }