Initial commit
[yaffs-website] / node_modules / node-sass / src / libsass / src / units.cpp
1 #include "sass.hpp"
2 #include <stdexcept>
3 #include "units.hpp"
4
5 namespace Sass {
6
7   /* the conversion matrix can be readed the following way */
8   /* if you go down, the factor is for the numerator (multiply) */
9   /* if you go right, the factor is for the denominator (divide) */
10   /* and yes, we actually use both, not sure why, but why not!? */
11
12   const double size_conversion_factors[6][6] =
13   {
14              /*  in         cm         pc         mm         pt         px        */
15     /* in   */ { 1,         2.54,      6,         25.4,      72,        96,       },
16     /* cm   */ { 1.0/2.54,  1,         6.0/2.54,  10,        72.0/2.54, 96.0/2.54 },
17     /* pc   */ { 1.0/6.0,   2.54/6.0,  1,         25.4/6.0,  72.0/6.0,  96.0/6.0  },
18     /* mm   */ { 1.0/25.4,  1.0/10.0,  6.0/25.4,  1,         72.0/25.4, 96.0/25.4 },
19     /* pt   */ { 1.0/72.0,  2.54/72.0, 6.0/72.0,  25.4/72.0, 1,         96.0/72.0 },
20     /* px   */ { 1.0/96.0,  2.54/96.0, 6.0/96.0,  25.4/96.0, 72.0/96.0, 1,        }
21   };
22
23   const double angle_conversion_factors[4][4] =
24   {
25              /*  deg        grad       rad        turn      */
26     /* deg  */ { 1,         40.0/36.0, PI/180.0,  1.0/360.0 },
27     /* grad */ { 36.0/40.0, 1,         PI/200.0,  1.0/400.0 },
28     /* rad  */ { 180.0/PI,  200.0/PI,  1,         0.5/PI    },
29     /* turn */ { 360.0,     400.0,     2.0*PI,    1         }
30   };
31
32   const double time_conversion_factors[2][2] =
33   {
34              /*  s          ms        */
35     /* s    */ { 1,         1000.0    },
36     /* ms   */ { 1/1000.0,  1         }
37   };
38   const double frequency_conversion_factors[2][2] =
39   {
40              /*  Hz         kHz       */
41     /* Hz   */ { 1,         1/1000.0  },
42     /* kHz  */ { 1000.0,    1         }
43   };
44   const double resolution_conversion_factors[3][3] =
45   {
46              /*  dpi        dpcm       dppx     */
47     /* dpi  */ { 1,         1/2.54,    1/96.0   },
48     /* dpcm */ { 2.54,      1,         2.54/96  },
49     /* dppx */ { 96,        96/2.54,   1        }
50   };
51
52   UnitClass get_unit_type(UnitType unit)
53   {
54     switch (unit & 0xFF00)
55     {
56       case UnitClass::LENGTH:      return UnitClass::LENGTH; break;
57       case UnitClass::ANGLE:       return UnitClass::ANGLE; break;
58       case UnitClass::TIME:        return UnitClass::TIME; break;
59       case UnitClass::FREQUENCY:   return UnitClass::FREQUENCY; break;
60       case UnitClass::RESOLUTION:  return UnitClass::RESOLUTION; break;
61       default:                     return UnitClass::INCOMMENSURABLE; break;
62     }
63   };
64
65   std::string get_unit_class(UnitType unit)
66   {
67     switch (unit & 0xFF00)
68     {
69       case UnitClass::LENGTH:      return "LENGTH"; break;
70       case UnitClass::ANGLE:       return "ANGLE"; break;
71       case UnitClass::TIME:        return "TIME"; break;
72       case UnitClass::FREQUENCY:   return "FREQUENCY"; break;
73       case UnitClass::RESOLUTION:  return "RESOLUTION"; break;
74       default:                     return "INCOMMENSURABLE"; break;
75     }
76   };
77
78   UnitType string_to_unit(const std::string& s)
79   {
80     // size units
81     if      (s == "px")   return UnitType::PX;
82     else if (s == "pt")   return UnitType::PT;
83     else if (s == "pc")   return UnitType::PC;
84     else if (s == "mm")   return UnitType::MM;
85     else if (s == "cm")   return UnitType::CM;
86     else if (s == "in")   return UnitType::IN;
87     // angle units
88     else if (s == "deg")  return UnitType::DEG;
89     else if (s == "grad") return UnitType::GRAD;
90     else if (s == "rad")  return UnitType::RAD;
91     else if (s == "turn") return UnitType::TURN;
92     // time units
93     else if (s == "s")    return UnitType::SEC;
94     else if (s == "ms")   return UnitType::MSEC;
95     // frequency units
96     else if (s == "Hz")   return UnitType::HERTZ;
97     else if (s == "kHz")  return UnitType::KHERTZ;
98     // resolutions units
99     else if (s == "dpi")  return UnitType::DPI;
100     else if (s == "dpcm") return UnitType::DPCM;
101     else if (s == "dppx") return UnitType::DPPX;
102     // for unknown units
103     else return UnitType::UNKNOWN;
104   }
105
106   const char* unit_to_string(UnitType unit)
107   {
108     switch (unit) {
109       // size units
110       case UnitType::PX:      return "px"; break;
111       case UnitType::PT:      return "pt"; break;
112       case UnitType::PC:      return "pc"; break;
113       case UnitType::MM:      return "mm"; break;
114       case UnitType::CM:      return "cm"; break;
115       case UnitType::IN:      return "in"; break;
116       // angle units
117       case UnitType::DEG:     return "deg"; break;
118       case UnitType::GRAD:    return "grad"; break;
119       case UnitType::RAD:     return "rad"; break;
120       case UnitType::TURN:    return "turn"; break;
121       // time units
122       case UnitType::SEC:     return "s"; break;
123       case UnitType::MSEC:    return "ms"; break;
124       // frequency units
125       case UnitType::HERTZ:   return "Hz"; break;
126       case UnitType::KHERTZ:  return "kHz"; break;
127       // resolutions units
128       case UnitType::DPI:     return "dpi"; break;
129       case UnitType::DPCM:    return "dpcm"; break;
130       case UnitType::DPPX:    return "dppx"; break;
131       // for unknown units
132       default:                return ""; break;
133     }
134   }
135
136   std::string unit_to_class(const std::string& s)
137   {
138     if      (s == "px")   return "LENGTH";
139     else if (s == "pt")   return "LENGTH";
140     else if (s == "pc")   return "LENGTH";
141     else if (s == "mm")   return "LENGTH";
142     else if (s == "cm")   return "LENGTH";
143     else if (s == "in")   return "LENGTH";
144     // angle units
145     else if (s == "deg")  return "ANGLE";
146     else if (s == "grad") return "ANGLE";
147     else if (s == "rad")  return "ANGLE";
148     else if (s == "turn") return "ANGLE";
149     // time units
150     else if (s == "s")    return "TIME";
151     else if (s == "ms")   return "TIME";
152     // frequency units
153     else if (s == "Hz")   return "FREQUENCY";
154     else if (s == "kHz")  return "FREQUENCY";
155     // resolutions units
156     else if (s == "dpi")  return "RESOLUTION";
157     else if (s == "dpcm") return "RESOLUTION";
158     else if (s == "dppx") return "RESOLUTION";
159     // for unknown units
160     return "CUSTOM:" + s;
161   }
162
163   // throws incompatibleUnits exceptions
164   double conversion_factor(const std::string& s1, const std::string& s2, bool strict)
165   {
166     // assert for same units
167     if (s1 == s2) return 1;
168     // get unit enum from string
169     UnitType u1 = string_to_unit(s1);
170     UnitType u2 = string_to_unit(s2);
171     // query unit group types
172     UnitClass t1 = get_unit_type(u1);
173     UnitClass t2 = get_unit_type(u2);
174     // get absolute offset
175     // used for array acces
176     size_t i1 = u1 - t1;
177     size_t i2 = u2 - t2;
178     // error if units are not of the same group
179     // don't error for multiplication and division
180     if (strict && t1 != t2) throw incompatibleUnits(u1, u2);
181     // only process known units
182     if (u1 != UNKNOWN && u2 != UNKNOWN) {
183       switch (t1) {
184         case UnitClass::LENGTH:            return size_conversion_factors[i1][i2]; break;
185         case UnitClass::ANGLE:             return angle_conversion_factors[i1][i2]; break;
186         case UnitClass::TIME:              return time_conversion_factors[i1][i2]; break;
187         case UnitClass::FREQUENCY:         return frequency_conversion_factors[i1][i2]; break;
188         case UnitClass::RESOLUTION:        return resolution_conversion_factors[i1][i2]; break;
189         // ToDo: should we throw error here?
190         case UnitClass::INCOMMENSURABLE:   return 0; break;
191       }
192     }
193     // fallback
194     return 0;
195   }
196
197 }