From 8f8127111a74dcc31d7f32f3473890a0a3fa5f25 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Fri, 8 Apr 2016 13:29:07 +1000 Subject: [PATCH] shiny/unit: new package for units of length. Change-Id: I5b3e90ac5a1eced0eb3ab88683cee5526932d118 Reviewed-on: https://go-review.googlesource.com/21691 Reviewed-by: Andrew Gerrand --- shiny/unit/unit.go | 137 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 shiny/unit/unit.go diff --git a/shiny/unit/unit.go b/shiny/unit/unit.go new file mode 100644 index 000000000..a30eb22c0 --- /dev/null +++ b/shiny/unit/unit.go @@ -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} }