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

File diff suppressed because it is too large Load Diff

View File

@@ -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 = {

View File

@@ -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;

View 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

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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";

View File

@@ -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) {

View File

@@ -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));
}

View 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;
}

View 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
View 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;
}
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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) {

View File

@@ -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",

View File

@@ -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",

View File

@@ -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 } });
}

View File

@@ -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");

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"]);
}