From da33bef634b9555fb93c5e02faffd29c516f7ec7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 29 May 2014 13:09:10 -0700 Subject: [PATCH 01/15] initialize variables --- src/style/properties.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/style/properties.cpp b/src/style/properties.cpp index 0e4841830..b39f20c51 100644 --- a/src/style/properties.cpp +++ b/src/style/properties.cpp @@ -29,9 +29,11 @@ float functions::stops(float z, const std::vector& stops) { if (stops.size() % 2 != 0) return 0; bool smaller = false; - float smaller_z, smaller_val; + float smaller_z = 0.0; + float smaller_val = 0.0; bool larger = false; - float larger_z, larger_val; + float larger_z = 0.0; + float larger_val = 0.0; for (uint32_t i = 0; i < stops.size(); i += 2) { float stop_z = stops[i]; From 23655f0bb1484408072a6ce60c8a787b4b51d460 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 29 May 2014 13:09:24 -0700 Subject: [PATCH 02/15] use std::pow --- src/map/transform.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/map/transform.cpp b/src/map/transform.cpp index 996117bfa..d567a586c 100644 --- a/src/map/transform.cpp +++ b/src/map/transform.cpp @@ -60,8 +60,8 @@ void Transform::_moveBy(const double dx, const double dy, const time duration) { // Un-rotate when rotated and panning far enough to show off-world in corners. double w = final.scale * util::tileSize / 2; - double m = std::sqrt(pow((current.width / 2), 2) + pow((current.height / 2), 2)); - double x = std::abs(sqrt(pow(final.x, 2) + pow(final.y, 2))); + double m = std::sqrt(std::pow((current.width / 2), 2) + pow((current.height / 2), 2)); + double x = std::abs(sqrt(std::pow(final.x, 2) + std::pow(final.y, 2))); if (current.angle && w - x < m) _setAngle(0, 500_milliseconds, true); if (duration == 0) { From 5c7461f19e293491a1a0ae7c3d528364207c8007 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 29 May 2014 13:10:51 -0700 Subject: [PATCH 03/15] use std::abs --- src/clipper/clipper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clipper/clipper.cpp b/src/clipper/clipper.cpp index 95975450e..56ad58416 100755 --- a/src/clipper/clipper.cpp +++ b/src/clipper/clipper.cpp @@ -2152,13 +2152,13 @@ void Clipper::IntersectEdges(TEdge *e1, TEdge *e2, else if (e1->PolyTyp != e2->PolyTyp) { //toggle subj open path OutIdx on/off when Abs(clip.WndCnt) == 1 ... - if ((e1->WindDelta == 0) && abs(e2->WindCnt) == 1 && + if ((e1->WindDelta == 0) && std::abs(e2->WindCnt) == 1 && (m_ClipType != ctUnion || e2->WindCnt2 == 0)) { AddOutPt(e1, Pt); if (e1Contributing) e1->OutIdx = Unassigned; } - else if ((e2->WindDelta == 0) && (abs(e1->WindCnt) == 1) && + else if ((e2->WindDelta == 0) && (std::abs(e1->WindCnt) == 1) && (m_ClipType != ctUnion || e1->WindCnt2 == 0)) { AddOutPt(e2, Pt); From 30a34d73f87f28a63b4451e823b6d10ee3fc5d9e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 29 May 2014 13:23:00 -0700 Subject: [PATCH 04/15] fix static analyzer warning: Result of 'calloc' is converted to a pointer of type 'char', which is incompatible with sizeof operand type 'uint32_t' --- include/llmr/geometry/sprite_atlas.hpp | 2 +- src/geometry/sprite_atlas.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/llmr/geometry/sprite_atlas.hpp b/include/llmr/geometry/sprite_atlas.hpp index 220edc701..13b85e548 100644 --- a/include/llmr/geometry/sprite_atlas.hpp +++ b/include/llmr/geometry/sprite_atlas.hpp @@ -62,7 +62,7 @@ private: BinPack bin; std::map> images; std::set uninitialized; - char *data = nullptr; + uint32_t *data = nullptr; std::atomic dirty; uint32_t texture = 0; uint32_t filter = 0; diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index 35f6f4588..4404695f9 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -30,7 +30,7 @@ bool SpriteAtlas::resize(const float newRatio) { pixelRatio = newRatio; if (data) { - char *old_data = data; + uint32_t *old_data = data; data = nullptr; allocate(); @@ -185,7 +185,7 @@ void SpriteAtlas::allocate() { if (!data) { dimension w = static_cast(width * pixelRatio); dimension h = static_cast(height * pixelRatio); - data = (char *)calloc(w * h, sizeof(uint32_t)); + data = (uint32_t *)calloc(w * h, sizeof(uint32_t)); } } From f5394a76383507565fb4f798d3fe4afdd0fa5c15 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 29 May 2014 18:07:19 -0700 Subject: [PATCH 05/15] release mode: silent debug output + ifdef any potentially expensive calls --- src/geometry/glyph_atlas.cpp | 2 ++ src/geometry/sprite_atlas.cpp | 3 ++- src/map/map.cpp | 10 ++++++++-- src/map/tile_data.cpp | 2 ++ src/map/vector_tile_data.cpp | 2 ++ src/renderer/fill_bucket.cpp | 6 ++++++ src/renderer/painter.cpp | 9 +++++---- src/renderer/painter_text.cpp | 8 +++++--- src/shader/gaussian_shader.cpp | 2 ++ src/shader/raster_shader.cpp | 2 ++ src/shader/shader.cpp | 12 ++++++++++-- src/style/sprite.cpp | 2 ++ src/text/glyph_store.cpp | 2 ++ src/util/constants.cpp | 13 +++++++++++++ 14 files changed, 63 insertions(+), 12 deletions(-) diff --git a/src/geometry/glyph_atlas.cpp b/src/geometry/glyph_atlas.cpp index f4defac69..afb904407 100644 --- a/src/geometry/glyph_atlas.cpp +++ b/src/geometry/glyph_atlas.cpp @@ -137,6 +137,8 @@ void GlyphAtlas::bind() { glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, data); dirty = false; +#if defined(DEBUG) // platform::show_debug_image("Glyph Atlas", data, width, height); +#endif } }; diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index 35f6f4588..882c6c17d 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -270,8 +270,9 @@ void SpriteAtlas::bind(bool linear) { data // const GLvoid * data ); +#if defined(DEBUG) // platform::show_color_debug_image("Sprite Atlas", data, width, height, width * pixelRatio, height * pixelRatio); - +#endif dirty = false; } }; diff --git a/src/map/map.cpp b/src/map/map.cpp index 7ac6dbe0e..60a7aa78d 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -479,8 +479,9 @@ void Map::prepare() { } void Map::render() { +#if defined(DEBUG) std::vector debug; - +#endif painter.clear(); painter.resetFramebuffer(); @@ -493,6 +494,7 @@ void Map::render() { painter.drawClippingMasks(sources); +#if defined(DEBUG) // Generate debug information size_t source_id = 0; for (const auto &pair : sources) { @@ -501,7 +503,7 @@ void Map::render() { debug.emplace_back(util::sprintf<100>("source %d: %d\n", source_id, count)); source_id++; } - +#endif // Actually render the layers if (debug::renderTree) { std::cout << "{" << std::endl; indent++; } renderLayers(style.layers); @@ -520,7 +522,9 @@ void Map::render() { painter.renderMatte(); +#if defined(DEBUG) painter.renderDebugText(debug); +#endif // Schedule another rerender when we definitely need a next frame. if (transform.needsTransition()) { @@ -573,12 +577,14 @@ void Map::renderLayers(const std::vector& layers) { template typename Styles::const_iterator find_style(const Styles &styles, const LayerDescription &layer_desc) { auto it = styles.find(layer_desc.name); +#if defined(DEBUG) if (it == styles.end()) { if (debug::renderWarnings) { fprintf(stderr, "[WARNING] can't find class named '%s' in style\n", layer_desc.name.c_str()); } } +#endif return it; } diff --git a/src/map/tile_data.cpp b/src/map/tile_data.cpp index 9ad752526..2c8a47deb 100644 --- a/src/map/tile_data.cpp +++ b/src/map/tile_data.cpp @@ -42,7 +42,9 @@ void TileData::request() { // Schedule tile parsing in another thread tile->reparse(); } else { +#if defined(DEBUG) fprintf(stderr, "[%s] tile loading failed: %d, %s\n", tile->url.c_str(), res->code, res->error_message.c_str()); +#endif } }, map.getLoop()); } diff --git a/src/map/vector_tile_data.cpp b/src/map/vector_tile_data.cpp index 3c972aa31..4a1e91f41 100644 --- a/src/map/vector_tile_data.cpp +++ b/src/map/vector_tile_data.cpp @@ -24,7 +24,9 @@ void VectorTileData::parse() { // is going to be discarded afterwards. TileParser parser(data, *this, map.getStyle(), map.getGlyphAtlas(), map.getGlyphStore(), map.getSpriteAtlas()); } catch (const std::exception& ex) { +#if defined(DEBUG) fprintf(stderr, "[%p] exception [%d/%d/%d]... failed: %s\n", this, id.z, id.x, id.y, ex.what()); +#endif cancel(); return; } diff --git a/src/renderer/fill_bucket.cpp b/src/renderer/fill_bucket.cpp index 2a4e1c78a..702156659 100644 --- a/src/renderer/fill_bucket.cpp +++ b/src/renderer/fill_bucket.cpp @@ -182,18 +182,24 @@ void FillBucket::tessellate() { if (a != TESS_UNDEF && b != TESS_UNDEF && c != TESS_UNDEF) { triangleElementsBuffer.add(triangleIndex + a, triangleIndex + b, triangleIndex + c); } else { +#if defined(DEBUG) // TODO: We're missing a vertex that was not part of the line. fprintf(stderr, "undefined element buffer\n"); +#endif } } else { +#if defined(DEBUG) fprintf(stderr, "undefined element buffer\n"); +#endif } } triangleGroup.vertex_length += total_vertex_count; triangleGroup.elements_length += triangle_count; } else { +#if defined(DEBUG) fprintf(stderr, "tessellation failed\n"); +#endif } // We're adding the total vertex count *after* we added additional vertices diff --git a/src/renderer/painter.cpp b/src/renderer/painter.cpp index 82808f4d1..b755301eb 100644 --- a/src/renderer/painter.cpp +++ b/src/renderer/painter.cpp @@ -1,13 +1,13 @@ #include - #include - #include #include -#include #include #include #include +#if defined(DEBUG) +#include +#endif #include #include @@ -29,8 +29,9 @@ bool Painter::needsAnimation() const { } void Painter::setup() { +#if defined(DEBUG) util::timer timer("painter setup"); - +#endif setupShaders(); assert(iconShader); diff --git a/src/renderer/painter_text.cpp b/src/renderer/painter_text.cpp index 0c3c0a01b..bd1709a96 100644 --- a/src/renderer/painter_text.cpp +++ b/src/renderer/painter_text.cpp @@ -1,6 +1,7 @@ #include #include #include +#include using namespace llmr; @@ -66,8 +67,7 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons history[0].z = history[1].z; } - size_t frameLen = history.size(); - assert("there should never be less than three frames in the history" && frameLen >= 3); + assert("there should never be less than three frames in the history" && (history.size() >= 3)); // Find the range of zoom levels we want to fade between float startingZ = history.front().z; @@ -81,7 +81,9 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons timeDiff = lastFrame.timestamp - history[1].timestamp; float fadedist = zoomDiff / (timeDiff / duration); - if (isnan(fadedist)) fprintf(stderr, "fadedist should never be NaN\n"); +#if defined(DEBUG) + if (std::isnan(fadedist)) fprintf(stderr, "fadedist should never be NaN\n"); +#endif // At end of a zoom when the zoom stops changing continue pretending to zoom at that speed // bump is how much farther it would have been if it had continued zooming at the same rate diff --git a/src/shader/gaussian_shader.cpp b/src/shader/gaussian_shader.cpp index 450ce331a..03509de41 100644 --- a/src/shader/gaussian_shader.cpp +++ b/src/shader/gaussian_shader.cpp @@ -12,7 +12,9 @@ GaussianShader::GaussianShader() shaders[GAUSSIAN_SHADER].fragment ) { if (!valid) { +#if defined(DEBUG) fprintf(stderr, "invalid raster shader\n"); +#endif return; } diff --git a/src/shader/raster_shader.cpp b/src/shader/raster_shader.cpp index eaf45ea2b..f083d3e26 100644 --- a/src/shader/raster_shader.cpp +++ b/src/shader/raster_shader.cpp @@ -12,7 +12,9 @@ RasterShader::RasterShader() shaders[RASTER_SHADER].fragment ) { if (!valid) { +#if defined(DEBUG) fprintf(stderr, "invalid raster shader\n"); +#endif return; } diff --git a/src/shader/shader.cpp b/src/shader/shader.cpp index 97e494f65..70b59e7aa 100644 --- a/src/shader/shader.cpp +++ b/src/shader/shader.cpp @@ -1,7 +1,8 @@ #include #include +#if defined(DEBUG) #include - +#endif #include #include #include @@ -11,18 +12,23 @@ using namespace llmr; Shader::Shader(const GLchar *vertSource, const GLchar *fragSource) : valid(false), program(0) { +#if defined(DEBUG) util::timer timer("shader compilation"); - +#endif GLuint vertShader; if (!compileShader(&vertShader, GL_VERTEX_SHADER, vertSource)) { +#if defined(DEBUG) fprintf(stderr, "Vertex shader failed to compile: %s\n", vertSource); +#endif return; } GLuint fragShader; if (!compileShader(&fragShader, GL_FRAGMENT_SHADER, fragSource)) { +#if defined(DEBUG) fprintf(stderr, "Fragment shader failed to compile: %s\n", fragSource); +#endif return; } @@ -80,7 +86,9 @@ Shader::Shader(const GLchar *vertSource, const GLchar *fragSource) glGetProgramiv(program, GL_VALIDATE_STATUS, &status); if (status == 0) { +#if defined(DEBUG) fprintf(stderr, "Program failed to validate\n"); +#endif glDeleteShader(vertShader); vertShader = 0; glDeleteShader(fragShader); diff --git a/src/style/sprite.cpp b/src/style/sprite.cpp index bb24c5fec..a0070b288 100644 --- a/src/style/sprite.cpp +++ b/src/style/sprite.cpp @@ -54,7 +54,9 @@ void Sprite::complete(std::shared_ptr &sprite) { if (sprite->raster && sprite->pos.size()) { sprite->loaded = true; sprite->map.update(); +#if defined(DEBUG) fprintf(stderr, "sprite loaded\n"); +#endif } } diff --git a/src/text/glyph_store.cpp b/src/text/glyph_store.cpp index 3f741236f..4a4517b70 100644 --- a/src/text/glyph_store.cpp +++ b/src/text/glyph_store.cpp @@ -52,7 +52,9 @@ GlyphPBF::GlyphPBF(const std::string &fontStack, GlyphRange glyphRange) // TODO: Find more reliable URL normalization function std::replace(url.begin(), url.end(), ' ', '+'); +#if defined(DEBUG) fprintf(stderr, "%s\n", url.c_str()); +#endif platform::request_http(url, [&](platform::Response *res) { if (res->code != 200) { diff --git a/src/util/constants.cpp b/src/util/constants.cpp index f67464926..c939bbde4 100644 --- a/src/util/constants.cpp +++ b/src/util/constants.cpp @@ -2,6 +2,7 @@ const float llmr::util::tileSize = 512.0f; +#if defined(DEBUG) const bool llmr::debug::tileParseWarnings = false; const bool llmr::debug::styleParseWarnings = false; const bool llmr::debug::spriteWarnings = false; @@ -12,3 +13,15 @@ const bool llmr::debug::missingFontStackWarning = true; const bool llmr::debug::missingFontFaceWarning = true; const bool llmr::debug::glyphWarning = true; const bool llmr::debug::shapingWarning = true; +#else +const bool llmr::debug::tileParseWarnings = false; +const bool llmr::debug::styleParseWarnings = false; +const bool llmr::debug::spriteWarnings = false; +const bool llmr::debug::renderWarnings = false; +const bool llmr::debug::renderTree = false; +const bool llmr::debug::labelTextMissingWarning = false; +const bool llmr::debug::missingFontStackWarning = false; +const bool llmr::debug::missingFontFaceWarning = false; +const bool llmr::debug::glyphWarning = true; +const bool llmr::debug::shapingWarning = true; +#endif \ No newline at end of file From 2be6fefdf80521d31bf79bddcc66acb3f5f5a1f2 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 29 May 2014 18:13:41 -0700 Subject: [PATCH 06/15] make shapingWarning and glyphWarning off for release builds --- src/util/constants.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/constants.cpp b/src/util/constants.cpp index c939bbde4..46852e5e7 100644 --- a/src/util/constants.cpp +++ b/src/util/constants.cpp @@ -22,6 +22,6 @@ const bool llmr::debug::renderTree = false; const bool llmr::debug::labelTextMissingWarning = false; const bool llmr::debug::missingFontStackWarning = false; const bool llmr::debug::missingFontFaceWarning = false; -const bool llmr::debug::glyphWarning = true; -const bool llmr::debug::shapingWarning = true; +const bool llmr::debug::glyphWarning = false; +const bool llmr::debug::shapingWarning = false; #endif \ No newline at end of file From 6e53a0328b5de4609f9bc187d6f076ee9f65ecaa Mon Sep 17 00:00:00 2001 From: Young Hahn Date: Thu, 29 May 2014 22:54:46 -0400 Subject: [PATCH 07/15] Remove VectorTileGlyph, VectorTileFace, IndexedFaces, Faces and glyph related parts of vector_tile.proto. Refs #274. --- include/llmr/geometry/glyph_atlas.hpp | 2 - include/llmr/map/tile_parser.hpp | 1 - include/llmr/map/vector_tile.hpp | 30 ------- include/llmr/text/glyph.hpp | 2 - proto/vector_tile.proto | 44 ---------- src/map/vector_tile.cpp | 119 -------------------------- 6 files changed, 198 deletions(-) diff --git a/include/llmr/geometry/glyph_atlas.hpp b/include/llmr/geometry/glyph_atlas.hpp index 5bcd573f5..0aada6a73 100644 --- a/include/llmr/geometry/glyph_atlas.hpp +++ b/include/llmr/geometry/glyph_atlas.hpp @@ -12,8 +12,6 @@ namespace llmr { -class VectorTileGlyph; - class GlyphAtlas { public: diff --git a/include/llmr/map/tile_parser.hpp b/include/llmr/map/tile_parser.hpp index 5785c29b3..84bb65e12 100644 --- a/include/llmr/map/tile_parser.hpp +++ b/include/llmr/map/tile_parser.hpp @@ -42,7 +42,6 @@ private: GlyphAtlas& glyphAtlas; GlyphStore &glyphStore; SpriteAtlas &spriteAtlas; - Faces faces; Placement placement; }; diff --git a/include/llmr/map/vector_tile.hpp b/include/llmr/map/vector_tile.hpp index f57c5d350..1e809556e 100644 --- a/include/llmr/map/vector_tile.hpp +++ b/include/llmr/map/vector_tile.hpp @@ -83,38 +83,9 @@ public: uint32_t extent = 4096; std::vector keys; std::vector values; - std::vector faces; std::map> shaping; }; -class VectorTileGlyph { -public: - VectorTileGlyph(); - VectorTileGlyph(pbf data); - - uint32_t id = 0; - - // A signed distance field of the glyph with a border of 3 pixels. - std::string bitmap; - - // Glyph metrics - GlyphMetrics metrics; -}; - -std::ostream& operator<<(std::ostream&, const VectorTileGlyph& glyph); - -class VectorTileFace { -public: - VectorTileFace(pbf data); - - std::string name; - std::string family; - std::string style; - std::vector glyphs; -}; - -std::ostream& operator<<(std::ostream&, const VectorTileFace& face); - class VectorTile { public: VectorTile(); @@ -122,7 +93,6 @@ public: VectorTile& operator=(VectorTile&& other); std::map layers; - std::map faces; }; diff --git a/include/llmr/text/glyph.hpp b/include/llmr/text/glyph.hpp index e6138e712..8f9024a90 100644 --- a/include/llmr/text/glyph.hpp +++ b/include/llmr/text/glyph.hpp @@ -43,8 +43,6 @@ struct Glyph { }; typedef std::map GlyphPositions; -typedef std::map Faces; -typedef std::vector IndexedFaces; class GlyphPlacement { public: diff --git a/proto/vector_tile.proto b/proto/vector_tile.proto index e982c1a01..ea482adb2 100644 --- a/proto/vector_tile.proto +++ b/proto/vector_tile.proto @@ -75,43 +75,6 @@ message feature { optional uint32 vertex_count = 6; } -// Stores a glyph with metrics and optional SDF bitmap information. -message glyph { - required uint32 id = 1; - - // A signed distance field of the glyph with a border of 3 pixels. - optional bytes bitmap = 2; - - // Glyph metrics. - required uint32 width = 3; - required uint32 height = 4; - required sint32 left = 5; - required sint32 top = 6; - required uint32 advance = 7; -} - -// Stores font face information and a list of glyphs. -message face { - required string family = 1; - required string style = 2; - repeated glyph glyphs = 5; -} - -// Stores the shaping information for the label with a given text -message label { - // The original value ID this shaping information is for. - required uint32 text = 1; - - // References the index of the font stack in the layer's fontstack array. - required uint32 stack = 2; - - // Parallel arrays of face ID, glyph ID and position. - repeated uint32 faces = 3 [packed = true]; - repeated uint32 glyphs = 4 [packed = true]; - repeated uint32 x = 5 [packed = true]; - repeated uint32 y = 6 [packed = true]; -} - message layer { // Any compliant implementation must first read the version // number encoded in this message and choose the correct @@ -136,18 +99,11 @@ message layer { // Total vertex count in this layer. optional uint32 vertex_count = 6; - // Shaping information for labels contained in this tile. - repeated string faces = 7; - repeated label labels = 8; - repeated string stacks = 9; - extensions 16 to max; } message tile { repeated layer layers = 3; - repeated face faces = 4; - extensions 16 to 8191; } diff --git a/src/map/vector_tile.cpp b/src/map/vector_tile.cpp index 248e94712..f0f5a85cd 100644 --- a/src/map/vector_tile.cpp +++ b/src/map/vector_tile.cpp @@ -70,9 +70,6 @@ VectorTile::VectorTile(pbf tile) { if (tile.tag == 3) { // layer VectorTileLayer layer(tile.message()); layers.emplace(layer.name, std::forward(layer)); - } else if (tile.tag == 4) { // face - VectorTileFace face(tile.message()); - faces.emplace(face.name, std::forward(face)); } else { tile.skip(); } @@ -86,100 +83,8 @@ VectorTile& VectorTile::operator=(VectorTile && other) { return *this; } -VectorTileFace::VectorTileFace(pbf face) { - while (face.next()) { - if (face.tag == 1) { // family - family = face.string(); - } else if (face.tag == 2) { // style - style = face.string(); - } else if (face.tag == 5) { // glyphs - glyphs.emplace_back(face.message()); - } else { - face.skip(); - } - } - name = family + " " + style; -} - - -std::ostream& llmr::operator<<(std::ostream& os, const VectorTileFace& face) { - os << "Face: " << face.name << std::endl; - for (const VectorTileGlyph& glyph : face.glyphs) { - os << " - " << glyph; - } - return os; -} - - -// -1 overflows to maximum value -VectorTileGlyph::VectorTileGlyph() {} - -VectorTileGlyph::VectorTileGlyph(pbf glyph) { - while (glyph.next()) { - if (glyph.tag == 1) { // id - id = glyph.varint(); - } else if (glyph.tag == 2) { // bitmap - bitmap = glyph.string(); - } else if (glyph.tag == 3) { // width - metrics.width = glyph.varint(); - } else if (glyph.tag == 4) { // height - metrics.height = glyph.varint(); - } else if (glyph.tag == 5) { // left - metrics.left = glyph.svarint(); - } else if (glyph.tag == 6) { // top - metrics.top = glyph.svarint(); - } else if (glyph.tag == 7) { // advance - metrics.advance = glyph.varint(); - } else { - glyph.skip(); - } - } -} - -std::ostream& llmr::operator<<(std::ostream& os, const VectorTileGlyph& glyph) { - os << "Glyph " << glyph.id << ": " << glyph.metrics.width << "x" << glyph.metrics.height << - " (" << glyph.metrics.left << "/" << glyph.metrics.top << ") +" << glyph.metrics.advance << std::endl; - return os; -} - -class VectorTileLabel { -public: - VectorTileLabel(pbf data); - - uint32_t text = 0; - uint32_t stack = 0; - std::vector placements; -}; - -VectorTileLabel::VectorTileLabel(pbf label) { - pbf faces, glyphs, x, y; - - while (label.next()) { - if (label.tag == 1) { // text - text = label.varint(); - } else if (label.tag == 2) { // stack - stack = label.varint(); - } else if (label.tag == 3) { // faces - faces = label.message(); - } else if (label.tag == 4) { // glyphs - glyphs = label.message(); - } else if (label.tag == 5) { // x - x = label.message(); - } else if (label.tag == 6) { // y - y = label.message(); - } else { - label.skip(); - } - } - - while (faces && glyphs && x && y) { - placements.emplace_back(faces.varint(), glyphs.varint(), x.varint(), y.varint()); - } -} - VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) { std::vector stacks; - std::vector labels; while (layer.next()) { if (layer.tag == 1) { // name @@ -190,34 +95,10 @@ VectorTileLayer::VectorTileLayer(pbf layer) : data(layer) { values.emplace_back(std::move(parseValue(layer.message()))); } else if (layer.tag == 5) { // extent extent = layer.varint(); - } else if (layer.tag == 7) { // faces - faces.emplace_back(layer.string()); - } else if (layer.tag == 8) { // labels - labels.emplace_back(layer.message()); - } else if (layer.tag == 9) { // stacks - stacks.emplace_back(layer.string()); } else { layer.skip(); } } - - // Build index of [stack][text] => shaping information - for (VectorTileLabel& label : labels) { - if (values.size() <= label.text || stacks.size() <= label.stack) { - // The indices are out of range. Skip this label. - continue; - } - - const Value& text = values[label.text]; - const std::string& stack = stacks[label.stack]; - - shaping[stack][text].swap(label.placements); - } -} - -std::ostream& llmr::operator<<(std::ostream& os, const GlyphPlacement& placement) { - os << "Glyph " << placement.face << "/" << placement.glyph << ": " << placement.x << "/" << placement.y << std::endl; - return os; } FilteredVectorTileLayer::FilteredVectorTileLayer(const VectorTileLayer& layer, const BucketDescription& bucket_desc) From 2bf23a7d77cd3040826eee1a87e136e3d1badd84 Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Fri, 30 May 2014 00:40:49 -0700 Subject: [PATCH 08/15] bump MVK for latest pinch enhancements --- ios/MVKMapKit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/MVKMapKit b/ios/MVKMapKit index 9c3aa2d91..7c7bb2310 160000 --- a/ios/MVKMapKit +++ b/ios/MVKMapKit @@ -1 +1 @@ -Subproject commit 9c3aa2d919f2a76d5fef2500a3ee624b57a11383 +Subproject commit 7c7bb2310216a8d18108db40b09db08732df1f88 From cc9521c5e27b7c972fa30450f3cacf0de42c2acb Mon Sep 17 00:00:00 2001 From: "Justin R. Miller" Date: Fri, 30 May 2014 00:57:50 -0700 Subject: [PATCH 09/15] update iOS bundle ID --- ios/Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/Info.plist b/ios/Info.plist index d78b5428e..9c96d492a 100644 --- a/ios/Info.plist +++ b/ios/Info.plist @@ -9,7 +9,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.mapbox.llmr.native + com.mapbox.${PRODUCT_NAME:rfc1034identifier} CFBundleInfoDictionaryVersion 6.0 CFBundleName From ec973af82e467d7816bae5daf83359dbe85233dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 30 May 2014 13:02:40 +0200 Subject: [PATCH 10/15] skip characters that don't have metrics --- src/text/glyph_store.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/text/glyph_store.cpp b/src/text/glyph_store.cpp index 4a4517b70..cbcf012dd 100644 --- a/src/text/glyph_store.cpp +++ b/src/text/glyph_store.cpp @@ -38,7 +38,11 @@ const Shaping FontStack::getShaping(const std::u32string &string) const { GlyphPlacement glyph = GlyphPlacement(0, chr, x, 0); shaped.push_back(glyph); i++; - x += metrics.find(chr)->second.advance; + + auto metrics_it = metrics.find(chr); + if (metrics_it != metrics.end()) { + x += metrics_it->second.advance; + } } return shaped; } From 942da9cecc4b97eea68a1ad98f5d119a67be45bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 30 May 2014 13:23:48 +0200 Subject: [PATCH 11/15] don't convert twice --- src/map/tile_parser.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/map/tile_parser.cpp b/src/map/tile_parser.cpp index ff5d61a5e..f23a5e673 100644 --- a/src/map/tile_parser.cpp +++ b/src/map/tile_parser.cpp @@ -218,11 +218,12 @@ std::unique_ptr TileParser::createTextBucket(const VectorTileLayer& laye continue; } - const std::u32string string = ucs4conv.convert(toString(it_prop->second)); + const std::string source_string = toString(it_prop->second); + const std::u32string string = ucs4conv.convert(source_string); // Shape labels. const Shaping shaped = fontStack.getShaping(string); - shaping.emplace(toString(it_prop->second), shaped); + shaping.emplace(source_string, shaped); // Place labels. addGlyph(tile.id.to_uint64(), bucket_desc.geometry.font, string, fontStack, glyphAtlas, face); From 461a19dfa22b5301080d891baac5cad6e554adad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 30 May 2014 13:36:53 +0200 Subject: [PATCH 12/15] fallback to default properties instead of not rendering when we don't have a style refs #272 --- include/llmr/style/properties.hpp | 12 ++++++++++++ src/map/map.cpp | 6 +++++- src/renderer/painter_fill.cpp | 5 +++-- src/renderer/painter_icon.cpp | 5 +++-- src/renderer/painter_line.cpp | 5 +++-- src/renderer/painter_raster.cpp | 5 +++-- src/renderer/painter_text.cpp | 5 +++-- 7 files changed, 32 insertions(+), 11 deletions(-) diff --git a/include/llmr/style/properties.hpp b/include/llmr/style/properties.hpp index b8ffcfad6..d0bc3b2d4 100644 --- a/include/llmr/style/properties.hpp +++ b/include/llmr/style/properties.hpp @@ -128,6 +128,7 @@ struct IconClass : public GenericClass { }; struct IconProperties : public GenericProperties { + inline IconProperties() : GenericProperties() {} float size = 0; Color color = {{ 1, 1, 1, 1 }}; std::string image; @@ -147,6 +148,7 @@ struct LineClass : public GenericClass { }; struct LineProperties : public GenericProperties { + inline LineProperties() : GenericProperties() {} float width = 0; float offset = 0; Color color = {{ 0, 0, 0, 1 }}; @@ -164,6 +166,7 @@ struct FillClass : public GenericClass { }; struct FillProperties : public GenericProperties { + inline FillProperties() : GenericProperties() {} Winding winding = Winding::NonZero; bool antialias = true; Color fill_color = {{ 0, 0, 0, 1 }}; @@ -187,6 +190,7 @@ struct TextClass : public GenericClass { }; struct TextProperties : public GenericProperties { + inline TextProperties() : GenericProperties() {} Color color = {{ 0, 0, 0, 1 }}; Color halo = {{ 1, 1, 1, 0.75 }}; float halo_radius = 0.25f; @@ -202,6 +206,7 @@ struct BackgroundClass : public GenericClass { }; struct BackgroundProperties : public GenericProperties { + inline BackgroundProperties() : GenericProperties() {} Color color = {{ 1, 1, 1, 1 }}; }; @@ -209,6 +214,7 @@ struct RasterClass : public GenericClass { }; struct RasterProperties : public GenericProperties { + inline RasterProperties() : GenericProperties() {} }; struct CompositeClass : public GenericClass { @@ -219,6 +225,12 @@ struct CompositeProperties : public GenericProperties { }; +const IconProperties defaultIconProperties; +const LineProperties defaultLineProperties; +const FillProperties defaultFillProperties; +const TextProperties defaultTextProperties; +const BackgroundProperties defaultBackgroundProperties; +const RasterProperties defaultRasterProperties; const CompositeProperties defaultCompositeProperties; } diff --git a/src/map/map.cpp b/src/map/map.cpp index 60a7aa78d..71ce0e938 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -591,7 +591,11 @@ typename Styles::const_iterator find_style(const Styles &styles, const LayerDesc template bool is_invisible(const Styles &styles, const LayerDescription &layer_desc) { auto it = find_style(styles, layer_desc); - if (it == styles.end()) { return true; } + if (it == styles.end()) { + // We don't have a style, so we fall back to the default style which is + // always visible. + return false; + } return !it->second.isVisible(); } diff --git a/src/renderer/painter_fill.cpp b/src/renderer/painter_fill.cpp index cd7b0780d..d0ba2a8de 100644 --- a/src/renderer/painter_fill.cpp +++ b/src/renderer/painter_fill.cpp @@ -146,9 +146,10 @@ void Painter::renderFill(FillBucket& bucket, const std::string& layer_name, cons const std::unordered_map &fill_properties = map.getStyle().computed.fills; const std::unordered_map::const_iterator fill_properties_it = fill_properties.find(layer_name); - if (fill_properties_it == fill_properties.end()) return; - const FillProperties& properties = fill_properties_it->second; + const FillProperties &properties = fill_properties_it != fill_properties.end() + ? fill_properties_it->second + : defaultFillProperties; if (!properties.enabled) return; diff --git a/src/renderer/painter_icon.cpp b/src/renderer/painter_icon.cpp index 382312c12..51bb88fb2 100644 --- a/src/renderer/painter_icon.cpp +++ b/src/renderer/painter_icon.cpp @@ -13,9 +13,10 @@ void Painter::renderIcon(IconBucket& bucket, const std::string& layer_name, cons const std::unordered_map &icon_properties = map.getStyle().computed.icons; const std::unordered_map::const_iterator icon_properties_it = icon_properties.find(layer_name); - if (icon_properties_it == icon_properties.end()) return; - const IconProperties& properties = icon_properties_it->second; + const IconProperties &properties = icon_properties_it != icon_properties.end() + ? icon_properties_it->second + : defaultIconProperties; if (!properties.enabled) return; Color color = properties.color; diff --git a/src/renderer/painter_line.cpp b/src/renderer/painter_line.cpp index 2788a8bb1..71692c74c 100644 --- a/src/renderer/painter_line.cpp +++ b/src/renderer/painter_line.cpp @@ -11,9 +11,10 @@ void Painter::renderLine(LineBucket& bucket, const std::string& layer_name, cons const std::unordered_map &line_properties = map.getStyle().computed.lines; const std::unordered_map::const_iterator line_properties_it = line_properties.find(layer_name); - if (line_properties_it == line_properties.end()) return; - const LineProperties& properties = line_properties_it->second; + const LineProperties &properties = line_properties_it != line_properties.end() + ? line_properties_it->second + : defaultLineProperties; if (!properties.enabled) return; float width = properties.width; diff --git a/src/renderer/painter_raster.cpp b/src/renderer/painter_raster.cpp index de0d35261..f1943bb49 100644 --- a/src/renderer/painter_raster.cpp +++ b/src/renderer/painter_raster.cpp @@ -9,9 +9,10 @@ void Painter::renderRaster(RasterBucket& bucket, const std::string& layer_name, const std::unordered_map &raster_properties = map.getStyle().computed.rasters; const std::unordered_map::const_iterator raster_properties_it = raster_properties.find(layer_name); - if (raster_properties_it == raster_properties.end()) return; - const RasterProperties& properties = raster_properties_it->second; + const RasterProperties &properties = raster_properties_it != raster_properties.end() + ? raster_properties_it->second + : defaultRasterProperties; if (!properties.enabled) return; depthMask(false); diff --git a/src/renderer/painter_text.cpp b/src/renderer/painter_text.cpp index bd1709a96..148fe7d53 100644 --- a/src/renderer/painter_text.cpp +++ b/src/renderer/painter_text.cpp @@ -12,9 +12,10 @@ void Painter::renderText(TextBucket& bucket, const std::string& layer_name, cons const std::unordered_map &text_properties = map.getStyle().computed.texts; const std::unordered_map::const_iterator text_properties_it = text_properties.find(layer_name); - if (text_properties_it == text_properties.end()) return; - const TextProperties& properties = text_properties_it->second; + const TextProperties &properties = text_properties_it != text_properties.end() + ? text_properties_it->second + : defaultTextProperties; if (!properties.enabled) return; mat4 exMatrix; From 31d9dbefeaad90eaece85c013d355c624018db7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 30 May 2014 14:01:53 +0200 Subject: [PATCH 13/15] pass shaping directly instead of looking it up --- include/llmr/renderer/text_bucket.hpp | 4 ++-- src/map/tile_parser.cpp | 10 +++------- src/renderer/text_bucket.cpp | 28 +++------------------------ 3 files changed, 8 insertions(+), 34 deletions(-) diff --git a/include/llmr/renderer/text_bucket.hpp b/include/llmr/renderer/text_bucket.hpp index ad282bdd0..36c50ae7f 100644 --- a/include/llmr/renderer/text_bucket.hpp +++ b/include/llmr/renderer/text_bucket.hpp @@ -36,9 +36,9 @@ public: void addGlyphs(const PlacedGlyphs &glyphs, float placementZoom, PlacementRange placementRange, float zoom); - void addFeature(const VectorTileFeature &feature, + void addFeature(const pbf &geometry, const GlyphPositions &face, - const std::map &shapings); + const Shaping &shaping); void drawGlyphs(TextShader &shader); diff --git a/src/map/tile_parser.cpp b/src/map/tile_parser.cpp index f23a5e673..e0e28e345 100644 --- a/src/map/tile_parser.cpp +++ b/src/map/tile_parser.cpp @@ -199,7 +199,6 @@ std::unique_ptr TileParser::createTextBucket(const VectorTileLayer& laye // Create a copy! const FontStack &fontStack = glyphStore.getFontStack(bucket_desc.geometry.font); - std::map shaping; GlyphPositions face; // Shape and place all labels. @@ -222,18 +221,15 @@ std::unique_ptr TileParser::createTextBucket(const VectorTileLayer& laye const std::u32string string = ucs4conv.convert(source_string); // Shape labels. - const Shaping shaped = fontStack.getShaping(string); - shaping.emplace(source_string, shaped); + const Shaping shaping = fontStack.getShaping(string); // Place labels. addGlyph(tile.id.to_uint64(), bucket_desc.geometry.font, string, fontStack, glyphAtlas, face); + + bucket->addFeature(feature.geometry, face, shaping); } } - // It looks like nearly the same interface through the rest - // of the stack. - addBucketFeatures(bucket, layer, bucket_desc, face, shaping); - return std::move(bucket); } diff --git a/src/renderer/text_bucket.cpp b/src/renderer/text_bucket.cpp index 5823607ac..da6de3817 100644 --- a/src/renderer/text_bucket.cpp +++ b/src/renderer/text_bucket.cpp @@ -99,37 +99,15 @@ void TextBucket::addGlyphs(const PlacedGlyphs &glyphs, float placementZoom, } }; -void TextBucket::addFeature(const VectorTileFeature &feature, +void TextBucket::addFeature(const pbf &geom_pbf, const GlyphPositions &face, - const std::map &shapings) { - auto it_prop = feature.properties.find(geom_desc.field); - if (it_prop == feature.properties.end()) { - // feature does not have the correct property - if (debug::labelTextMissingWarning) { - fprintf(stderr, "[WARNING] feature doesn't have property '%s' required for labelling\n", geom_desc.field.c_str()); - } - return; - } - const Value &value = it_prop->second; - - auto it_shaping = shapings.find(toString(value)); - if (it_shaping == shapings.end()) { - if (debug::shapingWarning) { - fprintf(stderr, "[WARNING] missing shaping for '%s'\n", toString(value).c_str()); - } - // we lack shaping information for this label - return; - } - const Shaping &shaping = it_shaping->second; - - // std::cerr << "we have shaping for " << value << std::endl; - + const Shaping &shaping) { // Decode all lines. std::vector line; Geometry::command cmd; Coordinate coord; - pbf geom = feature.geometry; + pbf geom(geom_pbf); Geometry geometry(geom); int32_t x, y; while ((cmd = geometry.next(x, y)) != Geometry::end) { From 3a8b88dbbde2b1361b19dc5e4cc1c3edb592eea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 30 May 2014 14:26:26 +0200 Subject: [PATCH 14/15] fix nearest neighbor image scaling refs #226 --- src/geometry/sprite_atlas.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index 47f7832bc..1a077506a 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -35,15 +35,22 @@ bool SpriteAtlas::resize(const float newRatio) { data = nullptr; allocate(); - dimension w = static_cast(width * newRatio); - dimension h = static_cast(height * newRatio); - float s = std::pow(oldRatio / newRatio, 2); + const int old_w = width * oldRatio; + const int old_h = height * oldRatio; + const int new_w = width * newRatio; + const int new_h = height * newRatio; // Basic image scaling. TODO: Replace this with better image scaling. uint32_t *img_new = reinterpret_cast(data); - uint32_t *img_old = reinterpret_cast(old_data); - for (size_t i = 0, length = w * h; i < length; i++) { - img_new[i] = img_old[static_cast(s * i)]; + const uint32_t *img_old = reinterpret_cast(old_data); + + for (int y = 0; y < new_h; y++) { + const int old_yoffset = ((y * old_h) / new_h) * old_w; + const int new_yoffset = y * new_w; + for (int x = 0; x < new_w; x++) { + const int old_x = (x * old_w) / new_w; + img_new[new_yoffset + x] = img_old[old_yoffset + old_x]; + } } free(old_data); From 3e7f801de11ef6a73578f58cbd89b61a6448924b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20Ka=CC=88fer?= Date: Fri, 30 May 2014 14:28:42 +0200 Subject: [PATCH 15/15] mark all sprites as uninitialized on pixelRatio changes fixes #226 --- src/geometry/sprite_atlas.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/geometry/sprite_atlas.cpp b/src/geometry/sprite_atlas.cpp index 1a077506a..bb514502b 100644 --- a/src/geometry/sprite_atlas.cpp +++ b/src/geometry/sprite_atlas.cpp @@ -55,6 +55,11 @@ bool SpriteAtlas::resize(const float newRatio) { free(old_data); dirty = true; + + // Mark all sprite images as in need of update + for (const auto &pair : images) { + uninitialized.emplace(pair.first); + } } return dirty;