sassc4 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.gitmodules +3 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +97 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.md +80 -0
- data/Rakefile +51 -0
- data/ext/depend +4 -0
- data/ext/extconf.rb +92 -0
- data/ext/libsass/VERSION +1 -0
- data/ext/libsass/contrib/plugin.cpp +60 -0
- data/ext/libsass/include/sass/base.h +97 -0
- data/ext/libsass/include/sass/context.h +174 -0
- data/ext/libsass/include/sass/functions.h +139 -0
- data/ext/libsass/include/sass/values.h +145 -0
- data/ext/libsass/include/sass/version.h +12 -0
- data/ext/libsass/include/sass.h +15 -0
- data/ext/libsass/include/sass2scss.h +120 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +953 -0
- data/ext/libsass/src/ast.hpp +1064 -0
- data/ext/libsass/src/ast2c.cpp +80 -0
- data/ext/libsass/src/ast2c.hpp +39 -0
- data/ext/libsass/src/ast_def_macros.hpp +140 -0
- data/ext/libsass/src/ast_fwd_decl.cpp +31 -0
- data/ext/libsass/src/ast_fwd_decl.hpp +274 -0
- data/ext/libsass/src/ast_helpers.hpp +316 -0
- data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
- data/ext/libsass/src/ast_sel_super.cpp +539 -0
- data/ext/libsass/src/ast_sel_unify.cpp +275 -0
- data/ext/libsass/src/ast_sel_weave.cpp +616 -0
- data/ext/libsass/src/ast_selectors.cpp +1070 -0
- data/ext/libsass/src/ast_selectors.hpp +523 -0
- data/ext/libsass/src/ast_supports.cpp +114 -0
- data/ext/libsass/src/ast_supports.hpp +121 -0
- data/ext/libsass/src/ast_values.cpp +1154 -0
- data/ext/libsass/src/ast_values.hpp +498 -0
- data/ext/libsass/src/b64/cencode.h +32 -0
- data/ext/libsass/src/b64/encode.h +79 -0
- data/ext/libsass/src/backtrace.cpp +50 -0
- data/ext/libsass/src/backtrace.hpp +29 -0
- data/ext/libsass/src/base64vlq.cpp +47 -0
- data/ext/libsass/src/base64vlq.hpp +30 -0
- data/ext/libsass/src/bind.cpp +312 -0
- data/ext/libsass/src/bind.hpp +15 -0
- data/ext/libsass/src/c2ast.cpp +64 -0
- data/ext/libsass/src/c2ast.hpp +14 -0
- data/ext/libsass/src/c99func.c +54 -0
- data/ext/libsass/src/cencode.c +106 -0
- data/ext/libsass/src/check_nesting.cpp +393 -0
- data/ext/libsass/src/check_nesting.hpp +70 -0
- data/ext/libsass/src/color_maps.cpp +652 -0
- data/ext/libsass/src/color_maps.hpp +323 -0
- data/ext/libsass/src/color_spaces.cpp +241 -0
- data/ext/libsass/src/color_spaces.hpp +227 -0
- data/ext/libsass/src/constants.cpp +199 -0
- data/ext/libsass/src/constants.hpp +200 -0
- data/ext/libsass/src/context.cpp +870 -0
- data/ext/libsass/src/context.hpp +140 -0
- data/ext/libsass/src/cssize.cpp +521 -0
- data/ext/libsass/src/cssize.hpp +71 -0
- data/ext/libsass/src/dart_helpers.hpp +199 -0
- data/ext/libsass/src/debug.hpp +43 -0
- data/ext/libsass/src/debugger.hpp +964 -0
- data/ext/libsass/src/emitter.cpp +297 -0
- data/ext/libsass/src/emitter.hpp +101 -0
- data/ext/libsass/src/environment.cpp +260 -0
- data/ext/libsass/src/environment.hpp +124 -0
- data/ext/libsass/src/error_handling.cpp +239 -0
- data/ext/libsass/src/error_handling.hpp +248 -0
- data/ext/libsass/src/eval.cpp +1543 -0
- data/ext/libsass/src/eval.hpp +110 -0
- data/ext/libsass/src/eval_selectors.cpp +75 -0
- data/ext/libsass/src/expand.cpp +875 -0
- data/ext/libsass/src/expand.hpp +98 -0
- data/ext/libsass/src/extender.cpp +1226 -0
- data/ext/libsass/src/extender.hpp +399 -0
- data/ext/libsass/src/extension.cpp +43 -0
- data/ext/libsass/src/extension.hpp +89 -0
- data/ext/libsass/src/file.cpp +531 -0
- data/ext/libsass/src/file.hpp +124 -0
- data/ext/libsass/src/fn_colors.cpp +836 -0
- data/ext/libsass/src/fn_colors.hpp +99 -0
- data/ext/libsass/src/fn_lists.cpp +285 -0
- data/ext/libsass/src/fn_lists.hpp +34 -0
- data/ext/libsass/src/fn_maps.cpp +94 -0
- data/ext/libsass/src/fn_maps.hpp +30 -0
- data/ext/libsass/src/fn_miscs.cpp +248 -0
- data/ext/libsass/src/fn_miscs.hpp +40 -0
- data/ext/libsass/src/fn_numbers.cpp +246 -0
- data/ext/libsass/src/fn_numbers.hpp +45 -0
- data/ext/libsass/src/fn_selectors.cpp +205 -0
- data/ext/libsass/src/fn_selectors.hpp +35 -0
- data/ext/libsass/src/fn_strings.cpp +268 -0
- data/ext/libsass/src/fn_strings.hpp +34 -0
- data/ext/libsass/src/fn_utils.cpp +159 -0
- data/ext/libsass/src/fn_utils.hpp +62 -0
- data/ext/libsass/src/inspect.cpp +1126 -0
- data/ext/libsass/src/inspect.hpp +101 -0
- data/ext/libsass/src/json.cpp +1436 -0
- data/ext/libsass/src/json.hpp +117 -0
- data/ext/libsass/src/kwd_arg_macros.hpp +28 -0
- data/ext/libsass/src/lexer.cpp +122 -0
- data/ext/libsass/src/lexer.hpp +304 -0
- data/ext/libsass/src/listize.cpp +70 -0
- data/ext/libsass/src/listize.hpp +37 -0
- data/ext/libsass/src/mapping.hpp +19 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
- data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/operation.hpp +223 -0
- data/ext/libsass/src/operators.cpp +267 -0
- data/ext/libsass/src/operators.hpp +30 -0
- data/ext/libsass/src/ordered_map.hpp +112 -0
- data/ext/libsass/src/output.cpp +320 -0
- data/ext/libsass/src/output.hpp +47 -0
- data/ext/libsass/src/parser.cpp +3059 -0
- data/ext/libsass/src/parser.hpp +395 -0
- data/ext/libsass/src/parser_selectors.cpp +189 -0
- data/ext/libsass/src/permutate.hpp +164 -0
- data/ext/libsass/src/plugins.cpp +188 -0
- data/ext/libsass/src/plugins.hpp +57 -0
- data/ext/libsass/src/position.cpp +163 -0
- data/ext/libsass/src/position.hpp +147 -0
- data/ext/libsass/src/prelexer.cpp +1780 -0
- data/ext/libsass/src/prelexer.hpp +484 -0
- data/ext/libsass/src/remove_placeholders.cpp +86 -0
- data/ext/libsass/src/remove_placeholders.hpp +37 -0
- data/ext/libsass/src/sass.cpp +156 -0
- data/ext/libsass/src/sass.hpp +147 -0
- data/ext/libsass/src/sass2scss.cpp +895 -0
- data/ext/libsass/src/sass_context.cpp +742 -0
- data/ext/libsass/src/sass_context.hpp +129 -0
- data/ext/libsass/src/sass_functions.cpp +210 -0
- data/ext/libsass/src/sass_functions.hpp +50 -0
- data/ext/libsass/src/sass_values.cpp +362 -0
- data/ext/libsass/src/sass_values.hpp +82 -0
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +202 -0
- data/ext/libsass/src/source_map.hpp +65 -0
- data/ext/libsass/src/stylesheet.cpp +22 -0
- data/ext/libsass/src/stylesheet.hpp +57 -0
- data/ext/libsass/src/to_value.cpp +114 -0
- data/ext/libsass/src/to_value.hpp +46 -0
- data/ext/libsass/src/units.cpp +507 -0
- data/ext/libsass/src/units.hpp +110 -0
- data/ext/libsass/src/utf8/checked.h +336 -0
- data/ext/libsass/src/utf8/core.h +332 -0
- data/ext/libsass/src/utf8/unchecked.h +235 -0
- data/ext/libsass/src/utf8.h +34 -0
- data/ext/libsass/src/utf8_string.cpp +104 -0
- data/ext/libsass/src/utf8_string.hpp +38 -0
- data/ext/libsass/src/util.cpp +723 -0
- data/ext/libsass/src/util.hpp +105 -0
- data/ext/libsass/src/util_string.cpp +125 -0
- data/ext/libsass/src/util_string.hpp +73 -0
- data/ext/libsass/src/values.cpp +140 -0
- data/ext/libsass/src/values.hpp +12 -0
- data/lib/sassc/dependency.rb +17 -0
- data/lib/sassc/engine.rb +141 -0
- data/lib/sassc/error.rb +37 -0
- data/lib/sassc/functions_handler.rb +73 -0
- data/lib/sassc/import_handler.rb +50 -0
- data/lib/sassc/importer.rb +31 -0
- data/lib/sassc/native/native_context_api.rb +147 -0
- data/lib/sassc/native/native_functions_api.rb +159 -0
- data/lib/sassc/native/sass2scss_api.rb +10 -0
- data/lib/sassc/native/sass_input_style.rb +13 -0
- data/lib/sassc/native/sass_output_style.rb +12 -0
- data/lib/sassc/native/sass_value.rb +97 -0
- data/lib/sassc/native/string_list.rb +10 -0
- data/lib/sassc/native.rb +64 -0
- data/lib/sassc/sass_2_scss.rb +9 -0
- data/lib/sassc/script/functions.rb +8 -0
- data/lib/sassc/script/value/bool.rb +32 -0
- data/lib/sassc/script/value/color.rb +95 -0
- data/lib/sassc/script/value/list.rb +136 -0
- data/lib/sassc/script/value/map.rb +69 -0
- data/lib/sassc/script/value/number.rb +389 -0
- data/lib/sassc/script/value/string.rb +96 -0
- data/lib/sassc/script/value.rb +137 -0
- data/lib/sassc/script/value_conversion/base.rb +13 -0
- data/lib/sassc/script/value_conversion/bool.rb +13 -0
- data/lib/sassc/script/value_conversion/color.rb +18 -0
- data/lib/sassc/script/value_conversion/list.rb +25 -0
- data/lib/sassc/script/value_conversion/map.rb +21 -0
- data/lib/sassc/script/value_conversion/number.rb +13 -0
- data/lib/sassc/script/value_conversion/string.rb +17 -0
- data/lib/sassc/script/value_conversion.rb +69 -0
- data/lib/sassc/script.rb +17 -0
- data/lib/sassc/util/normalized_map.rb +117 -0
- data/lib/sassc/util.rb +231 -0
- data/lib/sassc/version.rb +5 -0
- data/lib/sassc.rb +57 -0
- data/sassc.gemspec +69 -0
- data/test/css_color_level4_test.rb +168 -0
- data/test/custom_importer_test.rb +127 -0
- data/test/engine_test.rb +314 -0
- data/test/error_test.rb +29 -0
- data/test/fixtures/paths.scss +10 -0
- data/test/functions_test.rb +340 -0
- data/test/native_test.rb +213 -0
- data/test/output_style_test.rb +107 -0
- data/test/sass_2_scss_test.rb +14 -0
- data/test/test_helper.rb +45 -0
- metadata +396 -0
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
#include "sass.hpp"
|
|
2
|
+
#include <map>
|
|
3
|
+
#include <stdexcept>
|
|
4
|
+
#include <algorithm>
|
|
5
|
+
#include "units.hpp"
|
|
6
|
+
#include "error_handling.hpp"
|
|
7
|
+
|
|
8
|
+
namespace Sass {
|
|
9
|
+
|
|
10
|
+
/* the conversion matrix can be readed the following way */
|
|
11
|
+
/* if you go down, the factor is for the numerator (multiply) */
|
|
12
|
+
/* if you go right, the factor is for the denominator (divide) */
|
|
13
|
+
/* and yes, we actually use both, not sure why, but why not!? */
|
|
14
|
+
|
|
15
|
+
const double size_conversion_factors[6][6] =
|
|
16
|
+
{
|
|
17
|
+
/* in cm pc mm pt px */
|
|
18
|
+
/* in */ { 1, 2.54, 6, 25.4, 72, 96, },
|
|
19
|
+
/* cm */ { 1.0/2.54, 1, 6.0/2.54, 10, 72.0/2.54, 96.0/2.54 },
|
|
20
|
+
/* pc */ { 1.0/6.0, 2.54/6.0, 1, 25.4/6.0, 72.0/6.0, 96.0/6.0 },
|
|
21
|
+
/* mm */ { 1.0/25.4, 1.0/10.0, 6.0/25.4, 1, 72.0/25.4, 96.0/25.4 },
|
|
22
|
+
/* pt */ { 1.0/72.0, 2.54/72.0, 6.0/72.0, 25.4/72.0, 1, 96.0/72.0 },
|
|
23
|
+
/* px */ { 1.0/96.0, 2.54/96.0, 6.0/96.0, 25.4/96.0, 72.0/96.0, 1, }
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const double angle_conversion_factors[4][4] =
|
|
27
|
+
{
|
|
28
|
+
/* deg grad rad turn */
|
|
29
|
+
/* deg */ { 1, 40.0/36.0, PI/180.0, 1.0/360.0 },
|
|
30
|
+
/* grad */ { 36.0/40.0, 1, PI/200.0, 1.0/400.0 },
|
|
31
|
+
/* rad */ { 180.0/PI, 200.0/PI, 1, 0.5/PI },
|
|
32
|
+
/* turn */ { 360.0, 400.0, 2.0*PI, 1 }
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const double time_conversion_factors[2][2] =
|
|
36
|
+
{
|
|
37
|
+
/* s ms */
|
|
38
|
+
/* s */ { 1, 1000.0 },
|
|
39
|
+
/* ms */ { 1/1000.0, 1 }
|
|
40
|
+
};
|
|
41
|
+
const double frequency_conversion_factors[2][2] =
|
|
42
|
+
{
|
|
43
|
+
/* Hz kHz */
|
|
44
|
+
/* Hz */ { 1, 1/1000.0 },
|
|
45
|
+
/* kHz */ { 1000.0, 1 }
|
|
46
|
+
};
|
|
47
|
+
const double resolution_conversion_factors[3][3] =
|
|
48
|
+
{
|
|
49
|
+
/* dpi dpcm dppx */
|
|
50
|
+
/* dpi */ { 1, 1/2.54, 1/96.0 },
|
|
51
|
+
/* dpcm */ { 2.54, 1, 2.54/96 },
|
|
52
|
+
/* dppx */ { 96, 96/2.54, 1 }
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
UnitClass get_unit_type(UnitType unit)
|
|
56
|
+
{
|
|
57
|
+
switch (unit & 0xFF00)
|
|
58
|
+
{
|
|
59
|
+
case UnitClass::LENGTH: return UnitClass::LENGTH;
|
|
60
|
+
case UnitClass::ANGLE: return UnitClass::ANGLE;
|
|
61
|
+
case UnitClass::TIME: return UnitClass::TIME;
|
|
62
|
+
case UnitClass::FREQUENCY: return UnitClass::FREQUENCY;
|
|
63
|
+
case UnitClass::RESOLUTION: return UnitClass::RESOLUTION;
|
|
64
|
+
default: return UnitClass::INCOMMENSURABLE;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
sass::string get_unit_class(UnitType unit)
|
|
69
|
+
{
|
|
70
|
+
switch (unit & 0xFF00)
|
|
71
|
+
{
|
|
72
|
+
case UnitClass::LENGTH: return "LENGTH";
|
|
73
|
+
case UnitClass::ANGLE: return "ANGLE";
|
|
74
|
+
case UnitClass::TIME: return "TIME";
|
|
75
|
+
case UnitClass::FREQUENCY: return "FREQUENCY";
|
|
76
|
+
case UnitClass::RESOLUTION: return "RESOLUTION";
|
|
77
|
+
default: return "INCOMMENSURABLE";
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
UnitType get_main_unit(const UnitClass unit)
|
|
82
|
+
{
|
|
83
|
+
switch (unit)
|
|
84
|
+
{
|
|
85
|
+
case UnitClass::LENGTH: return UnitType::PX;
|
|
86
|
+
case UnitClass::ANGLE: return UnitType::DEG;
|
|
87
|
+
case UnitClass::TIME: return UnitType::SEC;
|
|
88
|
+
case UnitClass::FREQUENCY: return UnitType::HERTZ;
|
|
89
|
+
case UnitClass::RESOLUTION: return UnitType::DPI;
|
|
90
|
+
default: return UnitType::UNKNOWN;
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
UnitType string_to_unit(const sass::string& s)
|
|
95
|
+
{
|
|
96
|
+
// size units
|
|
97
|
+
if (s == "px") return UnitType::PX;
|
|
98
|
+
else if (s == "pt") return UnitType::PT;
|
|
99
|
+
else if (s == "pc") return UnitType::PC;
|
|
100
|
+
else if (s == "mm") return UnitType::MM;
|
|
101
|
+
else if (s == "cm") return UnitType::CM;
|
|
102
|
+
else if (s == "in") return UnitType::IN;
|
|
103
|
+
// angle units
|
|
104
|
+
else if (s == "deg") return UnitType::DEG;
|
|
105
|
+
else if (s == "grad") return UnitType::GRAD;
|
|
106
|
+
else if (s == "rad") return UnitType::RAD;
|
|
107
|
+
else if (s == "turn") return UnitType::TURN;
|
|
108
|
+
// time units
|
|
109
|
+
else if (s == "s") return UnitType::SEC;
|
|
110
|
+
else if (s == "ms") return UnitType::MSEC;
|
|
111
|
+
// frequency units
|
|
112
|
+
else if (s == "Hz") return UnitType::HERTZ;
|
|
113
|
+
else if (s == "kHz") return UnitType::KHERTZ;
|
|
114
|
+
// resolutions units
|
|
115
|
+
else if (s == "dpi") return UnitType::DPI;
|
|
116
|
+
else if (s == "dpcm") return UnitType::DPCM;
|
|
117
|
+
else if (s == "dppx") return UnitType::DPPX;
|
|
118
|
+
// for unknown units
|
|
119
|
+
else return UnitType::UNKNOWN;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const char* unit_to_string(UnitType unit)
|
|
123
|
+
{
|
|
124
|
+
switch (unit) {
|
|
125
|
+
// size units
|
|
126
|
+
case UnitType::PX: return "px";
|
|
127
|
+
case UnitType::PT: return "pt";
|
|
128
|
+
case UnitType::PC: return "pc";
|
|
129
|
+
case UnitType::MM: return "mm";
|
|
130
|
+
case UnitType::CM: return "cm";
|
|
131
|
+
case UnitType::IN: return "in";
|
|
132
|
+
// angle units
|
|
133
|
+
case UnitType::DEG: return "deg";
|
|
134
|
+
case UnitType::GRAD: return "grad";
|
|
135
|
+
case UnitType::RAD: return "rad";
|
|
136
|
+
case UnitType::TURN: return "turn";
|
|
137
|
+
// time units
|
|
138
|
+
case UnitType::SEC: return "s";
|
|
139
|
+
case UnitType::MSEC: return "ms";
|
|
140
|
+
// frequency units
|
|
141
|
+
case UnitType::HERTZ: return "Hz";
|
|
142
|
+
case UnitType::KHERTZ: return "kHz";
|
|
143
|
+
// resolutions units
|
|
144
|
+
case UnitType::DPI: return "dpi";
|
|
145
|
+
case UnitType::DPCM: return "dpcm";
|
|
146
|
+
case UnitType::DPPX: return "dppx";
|
|
147
|
+
// for unknown units
|
|
148
|
+
default: return "";
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
sass::string unit_to_class(const sass::string& s)
|
|
153
|
+
{
|
|
154
|
+
if (s == "px") return "LENGTH";
|
|
155
|
+
else if (s == "pt") return "LENGTH";
|
|
156
|
+
else if (s == "pc") return "LENGTH";
|
|
157
|
+
else if (s == "mm") return "LENGTH";
|
|
158
|
+
else if (s == "cm") return "LENGTH";
|
|
159
|
+
else if (s == "in") return "LENGTH";
|
|
160
|
+
// angle units
|
|
161
|
+
else if (s == "deg") return "ANGLE";
|
|
162
|
+
else if (s == "grad") return "ANGLE";
|
|
163
|
+
else if (s == "rad") return "ANGLE";
|
|
164
|
+
else if (s == "turn") return "ANGLE";
|
|
165
|
+
// time units
|
|
166
|
+
else if (s == "s") return "TIME";
|
|
167
|
+
else if (s == "ms") return "TIME";
|
|
168
|
+
// frequency units
|
|
169
|
+
else if (s == "Hz") return "FREQUENCY";
|
|
170
|
+
else if (s == "kHz") return "FREQUENCY";
|
|
171
|
+
// resolutions units
|
|
172
|
+
else if (s == "dpi") return "RESOLUTION";
|
|
173
|
+
else if (s == "dpcm") return "RESOLUTION";
|
|
174
|
+
else if (s == "dppx") return "RESOLUTION";
|
|
175
|
+
// for unknown units
|
|
176
|
+
return "CUSTOM:" + s;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// throws incompatibleUnits exceptions
|
|
180
|
+
double conversion_factor(const sass::string& s1, const sass::string& s2)
|
|
181
|
+
{
|
|
182
|
+
// assert for same units
|
|
183
|
+
if (s1 == s2) return 1;
|
|
184
|
+
// get unit enum from string
|
|
185
|
+
UnitType u1 = string_to_unit(s1);
|
|
186
|
+
UnitType u2 = string_to_unit(s2);
|
|
187
|
+
// query unit group types
|
|
188
|
+
UnitClass t1 = get_unit_type(u1);
|
|
189
|
+
UnitClass t2 = get_unit_type(u2);
|
|
190
|
+
// return the conversion factor
|
|
191
|
+
return conversion_factor(u1, u2, t1, t2);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// throws incompatibleUnits exceptions
|
|
195
|
+
double conversion_factor(UnitType u1, UnitType u2, UnitClass t1, UnitClass t2)
|
|
196
|
+
{
|
|
197
|
+
// can't convert between groups
|
|
198
|
+
if (t1 != t2) return 0;
|
|
199
|
+
// get absolute offset
|
|
200
|
+
// used for array acces
|
|
201
|
+
size_t i1 = u1 - t1;
|
|
202
|
+
size_t i2 = u2 - t2;
|
|
203
|
+
// process known units
|
|
204
|
+
switch (t1) {
|
|
205
|
+
case LENGTH:
|
|
206
|
+
return size_conversion_factors[i1][i2];
|
|
207
|
+
case ANGLE:
|
|
208
|
+
return angle_conversion_factors[i1][i2];
|
|
209
|
+
case TIME:
|
|
210
|
+
return time_conversion_factors[i1][i2];
|
|
211
|
+
case FREQUENCY:
|
|
212
|
+
return frequency_conversion_factors[i1][i2];
|
|
213
|
+
case RESOLUTION:
|
|
214
|
+
return resolution_conversion_factors[i1][i2];
|
|
215
|
+
case INCOMMENSURABLE:
|
|
216
|
+
return 0;
|
|
217
|
+
}
|
|
218
|
+
// fallback
|
|
219
|
+
return 0;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
double convert_units(const sass::string& lhs, const sass::string& rhs, int& lhsexp, int& rhsexp)
|
|
223
|
+
{
|
|
224
|
+
double f = 0;
|
|
225
|
+
// do not convert same ones
|
|
226
|
+
if (lhs == rhs) return 0;
|
|
227
|
+
// skip already canceled out unit
|
|
228
|
+
if (lhsexp == 0) return 0;
|
|
229
|
+
if (rhsexp == 0) return 0;
|
|
230
|
+
// check if it can be converted
|
|
231
|
+
UnitType ulhs = string_to_unit(lhs);
|
|
232
|
+
UnitType urhs = string_to_unit(rhs);
|
|
233
|
+
// skip units we cannot convert
|
|
234
|
+
if (ulhs == UNKNOWN) return 0;
|
|
235
|
+
if (urhs == UNKNOWN) return 0;
|
|
236
|
+
// query unit group types
|
|
237
|
+
UnitClass clhs = get_unit_type(ulhs);
|
|
238
|
+
UnitClass crhs = get_unit_type(urhs);
|
|
239
|
+
// skip units we cannot convert
|
|
240
|
+
if (clhs != crhs) return 0;
|
|
241
|
+
// if right denominator is bigger than lhs, we want to keep it in rhs unit
|
|
242
|
+
if (rhsexp < 0 && lhsexp > 0 && - rhsexp > lhsexp) {
|
|
243
|
+
// get the conversion factor for units
|
|
244
|
+
f = conversion_factor(urhs, ulhs, clhs, crhs);
|
|
245
|
+
// left hand side has been consumned
|
|
246
|
+
f = std::pow(f, lhsexp);
|
|
247
|
+
rhsexp += lhsexp;
|
|
248
|
+
lhsexp = 0;
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
// get the conversion factor for units
|
|
252
|
+
f = conversion_factor(ulhs, urhs, clhs, crhs);
|
|
253
|
+
// right hand side has been consumned
|
|
254
|
+
f = std::pow(f, rhsexp);
|
|
255
|
+
lhsexp += rhsexp;
|
|
256
|
+
rhsexp = 0;
|
|
257
|
+
}
|
|
258
|
+
return f;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
bool Units::operator< (const Units& rhs) const
|
|
262
|
+
{
|
|
263
|
+
return (numerators < rhs.numerators) &&
|
|
264
|
+
(denominators < rhs.denominators);
|
|
265
|
+
}
|
|
266
|
+
bool Units::operator== (const Units& rhs) const
|
|
267
|
+
{
|
|
268
|
+
return (numerators == rhs.numerators) &&
|
|
269
|
+
(denominators == rhs.denominators);
|
|
270
|
+
}
|
|
271
|
+
bool Units::operator!= (const Units& rhs) const
|
|
272
|
+
{
|
|
273
|
+
return ! (*this == rhs);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
double Units::normalize()
|
|
277
|
+
{
|
|
278
|
+
|
|
279
|
+
size_t iL = numerators.size();
|
|
280
|
+
size_t nL = denominators.size();
|
|
281
|
+
|
|
282
|
+
// the final conversion factor
|
|
283
|
+
double factor = 1;
|
|
284
|
+
|
|
285
|
+
for (size_t i = 0; i < iL; i++) {
|
|
286
|
+
sass::string &lhs = numerators[i];
|
|
287
|
+
UnitType ulhs = string_to_unit(lhs);
|
|
288
|
+
if (ulhs == UNKNOWN) continue;
|
|
289
|
+
UnitClass clhs = get_unit_type(ulhs);
|
|
290
|
+
UnitType umain = get_main_unit(clhs);
|
|
291
|
+
if (ulhs == umain) continue;
|
|
292
|
+
double f(conversion_factor(umain, ulhs, clhs, clhs));
|
|
293
|
+
if (f == 0) throw std::runtime_error("INVALID");
|
|
294
|
+
numerators[i] = unit_to_string(umain);
|
|
295
|
+
factor /= f;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
for (size_t n = 0; n < nL; n++) {
|
|
299
|
+
sass::string &rhs = denominators[n];
|
|
300
|
+
UnitType urhs = string_to_unit(rhs);
|
|
301
|
+
if (urhs == UNKNOWN) continue;
|
|
302
|
+
UnitClass crhs = get_unit_type(urhs);
|
|
303
|
+
UnitType umain = get_main_unit(crhs);
|
|
304
|
+
if (urhs == umain) continue;
|
|
305
|
+
double f(conversion_factor(umain, urhs, crhs, crhs));
|
|
306
|
+
if (f == 0) throw std::runtime_error("INVALID");
|
|
307
|
+
denominators[n] = unit_to_string(umain);
|
|
308
|
+
factor /= f;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
std::sort (numerators.begin(), numerators.end());
|
|
312
|
+
std::sort (denominators.begin(), denominators.end());
|
|
313
|
+
|
|
314
|
+
// return for conversion
|
|
315
|
+
return factor;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
double Units::reduce()
|
|
319
|
+
{
|
|
320
|
+
|
|
321
|
+
size_t iL = numerators.size();
|
|
322
|
+
size_t nL = denominators.size();
|
|
323
|
+
|
|
324
|
+
// have less than two units?
|
|
325
|
+
if (iL + nL < 2) return 1;
|
|
326
|
+
|
|
327
|
+
// first make sure same units cancel each other out
|
|
328
|
+
// it seems that a map table will fit nicely to do this
|
|
329
|
+
// we basically construct exponents for each unit
|
|
330
|
+
// has the advantage that they will be pre-sorted
|
|
331
|
+
std::map<sass::string, int> exponents;
|
|
332
|
+
|
|
333
|
+
// initialize by summing up occurrences in unit vectors
|
|
334
|
+
// this will already cancel out equivalent units (e.q. px/px)
|
|
335
|
+
for (size_t i = 0; i < iL; i ++) exponents[numerators[i]] += 1;
|
|
336
|
+
for (size_t n = 0; n < nL; n ++) exponents[denominators[n]] -= 1;
|
|
337
|
+
|
|
338
|
+
// the final conversion factor
|
|
339
|
+
double factor = 1;
|
|
340
|
+
|
|
341
|
+
// convert between compatible units
|
|
342
|
+
for (size_t i = 0; i < iL; i++) {
|
|
343
|
+
for (size_t n = 0; n < nL; n++) {
|
|
344
|
+
sass::string &lhs = numerators[i], &rhs = denominators[n];
|
|
345
|
+
int &lhsexp = exponents[lhs], &rhsexp = exponents[rhs];
|
|
346
|
+
double f(convert_units(lhs, rhs, lhsexp, rhsexp));
|
|
347
|
+
if (f == 0) continue;
|
|
348
|
+
factor /= f;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// now we can build up the new unit arrays
|
|
353
|
+
numerators.clear();
|
|
354
|
+
denominators.clear();
|
|
355
|
+
|
|
356
|
+
// recreate sorted units vectors
|
|
357
|
+
for (auto exp : exponents) {
|
|
358
|
+
int &exponent = exp.second;
|
|
359
|
+
while (exponent > 0 && exponent --)
|
|
360
|
+
numerators.push_back(exp.first);
|
|
361
|
+
while (exponent < 0 && exponent ++)
|
|
362
|
+
denominators.push_back(exp.first);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// return for conversion
|
|
366
|
+
return factor;
|
|
367
|
+
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
sass::string Units::unit() const
|
|
371
|
+
{
|
|
372
|
+
sass::string u;
|
|
373
|
+
size_t iL = numerators.size();
|
|
374
|
+
size_t nL = denominators.size();
|
|
375
|
+
for (size_t i = 0; i < iL; i += 1) {
|
|
376
|
+
if (i) u += '*';
|
|
377
|
+
u += numerators[i];
|
|
378
|
+
}
|
|
379
|
+
if (nL != 0) u += '/';
|
|
380
|
+
for (size_t n = 0; n < nL; n += 1) {
|
|
381
|
+
if (n) u += '*';
|
|
382
|
+
u += denominators[n];
|
|
383
|
+
}
|
|
384
|
+
return u;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
bool Units::is_unitless() const
|
|
388
|
+
{
|
|
389
|
+
return numerators.empty() &&
|
|
390
|
+
denominators.empty();
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
bool Units::is_valid_css_unit() const
|
|
394
|
+
{
|
|
395
|
+
return numerators.size() <= 1 &&
|
|
396
|
+
denominators.size() == 0;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// this does not cover all cases (multiple preferred units)
|
|
400
|
+
double Units::convert_factor(const Units& r) const
|
|
401
|
+
{
|
|
402
|
+
|
|
403
|
+
sass::vector<sass::string> miss_nums(0);
|
|
404
|
+
sass::vector<sass::string> miss_dens(0);
|
|
405
|
+
// create copy since we need these for state keeping
|
|
406
|
+
sass::vector<sass::string> r_nums(r.numerators);
|
|
407
|
+
sass::vector<sass::string> r_dens(r.denominators);
|
|
408
|
+
|
|
409
|
+
auto l_num_it = numerators.begin();
|
|
410
|
+
auto l_num_end = numerators.end();
|
|
411
|
+
|
|
412
|
+
bool l_unitless = is_unitless();
|
|
413
|
+
auto r_unitless = r.is_unitless();
|
|
414
|
+
|
|
415
|
+
// overall conversion
|
|
416
|
+
double factor = 1;
|
|
417
|
+
|
|
418
|
+
// process all left numerators
|
|
419
|
+
while (l_num_it != l_num_end)
|
|
420
|
+
{
|
|
421
|
+
// get and increment afterwards
|
|
422
|
+
const sass::string l_num = *(l_num_it ++);
|
|
423
|
+
|
|
424
|
+
auto r_num_it = r_nums.begin(), r_num_end = r_nums.end();
|
|
425
|
+
|
|
426
|
+
bool found = false;
|
|
427
|
+
// search for compatible numerator
|
|
428
|
+
while (r_num_it != r_num_end)
|
|
429
|
+
{
|
|
430
|
+
// get and increment afterwards
|
|
431
|
+
const sass::string r_num = *(r_num_it);
|
|
432
|
+
// get possible conversion factor for units
|
|
433
|
+
double conversion = conversion_factor(l_num, r_num);
|
|
434
|
+
// skip incompatible numerator
|
|
435
|
+
if (conversion == 0) {
|
|
436
|
+
++ r_num_it;
|
|
437
|
+
continue;
|
|
438
|
+
}
|
|
439
|
+
// apply to global factor
|
|
440
|
+
factor *= conversion;
|
|
441
|
+
// remove item from vector
|
|
442
|
+
r_nums.erase(r_num_it);
|
|
443
|
+
// found numerator
|
|
444
|
+
found = true;
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
// maybe we did not find any
|
|
448
|
+
// left numerator is leftover
|
|
449
|
+
if (!found) miss_nums.push_back(l_num);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
auto l_den_it = denominators.begin();
|
|
453
|
+
auto l_den_end = denominators.end();
|
|
454
|
+
|
|
455
|
+
// process all left denominators
|
|
456
|
+
while (l_den_it != l_den_end)
|
|
457
|
+
{
|
|
458
|
+
// get and increment afterwards
|
|
459
|
+
const sass::string l_den = *(l_den_it ++);
|
|
460
|
+
|
|
461
|
+
auto r_den_it = r_dens.begin();
|
|
462
|
+
auto r_den_end = r_dens.end();
|
|
463
|
+
|
|
464
|
+
bool found = false;
|
|
465
|
+
// search for compatible denominator
|
|
466
|
+
while (r_den_it != r_den_end)
|
|
467
|
+
{
|
|
468
|
+
// get and increment afterwards
|
|
469
|
+
const sass::string r_den = *(r_den_it);
|
|
470
|
+
// get possible conversion factor for units
|
|
471
|
+
double conversion = conversion_factor(l_den, r_den);
|
|
472
|
+
// skip incompatible denominator
|
|
473
|
+
if (conversion == 0) {
|
|
474
|
+
++ r_den_it;
|
|
475
|
+
continue;
|
|
476
|
+
}
|
|
477
|
+
// apply to global factor
|
|
478
|
+
factor /= conversion;
|
|
479
|
+
// remove item from vector
|
|
480
|
+
r_dens.erase(r_den_it);
|
|
481
|
+
// found denominator
|
|
482
|
+
found = true;
|
|
483
|
+
break;
|
|
484
|
+
}
|
|
485
|
+
// maybe we did not find any
|
|
486
|
+
// left denominator is leftover
|
|
487
|
+
if (!found) miss_dens.push_back(l_den);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// check left-overs (ToDo: might cancel out?)
|
|
491
|
+
if (miss_nums.size() > 0 && !r_unitless) {
|
|
492
|
+
throw Exception::IncompatibleUnits(r, *this);
|
|
493
|
+
}
|
|
494
|
+
else if (miss_dens.size() > 0 && !r_unitless) {
|
|
495
|
+
throw Exception::IncompatibleUnits(r, *this);
|
|
496
|
+
}
|
|
497
|
+
else if (r_nums.size() > 0 && !l_unitless) {
|
|
498
|
+
throw Exception::IncompatibleUnits(r, *this);
|
|
499
|
+
}
|
|
500
|
+
else if (r_dens.size() > 0 && !l_unitless) {
|
|
501
|
+
throw Exception::IncompatibleUnits(r, *this);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return factor;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
#ifndef SASS_UNITS_H
|
|
2
|
+
#define SASS_UNITS_H
|
|
3
|
+
|
|
4
|
+
#include <cmath>
|
|
5
|
+
#include <string>
|
|
6
|
+
#include <sstream>
|
|
7
|
+
#include <vector>
|
|
8
|
+
|
|
9
|
+
namespace Sass {
|
|
10
|
+
|
|
11
|
+
const double PI = std::acos(-1);
|
|
12
|
+
|
|
13
|
+
enum UnitClass {
|
|
14
|
+
LENGTH = 0x000,
|
|
15
|
+
ANGLE = 0x100,
|
|
16
|
+
TIME = 0x200,
|
|
17
|
+
FREQUENCY = 0x300,
|
|
18
|
+
RESOLUTION = 0x400,
|
|
19
|
+
INCOMMENSURABLE = 0x500
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
enum UnitType {
|
|
23
|
+
|
|
24
|
+
// size units
|
|
25
|
+
IN = UnitClass::LENGTH,
|
|
26
|
+
CM,
|
|
27
|
+
PC,
|
|
28
|
+
MM,
|
|
29
|
+
PT,
|
|
30
|
+
PX,
|
|
31
|
+
|
|
32
|
+
// angle units
|
|
33
|
+
DEG = ANGLE,
|
|
34
|
+
GRAD,
|
|
35
|
+
RAD,
|
|
36
|
+
TURN,
|
|
37
|
+
|
|
38
|
+
// time units
|
|
39
|
+
SEC = TIME,
|
|
40
|
+
MSEC,
|
|
41
|
+
|
|
42
|
+
// frequency units
|
|
43
|
+
HERTZ = FREQUENCY,
|
|
44
|
+
KHERTZ,
|
|
45
|
+
|
|
46
|
+
// resolutions units
|
|
47
|
+
DPI = RESOLUTION,
|
|
48
|
+
DPCM,
|
|
49
|
+
DPPX,
|
|
50
|
+
|
|
51
|
+
// for unknown units
|
|
52
|
+
UNKNOWN = INCOMMENSURABLE
|
|
53
|
+
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
class Units {
|
|
57
|
+
public:
|
|
58
|
+
sass::vector<sass::string> numerators;
|
|
59
|
+
sass::vector<sass::string> denominators;
|
|
60
|
+
public:
|
|
61
|
+
// default constructor
|
|
62
|
+
Units() :
|
|
63
|
+
numerators(),
|
|
64
|
+
denominators()
|
|
65
|
+
{ }
|
|
66
|
+
// copy constructor
|
|
67
|
+
Units(const Units* ptr) :
|
|
68
|
+
numerators(ptr->numerators),
|
|
69
|
+
denominators(ptr->denominators)
|
|
70
|
+
{ }
|
|
71
|
+
// convert to string
|
|
72
|
+
sass::string unit() const;
|
|
73
|
+
// get if units are empty
|
|
74
|
+
bool is_unitless() const;
|
|
75
|
+
// return if valid for css
|
|
76
|
+
bool is_valid_css_unit() const;
|
|
77
|
+
// reduce units for output
|
|
78
|
+
// returns conversion factor
|
|
79
|
+
double reduce();
|
|
80
|
+
// normalize units for compare
|
|
81
|
+
// returns conversion factor
|
|
82
|
+
double normalize();
|
|
83
|
+
// compare operations
|
|
84
|
+
bool operator< (const Units& rhs) const;
|
|
85
|
+
bool operator== (const Units& rhs) const;
|
|
86
|
+
bool operator!= (const Units& rhs) const;
|
|
87
|
+
// factor to convert into given units
|
|
88
|
+
double convert_factor(const Units&) const;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
extern const double size_conversion_factors[6][6];
|
|
92
|
+
extern const double angle_conversion_factors[4][4];
|
|
93
|
+
extern const double time_conversion_factors[2][2];
|
|
94
|
+
extern const double frequency_conversion_factors[2][2];
|
|
95
|
+
extern const double resolution_conversion_factors[3][3];
|
|
96
|
+
|
|
97
|
+
UnitType get_main_unit(const UnitClass unit);
|
|
98
|
+
enum Sass::UnitType string_to_unit(const sass::string&);
|
|
99
|
+
const char* unit_to_string(Sass::UnitType unit);
|
|
100
|
+
enum Sass::UnitClass get_unit_type(Sass::UnitType unit);
|
|
101
|
+
sass::string get_unit_class(Sass::UnitType unit);
|
|
102
|
+
sass::string unit_to_class(const sass::string&);
|
|
103
|
+
// throws incompatibleUnits exceptions
|
|
104
|
+
double conversion_factor(const sass::string&, const sass::string&);
|
|
105
|
+
double conversion_factor(UnitType, UnitType, UnitClass, UnitClass);
|
|
106
|
+
double convert_units(const sass::string&, const sass::string&, int&, int&);
|
|
107
|
+
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
#endif
|