squashed stylequest merge

* uses OSM Bright style
 * adds dot shader
 * adds layer translation
 * adds dashed line support
 * adds style array parsing
 * improves background layer parsing
 * improves style constant parsing
 * fixes sprite JSON pixel ratio parsing
This commit is contained in:
Justin R. Miller
2014-05-07 10:37:25 -07:00
parent 40e3372b80
commit 2b9fbb0731
23 changed files with 2355 additions and 421 deletions

View File

@@ -3,6 +3,8 @@
using namespace llmr;
using JSVal = const rapidjson::Value&;
void StyleParser::parseBuckets(JSVal value, std::map<std::string, BucketDescription>& buckets) {
if (value.IsObject()) {
rapidjson::Value::ConstMemberIterator itr = value.MemberBegin();
@@ -192,17 +194,17 @@ void StyleParser::parseConstants(JSVal value) {
}
}
void StyleParser::parseClasses(JSVal value, std::map<std::string, ClassDescription>& classes) {
void StyleParser::parseClasses(JSVal value, std::map<std::string, ClassDescription>& classes, std::map<std::string, BucketDescription>& buckets, std::vector<LayerDescription>& layers) {
if (value.IsArray()) {
for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
classes.insert(std::forward<std::pair<std::string, ClassDescription>>(parseClassDescription(value[i])));
classes.insert(std::forward<std::pair<std::string, ClassDescription>>(parseClassDescription(value[i], buckets, layers)));
}
} else {
throw Style::exception("classes must be an array");
}
}
std::pair<std::string, ClassDescription> StyleParser::parseClassDescription(JSVal value) {
std::pair<std::string, ClassDescription> StyleParser::parseClassDescription(JSVal value, std::map<std::string, BucketDescription>& buckets, std::vector<LayerDescription>& style_layers) {
ClassDescription klass;
std::string klass_name;
@@ -227,7 +229,7 @@ std::pair<std::string, ClassDescription> StyleParser::parseClassDescription(JSVa
const std::string name {
itr->name.GetString(), itr->name.GetStringLength()
};
parseClass(name, itr->value, klass);
parseClass(name, itr->value, klass, buckets, style_layers);
}
} else {
throw Style::exception("class layer styles must be an object");
@@ -240,32 +242,31 @@ std::pair<std::string, ClassDescription> StyleParser::parseClassDescription(JSVa
return { klass_name, std::forward<ClassDescription>(klass) };
}
void StyleParser::parseClass(const std::string& name, JSVal value, ClassDescription& class_desc) {
void StyleParser::parseClass(const std::string& name, JSVal value, ClassDescription& class_desc, std::map<std::string, BucketDescription>& buckets, std::vector<LayerDescription>& layers) {
if (value.IsObject()) {
if (value.HasMember("type")) {
JSVal type = value["type"];
if (type.IsString()) {
std::string type_name = { type.GetString(), type.GetStringLength() };
if (type_name == "fill") {
class_desc.fill.insert({ name, std::forward<FillClass>(parseFillClass(value)) });
} else if (type_name == "line") {
class_desc.line.insert({ name, std::forward<LineClass>(parseLineClass(value)) });
} else if (type_name == "point") {
class_desc.point.insert({ name, std::forward<PointClass>(parsePointClass(value)) });
} else if (type_name == "text") {
class_desc.text.insert({ name, std::forward<TextClass>(parseTextClass(value)) });
} else if (type_name == "raster") {
class_desc.raster.insert({ name, std::forward<RasterClass>(parseRasterClass(value)) });
} else if (type_name == "background") {
for (const auto& layer : layers) {
if (name == layer.name) {
if (layer.bucket_name == "background") {
// background buckets are fake
class_desc.background = parseBackgroundClass(value);
} else {
throw Style::exception("unknown class type name");
auto bucket_it = buckets.find(layer.bucket_name);
BucketType type = bucket_it->second.type;
if (type == BucketType::Fill) {
class_desc.fill.insert({ name, std::forward<FillClass>(parseFillClass(value)) });
} else if (type == BucketType::Line) {
class_desc.line.insert({ name, std::forward<LineClass>(parseLineClass(value)) });
} else if (type == BucketType::Point) {
class_desc.point.insert({ name, std::forward<PointClass>(parsePointClass(value)) });
} else if (type == BucketType::Text) {
class_desc.text.insert({ name, std::forward<TextClass>(parseTextClass(value)) });
} else if (type == BucketType::Raster) {
class_desc.raster.insert({ name, std::forward<RasterClass>(parseRasterClass(value)) });
} else {
throw Style::exception("unknown class type name");
}
}
} else {
throw Style::exception("style class type must be a string");
}
} else {
throw Style::exception("style class must specify a type");
}
} else {
throw Style::exception("style class must be an object");
@@ -288,14 +289,46 @@ std::string StyleParser::parseString(JSVal value) {
return { value.GetString(), value.GetStringLength() };
}
const JSVal& StyleParser::replaceConstant(const JSVal& value) {
if (value.IsString()) {
const std::string string_value { value.GetString(), value.GetStringLength() };
auto it = constants.find(string_value);
if (it != constants.end()) {
return *it->second;
}
}
return value;
}
std::vector<FunctionProperty> StyleParser::parseArray(JSVal value, uint16_t expected_count) {
JSVal rvalue = replaceConstant(value);
if (!rvalue.IsArray()) {
throw Style::exception("array value must be an array");
}
if (rvalue.IsArray() && rvalue.Size() != expected_count) {
throw Style::exception("array value has unexpected number of elements");
}
std::vector<FunctionProperty> values;
values.reserve(expected_count);
for (uint16_t i = 0; i < expected_count; i++) {
values.push_back(parseFunction(rvalue[(rapidjson::SizeType)i]));
}
return values;
}
Color StyleParser::parseColor(JSVal value) {
if (value.IsArray()) {
JSVal rvalue = replaceConstant(value);
if (rvalue.IsArray()) {
// [ r, g, b, a] array
if (value.Size() != 4) {
if (rvalue.Size() != 4) {
throw Style::exception("color array must have four elements");
}
JSVal r = value[(rapidjson::SizeType)0], g = value[1], b = value[2], a = value[3];
JSVal r = rvalue[(rapidjson::SizeType)0], g = rvalue[1], b = rvalue[2], a = rvalue[3];
if (!r.IsNumber() || !g.IsNumber() || !b.IsNumber() || !a.IsNumber()) {
throw Style::exception("color values must be numbers");
}
@@ -305,20 +338,13 @@ Color StyleParser::parseColor(JSVal value) {
static_cast<float>(b.GetDouble()),
static_cast<float>(a.GetDouble())}};
} else if (!value.IsString()) {
} else if (!rvalue.IsString()) {
throw Style::exception("color value must be a string");
}
const std::string str{value.GetString(), value.GetStringLength()};
auto it = constants.find(str);
if (it != constants.end()) {
return parseColor(*it->second);
} else {
CSSColorParser::Color css_color = CSSColorParser::parse(str);
return {{(float)css_color.r / 255, (float)css_color.g / 255,
(float)css_color.b / 255, css_color.a}};
}
CSSColorParser::Color css_color = CSSColorParser::parse({ rvalue.GetString(), rvalue.GetStringLength() });
return {{(float)css_color.r / 255, (float)css_color.g / 255,
(float)css_color.b / 255, css_color.a}};
}
FunctionProperty::fn StyleParser::parseFunctionType(JSVal type) {
@@ -396,6 +422,11 @@ FillClass StyleParser::parseFillClass(JSVal value) {
klass.enabled = parseFunction(value["enabled"]);
}
if (value.HasMember("translate")) {
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("color")) {
klass.fill_color = parseColor(value["color"]);
}
@@ -428,6 +459,11 @@ LineClass StyleParser::parseLineClass(JSVal value) {
klass.enabled = parseFunction(value["enabled"]);
}
if (value.HasMember("translate")) {
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("color")) {
klass.color = parseColor(value["color"]);
}
@@ -440,6 +476,11 @@ LineClass StyleParser::parseLineClass(JSVal value) {
klass.opacity = parseFunction(value["opacity"]);
}
if (value.HasMember("dasharray")) {
std::vector<FunctionProperty> values = parseArray(value["dasharray"], 2);
klass.dash_array = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
return klass;
}
@@ -450,6 +491,11 @@ PointClass StyleParser::parsePointClass(JSVal value) {
klass.enabled = parseFunction(value["enabled"]);
}
if (value.HasMember("translate")) {
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("color")) {
klass.color = parseColor(value["color"]);
}
@@ -466,6 +512,14 @@ PointClass StyleParser::parsePointClass(JSVal value) {
klass.size = parseFunction(value["size"]);
}
if (value.HasMember("radius")) {
klass.radius = parseFunction(value["radius"]);
}
if (value.HasMember("blur")) {
klass.blur = parseFunction(value["blur"]);
}
return klass;
}
@@ -477,6 +531,11 @@ TextClass StyleParser::parseTextClass(JSVal value) {
klass.enabled = parseFunction(value["enabled"]);
}
if (value.HasMember("translate")) {
std::vector<FunctionProperty> values = parseArray(value["translate"], 2);
klass.translate = std::array<FunctionProperty, 2> {{ values[0], values[1] }};
}
if (value.HasMember("color")) {
klass.color = parseColor(value["color"]);
}