cascade styles

This commit is contained in:
Konstantin Käfer
2014-01-27 17:21:48 +01:00
parent e2dbcc95b5
commit 1538ebaf22
16 changed files with 408 additions and 113 deletions

View File

@@ -30,8 +30,16 @@ code += '\n';
code += 'using namespace llmr;\n';
code += '\n';
code += 'const unsigned char resources::' + name + '[] = {\n';
code += ' ' + Array.prototype.join.call(data, ', ') + '\n';
code += '};\n';
for (var i = 0; i < data.length; i += 16) {
if (i > 0) {
code += ',\n';
}
var part = data.slice(i, i + 16);
code += ' ' + Array.prototype.join.call(part, ', ');
}
code += '\n};\n';
code += 'const unsigned long resources::' + name + '_size = sizeof(resources::' + name + ');\n';
fs.writeFileSync('src/resources/' + name + '.cpp', code);

View File

@@ -27,6 +27,13 @@ var join_type = {
bevel: 2
};
// enum
var property_type = {
'null': 1,
constant: 2,
stops: 3
};
function createValue(value) {
var pbf = new Protobuf();
@@ -83,27 +90,61 @@ function createStructure(structure) {
return pbf;
}
function createWidth(width) {
// function createWidth(width) {
// var pbf = new Protobuf();
// var values = [];
// if (Array.isArray(width)) {
// pbf.writeTaggedString(1 /* scaling */, width[0]);
// for (var i = 1; i < width.length; i++) {
// if (width[0] === 'stops') {
// values.push(width[i].z, width[i].val);
// } else {
// values.push(width[i]);
// }
// }
// } else {
// values.push(width);
// }
// pbf.writePackedFloats(2 /* value */, values);
// return pbf;
// }
function createProperty(type, values) {
var pbf = new Protobuf();
var values = [];
if (Array.isArray(width)) {
pbf.writeTaggedString(1 /* scaling */, width[0]);
for (var i = 1; i < width.length; i++) {
if (width[0] === 'stops') {
values.push(width[i].z, width[i].val);
} else {
values.push(width[i]);
}
}
} else {
values.push(width);
}
pbf.writePackedFloats(2 /* value */, values);
pbf.writeTaggedVarint(1 /* function */, property_type[type]);
pbf.writePackedFloats(2 /* value */, values.map(function(value) { return +value; }));
return pbf;
}
function createLayer(layer, name) {
function createFillClass(layer, name) {
var pbf = new Protobuf();
pbf.writeTaggedString(1 /* layer_name */, name);
if ('antialias' in layer) {
pbf.writeMessage(4 /* antialias */, createProperty('constant', [layer.antialias]));
}
if ('color' in layer) {
var color = layer.color.match(/^#([0-9a-f]{6})$/i);
if (!color) {
console.warn('invalid color');
} else {
pbf.writeTaggedUInt32(5 /* fill_color */, parseInt(color[1] + 'ff', 16));
}
}
if ('opacity' in layer) {
if (typeof layer.opacity == 'number') {
pbf.writeMessage(7 /* opacity */, createProperty('constant', [layer.opacity]));
}
}
return pbf;
}
function createLineClass(layer, name) {
var pbf = new Protobuf();
pbf.writeTaggedString(1 /* layer_name */, name);
@@ -112,16 +153,28 @@ function createLayer(layer, name) {
if (!color) {
console.warn('invalid color');
} else {
pbf.writeTaggedUInt32(2 /* color */, parseInt(color[1] + 'ff', 16));
pbf.writeTaggedUInt32(3 /* color */, parseInt(color[1] + 'ff', 16));
}
}
if ('antialias' in layer) {
pbf.writeTaggedBoolean(3 /* antialias */, layer.antialias);
}
if ('width' in layer) {
pbf.writeMessage(4 /* width */, createWidth(layer.width));
var values = [];
var width = layer.width;
var type = 'constant';
if (Array.isArray(width)) {
type = width[0];
for (var i = 1; i < width.length; i++) {
if (width[0] === 'stops') {
values.push(width[i].z, width[i].val);
} else {
values.push(width[i]);
}
}
} else {
values.push(width);
}
pbf.writeMessage(4 /* width */, createProperty(type, values));
}
return pbf;
@@ -132,7 +185,10 @@ function createClass(klass) {
var pbf = new Protobuf();
pbf.writeTaggedString(1 /* name */, klass.name);
for (var name in klass.layers) {
pbf.writeMessage(2 /* layer */, createLayer(klass.layers[name], name));
switch (klass.layers[name].type) {
case 'fill': pbf.writeMessage(2 /* fill */, createFillClass(klass.layers[name], name)); break;
case 'line': pbf.writeMessage(3 /* line */, createLineClass(klass.layers[name], name)); break;
}
}
return pbf;
}

View File

@@ -75,21 +75,27 @@ module.exports = {
"name": "default",
"layers": {
"background": {
"type": "background",
"color": "#FFFFFF"
},
"park": {
"type": "fill",
"color": "#c8df9f",
"antialias": true
},
"wood": {
"type": "fill",
"color": "#33AA66",
"antialias": true
"antialias": true,
"opacity": 0.1
},
"water": {
"type": "fill",
"color": "#73b6e6",
"antialias": true
},
"road_limited": {
"type": "line",
"color": "#BBBBBB",
"width": [
"stops",
@@ -98,6 +104,7 @@ module.exports = {
]
},
"road_regular": {
"type": "line",
"color": "#999999",
"width": [
"stops",
@@ -108,6 +115,7 @@ module.exports = {
],
},
"road_large": {
"type": "line",
"color": "#666666",
"width": [
"stops",
@@ -119,6 +127,7 @@ module.exports = {
],
},
"alcohol": {
"type": "marker",
"image": "alcohol-shop"
}
}

View File

@@ -39,7 +39,7 @@ public:
// Getters
void matrixFor(float matrix[16], const vec3<int32_t>& id) const;
int32_t getZoom() const;
float getZoom() const;
double getScale() const;
double getAngle() const;
void getLonLat(double& lon, double& lat) const;

View File

@@ -8,25 +8,13 @@
namespace llmr {
class WidthDescription {
class ClassDescription {
public:
std::string scaling;
std::vector<float> value;
std::map<std::string, FillClass> fill;
std::map<std::string, StrokeClass> stroke;
};
class LayerStyleDescription {
public:
Color color = {{ 0, 0, 0, 0 }};
bool antialias = false;
WidthDescription width;
};
typedef std::map<std::string, LayerStyleDescription> ClassDescription;
std::ostream& operator<<(std::ostream&, const ClassDescription& layer);
}
#endif

View File

@@ -2,12 +2,13 @@
#define LLMR_STYLE_PROPERTIES
#include <array>
#include <vector>
namespace llmr {
typedef std::array<float, 4> Color;
enum Winding {
enum class Winding {
EvenOdd = 1,
NonZero = 2
};
@@ -22,19 +23,71 @@ enum Winding {
// };
enum class Property {
Null = 1,
Constant = 2,
Stops = 3
};
namespace functions {
float null(float z, const std::vector<float>&);
bool null(float z, const std::vector<bool>&);
float constant(float z, const std::vector<float>& values);
bool constant(float z, const std::vector<bool>& values);
}
template <typename T>
struct FunctionProperty {
typedef T (*fn)(float z, const std::vector<T>& values);
fn function;
std::vector<T> values;
inline FunctionProperty() : function(&functions::null) {}
inline FunctionProperty(T value) : function(&functions::constant), values(1, value) {}
inline T operator()(float z) const { return function(z, values); }
};
// StrokeClass is the information we parse from the stylesheet
struct StrokeClass {
FunctionProperty<bool> hidden;
FunctionProperty<float> width;
FunctionProperty<float> offset;
Color color = {{ 0, 0, 0, 1 }};
};
// StrokeProperties is the one we resolve this to.
struct StrokeProperties {
bool enabled = false;
Color line_color = {{ 0, 0, 0, 1 }};
float line_width = 1;
bool hidden = false;
float width = 0;
float offset = 0;
Color color = {{ 0, 0, 0, 1 }};
};
struct FillClass {
FunctionProperty<bool> hidden;
Winding winding = Winding::NonZero;
FunctionProperty<bool> antialias = true;
Color fill_color = {{ 0, 0, 0, 1 }};
Color stroke_color = {{ 0, 0, 0, std::numeric_limits<float>::infinity() }};
FunctionProperty<float> opacity = 1;
};
struct FillProperties {
bool enabled = false;
Winding winding = NonZero;
bool antialiasing = true;
bool hidden = false;
Winding winding = Winding::NonZero;
bool antialias = true;
Color fill_color = {{ 0, 0, 0, 1 }};
Color stroke_color = {{ 0, 0, 0, 1 }};
float stroke_width = 1;
float opacity = 1.0;
};
}

View File

@@ -21,14 +21,16 @@ public:
void reset();
void load(const uint8_t *const data, uint32_t bytes);
void cascade();
void cascade(float z);
private:
static std::pair<std::string, BucketDescription> loadBucket(pbf data);
static LayerDescription loadLayer(pbf data);
static std::pair<std::string, ClassDescription> loadClass(pbf data);
static std::pair<std::string, LayerStyleDescription> loadLayerStyle(pbf data);
static WidthDescription loadWidth(pbf data);
static std::pair<std::string, BucketDescription> parseBucket(pbf data);
static LayerDescription parseLayer(pbf data);
static std::pair<std::string, ClassDescription> parseClass(pbf data);
static std::pair<std::string, FillClass> parseFillClass(pbf data);
static std::pair<std::string, StrokeClass> parseStrokeClass(pbf data);
template <typename T> static FunctionProperty<T> parseProperty(pbf data);
static Color parseColor(pbf& data);
public:
// This is static information parsed from the stylesheet.

View File

@@ -2,6 +2,8 @@ enum bucket_type {
fill = 1;
line = 2;
point = 3;
background = 15;
}
enum cap_type {
@@ -13,6 +15,17 @@ enum join_type {
bevel = 2;
}
enum winding_type {
evenodd = 1;
nonzero = 2;
}
enum property_type {
null = 1;
constant = 2;
stops = 3;
}
message value {
// Exactly one of these values may be present in a valid message
optional string string_value = 1;
@@ -49,21 +62,38 @@ message layer {
repeated layer child_layer = 3;
}
message width {
optional string scaling = 1;
message property {
required property_type function = 1;
repeated float value = 2 [ packed = true ];
}
message layer_style {
message fill_style {
required string layer_name = 1;
optional fixed32 color = 2; // rgba (=> rgb << 8 | 0xFF for opaque!)
optional bool antialias = 3;
optional width width = 4;
optional property hidden = 2;
optional winding_type winding = 3 [ default = nonzero ];
optional property antialias = 4;
optional fixed32 fill_color = 5 [ default = 0x000000FF ]; // rgba (=> rgb << 8 | 0xFF for opaque!)
optional fixed32 stroke_color = 6; // if none is specified, no stroke will be painted
optional property opacity = 7; // values from 0..1
// TODO: translate x/y
}
message stroke_style {
required string layer_name = 1;
optional property hidden = 2;
optional fixed32 color = 3 [ default = 0x000000FF ]; // rgba (=> rgb << 8 | 0xFF for opaque!)
optional property width = 4;
optional property offset = 5;
// line join + line cap are already defined in the
// TODO: dasharray
// TODO: image/icon
// TODO: translate x/y
}
message class {
required string name = 1;
repeated layer_style layer = 2;
repeated fill_style fill = 2;
repeated stroke_style stroke = 3;
}
// root level object

Binary file not shown.

View File

@@ -17,6 +17,7 @@ SET(llmr_SOURCES
style/value.cpp
style/bucket_description.cpp
style/layer_description.cpp
style/properties.cpp
util/animation.cpp
util/mat4.cpp
)

View File

@@ -39,6 +39,7 @@ void Map::loadSettings() {
transform.setAngle(settings.angle);
transform.setScale(settings.scale);
transform.setLonLat(settings.longitude, settings.latitude);
style.cascade(transform.getZoom());
update();
}
@@ -60,6 +61,7 @@ void Map::moveBy(double dx, double dy) {
void Map::scaleBy(double ds, double cx, double cy) {
transform.scaleBy(ds, cx, cy);
style.cascade(transform.getZoom());
update();
transform.getLonLat(settings.longitude, settings.latitude);
@@ -87,6 +89,7 @@ void Map::resetPosition() {
transform.setAngle(0);
transform.setLonLat(0, 0);
transform.setZoom(0);
style.cascade(transform.getZoom());
update();
transform.getLonLat(settings.longitude, settings.latitude);

View File

@@ -164,8 +164,8 @@ void Transform::matrixFor(float matrix[16], const vec3<int32_t>& id) const {
mat4::translate(matrix, matrix, 0, 0, -1);
}
int32_t Transform::getZoom() const {
return floor(log(scale) / M_LN2);
float Transform::getZoom() const {
return log(scale) / M_LN2;
}
double Transform::getScale() const {

View File

@@ -204,7 +204,13 @@ void Painter::renderLayers(const std::shared_ptr<Tile>& tile, const std::vector<
void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) {
const FillProperties& properties = style.computed.fills[layer_name];
if (!properties.enabled) return;
if (properties.hidden) return;
Color fill_color = properties.fill_color;
fill_color[0] *= properties.opacity;
fill_color[1] *= properties.opacity;
fill_color[2] *= properties.opacity;
fill_color[3] *= properties.opacity;
// Draw the stencil mask.
{
@@ -219,7 +225,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) {
// orientation, while all holes (see below) are in CW orientation.
glStencilFunc(GL_NOTEQUAL, 0x80, 0x80);
if (properties.winding == EvenOdd) {
if (properties.winding == Winding::EvenOdd) {
// When we draw an even/odd winding fill, we just invert all the bits.
glStencilOp(GL_INVERT, GL_KEEP, GL_KEEP);
} else {
@@ -252,7 +258,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) {
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
if (properties.antialiasing) {
if (properties.antialias) {
switchShader(outlineShader);
glUniformMatrix4fv(outlineShader->u_matrix, 1, GL_FALSE, matrix);
glLineWidth(2);
@@ -270,7 +276,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) {
// the current shape, some pixels from the outline stroke overlapped
// the (non-antialiased) fill.
glStencilFunc(GL_EQUAL, 0x80, 0xBF);
glUniform4fv(outlineShader->u_color, 1, properties.fill_color.data());
glUniform4fv(outlineShader->u_color, 1, fill_color.data());
}
// Draw the entire line
@@ -307,7 +313,7 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name) {
// Draw filling rectangle.
switchShader(fillShader);
glUniformMatrix4fv(fillShader->u_matrix, 1, GL_FALSE, matrix);
glUniform4fv(fillShader->u_color, 1, properties.fill_color.data());
glUniform4fv(fillShader->u_color, 1, fill_color.data());
}
// Only draw regions that we marked

View File

@@ -4,6 +4,64 @@
using namespace llmr;
const unsigned char resources::style[] = {
10, 25, 10, 5, 119, 97, 116, 101, 114, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 5, 119, 97, 116, 101, 114, 10, 60, 10, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 16, 2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, 115, 50, 10, 10, 8, 109, 111, 116, 111, 114, 119, 97, 121, 50, 6, 10, 4, 109, 97, 105, 110, 56, 1, 64, 2, 10, 52, 10, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 16, 2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, 115, 50, 8, 10, 6, 115, 116, 114, 101, 101, 116, 56, 1, 64, 2, 10, 60, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 16, 2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115, 115, 50, 16, 10, 14, 115, 116, 114, 101, 101, 116, 95, 108, 105, 109, 105, 116, 101, 100, 56, 1, 64, 2, 10, 41, 10, 4, 112, 97, 114, 107, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 6, 10, 4, 112, 97, 114, 107, 10, 41, 10, 4, 119, 111, 111, 100, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 6, 10, 4, 119, 111, 111, 100, 10, 45, 10, 6, 115, 99, 104, 111, 111, 108, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 8, 10, 6, 115, 99, 104, 111, 111, 108, 10, 49, 10, 8, 99, 101, 109, 101, 116, 101, 114, 121, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 10, 10, 8, 99, 101, 109, 101, 116, 101, 114, 121, 10, 53, 10, 10, 105, 110, 100, 117, 115, 116, 114, 105, 97, 108, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 12, 10, 10, 105, 110, 100, 117, 115, 116, 114, 105, 97, 108, 10, 31, 10, 8, 98, 117, 105, 108, 100, 105, 110, 103, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 8, 98, 117, 105, 108, 100, 105, 110, 103, 10, 48, 10, 7, 97, 108, 99, 111, 104, 111, 108, 16, 3, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 9, 112, 111, 105, 95, 108, 97, 98, 101, 108, 42, 4, 116, 121, 112, 101, 50, 9, 10, 7, 65, 108, 99, 111, 104, 111, 108, 18, 12, 10, 4, 112, 97, 114, 107, 18, 4, 112, 97, 114, 107, 18, 12, 10, 4, 119, 111, 111, 100, 18, 4, 119, 111, 111, 100, 18, 14, 10, 5, 119, 97, 116, 101, 114, 18, 5, 119, 97, 116, 101, 114, 18, 28, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 28, 10, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 18, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 18, 24, 10, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 18, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 18, 18, 10, 7, 97, 108, 99, 111, 104, 111, 108, 18, 7, 97, 108, 99, 111, 104, 111, 108, 26, 139, 2, 10, 7, 100, 101, 102, 97, 117, 108, 116, 18, 17, 10, 10, 98, 97, 99, 107, 103, 114, 111, 117, 110, 100, 21, 255, 255, 255, 255, 18, 13, 10, 4, 112, 97, 114, 107, 21, 255, 159, 223, 200, 24, 1, 18, 13, 10, 4, 119, 111, 111, 100, 21, 255, 102, 170, 51, 24, 1, 18, 14, 10, 5, 119, 97, 116, 101, 114, 21, 255, 230, 182, 115, 24, 1, 18, 46, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 21, 255, 187, 187, 187, 34, 25, 10, 5, 115, 116, 111, 112, 115, 18, 16, 0, 0, 0, 0, 0, 0, 128, 63, 0, 0, 160, 65, 0, 0, 128, 63, 18, 62, 10, 12, 114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 21, 255, 153, 153, 153, 34, 41, 10, 5, 115, 116, 111, 112, 115, 18, 32, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 80, 65, 0, 0, 0, 63, 0, 0, 128, 65, 0, 0, 0, 64, 0, 0, 160, 65, 0, 0, 0, 66, 18, 68, 10, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103, 101, 21, 255, 102, 102, 102, 34, 49, 10, 5, 115, 116, 111, 112, 115, 18, 40, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 48, 65, 0, 0, 0, 63, 0, 0, 80, 65, 0, 0, 128, 63, 0, 0, 128, 65, 0, 0, 128, 64, 0, 0, 160, 65, 0, 0, 128, 66, 18, 9, 10, 7, 97, 108, 99, 111, 104, 111, 108
10, 25, 10, 5, 119, 97, 116, 101, 114, 16, 1, 26, 7, 115, 116, 114,
101, 101, 116, 115, 34, 5, 119, 97, 116, 101, 114, 10, 60, 10, 10, 114,
111, 97, 100, 95, 108, 97, 114, 103, 101, 16, 2, 26, 7, 115, 116, 114,
101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115,
115, 50, 10, 10, 8, 109, 111, 116, 111, 114, 119, 97, 121, 50, 6, 10,
4, 109, 97, 105, 110, 56, 1, 64, 2, 10, 52, 10, 12, 114, 111, 97,
100, 95, 114, 101, 103, 117, 108, 97, 114, 16, 2, 26, 7, 115, 116, 114,
101, 101, 116, 115, 34, 4, 114, 111, 97, 100, 42, 5, 99, 108, 97, 115,
115, 50, 8, 10, 6, 115, 116, 114, 101, 101, 116, 56, 1, 64, 2, 10,
60, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 16,
2, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 4, 114, 111, 97, 100,
42, 5, 99, 108, 97, 115, 115, 50, 16, 10, 14, 115, 116, 114, 101, 101,
116, 95, 108, 105, 109, 105, 116, 101, 100, 56, 1, 64, 2, 10, 41, 10,
4, 112, 97, 114, 107, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115,
34, 7, 108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115,
50, 6, 10, 4, 112, 97, 114, 107, 10, 41, 10, 4, 119, 111, 111, 100,
16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110,
100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 6, 10, 4, 119,
111, 111, 100, 10, 45, 10, 6, 115, 99, 104, 111, 111, 108, 16, 1, 26,
7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117, 115,
101, 42, 5, 99, 108, 97, 115, 115, 50, 8, 10, 6, 115, 99, 104, 111,
111, 108, 10, 49, 10, 8, 99, 101, 109, 101, 116, 101, 114, 121, 16, 1,
26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7, 108, 97, 110, 100, 117,
115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 10, 10, 8, 99, 101, 109,
101, 116, 101, 114, 121, 10, 53, 10, 10, 105, 110, 100, 117, 115, 116, 114,
105, 97, 108, 16, 1, 26, 7, 115, 116, 114, 101, 101, 116, 115, 34, 7,
108, 97, 110, 100, 117, 115, 101, 42, 5, 99, 108, 97, 115, 115, 50, 12,
10, 10, 105, 110, 100, 117, 115, 116, 114, 105, 97, 108, 10, 31, 10, 8,
98, 117, 105, 108, 100, 105, 110, 103, 16, 1, 26, 7, 115, 116, 114, 101,
101, 116, 115, 34, 8, 98, 117, 105, 108, 100, 105, 110, 103, 10, 48, 10,
7, 97, 108, 99, 111, 104, 111, 108, 16, 3, 26, 7, 115, 116, 114, 101,
101, 116, 115, 34, 9, 112, 111, 105, 95, 108, 97, 98, 101, 108, 42, 4,
116, 121, 112, 101, 50, 9, 10, 7, 65, 108, 99, 111, 104, 111, 108, 18,
12, 10, 4, 112, 97, 114, 107, 18, 4, 112, 97, 114, 107, 18, 12, 10,
4, 119, 111, 111, 100, 18, 4, 119, 111, 111, 100, 18, 14, 10, 5, 119,
97, 116, 101, 114, 18, 5, 119, 97, 116, 101, 114, 18, 28, 10, 12, 114,
111, 97, 100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 12, 114, 111, 97,
100, 95, 108, 105, 109, 105, 116, 101, 100, 18, 28, 10, 12, 114, 111, 97,
100, 95, 114, 101, 103, 117, 108, 97, 114, 18, 12, 114, 111, 97, 100, 95,
114, 101, 103, 117, 108, 97, 114, 18, 24, 10, 10, 114, 111, 97, 100, 95,
108, 97, 114, 103, 101, 18, 10, 114, 111, 97, 100, 95, 108, 97, 114, 103,
101, 18, 18, 10, 7, 97, 108, 99, 111, 104, 111, 108, 18, 7, 97, 108,
99, 111, 104, 111, 108, 26, 128, 2, 10, 7, 100, 101, 102, 97, 117, 108,
116, 18, 21, 10, 4, 112, 97, 114, 107, 34, 8, 8, 2, 18, 4, 0,
0, 128, 63, 45, 255, 159, 223, 200, 18, 31, 10, 4, 119, 111, 111, 100,
34, 8, 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 102, 170, 51, 58,
8, 8, 2, 18, 4, 205, 204, 204, 61, 18, 22, 10, 5, 119, 97, 116,
101, 114, 34, 8, 8, 2, 18, 4, 0, 0, 128, 63, 45, 255, 230, 182,
115, 26, 41, 10, 12, 114, 111, 97, 100, 95, 108, 105, 109, 105, 116, 101,
100, 29, 255, 187, 187, 187, 34, 20, 8, 3, 18, 16, 0, 0, 0, 0,
0, 0, 128, 63, 0, 0, 160, 65, 0, 0, 128, 63, 26, 57, 10, 12,
114, 111, 97, 100, 95, 114, 101, 103, 117, 108, 97, 114, 29, 255, 153, 153,
153, 34, 36, 8, 3, 18, 32, 0, 0, 0, 0, 0, 0, 0, 63, 0,
0, 80, 65, 0, 0, 0, 63, 0, 0, 128, 65, 0, 0, 0, 64, 0,
0, 160, 65, 0, 0, 0, 66, 26, 63, 10, 10, 114, 111, 97, 100, 95,
108, 97, 114, 103, 101, 29, 255, 102, 102, 102, 34, 44, 8, 3, 18, 40,
0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 48, 65, 0, 0, 0, 63,
0, 0, 80, 65, 0, 0, 128, 63, 0, 0, 128, 65, 0, 0, 128, 64,
0, 0, 160, 65, 0, 0, 128, 66
};
const unsigned long resources::style_size = sizeof(resources::style);

25
src/style/properties.cpp Normal file
View File

@@ -0,0 +1,25 @@
#include <llmr/style/properties.hpp>
#include <cassert>
using namespace llmr;
float functions::null(float z, const std::vector<float>&) {
return 0;
}
bool functions::null(float z, const std::vector<bool>&) {
return false;
}
float functions::constant(float z, const std::vector<float>& values) {
assert(values.size() == 1);
return values.front();
}
bool functions::constant(float z, const std::vector<bool>& values) {
assert(values.size() == 1);
return values.front();
}

View File

@@ -18,20 +18,18 @@ void Style::load(const uint8_t *const data, uint32_t bytes) {
while (style.next()) {
if (style.tag == 1) { // bucket
buckets.insert(loadBucket(style.message()));
buckets.insert(parseBucket(style.message()));
} else if (style.tag == 2) { // structure
layers.push_back(loadLayer(style.message()));
layers.push_back(parseLayer(style.message()));
} else if (style.tag == 3) { // class
classes.insert(loadClass(style.message()));
classes.insert(parseClass(style.message()));
} else {
style.skip();
}
}
cascade();
}
std::pair<std::string, BucketDescription> Style::loadBucket(pbf data) {
std::pair<std::string, BucketDescription> Style::parseBucket(pbf data) {
BucketDescription bucket;
std::string name;
@@ -64,7 +62,7 @@ std::pair<std::string, BucketDescription> Style::loadBucket(pbf data) {
return { name, bucket };
}
LayerDescription Style::loadLayer(pbf data) {
LayerDescription Style::parseLayer(pbf data) {
LayerDescription layer;
while (data.next()) {
@@ -73,7 +71,7 @@ LayerDescription Style::loadLayer(pbf data) {
} else if (data.tag == 2) { // bucket_name
layer.bucket_name = data.string();
} else if (data.tag == 3) { // child_layer
layer.child_layer.emplace_back(loadLayer(data.message()));
layer.child_layer.emplace_back(parseLayer(data.message()));
} else {
data.skip();
}
@@ -83,15 +81,17 @@ LayerDescription Style::loadLayer(pbf data) {
}
std::pair<std::string, ClassDescription> Style::loadClass(pbf data) {
std::pair<std::string, ClassDescription> Style::parseClass(pbf data) {
ClassDescription klass;
std::string name;
while (data.next()) {
if (data.tag == 1) { // name
name = data.string();
} else if (data.tag == 2) { // layer_style
klass.insert(loadLayerStyle(data.message()));
} else if (data.tag == 2) { // fill_style
klass.fill.insert(parseFillClass(data.message()));
} else if (data.tag == 3) { // stroke_style
klass.stroke.insert(parseStrokeClass(data.message()));
} else {
data.skip();
}
@@ -100,55 +100,96 @@ std::pair<std::string, ClassDescription> Style::loadClass(pbf data) {
return { name, klass };
}
std::pair<std::string, LayerStyleDescription> Style::loadLayerStyle(pbf data) {
LayerStyleDescription layerStyle;
std::pair<std::string, FillClass> Style::parseFillClass(pbf data) {
FillClass fill;
std::string name;
while (data.next()) {
if (data.tag == 1) { // name
name = data.string();
} else if (data.tag == 2) { // color
uint32_t rgba = data.fixed<uint32_t, 4>();
layerStyle.color = {{
(float)((rgba >> 24) & 0xFF) / 0xFF,
(float)((rgba >> 16) & 0xFF) / 0xFF,
(float)((rgba >> 8) & 0xFF) / 0xFF,
(float)((rgba >> 0) & 0xFF) / 0xFF
}};
} else if (data.tag == 3) { // antialias
layerStyle.antialias = data.boolean();
} else if (data.tag == 4) { // width
layerStyle.width = loadWidth(data.message());
} else if (data.tag == 2) { // hidden
fill.hidden = parseProperty<bool>(data.message());
} else if (data.tag == 3) { // winding
fill.winding = (Winding)data.varint();
} else if (data.tag == 4) { // antialias
fill.antialias = parseProperty<bool>(data.message());
} else if (data.tag == 5) { // fill_color
fill.fill_color = parseColor(data);
if (fill.stroke_color[3] == std::numeric_limits<float>::infinity()) {
fill.stroke_color = fill.fill_color;
}
} else if (data.tag == 6) { // stroke_color
fill.stroke_color = parseColor(data);
} else if (data.tag == 7) { // opacity
fill.opacity = parseProperty<float>(data.message());
} else {
data.skip();
}
}
return { name, layerStyle };
return { name, fill };
}
WidthDescription Style::loadWidth(pbf data) {
WidthDescription width;
std::pair<std::string, StrokeClass> Style::parseStrokeClass(pbf data) {
StrokeClass stroke;
std::string name;
while (data.next()) {
if (data.tag == 1) { // scaling
width.scaling = data.string();
if (data.tag == 1) { // name
name = data.string();
} else if (data.tag == 2) { // hidden
stroke.hidden = parseProperty<bool>(data.message());
} else if (data.tag == 3) { // color
stroke.color = parseColor(data);
} else if (data.tag == 4) { // width
stroke.width = parseProperty<float>(data.message());
} else if (data.tag == 5) { // opacity
stroke.offset = parseProperty<float>(data.message());
} else {
data.skip();
}
}
return { name, stroke };
}
Color Style::parseColor(pbf& data) {
uint32_t rgba = data.fixed<uint32_t, 4>();
return {{
(float)((rgba >> 24) & 0xFF) / 0xFF,
(float)((rgba >> 16) & 0xFF) / 0xFF,
(float)((rgba >> 8) & 0xFF) / 0xFF,
(float)((rgba >> 0) & 0xFF) / 0xFF
}};
}
template <typename T> FunctionProperty<T> Style::parseProperty(pbf data) {
FunctionProperty<T> property;
while (data.next()) {
if (data.tag == 1) { // function
switch((Property)data.varint()) {
case Property::Null: property.function = &functions::null; break;
case Property::Constant: property.function = &functions::constant; break;
default: property.function = &functions::null; break;
}
} else if (data.tag == 2) { // value
// read a packed float32
pbf floats = data.message();
while (floats) {
width.value.push_back(floats.float32());
property.values.push_back(floats.float32());
}
} else {
data.skip();
}
}
return width;
return property;
}
void Style::cascade() {
void Style::cascade(float z) {
reset();
// Recalculate style
@@ -160,15 +201,30 @@ void Style::cascade() {
// Not enabled
if (appliedClasses.find(class_name) == appliedClasses.end()) continue;
for (const auto& layer_pair : sheetClass) {
const std::string& layer_name = layer_pair.first;
const LayerStyleDescription& layer = layer_pair.second;
// Cascade fill classes
for (const auto& fill_pair : sheetClass.fill) {
const std::string& layer_name = fill_pair.first;
const llmr::FillClass& layer = fill_pair.second;
// Find out what type this layer style is.
computed.fills[layer_name].enabled = true;
computed.fills[layer_name].antialiasing = layer.antialias;
computed.fills[layer_name].fill_color = layer.color;
computed.fills[layer_name].stroke_color = layer.color;
llmr::FillProperties& fill = computed.fills[layer_name];
fill.hidden = layer.hidden(z);
fill.winding = layer.winding;
fill.antialias = layer.antialias(z);
fill.fill_color = layer.fill_color;
fill.stroke_color = layer.stroke_color;
fill.opacity = layer.opacity(z);
}
// Cascade line classes
for (const auto& stroke_pair : sheetClass.stroke) {
const std::string& layer_name = stroke_pair.first;
const llmr::StrokeClass& layer = stroke_pair.second;
llmr::StrokeProperties& stroke = computed.strokes[layer_name];
stroke.hidden = layer.hidden(z);
stroke.width = layer.width(z);
stroke.offset = layer.offset(z);
stroke.color = layer.color;
}
}
}