1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include <mbgl/style/expression/formatted.hpp>
#include <mbgl/style/conversion_impl.hpp>
#include <mbgl/style/conversion/constant.hpp>
namespace mbgl {
namespace style {
namespace expression {
const char* const kFormattedSectionFontScale = "font-scale";
const char* const kFormattedSectionTextFont = "text-font";
const char* const kFormattedSectionTextColor = "text-color";
bool Formatted::operator==(const Formatted& other) const {
if (other.sections.size() != sections.size()) {
return false;
}
for (std::size_t i = 0; i < sections.size(); i++) {
const auto& thisSection = sections.at(i);
const auto& otherSection = other.sections.at(i);
if (thisSection.text != otherSection.text ||
thisSection.fontScale != otherSection.fontScale ||
thisSection.fontStack != otherSection.fontStack ||
thisSection.textColor != otherSection.textColor) {
return false;
}
}
return true;
}
std::string Formatted::toString() const {
std::string result;
for (const auto& section : sections) {
result += section.text;
}
return result;
}
} // namespace expression
namespace conversion {
using namespace mbgl::style::expression;
optional<Formatted> Converter<Formatted>::operator()(const Convertible& value, Error& error) const {
using namespace mbgl::style::expression;
if (isArray(value)) {
std::vector<FormattedSection> sections;
for (std::size_t i = 0; i < arrayLength(value); ++i) {
Convertible section = arrayMember(value, i);
std::size_t sectionLength = arrayLength(section);
if (sectionLength < 1) {
error.message = "Section has to contain a text and optional parameters.";
return nullopt;
}
optional<std::string> sectionText = toString(arrayMember(section, 0));
if (!sectionText) {
error.message = "Section has to contain a text.";
return nullopt;
}
optional<double> fontScale;
optional<FontStack> textFont;
optional<Color> textColor;
if (sectionLength > 1) {
Convertible sectionParams = arrayMember(section, 1);
if (!isObject(sectionParams)) {
error.message = "Parameters have to be enclosed in an object.";
return nullopt;
}
optional<Convertible> fontScaleMember = objectMember(sectionParams, kFormattedSectionFontScale);
if (fontScaleMember) {
fontScale = toDouble(*fontScaleMember);
}
optional<Convertible> textFontMember = objectMember(sectionParams, kFormattedSectionTextFont);
if (textFontMember) {
if (isArray(*textFontMember)) {
std::vector<std::string> fontsVector;
for (std::size_t j = 0; j < arrayLength(*textFontMember); ++j) {
auto font = toString(arrayMember(*textFontMember, j));
if (font) {
fontsVector.push_back(*font);
} else {
error.message = "Font has to be a string.";
return nullopt;
}
}
textFont = fontsVector;
} else {
error.message = "Font stack has to be an array.";
return nullopt;
}
}
optional<Convertible> textColorMember = objectMember(sectionParams, kFormattedSectionTextColor);
if (textColorMember) {
textColor = convert<Color>(*textColorMember, error);
if (!textColor) {
return nullopt;
}
}
}
sections.push_back(FormattedSection(*sectionText, fontScale, textFont, textColor));
}
return Formatted(sections);
} else if (optional<std::string> result = toString(value)) {
return Formatted(result->c_str());
} else {
error.message = "Formatted must be plain string or array type.";
return nullopt;
}
}
} // namespace conversion
} // namespace style
} // namespace mbgl
|