Skip to content

Commit

Permalink
shiny/unit: new package for units of length.
Browse files Browse the repository at this point in the history
Change-Id: I5b3e90ac5a1eced0eb3ab88683cee5526932d118
Reviewed-on: https://go-review.googlesource.com/21691
Reviewed-by: Andrew Gerrand <[email protected]>
  • Loading branch information
nigeltao committed Apr 8, 2016
1 parent 835e9bb commit 8f81271
Showing 1 changed file with 137 additions and 0 deletions.
137 changes: 137 additions & 0 deletions shiny/unit/unit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// 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} }

0 comments on commit 8f81271

Please sign in to comment.