blob: a30eb22c0696fd7d0a62f29451ba1e23f07bcc59 [file] [log] [blame]
// 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} }