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:
2305
bin/style.js
2305
bin/style.js
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@
|
||||
#include <llmr/shader/point_shader.hpp>
|
||||
#include <llmr/shader/raster_shader.hpp>
|
||||
#include <llmr/shader/text_shader.hpp>
|
||||
#include <llmr/shader/dot_shader.hpp>
|
||||
|
||||
#include <llmr/map/transform_state.hpp>
|
||||
|
||||
@@ -62,6 +63,7 @@ private:
|
||||
void setupShaders();
|
||||
void renderLayers(const std::shared_ptr<TileData>& tile, const std::vector<LayerDescription>& layers);
|
||||
void renderLayer(const std::shared_ptr<TileData>& tile_data, const LayerDescription& layer_desc);
|
||||
void translateLayer(std::array<float, 2> translation, bool reverse = false);
|
||||
void renderDebug(const std::shared_ptr<TileData>& tile);
|
||||
|
||||
void useProgram(uint32_t program);
|
||||
@@ -97,6 +99,7 @@ private:
|
||||
std::unique_ptr<PointShader> pointShader;
|
||||
std::unique_ptr<RasterShader> rasterShader;
|
||||
std::unique_ptr<TextShader> textShader;
|
||||
std::unique_ptr<DotShader> dotShader;
|
||||
|
||||
// Set up the stencil quad we're using to generate the stencil mask.
|
||||
VertexBuffer tileStencilBuffer = {
|
||||
|
||||
@@ -19,6 +19,7 @@ class Style;
|
||||
class PointVertexBuffer;
|
||||
class BucketDescription;
|
||||
class PointShader;
|
||||
class DotShader;
|
||||
struct pbf;
|
||||
|
||||
class PointBucket : public Bucket {
|
||||
@@ -33,6 +34,7 @@ public:
|
||||
bool hasPoints() const;
|
||||
|
||||
void drawPoints(PointShader& shader);
|
||||
void drawPoints(DotShader& shader);
|
||||
|
||||
public:
|
||||
const BucketGeometryDescription geometry;
|
||||
|
||||
33
include/llmr/shader/dot_shader.hpp
Normal file
33
include/llmr/shader/dot_shader.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef LLMR_SHADER_SHADER_DOT
|
||||
#define LLMR_SHADER_SHADER_DOT
|
||||
|
||||
#include <llmr/shader/shader.hpp>
|
||||
|
||||
namespace llmr {
|
||||
|
||||
class DotShader : public Shader {
|
||||
public:
|
||||
DotShader();
|
||||
|
||||
void bind(char *offset);
|
||||
|
||||
void setColor(const std::array<float, 4>& color);
|
||||
void setSize(float size);
|
||||
void setBlur(float blur);
|
||||
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
|
||||
std::array<float, 4> color = {{}};
|
||||
int32_t u_color = -1;
|
||||
|
||||
float size = 0;
|
||||
int32_t u_size = -1;
|
||||
|
||||
float blur = 0;
|
||||
int32_t u_blur = -1;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
private:
|
||||
int32_t a_pos = -1;
|
||||
int32_t a_extrude = -1;
|
||||
// int32_t a_linesofar = -1;
|
||||
int32_t a_linesofar = -1;
|
||||
|
||||
std::array<float, 16> exmatrix = {{}};
|
||||
int32_t u_exmatrix = -1;
|
||||
|
||||
@@ -56,38 +56,49 @@ struct FunctionProperty {
|
||||
|
||||
struct PointClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
FunctionProperty size;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
FunctionProperty opacity = 1;
|
||||
std::string image;
|
||||
FunctionProperty radius = 0;
|
||||
FunctionProperty blur = 0;
|
||||
};
|
||||
|
||||
struct PointProperties {
|
||||
bool enabled = true;
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
float size = 0;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
float opacity = 1.0;
|
||||
std::string image;
|
||||
float radius = 0;
|
||||
float blur = 0;
|
||||
};
|
||||
|
||||
struct LineClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
FunctionProperty width;
|
||||
FunctionProperty offset;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
std::array<FunctionProperty, 2> dash_array = {{ 1, -1 }};
|
||||
FunctionProperty opacity = 1;
|
||||
};
|
||||
|
||||
struct LineProperties {
|
||||
bool enabled = true;
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
float width = 0;
|
||||
float offset = 0;
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
std::array<float, 2> dash_array = {{ 1, -1 }};
|
||||
float opacity = 1.0;
|
||||
};
|
||||
|
||||
struct FillClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
Winding winding = Winding::NonZero;
|
||||
FunctionProperty antialias = true;
|
||||
Color fill_color = {{ 0, 0, 0, 1 }};
|
||||
@@ -98,6 +109,7 @@ struct FillClass {
|
||||
|
||||
struct FillProperties {
|
||||
bool enabled = true;
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
Winding winding = Winding::NonZero;
|
||||
bool antialias = true;
|
||||
Color fill_color = {{ 0, 0, 0, 1 }};
|
||||
@@ -108,6 +120,7 @@ struct FillProperties {
|
||||
|
||||
struct TextClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
Color halo = {{ 1, 1, 1, 0.75 }};
|
||||
FunctionProperty haloRadius = 0.25f;
|
||||
@@ -118,6 +131,7 @@ struct TextClass {
|
||||
|
||||
struct TextProperties {
|
||||
bool enabled = true;
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
Color color = {{ 0, 0, 0, 1 }};
|
||||
Color halo = {{ 1, 1, 1, 0.75 }};
|
||||
float haloRadius = 0.25f;
|
||||
@@ -138,11 +152,13 @@ struct BackgroundProperties {
|
||||
|
||||
struct RasterClass {
|
||||
FunctionProperty enabled = true;
|
||||
std::array<FunctionProperty, 2> translate = {{ 0, 0 }};
|
||||
FunctionProperty opacity = 1;
|
||||
};
|
||||
|
||||
struct RasterProperties {
|
||||
bool enabled = true;
|
||||
std::array<float, 2> translate = {{ 0, 0 }};
|
||||
float opacity = 1.0;
|
||||
};
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@ public:
|
||||
void parseBuckets(JSVal value, std::map<std::string, BucketDescription>& buckets);
|
||||
void parseLayers(JSVal value, std::vector<LayerDescription>& layers);
|
||||
void parseConstants(JSVal value);
|
||||
void parseClasses(JSVal value, std::map<std::string, ClassDescription>& classes);
|
||||
void parseClasses(JSVal value, std::map<std::string, ClassDescription>& classes, std::map<std::string, BucketDescription>& buckets, std::vector<LayerDescription>& layers);
|
||||
|
||||
private:
|
||||
LayerDescription parseLayer(JSVal value);
|
||||
BucketDescription parseBucket(JSVal value);
|
||||
std::pair<std::string, ClassDescription> parseClassDescription(JSVal value);
|
||||
void parseClass(const std::string& name, JSVal value, ClassDescription& class_desc);
|
||||
std::pair<std::string, ClassDescription> parseClassDescription(JSVal value, std::map<std::string, BucketDescription>& buckets, std::vector<LayerDescription>& layers);
|
||||
void parseClass(const std::string& name, JSVal value, ClassDescription& class_desc, std::map<std::string, BucketDescription>& buckets, std::vector<LayerDescription>& layers);
|
||||
FillClass parseFillClass(JSVal value);
|
||||
LineClass parseLineClass(JSVal value);
|
||||
PointClass parsePointClass(JSVal value);
|
||||
@@ -29,6 +29,8 @@ private:
|
||||
|
||||
bool parseBoolean(JSVal value);
|
||||
std::string parseString(JSVal value);
|
||||
const JSVal& replaceConstant(const JSVal& value);
|
||||
std::vector<FunctionProperty> parseArray(JSVal value, uint16_t expected_count);
|
||||
Color parseColor(JSVal value);
|
||||
Value parseValue(JSVal value);
|
||||
FunctionProperty::fn parseFunctionType(JSVal type);
|
||||
|
||||
@@ -61,7 +61,11 @@ void TileParser::parseStyleLayers(const std::vector<LayerDescription>& layers) {
|
||||
auto bucket_it = tile.buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it == tile.buckets.end()) {
|
||||
auto bucket_it = style.buckets.find(layer_desc.bucket_name);
|
||||
if (bucket_it != style.buckets.end()) {
|
||||
if (layer_desc.bucket_name == "background") {
|
||||
// background is a special, fake bucket
|
||||
continue;
|
||||
}
|
||||
else if (bucket_it != style.buckets.end()) {
|
||||
// Only create the new bucket if we have an actual specification
|
||||
// for it.
|
||||
std::unique_ptr<Bucket> bucket = createBucket(bucket_it->second);
|
||||
|
||||
@@ -28,24 +28,18 @@ VectorTileFeature::VectorTileFeature(pbf feature, const VectorTileLayer& layer)
|
||||
uint32_t tag_key = tags.varint();
|
||||
|
||||
if (layer.keys.size() <= tag_key) {
|
||||
// TODO: Throw correct exception
|
||||
fprintf(stderr, "feature referenced out of range key\n");
|
||||
break;
|
||||
throw std::runtime_error("feature referenced out of range key");
|
||||
}
|
||||
|
||||
if (tags) {
|
||||
uint32_t tag_val = tags.varint();
|
||||
if (layer.values.size() <= tag_val) {
|
||||
// TODO: Throw correct exception
|
||||
fprintf(stderr, "feature referenced out of range value\n");
|
||||
break;
|
||||
throw std::runtime_error("feature referenced out of range value");
|
||||
}
|
||||
|
||||
properties.emplace(layer.keys[tag_key], layer.values[tag_val]);
|
||||
} else {
|
||||
// TODO: Throw correct exception
|
||||
fprintf(stderr, "uneven number of feature tag ids\n");
|
||||
break;
|
||||
throw std::runtime_error("uneven number of feature tag ids");
|
||||
}
|
||||
}
|
||||
} else if (feature.tag == 3) { // type
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
#include <llmr/platform/platform.hpp>
|
||||
|
||||
const char *llmr::kSpriteURL = "http://mapbox-kkaefer.s3.amazonaws.com/static/sprite";
|
||||
const char *llmr::kSpriteURL = "http://mapbox-kkaefer.s3.amazonaws.com/static/osm-bright-gl/sprite";
|
||||
|
||||
@@ -48,6 +48,7 @@ void Painter::setup() {
|
||||
assert(patternShader);
|
||||
assert(rasterShader);
|
||||
assert(textShader);
|
||||
assert(dotShader);
|
||||
|
||||
|
||||
// Blending
|
||||
@@ -76,6 +77,7 @@ void Painter::setupShaders() {
|
||||
pointShader = std::make_unique<PointShader>();
|
||||
rasterShader = std::make_unique<RasterShader>();
|
||||
textShader = std::make_unique<TextShader>();
|
||||
dotShader = std::make_unique<DotShader>();
|
||||
}
|
||||
|
||||
void Painter::resize() {
|
||||
@@ -255,6 +257,20 @@ void Painter::renderLayer(const std::shared_ptr<TileData>& tile_data, const Laye
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::translateLayer(std::array<float, 2> translation, bool reverse) {
|
||||
if (translation[0] || translation[1]) {
|
||||
if (reverse) {
|
||||
translation[0] *= -1;
|
||||
translation[1] *= -1;
|
||||
}
|
||||
matrix::translate(matrix,
|
||||
matrix,
|
||||
translation[0] / map.getState().getPixelRatio(),
|
||||
translation[1] / map.getState().getPixelRatio(),
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
void Painter::renderRaster(const std::string& layer_name, const std::shared_ptr<TileData>& tile_data) {
|
||||
if (pass == Opaque) return;
|
||||
|
||||
@@ -308,6 +324,8 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
stroke_color = fill_color;
|
||||
}
|
||||
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (fill)");
|
||||
// Because we're drawing top-to-bottom, and we update the stencil mask
|
||||
// below, we have to draw the outline first (!)
|
||||
@@ -410,6 +428,8 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons
|
||||
glDepthRange(strata + strata_epsilon, 1.0f);
|
||||
bucket.drawVertices(*outlineShader);
|
||||
}
|
||||
|
||||
translateLayer(properties.translate, true);
|
||||
}
|
||||
|
||||
void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, const Tile::ID& /*id*/) {
|
||||
@@ -438,6 +458,10 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
color[2] *= properties.opacity;
|
||||
color[3] *= properties.opacity;
|
||||
|
||||
float dash_length = properties.dash_array[0];
|
||||
float dash_gap = properties.dash_array[1];
|
||||
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (line)");
|
||||
glDepthRange(strata, 1.0f);
|
||||
@@ -486,16 +510,14 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons
|
||||
useProgram(lineShader->program);
|
||||
lineShader->setMatrix(matrix);
|
||||
lineShader->setExtrudeMatrix(extrudeMatrix);
|
||||
|
||||
// TODO: Move this to transform?
|
||||
const float tilePixelRatio = map.getState().getScale() / (1 << map.getState().getIntegerZoom()) / 8;
|
||||
|
||||
lineShader->setDashArray({{ 1, -1 }});
|
||||
lineShader->setDashArray({{ dash_length, dash_gap }});
|
||||
lineShader->setLineWidth({{ outset, inset }});
|
||||
lineShader->setRatio(tilePixelRatio);
|
||||
lineShader->setRatio(map.getState().getPixelRatio());
|
||||
lineShader->setColor(color);
|
||||
bucket.drawLines(*lineShader);
|
||||
}
|
||||
|
||||
translateLayer(properties.translate, true);
|
||||
}
|
||||
|
||||
void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, const Tile::ID& /*id&*/) {
|
||||
@@ -510,8 +532,7 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
|
||||
const PointProperties& properties = point_properties_it->second;
|
||||
if (!properties.enabled) return;
|
||||
|
||||
auto &sprite = map.getStyle().sprite;
|
||||
if (!sprite || !sprite->isLoaded()) return;
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (point)");
|
||||
|
||||
@@ -521,32 +542,58 @@ void Painter::renderPoint(PointBucket& bucket, const std::string& layer_name, co
|
||||
color[2] *= properties.opacity;
|
||||
color[3] *= properties.opacity;
|
||||
|
||||
std::string sized_image = properties.image;
|
||||
sized_image.append("-");
|
||||
sized_image.append(std::to_string(static_cast<int>(std::round(properties.size))));
|
||||
auto &sprite = map.getStyle().sprite;
|
||||
ImagePosition imagePos;
|
||||
|
||||
ImagePosition imagePos = sprite->getPosition(sized_image, false);
|
||||
|
||||
// fprintf(stderr, "%f/%f => %f/%f\n", imagePos.tl.x, imagePos.tl.y, imagePos.br.x, imagePos.br.y);
|
||||
|
||||
useProgram(pointShader->program);
|
||||
pointShader->setMatrix(matrix);
|
||||
pointShader->setImage(0);
|
||||
pointShader->setColor(color);
|
||||
const float pointSize = properties.size * 1.4142135623730951 * map.getState().getPixelRatio();
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
pointShader->setSize(pointSize);
|
||||
#else
|
||||
glPointSize(pointSize);
|
||||
glEnable(GL_POINT_SPRITE);
|
||||
#endif
|
||||
pointShader->setPointTopLeft({{ imagePos.tl.x, imagePos.tl.y }});
|
||||
pointShader->setPointBottomRight({{ imagePos.br.x, imagePos.br.y }});
|
||||
if (sprite->raster->isLoaded()) {
|
||||
sprite->raster->bind(map.getState().isChanging());
|
||||
if (properties.image.length() && sprite && sprite->isLoaded()) {
|
||||
std::string sized_image = properties.image;
|
||||
if (properties.size) {
|
||||
sized_image.append("-");
|
||||
sized_image.append(std::to_string(static_cast<int>(std::round(properties.size))));
|
||||
}
|
||||
imagePos = sprite->getPosition(sized_image, false);
|
||||
}
|
||||
glDepthRange(strata, 1.0f);
|
||||
bucket.drawPoints(*pointShader);
|
||||
|
||||
if (!imagePos.size) {
|
||||
useProgram(dotShader->program);
|
||||
dotShader->setMatrix(matrix);
|
||||
dotShader->setColor(color);
|
||||
|
||||
const float pointSize = (properties.radius ? properties.radius * 2 : 8) * map.getState().getPixelRatio();
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
dotShader->setSize(pointSize);
|
||||
#else
|
||||
glPointSize(pointSize);
|
||||
glEnable(GL_POINT_SPRITE);
|
||||
#endif
|
||||
dotShader->setBlur((properties.blur ? properties.blur : 1.5) / pointSize);
|
||||
|
||||
glDepthRange(strata, 1.0f);
|
||||
bucket.drawPoints(*dotShader);
|
||||
} else {
|
||||
useProgram(pointShader->program);
|
||||
pointShader->setMatrix(matrix);
|
||||
pointShader->setColor(color);
|
||||
|
||||
pointShader->setImage(0);
|
||||
pointShader->setPointTopLeft({{ imagePos.tl.x, imagePos.tl.y }});
|
||||
pointShader->setPointBottomRight({{ imagePos.br.x, imagePos.br.y }});
|
||||
|
||||
sprite->raster->bind(map.getState().isChanging());
|
||||
|
||||
const float pointSize = (properties.size ? properties.size : (imagePos.size.x / map.getState().getPixelRatio())) * 1.4142135623730951 * map.getState().getPixelRatio();
|
||||
#if defined(GL_ES_VERSION_2_0)
|
||||
pointShader->setSize(pointSize);
|
||||
#else
|
||||
glPointSize(pointSize);
|
||||
glEnable(GL_POINT_SPRITE);
|
||||
#endif
|
||||
|
||||
glDepthRange(strata, 1.0f);
|
||||
bucket.drawPoints(*pointShader);
|
||||
}
|
||||
|
||||
translateLayer(properties.translate, true);
|
||||
}
|
||||
|
||||
void Painter::renderText(TextBucket& bucket, const std::string& layer_name, const Tile::ID& /*id*/) {
|
||||
@@ -561,6 +608,8 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
|
||||
const TextProperties& properties = text_properties_it->second;
|
||||
if (!properties.enabled) return;
|
||||
|
||||
translateLayer(properties.translate);
|
||||
|
||||
gl::group group(layer_name + " (text)");
|
||||
|
||||
mat4 exMatrix;
|
||||
@@ -654,6 +703,8 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons
|
||||
textShader->setBuffer((256.0f - 64.0f) / 256.0f);
|
||||
glDepthRange(strata + strata_epsilon, 1.0f);
|
||||
bucket.drawGlyphs(*textShader);
|
||||
|
||||
translateLayer(properties.translate, true);
|
||||
}
|
||||
|
||||
void Painter::renderDebug(const TileData::Ptr& tile_data) {
|
||||
|
||||
@@ -50,3 +50,9 @@ void PointBucket::drawPoints(PointShader& shader) {
|
||||
array.bind(shader, vertexBuffer, vertex_index);
|
||||
glDrawArrays(GL_POINTS, 0, (GLsizei)(vertex_end - vertex_start));
|
||||
}
|
||||
|
||||
void PointBucket::drawPoints(DotShader& shader) {
|
||||
char *vertex_index = BUFFER_OFFSET(vertex_start * vertexBuffer.itemSize);
|
||||
array.bind(shader, vertexBuffer, vertex_index);
|
||||
glDrawArrays(GL_POINTS, 0, (GLsizei)(vertex_end - vertex_start));
|
||||
}
|
||||
|
||||
9
src/shader/dot.fragment.glsl
Normal file
9
src/shader/dot.fragment.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
uniform vec4 u_color;
|
||||
uniform float u_blur;
|
||||
|
||||
void main() {
|
||||
float dist = length(gl_PointCoord - 0.5);
|
||||
float t = smoothstep(0.5, 0.5 - u_blur, dist);
|
||||
|
||||
gl_FragColor = u_color * t;
|
||||
}
|
||||
9
src/shader/dot.vertex.glsl
Normal file
9
src/shader/dot.vertex.glsl
Normal file
@@ -0,0 +1,9 @@
|
||||
attribute vec2 a_pos;
|
||||
|
||||
uniform mat4 u_matrix;
|
||||
uniform float u_size;
|
||||
|
||||
void main(void) {
|
||||
gl_Position = u_matrix * vec4(a_pos, 0, 1);
|
||||
gl_PointSize = u_size;
|
||||
}
|
||||
57
src/shader/dot_shader.cpp
Normal file
57
src/shader/dot_shader.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include <llmr/shader/dot_shader.hpp>
|
||||
#include <llmr/shader/shaders.hpp>
|
||||
#include <llmr/platform/gl.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
using namespace llmr;
|
||||
|
||||
DotShader::DotShader()
|
||||
: Shader(
|
||||
shaders[DOT_SHADER].vertex,
|
||||
shaders[DOT_SHADER].fragment
|
||||
) {
|
||||
if (!valid) {
|
||||
fprintf(stderr, "invalid dot shader\n");
|
||||
return;
|
||||
}
|
||||
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_color = glGetUniformLocation(program, "u_color");
|
||||
u_size = glGetUniformLocation(program, "u_size");
|
||||
u_blur = glGetUniformLocation(program, "u_blur");
|
||||
|
||||
// fprintf(stderr, "PointShader:\n");
|
||||
// fprintf(stderr, " - u_matrix: %d\n", u_matrix);
|
||||
// fprintf(stderr, " - u_color: %d\n", u_color);
|
||||
// fprintf(stderr, " - u_size: %d\n", u_size);
|
||||
// fprintf(stderr, " - u_blur: %d\n", u_blur);
|
||||
}
|
||||
|
||||
void DotShader::bind(char *offset) {
|
||||
glEnableVertexAttribArray(a_pos);
|
||||
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset);
|
||||
}
|
||||
|
||||
void DotShader::setColor(const std::array<float, 4>& new_color) {
|
||||
if (color != new_color) {
|
||||
glUniform4fv(u_color, 1, new_color.data());
|
||||
color = new_color;
|
||||
}
|
||||
}
|
||||
|
||||
void DotShader::setSize(float new_size) {
|
||||
if (size != new_size) {
|
||||
glUniform1f(u_size, new_size);
|
||||
size = new_size;
|
||||
}
|
||||
}
|
||||
|
||||
void DotShader::setBlur(float new_blur) {
|
||||
if (blur != new_blur) {
|
||||
glUniform1f(u_blur, new_blur);
|
||||
blur = new_blur;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ uniform vec4 u_color;
|
||||
uniform vec2 u_dasharray;
|
||||
|
||||
varying vec2 v_normal;
|
||||
// varying float v_linesofar;
|
||||
varying float v_linesofar;
|
||||
|
||||
void main() {
|
||||
// Calculate the distance of the pixel from the line in pixels.
|
||||
@@ -17,8 +17,8 @@ void main() {
|
||||
|
||||
// Calculate the antialiasing fade factor based on distance to the dash.
|
||||
// Only affects alpha when line is dashed
|
||||
// float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y);
|
||||
// alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0));
|
||||
float pos = mod(v_linesofar, u_dasharray.x + u_dasharray.y);
|
||||
alpha *= max(step(0.0, -u_dasharray.y), clamp(min(pos, u_dasharray.x - pos), 0.0, 1.0));
|
||||
|
||||
gl_FragColor = u_color * alpha;
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
attribute vec2 a_pos;
|
||||
attribute vec2 a_extrude;
|
||||
// attribute float a_linesofar;
|
||||
attribute float a_linesofar;
|
||||
|
||||
// posmatrix is for the vertex position, exmatrix is for rotating and projecting
|
||||
// the extrusion vector.
|
||||
@@ -21,7 +21,7 @@ uniform vec2 u_linewidth;
|
||||
uniform vec4 u_color;
|
||||
|
||||
varying vec2 v_normal;
|
||||
// varying float v_linesofar;
|
||||
varying float v_linesofar;
|
||||
|
||||
void main() {
|
||||
// We store the texture normals in the most insignificant bit
|
||||
@@ -41,5 +41,5 @@ void main() {
|
||||
// because we're extruding the line in pixel space, regardless of the current
|
||||
// tile's zoom level.
|
||||
gl_Position = u_matrix * vec4(floor(a_pos * 0.5), 0.0, 1.0) + u_exmatrix * dist;
|
||||
// v_linesofar = a_linesofar * u_ratio;
|
||||
v_linesofar = a_linesofar * u_ratio;
|
||||
}
|
||||
@@ -18,7 +18,7 @@ LineShader::LineShader()
|
||||
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
a_extrude = glGetAttribLocation(program, "a_extrude");
|
||||
// a_linesofar = glGetAttribLocation(program, "a_linesofar");
|
||||
a_linesofar = glGetAttribLocation(program, "a_linesofar");
|
||||
|
||||
u_matrix = glGetUniformLocation(program, "u_matrix");
|
||||
u_exmatrix = glGetUniformLocation(program, "u_exmatrix");
|
||||
@@ -38,13 +38,13 @@ LineShader::LineShader()
|
||||
|
||||
void LineShader::bind(char *offset) {
|
||||
glEnableVertexAttribArray(a_pos);
|
||||
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset);
|
||||
|
||||
// glEnableVertexAttribArray(a_linesofar);
|
||||
// glVertexAttribPointer(a_linesofar, 1, GL_SHORT, false, 8, offset + 6);
|
||||
glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 8, offset + 0);
|
||||
|
||||
glEnableVertexAttribArray(a_extrude);
|
||||
glVertexAttribPointer(a_extrude, 2, GL_BYTE, false, 8, offset + 4);
|
||||
|
||||
glEnableVertexAttribArray(a_linesofar);
|
||||
glVertexAttribPointer(a_linesofar, 1, GL_SHORT, false, 8, offset + 6);
|
||||
}
|
||||
|
||||
void LineShader::setExtrudeMatrix(const std::array<float, 16>& new_exmatrix) {
|
||||
|
||||
@@ -7,8 +7,12 @@ using namespace llmr;
|
||||
|
||||
const shader_source llmr::shaders[SHADER_COUNT] = {
|
||||
{
|
||||
"#version 120\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\nuniform vec2 u_linewidth;\nvarying vec2 v_normal;\nvoid main ()\n{\n vec2 normal_1;\n vec2 tmpvar_2;\n tmpvar_2 = (vec2(mod (a_pos, 2.0)));\n normal_1.x = tmpvar_2.x;\n normal_1.y = sign((tmpvar_2.y - 0.5));\n v_normal = normal_1;\n vec4 tmpvar_3;\n tmpvar_3.zw = vec2(0.0, 0.0);\n tmpvar_3.xy = ((u_linewidth.x * a_extrude) * 0.015873);\n vec4 tmpvar_4;\n tmpvar_4.zw = vec2(0.0, 1.0);\n tmpvar_4.xy = floor((a_pos * 0.5));\n gl_Position = ((u_matrix * tmpvar_4) + (u_exmatrix * tmpvar_3));\n}\n\n",
|
||||
"#version 120\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nvarying vec2 v_normal;\nvoid main ()\n{\n float tmpvar_1;\n tmpvar_1 = (sqrt(dot (v_normal, v_normal)) * u_linewidth.x);\n gl_FragColor = (u_color * clamp (min (\n (tmpvar_1 - (u_linewidth.y - 1.0))\n , \n (u_linewidth.x - tmpvar_1)\n ), 0.0, 1.0));\n}\n\n",
|
||||
"#version 120\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform float u_size;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_matrix * tmpvar_1);\n gl_PointSize = u_size;\n}\n\n",
|
||||
"#version 120\nuniform vec4 u_color;\nuniform float u_blur;\nvoid main ()\n{\n vec2 x_1;\n x_1 = (gl_PointCoord - 0.5);\n float tmpvar_2;\n tmpvar_2 = clamp (((\n sqrt(dot (x_1, x_1))\n - 0.5) / (\n (0.5 - u_blur)\n - 0.5)), 0.0, 1.0);\n gl_FragColor = (u_color * (tmpvar_2 * (tmpvar_2 * \n (3.0 - (2.0 * tmpvar_2))\n )));\n}\n\n",
|
||||
},
|
||||
{
|
||||
"#version 120\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nattribute float a_linesofar;\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\nuniform float u_ratio;\nuniform vec2 u_linewidth;\nvarying vec2 v_normal;\nvarying float v_linesofar;\nvoid main ()\n{\n vec2 normal_1;\n vec2 tmpvar_2;\n tmpvar_2 = (vec2(mod (a_pos, 2.0)));\n normal_1.x = tmpvar_2.x;\n normal_1.y = sign((tmpvar_2.y - 0.5));\n v_normal = normal_1;\n vec4 tmpvar_3;\n tmpvar_3.zw = vec2(0.0, 0.0);\n tmpvar_3.xy = ((u_linewidth.x * a_extrude) * 0.015873);\n vec4 tmpvar_4;\n tmpvar_4.zw = vec2(0.0, 1.0);\n tmpvar_4.xy = floor((a_pos * 0.5));\n gl_Position = ((u_matrix * tmpvar_4) + (u_exmatrix * tmpvar_3));\n v_linesofar = (a_linesofar * u_ratio);\n}\n\n",
|
||||
"#version 120\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nuniform vec2 u_dasharray;\nvarying vec2 v_normal;\nvarying float v_linesofar;\nvoid main ()\n{\n float tmpvar_1;\n tmpvar_1 = (sqrt(dot (v_normal, v_normal)) * u_linewidth.x);\n float tmpvar_2;\n tmpvar_2 = (float(mod (v_linesofar, (u_dasharray.x + u_dasharray.y))));\n gl_FragColor = (u_color * (clamp (\n min ((tmpvar_1 - (u_linewidth.y - 1.0)), (u_linewidth.x - tmpvar_1))\n , 0.0, 1.0) * max (\n float((-(u_dasharray.y) >= 0.0))\n , \n clamp (min (tmpvar_2, (u_dasharray.x - tmpvar_2)), 0.0, 1.0)\n )));\n}\n\n",
|
||||
},
|
||||
{
|
||||
"#version 120\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\nuniform float u_size;\nvarying vec2 v_pos;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = floor((a_pos / 2.0));\n vec4 tmpvar_2;\n tmpvar_2 = (u_matrix * tmpvar_1);\n gl_Position = tmpvar_2;\n v_pos = ((tmpvar_2.xy + 1.0) * u_world);\n gl_PointSize = u_size;\n}\n\n",
|
||||
|
||||
@@ -7,8 +7,12 @@ using namespace llmr;
|
||||
|
||||
const shader_source llmr::shaders[SHADER_COUNT] = {
|
||||
{
|
||||
"precision highp float;\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\nuniform vec2 u_linewidth;\nvarying vec2 v_normal;\nvoid main ()\n{\n vec2 normal_1;\n vec2 tmpvar_2;\n tmpvar_2 = (vec2(mod (a_pos, 2.0)));\n normal_1.x = tmpvar_2.x;\n normal_1.y = sign((tmpvar_2.y - 0.5));\n v_normal = normal_1;\n vec4 tmpvar_3;\n tmpvar_3.zw = vec2(0.0, 0.0);\n tmpvar_3.xy = ((u_linewidth.x * a_extrude) * 0.015873);\n vec4 tmpvar_4;\n tmpvar_4.zw = vec2(0.0, 1.0);\n tmpvar_4.xy = floor((a_pos * 0.5));\n gl_Position = ((u_matrix * tmpvar_4) + (u_exmatrix * tmpvar_3));\n}\n\n",
|
||||
"precision highp float;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nvarying vec2 v_normal;\nvoid main ()\n{\n float tmpvar_1;\n tmpvar_1 = (sqrt(dot (v_normal, v_normal)) * u_linewidth.x);\n gl_FragColor = (u_color * clamp (min (\n (tmpvar_1 - (u_linewidth.y - 1.0))\n , \n (u_linewidth.x - tmpvar_1)\n ), 0.0, 1.0));\n}\n\n",
|
||||
"precision highp float;\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform float u_size;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = a_pos;\n gl_Position = (u_matrix * tmpvar_1);\n gl_PointSize = u_size;\n}\n\n",
|
||||
"precision highp float;\nuniform vec4 u_color;\nuniform float u_blur;\nvoid main ()\n{\n mediump vec2 x_1;\n x_1 = (gl_PointCoord - 0.5);\n mediump float tmpvar_2;\n tmpvar_2 = clamp (((\n sqrt(dot (x_1, x_1))\n - 0.5) / (\n (0.5 - u_blur)\n - 0.5)), 0.0, 1.0);\n gl_FragColor = (u_color * (tmpvar_2 * (tmpvar_2 * \n (3.0 - (2.0 * tmpvar_2))\n )));\n}\n\n",
|
||||
},
|
||||
{
|
||||
"precision highp float;\nattribute vec2 a_pos;\nattribute vec2 a_extrude;\nattribute float a_linesofar;\nuniform mat4 u_matrix;\nuniform mat4 u_exmatrix;\nuniform float u_ratio;\nuniform vec2 u_linewidth;\nvarying vec2 v_normal;\nvarying float v_linesofar;\nvoid main ()\n{\n vec2 normal_1;\n vec2 tmpvar_2;\n tmpvar_2 = (vec2(mod (a_pos, 2.0)));\n normal_1.x = tmpvar_2.x;\n normal_1.y = sign((tmpvar_2.y - 0.5));\n v_normal = normal_1;\n vec4 tmpvar_3;\n tmpvar_3.zw = vec2(0.0, 0.0);\n tmpvar_3.xy = ((u_linewidth.x * a_extrude) * 0.015873);\n vec4 tmpvar_4;\n tmpvar_4.zw = vec2(0.0, 1.0);\n tmpvar_4.xy = floor((a_pos * 0.5));\n gl_Position = ((u_matrix * tmpvar_4) + (u_exmatrix * tmpvar_3));\n v_linesofar = (a_linesofar * u_ratio);\n}\n\n",
|
||||
"precision highp float;\nuniform vec2 u_linewidth;\nuniform vec4 u_color;\nuniform vec2 u_dasharray;\nvarying vec2 v_normal;\nvarying float v_linesofar;\nvoid main ()\n{\n float tmpvar_1;\n tmpvar_1 = (sqrt(dot (v_normal, v_normal)) * u_linewidth.x);\n float tmpvar_2;\n tmpvar_2 = (float(mod (v_linesofar, (u_dasharray.x + u_dasharray.y))));\n gl_FragColor = (u_color * (clamp (\n min ((tmpvar_1 - (u_linewidth.y - 1.0)), (u_linewidth.x - tmpvar_1))\n , 0.0, 1.0) * max (\n float((-(u_dasharray.y) >= 0.0))\n , \n clamp (min (tmpvar_2, (u_dasharray.x - tmpvar_2)), 0.0, 1.0)\n )));\n}\n\n",
|
||||
},
|
||||
{
|
||||
"precision highp float;\nattribute vec2 a_pos;\nuniform mat4 u_matrix;\nuniform vec2 u_world;\nuniform float u_size;\nvarying highp vec2 v_pos;\nvoid main ()\n{\n vec4 tmpvar_1;\n tmpvar_1.zw = vec2(0.0, 1.0);\n tmpvar_1.xy = floor((a_pos / 2.0));\n vec4 tmpvar_2;\n tmpvar_2 = (u_matrix * tmpvar_1);\n gl_Position = tmpvar_2;\n v_pos = ((tmpvar_2.xy + 1.0) * u_world);\n gl_PointSize = u_size;\n}\n\n",
|
||||
|
||||
@@ -96,7 +96,7 @@ void Sprite::parseJSON(std::shared_ptr<Sprite> &sprite) {
|
||||
if (value.HasMember("y")) y = value["y"].GetInt();
|
||||
if (value.HasMember("width")) width = value["width"].GetInt();
|
||||
if (value.HasMember("height")) height = value["height"].GetInt();
|
||||
if (value.HasMember("pixelRatio")) pixelRatio = value["height"].GetInt();
|
||||
if (value.HasMember("pixelRatio")) pixelRatio = value["pixelRatio"].GetInt();
|
||||
|
||||
sprite->pos.insert({ name, { x, y, width, height, pixelRatio } });
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ void Style::cascade(float z) {
|
||||
// values so as to not override with default values.
|
||||
llmr::FillProperties& fill = computed.fills[layer_name];
|
||||
fill.enabled = layer.enabled.evaluate<bool>(z);
|
||||
fill.translate = {{ layer.translate[0].evaluate<float>(z),
|
||||
layer.translate[1].evaluate<float>(z) }};
|
||||
fill.winding = layer.winding;
|
||||
fill.antialias = layer.antialias.evaluate<bool>(z);
|
||||
fill.fill_color = layer.fill_color;
|
||||
@@ -55,9 +57,13 @@ void Style::cascade(float z) {
|
||||
// values so as to not override with default values.
|
||||
llmr::LineProperties& stroke = computed.lines[layer_name];
|
||||
stroke.enabled = layer.enabled.evaluate<bool>(z);
|
||||
stroke.translate = {{ layer.translate[0].evaluate<float>(z),
|
||||
layer.translate[1].evaluate<float>(z) }};
|
||||
stroke.width = layer.width.evaluate<float>(z);
|
||||
stroke.offset = layer.offset.evaluate<float>(z);
|
||||
stroke.color = layer.color;
|
||||
stroke.dash_array = {{ layer.dash_array[0].evaluate<float>(z),
|
||||
layer.dash_array[1].evaluate<float>(z) }};
|
||||
stroke.opacity = layer.opacity.evaluate<float>(z);
|
||||
}
|
||||
|
||||
@@ -70,10 +76,14 @@ void Style::cascade(float z) {
|
||||
// values so as to not override with default values.
|
||||
llmr::PointProperties& point = computed.points[layer_name];
|
||||
point.enabled = layer.enabled.evaluate<bool>(z);
|
||||
point.translate = {{ layer.translate[0].evaluate<float>(z),
|
||||
layer.translate[1].evaluate<float>(z) }};
|
||||
point.color = layer.color;
|
||||
point.size = layer.size.evaluate<float>(z);
|
||||
point.opacity = layer.opacity.evaluate<float>(z);
|
||||
point.image = layer.image;
|
||||
point.radius = layer.radius.evaluate<float>(z);
|
||||
point.blur = layer.blur.evaluate<float>(z);
|
||||
}
|
||||
|
||||
// Cascade text classes
|
||||
@@ -85,6 +95,8 @@ void Style::cascade(float z) {
|
||||
// values so as to not override with default values.
|
||||
llmr::TextProperties& text = computed.texts[layer_name];
|
||||
text.enabled = layer.enabled.evaluate<bool>(z);
|
||||
text.translate = {{ layer.translate[0].evaluate<float>(z),
|
||||
layer.translate[1].evaluate<float>(z) }};
|
||||
text.color = layer.color;
|
||||
text.size = layer.size.evaluate<float>(z);
|
||||
text.halo = layer.halo;
|
||||
@@ -146,7 +158,7 @@ void Style::loadJSON(const uint8_t *const data, size_t bytes) {
|
||||
}
|
||||
|
||||
if (document.HasMember("classes")) {
|
||||
parser.parseClasses(document["classes"], classes);
|
||||
parser.parseClasses(document["classes"], classes, buckets, layers);
|
||||
}
|
||||
} else {
|
||||
throw Style::exception("stylesheet root must be an object");
|
||||
|
||||
@@ -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"]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user