188 lines
5.1 KiB
Ruby
188 lines
5.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Sass
|
|
module Value
|
|
class Number
|
|
# The {Unit} module.
|
|
module Unit
|
|
CONVERSIONS = {
|
|
# Length
|
|
'in' => {
|
|
'in' => Rational(1),
|
|
'cm' => Rational(1, 2.54),
|
|
'pc' => Rational(1, 6),
|
|
'mm' => Rational(1, 25.4),
|
|
'q' => Rational(1, 101.6),
|
|
'pt' => Rational(1, 72),
|
|
'px' => Rational(1, 96)
|
|
},
|
|
'cm' => {
|
|
'in' => Rational(2.54),
|
|
'cm' => Rational(1),
|
|
'pc' => Rational(2.54, 6),
|
|
'mm' => Rational(1, 10),
|
|
'q' => Rational(1, 40),
|
|
'pt' => Rational(2.54, 72),
|
|
'px' => Rational(2.54, 96)
|
|
},
|
|
'pc' => {
|
|
'in' => Rational(6),
|
|
'cm' => Rational(6, 2.54),
|
|
'pc' => Rational(1),
|
|
'mm' => Rational(6, 25.4),
|
|
'q' => Rational(6, 101.6),
|
|
'pt' => Rational(1, 12),
|
|
'px' => Rational(1, 16)
|
|
},
|
|
'mm' => {
|
|
'in' => Rational(25.4),
|
|
'cm' => Rational(10),
|
|
'pc' => Rational(25.4, 6),
|
|
'mm' => Rational(1),
|
|
'q' => Rational(1, 4),
|
|
'pt' => Rational(25.4, 72),
|
|
'px' => Rational(25.4, 96)
|
|
},
|
|
'q' => {
|
|
'in' => Rational(101.6),
|
|
'cm' => Rational(40),
|
|
'pc' => Rational(101.6, 6),
|
|
'mm' => Rational(4),
|
|
'q' => Rational(1),
|
|
'pt' => Rational(101.6, 72),
|
|
'px' => Rational(101.6, 96)
|
|
},
|
|
'pt' => {
|
|
'in' => Rational(72),
|
|
'cm' => Rational(72, 2.54),
|
|
'pc' => Rational(12),
|
|
'mm' => Rational(72, 25.4),
|
|
'q' => Rational(72, 101.6),
|
|
'pt' => Rational(1),
|
|
'px' => Rational(3, 4)
|
|
},
|
|
'px' => {
|
|
'in' => Rational(96),
|
|
'cm' => Rational(96, 2.54),
|
|
'pc' => Rational(16),
|
|
'mm' => Rational(96, 25.4),
|
|
'q' => Rational(96, 101.6),
|
|
'pt' => Rational(4, 3),
|
|
'px' => Rational(1)
|
|
},
|
|
|
|
# Rotation
|
|
'deg' => {
|
|
'deg' => Rational(1),
|
|
'grad' => Rational(9, 10),
|
|
'rad' => Rational(180, Math::PI),
|
|
'turn' => Rational(360)
|
|
},
|
|
'grad' => {
|
|
'deg' => Rational(10, 9),
|
|
'grad' => Rational(1),
|
|
'rad' => Rational(200, Math::PI),
|
|
'turn' => Rational(400)
|
|
},
|
|
'rad' => {
|
|
'deg' => Rational(Math::PI, 180),
|
|
'grad' => Rational(Math::PI, 200),
|
|
'rad' => Rational(1),
|
|
'turn' => Rational(Math::PI * 2)
|
|
},
|
|
'turn' => {
|
|
'deg' => Rational(1, 360),
|
|
'grad' => Rational(1, 400),
|
|
'rad' => Rational(1, Math::PI * 2),
|
|
'turn' => Rational(1)
|
|
},
|
|
|
|
# Time
|
|
's' => {
|
|
's' => Rational(1),
|
|
'ms' => Rational(1, 1000)
|
|
},
|
|
'ms' => {
|
|
's' => Rational(1000),
|
|
'ms' => Rational(1)
|
|
},
|
|
|
|
# Frequency
|
|
'Hz' => {
|
|
'Hz' => Rational(1),
|
|
'kHz' => Rational(1000)
|
|
},
|
|
'kHz' => {
|
|
'Hz' => Rational(1, 1000),
|
|
'kHz' => Rational(1)
|
|
},
|
|
|
|
# Pixel density
|
|
'dpi' => {
|
|
'dpi' => Rational(1),
|
|
'dpcm' => Rational(2.54),
|
|
'dppx' => Rational(96)
|
|
},
|
|
'dpcm' => {
|
|
'dpi' => Rational(1, 2.54),
|
|
'dpcm' => Rational(1),
|
|
'dppx' => Rational(96, 2.54)
|
|
},
|
|
'dppx' => {
|
|
'dpi' => Rational(1, 96),
|
|
'dpcm' => Rational(2.54, 96),
|
|
'dppx' => Rational(1)
|
|
}
|
|
}.freeze
|
|
|
|
UNITS_BY_TYPE = {
|
|
time: %w[s ms],
|
|
frequency: %w[Hz kHz],
|
|
'pixel density': %w[dpi dpcm dppx]
|
|
}.freeze
|
|
|
|
TYPES_BY_UNIT = UNITS_BY_TYPE.each_with_object({}) do |(key, values), hash|
|
|
values.each do |value|
|
|
hash[value] = key
|
|
end
|
|
end
|
|
|
|
module_function
|
|
|
|
def conversion_factor(unit1, unit2)
|
|
return 1 if unit1 == unit2
|
|
|
|
CONVERSIONS.dig(unit1, unit2)
|
|
end
|
|
|
|
def canonicalize_units(units)
|
|
return units if units.empty?
|
|
|
|
if units.length == 1
|
|
type = TYPES_BY_UNIT[units.first]
|
|
return type.nil? ? units : [UNITS_BY_TYPE[type].first]
|
|
end
|
|
|
|
units.map do |unit|
|
|
type = TYPES_BY_UNIT[unit]
|
|
type.nil? ? units : [UNITS_BY_TYPE[type].first]
|
|
end.sort
|
|
end
|
|
|
|
def canonical_multiplier(units)
|
|
units.reduce(1) do |multiplier, unit|
|
|
multiplier * canonical_multiplier_for_unit(unit)
|
|
end
|
|
end
|
|
|
|
def canonical_multiplier_for_unit(unit)
|
|
inner_map = CONVERSIONS[unit]
|
|
inner_map.nil? ? 1 : 1 / inner_map.values.first
|
|
end
|
|
end
|
|
|
|
private_constant :Unit
|
|
end
|
|
end
|
|
end
|