summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/csscolorparser/csscolorparser.cpp6
-rw-r--r--src/mbgl/algorithm/generate_clip_ids.cpp1
-rw-r--r--src/mbgl/algorithm/update_renderables.hpp64
-rw-r--r--src/mbgl/annotation/annotation_manager.cpp92
-rw-r--r--src/mbgl/annotation/annotation_manager.hpp25
-rw-r--r--src/mbgl/annotation/annotation_source.cpp31
-rw-r--r--src/mbgl/annotation/annotation_source.hpp28
-rw-r--r--src/mbgl/annotation/annotation_tile.cpp39
-rw-r--r--src/mbgl/annotation/annotation_tile.hpp46
-rw-r--r--src/mbgl/annotation/fill_annotation_impl.cpp9
-rw-r--r--src/mbgl/annotation/fill_annotation_impl.hpp2
-rw-r--r--src/mbgl/annotation/line_annotation_impl.cpp8
-rw-r--r--src/mbgl/annotation/line_annotation_impl.hpp2
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.cpp112
-rw-r--r--src/mbgl/annotation/shape_annotation_impl.hpp36
-rw-r--r--src/mbgl/annotation/style_sourced_annotation_impl.cpp13
-rw-r--r--src/mbgl/annotation/style_sourced_annotation_impl.hpp2
-rw-r--r--src/mbgl/annotation/symbol_annotation_impl.cpp5
-rw-r--r--src/mbgl/annotation/symbol_annotation_impl.hpp4
-rw-r--r--src/mbgl/geometry/buffer.hpp8
-rw-r--r--src/mbgl/geometry/circle_buffer.cpp4
-rw-r--r--src/mbgl/geometry/debug_font_buffer.cpp4
-rw-r--r--src/mbgl/geometry/elements_buffer.cpp4
-rw-r--r--src/mbgl/geometry/feature_index.cpp10
-rw-r--r--src/mbgl/geometry/feature_index.hpp10
-rw-r--r--src/mbgl/geometry/fill_buffer.cpp4
-rw-r--r--src/mbgl/geometry/glyph_atlas.cpp11
-rw-r--r--src/mbgl/geometry/glyph_atlas.hpp4
-rw-r--r--src/mbgl/geometry/icon_buffer.cpp3
-rw-r--r--src/mbgl/geometry/icon_buffer.hpp2
-rw-r--r--src/mbgl/geometry/line_atlas.cpp11
-rw-r--r--src/mbgl/geometry/line_buffer.cpp4
-rw-r--r--src/mbgl/geometry/static_vertex_buffer.cpp18
-rw-r--r--src/mbgl/geometry/static_vertex_buffer.hpp17
-rw-r--r--src/mbgl/geometry/text_buffer.cpp3
-rw-r--r--src/mbgl/geometry/text_buffer.hpp2
-rw-r--r--src/mbgl/geometry/vao.cpp5
-rw-r--r--src/mbgl/geometry/vao.hpp14
-rw-r--r--src/mbgl/gl/gl.cpp4
-rw-r--r--src/mbgl/gl/gl_config.cpp1
-rw-r--r--src/mbgl/gl/gl_config.hpp7
-rw-r--r--src/mbgl/gl/object_store.cpp23
-rw-r--r--src/mbgl/gl/object_store.hpp36
-rw-r--r--src/mbgl/gl/texture_pool.cpp75
-rw-r--r--src/mbgl/gl/texture_pool.hpp38
-rw-r--r--src/mbgl/map/camera.cpp1
-rw-r--r--src/mbgl/map/map.cpp56
-rw-r--r--src/mbgl/map/transform.cpp74
-rw-r--r--src/mbgl/map/transform.hpp6
-rw-r--r--src/mbgl/map/transform_state.cpp12
-rw-r--r--src/mbgl/map/transform_state.hpp7
-rw-r--r--src/mbgl/platform/event.cpp34
-rw-r--r--src/mbgl/platform/log.cpp11
-rw-r--r--src/mbgl/renderer/bucket.hpp11
-rw-r--r--src/mbgl/renderer/circle_bucket.cpp2
-rw-r--r--src/mbgl/renderer/circle_bucket.hpp2
-rw-r--r--src/mbgl/renderer/debug_bucket.cpp4
-rw-r--r--src/mbgl/renderer/debug_bucket.hpp4
-rw-r--r--src/mbgl/renderer/fill_bucket.cpp29
-rw-r--r--src/mbgl/renderer/fill_bucket.hpp14
-rw-r--r--src/mbgl/renderer/frame_history.cpp6
-rw-r--r--src/mbgl/renderer/line_bucket.cpp14
-rw-r--r--src/mbgl/renderer/line_bucket.hpp10
-rw-r--r--src/mbgl/renderer/painter.cpp77
-rw-r--r--src/mbgl/renderer/painter.hpp102
-rw-r--r--src/mbgl/renderer/painter_background.cpp96
-rw-r--r--src/mbgl/renderer/painter_circle.cpp32
-rw-r--r--src/mbgl/renderer/painter_clipping.cpp14
-rw-r--r--src/mbgl/renderer/painter_debug.cpp55
-rw-r--r--src/mbgl/renderer/painter_fill.cpp216
-rw-r--r--src/mbgl/renderer/painter_line.cpp139
-rw-r--r--src/mbgl/renderer/painter_raster.cpp35
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp80
-rw-r--r--src/mbgl/renderer/raster_bucket.cpp19
-rw-r--r--src/mbgl/renderer/raster_bucket.hpp7
-rw-r--r--src/mbgl/renderer/render_item.hpp10
-rw-r--r--src/mbgl/renderer/render_pass.hpp10
-rw-r--r--src/mbgl/renderer/render_tile.cpp5
-rw-r--r--src/mbgl/renderer/render_tile.hpp26
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp53
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp16
-rw-r--r--src/mbgl/shader/circle_shader.cpp13
-rw-r--r--src/mbgl/shader/circle_shader.hpp5
-rw-r--r--src/mbgl/shader/collision_box_shader.cpp14
-rw-r--r--src/mbgl/shader/collision_box_shader.hpp4
-rw-r--r--src/mbgl/shader/icon_shader.cpp16
-rw-r--r--src/mbgl/shader/icon_shader.hpp9
-rw-r--r--src/mbgl/shader/line_shader.cpp14
-rw-r--r--src/mbgl/shader/line_shader.hpp8
-rw-r--r--src/mbgl/shader/linepattern_shader.cpp14
-rw-r--r--src/mbgl/shader/linepattern_shader.hpp6
-rw-r--r--src/mbgl/shader/linesdf_shader.cpp14
-rw-r--r--src/mbgl/shader/linesdf_shader.hpp8
-rw-r--r--src/mbgl/shader/outline_shader.cpp13
-rw-r--r--src/mbgl/shader/outline_shader.hpp5
-rw-r--r--src/mbgl/shader/outlinepattern_shader.cpp17
-rw-r--r--src/mbgl/shader/outlinepattern_shader.hpp31
-rw-r--r--src/mbgl/shader/pattern_shader.cpp17
-rw-r--r--src/mbgl/shader/pattern_shader.hpp29
-rw-r--r--src/mbgl/shader/plain_shader.cpp13
-rw-r--r--src/mbgl/shader/plain_shader.hpp5
-rw-r--r--src/mbgl/shader/raster_shader.cpp20
-rw-r--r--src/mbgl/shader/raster_shader.hpp12
-rw-r--r--src/mbgl/shader/sdf_shader.cpp32
-rw-r--r--src/mbgl/shader/sdf_shader.hpp26
-rw-r--r--src/mbgl/shader/shader.cpp61
-rw-r--r--src/mbgl/shader/shader.hpp26
-rw-r--r--src/mbgl/shader/uniform.cpp7
-rw-r--r--src/mbgl/sprite/sprite_atlas.cpp11
-rw-r--r--src/mbgl/sprite/sprite_atlas.hpp26
-rw-r--r--src/mbgl/sprite/sprite_parser.cpp6
-rw-r--r--src/mbgl/storage/resource.cpp2
-rw-r--r--src/mbgl/storage/response.cpp6
-rw-r--r--src/mbgl/style/bucket_parameters.cpp7
-rw-r--r--src/mbgl/style/calculation_parameters.hpp12
-rw-r--r--src/mbgl/style/cascade_parameters.hpp2
-rw-r--r--src/mbgl/style/filter_evaluator.hpp163
-rw-r--r--src/mbgl/style/layer.cpp8
-rw-r--r--src/mbgl/style/layer_impl.cpp10
-rw-r--r--src/mbgl/style/layer_impl.hpp13
-rw-r--r--src/mbgl/style/layers/background_layer.cpp20
-rw-r--r--src/mbgl/style/layers/background_layer_impl.cpp4
-rw-r--r--src/mbgl/style/layers/background_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/background_layer_properties.cpp6
-rw-r--r--src/mbgl/style/layers/background_layer_properties.hpp5
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp44
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.cpp6
-rw-r--r--src/mbgl/style/layers/circle_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.cpp9
-rw-r--r--src/mbgl/style/layers/circle_layer_properties.hpp5
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.cpp5
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp48
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.cpp6
-rw-r--r--src/mbgl/style/layers/fill_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.cpp10
-rw-r--r--src/mbgl/style/layers/fill_layer_properties.hpp7
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs100
-rw-r--r--src/mbgl/style/layers/layer_properties.cpp.ejs38
-rw-r--r--src/mbgl/style/layers/layer_properties.hpp.ejs48
-rw-r--r--src/mbgl/style/layers/line_layer.cpp60
-rw-r--r--src/mbgl/style/layers/line_layer_impl.cpp10
-rw-r--r--src/mbgl/style/layers/line_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/line_layer_properties.cpp20
-rw-r--r--src/mbgl/style/layers/line_layer_properties.hpp6
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp44
-rw-r--r--src/mbgl/style/layers/raster_layer_impl.cpp4
-rw-r--r--src/mbgl/style/layers/raster_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/raster_layer_properties.cpp10
-rw-r--r--src/mbgl/style/layers/raster_layer_properties.hpp3
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp105
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.cpp21
-rw-r--r--src/mbgl/style/layers/symbol_layer_impl.hpp4
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.cpp54
-rw-r--r--src/mbgl/style/layers/symbol_layer_properties.hpp19
-rw-r--r--src/mbgl/style/layout_property.hpp7
-rw-r--r--src/mbgl/style/observer.hpp6
-rw-r--r--src/mbgl/style/paint_property.hpp59
-rw-r--r--src/mbgl/style/parser.cpp515
-rw-r--r--src/mbgl/style/parser.hpp9
-rw-r--r--src/mbgl/style/property_evaluator.cpp46
-rw-r--r--src/mbgl/style/property_evaluator.hpp10
-rw-r--r--src/mbgl/style/property_parsing.cpp263
-rw-r--r--src/mbgl/style/property_parsing.hpp98
-rw-r--r--src/mbgl/style/rapidjson_conversion.hpp94
-rw-r--r--src/mbgl/style/source.cpp420
-rw-r--r--src/mbgl/style/source.hpp112
-rw-r--r--src/mbgl/style/source_impl.cpp280
-rw-r--r--src/mbgl/style/source_impl.hpp101
-rw-r--r--src/mbgl/style/source_observer.hpp2
-rw-r--r--src/mbgl/style/sources/geojson_source.cpp21
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.cpp113
-rw-r--r--src/mbgl/style/sources/geojson_source_impl.hpp40
-rw-r--r--src/mbgl/style/sources/raster_source.cpp12
-rw-r--r--src/mbgl/style/sources/raster_source_impl.cpp19
-rw-r--r--src/mbgl/style/sources/raster_source_impl.hpp18
-rw-r--r--src/mbgl/style/sources/vector_source.cpp12
-rw-r--r--src/mbgl/style/sources/vector_source_impl.cpp17
-rw-r--r--src/mbgl/style/sources/vector_source_impl.hpp18
-rw-r--r--src/mbgl/style/style.cpp88
-rw-r--r--src/mbgl/style/style.hpp9
-rw-r--r--src/mbgl/style/tile_source_impl.cpp118
-rw-r--r--src/mbgl/style/tile_source_impl.hpp48
-rw-r--r--src/mbgl/style/types.cpp87
-rw-r--r--src/mbgl/style/update_parameters.hpp6
-rw-r--r--src/mbgl/text/check_max_angle.hpp2
-rw-r--r--src/mbgl/text/collision_feature.cpp4
-rw-r--r--src/mbgl/text/collision_feature.hpp12
-rw-r--r--src/mbgl/text/collision_tile.cpp2
-rw-r--r--src/mbgl/text/get_anchors.cpp10
-rw-r--r--src/mbgl/text/get_anchors.hpp2
-rw-r--r--src/mbgl/text/glyph.hpp13
-rw-r--r--src/mbgl/text/glyph_pbf.cpp2
-rw-r--r--src/mbgl/text/glyph_set.cpp6
-rw-r--r--src/mbgl/text/glyph_set.hpp2
-rw-r--r--src/mbgl/text/placement_config.hpp6
-rw-r--r--src/mbgl/text/quads.cpp68
-rw-r--r--src/mbgl/text/quads.hpp28
-rw-r--r--src/mbgl/text/shaping.hpp6
-rw-r--r--src/mbgl/tile/geojson_tile.cpp189
-rw-r--r--src/mbgl/tile/geojson_tile.hpp64
-rw-r--r--src/mbgl/tile/geometry_tile.cpp342
-rw-r--r--src/mbgl/tile/geometry_tile.hpp139
-rw-r--r--src/mbgl/tile/geometry_tile_data.cpp217
-rw-r--r--src/mbgl/tile/geometry_tile_data.hpp143
-rw-r--r--src/mbgl/tile/raster_tile.cpp71
-rw-r--r--src/mbgl/tile/raster_tile.hpp46
-rw-r--r--src/mbgl/tile/raster_tile_data.cpp71
-rw-r--r--src/mbgl/tile/raster_tile_data.hpp39
-rw-r--r--src/mbgl/tile/tile.cpp35
-rw-r--r--src/mbgl/tile/tile.hpp111
-rw-r--r--src/mbgl/tile/tile_cache.cpp30
-rw-r--r--src/mbgl/tile/tile_cache.hpp8
-rw-r--r--src/mbgl/tile/tile_data.cpp25
-rw-r--r--src/mbgl/tile/tile_data.hpp87
-rw-r--r--src/mbgl/tile/tile_id.hpp23
-rw-r--r--src/mbgl/tile/tile_loader.hpp62
-rw-r--r--src/mbgl/tile/tile_loader_impl.hpp113
-rw-r--r--src/mbgl/tile/tile_observer.hpp18
-rw-r--r--src/mbgl/tile/tile_worker.cpp35
-rw-r--r--src/mbgl/tile/tile_worker.hpp14
-rw-r--r--src/mbgl/tile/vector_tile.cpp122
-rw-r--r--src/mbgl/tile/vector_tile.hpp83
-rw-r--r--src/mbgl/tile/vector_tile_data.cpp215
-rw-r--r--src/mbgl/tile/vector_tile_data.hpp75
-rw-r--r--src/mbgl/util/clip_id.hpp10
-rw-r--r--src/mbgl/util/color.cpp20
-rw-r--r--src/mbgl/util/convert.cpp9
-rw-r--r--src/mbgl/util/dtoa.cpp10
-rw-r--r--src/mbgl/util/dtoa.hpp9
-rw-r--r--src/mbgl/util/exclusive.hpp10
-rw-r--r--src/mbgl/util/geo.cpp4
-rw-r--r--src/mbgl/util/geojson.cpp11
-rw-r--r--src/mbgl/util/grid_index.cpp4
-rw-r--r--src/mbgl/util/grid_index.hpp2
-rw-r--r--src/mbgl/util/interpolate.hpp14
-rw-r--r--src/mbgl/util/intersection_tests.cpp4
-rw-r--r--src/mbgl/util/intersection_tests.hpp4
-rw-r--r--src/mbgl/util/io.hpp2
-rw-r--r--src/mbgl/util/mapbox.cpp11
-rw-r--r--src/mbgl/util/mat2.cpp6
-rw-r--r--src/mbgl/util/mat3.cpp6
-rw-r--r--src/mbgl/util/math.cpp6
-rw-r--r--src/mbgl/util/math.hpp26
-rw-r--r--src/mbgl/util/ptr.hpp6
-rw-r--r--src/mbgl/util/raster.cpp72
-rw-r--r--src/mbgl/util/raster.hpp46
-rw-r--r--src/mbgl/util/rect.hpp10
-rw-r--r--src/mbgl/util/stopwatch.cpp15
-rw-r--r--src/mbgl/util/stopwatch.hpp16
-rw-r--r--src/mbgl/util/thread.hpp31
-rw-r--r--src/mbgl/util/thread_context.cpp5
-rw-r--r--src/mbgl/util/thread_context.hpp2
-rw-r--r--src/mbgl/util/thread_local.hpp10
-rw-r--r--src/mbgl/util/tile_coordinate.cpp1
-rw-r--r--src/mbgl/util/tileset.hpp24
-rw-r--r--src/mbgl/util/utf.hpp2
-rw-r--r--src/mbgl/util/version_info.cpp2
-rw-r--r--src/mbgl/util/work_task.cpp0
-rw-r--r--src/mbgl/util/worker.cpp10
-rw-r--r--src/mbgl/util/worker.hpp2
261 files changed, 4574 insertions, 4622 deletions
diff --git a/src/csscolorparser/csscolorparser.cpp b/src/csscolorparser/csscolorparser.cpp
index 8281eb4202..592f10f025 100644
--- a/src/csscolorparser/csscolorparser.cpp
+++ b/src/csscolorparser/csscolorparser.cpp
@@ -30,7 +30,7 @@
#include <cmath>
#include <algorithm>
-using namespace CSSColorParser;
+namespace CSSColorParser {
// http://www.w3.org/TR/css3-color/
struct NamedColor { const char *const name; const Color color; };
@@ -180,7 +180,7 @@ std::vector<std::string> split(const std::string& s, char delim) {
return elems;
}
-Color CSSColorParser::parse(const std::string& css_str) {
+Color parse(const std::string& css_str) {
std::string str = css_str;
// Remove all whitespace, not compliant, but should just be more accepting.
@@ -288,3 +288,5 @@ Color CSSColorParser::parse(const std::string& css_str) {
return {};
}
+
+} // namespace CSSColorParser
diff --git a/src/mbgl/algorithm/generate_clip_ids.cpp b/src/mbgl/algorithm/generate_clip_ids.cpp
index 208db797d0..74e0ee242f 100644
--- a/src/mbgl/algorithm/generate_clip_ids.cpp
+++ b/src/mbgl/algorithm/generate_clip_ids.cpp
@@ -2,7 +2,6 @@
#include <mbgl/algorithm/covered_by_children.hpp>
#include <mbgl/util/std.hpp>
-#include <mbgl/tile/tile.hpp>
#include <list>
#include <vector>
diff --git a/src/mbgl/algorithm/update_renderables.hpp b/src/mbgl/algorithm/update_renderables.hpp
index 22d4205d90..d47a919bae 100644
--- a/src/mbgl/algorithm/update_renderables.hpp
+++ b/src/mbgl/algorithm/update_renderables.hpp
@@ -1,24 +1,24 @@
#pragma once
#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/range.hpp>
#include <set>
namespace mbgl {
namespace algorithm {
-template <typename GetTileDataFn,
- typename CreateTileDataFn,
- typename RetainTileDataFn,
+template <typename GetTileFn,
+ typename CreateTileFn,
+ typename RetainTileFn,
typename RenderTileFn,
- typename IdealTileIDs,
- typename SourceInfo>
-void updateRenderables(GetTileDataFn getTileData,
- CreateTileDataFn createTileData,
- RetainTileDataFn retainTileData,
+ typename IdealTileIDs>
+void updateRenderables(GetTileFn getTile,
+ CreateTileFn createTile,
+ RetainTileFn retainTile,
RenderTileFn renderTile,
const IdealTileIDs& idealTileIDs,
- const SourceInfo& info,
+ const Range<uint8_t>& zoomRange,
const uint8_t dataTileZoom) {
std::set<UnwrappedTileID> checked;
bool covered;
@@ -26,32 +26,34 @@ void updateRenderables(GetTileDataFn getTileData,
// for (all in the set of ideal tiles of the source) {
for (const auto& idealRenderTileID : idealTileIDs) {
- assert(idealRenderTileID.canonical.z >= info.minZoom);
- assert(idealRenderTileID.canonical.z <= info.maxZoom);
+ assert(idealRenderTileID.canonical.z >= zoomRange.min);
+ assert(idealRenderTileID.canonical.z <= zoomRange.max);
assert(dataTileZoom >= idealRenderTileID.canonical.z);
const OverscaledTileID idealDataTileID(dataTileZoom, idealRenderTileID.canonical);
- auto data = getTileData(idealDataTileID);
+ auto data = getTile(idealDataTileID);
if (!data) {
- data = createTileData(idealDataTileID);
+ data = createTile(idealDataTileID);
assert(data);
}
// if (source has the tile and bucket is loaded) {
if (data->isRenderable()) {
- retainTileData(*data);
+ retainTile(*data, true);
renderTile(idealRenderTileID, *data);
} else {
+ bool triedPrevious = data->hasTriedOptional();
+
// The tile isn't loaded yet, but retain it anyway because it's an ideal tile.
- retainTileData(*data);
+ retainTile(*data, true);
covered = true;
overscaledZ = dataTileZoom + 1;
- if (overscaledZ > info.maxZoom) {
+ if (overscaledZ > zoomRange.max) {
// We're looking for an overzoomed child tile.
const auto childDataTileID = idealDataTileID.scaledTo(overscaledZ);
- data = getTileData(childDataTileID);
+ data = getTile(childDataTileID);
if (data && data->isRenderable()) {
- retainTileData(*data);
+ retainTile(*data, false);
renderTile(idealRenderTileID, *data);
} else {
covered = false;
@@ -60,9 +62,9 @@ void updateRenderables(GetTileDataFn getTileData,
// Check all four actual child tiles.
for (const auto& childTileID : idealDataTileID.canonical.children()) {
const OverscaledTileID childDataTileID(overscaledZ, childTileID);
- data = getTileData(childDataTileID);
+ data = getTile(childDataTileID);
if (data && data->isRenderable()) {
- retainTileData(*data);
+ retainTile(*data, false);
renderTile(childDataTileID.unwrapTo(idealRenderTileID.wrap), *data);
} else {
// At least one child tile doesn't exist, so we are going to look for
@@ -74,7 +76,7 @@ void updateRenderables(GetTileDataFn getTileData,
if (!covered) {
// We couldn't find child tiles that entirely cover the ideal tile.
- for (overscaledZ = dataTileZoom - 1; overscaledZ >= info.minZoom; --overscaledZ) {
+ for (overscaledZ = dataTileZoom - 1; overscaledZ >= zoomRange.min; --overscaledZ) {
const auto parentDataTileID = idealDataTileID.scaledTo(overscaledZ);
const auto parentRenderTileID =
parentDataTileID.unwrapTo(idealRenderTileID.wrap);
@@ -87,12 +89,20 @@ void updateRenderables(GetTileDataFn getTileData,
checked.emplace(parentRenderTileID);
}
- data = getTileData(parentDataTileID);
- if (data && data->isRenderable()) {
- retainTileData(*data);
- renderTile(parentRenderTileID, *data);
- // Break parent tile ascent, since we found one.
- break;
+ data = getTile(parentDataTileID);
+ if (!data && triedPrevious) {
+ data = createTile(parentDataTileID);
+ }
+
+ if (data) {
+ triedPrevious = data->hasTriedOptional();
+ retainTile(*data, false);
+
+ if (data->isRenderable()) {
+ renderTile(parentRenderTileID, *data);
+ // Break parent tile ascent, since we found one.
+ break;
+ }
}
}
}
diff --git a/src/mbgl/annotation/annotation_manager.cpp b/src/mbgl/annotation/annotation_manager.cpp
index e332850357..0cd6bdf231 100644
--- a/src/mbgl/annotation/annotation_manager.cpp
+++ b/src/mbgl/annotation/annotation_manager.cpp
@@ -1,10 +1,10 @@
#include <mbgl/annotation/annotation_manager.hpp>
+#include <mbgl/annotation/annotation_source.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/annotation/line_annotation_impl.hpp>
#include <mbgl/annotation/fill_annotation_impl.hpp>
#include <mbgl/annotation/style_sourced_annotation_impl.hpp>
-#include <mbgl/style/source.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
@@ -31,10 +31,9 @@ AnnotationID AnnotationManager::addAnnotation(const Annotation& annotation, cons
return id;
}
-void AnnotationManager::updateAnnotation(const AnnotationID& id, const Annotation& annotation, const uint8_t maxZoom) {
- removeAnnotation(id);
- Annotation::visit(annotation, [&] (const auto& annotation_) {
- this->add(id, annotation_, maxZoom);
+Update AnnotationManager::updateAnnotation(const AnnotationID& id, const Annotation& annotation, const uint8_t maxZoom) {
+ return Annotation::visit(annotation, [&] (const auto& annotation_) {
+ return this->update(id, annotation_, maxZoom);
});
}
@@ -69,6 +68,53 @@ void AnnotationManager::add(const AnnotationID& id, const StyleSourcedAnnotation
std::make_unique<StyleSourcedAnnotationImpl>(id, annotation, maxZoom));
}
+Update AnnotationManager::update(const AnnotationID& id, const SymbolAnnotation& annotation, const uint8_t maxZoom) {
+ auto it = symbolAnnotations.find(id);
+ if (it == symbolAnnotations.end()) {
+ removeAndAdd(id, annotation, maxZoom);
+ return Update::AnnotationData | Update::AnnotationStyle;
+ }
+
+ Update result = Update::Nothing;
+ const SymbolAnnotation& existing = it->second->annotation;
+
+ if (existing.geometry != annotation.geometry) {
+ result |= Update::AnnotationData;
+ }
+
+ if (existing.icon != annotation.icon) {
+ result |= Update::AnnotationData | Update::AnnotationStyle;
+ }
+
+ if (result != Update::Nothing) {
+ removeAndAdd(id, annotation, maxZoom);
+ }
+
+ return result;
+}
+
+Update AnnotationManager::update(const AnnotationID& id, const LineAnnotation& annotation, const uint8_t maxZoom) {
+ removeAndAdd(id, annotation, maxZoom);
+ return Update::AnnotationData | Update::AnnotationStyle;
+}
+
+Update AnnotationManager::update(const AnnotationID& id, const FillAnnotation& annotation, const uint8_t maxZoom) {
+ removeAndAdd(id, annotation, maxZoom);
+ return Update::AnnotationData | Update::AnnotationStyle;
+}
+
+Update AnnotationManager::update(const AnnotationID& id, const StyleSourcedAnnotation& annotation, const uint8_t maxZoom) {
+ removeAndAdd(id, annotation, maxZoom);
+ return Update::AnnotationData | Update::AnnotationStyle;
+}
+
+void AnnotationManager::removeAndAdd(const AnnotationID& id, const Annotation& annotation, const uint8_t maxZoom) {
+ removeAnnotation(id);
+ Annotation::visit(annotation, [&] (const auto& annotation_) {
+ this->add(id, annotation_, maxZoom);
+ });
+}
+
AnnotationIDs AnnotationManager::getPointAnnotationsInBounds(const LatLngBounds& bounds) const {
AnnotationIDs result;
@@ -80,13 +126,13 @@ AnnotationIDs AnnotationManager::getPointAnnotationsInBounds(const LatLngBounds&
return result;
}
-std::unique_ptr<AnnotationTile> AnnotationManager::getTile(const CanonicalTileID& tileID) {
+std::unique_ptr<AnnotationTileData> AnnotationManager::getTileData(const CanonicalTileID& tileID) {
if (symbolAnnotations.empty() && shapeAnnotations.empty())
return nullptr;
- auto tile = std::make_unique<AnnotationTile>();
+ auto tileData = std::make_unique<AnnotationTileData>();
- AnnotationTileLayer& pointLayer = *tile->layers.emplace(
+ AnnotationTileLayer& pointLayer = *tileData->layers.emplace(
PointLayerID,
std::make_unique<AnnotationTileLayer>(PointLayerID)).first->second;
@@ -98,22 +144,22 @@ std::unique_ptr<AnnotationTile> AnnotationManager::getTile(const CanonicalTileID
}));
for (const auto& shape : shapeAnnotations) {
- shape.second->updateTile(tileID, *tile);
+ shape.second->updateTileData(tileID, *tileData);
}
- return tile;
+ return tileData;
}
void AnnotationManager::updateStyle(Style& style) {
// Create annotation source, point layer, and point bucket
if (!style.getSource(SourceID)) {
- std::unique_ptr<Source> source = std::make_unique<Source>(SourceType::Annotations, SourceID, "", util::tileSize, std::make_unique<Tileset>(), nullptr);
- source->enabled = true;
+ std::unique_ptr<Source> source = std::make_unique<AnnotationSource>();
+ source->baseImpl->enabled = true;
style.addSource(std::move(source));
- std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(PointLayerID);
+ std::unique_ptr<SymbolLayer> layer = std::make_unique<SymbolLayer>(PointLayerID, SourceID);
- layer->setSource(SourceID, PointLayerID);
+ layer->setSourceLayer(PointLayerID);
layer->setIconImage({"{sprite}"});
layer->setIconAllowOverlap(true);
@@ -133,26 +179,28 @@ void AnnotationManager::updateStyle(Style& style) {
}
obsoleteShapeAnnotationLayers.clear();
+}
- for (auto& monitor : monitors) {
- monitor->update(getTile(monitor->tileID.canonical));
+void AnnotationManager::updateData() {
+ for (auto& tile : tiles) {
+ tile->setData(getTileData(tile->id.canonical));
}
}
-void AnnotationManager::addTileMonitor(AnnotationTileMonitor& monitor) {
- monitors.insert(&monitor);
- monitor.update(getTile(monitor.tileID.canonical));
+void AnnotationManager::addTile(AnnotationTile& tile) {
+ tiles.insert(&tile);
+ tile.setData(getTileData(tile.id.canonical));
}
-void AnnotationManager::removeTileMonitor(AnnotationTileMonitor& monitor) {
- monitors.erase(&monitor);
+void AnnotationManager::removeTile(AnnotationTile& tile) {
+ tiles.erase(&tile);
}
void AnnotationManager::addIcon(const std::string& name, std::shared_ptr<const SpriteImage> sprite) {
spriteStore.setSprite(name, sprite);
spriteAtlas.updateDirty();
}
-
+
void AnnotationManager::removeIcon(const std::string& name) {
spriteStore.removeSprite(name);
spriteAtlas.updateDirty();
diff --git a/src/mbgl/annotation/annotation_manager.hpp b/src/mbgl/annotation/annotation_manager.hpp
index 73907e10c8..bdce1a8c3a 100644
--- a/src/mbgl/annotation/annotation_manager.hpp
+++ b/src/mbgl/annotation/annotation_manager.hpp
@@ -4,7 +4,7 @@
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/sprite/sprite_store.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
-#include <mbgl/util/geo.hpp>
+#include <mbgl/map/update.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <string>
@@ -14,14 +14,15 @@
namespace mbgl {
+class LatLngBounds;
class AnnotationTile;
-class AnnotationTileMonitor;
+class AnnotationTileData;
class SymbolAnnotationImpl;
class ShapeAnnotationImpl;
namespace style {
class Style;
-}
+} // namespace style
class AnnotationManager : private util::noncopyable {
public:
@@ -29,7 +30,7 @@ public:
~AnnotationManager();
AnnotationID addAnnotation(const Annotation&, const uint8_t maxZoom);
- void updateAnnotation(const AnnotationID&, const Annotation&, const uint8_t maxZoom);
+ Update updateAnnotation(const AnnotationID&, const Annotation&, const uint8_t maxZoom);
void removeAnnotation(const AnnotationID&);
AnnotationIDs getPointAnnotationsInBounds(const LatLngBounds&) const;
@@ -40,9 +41,10 @@ public:
SpriteAtlas& getSpriteAtlas() { return spriteAtlas; }
void updateStyle(style::Style&);
+ void updateData();
- void addTileMonitor(AnnotationTileMonitor&);
- void removeTileMonitor(AnnotationTileMonitor&);
+ void addTile(AnnotationTile&);
+ void removeTile(AnnotationTile&);
static const std::string SourceID;
static const std::string PointLayerID;
@@ -53,7 +55,14 @@ private:
void add(const AnnotationID&, const FillAnnotation&, const uint8_t);
void add(const AnnotationID&, const StyleSourcedAnnotation&, const uint8_t);
- std::unique_ptr<AnnotationTile> getTile(const CanonicalTileID&);
+ Update update(const AnnotationID&, const SymbolAnnotation&, const uint8_t);
+ Update update(const AnnotationID&, const LineAnnotation&, const uint8_t);
+ Update update(const AnnotationID&, const FillAnnotation&, const uint8_t);
+ Update update(const AnnotationID&, const StyleSourcedAnnotation&, const uint8_t);
+
+ void removeAndAdd(const AnnotationID&, const Annotation&, const uint8_t);
+
+ std::unique_ptr<AnnotationTileData> getTileData(const CanonicalTileID&);
AnnotationID nextID = 0;
@@ -65,7 +74,7 @@ private:
SymbolAnnotationMap symbolAnnotations;
ShapeAnnotationMap shapeAnnotations;
std::vector<std::string> obsoleteShapeAnnotationLayers;
- std::set<AnnotationTileMonitor*> monitors;
+ std::set<AnnotationTile*> tiles;
SpriteStore spriteStore;
SpriteAtlas spriteAtlas;
diff --git a/src/mbgl/annotation/annotation_source.cpp b/src/mbgl/annotation/annotation_source.cpp
new file mode 100644
index 0000000000..cc82b34de7
--- /dev/null
+++ b/src/mbgl/annotation/annotation_source.cpp
@@ -0,0 +1,31 @@
+#include <mbgl/annotation/annotation_source.hpp>
+#include <mbgl/annotation/annotation_manager.hpp>
+#include <mbgl/annotation/annotation_tile.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+AnnotationSource::AnnotationSource()
+ : Source(SourceType::Annotations, std::make_unique<Impl>(*this)) {
+}
+
+AnnotationSource::Impl::Impl(Source& base_)
+ : Source::Impl(SourceType::Annotations, AnnotationManager::SourceID, base_) {
+}
+
+Range<uint8_t> AnnotationSource::Impl::getZoomRange() {
+ // Same as default geojson-vt-cpp.
+ return { 0, 18 };
+}
+
+void AnnotationSource::Impl::load(FileSource&) {
+ loaded = true;
+}
+
+std::unique_ptr<Tile> AnnotationSource::Impl::createTile(const OverscaledTileID& tileID,
+ const style::UpdateParameters& parameters) {
+ return std::make_unique<AnnotationTile>(tileID, parameters);
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/annotation/annotation_source.hpp b/src/mbgl/annotation/annotation_source.hpp
new file mode 100644
index 0000000000..db9221788f
--- /dev/null
+++ b/src/mbgl/annotation/annotation_source.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+#include <mbgl/style/source_impl.hpp>
+
+namespace mbgl {
+
+class AnnotationSource : public style::Source {
+public:
+ AnnotationSource();
+
+ class Impl;
+};
+
+class AnnotationSource::Impl : public style::Source::Impl {
+public:
+ Impl(Source&);
+
+ void load(FileSource&) final;
+
+private:
+ uint16_t getTileSize() const final { return util::tileSize; }
+ Range<uint8_t> getZoomRange() final;
+
+ std::unique_ptr<Tile> createTile(const OverscaledTileID&, const style::UpdateParameters&) final;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/annotation/annotation_tile.cpp b/src/mbgl/annotation/annotation_tile.cpp
index ba4b69108c..91b7f7ddc1 100644
--- a/src/mbgl/annotation/annotation_tile.cpp
+++ b/src/mbgl/annotation/annotation_tile.cpp
@@ -2,11 +2,25 @@
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/storage/file_source.hpp>
+#include <mbgl/style/update_parameters.hpp>
#include <utility>
namespace mbgl {
+AnnotationTile::AnnotationTile(const OverscaledTileID& overscaledTileID,
+ const style::UpdateParameters& parameters)
+ : GeometryTile(overscaledTileID, AnnotationManager::SourceID, parameters.style, parameters.mode),
+ annotationManager(parameters.annotationManager) {
+ annotationManager.addTile(*this);
+}
+
+AnnotationTile::~AnnotationTile() {
+ annotationManager.removeTile(*this);
+}
+
+void AnnotationTile::setNecessity(Necessity) {}
+
AnnotationTileFeature::AnnotationTileFeature(FeatureType type_, GeometryCollection geometries_,
std::unordered_map<std::string, std::string> properties_)
: type(type_),
@@ -21,10 +35,10 @@ optional<Value> AnnotationTileFeature::getValue(const std::string& key) const {
return optional<Value>();
}
-AnnotationTileLayer::AnnotationTileLayer(const std::string &name_)
- : name(name_) {}
+AnnotationTileLayer::AnnotationTileLayer(std::string name_)
+ : name(std::move(name_)) {}
-util::ptr<GeometryTileLayer> AnnotationTile::getLayer(const std::string& name) const {
+util::ptr<GeometryTileLayer> AnnotationTileData::getLayer(const std::string& name) const {
auto it = layers.find(name);
if (it != layers.end()) {
return it->second;
@@ -32,23 +46,4 @@ util::ptr<GeometryTileLayer> AnnotationTile::getLayer(const std::string& name) c
return nullptr;
}
-AnnotationTileMonitor::AnnotationTileMonitor(const OverscaledTileID& tileID_, AnnotationManager& annotationManager_)
- : tileID(tileID_),
- annotationManager(annotationManager_) {
-}
-
-AnnotationTileMonitor::~AnnotationTileMonitor() {
- annotationManager.removeTileMonitor(*this);
-}
-
-std::unique_ptr<AsyncRequest> AnnotationTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback_) {
- callback = callback_;
- annotationManager.addTileMonitor(*this);
- return nullptr;
-}
-
-void AnnotationTileMonitor::update(std::unique_ptr<GeometryTile> tile) {
- callback(nullptr, std::move(tile), {}, {});
-}
-
} // namespace mbgl
diff --git a/src/mbgl/annotation/annotation_tile.hpp b/src/mbgl/annotation/annotation_tile.hpp
index d607d563d4..3e7c2c447f 100644
--- a/src/mbgl/annotation/annotation_tile.hpp
+++ b/src/mbgl/annotation/annotation_tile.hpp
@@ -1,13 +1,28 @@
#pragma once
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/tile/tile_id.hpp>
-
-#include <map>
-#include <unordered_map>
+#include <mbgl/tile/geometry_tile_data.hpp>
namespace mbgl {
+class AnnotationManager;
+
+namespace style {
+class UpdateParameters;
+} // namespace style
+
+class AnnotationTile : public GeometryTile {
+public:
+ AnnotationTile(const OverscaledTileID&,
+ const style::UpdateParameters&);
+ ~AnnotationTile() override;
+
+ void setNecessity(Necessity) final;
+
+private:
+ AnnotationManager& annotationManager;
+};
+
class AnnotationTileFeature : public GeometryTileFeature {
public:
AnnotationTileFeature(FeatureType, GeometryCollection,
@@ -24,7 +39,7 @@ public:
class AnnotationTileLayer : public GeometryTileLayer {
public:
- AnnotationTileLayer(const std::string&);
+ AnnotationTileLayer(std::string);
std::size_t featureCount() const override { return features.size(); }
util::ptr<const GeometryTileFeature> getFeature(std::size_t i) const override { return features[i]; }
@@ -36,28 +51,11 @@ private:
std::string name;
};
-class AnnotationTile : public GeometryTile {
+class AnnotationTileData : public GeometryTileData {
public:
util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
- std::map<std::string, util::ptr<AnnotationTileLayer>> layers;
-};
-
-class AnnotationManager;
-
-class AnnotationTileMonitor : public GeometryTileMonitor {
-public:
- AnnotationTileMonitor(const OverscaledTileID&, AnnotationManager&);
- ~AnnotationTileMonitor();
-
- void update(std::unique_ptr<GeometryTile>);
- std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileMonitor::Callback&) override;
-
- OverscaledTileID tileID;
-
-private:
- AnnotationManager& annotationManager;
- GeometryTileMonitor::Callback callback;
+ std::unordered_map<std::string, util::ptr<AnnotationTileLayer>> layers;
};
} // namespace mbgl
diff --git a/src/mbgl/annotation/fill_annotation_impl.cpp b/src/mbgl/annotation/fill_annotation_impl.cpp
index 31c9f6d720..fe520451f7 100644
--- a/src/mbgl/annotation/fill_annotation_impl.cpp
+++ b/src/mbgl/annotation/fill_annotation_impl.cpp
@@ -7,18 +7,17 @@ namespace mbgl {
using namespace style;
-FillAnnotationImpl::FillAnnotationImpl(const AnnotationID id_, const FillAnnotation& annotation_, const uint8_t maxZoom_)
+FillAnnotationImpl::FillAnnotationImpl(AnnotationID id_, FillAnnotation annotation_, uint8_t maxZoom_)
: ShapeAnnotationImpl(id_, maxZoom_),
- annotation(annotation_) {
+ annotation({ ShapeAnnotationGeometry::visit(annotation_.geometry, CloseShapeAnnotation{}), annotation_.opacity, annotation_.color, annotation_.outlineColor }) {
}
void FillAnnotationImpl::updateStyle(Style& style) const {
if (style.getLayer(layerID))
return;
- std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>(layerID);
- layer->setSource(AnnotationManager::SourceID, layerID);
-
+ std::unique_ptr<FillLayer> layer = std::make_unique<FillLayer>(layerID, AnnotationManager::SourceID);
+ layer->setSourceLayer(layerID);
layer->setFillOpacity(annotation.opacity);
layer->setFillColor(annotation.color);
layer->setFillOutlineColor(annotation.outlineColor);
diff --git a/src/mbgl/annotation/fill_annotation_impl.hpp b/src/mbgl/annotation/fill_annotation_impl.hpp
index b879860c08..6376eee880 100644
--- a/src/mbgl/annotation/fill_annotation_impl.hpp
+++ b/src/mbgl/annotation/fill_annotation_impl.hpp
@@ -7,7 +7,7 @@ namespace mbgl {
class FillAnnotationImpl : public ShapeAnnotationImpl {
public:
- FillAnnotationImpl(const AnnotationID, const FillAnnotation&, const uint8_t maxZoom);
+ FillAnnotationImpl(AnnotationID, FillAnnotation, uint8_t maxZoom);
void updateStyle(style::Style&) const final;
const ShapeAnnotationGeometry& geometry() const final;
diff --git a/src/mbgl/annotation/line_annotation_impl.cpp b/src/mbgl/annotation/line_annotation_impl.cpp
index 85177591f4..f18ca9fadc 100644
--- a/src/mbgl/annotation/line_annotation_impl.cpp
+++ b/src/mbgl/annotation/line_annotation_impl.cpp
@@ -7,17 +7,17 @@ namespace mbgl {
using namespace style;
-LineAnnotationImpl::LineAnnotationImpl(const AnnotationID id_, const LineAnnotation& annotation_, const uint8_t maxZoom_)
+LineAnnotationImpl::LineAnnotationImpl(AnnotationID id_, LineAnnotation annotation_, uint8_t maxZoom_)
: ShapeAnnotationImpl(id_, maxZoom_),
- annotation(annotation_) {
+ annotation({ ShapeAnnotationGeometry::visit(annotation_.geometry, CloseShapeAnnotation{}), annotation_.opacity, annotation_.width, annotation_.color }) {
}
void LineAnnotationImpl::updateStyle(Style& style) const {
if (style.getLayer(layerID))
return;
- std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>(layerID);
- layer->setSource(AnnotationManager::SourceID, layerID);
+ std::unique_ptr<LineLayer> layer = std::make_unique<LineLayer>(layerID, AnnotationManager::SourceID);
+ layer->setSourceLayer(layerID);
layer->setLineJoin(LineJoinType::Round);
layer->setLineOpacity(annotation.opacity);
layer->setLineWidth(annotation.width);
diff --git a/src/mbgl/annotation/line_annotation_impl.hpp b/src/mbgl/annotation/line_annotation_impl.hpp
index c9a37dd390..7945da5d97 100644
--- a/src/mbgl/annotation/line_annotation_impl.hpp
+++ b/src/mbgl/annotation/line_annotation_impl.hpp
@@ -7,7 +7,7 @@ namespace mbgl {
class LineAnnotationImpl : public ShapeAnnotationImpl {
public:
- LineAnnotationImpl(const AnnotationID, const LineAnnotation&, const uint8_t maxZoom);
+ LineAnnotationImpl(AnnotationID, LineAnnotation, uint8_t maxZoom);
void updateStyle(style::Style&) const final;
const ShapeAnnotationGeometry& geometry() const final;
diff --git a/src/mbgl/annotation/shape_annotation_impl.cpp b/src/mbgl/annotation/shape_annotation_impl.cpp
index be6e12558d..620b1acc76 100644
--- a/src/mbgl/annotation/shape_annotation_impl.cpp
+++ b/src/mbgl/annotation/shape_annotation_impl.cpp
@@ -1,5 +1,3 @@
-#include <mapbox/geojsonvt/convert.hpp>
-
#include <mbgl/annotation/shape_annotation_impl.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
#include <mbgl/tile/tile_id.hpp>
@@ -7,6 +5,7 @@
#include <mbgl/math/clamp.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/constants.hpp>
+#include <mbgl/util/geometry.hpp>
namespace mbgl {
@@ -19,85 +18,16 @@ ShapeAnnotationImpl::ShapeAnnotationImpl(const AnnotationID id_, const uint8_t m
layerID("com.mapbox.annotations.shape." + util::toString(id)) {
}
-struct ToGeoJSONVT {
- const double tolerance;
-
- ToGeoJSONVT(const double tolerance_)
- : tolerance(tolerance_) {
- }
-
- geojsonvt::ProjectedFeature operator()(const LineString<double>& line) const {
- geojsonvt::ProjectedRings converted;
- converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::LineString, line));
- return convertFeature(geojsonvt::ProjectedFeatureType::LineString, converted);
- }
-
- geojsonvt::ProjectedFeature operator()(const Polygon<double>& polygon) const {
- geojsonvt::ProjectedRings converted;
- for (const auto& ring : polygon) {
- converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::Polygon, ring));
- }
- return convertFeature(geojsonvt::ProjectedFeatureType::Polygon, converted);
- }
-
- geojsonvt::ProjectedFeature operator()(const MultiLineString<double>& lines) const {
- geojsonvt::ProjectedRings converted;
- for (const auto& line : lines) {
- converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::LineString, line));
- }
- return convertFeature(geojsonvt::ProjectedFeatureType::LineString, converted);
- }
-
- geojsonvt::ProjectedFeature operator()(const MultiPolygon<double>& polygons) const {
- geojsonvt::ProjectedRings converted;
- for (const auto& polygon : polygons) {
- for (const auto& ring : polygon) {
- converted.push_back(convertPoints(geojsonvt::ProjectedFeatureType::Polygon, ring));
- }
- }
- return convertFeature(geojsonvt::ProjectedFeatureType::Polygon, converted);
- }
-
-private:
- geojsonvt::LonLat convertPoint(const Point<double>& p) const {
- return {
- util::wrap(p.x, -util::LONGITUDE_MAX, util::LONGITUDE_MAX),
- util::clamp(p.y, -util::LATITUDE_MAX, util::LATITUDE_MAX)
- };
- }
-
- geojsonvt::ProjectedRing convertPoints(geojsonvt::ProjectedFeatureType type, const std::vector<Point<double>>& points) const {
- std::vector<geojsonvt::LonLat> converted;
-
- for (const auto& p : points) {
- converted.push_back(convertPoint(p));
- }
-
- if (type == geojsonvt::ProjectedFeatureType::Polygon && points.front() != points.back()) {
- converted.push_back(converted.front());
- }
-
- return geojsonvt::Convert::projectRing(converted, tolerance);
- }
-
- geojsonvt::ProjectedFeature convertFeature(geojsonvt::ProjectedFeatureType type, const geojsonvt::ProjectedRings& rings) const {
- return geojsonvt::Convert::create(geojsonvt::Tags(), type, rings);
- }
-};
-
-void ShapeAnnotationImpl::updateTile(const CanonicalTileID& tileID, AnnotationTile& tile) {
+void ShapeAnnotationImpl::updateTileData(const CanonicalTileID& tileID, AnnotationTileData& data) {
static const double baseTolerance = 4;
if (!shapeTiler) {
- const uint64_t maxAmountOfTiles = 1 << maxZoom;
- const double tolerance = baseTolerance / (maxAmountOfTiles * util::EXTENT);
-
- std::vector<geojsonvt::ProjectedFeature> features = {
- ShapeAnnotationGeometry::visit(geometry(), ToGeoJSONVT(tolerance))
- };
-
+ mapbox::geometry::feature_collection<double> features;
+ features.emplace_back(ShapeAnnotationGeometry::visit(geometry(), [] (auto&& geom) {
+ return Feature(std::move(geom));
+ }));
mapbox::geojsonvt::Options options;
- options.maxZoom = maxZoom;
+ options.maxZoom = util::clamp<uint8_t>(maxZoom, 0, 18);
options.buffer = 255u;
options.extent = util::EXTENT;
options.tolerance = baseTolerance;
@@ -105,34 +35,20 @@ void ShapeAnnotationImpl::updateTile(const CanonicalTileID& tileID, AnnotationTi
}
const auto& shapeTile = shapeTiler->getTile(tileID.z, tileID.x, tileID.y);
- if (!shapeTile)
+ if (shapeTile.features.empty())
return;
- AnnotationTileLayer& layer = *tile.layers.emplace(layerID,
+ AnnotationTileLayer& layer = *data.layers.emplace(layerID,
std::make_unique<AnnotationTileLayer>(layerID)).first->second;
- for (auto& shapeFeature : shapeTile.features) {
- FeatureType featureType = FeatureType::Unknown;
-
- if (shapeFeature.type == geojsonvt::TileFeatureType::LineString) {
- featureType = FeatureType::LineString;
- } else if (shapeFeature.type == geojsonvt::TileFeatureType::Polygon) {
- featureType = FeatureType::Polygon;
- }
+ ToGeometryCollection toGeometryCollection;
+ ToFeatureType toFeatureType;
+ for (const auto& shapeFeature : shapeTile.features) {
+ FeatureType featureType = apply_visitor(toFeatureType, shapeFeature.geometry);
+ GeometryCollection renderGeometry = apply_visitor(toGeometryCollection, shapeFeature.geometry);
assert(featureType != FeatureType::Unknown);
- GeometryCollection renderGeometry;
- for (auto& shapeRing : shapeFeature.tileGeometry.get<geojsonvt::TileRings>()) {
- GeometryCoordinates renderLine;
-
- for (auto& shapePoint : shapeRing) {
- renderLine.emplace_back(shapePoint.x, shapePoint.y);
- }
-
- renderGeometry.push_back(renderLine);
- }
-
// https://github.com/mapbox/geojson-vt-cpp/issues/44
if (featureType == FeatureType::Polygon) {
renderGeometry = fixupPolygons(renderGeometry);
diff --git a/src/mbgl/annotation/shape_annotation_impl.hpp b/src/mbgl/annotation/shape_annotation_impl.hpp
index e6ba9a4bd7..800b4ec313 100644
--- a/src/mbgl/annotation/shape_annotation_impl.hpp
+++ b/src/mbgl/annotation/shape_annotation_impl.hpp
@@ -3,18 +3,19 @@
#include <mapbox/geojsonvt.hpp>
#include <mbgl/annotation/annotation.hpp>
+#include <mbgl/util/geometry.hpp>
#include <string>
#include <memory>
namespace mbgl {
-class AnnotationTile;
+class AnnotationTileData;
class CanonicalTileID;
namespace style {
class Style;
-}
+} // namespace style
class ShapeAnnotationImpl {
public:
@@ -24,7 +25,7 @@ public:
virtual void updateStyle(style::Style&) const = 0;
virtual const ShapeAnnotationGeometry& geometry() const = 0;
- void updateTile(const CanonicalTileID&, AnnotationTile&);
+ void updateTileData(const CanonicalTileID&, AnnotationTileData&);
const AnnotationID id;
const uint8_t maxZoom;
@@ -32,4 +33,33 @@ public:
std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> shapeTiler;
};
+struct CloseShapeAnnotation {
+ ShapeAnnotationGeometry operator()(const mbgl::LineString<double> &geom) const {
+ return geom;
+ }
+ ShapeAnnotationGeometry operator()(const mbgl::MultiLineString<double> &geom) const {
+ return geom;
+ }
+ ShapeAnnotationGeometry operator()(const mbgl::Polygon<double> &geom) const {
+ mbgl::Polygon<double> closed = geom;
+ for (auto &ring : closed) {
+ if (!ring.empty() && ring.front() != ring.back()) {
+ ring.emplace_back(ring.front());
+ }
+ }
+ return closed;
+ }
+ ShapeAnnotationGeometry operator()(const mbgl::MultiPolygon<double> &geom) const {
+ mbgl::MultiPolygon<double> closed = geom;
+ for (auto &polygon : closed) {
+ for (auto &ring : polygon) {
+ if (!ring.empty() && ring.front() != ring.back()) {
+ ring.emplace_back(ring.front());
+ }
+ }
+ }
+ return closed;
+ }
+};
+
} // namespace mbgl
diff --git a/src/mbgl/annotation/style_sourced_annotation_impl.cpp b/src/mbgl/annotation/style_sourced_annotation_impl.cpp
index 43a27c8aac..d3212da12d 100644
--- a/src/mbgl/annotation/style_sourced_annotation_impl.cpp
+++ b/src/mbgl/annotation/style_sourced_annotation_impl.cpp
@@ -2,6 +2,7 @@
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/layer.hpp>
+#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
@@ -9,9 +10,9 @@ namespace mbgl {
using namespace style;
-StyleSourcedAnnotationImpl::StyleSourcedAnnotationImpl(const AnnotationID id_, const StyleSourcedAnnotation& annotation_, const uint8_t maxZoom_)
+StyleSourcedAnnotationImpl::StyleSourcedAnnotationImpl(AnnotationID id_, StyleSourcedAnnotation annotation_, uint8_t maxZoom_)
: ShapeAnnotationImpl(id_, maxZoom_),
- annotation(annotation_) {
+ annotation(std::move(annotation_)) {
}
void StyleSourcedAnnotationImpl::updateStyle(Style& style) const {
@@ -23,13 +24,13 @@ void StyleSourcedAnnotationImpl::updateStyle(Style& style) const {
return;
if (sourceLayer->is<LineLayer>()) {
- std::unique_ptr<Layer> layer = sourceLayer->copy(layerID, "");
- layer->as<LineLayer>()->setSource(AnnotationManager::SourceID, layerID);
+ std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID);
+ layer->as<LineLayer>()->setSourceLayer(layerID);
layer->as<LineLayer>()->setVisibility(VisibilityType::Visible);
style.addLayer(std::move(layer), sourceLayer->getID());
} else if (sourceLayer->is<FillLayer>()) {
- std::unique_ptr<Layer> layer = sourceLayer->copy(layerID, "");
- layer->as<FillLayer>()->setSource(AnnotationManager::SourceID, layerID);
+ std::unique_ptr<Layer> layer = sourceLayer->baseImpl->copy(layerID, "", AnnotationManager::SourceID);
+ layer->as<FillLayer>()->setSourceLayer(layerID);
layer->as<FillLayer>()->setVisibility(VisibilityType::Visible);
style.addLayer(std::move(layer), sourceLayer->getID());
}
diff --git a/src/mbgl/annotation/style_sourced_annotation_impl.hpp b/src/mbgl/annotation/style_sourced_annotation_impl.hpp
index 09ef474fc0..82b947302d 100644
--- a/src/mbgl/annotation/style_sourced_annotation_impl.hpp
+++ b/src/mbgl/annotation/style_sourced_annotation_impl.hpp
@@ -7,7 +7,7 @@ namespace mbgl {
class StyleSourcedAnnotationImpl : public ShapeAnnotationImpl {
public:
- StyleSourcedAnnotationImpl(const AnnotationID, const StyleSourcedAnnotation&, const uint8_t maxZoom);
+ StyleSourcedAnnotationImpl(AnnotationID, StyleSourcedAnnotation, uint8_t maxZoom);
void updateStyle(style::Style&) const final;
const ShapeAnnotationGeometry& geometry() const final;
diff --git a/src/mbgl/annotation/symbol_annotation_impl.cpp b/src/mbgl/annotation/symbol_annotation_impl.cpp
index 44a89576bb..5ac2581949 100644
--- a/src/mbgl/annotation/symbol_annotation_impl.cpp
+++ b/src/mbgl/annotation/symbol_annotation_impl.cpp
@@ -1,12 +1,13 @@
#include <mbgl/annotation/symbol_annotation_impl.hpp>
#include <mbgl/annotation/annotation_tile.hpp>
+#include <mbgl/tile/tile_id.hpp>
#include <mbgl/math/clamp.hpp>
namespace mbgl {
-SymbolAnnotationImpl::SymbolAnnotationImpl(const AnnotationID id_, const SymbolAnnotation& annotation_)
+SymbolAnnotationImpl::SymbolAnnotationImpl(AnnotationID id_, SymbolAnnotation annotation_)
: id(id_),
- annotation(annotation_) {
+ annotation(std::move(annotation_)) {
}
void SymbolAnnotationImpl::updateLayer(const CanonicalTileID& tileID, AnnotationTileLayer& layer) const {
diff --git a/src/mbgl/annotation/symbol_annotation_impl.hpp b/src/mbgl/annotation/symbol_annotation_impl.hpp
index 5dc882ab93..2e98f2414c 100644
--- a/src/mbgl/annotation/symbol_annotation_impl.hpp
+++ b/src/mbgl/annotation/symbol_annotation_impl.hpp
@@ -37,7 +37,7 @@ class CanonicalTileID;
class SymbolAnnotationImpl {
public:
- SymbolAnnotationImpl(const AnnotationID, const SymbolAnnotation&);
+ SymbolAnnotationImpl(AnnotationID, SymbolAnnotation);
void updateLayer(const CanonicalTileID&, AnnotationTileLayer&) const;
@@ -55,7 +55,7 @@ namespace index {
template <>
struct indexable<std::shared_ptr<const mbgl::SymbolAnnotationImpl>> {
using result_type = mbgl::LatLng;
- inline mbgl::LatLng operator()(const std::shared_ptr<const mbgl::SymbolAnnotationImpl>& v) const {
+ mbgl::LatLng operator()(const std::shared_ptr<const mbgl::SymbolAnnotationImpl>& v) const {
const mbgl::Point<double>& p = v->annotation.geometry;
return mbgl::LatLng(p.y, p.x);
}
diff --git a/src/mbgl/geometry/buffer.hpp b/src/mbgl/geometry/buffer.hpp
index 6465b6f8e3..d372a040bf 100644
--- a/src/mbgl/geometry/buffer.hpp
+++ b/src/mbgl/geometry/buffer.hpp
@@ -27,11 +27,11 @@ public:
// Returns the number of elements in this buffer. This is not the number of
// bytes, but rather the number of coordinates with associated information.
- inline GLsizei index() const {
+ GLsizei index() const {
return static_cast<GLsizei>(pos / itemSize);
}
- inline bool empty() const {
+ bool empty() const {
return pos == 0;
}
@@ -65,7 +65,7 @@ public:
}
// Uploads the buffer to the GPU to be available when we need it.
- inline void upload(gl::ObjectStore& store) {
+ void upload(gl::ObjectStore& store) {
if (!buffer) {
bind(store);
}
@@ -73,7 +73,7 @@ public:
protected:
// increase the buffer size by at least /required/ bytes.
- inline void *addElement() {
+ void *addElement() {
if (buffer) {
throw std::runtime_error("Can't add elements after buffer was bound to GPU");
}
diff --git a/src/mbgl/geometry/circle_buffer.cpp b/src/mbgl/geometry/circle_buffer.cpp
index 74ccfa8267..cc31fb83bf 100644
--- a/src/mbgl/geometry/circle_buffer.cpp
+++ b/src/mbgl/geometry/circle_buffer.cpp
@@ -4,10 +4,12 @@
#include <climits>
-using namespace mbgl;
+namespace mbgl {
void CircleVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey) {
vertex_type *vertices = static_cast<vertex_type *>(addElement());
vertices[0] = (x * 2) + ((ex + 1) / 2);
vertices[1] = (y * 2) + ((ey + 1) / 2);
}
+
+} // namespace mbgl
diff --git a/src/mbgl/geometry/debug_font_buffer.cpp b/src/mbgl/geometry/debug_font_buffer.cpp
index 5df67accd6..f64ce8816b 100644
--- a/src/mbgl/geometry/debug_font_buffer.cpp
+++ b/src/mbgl/geometry/debug_font_buffer.cpp
@@ -5,7 +5,7 @@
#include <cmath>
#include <cstring>
-using namespace mbgl;
+namespace mbgl {
void DebugFontBuffer::addText(const char *text, double left, double baseline, double scale) {
uint16_t *coords = nullptr;
@@ -40,3 +40,5 @@ void DebugFontBuffer::addText(const char *text, double left, double baseline, do
left += glyph.width * scale;
}
}
+
+} // namespace mbgl
diff --git a/src/mbgl/geometry/elements_buffer.cpp b/src/mbgl/geometry/elements_buffer.cpp
index 3e2e2794dd..b7d8cb2015 100644
--- a/src/mbgl/geometry/elements_buffer.cpp
+++ b/src/mbgl/geometry/elements_buffer.cpp
@@ -1,6 +1,6 @@
#include <mbgl/geometry/elements_buffer.hpp>
-using namespace mbgl;
+namespace mbgl {
void TriangleElementsBuffer::add(element_type a, element_type b, element_type c) {
element_type *elements = static_cast<element_type *>(addElement());
@@ -14,3 +14,5 @@ void LineElementsBuffer::add(element_type a, element_type b) {
elements[0] = a;
elements[1] = b;
}
+
+} // namespace mbgl
diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp
index 8c10344915..6d6521917e 100644
--- a/src/mbgl/geometry/feature_index.cpp
+++ b/src/mbgl/geometry/feature_index.cpp
@@ -57,7 +57,7 @@ void FeatureIndex::query(
const double tileSize,
const double scale,
const optional<std::vector<std::string>>& filterLayerIDs,
- const GeometryTile& geometryTile,
+ const GeometryTileData& geometryTileData,
const CanonicalTileID& tileID,
const style::Style& style) const {
@@ -75,7 +75,7 @@ void FeatureIndex::query(
if (indexedFeature.sortIndex == previousSortIndex) continue;
previousSortIndex = indexedFeature.sortIndex;
- addFeature(result, indexedFeature, queryGeometry, filterLayerIDs, geometryTile, tileID, style, bearing, pixelsToTileUnits);
+ addFeature(result, indexedFeature, queryGeometry, filterLayerIDs, geometryTileData, tileID, style, bearing, pixelsToTileUnits);
}
// query symbol features
@@ -83,7 +83,7 @@ void FeatureIndex::query(
std::vector<IndexedSubfeature> symbolFeatures = collisionTile->queryRenderedSymbols(box, scale);
std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols);
for (const auto& symbolFeature : symbolFeatures) {
- addFeature(result, symbolFeature, queryGeometry, filterLayerIDs, geometryTile, tileID, style, bearing, pixelsToTileUnits);
+ addFeature(result, symbolFeature, queryGeometry, filterLayerIDs, geometryTileData, tileID, style, bearing, pixelsToTileUnits);
}
}
@@ -92,7 +92,7 @@ void FeatureIndex::addFeature(
const IndexedSubfeature& indexedFeature,
const GeometryCollection& queryGeometry,
const optional<std::vector<std::string>>& filterLayerIDs,
- const GeometryTile& geometryTile,
+ const GeometryTileData& geometryTileData,
const CanonicalTileID& tileID,
const style::Style& style,
const float bearing,
@@ -103,7 +103,7 @@ void FeatureIndex::addFeature(
return;
}
- auto sourceLayer = geometryTile.getLayer(indexedFeature.sourceLayerName);
+ auto sourceLayer = geometryTileData.getLayer(indexedFeature.sourceLayerName);
assert(sourceLayer);
auto geometryTileFeature = sourceLayer->getFeature(indexedFeature.index);
diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp
index c944a98130..0fddcb4700 100644
--- a/src/mbgl/geometry/feature_index.hpp
+++ b/src/mbgl/geometry/feature_index.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/style/types.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/util/grid_index.hpp>
#include <mbgl/util/feature.hpp>
@@ -13,7 +13,7 @@ namespace mbgl {
namespace style {
class Style;
-}
+} // namespace style
class CollisionTile;
class CanonicalTileID;
@@ -40,7 +40,7 @@ public:
const double tileSize,
const double scale,
const optional<std::vector<std::string>>& layerIDs,
- const GeometryTile&,
+ const GeometryTileData&,
const CanonicalTileID&,
const style::Style&) const;
@@ -61,7 +61,7 @@ private:
const IndexedSubfeature&,
const GeometryCollection& queryGeometry,
const optional<std::vector<std::string>>& filterLayerIDs,
- const GeometryTile&,
+ const GeometryTileData&,
const CanonicalTileID&,
const style::Style&,
const float bearing,
@@ -73,4 +73,4 @@ private:
std::unordered_map<std::string, std::vector<std::string>> bucketLayerIDs;
};
-}
+} // namespace mbgl
diff --git a/src/mbgl/geometry/fill_buffer.cpp b/src/mbgl/geometry/fill_buffer.cpp
index ee70dfc53b..6cb07ea66a 100644
--- a/src/mbgl/geometry/fill_buffer.cpp
+++ b/src/mbgl/geometry/fill_buffer.cpp
@@ -4,10 +4,12 @@
#include <climits>
-using namespace mbgl;
+namespace mbgl {
void FillVertexBuffer::add(vertex_type x, vertex_type y) {
vertex_type *vertices = static_cast<vertex_type *>(addElement());
vertices[0] = x;
vertices[1] = y;
}
+
+} // namespace mbgl
diff --git a/src/mbgl/geometry/glyph_atlas.cpp b/src/mbgl/geometry/glyph_atlas.cpp
index b4687b8e07..c45a93d24e 100644
--- a/src/mbgl/geometry/glyph_atlas.cpp
+++ b/src/mbgl/geometry/glyph_atlas.cpp
@@ -9,7 +9,7 @@
#include <algorithm>
-using namespace mbgl;
+namespace mbgl {
GlyphAtlas::GlyphAtlas(uint16_t width_, uint16_t height_)
: width(width_),
@@ -19,8 +19,7 @@ GlyphAtlas::GlyphAtlas(uint16_t width_, uint16_t height_)
dirty(true) {
}
-GlyphAtlas::~GlyphAtlas() {
-}
+GlyphAtlas::~GlyphAtlas() = default;
void GlyphAtlas::addGlyphs(uintptr_t tileUID,
const std::u32string& text,
@@ -53,7 +52,7 @@ Rect<uint16_t> GlyphAtlas::addGlyph(uintptr_t tileUID,
const uint8_t buffer = 3;
std::map<uint32_t, GlyphValue>& face = index[fontStack];
- std::map<uint32_t, GlyphValue>::iterator it = face.find(glyph.id);
+ auto it = face.find(glyph.id);
// The glyph is already in this texture.
if (it != face.end()) {
@@ -197,4 +196,6 @@ void GlyphAtlas::bind(gl::ObjectStore& store) {
} else {
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
}
-};
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/geometry/glyph_atlas.hpp b/src/mbgl/geometry/glyph_atlas.hpp
index d3e2a62199..b1fc9d5747 100644
--- a/src/mbgl/geometry/glyph_atlas.hpp
+++ b/src/mbgl/geometry/glyph_atlas.hpp
@@ -39,8 +39,8 @@ public:
private:
struct GlyphValue {
- GlyphValue(const Rect<uint16_t>& rect_, uintptr_t id)
- : rect(rect_), ids({ id }) {}
+ GlyphValue(Rect<uint16_t> rect_, uintptr_t id)
+ : rect(std::move(rect_)), ids({ id }) {}
Rect<uint16_t> rect;
std::set<uintptr_t> ids;
};
diff --git a/src/mbgl/geometry/icon_buffer.cpp b/src/mbgl/geometry/icon_buffer.cpp
index 101132ddbc..51a4aa69fd 100644
--- a/src/mbgl/geometry/icon_buffer.cpp
+++ b/src/mbgl/geometry/icon_buffer.cpp
@@ -6,7 +6,7 @@
namespace mbgl {
-size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom) {
+size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle) {
const size_t idx = index();
void *data = addElement();
@@ -21,6 +21,7 @@ size_t IconVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, int16_t t
ubytes[8] /* tex */ = tx / 4;
ubytes[9] /* tex */ = ty / 4;
ubytes[10] /* labelminzoom */ = labelminzoom * 10;
+ ubytes[11] /* labelangle */ = labelangle;
// a_data2
ubytes[12] /* minzoom */ = minzoom * 10; // 1/10 zoom levels: z16 == 160.
diff --git a/src/mbgl/geometry/icon_buffer.hpp b/src/mbgl/geometry/icon_buffer.hpp
index 0116686265..3a1d57ccd7 100644
--- a/src/mbgl/geometry/icon_buffer.hpp
+++ b/src/mbgl/geometry/icon_buffer.hpp
@@ -10,7 +10,7 @@ namespace mbgl {
16
> {
public:
- size_t add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom);
+ size_t add(int16_t x, int16_t y, float ox, float oy, int16_t tx, int16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle);
};
diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp
index 830640f780..d7ae5b4a60 100644
--- a/src/mbgl/geometry/line_atlas.cpp
+++ b/src/mbgl/geometry/line_atlas.cpp
@@ -9,7 +9,7 @@
#include <sstream>
#include <cmath>
-using namespace mbgl;
+namespace mbgl {
LineAtlas::LineAtlas(GLsizei w, GLsizei h)
: width(w),
@@ -18,8 +18,7 @@ LineAtlas::LineAtlas(GLsizei w, GLsizei h)
dirty(true) {
}
-LineAtlas::~LineAtlas() {
-}
+LineAtlas::~LineAtlas() = default;
LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round, gl::ObjectStore& store) {
size_t key = round ? std::numeric_limits<size_t>::min() : std::numeric_limits<size_t>::max();
@@ -119,7 +118,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool roun
bind(store);
return position;
-};
+}
void LineAtlas::upload(gl::ObjectStore& store) {
if (dirty) {
@@ -171,4 +170,6 @@ void LineAtlas::bind(gl::ObjectStore& store) {
dirty = false;
}
-};
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/geometry/line_buffer.cpp b/src/mbgl/geometry/line_buffer.cpp
index 3d979a2a45..7d2e2eb9a2 100644
--- a/src/mbgl/geometry/line_buffer.cpp
+++ b/src/mbgl/geometry/line_buffer.cpp
@@ -3,7 +3,7 @@
#include <cmath>
-using namespace mbgl;
+namespace mbgl {
GLsizei LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey, bool tx, bool ty, int8_t dir, int32_t linesofar) {
GLsizei idx = index();
@@ -34,3 +34,5 @@ GLsizei LineVertexBuffer::add(vertex_type x, vertex_type y, float ex, float ey,
return idx;
}
+
+} // namespace mbgl
diff --git a/src/mbgl/geometry/static_vertex_buffer.cpp b/src/mbgl/geometry/static_vertex_buffer.cpp
index 254b01b6b6..c66b194748 100644
--- a/src/mbgl/geometry/static_vertex_buffer.cpp
+++ b/src/mbgl/geometry/static_vertex_buffer.cpp
@@ -3,11 +3,21 @@
namespace mbgl {
-StaticVertexBuffer::StaticVertexBuffer(std::initializer_list<std::pair<int16_t, int16_t>> init) {
+StaticVertexBuffer::StaticVertexBuffer(std::initializer_list<std::array<VertexType, 2>> init) {
for (const auto& vertex : init) {
- vertex_type *vertices = static_cast<vertex_type *>(addElement());
- vertices[0] = vertex.first;
- vertices[1] = vertex.second;
+ VertexType* vertices = static_cast<VertexType*>(addElement());
+ vertices[0] = std::get<0>(vertex);
+ vertices[1] = std::get<1>(vertex);
+ }
+}
+
+StaticRasterVertexBuffer::StaticRasterVertexBuffer(std::initializer_list<std::array<VertexType, 4>> init) {
+ for (const auto& vertex : init) {
+ VertexType* vertices = static_cast<VertexType*>(addElement());
+ vertices[0] = std::get<0>(vertex);
+ vertices[1] = std::get<1>(vertex);
+ vertices[2] = std::get<2>(vertex);
+ vertices[3] = std::get<3>(vertex);
}
}
diff --git a/src/mbgl/geometry/static_vertex_buffer.hpp b/src/mbgl/geometry/static_vertex_buffer.hpp
index 79f6117cbc..2e738afc98 100644
--- a/src/mbgl/geometry/static_vertex_buffer.hpp
+++ b/src/mbgl/geometry/static_vertex_buffer.hpp
@@ -2,10 +2,8 @@
#include <mbgl/geometry/buffer.hpp>
-#include <vector>
-#include <cstddef>
+#include <array>
#include <cstdint>
-#include <cmath>
namespace mbgl {
@@ -15,9 +13,18 @@ class StaticVertexBuffer : public Buffer<
32 // default length
> {
public:
- typedef int16_t vertex_type;
+ using VertexType = int16_t;
+ StaticVertexBuffer(std::initializer_list<std::array<VertexType, 2>>);
+};
- StaticVertexBuffer(std::initializer_list<std::pair<int16_t, int16_t>> init);
+class StaticRasterVertexBuffer : public Buffer<
+ 8, // bytes per vertex (4 * signed short == 8 bytes)
+ GL_ARRAY_BUFFER,
+ 32 // default length
+> {
+public:
+ using VertexType = int16_t;
+ StaticRasterVertexBuffer(std::initializer_list<std::array<VertexType, 4>>);
};
} // namespace mbgl
diff --git a/src/mbgl/geometry/text_buffer.cpp b/src/mbgl/geometry/text_buffer.cpp
index 1aa65146a4..382e87324d 100644
--- a/src/mbgl/geometry/text_buffer.cpp
+++ b/src/mbgl/geometry/text_buffer.cpp
@@ -6,7 +6,7 @@
namespace mbgl {
-size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom) {
+size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle) {
const size_t idx = index();
void *data = addElement();
@@ -21,6 +21,7 @@ size_t TextVertexBuffer::add(int16_t x, int16_t y, float ox, float oy, uint16_t
ubytes[8] /* tex */ = tx / 4;
ubytes[9] /* tex */ = ty / 4;
ubytes[10] /* labelminzoom */ = labelminzoom * 10;
+ ubytes[11] /* labelangle */ = labelangle;
// a_data2
ubytes[12] /* minzoom */ = minzoom * 10; // 1/10 zoom levels: z16 == 160.
diff --git a/src/mbgl/geometry/text_buffer.hpp b/src/mbgl/geometry/text_buffer.hpp
index 8d7859fde2..c6b632c67e 100644
--- a/src/mbgl/geometry/text_buffer.hpp
+++ b/src/mbgl/geometry/text_buffer.hpp
@@ -13,7 +13,7 @@ class TextVertexBuffer : public Buffer <
public:
typedef int16_t vertex_type;
- size_t add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom);
+ size_t add(int16_t x, int16_t y, float ox, float oy, uint16_t tx, uint16_t ty, float minzoom, float maxzoom, float labelminzoom, uint8_t labelangle);
};
diff --git a/src/mbgl/geometry/vao.cpp b/src/mbgl/geometry/vao.cpp
index 46f10cb48c..30f5484896 100644
--- a/src/mbgl/geometry/vao.cpp
+++ b/src/mbgl/geometry/vao.cpp
@@ -13,8 +13,7 @@ void VertexArrayObject::Unbind() {
VertexArrayObject::VertexArrayObject() {
}
-VertexArrayObject::~VertexArrayObject() {
-}
+VertexArrayObject::~VertexArrayObject() = default;
void VertexArrayObject::bindVertexArrayObject(gl::ObjectStore& store) {
if (!gl::GenVertexArrays || !gl::BindVertexArray) {
@@ -32,7 +31,7 @@ void VertexArrayObject::bindVertexArrayObject(gl::ObjectStore& store) {
MBGL_CHECK_ERROR(gl::BindVertexArray(*vao));
}
-void VertexArrayObject::verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer,
+void VertexArrayObject::verifyBinding(Shader& shader, GLuint vertexBuffer, GLuint elementsBuffer,
GLbyte *offset) {
if (bound_shader != shader.getID()) {
throw std::runtime_error(std::string("trying to rebind VAO to another shader from " +
diff --git a/src/mbgl/geometry/vao.hpp b/src/mbgl/geometry/vao.hpp
index 150a6badbd..aa0a72ec59 100644
--- a/src/mbgl/geometry/vao.hpp
+++ b/src/mbgl/geometry/vao.hpp
@@ -10,8 +10,6 @@
namespace mbgl {
-class Shader;
-
class VertexArrayObject : public util::noncopyable {
public:
static void Unbind();
@@ -19,8 +17,8 @@ public:
VertexArrayObject();
~VertexArrayObject();
- template <typename Shader, typename VertexBuffer>
- inline void bind(Shader& shader, VertexBuffer &vertexBuffer, GLbyte *offset, gl::ObjectStore& store) {
+ template <typename VertexBuffer>
+ void bind(Shader& shader, VertexBuffer& vertexBuffer, GLbyte* offset, gl::ObjectStore& store) {
bindVertexArrayObject(store);
if (bound_shader == 0) {
vertexBuffer.bind(store);
@@ -33,8 +31,8 @@ public:
}
}
- template <typename Shader, typename VertexBuffer, typename ElementsBuffer>
- inline void bind(Shader& shader, VertexBuffer &vertexBuffer, ElementsBuffer &elementsBuffer, GLbyte *offset, gl::ObjectStore& store) {
+ template <typename VertexBuffer, typename ElementsBuffer>
+ void bind(Shader& shader, VertexBuffer& vertexBuffer, ElementsBuffer& elementsBuffer, GLbyte* offset, gl::ObjectStore& store) {
bindVertexArrayObject(store);
if (bound_shader == 0) {
vertexBuffer.bind(store);
@@ -62,10 +60,10 @@ private:
// For debug reasons, we're storing the bind information so that we can
// detect errors and report
GLuint bound_shader = 0;
- const char *bound_shader_name = "";
+ const char* bound_shader_name = "";
GLuint bound_vertex_buffer = 0;
GLuint bound_elements_buffer = 0;
- GLbyte *bound_offset = 0;
+ GLbyte *bound_offset = nullptr;
};
} // namespace mbgl
diff --git a/src/mbgl/gl/gl.cpp b/src/mbgl/gl/gl.cpp
index 48f00ec177..7747717c63 100644
--- a/src/mbgl/gl/gl.cpp
+++ b/src/mbgl/gl/gl.cpp
@@ -121,7 +121,7 @@ namespace mbgl {
void mbx_trapExtension(const char *, GLenum, GLuint, GLsizei, const GLchar *) { }
void mbx_trapExtension(const char *, GLDEBUGPROC, const void *) { }
void mbx_trapExtension(const char *, GLuint, GLuint, GLuint, GLuint, GLint, const char *, const void*) { }
-
+
void mbx_trapExtension(const char *name, GLuint array) {
if(strncasecmp(name, "glBindVertexArray", 17) == 0) {
currentVertexArray = array;
@@ -188,7 +188,7 @@ void mbx_glBufferData(GLenum target,
}
std::cout << "GL glBufferData: " << currentBinding << " using " << bufferBindingToSizeMap[currentBinding] << " bytes current total " << currentUsedBufferBytes << " high water mark " << largestAmountUsedSoFar << "\n";
lock.unlock();
-
+
glBufferData(target, size, data, usage);
}
diff --git a/src/mbgl/gl/gl_config.cpp b/src/mbgl/gl/gl_config.cpp
index c3c6601e43..97d2f26f6c 100644
--- a/src/mbgl/gl/gl_config.cpp
+++ b/src/mbgl/gl/gl_config.cpp
@@ -13,6 +13,7 @@ const DepthTest::Type DepthTest::Default = GL_FALSE;
const DepthFunc::Type DepthFunc::Default = GL_LEQUAL;
const Blend::Type Blend::Default = GL_TRUE;
const BlendFunc::Type BlendFunc::Default = { GL_ONE, GL_ONE_MINUS_SRC_ALPHA };
+const BlendColor::Type BlendColor::Default = { 0, 0, 0, 0 };
const ColorMask::Type ColorMask::Default = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE };
const ClearDepth::Type ClearDepth::Default = 1;
const ClearColor::Type ClearColor::Default = { 0, 0, 0, 0 };
diff --git a/src/mbgl/gl/gl_config.hpp b/src/mbgl/gl/gl_config.hpp
index 66f4406530..9d7dfb3b6c 100644
--- a/src/mbgl/gl/gl_config.hpp
+++ b/src/mbgl/gl/gl_config.hpp
@@ -21,9 +21,7 @@ public:
}
void reset() {
- dirty = true;
- current = T::Default;
- T::Set(current);
+ *this = T::Default;
}
void setDirty() {
@@ -56,6 +54,7 @@ public:
depthFunc.reset();
blend.reset();
blendFunc.reset();
+ blendColor.reset();
colorMask.reset();
clearDepth.reset();
clearColor.reset();
@@ -80,6 +79,7 @@ public:
depthFunc.setDirty();
blend.setDirty();
blendFunc.setDirty();
+ blendColor.setDirty();
colorMask.setDirty();
clearDepth.setDirty();
clearColor.setDirty();
@@ -103,6 +103,7 @@ public:
Value<DepthFunc> depthFunc;
Value<Blend> blend;
Value<BlendFunc> blendFunc;
+ Value<BlendColor> blendColor;
Value<ColorMask> colorMask;
Value<ClearDepth> clearDepth;
Value<ClearColor> clearColor;
diff --git a/src/mbgl/gl/object_store.cpp b/src/mbgl/gl/object_store.cpp
index 3072296a1e..4139854f61 100644
--- a/src/mbgl/gl/object_store.cpp
+++ b/src/mbgl/gl/object_store.cpp
@@ -22,7 +22,11 @@ void BufferDeleter::operator()(GLuint id) const {
void TextureDeleter::operator()(GLuint id) const {
assert(store);
- store->abandonedTextures.push_back(id);
+ if (store->pooledTextures.size() >= TextureMax) {
+ store->abandonedTextures.push_back(id);
+ } else {
+ store->pooledTextures.push_back(id);
+ }
}
void VAODeleter::operator()(GLuint id) const {
@@ -30,17 +34,8 @@ void VAODeleter::operator()(GLuint id) const {
store->abandonedVAOs.push_back(id);
}
-void TexturePoolDeleter::operator()(ObjectPool ids) const {
- assert(store);
- for (GLuint& id : ids) {
- if (id) {
- store->abandonedTextures.push_back(id);
- id = 0;
- };
- }
-}
-
ObjectStore::~ObjectStore() {
+ assert(pooledTextures.empty());
assert(abandonedPrograms.empty());
assert(abandonedShaders.empty());
assert(abandonedBuffers.empty());
@@ -48,6 +43,12 @@ ObjectStore::~ObjectStore() {
assert(abandonedVAOs.empty());
}
+void ObjectStore::reset() {
+ std::copy(pooledTextures.begin(), pooledTextures.end(), std::back_inserter(abandonedTextures));
+ pooledTextures.resize(0);
+ performCleanup();
+}
+
void ObjectStore::performCleanup() {
for (GLuint id : abandonedPrograms) {
MBGL_CHECK_ERROR(glDeleteProgram(id));
diff --git a/src/mbgl/gl/object_store.hpp b/src/mbgl/gl/object_store.hpp
index 3ae1b6e2fe..96bb8008f1 100644
--- a/src/mbgl/gl/object_store.hpp
+++ b/src/mbgl/gl/object_store.hpp
@@ -5,9 +5,7 @@
#include <unique_resource.hpp>
-#include <array>
#include <algorithm>
-#include <cassert>
#include <memory>
#include <vector>
@@ -43,19 +41,11 @@ struct VAODeleter {
void operator()(GLuint) const;
};
-using ObjectPool = std::array<GLuint, TextureMax>;
-
-struct TexturePoolDeleter {
- ObjectStore* store;
- void operator()(ObjectPool ids) const;
-};
-
using UniqueProgram = std_experimental::unique_resource<GLuint, ProgramDeleter>;
using UniqueShader = std_experimental::unique_resource<GLuint, ShaderDeleter>;
using UniqueBuffer = std_experimental::unique_resource<GLuint, BufferDeleter>;
using UniqueTexture = std_experimental::unique_resource<GLuint, TextureDeleter>;
using UniqueVAO = std_experimental::unique_resource<GLuint, VAODeleter>;
-using UniqueTexturePool = std_experimental::unique_resource<ObjectPool, TexturePoolDeleter>;
class ObjectStore : private util::noncopyable {
public:
@@ -76,8 +66,13 @@ public:
}
UniqueTexture createTexture() {
- GLuint id = 0;
- MBGL_CHECK_ERROR(glGenTextures(1, &id));
+ if (pooledTextures.empty()) {
+ pooledTextures.resize(TextureMax);
+ MBGL_CHECK_ERROR(glGenTextures(TextureMax, pooledTextures.data()));
+ }
+
+ GLuint id = pooledTextures.back();
+ pooledTextures.pop_back();
return UniqueTexture { std::move(id), { this } };
}
@@ -87,19 +82,17 @@ public:
return UniqueVAO { std::move(id), { this } };
}
- UniqueTexturePool createTexturePool() {
- ObjectPool ids;
- MBGL_CHECK_ERROR(glGenTextures(TextureMax, ids.data()));
- assert(ids.size() == size_t(TextureMax));
- return UniqueTexturePool { std::move(ids), { this } };
- }
-
// Actually remove the objects we marked as abandoned with the above methods.
// Only call this while the OpenGL context is exclusive to this thread.
void performCleanup();
+ // Drain pools and remove abandoned objects, in preparation for destroying the store.
+ // Only call this while the OpenGL context is exclusive to this thread.
+ void reset();
+
bool empty() const {
- return abandonedPrograms.empty()
+ return pooledTextures.empty()
+ && abandonedPrograms.empty()
&& abandonedShaders.empty()
&& abandonedBuffers.empty()
&& abandonedTextures.empty()
@@ -112,7 +105,8 @@ private:
friend BufferDeleter;
friend TextureDeleter;
friend VAODeleter;
- friend TexturePoolDeleter;
+
+ std::vector<GLuint> pooledTextures;
std::vector<GLuint> abandonedPrograms;
std::vector<GLuint> abandonedShaders;
diff --git a/src/mbgl/gl/texture_pool.cpp b/src/mbgl/gl/texture_pool.cpp
deleted file mode 100644
index c4984b0186..0000000000
--- a/src/mbgl/gl/texture_pool.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <mbgl/gl/texture_pool.hpp>
-#include <mbgl/gl/object_store.hpp>
-
-#include <algorithm>
-#include <vector>
-
-namespace mbgl {
-namespace gl {
-
-class TexturePool::Impl : private util::noncopyable {
-public:
- class Pool : private util::noncopyable {
- public:
- Pool(gl::ObjectStore& store) : pool(store.createTexturePool()), availableIDs(gl::TextureMax) {
- std::copy(pool.get().begin(), pool.get().end(), availableIDs.begin());
- }
-
- Pool(Pool&& o) : pool(std::move(o.pool)), availableIDs(std::move(o.availableIDs)) {}
- Pool& operator=(Pool&& o) { pool = std::move(o.pool); availableIDs = std::move(o.availableIDs); return *this; }
-
- gl::UniqueTexturePool pool;
- std::vector<GLuint> availableIDs;
- };
-
- GLuint acquireTexture(gl::ObjectStore& store) {
- auto nextAvailableID = [](auto& pool_) {
- auto it = pool_.availableIDs.begin();
- GLuint id = *it;
- pool_.availableIDs.erase(it);
- return id;
- };
-
- for (auto& pool : pools) {
- if (pool.availableIDs.empty()) continue;
- return nextAvailableID(pool);
- }
-
- // All texture IDs are in use.
- pools.emplace_back(Pool { store });
- return nextAvailableID(pools.back());
- }
-
- void releaseTexture(GLuint id) {
- for (auto it = pools.begin(); it != pools.end(); ++it) {
- if (std::find(it->pool.get().begin(), it->pool.get().end(), id) != it->pool.get().end()) {
- it->availableIDs.push_back(id);
- if (GLsizei(it->availableIDs.size()) == gl::TextureMax) {
- pools.erase(it);
- }
- return;
- }
- }
- }
-
-private:
- std::vector<Pool> pools;
-};
-
-void TextureReleaser::operator()(GLuint id) const {
- assert(pool);
- pool->impl->releaseTexture(id);
-}
-
-TexturePool::TexturePool() : impl(std::make_unique<Impl>()) {
-}
-
-TexturePool::~TexturePool() {
-}
-
-PooledTexture TexturePool::acquireTexture(gl::ObjectStore& store) {
- return PooledTexture { impl->acquireTexture(store) , { this } };
-}
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/gl/texture_pool.hpp b/src/mbgl/gl/texture_pool.hpp
deleted file mode 100644
index 1cdcdf220c..0000000000
--- a/src/mbgl/gl/texture_pool.hpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/object_store.hpp>
-
-#include <unique_resource.hpp>
-
-#include <memory>
-
-namespace mbgl {
-namespace gl {
-
-class TexturePool;
-
-struct TextureReleaser {
- TexturePool* pool;
- void operator()(GLuint) const;
-};
-
-using PooledTexture = std_experimental::unique_resource<GLuint, TextureReleaser>;
-
-class TexturePool : private util::noncopyable {
-public:
- TexturePool();
- ~TexturePool();
-
- PooledTexture acquireTexture(gl::ObjectStore&);
-
-private:
- friend TextureReleaser;
-
- class Impl;
- const std::unique_ptr<Impl> impl;
-};
-
-} // namespace gl
-} // namespace mbgl
diff --git a/src/mbgl/map/camera.cpp b/src/mbgl/map/camera.cpp
deleted file mode 100644
index 4a45e904f8..0000000000
--- a/src/mbgl/map/camera.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include <mbgl/map/camera.hpp>
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index b08d3ef710..5d3a1f3e5d 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -5,6 +5,7 @@
#include <mbgl/map/transform_state.hpp>
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/style/style.hpp>
+#include <mbgl/style/source.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/style/observer.hpp>
#include <mbgl/style/transition_options.hpp>
@@ -15,7 +16,6 @@
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/gl/object_store.hpp>
-#include <mbgl/gl/texture_pool.hpp>
#include <mbgl/util/projection.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/exception.hpp>
@@ -37,7 +37,7 @@ class Map::Impl : public style::Observer {
public:
Impl(View&, FileSource&, MapMode, GLContextMode, ConstrainMode, ViewportMode);
- void onResourceLoaded() override;
+ void onNeedsRepaint() override;
void onResourceError(std::exception_ptr) override;
void update();
@@ -62,7 +62,6 @@ public:
util::AsyncTask asyncUpdate;
std::unique_ptr<AnnotationManager> annotationManager;
- std::unique_ptr<gl::TexturePool> texturePool;
std::unique_ptr<Painter> painter;
std::unique_ptr<Style> style;
@@ -98,8 +97,7 @@ Map::Impl::Impl(View& view_,
contextMode(contextMode_),
pixelRatio(view.getPixelRatio()),
asyncUpdate([this] { update(); }),
- annotationManager(std::make_unique<AnnotationManager>(pixelRatio)),
- texturePool(std::make_unique<gl::TexturePool>()) {
+ annotationManager(std::make_unique<AnnotationManager>(pixelRatio)) {
}
Map::~Map() {
@@ -108,13 +106,11 @@ Map::~Map() {
impl->styleRequest = nullptr;
// Explicit resets currently necessary because these abandon resources that need to be
- // cleaned up by store.performCleanup();
+ // cleaned up by store.reset();
impl->style.reset();
impl->painter.reset();
- impl->texturePool.reset();
impl->annotationManager.reset();
-
- impl->store.performCleanup();
+ impl->store.reset();
impl->view.deactivate();
}
@@ -210,11 +206,15 @@ void Map::Impl::update() {
// - Hint style sources to notify when all its tiles are loaded;
timePoint = Clock::now();
- if (style->loaded && updateFlags & Update::Annotations) {
+ if (style->loaded && updateFlags & Update::AnnotationStyle) {
annotationManager->updateStyle(*style);
updateFlags |= Update::Classes;
}
+ if (updateFlags & Update::AnnotationData) {
+ annotationManager->updateData();
+ }
+
if (updateFlags & Update::Classes) {
style->cascade(timePoint, mode);
}
@@ -229,7 +229,6 @@ void Map::Impl::update() {
transform.getState(),
style->workers,
fileSource,
- *texturePool,
style->shouldReparsePartialTiles,
mode,
*annotationManager,
@@ -337,7 +336,7 @@ void Map::Impl::loadStyleJSON(const std::string& json) {
// force style cascade, causing all pending transitions to complete.
style->cascade(Clock::now(), mode);
- updateFlags |= Update::Classes | Update::RecalculateStyle | Update::Annotations;
+ updateFlags |= Update::Classes | Update::RecalculateStyle | Update::AnnotationStyle;
asyncUpdate.send();
}
@@ -378,7 +377,7 @@ bool Map::isPanning() const {
}
#pragma mark -
-
+
CameraOptions Map::getCameraOptions(optional<EdgeInsets> padding) const {
return impl->transform.getCameraOptions(padding);
}
@@ -688,18 +687,17 @@ double Map::getTopOffsetPixelsForAnnotationIcon(const std::string& name) {
AnnotationID Map::addAnnotation(const Annotation& annotation) {
auto result = impl->annotationManager->addAnnotation(annotation, getMaxZoom());
- update(Update::Annotations);
+ update(Update::AnnotationStyle | Update::AnnotationData);
return result;
}
void Map::updateAnnotation(AnnotationID id, const Annotation& annotation) {
- impl->annotationManager->updateAnnotation(id, annotation, getMaxZoom());
- update(Update::Annotations);
+ update(impl->annotationManager->updateAnnotation(id, annotation, getMaxZoom()));
}
void Map::removeAnnotation(AnnotationID annotation) {
impl->annotationManager->removeAnnotation(annotation);
- update(Update::Annotations);
+ update(Update::AnnotationStyle | Update::AnnotationData);
}
AnnotationIDs Map::getPointAnnotationsInBounds(const LatLngBounds& bounds) {
@@ -736,6 +734,22 @@ std::vector<Feature> Map::queryRenderedFeatures(const ScreenBox& box, const opti
#pragma mark - Style API
+style::Source* Map::getSource(const std::string& sourceID) {
+ return impl->style ? impl->style->getSource(sourceID) : nullptr;
+}
+
+void Map::addSource(std::unique_ptr<style::Source> source) {
+ impl->style->addSource(std::move(source));
+}
+
+void Map::removeSource(const std::string& sourceID) {
+ impl->style->removeSource(sourceID);
+}
+
+style::Layer* Map::getLayer(const std::string& layerID) {
+ return impl->style ? impl->style->getLayer(layerID) : nullptr;
+}
+
void Map::addLayer(std::unique_ptr<Layer> layer, const optional<std::string>& before) {
impl->view.activate();
@@ -767,14 +781,14 @@ void Map::cycleDebugOptions() {
#ifndef GL_ES_VERSION_2_0
if (impl->debugOptions & MapDebugOptions::StencilClip)
impl->debugOptions = MapDebugOptions::NoDebug;
- else if (impl->debugOptions & MapDebugOptions::Wireframe)
+ else if (impl->debugOptions & MapDebugOptions::Overdraw)
impl->debugOptions = MapDebugOptions::StencilClip;
#else
- if (impl->debugOptions & MapDebugOptions::Wireframe)
+ if (impl->debugOptions & MapDebugOptions::Overdraw)
impl->debugOptions = MapDebugOptions::NoDebug;
#endif // GL_ES_VERSION_2_0
else if (impl->debugOptions & MapDebugOptions::Collision)
- impl->debugOptions = MapDebugOptions::Collision | MapDebugOptions::Wireframe;
+ impl->debugOptions = MapDebugOptions::Overdraw;
else if (impl->debugOptions & MapDebugOptions::Timestamps)
impl->debugOptions = impl->debugOptions | MapDebugOptions::Collision;
else if (impl->debugOptions & MapDebugOptions::ParseStatus)
@@ -836,7 +850,7 @@ void Map::onLowMemory() {
impl->view.invalidate();
}
-void Map::Impl::onResourceLoaded() {
+void Map::Impl::onNeedsRepaint() {
updateFlags |= Update::Repaint;
asyncUpdate.send();
}
diff --git a/src/mbgl/map/transform.cpp b/src/mbgl/map/transform.cpp
index bf95dd0714..41fc36ce27 100644
--- a/src/mbgl/map/transform.cpp
+++ b/src/mbgl/map/transform.cpp
@@ -14,7 +14,7 @@
#include <cstdio>
#include <cmath>
-using namespace mbgl;
+namespace mbgl {
/** Converts the given angle (in radians) to be numerically close to the anchor angle, allowing it to be interpolated properly without sudden jumps. */
static double _normalizeAngle(double angle, double anchorAngle)
@@ -117,24 +117,24 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
ScreenCoordinate center = getScreenCoordinate(padding);
center.y = state.height - center.y;
-
+
// Constrain camera options.
zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom());
const double scale = state.zoomScale(zoom);
pitch = util::clamp(pitch, 0., util::PITCH_MAX);
-
+
Update update = state.getZoom() == zoom ? Update::Repaint : Update::RecalculateStyle;
-
+
// Minimize rotation by taking the shorter path around the circle.
angle = _normalizeAngle(angle, state.angle);
state.angle = _normalizeAngle(state.angle, angle);
Duration duration = animation.duration ? *animation.duration : Duration::zero();
-
+
const double startWorldSize = state.worldSize();
state.Bc = startWorldSize / util::DEGREES_MAX;
state.Cc = startWorldSize / util::M2PI;
-
+
const double startScale = state.scale;
const double startAngle = state.angle;
const double startPitch = state.pitch;
@@ -147,14 +147,14 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
LatLng frameLatLng = state.unproject(framePoint, startWorldSize);
double frameScale = util::interpolate(startScale, scale, t);
state.setLatLngZoom(frameLatLng, state.scaleZoom(frameScale));
-
+
if (angle != startAngle) {
state.angle = util::wrap(util::interpolate(startAngle, angle, t), -M_PI, M_PI);
}
if (pitch != startPitch) {
state.pitch = util::interpolate(startPitch, pitch, t);
}
-
+
if (padding) {
state.moveLatLng(frameLatLng, center);
}
@@ -163,11 +163,11 @@ void Transform::easeTo(const CameraOptions& camera, const AnimationOptions& anim
}
/** This method implements an “optimal path” animation, as detailed in:
-
+
Van Wijk, Jarke J.; Nuij, Wim A. A. “Smooth and efficient zooming and
panning.” INFOVIS ’03. pp. 15–22.
<https://www.win.tue.nl/~vanwijk/zoompan.pdf#page=5>.
-
+
Where applicable, local variable documentation begins with the associated
variable or function in van Wijk (2003). */
void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &animation) {
@@ -179,7 +179,7 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
if (!latLng || std::isnan(zoom)) {
return;
}
-
+
// Determine endpoints.
EdgeInsets padding;
if (camera.padding) padding = *camera.padding;
@@ -191,19 +191,19 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
ScreenCoordinate center = getScreenCoordinate(padding);
center.y = state.height - center.y;
-
+
// Constrain camera options.
zoom = util::clamp(zoom, state.getMinZoom(), state.getMaxZoom());
pitch = util::clamp(pitch, 0., util::PITCH_MAX);
-
+
// Minimize rotation by taking the shorter path around the circle.
angle = _normalizeAngle(angle, state.angle);
state.angle = _normalizeAngle(state.angle, angle);
-
+
const double startZoom = state.scaleZoom(state.scale);
const double startAngle = state.angle;
const double startPitch = state.pitch;
-
+
/// w₀: Initial visible span, measured in pixels at the initial scale.
/// Known henceforth as a <i>screenful</i>.
double w0 = padding ? std::max(state.width, state.height)
@@ -215,11 +215,11 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
/// Length of the flight path as projected onto the ground plane, measured
/// in pixels from the world image origin at the initial scale.
double u1 = ::hypot((endPoint - startPoint).x, (endPoint - startPoint).y);
-
+
/** ρ: The relative amount of zooming that takes place along the flight
path. A high value maximizes zooming for an exaggerated animation, while
a low value minimizes zooming for something closer to easeTo().
-
+
1.42 is the average value selected by participants in the user study in
van Wijk (2003). A value of 6<sup>¼</sup> would be equivalent to the
root mean squared average velocity, V<sub>RMS</sub>. A value of 1 would
@@ -235,16 +235,16 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
}
/// ρ²
double rho2 = rho * rho;
-
+
/** rᵢ: Returns the zoom-out factor at one end of the animation.
-
+
@param i 0 for the ascent or 1 for the descent. */
auto r = [=](double i) {
/// bᵢ
double b = (w1 * w1 - w0 * w0 + (i ? -1 : 1) * rho2 * rho2 * u1 * u1) / (2 * (i ? w1 : w0) * rho2 * u1);
return std::log(std::sqrt(b * b + 1) - b);
};
-
+
// When u₀ = u₁, the optimal path doesn’t require both ascent and descent.
bool isClose = std::abs(u1) < 0.000001;
// Perform a more or less instantaneous transition if the path is too short.
@@ -252,12 +252,12 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
easeTo(camera, animation);
return;
}
-
+
/// r₀: Zoom-out factor during ascent.
double r0 = r(0);
/** w(s): Returns the visible span on the ground, measured in pixels with
respect to the initial scale.
-
+
Assumes an angular field of view of 2 arctan ½ ≈ 53°. */
auto w = [=](double s) {
return (isClose ? std::exp((w1 < w0 ? -1 : 1) * rho * s)
@@ -273,7 +273,7 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
/// S: Total length of the flight path, measured in ρ-screenfuls.
double S = (isClose ? (std::abs(std::log(w1 / w0)) / rho)
: ((r(1) - r0) / rho));
-
+
Duration duration;
if (animation.duration) {
duration = *animation.duration;
@@ -290,36 +290,36 @@ void Transform::flyTo(const CameraOptions &camera, const AnimationOptions &anima
jumpTo(camera);
return;
}
-
+
const double startWorldSize = state.worldSize();
state.Bc = startWorldSize / util::DEGREES_MAX;
state.Cc = startWorldSize / util::M2PI;
-
+
state.panning = true;
state.scaling = true;
state.rotating = angle != startAngle;
-
+
startTransition(camera, animation, [=](double k) {
/// s: The distance traveled along the flight path, measured in
/// ρ-screenfuls.
double s = k * S;
double us = u(s);
-
+
// Calculate the current point and zoom level along the flight path.
Point<double> framePoint = util::interpolate(startPoint, endPoint, us);
double frameZoom = startZoom + state.scaleZoom(1 / w(s));
-
+
// Convert to geographic coordinates and set the new viewpoint.
LatLng frameLatLng = state.unproject(framePoint, startWorldSize);
state.setLatLngZoom(frameLatLng, frameZoom);
-
+
if (angle != startAngle) {
state.angle = util::wrap(util::interpolate(startAngle, angle, k), -M_PI, M_PI);
}
if (pitch != startPitch) {
state.pitch = util::interpolate(startPitch, pitch, k);
}
-
+
if (padding) {
state.moveLatLng(frameLatLng, center);
}
@@ -474,7 +474,7 @@ void Transform::rotateBy(const ScreenCoordinate& first, const ScreenCoordinate&
center.x = first.x + std::cos(rotateAngle) * heightOffset;
center.y = first.y + std::sin(rotateAngle) * heightOffset;
}
-
+
CameraOptions camera;
camera.angle = state.angle + util::angle_between(first - center, second - center);
easeTo(camera, duration);
@@ -561,7 +561,7 @@ void Transform::startTransition(const CameraOptions& camera,
if (transitionFinishFn) {
transitionFinishFn();
}
-
+
bool isAnimated = duration != Duration::zero();
if (callback) {
callback(isAnimated ? MapChangeRegionWillChangeAnimated : MapChangeRegionWillChange);
@@ -584,12 +584,12 @@ void Transform::startTransition(const CameraOptions& camera,
if (t >= 1.0) {
result = frame(1.0);
} else {
- util::UnitBezier ease = animation.easing ? *animation.easing : util::UnitBezier(0, 0, 0.25, 1);
+ util::UnitBezier ease = animation.easing ? *animation.easing : util::DEFAULT_TRANSITION_EASE;
result = frame(ease.solve(t, 0.001));
}
-
+
if (anchor) state.moveLatLng(anchorLatLng, *anchor);
-
+
// At t = 1.0, a DidChangeAnimated notification should be sent from finish().
if (t < 1.0) {
if (animation.transitionFrameFn) {
@@ -620,7 +620,7 @@ void Transform::startTransition(const CameraOptions& camera,
callback(isAnimated ? MapChangeRegionDidChangeAnimated : MapChangeRegionDidChange);
}
};
-
+
if (!isAnimated) {
transitionFrameFn(Clock::now());
}
@@ -665,3 +665,5 @@ LatLng Transform::screenCoordinateToLatLng(const ScreenCoordinate& point) const
flippedPoint.y = state.height - flippedPoint.y;
return state.screenCoordinateToLatLng(flippedPoint).wrapped();
}
+
+} // namespace mbgl
diff --git a/src/mbgl/map/transform.hpp b/src/mbgl/map/transform.hpp
index 904ed11392..abc301b1cb 100644
--- a/src/mbgl/map/transform.hpp
+++ b/src/mbgl/map/transform.hpp
@@ -28,7 +28,7 @@ public:
// Camera
/** Returns the current camera options. */
CameraOptions getCameraOptions(optional<EdgeInsets>) const;
-
+
/** Instantaneously, synchronously applies the given camera options. */
void jumpTo(const CameraOptions&);
/** Asynchronously transitions all specified camera options linearly along
@@ -40,7 +40,7 @@ public:
void flyTo(const CameraOptions&, const AnimationOptions& = {});
// Position
-
+
/** Pans the map by the given amount.
@param offset The distance to pan the map by, measured in pixels from
top to bottom and from left to right. */
@@ -157,7 +157,7 @@ public:
bool isRotating() const { return state.isRotating(); }
bool isScaling() const { return state.isScaling(); }
bool isPanning() const { return state.isPanning(); }
-
+
// Conversion and projection
ScreenCoordinate latLngToScreenCoordinate(const LatLng&) const;
LatLng screenCoordinateToLatLng(const ScreenCoordinate&) const;
diff --git a/src/mbgl/map/transform_state.cpp b/src/mbgl/map/transform_state.cpp
index fab5991de8..86ffc254d8 100644
--- a/src/mbgl/map/transform_state.cpp
+++ b/src/mbgl/map/transform_state.cpp
@@ -16,13 +16,13 @@ TransformState::TransformState(ConstrainMode constrainMode_, ViewportMode viewpo
#pragma mark - Matrix
void TransformState::matrixFor(mat4& matrix, const UnwrappedTileID& tileID) const {
- const uint64_t tileScale = 1ull << tileID.canonical.z;
+ const uint32_t tileScale = 1u << tileID.canonical.z;
const double s = worldSize() / tileScale;
matrix::identity(matrix);
matrix::translate(matrix, matrix,
- static_cast<int64_t>(tileID.canonical.x + tileID.wrap * tileScale) * s,
- static_cast<int64_t>(tileID.canonical.y) * s, 0);
+ int64_t(tileID.canonical.x + tileID.wrap * tileScale) * s,
+ int64_t(tileID.canonical.y) * s, 0);
matrix::scale(matrix, matrix, s / util::EXTENT, s / util::EXTENT, 1);
}
@@ -336,10 +336,10 @@ void TransformState::setLatLngZoom(const LatLng &latLng, double zoom) {
const double newWorldSize = newScale * util::tileSize;
Bc = newWorldSize / util::DEGREES_MAX;
Cc = newWorldSize / util::M2PI;
-
+
const double m = 1 - 1e-15;
const double f = util::clamp(std::sin(util::DEG2RAD * latLng.latitude), -m, m);
-
+
ScreenCoordinate point = {
-latLng.longitude * Bc,
0.5 * Cc * std::log((1 + f) / (1 - f)),
@@ -351,7 +351,7 @@ void TransformState::setScalePoint(const double newScale, const ScreenCoordinate
double constrainedScale = newScale;
ScreenCoordinate constrainedPoint = point;
constrain(constrainedScale, constrainedPoint.x, constrainedPoint.y);
-
+
scale = constrainedScale;
x = constrainedPoint.x;
y = constrainedPoint.y;
diff --git a/src/mbgl/map/transform_state.hpp b/src/mbgl/map/transform_state.hpp
index 0489b69dd4..1e4b2054f7 100644
--- a/src/mbgl/map/transform_state.hpp
+++ b/src/mbgl/map/transform_state.hpp
@@ -72,6 +72,9 @@ public:
Point<double> project(const LatLng&) const;
LatLng unproject(const Point<double>&, double worldSize, LatLng::WrapMode = LatLng::Unwrapped) const;
+ double zoomScale(double zoom) const;
+ double scaleZoom(double scale) const;
+
private:
bool rotatedNorth() const;
void constrain(double& scale, double& x, double& y) const;
@@ -85,13 +88,11 @@ private:
// logical dimensions
uint16_t width = 0, height = 0;
- double zoomScale(double zoom) const;
- double scaleZoom(double scale) const;
double worldSize() const;
mat4 coordinatePointMatrix(double z) const;
mat4 getPixelMatrix() const;
-
+
/** Recenter the map so that the given coordinate is located at the given
point on screen. */
void moveLatLng(const LatLng&, const ScreenCoordinate&);
diff --git a/src/mbgl/platform/event.cpp b/src/mbgl/platform/event.cpp
new file mode 100644
index 0000000000..68d75a2941
--- /dev/null
+++ b/src/mbgl/platform/event.cpp
@@ -0,0 +1,34 @@
+#include <mbgl/platform/event.hpp>
+#include <mbgl/util/enum.hpp>
+
+namespace mbgl {
+
+MBGL_DEFINE_ENUM(EventSeverity, {
+ { EventSeverity::Debug, "DEBUG" },
+ { EventSeverity::Info, "INFO" },
+ { EventSeverity::Warning, "WARNING" },
+ { EventSeverity::Error, "ERROR" },
+ { EventSeverity(-1), "UNKNOWN" },
+});
+
+MBGL_DEFINE_ENUM(Event, {
+ { Event::General, "General" },
+ { Event::Setup, "Setup" },
+ { Event::Shader, "Shader" },
+ { Event::ParseStyle, "ParseStyle" },
+ { Event::ParseTile, "ParseTile" },
+ { Event::Render, "Render" },
+ { Event::Style, "Style" },
+ { Event::Database, "Database" },
+ { Event::HttpRequest, "HttpRequest" },
+ { Event::Sprite, "Sprite" },
+ { Event::Image, "Image" },
+ { Event::OpenGL, "OpenGL" },
+ { Event::JNI, "JNI" },
+ { Event::Android, "Android" },
+ { Event::Crash, "Crash" },
+ { Event::Glyph, "Glyph" },
+ { Event(-1), "Unknown" },
+});
+
+} // namespace mbgl
diff --git a/src/mbgl/platform/log.cpp b/src/mbgl/platform/log.cpp
index 2118511592..0f334ae3e7 100644
--- a/src/mbgl/platform/log.cpp
+++ b/src/mbgl/platform/log.cpp
@@ -1,4 +1,6 @@
#include <mbgl/platform/log.hpp>
+#include <mbgl/util/enum.hpp>
+#include <mbgl/util/thread.hpp>
#include <cstdio>
#include <cstdarg>
@@ -48,13 +50,8 @@ void Log::record(EventSeverity severity, Event event, int64_t code, const std::s
std::stringstream logStream;
- #if !defined(__ANDROID__) && (defined( __APPLE__) || defined(__linux__))
- char name[32];
- pthread_getname_np(pthread_self(), name, sizeof(name));
- logStream << "{" << name << "}";
- #endif
-
- logStream << "[" << event << "]";
+ logStream << "{" << util::getCurrentThreadName() << "}";
+ logStream << "[" << Enum<Event>::toString(event) << "]";
if (code >= 0) {
logStream << "(" << code << ")";
diff --git a/src/mbgl/renderer/bucket.hpp b/src/mbgl/renderer/bucket.hpp
index f12ed1fb96..6792c162a5 100644
--- a/src/mbgl/renderer/bucket.hpp
+++ b/src/mbgl/renderer/bucket.hpp
@@ -17,15 +17,15 @@ class CollisionTile;
namespace gl {
class ObjectStore;
-}
+} // namespace gl
namespace style {
class Layer;
-}
+} // namespace style
class Bucket : private util::noncopyable {
public:
- Bucket() : uploaded(false) {}
+ Bucket() = default;
// As long as this bucket has a Prepare render pass, this function is getting called. Typically,
// this only happens once when the bucket is being rendered for the first time.
@@ -41,7 +41,7 @@ public:
virtual bool needsClipping() const = 0;
- inline bool needsUpload() const {
+ bool needsUpload() const {
return !uploaded;
}
@@ -49,8 +49,7 @@ public:
virtual void swapRenderData() {}
protected:
- util::Atomic<bool> uploaded;
-
+ util::Atomic<bool> uploaded { false };
};
} // namespace mbgl
diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp
index 4ae63fed46..d86fbda489 100644
--- a/src/mbgl/renderer/circle_bucket.cpp
+++ b/src/mbgl/renderer/circle_bucket.cpp
@@ -100,4 +100,4 @@ void CircleBucket::drawCircles(CircleShader& shader, gl::ObjectStore& store) {
}
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp
index fa34aa088a..041207a6ca 100644
--- a/src/mbgl/renderer/circle_bucket.hpp
+++ b/src/mbgl/renderer/circle_bucket.hpp
@@ -2,7 +2,7 @@
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/map/mode.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/circle_buffer.hpp>
diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp
index 8c7a25c675..b4218485b2 100644
--- a/src/mbgl/renderer/debug_bucket.cpp
+++ b/src/mbgl/renderer/debug_bucket.cpp
@@ -8,7 +8,7 @@
#include <cassert>
#include <string>
-using namespace mbgl;
+namespace mbgl {
DebugBucket::DebugBucket(const OverscaledTileID& id,
const bool renderable_,
@@ -51,3 +51,5 @@ void DebugBucket::drawPoints(PlainShader& shader, gl::ObjectStore& store) {
MBGL_CHECK_ERROR(glDrawArrays(GL_POINTS, 0, (GLsizei)(fontBuffer.index())));
}
}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp
index d69014bb8b..7097ae0735 100644
--- a/src/mbgl/renderer/debug_bucket.hpp
+++ b/src/mbgl/renderer/debug_bucket.hpp
@@ -1,6 +1,5 @@
#pragma once
-#include <mbgl/tile/tile_data.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/geometry/debug_font_buffer.hpp>
#include <mbgl/geometry/vao.hpp>
@@ -8,11 +7,12 @@
namespace mbgl {
+class OverscaledTileID;
class PlainShader;
namespace gl {
class ObjectStore;
-}
+} // namespace gl
class DebugBucket : private util::noncopyable {
public:
diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp
index 02f346decb..c927071850 100644
--- a/src/mbgl/renderer/fill_bucket.cpp
+++ b/src/mbgl/renderer/fill_bucket.cpp
@@ -15,14 +15,14 @@
namespace mapbox {
namespace util {
template <> struct nth<0, mbgl::GeometryCoordinate> {
- inline static int64_t get(const mbgl::GeometryCoordinate& t) { return t.x; };
+ static int64_t get(const mbgl::GeometryCoordinate& t) { return t.x; };
};
template <> struct nth<1, mbgl::GeometryCoordinate> {
- inline static int64_t get(const mbgl::GeometryCoordinate& t) { return t.y; };
+ static int64_t get(const mbgl::GeometryCoordinate& t) { return t.y; };
};
-}
-}
+} // namespace util
+} // namespace mapbox
namespace mbgl {
@@ -33,8 +33,7 @@ struct GeometryTooLongException : std::exception {};
FillBucket::FillBucket() {
}
-FillBucket::~FillBucket() {
-}
+FillBucket::~FillBucket() = default;
void FillBucket::addGeometry(const GeometryCollection& geometry) {
for (auto& polygon : classifyRings(geometry)) {
@@ -120,52 +119,52 @@ bool FillBucket::needsClipping() const {
return true;
}
-void FillBucket::drawElements(PlainShader& shader, gl::ObjectStore& store) {
+void FillBucket::drawElements(PlainShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
assert(group);
- group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
+ group->array[overdraw ? 1 : 0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * triangleElementsBuffer.itemSize;
}
}
-void FillBucket::drawElements(PatternShader& shader, gl::ObjectStore& store) {
+void FillBucket::drawElements(PatternShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
assert(group);
- group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
+ group->array[overdraw ? 3 : 2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * triangleElementsBuffer.itemSize;
}
}
-void FillBucket::drawVertices(OutlineShader& shader, gl::ObjectStore& store) {
+void FillBucket::drawVertices(OutlineShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : lineGroups) {
assert(group);
- group->array[0].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
+ group->array[overdraw ? 1 : 0].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_LINES, group->elements_length * 2, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * lineElementsBuffer.itemSize;
}
}
-void FillBucket::drawVertices(OutlinePatternShader& shader, gl::ObjectStore& store) {
+void FillBucket::drawVertices(OutlinePatternShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : lineGroups) {
assert(group);
- group->array[1].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
+ group->array[overdraw? 3 : 2].bind(shader, vertexBuffer, lineElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_LINES, group->elements_length * 2, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
elements_index += group->elements_length * lineElementsBuffer.itemSize;
}
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp
index 35d70d169c..7508445579 100644
--- a/src/mbgl/renderer/fill_bucket.hpp
+++ b/src/mbgl/renderer/fill_bucket.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/fill_buffer.hpp>
@@ -27,18 +27,18 @@ public:
void addGeometry(const GeometryCollection&);
- void drawElements(PlainShader&, gl::ObjectStore&);
- void drawElements(PatternShader&, gl::ObjectStore&);
- void drawVertices(OutlineShader&, gl::ObjectStore&);
- void drawVertices(OutlinePatternShader&, gl::ObjectStore&);
+ void drawElements(PlainShader&, gl::ObjectStore&, bool overdraw);
+ void drawElements(PatternShader&, gl::ObjectStore&, bool overdraw);
+ void drawVertices(OutlineShader&, gl::ObjectStore&, bool overdraw);
+ void drawVertices(OutlinePatternShader&, gl::ObjectStore&, bool overdraw);
private:
FillVertexBuffer vertexBuffer;
TriangleElementsBuffer triangleElementsBuffer;
LineElementsBuffer lineElementsBuffer;
- typedef ElementGroup<2> TriangleGroup;
- typedef ElementGroup<2> LineGroup;
+ typedef ElementGroup<4> TriangleGroup;
+ typedef ElementGroup<4> LineGroup;
std::vector<std::unique_ptr<TriangleGroup>> triangleGroups;
std::vector<std::unique_ptr<LineGroup>> lineGroups;
diff --git a/src/mbgl/renderer/frame_history.cpp b/src/mbgl/renderer/frame_history.cpp
index dbaf8fbf7a..68b6bf863e 100644
--- a/src/mbgl/renderer/frame_history.cpp
+++ b/src/mbgl/renderer/frame_history.cpp
@@ -1,12 +1,12 @@
#include <mbgl/renderer/frame_history.hpp>
#include <mbgl/math/minmax.hpp>
-using namespace mbgl;
+namespace mbgl {
FrameHistory::FrameHistory() {
changeOpacities.fill(0);
opacities.fill(0);
-};
+}
void FrameHistory::record(const TimePoint& now, float zoom, const Duration& duration) {
@@ -110,3 +110,5 @@ void FrameHistory::bind(gl::ObjectStore& store) {
}
}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index d207cdb8c5..e9a8e78618 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -460,7 +460,7 @@ bool LineBucket::needsClipping() const {
return true;
}
-void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store) {
+void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -468,7 +468,7 @@ void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store) {
if (!group->elements_length) {
continue;
}
- group->array[0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
+ group->array[overdraw ? 1 : 0].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
@@ -476,7 +476,7 @@ void LineBucket::drawLines(LineShader& shader, gl::ObjectStore& store) {
}
}
-void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store) {
+void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -484,7 +484,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store) {
if (!group->elements_length) {
continue;
}
- group->array[2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
+ group->array[overdraw ? 3 : 2].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
@@ -492,7 +492,7 @@ void LineBucket::drawLineSDF(LineSDFShader& shader, gl::ObjectStore& store) {
}
}
-void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::ObjectStore& store) {
+void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte* vertex_index = BUFFER_OFFSET(0);
GLbyte* elements_index = BUFFER_OFFSET(0);
for (auto& group : triangleGroups) {
@@ -500,7 +500,7 @@ void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::ObjectStore& st
if (!group->elements_length) {
continue;
}
- group->array[1].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
+ group->array[overdraw ? 5 : 4].bind(shader, vertexBuffer, triangleElementsBuffer, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT,
elements_index));
vertex_index += group->vertex_length * vertexBuffer.itemSize;
@@ -508,4 +508,4 @@ void LineBucket::drawLinePatterns(LinepatternShader& shader, gl::ObjectStore& st
}
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp
index d746f29c7e..5ece05b03b 100644
--- a/src/mbgl/renderer/line_bucket.hpp
+++ b/src/mbgl/renderer/line_bucket.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/geometry/vao.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/line_buffer.hpp>
@@ -18,7 +18,7 @@ class LineSDFShader;
class LinepatternShader;
class LineBucket : public Bucket {
- using TriangleGroup = ElementGroup<3>;
+ using TriangleGroup = ElementGroup<6>;
public:
LineBucket(uint32_t overscaling);
@@ -32,9 +32,9 @@ public:
void addGeometry(const GeometryCollection&);
void addGeometry(const GeometryCoordinates& line);
- void drawLines(LineShader&, gl::ObjectStore&);
- void drawLineSDF(LineSDFShader&, gl::ObjectStore&);
- void drawLinePatterns(LinepatternShader&, gl::ObjectStore&);
+ void drawLines(LineShader&, gl::ObjectStore&, bool overdraw);
+ void drawLineSDF(LineSDFShader&, gl::ObjectStore&, bool overdraw);
+ void drawLinePatterns(LinepatternShader&, gl::ObjectStore&, bool overdraw);
private:
struct TriangleElement {
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 1864bf7ef1..ba68b5a24d 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -1,7 +1,8 @@
#include <mbgl/renderer/painter.hpp>
+#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/style/source.hpp>
-#include <mbgl/tile/tile.hpp>
+#include <mbgl/style/source_impl.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/gl/debugging.hpp>
@@ -49,26 +50,40 @@ namespace mbgl {
using namespace style;
-Painter::Painter(const TransformState& state_, gl::ObjectStore& store_)
- : state(state_),
- store(store_) {
+Painter::Painter(const TransformState& state_,
+ gl::ObjectStore& store_)
+ : state(state_), store(store_) {
gl::debugging::enable();
- plainShader = std::make_unique<PlainShader>(store);
- outlineShader = std::make_unique<OutlineShader>(store);
- outlinePatternShader = std::make_unique<OutlinePatternShader>(store);
- lineShader = std::make_unique<LineShader>(store);
- linesdfShader = std::make_unique<LineSDFShader>(store);
- linepatternShader = std::make_unique<LinepatternShader>(store);
- patternShader = std::make_unique<PatternShader>(store);
- iconShader = std::make_unique<IconShader>(store);
- rasterShader = std::make_unique<RasterShader>(store);
- sdfGlyphShader = std::make_unique<SDFGlyphShader>(store);
- sdfIconShader = std::make_unique<SDFIconShader>(store);
- collisionBoxShader = std::make_unique<CollisionBoxShader>(store);
- circleShader = std::make_unique<CircleShader>(store);
+ shader.plain = std::make_unique<PlainShader>(store);
+ shader.outline = std::make_unique<OutlineShader>(store);
+ shader.outlinePattern = std::make_unique<OutlinePatternShader>(store);
+ shader.line = std::make_unique<LineShader>(store);
+ shader.linesdf = std::make_unique<LineSDFShader>(store);
+ shader.linepattern = std::make_unique<LinepatternShader>(store);
+ shader.pattern = std::make_unique<PatternShader>(store);
+ shader.icon = std::make_unique<IconShader>(store);
+ shader.raster = std::make_unique<RasterShader>(store);
+ shader.sdfGlyph = std::make_unique<SDFShader>(store);
+ shader.sdfIcon = std::make_unique<SDFShader>(store);
+ shader.collisionBox = std::make_unique<CollisionBoxShader>(store);
+ shader.circle = std::make_unique<CircleShader>(store);
+
+ overdrawShader.plain = std::make_unique<PlainShader>(store, Shader::Overdraw);
+ overdrawShader.outline = std::make_unique<OutlineShader>(store, Shader::Overdraw);
+ overdrawShader.outlinePattern = std::make_unique<OutlinePatternShader>(store, Shader::Overdraw);
+ overdrawShader.line = std::make_unique<LineShader>(store, Shader::Overdraw);
+ overdrawShader.linesdf = std::make_unique<LineSDFShader>(store, Shader::Overdraw);
+ overdrawShader.linepattern = std::make_unique<LinepatternShader>(store, Shader::Overdraw);
+ overdrawShader.pattern = std::make_unique<PatternShader>(store, Shader::Overdraw);
+ overdrawShader.icon = std::make_unique<IconShader>(store, Shader::Overdraw);
+ overdrawShader.raster = std::make_unique<RasterShader>(store, Shader::Overdraw);
+ overdrawShader.sdfGlyph = std::make_unique<SDFShader>(store, Shader::Overdraw);
+ overdrawShader.sdfIcon = std::make_unique<SDFShader>(store, Shader::Overdraw);
+ overdrawShader.circle = std::make_unique<CircleShader>(store, Shader::Overdraw);
// Reset GL values
+ config.setDirty();
config.reset();
}
@@ -91,7 +106,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
spriteAtlas = style.spriteAtlas.get();
lineAtlas = style.lineAtlas.get();
- RenderData renderData = style.getRenderData();
+ RenderData renderData = style.getRenderData(frame.debugOptions);
const std::vector<RenderItem>& order = renderData.order;
const std::set<Source*>& sources = renderData.sources;
const Color& background = renderData.backgroundColor;
@@ -118,6 +133,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
MBGL_DEBUG_GROUP("upload");
tileStencilBuffer.upload(store);
+ rasterBoundsBuffer.upload(store);
tileBorderBuffer.upload(store);
spriteAtlas->upload(store);
lineAtlas->upload(store);
@@ -143,10 +159,15 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
config.depthTest = GL_FALSE;
config.depthMask = GL_TRUE;
config.colorMask = { GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE };
- if (frame.debugOptions & MapDebugOptions::Wireframe) {
- config.clearColor = { 0.0f, 0.0f, 0.0f, 1.0f };
+
+ if (isOverdraw()) {
+ config.blend = GL_TRUE;
+ config.blendFunc = { GL_CONSTANT_COLOR, GL_ONE };
+ const float overdraw = 1.0f / 8.0f;
+ config.blendColor = { overdraw, overdraw, overdraw, 0.0f };
+ config.clearColor = Color::black();
} else {
- config.clearColor = { background[0], background[1], background[2], background[3] };
+ config.clearColor = background;
}
config.clearStencil = 0;
config.clearDepth = 1;
@@ -161,11 +182,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
// Update all clipping IDs.
algorithm::ClipIDGenerator generator;
for (const auto& source : sources) {
- if (source->type == SourceType::Vector || source->type == SourceType::GeoJSON ||
- source->type == SourceType::Annotations) {
- source->updateClipIDs(generator);
- }
- source->updateMatrices(projMatrix, state);
+ source->baseImpl->startRender(generator, projMatrix, state);
}
drawClippingMasks(generator.getStencils());
@@ -206,7 +223,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
// When only rendering layers via the stylesheet, it's possible that we don't
// ever visit a tile during rendering.
for (const auto& source : sources) {
- source->finishRender(*this);
+ source->baseImpl->finishRender(*this);
}
}
@@ -246,7 +263,9 @@ void Painter::renderPass(RenderPass pass_,
if (!layer.baseImpl->hasRenderPass(pass))
continue;
- if (pass == RenderPass::Translucent) {
+ if (isOverdraw()) {
+ config.blend = GL_TRUE;
+ } else if (pass == RenderPass::Translucent) {
config.blendFunc.reset();
config.blend = GL_TRUE;
} else {
@@ -310,4 +329,4 @@ void Painter::setDepthSublayer(int n) {
config.depthRange = { nearDepth, farDepth };
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index 25627a8d7a..03885ed49e 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -27,12 +27,12 @@
namespace mbgl {
-class Tile;
+class RenderTile;
class SpriteAtlas;
class GlyphAtlas;
class LineAtlas;
struct FrameData;
-class TileData;
+class Tile;
class DebugBucket;
class FillBucket;
@@ -53,15 +53,13 @@ class CircleShader;
class PatternShader;
class IconShader;
class RasterShader;
-class SDFGlyphShader;
-class SDFIconShader;
class CollisionBoxShader;
struct ClipID;
namespace util {
class ObjectStore;
-}
+} // namespace util
namespace style {
class Style;
@@ -72,7 +70,7 @@ class CircleLayer;
class SymbolLayer;
class RasterLayer;
class BackgroundLayer;
-}
+} // namespace style
struct FrameData {
std::array<uint16_t, 2> framebufferSize;
@@ -93,14 +91,14 @@ public:
SpriteAtlas& annotationSpriteAtlas);
// Renders debug information for a tile.
- void renderTileDebug(const Tile& tile);
+ void renderTileDebug(const RenderTile&);
// Renders the red debug frame around a tile, visualizing its perimeter.
void renderDebugFrame(const mat4 &matrix);
void renderClipMasks();
- void renderDebugText(TileData&, const mat4&);
+ void renderDebugText(Tile&, const mat4&);
void renderFill(FillBucket&, const style::FillLayer&, const UnwrappedTileID&, const mat4&);
void renderLine(LineBucket&, const style::LineLayer&, const UnwrappedTileID&, const mat4&);
void renderCircle(CircleBucket&, const style::CircleLayer&, const UnwrappedTileID&, const mat4&);
@@ -137,10 +135,11 @@ private:
float scaleDivisor,
std::array<float, 2> texsize,
SDFShader& sdfShader,
- void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&),
+ void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&, bool),
// Layout
- style::RotationAlignmentType rotationAlignment,
+ style::AlignmentType rotationAlignment,
+ style::AlignmentType pitchAlignment,
float layoutSize,
// Paint
@@ -155,6 +154,8 @@ private:
void setDepthSublayer(int n);
+ bool isOverdraw() const { return frame.debugOptions & MapDebugOptions::Overdraw; }
+
mat4 projMatrix;
mat4 nativeMatrix;
@@ -196,31 +197,55 @@ private:
FrameHistory frameHistory;
- std::unique_ptr<PlainShader> plainShader;
- std::unique_ptr<OutlineShader> outlineShader;
- std::unique_ptr<OutlinePatternShader> outlinePatternShader;
- std::unique_ptr<LineShader> lineShader;
- std::unique_ptr<LineSDFShader> linesdfShader;
- std::unique_ptr<LinepatternShader> linepatternShader;
- std::unique_ptr<PatternShader> patternShader;
- std::unique_ptr<IconShader> iconShader;
- std::unique_ptr<RasterShader> rasterShader;
- std::unique_ptr<SDFGlyphShader> sdfGlyphShader;
- std::unique_ptr<SDFIconShader> sdfIconShader;
- std::unique_ptr<CollisionBoxShader> collisionBoxShader;
- std::unique_ptr<CircleShader> circleShader;
+ struct {
+ std::unique_ptr<PlainShader> plain;
+ std::unique_ptr<OutlineShader> outline;
+ std::unique_ptr<OutlinePatternShader> outlinePattern;
+ std::unique_ptr<LineShader> line;
+ std::unique_ptr<LineSDFShader> linesdf;
+ std::unique_ptr<LinepatternShader> linepattern;
+ std::unique_ptr<PatternShader> pattern;
+ std::unique_ptr<IconShader> icon;
+ std::unique_ptr<RasterShader> raster;
+ std::unique_ptr<SDFShader> sdfGlyph;
+ std::unique_ptr<SDFShader> sdfIcon;
+ std::unique_ptr<CollisionBoxShader> collisionBox;
+ std::unique_ptr<CircleShader> circle;
+ } shader;
+
+ struct {
+ std::unique_ptr<PlainShader> plain;
+ std::unique_ptr<OutlineShader> outline;
+ std::unique_ptr<OutlinePatternShader> outlinePattern;
+ std::unique_ptr<LineShader> line;
+ std::unique_ptr<LineSDFShader> linesdf;
+ std::unique_ptr<LinepatternShader> linepattern;
+ std::unique_ptr<PatternShader> pattern;
+ std::unique_ptr<IconShader> icon;
+ std::unique_ptr<RasterShader> raster;
+ std::unique_ptr<SDFShader> sdfGlyph;
+ std::unique_ptr<SDFShader> sdfIcon;
+ std::unique_ptr<CircleShader> circle;
+ } overdrawShader;
// Set up the stencil quad we're using to generate the stencil mask.
- StaticVertexBuffer tileStencilBuffer = {
+ StaticVertexBuffer tileStencilBuffer {
// top left triangle
- { 0, 0 },
- { util::EXTENT, 0 },
- { 0, util::EXTENT },
+ {{ 0, 0 }},
+ {{ util::EXTENT, 0 }},
+ {{ 0, util::EXTENT }},
// bottom right triangle
- { util::EXTENT, 0 },
- { 0, util::EXTENT },
- { util::EXTENT, util::EXTENT },
+ {{ util::EXTENT, 0 }},
+ {{ 0, util::EXTENT }},
+ {{ util::EXTENT, util::EXTENT }},
+ };
+
+ StaticRasterVertexBuffer rasterBoundsBuffer {
+ {{ 0, 0, 0, 0 }},
+ {{ util::EXTENT, 0, 32767, 0 }},
+ {{ 0, util::EXTENT, 0, 32767 }},
+ {{ util::EXTENT, util::EXTENT, 32767, 32767 }},
};
VertexArrayObject coveringPlainArray;
@@ -228,13 +253,18 @@ private:
VertexArrayObject backgroundPatternArray;
VertexArrayObject backgroundArray;
+ VertexArrayObject coveringPlainOverdrawArray;
+ VertexArrayObject coveringRasterOverdrawArray;
+ VertexArrayObject backgroundPatternOverdrawArray;
+ VertexArrayObject backgroundOverdrawArray;
+
// Set up the tile boundary lines we're using to draw the tile outlines.
- StaticVertexBuffer tileBorderBuffer = {
- { 0, 0 },
- { util::EXTENT, 0 },
- { util::EXTENT, util::EXTENT },
- { 0, util::EXTENT },
- { 0, 0 },
+ StaticVertexBuffer tileBorderBuffer {
+ {{ 0, 0 }},
+ {{ util::EXTENT, 0 }},
+ {{ util::EXTENT, util::EXTENT }},
+ {{ 0, util::EXTENT }},
+ {{ 0, 0 }},
};
VertexArrayObject tileBorderArray;
diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp
index 07e5821ce8..6c47bb08fb 100644
--- a/src/mbgl/renderer/painter_background.cpp
+++ b/src/mbgl/renderer/painter_background.cpp
@@ -21,8 +21,11 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
optional<SpriteAtlasPosition> imagePosA;
optional<SpriteAtlasPosition> imagePosB;
- bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe;
- isPatterned &= !wireframe;
+ const bool overdraw = isOverdraw();
+ auto& patternShader = overdraw ? *overdrawShader.pattern : *shader.pattern;
+ auto& plainShader = overdraw ? *overdrawShader.plain : *shader.plain;
+ auto& arrayBackgroundPattern = overdraw ? backgroundPatternOverdrawArray : backgroundPatternArray;
+ auto& arrayBackground = overdraw ? backgroundOverdrawArray : backgroundArray;
if (isPatterned) {
imagePosA = spriteAtlas->getPosition(properties.backgroundPattern.value.from, true);
@@ -31,29 +34,24 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
if (!imagePosA || !imagePosB)
return;
- config.program = patternShader->getID();
- patternShader->u_matrix = identityMatrix;
- patternShader->u_pattern_tl_a = (*imagePosA).tl;
- patternShader->u_pattern_br_a = (*imagePosA).br;
- patternShader->u_pattern_tl_b = (*imagePosB).tl;
- patternShader->u_pattern_br_b = (*imagePosB).br;
- patternShader->u_mix = properties.backgroundPattern.value.t;
- patternShader->u_opacity = properties.backgroundOpacity;
+ config.program = patternShader.getID();
+ patternShader.u_matrix = identityMatrix;
+ patternShader.u_pattern_tl_a = imagePosA->tl;
+ patternShader.u_pattern_br_a = imagePosA->br;
+ patternShader.u_pattern_tl_b = imagePosB->tl;
+ patternShader.u_pattern_br_b = imagePosB->br;
+ patternShader.u_mix = properties.backgroundPattern.value.t;
+ patternShader.u_opacity = properties.backgroundOpacity;
spriteAtlas->bind(true, store);
- backgroundPatternArray.bind(*patternShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
+ arrayBackgroundPattern.bind(patternShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
} else {
- if (wireframe) {
- plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
- plainShader->u_opacity = 1.0f;
- } else {
- plainShader->u_color = properties.backgroundColor;
- plainShader->u_opacity = properties.backgroundOpacity;
- }
+ config.program = plainShader.getID();
+ plainShader.u_color = properties.backgroundColor;
+ plainShader.u_opacity = properties.backgroundOpacity;
- config.program = plainShader->getID();
- backgroundArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
+ arrayBackground.bind(plainShader, tileStencilBuffer, BUFFER_OFFSET(0), store);
}
config.stencilTest = GL_FALSE;
@@ -62,52 +60,30 @@ void Painter::renderBackground(const BackgroundLayer& layer) {
config.depthMask = GL_FALSE;
setDepthSublayer(0);
- auto tileIDs = util::tileCover(state, state.getIntegerZoom());
-
- for (auto& id : tileIDs) {
- mat4 vtxMatrix;
- state.matrixFor(vtxMatrix, id);
- matrix::multiply(vtxMatrix, projMatrix, vtxMatrix);
+ for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) {
+ mat4 vertexMatrix;
+ state.matrixFor(vertexMatrix, tileID);
+ matrix::multiply(vertexMatrix, projMatrix, vertexMatrix);
if (isPatterned) {
- patternShader->u_matrix = vtxMatrix;
-
- std::array<int, 2> imageSizeScaledA = {{
- (int)((*imagePosA).size[0] * properties.backgroundPattern.value.fromScale),
- (int)((*imagePosA).size[1] * properties.backgroundPattern.value.fromScale)
- }};
- std::array<int, 2> imageSizeScaledB = {{
- (int)((*imagePosB).size[0] * properties.backgroundPattern.value.toScale),
- (int)((*imagePosB).size[1] * properties.backgroundPattern.value.toScale)
- }};
-
- patternShader->u_patternscale_a = {{
- 1.0f / id.pixelsToTileUnits(imageSizeScaledA[0], state.getIntegerZoom()),
- 1.0f / id.pixelsToTileUnits(imageSizeScaledA[1], state.getIntegerZoom())
- }};
- patternShader->u_patternscale_b = {{
- 1.0f / id.pixelsToTileUnits(imageSizeScaledB[0], state.getIntegerZoom()),
- 1.0f / id.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom())
- }};
-
- float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * id.canonical.x) /
- (float)imageSizeScaledA[0];
- float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * id.canonical.y) /
- (float)imageSizeScaledA[1];
-
- float offsetBx = (std::fmod(util::tileSize, imageSizeScaledB[0]) * id.canonical.x) /
- (float)imageSizeScaledB[0];
- float offsetBy = (std::fmod(util::tileSize, imageSizeScaledB[1]) * id.canonical.y) /
- (float)imageSizeScaledB[1];
-
- patternShader->u_offset_a = std::array<float, 2>{{offsetAx, offsetAy}};
- patternShader->u_offset_b = std::array<float, 2>{{offsetBx, offsetBy}};
+ patternShader.u_matrix = vertexMatrix;
+ patternShader.u_pattern_size_a = imagePosA->size;
+ patternShader.u_pattern_size_b = imagePosB->size;
+ patternShader.u_scale_a = properties.backgroundPattern.value.fromScale;
+ patternShader.u_scale_b = properties.backgroundPattern.value.toScale;
+ patternShader.u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
+
+ GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
+ GLint pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
+ GLint pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
+ patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
+ patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
} else {
- plainShader->u_matrix = vtxMatrix;
+ plainShader.u_matrix = vertexMatrix;
}
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)tileStencilBuffer.index()));
}
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp
index 9f2cd17f7f..e36019463a 100644
--- a/src/mbgl/renderer/painter_circle.cpp
+++ b/src/mbgl/renderer/painter_circle.cpp
@@ -27,23 +27,19 @@ void Painter::renderCircle(CircleBucket& bucket,
mat4 vtxMatrix = translatedMatrix(matrix, properties.circleTranslate, tileID,
properties.circleTranslateAnchor);
- // Antialiasing factor: this is a minimum blur distance that serves as
- // a faux-antialiasing for the circle. since blur is a ratio of the circle's
- // size and the intent is to keep the blur at roughly 1px, the two
- // are inversely related.
- float antialiasing = 1 / frame.pixelRatio / properties.circleRadius;
-
- config.program = circleShader->getID();
-
- circleShader->u_matrix = vtxMatrix;
- circleShader->u_extrude_scale = extrudeScale;
- circleShader->u_devicepixelratio = frame.pixelRatio;
- circleShader->u_color = properties.circleColor;
- circleShader->u_radius = properties.circleRadius;
- circleShader->u_blur = std::max<float>(properties.circleBlur, antialiasing);
- circleShader->u_opacity = properties.circleOpacity;
-
- bucket.drawCircles(*circleShader, store);
-}
+ auto& circleShader = isOverdraw() ? *overdrawShader.circle : *shader.circle;
+
+ config.program = circleShader.getID();
+ circleShader.u_matrix = vtxMatrix;
+ circleShader.u_extrude_scale = extrudeScale;
+ circleShader.u_devicepixelratio = frame.pixelRatio;
+ circleShader.u_color = properties.circleColor;
+ circleShader.u_radius = properties.circleRadius;
+ circleShader.u_blur = properties.circleBlur;
+ circleShader.u_opacity = properties.circleOpacity;
+
+ bucket.drawCircles(circleShader, store);
}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp
index e6ce1a040e..4f03ec4fb3 100644
--- a/src/mbgl/renderer/painter_clipping.cpp
+++ b/src/mbgl/renderer/painter_clipping.cpp
@@ -5,16 +5,20 @@
#include <mbgl/util/string.hpp>
#include <mbgl/gl/debugging.hpp>
-using namespace mbgl;
+namespace mbgl {
void Painter::drawClippingMasks(const std::map<UnwrappedTileID, ClipID>& stencils) {
MBGL_DEBUG_GROUP("clipping masks");
+ const bool overdraw = isOverdraw();
+ auto& plainShader = overdraw ? *overdrawShader.plain : *shader.plain;
+ auto& arrayCoveringPlain = overdraw ? coveringPlainOverdrawArray : coveringPlainArray;
+
mat4 matrix;
const GLuint mask = 0b11111111;
- config.program = plainShader->getID();
+ config.program = plainShader.getID();
config.stencilOp.reset();
config.stencilTest = GL_TRUE;
config.depthTest = GL_FALSE;
@@ -22,7 +26,7 @@ void Painter::drawClippingMasks(const std::map<UnwrappedTileID, ClipID>& stencil
config.colorMask = { GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE };
config.stencilMask = mask;
- coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET_0, store);
+ arrayCoveringPlain.bind(plainShader, tileStencilBuffer, BUFFER_OFFSET_0, store);
for (const auto& stencil : stencils) {
const auto& id = stencil.first;
@@ -31,10 +35,12 @@ void Painter::drawClippingMasks(const std::map<UnwrappedTileID, ClipID>& stencil
MBGL_DEBUG_GROUP(std::string{ "mask: " } + util::toString(id));
state.matrixFor(matrix, id);
matrix::multiply(matrix, projMatrix, matrix);
- plainShader->u_matrix = matrix;
+ plainShader.u_matrix = matrix;
const GLint ref = (GLint)(clip.reference.to_ulong());
config.stencilFunc = { GL_ALWAYS, ref, mask };
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)tileStencilBuffer.index()));
}
}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index b55a3c1628..f0b29ebf24 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -1,22 +1,23 @@
#include <mbgl/renderer/painter.hpp>
#include <mbgl/renderer/debug_bucket.hpp>
+#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/tile/tile.hpp>
-#include <mbgl/tile/tile_data.hpp>
#include <mbgl/shader/plain_shader.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/gl/debugging.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/gl_values.hpp>
#include <mbgl/gl/gl_helper.hpp>
+#include <mbgl/util/color.hpp>
-using namespace mbgl;
+namespace mbgl {
-void Painter::renderTileDebug(const Tile& tile) {
+void Painter::renderTileDebug(const RenderTile& tile) {
MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(tile.id));
if (frame.debugOptions != MapDebugOptions::NoDebug) {
setClipping(tile.clip);
if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) {
- renderDebugText(tile.data, tile.matrix);
+ renderDebugText(tile.tile, tile.matrix);
}
if (frame.debugOptions & MapDebugOptions::TileBorders) {
renderDebugFrame(tile.matrix);
@@ -24,39 +25,41 @@ void Painter::renderTileDebug(const Tile& tile) {
}
}
-void Painter::renderDebugText(TileData& tileData, const mat4 &matrix) {
+void Painter::renderDebugText(Tile& tile, const mat4 &matrix) {
MBGL_DEBUG_GROUP("debug text");
config.depthTest = GL_FALSE;
- if (!tileData.debugBucket || tileData.debugBucket->renderable != tileData.isRenderable() ||
- tileData.debugBucket->complete != tileData.isComplete() ||
- !(tileData.debugBucket->modified == tileData.modified) ||
- !(tileData.debugBucket->expires == tileData.expires) ||
- tileData.debugBucket->debugMode != frame.debugOptions) {
- tileData.debugBucket = std::make_unique<DebugBucket>(
- tileData.id, tileData.isRenderable(), tileData.isComplete(), tileData.modified,
- tileData.expires, frame.debugOptions);
+ if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() ||
+ tile.debugBucket->complete != tile.isComplete() ||
+ !(tile.debugBucket->modified == tile.modified) ||
+ !(tile.debugBucket->expires == tile.expires) ||
+ tile.debugBucket->debugMode != frame.debugOptions) {
+ tile.debugBucket = std::make_unique<DebugBucket>(
+ tile.id, tile.isRenderable(), tile.isComplete(), tile.modified,
+ tile.expires, frame.debugOptions);
}
- config.program = plainShader->getID();
- plainShader->u_matrix = matrix;
+ auto& plainShader = *shader.plain;
+ config.program = plainShader.getID();
+ plainShader.u_matrix = matrix;
+ plainShader.u_opacity = 1.0f;
// Draw white outline
- plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
+ plainShader.u_color = Color::white();
config.lineWidth = 4.0f * frame.pixelRatio;
- tileData.debugBucket->drawLines(*plainShader, store);
+ tile.debugBucket->drawLines(plainShader, store);
#ifndef GL_ES_VERSION_2_0
// Draw line "end caps"
MBGL_CHECK_ERROR(glPointSize(2));
- tileData.debugBucket->drawPoints(*plainShader, store);
+ tile.debugBucket->drawPoints(plainShader, store);
#endif
// Draw black text.
- plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
+ plainShader.u_color = Color::black();
config.lineWidth = 2.0f * frame.pixelRatio;
- tileData.debugBucket->drawLines(*plainShader, store);
+ tile.debugBucket->drawLines(plainShader, store);
config.depthFunc.reset();
config.depthTest = GL_TRUE;
@@ -72,12 +75,14 @@ void Painter::renderDebugFrame(const mat4 &matrix) {
config.stencilOp.reset();
config.stencilTest = GL_TRUE;
- config.program = plainShader->getID();
- plainShader->u_matrix = matrix;
+ auto& plainShader = *shader.plain;
+ config.program = plainShader.getID();
+ plainShader.u_matrix = matrix;
+ plainShader.u_opacity = 1.0f;
// draw tile outline
- tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET_0, store);
- plainShader->u_color = {{ 1.0f, 0.0f, 0.0f, 1.0f }};
+ tileBorderArray.bind(plainShader, tileBorderBuffer, BUFFER_OFFSET_0, store);
+ plainShader.u_color = { 1.0f, 0.0f, 0.0f, 1.0f };
config.lineWidth = 4.0f * frame.pixelRatio;
MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index()));
}
@@ -117,3 +122,5 @@ void Painter::renderClipMasks() {
MBGL_CHECK_ERROR(glDrawPixels(fbSize[0], fbSize[1], GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels.get()));
#endif // GL_ES_VERSION_2_0
}
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp
index 4c6ad1ba0f..2b90f6d351 100644
--- a/src/mbgl/renderer/painter_fill.cpp
+++ b/src/mbgl/renderer/painter_fill.cpp
@@ -7,6 +7,7 @@
#include <mbgl/shader/outlinepattern_shader.hpp>
#include <mbgl/shader/pattern_shader.hpp>
#include <mbgl/shader/plain_shader.hpp>
+#include <mbgl/util/convert.hpp>
namespace mbgl {
@@ -17,185 +18,160 @@ void Painter::renderFill(FillBucket& bucket,
const UnwrappedTileID& tileID,
const mat4& matrix) {
const FillPaintProperties& properties = layer.impl->paint;
- mat4 vtxMatrix =
+ mat4 vertexMatrix =
translatedMatrix(matrix, properties.fillTranslate, tileID, properties.fillTranslateAnchor);
- Color fill_color = properties.fillColor;
+ Color fillColor = properties.fillColor;
float opacity = properties.fillOpacity;
- Color stroke_color = properties.fillOutlineColor;
- if (stroke_color[3] < 0) {
- stroke_color = fill_color;
+ Color strokeColor = properties.fillOutlineColor;
+ bool isOutlineColorDefined = strokeColor.a >= 0;
+ if (!isOutlineColorDefined) {
+ strokeColor = fillColor;
}
+ auto worldSize = util::convert<GLfloat>(frame.framebufferSize);
+
bool pattern = !properties.fillPattern.value.from.empty();
- bool outline = properties.fillAntialias && !pattern && stroke_color != fill_color;
- bool fringeline = properties.fillAntialias && !pattern && stroke_color == fill_color;
-
- bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe;
- if (wireframe) {
- fill_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
- stroke_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
- opacity = 1.0f;
- pattern = false;
- outline = true;
- fringeline = true;
- }
+ bool outline = properties.fillAntialias && !pattern && isOutlineColorDefined;
+ bool fringeline = properties.fillAntialias && !pattern && !isOutlineColorDefined;
config.stencilOp.reset();
config.stencilTest = GL_TRUE;
config.depthFunc.reset();
config.depthTest = GL_TRUE;
config.depthMask = GL_TRUE;
+ config.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio!
+
+ const bool overdraw = isOverdraw();
+ auto& outlineShader = overdraw ? *overdrawShader.outline : *shader.outline;
+ auto& patternShader = overdraw ? *overdrawShader.pattern : *shader.pattern;
+ auto& outlinePatternShader = overdraw ? *overdrawShader.outlinePattern : *shader.outlinePattern;
+ auto& plainShader = overdraw ? *overdrawShader.plain : *shader.plain;
// Because we're drawing top-to-bottom, and we update the stencil mask
// befrom, we have to draw the outline first (!)
if (outline && pass == RenderPass::Translucent) {
- config.program = outlineShader->getID();
- outlineShader->u_matrix = vtxMatrix;
- config.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio!
+ config.program = outlineShader.getID();
+ outlineShader.u_matrix = vertexMatrix;
- outlineShader->u_outline_color = stroke_color;
- outlineShader->u_opacity = opacity;
+ outlineShader.u_outline_color = strokeColor;
+ outlineShader.u_opacity = opacity;
// Draw the entire line
- outlineShader->u_world = {{
- static_cast<float>(frame.framebufferSize[0]),
- static_cast<float>(frame.framebufferSize[1])
- }};
- setDepthSublayer(0);
- bucket.drawVertices(*outlineShader, store);
+ outlineShader.u_world = worldSize;
+ if (isOutlineColorDefined) {
+ // If we defined a different color for the fill outline, we are
+ // going to ignore the bits in 0x07 and just care about the global
+ // clipping mask.
+ setDepthSublayer(2); // OK
+ } else {
+ // Otherwise, we only want to drawFill the antialiased parts that are
+ // *outside* the current shape. This is important in case the fill
+ // or stroke color is translucent. If we wouldn't clip to outside
+ // the current shape, some pixels from the outline stroke overlapped
+ // the (non-antialiased) fill.
+ setDepthSublayer(0); // OK
+ }
+ bucket.drawVertices(outlineShader, store, overdraw);
}
if (pattern) {
- optional<SpriteAtlasPosition> posA = spriteAtlas->getPosition(properties.fillPattern.value.from, true);
- optional<SpriteAtlasPosition> posB = spriteAtlas->getPosition(properties.fillPattern.value.to, true);
+ optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(properties.fillPattern.value.from, true);
+ optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(properties.fillPattern.value.to, true);
// Image fill.
- if (pass == RenderPass::Translucent && posA && posB) {
- config.program = patternShader->getID();
- patternShader->u_matrix = vtxMatrix;
- patternShader->u_pattern_tl_a = (*posA).tl;
- patternShader->u_pattern_br_a = (*posA).br;
- patternShader->u_pattern_tl_b = (*posB).tl;
- patternShader->u_pattern_br_b = (*posB).br;
- patternShader->u_opacity = properties.fillOpacity;
- patternShader->u_image = 0;
- patternShader->u_mix = properties.fillPattern.value.t;
-
- std::array<int, 2> imageSizeScaledA = {{
- (int)((*posA).size[0] * properties.fillPattern.value.fromScale),
- (int)((*posA).size[1] * properties.fillPattern.value.fromScale)
- }};
- std::array<int, 2> imageSizeScaledB = {{
- (int)((*posB).size[0] * properties.fillPattern.value.toScale),
- (int)((*posB).size[1] * properties.fillPattern.value.toScale)
- }};
-
- patternShader->u_patternscale_a = {
- { 1.0f / tileID.pixelsToTileUnits(imageSizeScaledA[0], state.getIntegerZoom()),
- 1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom()) }
- };
- patternShader->u_patternscale_b = {
- { 1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[0], state.getIntegerZoom()),
- 1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom()) }
- };
-
- float offsetAx = (std::fmod(util::tileSize, imageSizeScaledA[0]) * tileID.canonical.x) /
- (float)imageSizeScaledA[0];
- float offsetAy = (std::fmod(util::tileSize, imageSizeScaledA[1]) * tileID.canonical.y) /
- (float)imageSizeScaledA[1];
-
- float offsetBx = (std::fmod(util::tileSize, imageSizeScaledB[0]) * tileID.canonical.x) /
- (float)imageSizeScaledB[0];
- float offsetBy = (std::fmod(util::tileSize, imageSizeScaledB[1]) * tileID.canonical.y) /
- (float)imageSizeScaledB[1];
-
- patternShader->u_offset_a = std::array<float, 2>{{offsetAx, offsetAy}};
- patternShader->u_offset_b = std::array<float, 2>{{offsetBx, offsetBy}};
+ if (pass == RenderPass::Translucent && imagePosA && imagePosB) {
+ config.program = patternShader.getID();
+ patternShader.u_matrix = vertexMatrix;
+ patternShader.u_pattern_tl_a = imagePosA->tl;
+ patternShader.u_pattern_br_a = imagePosA->br;
+ patternShader.u_pattern_tl_b = imagePosB->tl;
+ patternShader.u_pattern_br_b = imagePosB->br;
+ patternShader.u_opacity = properties.fillOpacity;
+ patternShader.u_image = 0;
+ patternShader.u_mix = properties.fillPattern.value.t;
+ patternShader.u_pattern_size_a = imagePosA->size;
+ patternShader.u_pattern_size_b = imagePosB->size;
+ patternShader.u_scale_a = properties.fillPattern.value.fromScale;
+ patternShader.u_scale_b = properties.fillPattern.value.toScale;
+ patternShader.u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
+
+ GLint tileSizeAtNearestZoom = util::tileSize * state.zoomScale(state.getIntegerZoom() - tileID.canonical.z);
+ GLint pixelX = tileSizeAtNearestZoom * (tileID.canonical.x + tileID.wrap * state.zoomScale(tileID.canonical.z));
+ GLint pixelY = tileSizeAtNearestZoom * tileID.canonical.y;
+ patternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
+ patternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
config.activeTexture = GL_TEXTURE0;
spriteAtlas->bind(true, store);
// Draw the actual triangles into the color & stencil buffer.
setDepthSublayer(0);
- bucket.drawElements(*patternShader, store);
-
- if (properties.fillAntialias && stroke_color == fill_color) {
- config.program = outlinePatternShader->getID();
- outlinePatternShader->u_matrix = vtxMatrix;
- config.lineWidth = 2.0f;
+ bucket.drawElements(patternShader, store, overdraw);
+
+ if (properties.fillAntialias && !isOutlineColorDefined) {
+ config.program = outlinePatternShader.getID();
+ outlinePatternShader.u_matrix = vertexMatrix;
+
+ outlinePatternShader.u_pattern_tl_a = imagePosA->tl;
+ outlinePatternShader.u_pattern_br_a = imagePosA->br;
+ outlinePatternShader.u_pattern_tl_b = imagePosB->tl;
+ outlinePatternShader.u_pattern_br_b = imagePosB->br;
+ outlinePatternShader.u_opacity = properties.fillOpacity;
+ outlinePatternShader.u_image = 0;
+ outlinePatternShader.u_mix = properties.fillPattern.value.t;
+ outlinePatternShader.u_pattern_size_a = imagePosA->size;
+ outlinePatternShader.u_pattern_size_b = imagePosB->size;
+ outlinePatternShader.u_scale_a = properties.fillPattern.value.fromScale;
+ outlinePatternShader.u_scale_b = properties.fillPattern.value.toScale;
+ outlinePatternShader.u_tile_units_to_pixels = 1.0f / tileID.pixelsToTileUnits(1.0f, state.getIntegerZoom());
+ outlinePatternShader.u_pixel_coord_upper = {{ float(pixelX >> 16), float(pixelY >> 16) }};
+ outlinePatternShader.u_pixel_coord_lower = {{ float(pixelX & 0xFFFF), float(pixelY & 0xFFFF) }};
// Draw the entire line
- outlinePatternShader->u_world = {{
- static_cast<float>(frame.framebufferSize[0]),
- static_cast<float>(frame.framebufferSize[1])
- }};
-
- outlinePatternShader->u_pattern_tl_a = (*posA).tl;
- outlinePatternShader->u_pattern_br_a = (*posA).br;
- outlinePatternShader->u_pattern_tl_b = (*posB).tl;
- outlinePatternShader->u_pattern_br_b = (*posB).br;
- outlinePatternShader->u_opacity = properties.fillOpacity;
- outlinePatternShader->u_image = 0;
- outlinePatternShader->u_mix = properties.fillPattern.value.t;
-
- outlinePatternShader->u_patternscale_a = {{
- 1.0f / tileID.pixelsToTileUnits(imageSizeScaledA[0], state.getIntegerZoom()),
- 1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom())
- }};
- outlinePatternShader->u_patternscale_b = {{
- 1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[0], state.getIntegerZoom()),
- 1.0f / tileID.pixelsToTileUnits(imageSizeScaledB[1], state.getIntegerZoom())
- }};
-
- outlinePatternShader->u_offset_a = std::array<float, 2>{{offsetAx, offsetAy}};
- outlinePatternShader->u_offset_b = std::array<float, 2>{{offsetBx, offsetBy}};
+ outlinePatternShader.u_world = worldSize;
config.activeTexture = GL_TEXTURE0;
spriteAtlas->bind(true, store);
setDepthSublayer(2);
- bucket.drawVertices(*outlinePatternShader, store);
+ bucket.drawVertices(outlinePatternShader, store, overdraw);
}
}
- } else if (!wireframe) {
+ } else {
// No image fill.
- if ((fill_color[3] >= 1.0f && opacity >= 1.0f) == (pass == RenderPass::Opaque)) {
+ if ((fillColor.a >= 1.0f && opacity >= 1.0f) == (pass == RenderPass::Opaque)) {
// Only draw the fill when it's either opaque and we're drawing opaque
// fragments or when it's translucent and we're drawing translucent
// fragments
// Draw filling rectangle.
- config.program = plainShader->getID();
- plainShader->u_matrix = vtxMatrix;
- plainShader->u_color = fill_color;
- plainShader->u_opacity = opacity;
+ config.program = plainShader.getID();
+ plainShader.u_matrix = vertexMatrix;
+ plainShader.u_color = fillColor;
+ plainShader.u_opacity = opacity;
// Draw the actual triangles into the color & stencil buffer.
setDepthSublayer(1);
- bucket.drawElements(*plainShader, store);
+ bucket.drawElements(plainShader, store, overdraw);
}
}
// Because we're drawing top-to-bottom, and we update the stencil mask
// below, we have to draw the outline first (!)
if (fringeline && pass == RenderPass::Translucent) {
- config.program = outlineShader->getID();
- outlineShader->u_matrix = vtxMatrix;
- config.lineWidth = 2.0f; // This is always fixed and does not depend on the pixelRatio!
+ config.program = outlineShader.getID();
+ outlineShader.u_matrix = vertexMatrix;
- outlineShader->u_outline_color = fill_color;
- outlineShader->u_opacity = opacity;
+ outlineShader.u_outline_color = fillColor;
+ outlineShader.u_opacity = opacity;
// Draw the entire line
- outlineShader->u_world = {{
- static_cast<float>(frame.framebufferSize[0]),
- static_cast<float>(frame.framebufferSize[1])
- }};
+ outlineShader.u_world = worldSize;
setDepthSublayer(2);
- bucket.drawVertices(*outlineShader, store);
+ bucket.drawVertices(outlineShader, store, overdraw);
}
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 26041a8165..ab552d7ef9 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -33,17 +33,10 @@ void Painter::renderLine(LineBucket& bucket,
// Retina devices need a smaller distance to avoid aliasing.
float antialiasing = 1.0 / frame.pixelRatio;
- bool wireframe = frame.debugOptions & MapDebugOptions::Wireframe;
-
float blur = properties.lineBlur + antialiasing;
- Color color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
- float opacity = 1.0f;
- if (!wireframe) {
- color = properties.lineColor;
- opacity = properties.lineOpacity;
- }
-
+ const Color color = properties.lineColor;
+ const float opacity = properties.lineOpacity;
const float ratio = 1.0 / tileID.pixelsToTileUnits(1.0, state.getZoom());
mat2 antialiasingMatrix;
@@ -53,27 +46,31 @@ void Painter::renderLine(LineBucket& bucket,
// calculate how much longer the real world distance is at the top of the screen
// than at the middle of the screen.
- float topedgelength = std::sqrt(std::pow(state.getHeight(), 2) / 4 * (1 + std::pow(state.getAltitude(), 2)));
+ float topedgelength = std::sqrt(std::pow(state.getHeight(), 2.0f) / 4.0f * (1.0f + std::pow(state.getAltitude(), 2.0f)));
float x = state.getHeight() / 2.0f * std::tan(state.getPitch());
- float extra = (topedgelength + x) / topedgelength - 1;
+ float extra = (topedgelength + x) / topedgelength - 1.0f;
mat4 vtxMatrix =
translatedMatrix(matrix, properties.lineTranslate, tileID, properties.lineTranslateAnchor);
setDepthSublayer(0);
- if (!properties.lineDasharray.value.from.empty()) {
+ const bool overdraw = isOverdraw();
+ auto& linesdfShader = overdraw ? *overdrawShader.linesdf : *shader.linesdf;
+ auto& linepatternShader = overdraw ? *overdrawShader.linepattern : *shader.linepattern;
+ auto& lineShader = overdraw ? *overdrawShader.line : *shader.line;
- config.program = linesdfShader->getID();
+ if (!properties.lineDasharray.value.from.empty()) {
+ config.program = linesdfShader.getID();
- linesdfShader->u_matrix = vtxMatrix;
- linesdfShader->u_linewidth = properties.lineWidth / 2;
- linesdfShader->u_gapwidth = properties.lineGapWidth / 2;
- linesdfShader->u_antialiasing = antialiasing / 2;
- linesdfShader->u_ratio = ratio;
- linesdfShader->u_blur = blur;
- linesdfShader->u_color = color;
- linesdfShader->u_opacity = opacity;
+ linesdfShader.u_matrix = vtxMatrix;
+ linesdfShader.u_linewidth = properties.lineWidth / 2;
+ linesdfShader.u_gapwidth = properties.lineGapWidth / 2;
+ linesdfShader.u_antialiasing = antialiasing / 2;
+ linesdfShader.u_ratio = ratio;
+ linesdfShader.u_blur = blur;
+ linesdfShader.u_color = color;
+ linesdfShader.u_opacity = opacity;
LinePatternPos posA = lineAtlas->getDashPosition(properties.lineDasharray.value.from, layout.lineCap == LineCapType::Round, store);
LinePatternPos posB = lineAtlas->getDashPosition(properties.lineDasharray.value.to, layout.lineCap == LineCapType::Round, store);
@@ -86,82 +83,82 @@ void Painter::renderLine(LineBucket& bucket,
float scaleXB = 1.0 / tileID.pixelsToTileUnits(widthB, state.getIntegerZoom());
float scaleYB = -posB.height / 2.0;
- linesdfShader->u_patternscale_a = {{ scaleXA, scaleYA }};
- linesdfShader->u_tex_y_a = posA.y;
- linesdfShader->u_patternscale_b = {{ scaleXB, scaleYB }};
- linesdfShader->u_tex_y_b = posB.y;
- linesdfShader->u_sdfgamma = lineAtlas->width / (std::min(widthA, widthB) * 256.0 * frame.pixelRatio) / 2;
- linesdfShader->u_mix = properties.lineDasharray.value.t;
- linesdfShader->u_extra = extra;
- linesdfShader->u_offset = -properties.lineOffset;
- linesdfShader->u_antialiasingmatrix = antialiasingMatrix;
-
- linesdfShader->u_image = 0;
+ linesdfShader.u_patternscale_a = {{ scaleXA, scaleYA }};
+ linesdfShader.u_tex_y_a = posA.y;
+ linesdfShader.u_patternscale_b = {{ scaleXB, scaleYB }};
+ linesdfShader.u_tex_y_b = posB.y;
+ linesdfShader.u_sdfgamma = lineAtlas->width / (std::min(widthA, widthB) * 256.0 * frame.pixelRatio) / 2;
+ linesdfShader.u_mix = properties.lineDasharray.value.t;
+ linesdfShader.u_extra = extra;
+ linesdfShader.u_offset = -properties.lineOffset;
+ linesdfShader.u_antialiasingmatrix = antialiasingMatrix;
+
+ linesdfShader.u_image = 0;
config.activeTexture = GL_TEXTURE0;
lineAtlas->bind(store);
- bucket.drawLineSDF(*linesdfShader, store);
+ bucket.drawLineSDF(linesdfShader, store, overdraw);
} else if (!properties.linePattern.value.from.empty()) {
optional<SpriteAtlasPosition> imagePosA = spriteAtlas->getPosition(properties.linePattern.value.from, true);
optional<SpriteAtlasPosition> imagePosB = spriteAtlas->getPosition(properties.linePattern.value.to, true);
-
+
if (!imagePosA || !imagePosB)
return;
- config.program = linepatternShader->getID();
+ config.program = linepatternShader.getID();
- linepatternShader->u_matrix = vtxMatrix;
- linepatternShader->u_linewidth = properties.lineWidth / 2;
- linepatternShader->u_gapwidth = properties.lineGapWidth / 2;
- linepatternShader->u_antialiasing = antialiasing / 2;
- linepatternShader->u_ratio = ratio;
- linepatternShader->u_blur = blur;
+ linepatternShader.u_matrix = vtxMatrix;
+ linepatternShader.u_linewidth = properties.lineWidth / 2;
+ linepatternShader.u_gapwidth = properties.lineGapWidth / 2;
+ linepatternShader.u_antialiasing = antialiasing / 2;
+ linepatternShader.u_ratio = ratio;
+ linepatternShader.u_blur = blur;
- linepatternShader->u_pattern_size_a = {{
+ linepatternShader.u_pattern_size_a = {{
tileID.pixelsToTileUnits((*imagePosA).size[0] * properties.linePattern.value.fromScale, state.getIntegerZoom()),
(*imagePosA).size[1]
}};
- linepatternShader->u_pattern_tl_a = (*imagePosA).tl;
- linepatternShader->u_pattern_br_a = (*imagePosA).br;
+ linepatternShader.u_pattern_tl_a = (*imagePosA).tl;
+ linepatternShader.u_pattern_br_a = (*imagePosA).br;
- linepatternShader->u_pattern_size_b = {{
+ linepatternShader.u_pattern_size_b = {{
tileID.pixelsToTileUnits((*imagePosB).size[0] * properties.linePattern.value.toScale, state.getIntegerZoom()),
(*imagePosB).size[1]
}};
- linepatternShader->u_pattern_tl_b = (*imagePosB).tl;
- linepatternShader->u_pattern_br_b = (*imagePosB).br;
+ linepatternShader.u_pattern_tl_b = (*imagePosB).tl;
+ linepatternShader.u_pattern_br_b = (*imagePosB).br;
- linepatternShader->u_fade = properties.linePattern.value.t;
- linepatternShader->u_opacity = properties.lineOpacity;
- linepatternShader->u_extra = extra;
- linepatternShader->u_offset = -properties.lineOffset;
- linepatternShader->u_antialiasingmatrix = antialiasingMatrix;
+ linepatternShader.u_fade = properties.linePattern.value.t;
+ linepatternShader.u_opacity = properties.lineOpacity;
+ linepatternShader.u_extra = extra;
+ linepatternShader.u_offset = -properties.lineOffset;
+ linepatternShader.u_antialiasingmatrix = antialiasingMatrix;
- linepatternShader->u_image = 0;
+ linepatternShader.u_image = 0;
config.activeTexture = GL_TEXTURE0;
spriteAtlas->bind(true, store);
- bucket.drawLinePatterns(*linepatternShader, store);
+ bucket.drawLinePatterns(linepatternShader, store, overdraw);
} else {
- config.program = lineShader->getID();
-
- lineShader->u_matrix = vtxMatrix;
- lineShader->u_linewidth = properties.lineWidth / 2;
- lineShader->u_gapwidth = properties.lineGapWidth / 2;
- lineShader->u_antialiasing = antialiasing / 2;
- lineShader->u_ratio = ratio;
- lineShader->u_blur = blur;
- lineShader->u_extra = extra;
- lineShader->u_offset = -properties.lineOffset;
- lineShader->u_antialiasingmatrix = antialiasingMatrix;
-
- lineShader->u_color = color;
- lineShader->u_opacity = opacity;
-
- bucket.drawLines(*lineShader, store);
+ config.program = lineShader.getID();
+
+ lineShader.u_matrix = vtxMatrix;
+ lineShader.u_linewidth = properties.lineWidth / 2;
+ lineShader.u_gapwidth = properties.lineGapWidth / 2;
+ lineShader.u_antialiasing = antialiasing / 2;
+ lineShader.u_ratio = ratio;
+ lineShader.u_blur = blur;
+ lineShader.u_extra = extra;
+ lineShader.u_offset = -properties.lineOffset;
+ lineShader.u_antialiasingmatrix = antialiasingMatrix;
+
+ lineShader.u_color = color;
+ lineShader.u_opacity = opacity;
+
+ bucket.drawLines(lineShader, store, overdraw);
}
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index cce71e8ce2..10b960b37e 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -18,26 +18,35 @@ void Painter::renderRaster(RasterBucket& bucket,
const RasterPaintProperties& properties = layer.impl->paint;
if (bucket.hasData()) {
- config.program = rasterShader->getID();
- rasterShader->u_matrix = matrix;
- rasterShader->u_buffer = 0;
- rasterShader->u_opacity = properties.rasterOpacity;
- rasterShader->u_brightness_low = properties.rasterBrightnessMin;
- rasterShader->u_brightness_high = properties.rasterBrightnessMax;
- rasterShader->u_saturation_factor = saturationFactor(properties.rasterSaturation);
- rasterShader->u_contrast_factor = contrastFactor(properties.rasterContrast);
- rasterShader->u_spin_weights = spinWeights(properties.rasterHueRotate);
+ const bool overdraw = isOverdraw();
+ auto& rasterShader = overdraw ? *overdrawShader.raster : *shader.raster;
+ auto& rasterVAO = overdraw ? coveringRasterOverdrawArray : coveringRasterArray;
+
+ config.program = rasterShader.getID();
+ rasterShader.u_matrix = matrix;
+ rasterShader.u_buffer_scale = 1.0f;
+ rasterShader.u_opacity0 = properties.rasterOpacity;
+ rasterShader.u_opacity1 = 1.0f - properties.rasterOpacity;
+
+ rasterShader.u_brightness_low = properties.rasterBrightnessMin;
+ rasterShader.u_brightness_high = properties.rasterBrightnessMax;
+ rasterShader.u_saturation_factor = saturationFactor(properties.rasterSaturation);
+ rasterShader.u_contrast_factor = contrastFactor(properties.rasterContrast);
+ rasterShader.u_spin_weights = spinWeights(properties.rasterHueRotate);
config.stencilTest = GL_FALSE;
- rasterShader->u_image = 0;
- config.activeTexture = GL_TEXTURE0;
+ rasterShader.u_image0 = 0; // GL_TEXTURE0
+ rasterShader.u_image1 = 1; // GL_TEXTURE1
+ rasterShader.u_tl_parent = {{ 0.0f, 0.0f }};
+ rasterShader.u_scale_parent = 1.0f;
config.depthFunc.reset();
config.depthTest = GL_TRUE;
config.depthMask = GL_FALSE;
setDepthSublayer(0);
- bucket.drawRaster(*rasterShader, tileStencilBuffer, coveringRasterArray, store);
+
+ bucket.drawRaster(rasterShader, rasterBoundsBuffer, rasterVAO, config, store);
}
}
@@ -69,4 +78,4 @@ std::array<float, 3> Painter::spinWeights(float spin) {
return spin_weights;
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 3c453242ae..4559b02778 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -21,10 +21,11 @@ void Painter::renderSDF(SymbolBucket &bucket,
float sdfFontSize,
std::array<float, 2> texsize,
SDFShader& sdfShader,
- void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&),
+ void (SymbolBucket::*drawSDF)(SDFShader&, gl::ObjectStore&, bool),
// Layout
- RotationAlignmentType rotationAlignment,
+ AlignmentType rotationAlignment,
+ AlignmentType pitchAlignment,
float layoutSize,
// Paint
@@ -45,10 +46,11 @@ void Painter::renderSDF(SymbolBucket &bucket,
float scale = fontScale;
std::array<float, 2> exScale = extrudeScale;
- bool alignedWithMap = rotationAlignment == RotationAlignmentType::Map;
+ bool rotateWithMap = rotationAlignment == AlignmentType::Map;
+ bool pitchWithMap = pitchAlignment == AlignmentType::Map;
float gammaScale = 1.0f;
- if (alignedWithMap) {
+ if (pitchWithMap) {
scale *= tileID.pixelsToTileUnits(1, state.getZoom());
exScale.fill(scale);
gammaScale /= std::cos(state.getPitch());
@@ -60,8 +62,12 @@ void Painter::renderSDF(SymbolBucket &bucket,
sdfShader.u_matrix = vtxMatrix;
sdfShader.u_extrude_scale = exScale;
sdfShader.u_texsize = texsize;
- sdfShader.u_skewed = alignedWithMap;
+ sdfShader.u_rotate_with_map = rotateWithMap;
+ sdfShader.u_pitch_with_map = pitchWithMap;
sdfShader.u_texture = 0;
+ sdfShader.u_pitch = state.getPitch() * util::DEG2RAD;
+ sdfShader.u_bearing = -1.0f * state.getAngle();
+ sdfShader.u_aspect_ratio = (state.getWidth() * 1.0f) / (state.getHeight() * 1.0f);
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / layoutSize) / std::log(2);
@@ -82,25 +88,25 @@ void Painter::renderSDF(SymbolBucket &bucket,
// We're drawing in the translucent pass which is bottom-to-top, so we need
// to draw the halo first.
- if (haloColor[3] > 0.0f && haloWidth > 0.0f) {
+ if (haloColor.a > 0.0f && haloWidth > 0.0f) {
sdfShader.u_gamma = (haloBlur * blurOffset / fontScale / sdfPx + gamma) * gammaScale;
sdfShader.u_color = haloColor;
sdfShader.u_opacity = opacity;
sdfShader.u_buffer = (haloOffset - haloWidth / fontScale) / sdfPx;
setDepthSublayer(0);
- (bucket.*drawSDF)(sdfShader, store);
+ (bucket.*drawSDF)(sdfShader, store, isOverdraw());
}
// Then, we draw the text/icon over the halo
- if (color[3] > 0.0f) {
+ if (color.a > 0.0f) {
sdfShader.u_gamma = gamma * gammaScale;
sdfShader.u_color = color;
sdfShader.u_opacity = opacity;
sdfShader.u_buffer = (256.0f - 64.0f) / 256.0f;
setDepthSublayer(1);
- (bucket.*drawSDF)(sdfShader, store);
+ (bucket.*drawSDF)(sdfShader, store, isOverdraw());
}
}
@@ -135,7 +141,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
}
if (bucket.hasIconData()) {
- if (layout.iconRotationAlignment == RotationAlignmentType::Map) {
+ if (layout.iconRotationAlignment == AlignmentType::Map) {
config.depthFunc.reset();
config.depthTest = GL_TRUE;
} else {
@@ -145,7 +151,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
bool sdf = bucket.sdfIcons;
const float angleOffset =
- layout.iconRotationAlignment == RotationAlignmentType::Map
+ layout.iconRotationAlignment == AlignmentType::Map
? state.getAngle()
: 0;
@@ -154,7 +160,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
SpriteAtlas* activeSpriteAtlas = layer.impl->spriteAtlas;
const bool iconScaled = fontScale != 1 || frame.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear;
- const bool iconTransformed = layout.iconRotationAlignment == RotationAlignmentType::Map || angleOffset != 0 || state.getPitch() != 0;
+ const bool iconTransformed = layout.iconRotationAlignment == AlignmentType::Map || angleOffset != 0 || state.getPitch() != 0;
config.activeTexture = GL_TEXTURE0;
activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed, store);
@@ -164,9 +170,12 @@ void Painter::renderSymbol(SymbolBucket& bucket,
matrix,
1.0f,
{{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }},
- *sdfIconShader,
+ isOverdraw() ? *overdrawShader.sdfIcon : *shader.sdfIcon,
&SymbolBucket::drawIcons,
layout.iconRotationAlignment,
+ // icon-pitch-alignment is not yet implemented
+ // and we simply inherit the rotation alignment
+ layout.iconRotationAlignment,
layout.iconSize,
paint.iconOpacity,
paint.iconColor,
@@ -182,7 +191,7 @@ void Painter::renderSymbol(SymbolBucket& bucket,
float scale = fontScale;
std::array<float, 2> exScale = extrudeScale;
- const bool alignedWithMap = layout.iconRotationAlignment == RotationAlignmentType::Map;
+ const bool alignedWithMap = layout.iconRotationAlignment == AlignmentType::Map;
if (alignedWithMap) {
scale *= tileID.pixelsToTileUnits(1, state.getZoom());
exScale.fill(scale);
@@ -190,29 +199,32 @@ void Painter::renderSymbol(SymbolBucket& bucket,
exScale = {{ exScale[0] * scale, exScale[1] * scale }};
}
- config.program = iconShader->getID();
- iconShader->u_matrix = vtxMatrix;
- iconShader->u_extrude_scale = exScale;
- iconShader->u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }};
- iconShader->u_skewed = alignedWithMap;
- iconShader->u_texture = 0;
+ const bool overdraw = isOverdraw();
+ auto& iconShader = overdraw ? *overdrawShader.icon : *shader.icon;
+
+ config.program = iconShader.getID();
+ iconShader.u_matrix = vtxMatrix;
+ iconShader.u_extrude_scale = exScale;
+ iconShader.u_texsize = {{ float(activeSpriteAtlas->getWidth()) / 4.0f, float(activeSpriteAtlas->getHeight()) / 4.0f }};
+ iconShader.u_rotate_with_map = alignedWithMap;
+ iconShader.u_texture = 0;
// adjust min/max zooms for variable font sies
float zoomAdjust = std::log(fontSize / layout.iconSize) / std::log(2);
- iconShader->u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
- iconShader->u_opacity = paint.iconOpacity;
+ iconShader.u_zoom = (state.getZoom() - zoomAdjust) * 10; // current zoom level
+ iconShader.u_opacity = paint.iconOpacity;
config.activeTexture = GL_TEXTURE1;
frameHistory.bind(store);
- iconShader->u_fadetexture = 1;
+ iconShader.u_fadetexture = 1;
setDepthSublayer(0);
- bucket.drawIcons(*iconShader, store);
+ bucket.drawIcons(iconShader, store, overdraw);
}
}
if (bucket.hasTextData()) {
- if (layout.textRotationAlignment == RotationAlignmentType::Map) {
+ if (layout.textRotationAlignment == AlignmentType::Map) {
config.depthFunc.reset();
config.depthTest = GL_TRUE;
} else {
@@ -227,9 +239,10 @@ void Painter::renderSymbol(SymbolBucket& bucket,
matrix,
24.0f,
{{ float(glyphAtlas->width) / 4, float(glyphAtlas->height) / 4 }},
- *sdfGlyphShader,
+ isOverdraw() ? *overdrawShader.sdfGlyph : *shader.sdfGlyph,
&SymbolBucket::drawGlyphs,
layout.textRotationAlignment,
+ layout.textPitchAlignment,
layout.textSize,
paint.textOpacity,
paint.textColor,
@@ -245,20 +258,21 @@ void Painter::renderSymbol(SymbolBucket& bucket,
config.stencilOp.reset();
config.stencilTest = GL_TRUE;
- config.program = collisionBoxShader->getID();
- collisionBoxShader->u_matrix = matrix;
+ auto& collisionBoxShader = *shader.collisionBox;
+ config.program = collisionBoxShader.getID();
+ collisionBoxShader.u_matrix = matrix;
// TODO: This was the overscaled z instead of the canonical z.
- collisionBoxShader->u_scale = std::pow(2, state.getZoom() - tileID.canonical.z);
- collisionBoxShader->u_zoom = state.getZoom() * 10;
- collisionBoxShader->u_maxzoom = (tileID.canonical.z + 1) * 10;
+ collisionBoxShader.u_scale = std::pow(2, state.getZoom() - tileID.canonical.z);
+ collisionBoxShader.u_zoom = state.getZoom() * 10;
+ collisionBoxShader.u_maxzoom = (tileID.canonical.z + 1) * 10;
config.lineWidth = 1.0f;
setDepthSublayer(0);
- bucket.drawCollisionBoxes(*collisionBoxShader, store);
+ bucket.drawCollisionBoxes(collisionBoxShader, store);
}
config.activeTexture = GL_TEXTURE0;
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp
index 39f8dacd92..1cf6f2c413 100644
--- a/src/mbgl/renderer/raster_bucket.cpp
+++ b/src/mbgl/renderer/raster_bucket.cpp
@@ -7,10 +7,6 @@ namespace mbgl {
using namespace style;
-RasterBucket::RasterBucket(gl::TexturePool& texturePool)
-: raster(texturePool) {
-}
-
void RasterBucket::upload(gl::ObjectStore& store) {
if (hasData()) {
raster.upload(store);
@@ -29,10 +25,17 @@ void RasterBucket::setImage(PremultipliedImage image) {
raster.load(std::move(image));
}
-void RasterBucket::drawRaster(RasterShader& shader, StaticVertexBuffer &vertices, VertexArrayObject &array, gl::ObjectStore& store) {
- raster.bind(true, store);
+void RasterBucket::drawRaster(RasterShader& shader,
+ StaticRasterVertexBuffer& vertices,
+ VertexArrayObject& array,
+ gl::Config& config,
+ gl::ObjectStore& store) {
+ config.activeTexture = GL_TEXTURE0;
+ raster.bind(store, Raster::Scaling::Linear);
+ config.activeTexture = GL_TEXTURE1;
+ raster.bind(store, Raster::Scaling::Linear);
array.bind(shader, vertices, BUFFER_OFFSET_0, store);
- MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLES, 0, (GLsizei)vertices.index()));
+ MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, (GLsizei)vertices.index()));
}
bool RasterBucket::hasData() const {
@@ -43,4 +46,4 @@ bool RasterBucket::needsClipping() const {
return false;
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp
index 93331755fb..35b1bc2b51 100644
--- a/src/mbgl/renderer/raster_bucket.hpp
+++ b/src/mbgl/renderer/raster_bucket.hpp
@@ -2,17 +2,16 @@
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/util/raster.hpp>
+#include <mbgl/gl/gl_config.hpp>
namespace mbgl {
class RasterShader;
-class StaticVertexBuffer;
+class StaticRasterVertexBuffer;
class VertexArrayObject;
class RasterBucket : public Bucket {
public:
- RasterBucket(gl::TexturePool&);
-
void upload(gl::ObjectStore&) override;
void render(Painter&, const style::Layer&, const UnwrappedTileID&, const mat4&) override;
bool hasData() const override;
@@ -20,7 +19,7 @@ public:
void setImage(PremultipliedImage);
- void drawRaster(RasterShader&, StaticVertexBuffer&, VertexArrayObject&, gl::ObjectStore&);
+ void drawRaster(RasterShader&, StaticRasterVertexBuffer&, VertexArrayObject&, gl::Config&, gl::ObjectStore&);
Raster raster;
};
diff --git a/src/mbgl/renderer/render_item.hpp b/src/mbgl/renderer/render_item.hpp
index 6c97b66bd1..82ea897047 100644
--- a/src/mbgl/renderer/render_item.hpp
+++ b/src/mbgl/renderer/render_item.hpp
@@ -7,30 +7,30 @@
namespace mbgl {
-class Tile;
+class RenderTile;
class Bucket;
namespace style {
class Layer;
class Source;
-}
+} // namespace style
class RenderItem {
public:
RenderItem(const style::Layer& layer_,
- const Tile* tile_ = nullptr,
+ const RenderTile* tile_ = nullptr,
Bucket* bucket_ = nullptr)
: tile(tile_), bucket(bucket_), layer(layer_) {
}
- const Tile* const tile;
+ const RenderTile* const tile;
Bucket* const bucket;
const style::Layer& layer;
};
class RenderData {
public:
- Color backgroundColor = {{ 0, 0, 0, 0 }};
+ Color backgroundColor;
std::set<style::Source*> sources;
std::vector<RenderItem> order;
};
diff --git a/src/mbgl/renderer/render_pass.hpp b/src/mbgl/renderer/render_pass.hpp
index e31383b7cf..93edac2039 100644
--- a/src/mbgl/renderer/render_pass.hpp
+++ b/src/mbgl/renderer/render_pass.hpp
@@ -12,16 +12,16 @@ enum class RenderPass : uint8_t {
Translucent = 1 << 1,
};
-constexpr inline RenderPass operator|(RenderPass a, RenderPass b) {
- return static_cast<RenderPass>(mbgl::underlying_type(a) | mbgl::underlying_type(b));
+constexpr RenderPass operator|(RenderPass a, RenderPass b) {
+ return RenderPass(mbgl::underlying_type(a) | mbgl::underlying_type(b));
}
-inline RenderPass operator|=(RenderPass& a, RenderPass b) {
+constexpr RenderPass& operator|=(RenderPass& a, RenderPass b) {
return (a = a | b);
}
-constexpr inline RenderPass operator&(RenderPass a, RenderPass b) {
- return static_cast<RenderPass>(mbgl::underlying_type(a) & mbgl::underlying_type(b));
+constexpr RenderPass operator&(RenderPass a, RenderPass b) {
+ return RenderPass(mbgl::underlying_type(a) & mbgl::underlying_type(b));
}
} // namespace mbgl
diff --git a/src/mbgl/renderer/render_tile.cpp b/src/mbgl/renderer/render_tile.cpp
new file mode 100644
index 0000000000..513515ddf0
--- /dev/null
+++ b/src/mbgl/renderer/render_tile.cpp
@@ -0,0 +1,5 @@
+#include <mbgl/renderer/render_tile.hpp>
+
+namespace mbgl {
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/render_tile.hpp b/src/mbgl/renderer/render_tile.hpp
new file mode 100644
index 0000000000..55a605280e
--- /dev/null
+++ b/src/mbgl/renderer/render_tile.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/ptr.hpp>
+#include <mbgl/util/clip_id.hpp>
+
+namespace mbgl {
+
+class Tile;
+
+class RenderTile {
+public:
+ RenderTile(UnwrappedTileID id_, Tile& tile_) : id(std::move(id_)), tile(tile_) {}
+ RenderTile(const RenderTile&) = delete;
+ RenderTile(RenderTile&&) = default;
+ RenderTile& operator=(const RenderTile&) = delete;
+ RenderTile& operator=(RenderTile&&) = default;
+
+ const UnwrappedTileID id;
+ Tile& tile;
+ ClipID clip;
+ mat4 matrix;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index f4e55432c1..66d2f04700 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -1,7 +1,7 @@
#include <mbgl/renderer/symbol_bucket.hpp>
#include <mbgl/style/filter_evaluator.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/sprite/sprite_store.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
@@ -51,23 +51,23 @@ SymbolInstance::SymbolInstance(Anchor& anchor, const GeometryCoordinates& line,
// Create the quad used for rendering the icon.
iconQuads(addToBuffers && shapedIcon ?
- getIconQuads(anchor, shapedIcon, line, layout, iconAlongLine) :
+ getIconQuads(anchor, shapedIcon, line, layout, iconAlongLine, shapedText) :
SymbolQuads()),
// Create the collision features that will be used to check whether this symbol instance can be placed
textCollisionFeature(line, anchor, shapedText, textBoxScale, textPadding, textAlongLine, indexedFeature),
iconCollisionFeature(line, anchor, shapedIcon, iconBoxScale, iconPadding, iconAlongLine, indexedFeature)
- {};
+ {}
-SymbolBucket::SymbolBucket(uint32_t overscaling_, float zoom_, const MapMode mode_, const std::string& bucketName_, const std::string& sourceLayerName_)
+SymbolBucket::SymbolBucket(uint32_t overscaling_, float zoom_, const MapMode mode_, std::string bucketName_, std::string sourceLayerName_)
: overscaling(overscaling_),
zoom(zoom_),
tileSize(util::tileSize * overscaling_),
tilePixelRatio(float(util::EXTENT) / tileSize),
mode(mode_),
- bucketName(bucketName_),
- sourceLayerName(sourceLayerName_) {}
+ bucketName(std::move(bucketName_)),
+ sourceLayerName(std::move(sourceLayerName_)) {}
SymbolBucket::~SymbolBucket() {
// Do not remove. header file only contains forward definitions to unique pointers.
@@ -119,9 +119,7 @@ void SymbolBucket::parseFeatures(const GeometryTileLayer& layer, const Filter& f
const GLsizei featureCount = static_cast<GLsizei>(layer.featureCount());
for (GLsizei i = 0; i < featureCount; i++) {
auto feature = layer.getFeature(i);
-
- FilterEvaluator evaluator(*feature);
- if (!Filter::visit(filter, evaluator))
+ if (!filter(feature->getType(), [&] (const auto& key) { return feature->getValue(key); }))
continue;
SymbolFeature ft;
@@ -284,6 +282,8 @@ void SymbolBucket::addFeatures(uintptr_t tileUID,
}
if ((*image).relativePixelRatio != 1.0f) {
iconsNeedLinear = true;
+ } else if (layout.iconRotate != 0) {
+ iconsNeedLinear = true;
}
}
}
@@ -314,10 +314,10 @@ void SymbolBucket::addFeature(const GeometryCollection &lines,
const float iconPadding = layout.iconPadding * tilePixelRatio;
const float textMaxAngle = layout.textMaxAngle * util::DEG2RAD;
const bool textAlongLine =
- layout.textRotationAlignment == RotationAlignmentType::Map &&
+ layout.textRotationAlignment == AlignmentType::Map &&
layout.symbolPlacement == SymbolPlacementType::Line;
const bool iconAlongLine =
- layout.iconRotationAlignment == RotationAlignmentType::Map &&
+ layout.iconRotationAlignment == AlignmentType::Map &&
layout.symbolPlacement == SymbolPlacementType::Line;
const bool mayOverlap = layout.textAllowOverlap || layout.iconAllowOverlap ||
layout.textIgnorePlacement || layout.iconIgnorePlacement;
@@ -370,7 +370,7 @@ void SymbolBucket::addFeature(const GeometryCollection &lines,
}
}
}
-
+
bool SymbolBucket::anchorIsTooClose(const std::u32string &text, const float repeatDistance, Anchor &anchor) {
if (compareText.find(text) == compareText.end()) {
compareText.emplace(text, Anchors());
@@ -394,10 +394,10 @@ void SymbolBucket::placeFeatures(CollisionTile& collisionTile) {
// create the bufers used for rendering.
const bool textAlongLine =
- layout.textRotationAlignment == RotationAlignmentType::Map &&
+ layout.textRotationAlignment == AlignmentType::Map &&
layout.symbolPlacement == SymbolPlacementType::Line;
const bool iconAlongLine =
- layout.iconRotationAlignment == RotationAlignmentType::Map &&
+ layout.iconRotationAlignment == AlignmentType::Map &&
layout.symbolPlacement == SymbolPlacementType::Line;
const bool mayOverlap = layout.textAllowOverlap || layout.iconAllowOverlap ||
@@ -495,7 +495,7 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
const auto &anchorPoint = symbol.anchorPoint;
// drop upside down versions of glyphs
- const float a = std::fmod(symbol.angle + placementAngle + M_PI, M_PI * 2);
+ const float a = std::fmod(symbol.anchorAngle + placementAngle + M_PI, M_PI * 2);
if (keepUpright && alongLine && (a <= M_PI / 2 || a > M_PI * 3 / 2)) continue;
@@ -521,15 +521,18 @@ void SymbolBucket::addSymbols(Buffer &buffer, const SymbolQuads &symbols, float
auto &triangleGroup = *buffer.groups.back();
GLsizei triangleIndex = triangleGroup.vertex_length;
+ // Encode angle of glyph
+ uint8_t glyphAngle = std::round((symbol.glyphAngle / (M_PI * 2)) * 256);
+
// coordinates (2 triangles)
buffer.vertices.add(anchorPoint.x, anchorPoint.y, tl.x, tl.y, tex.x, tex.y, minZoom,
- maxZoom, placementZoom);
+ maxZoom, placementZoom, glyphAngle);
buffer.vertices.add(anchorPoint.x, anchorPoint.y, tr.x, tr.y, tex.x + tex.w, tex.y,
- minZoom, maxZoom, placementZoom);
+ minZoom, maxZoom, placementZoom, glyphAngle);
buffer.vertices.add(anchorPoint.x, anchorPoint.y, bl.x, bl.y, tex.x, tex.y + tex.h,
- minZoom, maxZoom, placementZoom);
+ minZoom, maxZoom, placementZoom, glyphAngle);
buffer.vertices.add(anchorPoint.x, anchorPoint.y, br.x, br.y, tex.x + tex.w, tex.y + tex.h,
- minZoom, maxZoom, placementZoom);
+ minZoom, maxZoom, placementZoom, glyphAngle);
// add the two triangles, referencing the four coordinates we just inserted.
buffer.triangles.add(triangleIndex + 0, triangleIndex + 1, triangleIndex + 2);
@@ -598,39 +601,39 @@ void SymbolBucket::swapRenderData() {
}
}
-void SymbolBucket::drawGlyphs(SDFShader& shader, gl::ObjectStore& store) {
+void SymbolBucket::drawGlyphs(SDFShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte *vertex_index = BUFFER_OFFSET_0;
GLbyte *elements_index = BUFFER_OFFSET_0;
auto& text = renderData->text;
for (auto &group : text.groups) {
assert(group);
- group->array[0].bind(shader, text.vertices, text.triangles, vertex_index, store);
+ group->array[overdraw ? 1 : 0].bind(shader, text.vertices, text.triangles, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * text.vertices.itemSize;
elements_index += group->elements_length * text.triangles.itemSize;
}
}
-void SymbolBucket::drawIcons(SDFShader& shader, gl::ObjectStore& store) {
+void SymbolBucket::drawIcons(SDFShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte *vertex_index = BUFFER_OFFSET_0;
GLbyte *elements_index = BUFFER_OFFSET_0;
auto& icon = renderData->icon;
for (auto &group : icon.groups) {
assert(group);
- group->array[0].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
+ group->array[overdraw ? 1 : 0].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * icon.vertices.itemSize;
elements_index += group->elements_length * icon.triangles.itemSize;
}
}
-void SymbolBucket::drawIcons(IconShader& shader, gl::ObjectStore& store) {
+void SymbolBucket::drawIcons(IconShader& shader, gl::ObjectStore& store, bool overdraw) {
GLbyte *vertex_index = BUFFER_OFFSET_0;
GLbyte *elements_index = BUFFER_OFFSET_0;
auto& icon = renderData->icon;
for (auto &group : icon.groups) {
assert(group);
- group->array[1].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
+ group->array[overdraw ? 3 : 2].bind(shader, icon.vertices, icon.triangles, vertex_index, store);
MBGL_CHECK_ERROR(glDrawElements(GL_TRIANGLES, group->elements_length * 3, GL_UNSIGNED_SHORT, elements_index));
vertex_index += group->vertex_length * icon.vertices.itemSize;
elements_index += group->elements_length * icon.triangles.itemSize;
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index 314d44bdee..b899d52767 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/geometry/vao.hpp>
#include <mbgl/geometry/elements_buffer.hpp>
@@ -61,12 +61,12 @@ class SymbolInstance {
};
class SymbolBucket : public Bucket {
- typedef ElementGroup<1> TextElementGroup;
- typedef ElementGroup<2> IconElementGroup;
+ typedef ElementGroup<2> TextElementGroup;
+ typedef ElementGroup<4> IconElementGroup;
typedef ElementGroup<1> CollisionBoxElementGroup;
public:
- SymbolBucket(uint32_t overscaling, float zoom, const MapMode, const std::string& bucketName_, const std::string& sourceLayerName_);
+ SymbolBucket(uint32_t overscaling, float zoom, const MapMode, std::string bucketName_, std::string sourceLayerName_);
~SymbolBucket() override;
void upload(gl::ObjectStore&) override;
@@ -82,9 +82,9 @@ public:
GlyphAtlas&,
GlyphStore&);
- void drawGlyphs(SDFShader&, gl::ObjectStore&);
- void drawIcons(SDFShader&, gl::ObjectStore&);
- void drawIcons(IconShader&, gl::ObjectStore&);
+ void drawGlyphs(SDFShader&, gl::ObjectStore&, bool overdraw);
+ void drawIcons(SDFShader&, gl::ObjectStore&, bool overdraw);
+ void drawIcons(IconShader&, gl::ObjectStore&, bool overdraw);
void drawCollisionBoxes(CollisionBoxShader&, gl::ObjectStore&);
void parseFeatures(const GeometryTileLayer&, const style::Filter&);
@@ -98,7 +98,7 @@ private:
const size_t index);
bool anchorIsTooClose(const std::u32string &text, const float repeatDistance, Anchor &anchor);
std::map<std::u32string, std::vector<Anchor>> compareText;
-
+
void addToDebugBuffers(CollisionTile &collisionTile);
void swapRenderData() override;
diff --git a/src/mbgl/shader/circle_shader.cpp b/src/mbgl/shader/circle_shader.cpp
index 2865769ee2..b19dbeba68 100644
--- a/src/mbgl/shader/circle_shader.cpp
+++ b/src/mbgl/shader/circle_shader.cpp
@@ -3,15 +3,18 @@
#include <mbgl/shader/circle.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-CircleShader::CircleShader(gl::ObjectStore& store)
- : Shader("circle", shaders::circle::vertex, shaders::circle::fragment, store) {
+CircleShader::CircleShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::circle::name,
+ shaders::circle::vertex,
+ shaders::circle::fragment,
+ store, defines) {
}
void CircleShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 4, offset));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/circle_shader.hpp b/src/mbgl/shader/circle_shader.hpp
index cd22d4c9b1..34466ace04 100644
--- a/src/mbgl/shader/circle_shader.hpp
+++ b/src/mbgl/shader/circle_shader.hpp
@@ -2,19 +2,20 @@
#include <mbgl/shader/shader.hpp>
#include <mbgl/shader/uniform.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
class CircleShader : public Shader {
public:
- CircleShader(gl::ObjectStore&);
+ CircleShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
UniformMatrix<4> u_matrix = {"u_matrix", *this};
Uniform<std::array<GLfloat, 2>> u_extrude_scale = {"u_extrude_scale", *this};
Uniform<GLfloat> u_devicepixelratio = {"u_devicepixelratio", *this};
- Uniform<std::array<GLfloat, 4>> u_color = {"u_color", *this};
+ Uniform<Color> u_color = {"u_color", *this};
Uniform<GLfloat> u_radius = {"u_radius", *this};
Uniform<GLfloat> u_blur = {"u_blur", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
diff --git a/src/mbgl/shader/collision_box_shader.cpp b/src/mbgl/shader/collision_box_shader.cpp
index cf4ff81e96..bfee89fac2 100644
--- a/src/mbgl/shader/collision_box_shader.cpp
+++ b/src/mbgl/shader/collision_box_shader.cpp
@@ -3,14 +3,13 @@
#include <mbgl/shader/collisionbox.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
-
-using namespace mbgl;
+namespace mbgl {
CollisionBoxShader::CollisionBoxShader(gl::ObjectStore& store)
- : Shader("collisionbox", shaders::collisionbox::vertex, shaders::collisionbox::fragment, store)
- , a_extrude(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_extrude")))
- , a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
+ : Shader(shaders::collisionbox::name,
+ shaders::collisionbox::vertex,
+ shaders::collisionbox::fragment,
+ store) {
}
void CollisionBoxShader::bind(GLbyte *offset) {
@@ -24,5 +23,6 @@ void CollisionBoxShader::bind(GLbyte *offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 2, GL_UNSIGNED_BYTE, false, stride, offset + 8));
-
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/collision_box_shader.hpp b/src/mbgl/shader/collision_box_shader.hpp
index a9b38a9849..bbd2611ce8 100644
--- a/src/mbgl/shader/collision_box_shader.hpp
+++ b/src/mbgl/shader/collision_box_shader.hpp
@@ -16,10 +16,6 @@ public:
Uniform<GLfloat> u_scale = {"u_scale", *this};
Uniform<GLfloat> u_zoom = {"u_zoom", *this};
Uniform<GLfloat> u_maxzoom = {"u_maxzoom", *this};
-
-protected:
- GLint a_extrude = -1;
- GLint a_data = -1;
};
} // namespace mbgl
diff --git a/src/mbgl/shader/icon_shader.cpp b/src/mbgl/shader/icon_shader.cpp
index 7fb0335dc8..d91fbe2ec0 100644
--- a/src/mbgl/shader/icon_shader.cpp
+++ b/src/mbgl/shader/icon_shader.cpp
@@ -3,15 +3,13 @@
#include <mbgl/shader/icon.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-IconShader::IconShader(gl::ObjectStore& store)
- : Shader("icon", shaders::icon::vertex, shaders::icon::fragment, store)
- , a_offset(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_offset")))
- , a_data1(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data1")))
- , a_data2(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data2"))) {
+IconShader::IconShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::icon::name,
+ shaders::icon::vertex,
+ shaders::icon::fragment,
+ store, defines) {
}
void IconShader::bind(GLbyte* offset) {
@@ -29,3 +27,5 @@ void IconShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data2));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data2, 4, GL_UNSIGNED_BYTE, false, stride, offset + 12));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/icon_shader.hpp b/src/mbgl/shader/icon_shader.hpp
index b8cfcabb10..86c7b8ece0 100644
--- a/src/mbgl/shader/icon_shader.hpp
+++ b/src/mbgl/shader/icon_shader.hpp
@@ -7,7 +7,7 @@ namespace mbgl {
class IconShader : public Shader {
public:
- IconShader(gl::ObjectStore&);
+ IconShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
@@ -16,14 +16,9 @@ public:
Uniform<GLfloat> u_zoom = {"u_zoom", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
Uniform<std::array<GLfloat, 2>> u_texsize = {"u_texsize", *this};
- Uniform<GLint> u_skewed = {"u_skewed", *this};
+ Uniform<GLint> u_rotate_with_map = {"u_rotate_with_map", *this};
Uniform<GLint> u_texture = {"u_texture", *this};
Uniform<GLint> u_fadetexture = {"u_fadetexture", *this};
-
-protected:
- GLint a_offset = -1;
- GLint a_data1 = -1;
- GLint a_data2 = -1;
};
} // namespace mbgl
diff --git a/src/mbgl/shader/line_shader.cpp b/src/mbgl/shader/line_shader.cpp
index f21384082f..8c3ad32d73 100644
--- a/src/mbgl/shader/line_shader.cpp
+++ b/src/mbgl/shader/line_shader.cpp
@@ -3,13 +3,13 @@
#include <mbgl/shader/line.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-LineShader::LineShader(gl::ObjectStore& store)
- : Shader("line", shaders::line::vertex, shaders::line::fragment, store)
- , a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
+LineShader::LineShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::line::name,
+ shaders::line::vertex,
+ shaders::line::fragment,
+ store, defines) {
}
void LineShader::bind(GLbyte* offset) {
@@ -19,3 +19,5 @@ void LineShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 4, GL_UNSIGNED_BYTE, false, 8, offset + 4));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/line_shader.hpp b/src/mbgl/shader/line_shader.hpp
index e0d14094a6..a2cda56314 100644
--- a/src/mbgl/shader/line_shader.hpp
+++ b/src/mbgl/shader/line_shader.hpp
@@ -2,17 +2,18 @@
#include <mbgl/shader/shader.hpp>
#include <mbgl/shader/uniform.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
class LineShader : public Shader {
public:
- LineShader(gl::ObjectStore&);
+ LineShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<std::array<GLfloat, 4>> u_color = {"u_color", *this};
+ Uniform<Color> u_color = {"u_color", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
Uniform<GLfloat> u_ratio = {"u_ratio", *this};
Uniform<GLfloat> u_linewidth = {"u_linewidth", *this};
@@ -22,9 +23,6 @@ public:
Uniform<GLfloat> u_extra = {"u_extra", *this};
Uniform<GLfloat> u_offset = {"u_offset", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
-
-private:
- GLint a_data = -1;
};
diff --git a/src/mbgl/shader/linepattern_shader.cpp b/src/mbgl/shader/linepattern_shader.cpp
index a9923233af..48375dec24 100644
--- a/src/mbgl/shader/linepattern_shader.cpp
+++ b/src/mbgl/shader/linepattern_shader.cpp
@@ -3,13 +3,13 @@
#include <mbgl/shader/linepattern.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-LinepatternShader::LinepatternShader(gl::ObjectStore& store)
- : Shader("linepattern", shaders::linepattern::vertex, shaders::linepattern::fragment, store)
- , a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
+LinepatternShader::LinepatternShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::linepattern::name,
+ shaders::linepattern::vertex,
+ shaders::linepattern::fragment,
+ store, defines) {
}
void LinepatternShader::bind(GLbyte* offset) {
@@ -19,3 +19,5 @@ void LinepatternShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 4, GL_UNSIGNED_BYTE, false, 8, offset + 4));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/linepattern_shader.hpp b/src/mbgl/shader/linepattern_shader.hpp
index c34c1a5292..6c44716d10 100644
--- a/src/mbgl/shader/linepattern_shader.hpp
+++ b/src/mbgl/shader/linepattern_shader.hpp
@@ -7,7 +7,7 @@ namespace mbgl {
class LinepatternShader : public Shader {
public:
- LinepatternShader(gl::ObjectStore&);
+ LinepatternShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
@@ -30,8 +30,6 @@ public:
Uniform<GLfloat> u_offset = {"u_offset", *this};
Uniform<GLint> u_image = {"u_image", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
-
-private:
- GLint a_data = -1;
};
+
} // namespace mbgl
diff --git a/src/mbgl/shader/linesdf_shader.cpp b/src/mbgl/shader/linesdf_shader.cpp
index b316d2562d..8b2e983e0d 100644
--- a/src/mbgl/shader/linesdf_shader.cpp
+++ b/src/mbgl/shader/linesdf_shader.cpp
@@ -3,13 +3,13 @@
#include <mbgl/shader/linesdfpattern.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-LineSDFShader::LineSDFShader(gl::ObjectStore& store)
- : Shader("linesdfpattern", shaders::linesdfpattern::vertex, shaders::linesdfpattern::fragment, store)
- , a_data(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data"))) {
+LineSDFShader::LineSDFShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::linesdfpattern::name,
+ shaders::linesdfpattern::vertex,
+ shaders::linesdfpattern::fragment,
+ store, defines) {
}
void LineSDFShader::bind(GLbyte* offset) {
@@ -19,3 +19,5 @@ void LineSDFShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data, 4, GL_UNSIGNED_BYTE, false, 8, offset + 4));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/linesdf_shader.hpp b/src/mbgl/shader/linesdf_shader.hpp
index 8791f243c0..ce1fe4d17c 100644
--- a/src/mbgl/shader/linesdf_shader.hpp
+++ b/src/mbgl/shader/linesdf_shader.hpp
@@ -2,17 +2,18 @@
#include <mbgl/shader/shader.hpp>
#include <mbgl/shader/uniform.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
class LineSDFShader : public Shader {
public:
- LineSDFShader(gl::ObjectStore&);
+ LineSDFShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<std::array<GLfloat, 4>> u_color = {"u_color", *this};
+ Uniform<Color> u_color = {"u_color", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
Uniform<GLfloat> u_linewidth = {"u_linewidth", *this};
Uniform<GLfloat> u_gapwidth = {"u_gapwidth", *this};
@@ -29,9 +30,6 @@ public:
Uniform<GLfloat> u_extra = {"u_extra", *this};
Uniform<GLfloat> u_offset = {"u_offset", *this};
UniformMatrix<2> u_antialiasingmatrix = {"u_antialiasingmatrix", *this};
-
-private:
- GLint a_data = -1;
};
diff --git a/src/mbgl/shader/outline_shader.cpp b/src/mbgl/shader/outline_shader.cpp
index 58a647f375..58f73d9f44 100644
--- a/src/mbgl/shader/outline_shader.cpp
+++ b/src/mbgl/shader/outline_shader.cpp
@@ -3,15 +3,18 @@
#include <mbgl/shader/outline.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-OutlineShader::OutlineShader(gl::ObjectStore& store)
- : Shader("outline", shaders::outline::vertex, shaders::outline::fragment, store) {
+OutlineShader::OutlineShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::outline::name,
+ shaders::outline::vertex,
+ shaders::outline::fragment,
+ store, defines) {
}
void OutlineShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/outline_shader.hpp b/src/mbgl/shader/outline_shader.hpp
index 25c873b4fe..5840ad2238 100644
--- a/src/mbgl/shader/outline_shader.hpp
+++ b/src/mbgl/shader/outline_shader.hpp
@@ -2,17 +2,18 @@
#include <mbgl/shader/shader.hpp>
#include <mbgl/shader/uniform.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
class OutlineShader : public Shader {
public:
- OutlineShader(gl::ObjectStore&);
+ OutlineShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<std::array<GLfloat, 4>> u_outline_color = {"u_outline_color", *this};
+ Uniform<Color> u_outline_color = {"u_outline_color", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
Uniform<std::array<GLfloat, 2>> u_world = {"u_world", *this};
};
diff --git a/src/mbgl/shader/outlinepattern_shader.cpp b/src/mbgl/shader/outlinepattern_shader.cpp
index 5ffa458a4f..2373a75370 100644
--- a/src/mbgl/shader/outlinepattern_shader.cpp
+++ b/src/mbgl/shader/outlinepattern_shader.cpp
@@ -3,19 +3,18 @@
#include <mbgl/shader/outlinepattern.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-OutlinePatternShader::OutlinePatternShader(gl::ObjectStore& store)
- : Shader(
- "outlinepattern",
- shaders::outlinepattern::vertex, shaders::outlinepattern::fragment,
- store
- ) {
+OutlinePatternShader::OutlinePatternShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::outlinepattern::name,
+ shaders::outlinepattern::vertex,
+ shaders::outlinepattern::fragment,
+ store, defines) {
}
void OutlinePatternShader::bind(GLbyte *offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/outlinepattern_shader.hpp b/src/mbgl/shader/outlinepattern_shader.hpp
index e124923b6f..6869763412 100644
--- a/src/mbgl/shader/outlinepattern_shader.hpp
+++ b/src/mbgl/shader/outlinepattern_shader.hpp
@@ -7,23 +7,26 @@ namespace mbgl {
class OutlinePatternShader : public Shader {
public:
- OutlinePatternShader(gl::ObjectStore&);
+ OutlinePatternShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
- UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
- Uniform<GLfloat> u_opacity = {"u_opacity", *this};
- Uniform<GLfloat> u_mix = {"u_mix", *this};
- Uniform<GLint> u_image = {"u_image", *this};
- Uniform<std::array<GLfloat, 2>> u_patternscale_a = {"u_patternscale_a", *this};
- Uniform<std::array<GLfloat, 2>> u_patternscale_b = {"u_patternscale_b", *this};
- Uniform<std::array<GLfloat, 2>> u_offset_a = {"u_offset_a", *this};
- Uniform<std::array<GLfloat, 2>> u_offset_b = {"u_offset_b", *this};
- Uniform<std::array<GLfloat, 2>> u_world = {"u_world", *this};
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
+ Uniform<GLfloat> u_opacity = {"u_opacity", *this};
+ Uniform<GLfloat> u_mix = {"u_mix", *this};
+ Uniform<GLfloat> u_scale_a = {"u_scale_a", *this};
+ Uniform<GLfloat> u_scale_b = {"u_scale_b", *this};
+ Uniform<GLfloat> u_tile_units_to_pixels = {"u_tile_units_to_pixels", *this};
+ Uniform<GLint> u_image = {"u_image", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_size_a = {"u_pattern_size_a", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_size_b = {"u_pattern_size_b", *this};
+ Uniform<std::array<GLfloat, 2>> u_pixel_coord_upper = {"u_pixel_coord_upper", *this};
+ Uniform<std::array<GLfloat, 2>> u_pixel_coord_lower = {"u_pixel_coord_lower", *this};
+ Uniform<std::array<GLfloat, 2>> u_world = {"u_world", *this};
};
} // namespace mbgl
diff --git a/src/mbgl/shader/pattern_shader.cpp b/src/mbgl/shader/pattern_shader.cpp
index 64a72d1451..5caa892feb 100644
--- a/src/mbgl/shader/pattern_shader.cpp
+++ b/src/mbgl/shader/pattern_shader.cpp
@@ -3,19 +3,18 @@
#include <mbgl/shader/pattern.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-PatternShader::PatternShader(gl::ObjectStore& store)
- : Shader(
- "pattern",
- shaders::pattern::vertex, shaders::pattern::fragment,
- store
- ) {
+PatternShader::PatternShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::pattern::name,
+ shaders::pattern::vertex,
+ shaders::pattern::fragment,
+ store, defines) {
}
void PatternShader::bind(GLbyte *offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/pattern_shader.hpp b/src/mbgl/shader/pattern_shader.hpp
index ae515c1948..ae356fdfb7 100644
--- a/src/mbgl/shader/pattern_shader.hpp
+++ b/src/mbgl/shader/pattern_shader.hpp
@@ -7,22 +7,25 @@ namespace mbgl {
class PatternShader : public Shader {
public:
- PatternShader(gl::ObjectStore&);
+ PatternShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
- UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
- Uniform<std::array<GLfloat, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
- Uniform<GLfloat> u_opacity = {"u_opacity", *this};
- Uniform<GLfloat> u_mix = {"u_mix", *this};
- Uniform<GLint> u_image = {"u_image", *this};
- Uniform<std::array<GLfloat, 2>> u_patternscale_a = {"u_patternscale_a", *this};
- Uniform<std::array<GLfloat, 2>> u_patternscale_b = {"u_patternscale_b", *this};
- Uniform<std::array<GLfloat, 2>> u_offset_a = {"u_offset_a", *this};
- Uniform<std::array<GLfloat, 2>> u_offset_b = {"u_offset_b", *this};
+ UniformMatrix<4> u_matrix = {"u_matrix", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_tl_a = {"u_pattern_tl_a", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_br_a = {"u_pattern_br_a", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_tl_b = {"u_pattern_tl_b", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_br_b = {"u_pattern_br_b", *this};
+ Uniform<GLfloat> u_opacity = {"u_opacity", *this};
+ Uniform<GLfloat> u_mix = {"u_mix", *this};
+ Uniform<GLfloat> u_scale_a = {"u_scale_a", *this};
+ Uniform<GLfloat> u_scale_b = {"u_scale_b", *this};
+ Uniform<GLfloat> u_tile_units_to_pixels = {"u_tile_units_to_pixels", *this};
+ Uniform<GLint> u_image = {"u_image", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_size_a = {"u_pattern_size_a", *this};
+ Uniform<std::array<GLfloat, 2>> u_pattern_size_b = {"u_pattern_size_b", *this};
+ Uniform<std::array<GLfloat, 2>> u_pixel_coord_upper = {"u_pixel_coord_upper", *this};
+ Uniform<std::array<GLfloat, 2>> u_pixel_coord_lower = {"u_pixel_coord_lower", *this};
};
} // namespace mbgl
diff --git a/src/mbgl/shader/plain_shader.cpp b/src/mbgl/shader/plain_shader.cpp
index c030a2d7b3..1309c4f14a 100644
--- a/src/mbgl/shader/plain_shader.cpp
+++ b/src/mbgl/shader/plain_shader.cpp
@@ -3,15 +3,18 @@
#include <mbgl/shader/fill.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-PlainShader::PlainShader(gl::ObjectStore& store)
- : Shader("fill", shaders::fill::vertex, shaders::fill::fragment, store) {
+PlainShader::PlainShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::fill::name,
+ shaders::fill::vertex,
+ shaders::fill::fragment,
+ store, defines) {
}
void PlainShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/plain_shader.hpp b/src/mbgl/shader/plain_shader.hpp
index 7edf4b4b19..a126fa30a9 100644
--- a/src/mbgl/shader/plain_shader.hpp
+++ b/src/mbgl/shader/plain_shader.hpp
@@ -2,17 +2,18 @@
#include <mbgl/shader/shader.hpp>
#include <mbgl/shader/uniform.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
class PlainShader : public Shader {
public:
- PlainShader(gl::ObjectStore&);
+ PlainShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<std::array<GLfloat, 4>> u_color = {"u_color", *this};
+ Uniform<Color> u_color = {"u_color", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
};
diff --git a/src/mbgl/shader/raster_shader.cpp b/src/mbgl/shader/raster_shader.cpp
index e5e290bedd..76723b06e9 100644
--- a/src/mbgl/shader/raster_shader.cpp
+++ b/src/mbgl/shader/raster_shader.cpp
@@ -3,15 +3,23 @@
#include <mbgl/shader/raster.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-RasterShader::RasterShader(gl::ObjectStore& store)
- : Shader("raster", shaders::raster::vertex, shaders::raster::fragment, store) {
+RasterShader::RasterShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::raster::name,
+ shaders::raster::vertex,
+ shaders::raster::fragment,
+ store, defines) {
}
void RasterShader::bind(GLbyte* offset) {
+ const GLint stride = 8;
+
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
- MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, 0, offset));
+ MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, stride, offset));
+
+ MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_texture_pos));
+ MBGL_CHECK_ERROR(glVertexAttribPointer(a_texture_pos, 2, GL_SHORT, false, stride, offset + 4));
}
+
+} // namespace mbgl
diff --git a/src/mbgl/shader/raster_shader.hpp b/src/mbgl/shader/raster_shader.hpp
index ee53385a0b..4b3ba9168b 100644
--- a/src/mbgl/shader/raster_shader.hpp
+++ b/src/mbgl/shader/raster_shader.hpp
@@ -7,19 +7,23 @@ namespace mbgl {
class RasterShader : public Shader {
public:
- RasterShader(gl::ObjectStore&);
+ RasterShader(gl::ObjectStore&, Defines defines = None);
void bind(GLbyte *offset) final;
UniformMatrix<4> u_matrix = {"u_matrix", *this};
- Uniform<GLint> u_image = {"u_image", *this};
- Uniform<GLfloat> u_opacity = {"u_opacity", *this};
- Uniform<GLfloat> u_buffer = {"u_buffer", *this};
+ Uniform<GLint> u_image0 = {"u_image0", *this};
+ Uniform<GLint> u_image1 = {"u_image1", *this};
+ Uniform<GLfloat> u_opacity0 = {"u_opacity0", *this};
+ Uniform<GLfloat> u_opacity1 = {"u_opacity1", *this};
+ Uniform<GLfloat> u_buffer_scale = {"u_buffer_scale", *this};
Uniform<GLfloat> u_brightness_low = {"u_brightness_low", *this};
Uniform<GLfloat> u_brightness_high = {"u_brightness_high", *this};
Uniform<GLfloat> u_saturation_factor = {"u_saturation_factor", *this};
Uniform<GLfloat> u_contrast_factor = {"u_contrast_factor", *this};
Uniform<std::array<GLfloat, 3>> u_spin_weights = {"u_spin_weights", *this};
+ Uniform<std::array<GLfloat, 2>> u_tl_parent = {"u_tl_parent", *this};
+ Uniform<GLfloat> u_scale_parent = {"u_scale_parent", *this};
};
} // namespace mbgl
diff --git a/src/mbgl/shader/sdf_shader.cpp b/src/mbgl/shader/sdf_shader.cpp
index 76ea1e3b4d..24b6f77d68 100644
--- a/src/mbgl/shader/sdf_shader.cpp
+++ b/src/mbgl/shader/sdf_shader.cpp
@@ -3,18 +3,16 @@
#include <mbgl/shader/sdf.fragment.hpp>
#include <mbgl/gl/gl.hpp>
-#include <cstdio>
+namespace mbgl {
-using namespace mbgl;
-
-SDFShader::SDFShader(gl::ObjectStore& store)
- : Shader("sdf", shaders::sdf::vertex, shaders::sdf::fragment, store)
- , a_offset(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_offset")))
- , a_data1(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data1")))
- , a_data2(MBGL_CHECK_ERROR(glGetAttribLocation(getID(), "a_data2"))) {
+SDFShader::SDFShader(gl::ObjectStore& store, Defines defines)
+ : Shader(shaders::sdf::name,
+ shaders::sdf::vertex,
+ shaders::sdf::fragment,
+ store, defines) {
}
-void SDFGlyphShader::bind(GLbyte* offset) {
+void SDFShader::bind(GLbyte* offset) {
const int stride = 16;
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
@@ -30,18 +28,4 @@ void SDFGlyphShader::bind(GLbyte* offset) {
MBGL_CHECK_ERROR(glVertexAttribPointer(a_data2, 4, GL_UNSIGNED_BYTE, false, stride, offset + 12));
}
-void SDFIconShader::bind(GLbyte* offset) {
- const int stride = 16;
-
- MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
- MBGL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_SHORT, false, stride, offset + 0));
-
- MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_offset));
- MBGL_CHECK_ERROR(glVertexAttribPointer(a_offset, 2, GL_SHORT, false, stride, offset + 4));
-
- MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data1));
- MBGL_CHECK_ERROR(glVertexAttribPointer(a_data1, 4, GL_UNSIGNED_BYTE, false, stride, offset + 8));
-
- MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_data2));
- MBGL_CHECK_ERROR(glVertexAttribPointer(a_data2, 4, GL_UNSIGNED_BYTE, false, stride, offset + 12));
-}
+} // namespace mbgl
diff --git a/src/mbgl/shader/sdf_shader.hpp b/src/mbgl/shader/sdf_shader.hpp
index f067c30aeb..f2f79f1cc9 100644
--- a/src/mbgl/shader/sdf_shader.hpp
+++ b/src/mbgl/shader/sdf_shader.hpp
@@ -2,40 +2,30 @@
#include <mbgl/shader/shader.hpp>
#include <mbgl/shader/uniform.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
class SDFShader : public Shader {
public:
- SDFShader(gl::ObjectStore&);
+ SDFShader(gl::ObjectStore&, Defines defines = None);
UniformMatrix<4> u_matrix = {"u_matrix", *this};
Uniform<std::array<GLfloat, 2>> u_extrude_scale = {"u_extrude_scale", *this};
- Uniform<std::array<GLfloat, 4>> u_color = {"u_color", *this};
+ Uniform<Color> u_color = {"u_color", *this};
Uniform<GLfloat> u_opacity = {"u_opacity", *this};
Uniform<std::array<GLfloat, 2>> u_texsize = {"u_texsize", *this};
Uniform<GLfloat> u_buffer = {"u_buffer", *this};
Uniform<GLfloat> u_gamma = {"u_gamma", *this};
Uniform<GLfloat> u_zoom = {"u_zoom", *this};
- Uniform<GLint> u_skewed = {"u_skewed", *this};
+ Uniform<GLfloat> u_pitch = {"u_pitch", *this};
+ Uniform<GLfloat> u_bearing = {"u_bearing", *this};
+ Uniform<GLfloat> u_aspect_ratio = {"u_aspect_ratio", *this};
+ Uniform<GLint> u_rotate_with_map = {"u_rotate_with_map",*this};
+ Uniform<GLint> u_pitch_with_map = {"u_pitch_with_map",*this};
Uniform<GLint> u_texture = {"u_texture", *this};
Uniform<GLint> u_fadetexture = {"u_fadetexture", *this};
-protected:
- GLint a_offset = -1;
- GLint a_data1 = -1;
- GLint a_data2 = -1;
-};
-
-class SDFGlyphShader : public SDFShader {
-public:
- SDFGlyphShader(gl::ObjectStore& store) : SDFShader(store) {}
- void bind(GLbyte *offset) final;
-};
-
-class SDFIconShader : public SDFShader {
-public:
- SDFIconShader(gl::ObjectStore& store) : SDFShader(store) {}
void bind(GLbyte *offset) final;
};
diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp
index 23ea043720..ae36d21740 100644
--- a/src/mbgl/shader/shader.cpp
+++ b/src/mbgl/shader/shader.cpp
@@ -8,12 +8,14 @@
#include <cstring>
#include <cassert>
#include <iostream>
+#include <string>
#include <fstream>
#include <cstdio>
+#include <cassert>
namespace mbgl {
-Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSource, gl::ObjectStore& store)
+Shader::Shader(const char* name_, const char* vertexSource, const char* fragmentSource, gl::ObjectStore& store, Defines defines)
: name(name_)
, program(store.createProgram())
, vertexShader(store.createShader(GL_VERTEX_SHADER))
@@ -21,13 +23,19 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
{
util::stopwatch stopwatch("shader compilation", Event::Shader);
- if (!compileShader(vertexShader, &vertSource)) {
- Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertSource);
+ if (!compileShader(vertexShader, vertexSource)) {
+ Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertexSource);
throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
}
- if (!compileShader(fragmentShader, &fragSource)) {
- Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragSource);
+ std::string fragment(fragmentSource);
+ if (defines & Defines::Overdraw) {
+ assert(fragment.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos);
+ fragment.replace(fragment.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
+ }
+
+ if (!compileShader(fragmentShader, fragment.c_str())) {
+ Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragmentSource);
throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
}
@@ -35,32 +43,37 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
MBGL_CHECK_ERROR(glAttachShader(program.get(), vertexShader.get()));
MBGL_CHECK_ERROR(glAttachShader(program.get(), fragmentShader.get()));
- {
- // Link program
- GLint status;
- MBGL_CHECK_ERROR(glLinkProgram(program.get()));
+ // Bind attribute variables
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_pos, "a_pos"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_extrude, "a_extrude"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_offset, "a_offset"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_data, "a_data"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_data1, "a_data1"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_data2, "a_data2"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_texture_pos, "a_texture_pos"));
- MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status));
- if (status == 0) {
- GLint logLength;
- MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength));
- const auto log = std::make_unique<GLchar[]>(logLength);
- if (logLength > 0) {
- MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get()));
- Log::Error(Event::Shader, "Program failed to link: %s", log.get());
- }
- throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
+ // Link program
+ GLint status;
+ MBGL_CHECK_ERROR(glLinkProgram(program.get()));
+
+ MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status));
+ if (status == 0) {
+ GLint logLength;
+ MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength));
+ const auto log = std::make_unique<GLchar[]>(logLength);
+ if (logLength > 0) {
+ MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get()));
+ Log::Error(Event::Shader, "Program failed to link: %s", log.get());
}
+ throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
}
-
- a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.get(), "a_pos"));
}
-bool Shader::compileShader(gl::UniqueShader& shader, const GLchar *source[]) {
+bool Shader::compileShader(gl::UniqueShader& shader, const GLchar *source) {
GLint status = 0;
- const GLsizei lengths = static_cast<GLsizei>(std::strlen(*source));
- MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, source, &lengths));
+ const GLsizei lengths = static_cast<GLsizei>(std::strlen(source));
+ MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, &source, &lengths));
MBGL_CHECK_ERROR(glCompileShader(shader.get()));
diff --git a/src/mbgl/shader/shader.hpp b/src/mbgl/shader/shader.hpp
index 1cb2a5601f..f7da0c91ab 100644
--- a/src/mbgl/shader/shader.hpp
+++ b/src/mbgl/shader/shader.hpp
@@ -3,15 +3,14 @@
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/object_store.hpp>
#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/optional.hpp>
namespace mbgl {
class Shader : private util::noncopyable {
public:
- Shader(const GLchar *name, const GLchar *vertex, const GLchar *fragment, gl::ObjectStore&);
-
~Shader();
- const GLchar *name;
+ const char* name;
GLuint getID() const {
return program.get();
@@ -19,11 +18,28 @@ public:
virtual void bind(GLbyte *offset) = 0;
+ enum Defines : bool {
+ None = false,
+ Overdraw = true,
+ };
+
protected:
- GLint a_pos = -1;
+ Shader(const char* name_,
+ const char* vertex,
+ const char* fragment,
+ gl::ObjectStore&,
+ Defines defines = Defines::None);
+
+ static constexpr GLint a_pos = 0;
+ static constexpr GLint a_extrude = 1;
+ static constexpr GLint a_offset = 2;
+ static constexpr GLint a_data = 3;
+ static constexpr GLint a_data1 = 4;
+ static constexpr GLint a_data2 = 5;
+ static constexpr GLint a_texture_pos = 6;
private:
- bool compileShader(gl::UniqueShader&, const GLchar *source[]);
+ bool compileShader(gl::UniqueShader&, const GLchar *source);
gl::UniqueProgram program;
gl::UniqueShader vertexShader;
diff --git a/src/mbgl/shader/uniform.cpp b/src/mbgl/shader/uniform.cpp
index d43dd20016..4c7646119a 100644
--- a/src/mbgl/shader/uniform.cpp
+++ b/src/mbgl/shader/uniform.cpp
@@ -1,4 +1,5 @@
#include <mbgl/shader/uniform.hpp>
+#include <mbgl/util/color.hpp>
namespace mbgl {
@@ -28,6 +29,12 @@ void Uniform<std::array<GLfloat, 4>>::bind(const std::array<GLfloat, 4>& t) {
}
template <>
+void Uniform<Color>::bind(const Color& t) {
+ std::array<GLfloat, 4> a = {{ t.r, t.g, t.b, t.a }};
+ MBGL_CHECK_ERROR(glUniform4fv(location, 1, a.data()));
+}
+
+template <>
void UniformMatrix<2>::bind(const std::array<GLfloat, 4>& t) {
MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, t.data()));
}
diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp
index 5d7d01deb3..581bc01ed8 100644
--- a/src/mbgl/sprite/sprite_atlas.cpp
+++ b/src/mbgl/sprite/sprite_atlas.cpp
@@ -11,7 +11,7 @@
#include <cmath>
#include <algorithm>
-using namespace mbgl;
+namespace mbgl {
SpriteAtlas::SpriteAtlas(dimension width_, dimension height_, float pixelRatio_, SpriteStore& store_)
: width(width_),
@@ -243,14 +243,15 @@ void SpriteAtlas::bind(bool linear, gl::ObjectStore& objectStore) {
// pixelWidth, pixelHeight, pixelWidth, pixelHeight);
#endif
}
-};
+}
SpriteAtlas::~SpriteAtlas() = default;
-SpriteAtlas::Holder::Holder(const std::shared_ptr<const SpriteImage>& spriteImage_,
- const Rect<dimension>& pos_)
- : spriteImage(spriteImage_), pos(pos_) {
+SpriteAtlas::Holder::Holder(std::shared_ptr<const SpriteImage> spriteImage_, Rect<dimension> pos_)
+ : spriteImage(std::move(spriteImage_)), pos(std::move(pos_)) {
}
SpriteAtlas::Holder::Holder(Holder&& h) : spriteImage(std::move(h.spriteImage)), pos(h.pos) {
}
+
+} // namespace mbgl
diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp
index 3d91f5c9d8..4d1ee1c38c 100644
--- a/src/mbgl/sprite/sprite_atlas.hpp
+++ b/src/mbgl/sprite/sprite_atlas.hpp
@@ -21,13 +21,9 @@ class SpriteImage;
class SpritePosition;
struct SpriteAtlasPosition {
- inline SpriteAtlasPosition(const std::array<float, 2> size_ = {{0, 0}},
- const std::array<float, 2> tl_ = {{0, 0}},
- const std::array<float, 2> br_ = {{0, 0}})
- : size(size_), tl(tl_), br(br_) {}
- std::array<float, 2> size;
- std::array<float, 2> tl;
- std::array<float, 2> br;
+ std::array<float, 2> size = {{ 0, 0 }};
+ std::array<float, 2> tl = {{ 0, 0 }};
+ std::array<float, 2> br = {{ 0, 0 }};
};
struct SpriteAtlasElement {
@@ -60,14 +56,14 @@ public:
// the texture is only bound when the data is out of date (=dirty).
void upload(gl::ObjectStore&);
- inline dimension getWidth() const { return width; }
- inline dimension getHeight() const { return height; }
- inline dimension getTextureWidth() const { return pixelWidth; }
- inline dimension getTextureHeight() const { return pixelHeight; }
- inline float getPixelRatio() const { return pixelRatio; }
+ dimension getWidth() const { return width; }
+ dimension getHeight() const { return height; }
+ dimension getTextureWidth() const { return pixelWidth; }
+ dimension getTextureHeight() const { return pixelHeight; }
+ float getPixelRatio() const { return pixelRatio; }
// Only for use in tests.
- inline const uint32_t* getData() const { return data.get(); }
+ const uint32_t* getData() const { return data.get(); }
private:
const GLsizei width, height;
@@ -75,8 +71,8 @@ private:
const float pixelRatio;
struct Holder : private util::noncopyable {
- inline Holder(const std::shared_ptr<const SpriteImage>&, const Rect<dimension>&);
- inline Holder(Holder&&);
+ Holder(std::shared_ptr<const SpriteImage>, Rect<dimension>);
+ Holder(Holder&&);
std::shared_ptr<const SpriteImage> spriteImage;
const Rect<dimension> pos;
};
diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp
index 9fbca51112..190ac66e14 100644
--- a/src/mbgl/sprite/sprite_parser.cpp
+++ b/src/mbgl/sprite/sprite_parser.cpp
@@ -46,7 +46,7 @@ SpriteImagePtr createSpriteImage(const PremultipliedImage& image,
namespace {
-inline uint16_t getUInt16(const JSValue& value, const char* name, const uint16_t def = 0) {
+uint16_t getUInt16(const JSValue& value, const char* name, const uint16_t def = 0) {
if (value.HasMember(name)) {
auto& v = value[name];
if (v.IsUint() && v.GetUint() <= std::numeric_limits<uint16_t>::max()) {
@@ -60,7 +60,7 @@ inline uint16_t getUInt16(const JSValue& value, const char* name, const uint16_t
return def;
}
-inline double getDouble(const JSValue& value, const char* name, const double def = 0) {
+double getDouble(const JSValue& value, const char* name, const double def = 0) {
if (value.HasMember(name)) {
auto& v = value[name];
if (v.IsNumber()) {
@@ -73,7 +73,7 @@ inline double getDouble(const JSValue& value, const char* name, const double def
return def;
}
-inline bool getBoolean(const JSValue& value, const char* name, const bool def = false) {
+bool getBoolean(const JSValue& value, const char* name, const bool def = false) {
if (value.HasMember(name)) {
auto& v = value[name];
if (v.IsBool()) {
diff --git a/src/mbgl/storage/resource.cpp b/src/mbgl/storage/resource.cpp
index 3f5b4a3f71..8019e4aeb7 100644
--- a/src/mbgl/storage/resource.cpp
+++ b/src/mbgl/storage/resource.cpp
@@ -86,4 +86,4 @@ Resource Resource::tile(const std::string& urlTemplate,
};
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/storage/response.cpp b/src/mbgl/storage/response.cpp
index 644d73d286..6809220166 100644
--- a/src/mbgl/storage/response.cpp
+++ b/src/mbgl/storage/response.cpp
@@ -21,14 +21,14 @@ Response& Response::operator=(const Response& res) {
return *this;
}
-Response::Error::Error(Reason reason_, const std::string& message_)
- : reason(reason_), message(message_) {
+Response::Error::Error(Reason reason_, std::string message_)
+ : reason(reason_), message(std::move(message_)) {
}
std::ostream& operator<<(std::ostream& os, Response::Error::Reason r) {
switch (r) {
case Response::Error::Reason::Success:
- return os << "Response::Error::Reason::NotFound";
+ return os << "Response::Error::Reason::Success";
case Response::Error::Reason::NotFound:
return os << "Response::Error::Reason::NotFound";
case Response::Error::Reason::Server:
diff --git a/src/mbgl/style/bucket_parameters.cpp b/src/mbgl/style/bucket_parameters.cpp
index f3367d57e1..5bb08af873 100644
--- a/src/mbgl/style/bucket_parameters.cpp
+++ b/src/mbgl/style/bucket_parameters.cpp
@@ -1,6 +1,6 @@
#include <mbgl/style/bucket_parameters.hpp>
#include <mbgl/style/filter_evaluator.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
namespace mbgl {
namespace style {
@@ -10,11 +10,8 @@ void BucketParameters::eachFilteredFeature(const Filter& filter,
auto name = layer.getName();
for (std::size_t i = 0; !cancelled() && i < layer.featureCount(); i++) {
auto feature = layer.getFeature(i);
-
- FilterEvaluator evaluator(*feature);
- if (!Filter::visit(filter, evaluator))
+ if (!filter(feature->getType(), [&] (const auto& key) { return feature->getValue(key); }))
continue;
-
function(*feature, i, name);
}
}
diff --git a/src/mbgl/style/calculation_parameters.hpp b/src/mbgl/style/calculation_parameters.hpp
index 2afd7c4b34..e1f059c524 100644
--- a/src/mbgl/style/calculation_parameters.hpp
+++ b/src/mbgl/style/calculation_parameters.hpp
@@ -12,13 +12,13 @@ public:
: z(z_) {}
CalculationParameters(float z_,
- const TimePoint& now_,
- const ZoomHistory& zoomHistory_,
- const Duration& defaultFadeDuration_)
+ TimePoint now_,
+ ZoomHistory zoomHistory_,
+ Duration defaultFadeDuration_)
: z(z_),
- now(now_),
- zoomHistory(zoomHistory_),
- defaultFadeDuration(defaultFadeDuration_) {}
+ now(std::move(now_)),
+ zoomHistory(std::move(zoomHistory_)),
+ defaultFadeDuration(std::move(defaultFadeDuration_)) {}
float z;
TimePoint now;
diff --git a/src/mbgl/style/cascade_parameters.hpp b/src/mbgl/style/cascade_parameters.hpp
index 4ad6da2ce3..e0333741dd 100644
--- a/src/mbgl/style/cascade_parameters.hpp
+++ b/src/mbgl/style/cascade_parameters.hpp
@@ -9,8 +9,6 @@
namespace mbgl {
namespace style {
-class TransitionOptions;
-
class CascadeParameters {
public:
std::vector<ClassID> classes;
diff --git a/src/mbgl/style/filter_evaluator.hpp b/src/mbgl/style/filter_evaluator.hpp
deleted file mode 100644
index e03beaa4d0..0000000000
--- a/src/mbgl/style/filter_evaluator.hpp
+++ /dev/null
@@ -1,163 +0,0 @@
-#pragma once
-
-#include <mbgl/style/filter.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
-
-#include <type_traits>
-
-namespace mbgl {
-namespace style {
-
-class FilterEvaluator {
-public:
- FilterEvaluator(const GeometryTileFeature& feature_)
- : feature(feature_) {}
-
- bool operator()(const NullFilter&) const {
- return true;
- }
-
- bool operator()(const EqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- return actual && equal(*actual, filter.value);
- }
-
- bool operator()(const NotEqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- return !actual || !equal(*actual, filter.value);
- }
-
- bool operator()(const LessThanFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ < rhs_; });
- }
-
- bool operator()(const LessThanEqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ <= rhs_; });
- }
-
- bool operator()(const GreaterThanFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ > rhs_; });
- }
-
- bool operator()(const GreaterThanEqualsFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- return actual && compare(*actual, filter.value, [] (const auto& lhs_, const auto& rhs_) { return lhs_ >= rhs_; });
- }
-
- bool operator()(const InFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- if (!actual)
- return false;
- for (const auto& v: filter.values) {
- if (equal(*actual, v)) {
- return true;
- }
- }
- return false;
- }
-
- bool operator()(const NotInFilter& filter) const {
- optional<Value> actual = getValue(filter.key);
- if (!actual)
- return true;
- for (const auto& v: filter.values) {
- if (equal(*actual, v)) {
- return false;
- }
- }
- return true;
- }
-
- bool operator()(const AnyFilter& filter) const {
- for (const auto& f: filter.filters) {
- if (Filter::visit(f, *this)) {
- return true;
- }
- }
- return false;
- }
-
- bool operator()(const AllFilter& filter) const {
- for (const auto& f: filter.filters) {
- if (!Filter::visit(f, *this)) {
- return false;
- }
- }
- return true;
- }
-
- bool operator()(const NoneFilter& filter) const {
- for (const auto& f: filter.filters) {
- if (Filter::visit(f, *this)) {
- return false;
- }
- }
- return true;
- }
-
- bool operator()(const HasFilter& filter) const {
- return bool(getValue(filter.key));
- }
-
- bool operator()(const NotHasFilter& filter) const {
- return !getValue(filter.key);
- }
-
-private:
- optional<Value> getValue(const std::string& key) const {
- return key == "$type"
- ? optional<Value>(uint64_t(feature.getType()))
- : feature.getValue(key);
- }
-
- template <class Op>
- struct Comparator {
- const Op& op;
-
- template <class T>
- bool operator()(const T& lhs, const T& rhs) const {
- return op(lhs, rhs);
- }
-
- template <class T0, class T1>
- auto operator()(const T0& lhs, const T1& rhs) const
- -> typename std::enable_if_t<std::is_arithmetic<T0>::value && !std::is_same<T0, bool>::value &&
- std::is_arithmetic<T1>::value && !std::is_same<T1, bool>::value, bool> {
- return op(double(lhs), double(rhs));
- }
-
- template <class T0, class T1>
- auto operator()(const T0&, const T1&) const
- -> typename std::enable_if_t<!std::is_arithmetic<T0>::value || std::is_same<T0, bool>::value ||
- !std::is_arithmetic<T1>::value || std::is_same<T1, bool>::value, bool> {
- return false;
- }
-
- bool operator()(const std::vector<Value>&,
- const std::vector<Value>&) const {
- return false;
- }
-
- bool operator()(const std::unordered_map<std::string, Value>&,
- const std::unordered_map<std::string, Value>&) const {
- return false;
- }
- };
-
- template <class Op>
- bool compare(const Value& lhs, const Value& rhs, const Op& op) const {
- return Value::binary_visit(lhs, rhs, Comparator<Op> { op });
- }
-
- bool equal(const Value& lhs, const Value& rhs) const {
- return compare(lhs, rhs, [] (const auto& lhs_, const auto& rhs_) { return lhs_ == rhs_; });
- }
-
- const GeometryTileFeature& feature;
-};
-
-} // namespace mbgl
-} // namespace mbgl
diff --git a/src/mbgl/style/layer.cpp b/src/mbgl/style/layer.cpp
index 342699a2c9..6eff64ae09 100644
--- a/src/mbgl/style/layer.cpp
+++ b/src/mbgl/style/layer.cpp
@@ -38,13 +38,5 @@ void Layer::setMaxZoom(float maxZoom) const {
baseImpl->maxZoom = maxZoom;
}
-std::unique_ptr<Layer> Layer::copy(const std::string& id,
- const std::string& ref) const {
- std::unique_ptr<Layer> result = baseImpl->clone();
- result->baseImpl->id = id;
- result->baseImpl->ref = ref;
- return result;
-}
-
} // namespace style
} // namespace mbgl
diff --git a/src/mbgl/style/layer_impl.cpp b/src/mbgl/style/layer_impl.cpp
index 74cc80d253..b345297027 100644
--- a/src/mbgl/style/layer_impl.cpp
+++ b/src/mbgl/style/layer_impl.cpp
@@ -3,6 +3,16 @@
namespace mbgl {
namespace style {
+std::unique_ptr<Layer> Layer::Impl::copy(const std::string& id_,
+ const std::string& ref_,
+ const std::string& source_) const {
+ std::unique_ptr<Layer> result = clone();
+ result->baseImpl->id = id_;
+ result->baseImpl->ref = ref_;
+ result->baseImpl->source = source_;
+ return result;
+}
+
const std::string& Layer::Impl::bucketName() const {
return ref.empty() ? id : ref;
}
diff --git a/src/mbgl/style/layer_impl.hpp b/src/mbgl/style/layer_impl.hpp
index dcd5d9906b..d2bf866e8e 100644
--- a/src/mbgl/style/layer_impl.hpp
+++ b/src/mbgl/style/layer_impl.hpp
@@ -5,8 +5,7 @@
#include <mbgl/style/filter.hpp>
#include <mbgl/renderer/render_pass.hpp>
#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/rapidjson.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <memory>
#include <string>
@@ -37,11 +36,17 @@ class Layer::Impl {
public:
virtual ~Impl() = default;
+ // Create a new layer with the specified `id`, `ref`, and `sourceID`. All other properties
+ // are copied from this layer.
+ std::unique_ptr<Layer> copy(const std::string& id,
+ const std::string& ref,
+ const std::string& sourceID) const;
+
// Create an identical copy of this layer.
virtual std::unique_ptr<Layer> clone() const = 0;
- virtual void parseLayout(const JSValue& value) = 0;
- virtual void parsePaints(const JSValue& value) = 0;
+ // Create a layer, copying all properties except id, ref, and paint properties from this layer.
+ virtual std::unique_ptr<Layer> cloneRef(const std::string& id) const = 0;
// If the layer has a ref, the ref. Otherwise, the id.
const std::string& bucketName() const;
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
index aeb4067503..42cd76d01f 100644
--- a/src/mbgl/style/layers/background_layer.cpp
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -23,6 +23,14 @@ std::unique_ptr<Layer> BackgroundLayer::Impl::clone() const {
return std::make_unique<BackgroundLayer>(*this);
}
+std::unique_ptr<Layer> BackgroundLayer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<BackgroundLayer>(*this);
+ result->impl->id = id_;
+ result->impl->ref = this->id;
+ result->impl->paint = BackgroundPaintProperties();
+ return std::move(result);
+}
+
// Layout properties
@@ -33,24 +41,24 @@ PropertyValue<Color> BackgroundLayer::getBackgroundColor() const {
return impl->paint.backgroundColor.get();
}
-void BackgroundLayer::setBackgroundColor(PropertyValue<Color> value) {
- impl->paint.backgroundColor.set(value);
+void BackgroundLayer::setBackgroundColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.backgroundColor.set(value, klass);
}
PropertyValue<std::string> BackgroundLayer::getBackgroundPattern() const {
return impl->paint.backgroundPattern.get();
}
-void BackgroundLayer::setBackgroundPattern(PropertyValue<std::string> value) {
- impl->paint.backgroundPattern.set(value);
+void BackgroundLayer::setBackgroundPattern(PropertyValue<std::string> value, const optional<std::string>& klass) {
+ impl->paint.backgroundPattern.set(value, klass);
}
PropertyValue<float> BackgroundLayer::getBackgroundOpacity() const {
return impl->paint.backgroundOpacity.get();
}
-void BackgroundLayer::setBackgroundOpacity(PropertyValue<float> value) {
- impl->paint.backgroundOpacity.set(value);
+void BackgroundLayer::setBackgroundOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.backgroundOpacity.set(value, klass);
}
} // namespace style
diff --git a/src/mbgl/style/layers/background_layer_impl.cpp b/src/mbgl/style/layers/background_layer_impl.cpp
index 0c09c5d158..ea389b828e 100644
--- a/src/mbgl/style/layers/background_layer_impl.cpp
+++ b/src/mbgl/style/layers/background_layer_impl.cpp
@@ -4,10 +4,6 @@
namespace mbgl {
namespace style {
-void BackgroundLayer::Impl::parsePaints(const JSValue& layer) {
- paint.parse(layer);
-}
-
void BackgroundLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
diff --git a/src/mbgl/style/layers/background_layer_impl.hpp b/src/mbgl/style/layers/background_layer_impl.hpp
index 19e2a062a4..abbb740f42 100644
--- a/src/mbgl/style/layers/background_layer_impl.hpp
+++ b/src/mbgl/style/layers/background_layer_impl.hpp
@@ -10,9 +10,7 @@ namespace style {
class BackgroundLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
-
- void parseLayout(const JSValue&) override {};
- void parsePaints(const JSValue&) override;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
void cascade(const CascadeParameters&) override;
bool recalculate(const CalculationParameters&) override;
diff --git a/src/mbgl/style/layers/background_layer_properties.cpp b/src/mbgl/style/layers/background_layer_properties.cpp
index a20cedf12c..558093a255 100644
--- a/src/mbgl/style/layers/background_layer_properties.cpp
+++ b/src/mbgl/style/layers/background_layer_properties.cpp
@@ -5,12 +5,6 @@
namespace mbgl {
namespace style {
-void BackgroundPaintProperties::parse(const JSValue& value) {
- backgroundColor.parse("background-color", value);
- backgroundPattern.parse("background-pattern", value);
- backgroundOpacity.parse("background-opacity", value);
-}
-
void BackgroundPaintProperties::cascade(const CascadeParameters& parameters) {
backgroundColor.cascade(parameters);
backgroundPattern.cascade(parameters);
diff --git a/src/mbgl/style/layers/background_layer_properties.hpp b/src/mbgl/style/layers/background_layer_properties.hpp
index a1a1a3a5a7..6c5a7c57ca 100644
--- a/src/mbgl/style/layers/background_layer_properties.hpp
+++ b/src/mbgl/style/layers/background_layer_properties.hpp
@@ -2,9 +2,9 @@
#pragma once
+#include <mbgl/style/types.hpp>
#include <mbgl/style/layout_property.hpp>
#include <mbgl/style/paint_property.hpp>
-#include <mbgl/util/rapidjson.hpp>
namespace mbgl {
namespace style {
@@ -14,11 +14,10 @@ class CalculationParameters;
class BackgroundPaintProperties {
public:
- void parse(const JSValue&);
void cascade(const CascadeParameters&);
bool recalculate(const CalculationParameters&);
- PaintProperty<Color> backgroundColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<Color> backgroundColor { { 0, 0, 0, 1 } };
PaintProperty<std::string, CrossFadedPropertyEvaluator> backgroundPattern { "" };
PaintProperty<float> backgroundOpacity { 1 };
};
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index bdfbf629e6..a47d723548 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -6,10 +6,11 @@
namespace mbgl {
namespace style {
-CircleLayer::CircleLayer(const std::string& layerID)
+CircleLayer::CircleLayer(const std::string& layerID, const std::string& sourceID)
: Layer(Type::Circle, std::make_unique<Impl>())
, impl(static_cast<Impl*>(baseImpl.get())) {
impl->id = layerID;
+ impl->source = sourceID;
}
CircleLayer::CircleLayer(const Impl& other)
@@ -23,17 +24,24 @@ std::unique_ptr<Layer> CircleLayer::Impl::clone() const {
return std::make_unique<CircleLayer>(*this);
}
-// Source
-
-void CircleLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
- impl->source = sourceID;
- impl->sourceLayer = sourceLayer;
+std::unique_ptr<Layer> CircleLayer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<CircleLayer>(*this);
+ result->impl->id = id_;
+ result->impl->ref = this->id;
+ result->impl->paint = CirclePaintProperties();
+ return std::move(result);
}
+// Source
+
const std::string& CircleLayer::getSourceID() const {
return impl->source;
}
+void CircleLayer::setSourceLayer(const std::string& sourceLayer) {
+ impl->sourceLayer = sourceLayer;
+}
+
const std::string& CircleLayer::getSourceLayer() const {
return impl->sourceLayer;
}
@@ -57,48 +65,48 @@ PropertyValue<float> CircleLayer::getCircleRadius() const {
return impl->paint.circleRadius.get();
}
-void CircleLayer::setCircleRadius(PropertyValue<float> value) {
- impl->paint.circleRadius.set(value);
+void CircleLayer::setCircleRadius(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.circleRadius.set(value, klass);
}
PropertyValue<Color> CircleLayer::getCircleColor() const {
return impl->paint.circleColor.get();
}
-void CircleLayer::setCircleColor(PropertyValue<Color> value) {
- impl->paint.circleColor.set(value);
+void CircleLayer::setCircleColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.circleColor.set(value, klass);
}
PropertyValue<float> CircleLayer::getCircleBlur() const {
return impl->paint.circleBlur.get();
}
-void CircleLayer::setCircleBlur(PropertyValue<float> value) {
- impl->paint.circleBlur.set(value);
+void CircleLayer::setCircleBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.circleBlur.set(value, klass);
}
PropertyValue<float> CircleLayer::getCircleOpacity() const {
return impl->paint.circleOpacity.get();
}
-void CircleLayer::setCircleOpacity(PropertyValue<float> value) {
- impl->paint.circleOpacity.set(value);
+void CircleLayer::setCircleOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.circleOpacity.set(value, klass);
}
PropertyValue<std::array<float, 2>> CircleLayer::getCircleTranslate() const {
return impl->paint.circleTranslate.get();
}
-void CircleLayer::setCircleTranslate(PropertyValue<std::array<float, 2>> value) {
- impl->paint.circleTranslate.set(value);
+void CircleLayer::setCircleTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
+ impl->paint.circleTranslate.set(value, klass);
}
PropertyValue<TranslateAnchorType> CircleLayer::getCircleTranslateAnchor() const {
return impl->paint.circleTranslateAnchor.get();
}
-void CircleLayer::setCircleTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
- impl->paint.circleTranslateAnchor.set(value);
+void CircleLayer::setCircleTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
+ impl->paint.circleTranslateAnchor.set(value, klass);
}
} // namespace style
diff --git a/src/mbgl/style/layers/circle_layer_impl.cpp b/src/mbgl/style/layers/circle_layer_impl.cpp
index c2efac5cef..e08d9df146 100644
--- a/src/mbgl/style/layers/circle_layer_impl.cpp
+++ b/src/mbgl/style/layers/circle_layer_impl.cpp
@@ -8,10 +8,6 @@
namespace mbgl {
namespace style {
-void CircleLayer::Impl::parsePaints(const JSValue& layer) {
- paint.parse(layer);
-}
-
void CircleLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
@@ -19,7 +15,7 @@ void CircleLayer::Impl::cascade(const CascadeParameters& parameters) {
bool CircleLayer::Impl::recalculate(const CalculationParameters& parameters) {
bool hasTransitions = paint.recalculate(parameters);
- passes = (paint.circleRadius > 0 && paint.circleColor.value[3] > 0 && paint.circleOpacity > 0)
+ passes = (paint.circleRadius > 0 && paint.circleColor.value.a > 0 && paint.circleOpacity > 0)
? RenderPass::Translucent : RenderPass::None;
return hasTransitions;
diff --git a/src/mbgl/style/layers/circle_layer_impl.hpp b/src/mbgl/style/layers/circle_layer_impl.hpp
index 463f3ca18d..555691b6b4 100644
--- a/src/mbgl/style/layers/circle_layer_impl.hpp
+++ b/src/mbgl/style/layers/circle_layer_impl.hpp
@@ -10,9 +10,7 @@ namespace style {
class CircleLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
-
- void parseLayout(const JSValue&) override {};
- void parsePaints(const JSValue&) override;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
void cascade(const CascadeParameters&) override;
bool recalculate(const CalculationParameters&) override;
diff --git a/src/mbgl/style/layers/circle_layer_properties.cpp b/src/mbgl/style/layers/circle_layer_properties.cpp
index b21df1e2d0..045c73ba63 100644
--- a/src/mbgl/style/layers/circle_layer_properties.cpp
+++ b/src/mbgl/style/layers/circle_layer_properties.cpp
@@ -5,15 +5,6 @@
namespace mbgl {
namespace style {
-void CirclePaintProperties::parse(const JSValue& value) {
- circleRadius.parse("circle-radius", value);
- circleColor.parse("circle-color", value);
- circleBlur.parse("circle-blur", value);
- circleOpacity.parse("circle-opacity", value);
- circleTranslate.parse("circle-translate", value);
- circleTranslateAnchor.parse("circle-translate-anchor", value);
-}
-
void CirclePaintProperties::cascade(const CascadeParameters& parameters) {
circleRadius.cascade(parameters);
circleColor.cascade(parameters);
diff --git a/src/mbgl/style/layers/circle_layer_properties.hpp b/src/mbgl/style/layers/circle_layer_properties.hpp
index 956e423c45..40d37dc392 100644
--- a/src/mbgl/style/layers/circle_layer_properties.hpp
+++ b/src/mbgl/style/layers/circle_layer_properties.hpp
@@ -2,9 +2,9 @@
#pragma once
+#include <mbgl/style/types.hpp>
#include <mbgl/style/layout_property.hpp>
#include <mbgl/style/paint_property.hpp>
-#include <mbgl/util/rapidjson.hpp>
namespace mbgl {
namespace style {
@@ -14,12 +14,11 @@ class CalculationParameters;
class CirclePaintProperties {
public:
- void parse(const JSValue&);
void cascade(const CascadeParameters&);
bool recalculate(const CalculationParameters&);
PaintProperty<float> circleRadius { 5 };
- PaintProperty<Color> circleColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<Color> circleColor { { 0, 0, 0, 1 } };
PaintProperty<float> circleBlur { 0 };
PaintProperty<float> circleOpacity { 1 };
PaintProperty<std::array<float, 2>> circleTranslate { {{ 0, 0 }} };
diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp
index 214d4ce663..a0686e353c 100644
--- a/src/mbgl/style/layers/custom_layer_impl.cpp
+++ b/src/mbgl/style/layers/custom_layer_impl.cpp
@@ -33,6 +33,11 @@ std::unique_ptr<Layer> CustomLayer::Impl::clone() const {
return std::make_unique<CustomLayer>(*this);
}
+std::unique_ptr<Layer> CustomLayer::Impl::cloneRef(const std::string&) const {
+ assert(false);
+ return std::make_unique<CustomLayer>(*this);
+}
+
void CustomLayer::Impl::initialize() {
assert(initializeFn);
initializeFn(context);
diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp
index 00e576b6a3..ffa892ddf8 100644
--- a/src/mbgl/style/layers/custom_layer_impl.hpp
+++ b/src/mbgl/style/layers/custom_layer_impl.hpp
@@ -25,9 +25,7 @@ public:
private:
std::unique_ptr<Layer> clone() const override;
-
- void parseLayout(const JSValue&) final {}
- void parsePaints(const JSValue&) final {}
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
void cascade(const CascadeParameters&) final {}
bool recalculate(const CalculationParameters&) final;
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
index 1deaabb5ef..44894aff33 100644
--- a/src/mbgl/style/layers/fill_layer.cpp
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -6,10 +6,11 @@
namespace mbgl {
namespace style {
-FillLayer::FillLayer(const std::string& layerID)
+FillLayer::FillLayer(const std::string& layerID, const std::string& sourceID)
: Layer(Type::Fill, std::make_unique<Impl>())
, impl(static_cast<Impl*>(baseImpl.get())) {
impl->id = layerID;
+ impl->source = sourceID;
}
FillLayer::FillLayer(const Impl& other)
@@ -23,17 +24,24 @@ std::unique_ptr<Layer> FillLayer::Impl::clone() const {
return std::make_unique<FillLayer>(*this);
}
-// Source
-
-void FillLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
- impl->source = sourceID;
- impl->sourceLayer = sourceLayer;
+std::unique_ptr<Layer> FillLayer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<FillLayer>(*this);
+ result->impl->id = id_;
+ result->impl->ref = this->id;
+ result->impl->paint = FillPaintProperties();
+ return std::move(result);
}
+// Source
+
const std::string& FillLayer::getSourceID() const {
return impl->source;
}
+void FillLayer::setSourceLayer(const std::string& sourceLayer) {
+ impl->sourceLayer = sourceLayer;
+}
+
const std::string& FillLayer::getSourceLayer() const {
return impl->sourceLayer;
}
@@ -57,56 +65,56 @@ PropertyValue<bool> FillLayer::getFillAntialias() const {
return impl->paint.fillAntialias.get();
}
-void FillLayer::setFillAntialias(PropertyValue<bool> value) {
- impl->paint.fillAntialias.set(value);
+void FillLayer::setFillAntialias(PropertyValue<bool> value, const optional<std::string>& klass) {
+ impl->paint.fillAntialias.set(value, klass);
}
PropertyValue<float> FillLayer::getFillOpacity() const {
return impl->paint.fillOpacity.get();
}
-void FillLayer::setFillOpacity(PropertyValue<float> value) {
- impl->paint.fillOpacity.set(value);
+void FillLayer::setFillOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.fillOpacity.set(value, klass);
}
PropertyValue<Color> FillLayer::getFillColor() const {
return impl->paint.fillColor.get();
}
-void FillLayer::setFillColor(PropertyValue<Color> value) {
- impl->paint.fillColor.set(value);
+void FillLayer::setFillColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.fillColor.set(value, klass);
}
PropertyValue<Color> FillLayer::getFillOutlineColor() const {
return impl->paint.fillOutlineColor.get();
}
-void FillLayer::setFillOutlineColor(PropertyValue<Color> value) {
- impl->paint.fillOutlineColor.set(value);
+void FillLayer::setFillOutlineColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.fillOutlineColor.set(value, klass);
}
PropertyValue<std::array<float, 2>> FillLayer::getFillTranslate() const {
return impl->paint.fillTranslate.get();
}
-void FillLayer::setFillTranslate(PropertyValue<std::array<float, 2>> value) {
- impl->paint.fillTranslate.set(value);
+void FillLayer::setFillTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
+ impl->paint.fillTranslate.set(value, klass);
}
PropertyValue<TranslateAnchorType> FillLayer::getFillTranslateAnchor() const {
return impl->paint.fillTranslateAnchor.get();
}
-void FillLayer::setFillTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
- impl->paint.fillTranslateAnchor.set(value);
+void FillLayer::setFillTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
+ impl->paint.fillTranslateAnchor.set(value, klass);
}
PropertyValue<std::string> FillLayer::getFillPattern() const {
return impl->paint.fillPattern.get();
}
-void FillLayer::setFillPattern(PropertyValue<std::string> value) {
- impl->paint.fillPattern.set(value);
+void FillLayer::setFillPattern(PropertyValue<std::string> value, const optional<std::string>& klass) {
+ impl->paint.fillPattern.set(value, klass);
}
} // namespace style
diff --git a/src/mbgl/style/layers/fill_layer_impl.cpp b/src/mbgl/style/layers/fill_layer_impl.cpp
index c183617482..2992312514 100644
--- a/src/mbgl/style/layers/fill_layer_impl.cpp
+++ b/src/mbgl/style/layers/fill_layer_impl.cpp
@@ -8,10 +8,6 @@
namespace mbgl {
namespace style {
-void FillLayer::Impl::parsePaints(const JSValue& layer) {
- paint.parse(layer);
-}
-
void FillLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
@@ -25,7 +21,7 @@ bool FillLayer::Impl::recalculate(const CalculationParameters& parameters) {
passes |= RenderPass::Translucent;
}
- if (!paint.fillPattern.value.from.empty() || (paint.fillColor.value[3] * paint.fillOpacity) < 1.0f) {
+ if (!paint.fillPattern.value.from.empty() || (paint.fillColor.value.a * paint.fillOpacity) < 1.0f) {
passes |= RenderPass::Translucent;
} else {
passes |= RenderPass::Opaque;
diff --git a/src/mbgl/style/layers/fill_layer_impl.hpp b/src/mbgl/style/layers/fill_layer_impl.hpp
index a37dd76ace..fc6578ecd1 100644
--- a/src/mbgl/style/layers/fill_layer_impl.hpp
+++ b/src/mbgl/style/layers/fill_layer_impl.hpp
@@ -10,9 +10,7 @@ namespace style {
class FillLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
-
- void parseLayout(const JSValue&) override {};
- void parsePaints(const JSValue&) override;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
void cascade(const CascadeParameters&) override;
bool recalculate(const CalculationParameters&) override;
diff --git a/src/mbgl/style/layers/fill_layer_properties.cpp b/src/mbgl/style/layers/fill_layer_properties.cpp
index a4714689f9..9a55cbc145 100644
--- a/src/mbgl/style/layers/fill_layer_properties.cpp
+++ b/src/mbgl/style/layers/fill_layer_properties.cpp
@@ -5,16 +5,6 @@
namespace mbgl {
namespace style {
-void FillPaintProperties::parse(const JSValue& value) {
- fillAntialias.parse("fill-antialias", value);
- fillOpacity.parse("fill-opacity", value);
- fillColor.parse("fill-color", value);
- fillOutlineColor.parse("fill-outline-color", value);
- fillTranslate.parse("fill-translate", value);
- fillTranslateAnchor.parse("fill-translate-anchor", value);
- fillPattern.parse("fill-pattern", value);
-}
-
void FillPaintProperties::cascade(const CascadeParameters& parameters) {
fillAntialias.cascade(parameters);
fillOpacity.cascade(parameters);
diff --git a/src/mbgl/style/layers/fill_layer_properties.hpp b/src/mbgl/style/layers/fill_layer_properties.hpp
index 43396f45d2..82981a9b64 100644
--- a/src/mbgl/style/layers/fill_layer_properties.hpp
+++ b/src/mbgl/style/layers/fill_layer_properties.hpp
@@ -2,9 +2,9 @@
#pragma once
+#include <mbgl/style/types.hpp>
#include <mbgl/style/layout_property.hpp>
#include <mbgl/style/paint_property.hpp>
-#include <mbgl/util/rapidjson.hpp>
namespace mbgl {
namespace style {
@@ -14,14 +14,13 @@ class CalculationParameters;
class FillPaintProperties {
public:
- void parse(const JSValue&);
void cascade(const CascadeParameters&);
bool recalculate(const CalculationParameters&);
PaintProperty<bool> fillAntialias { true };
PaintProperty<float> fillOpacity { 1 };
- PaintProperty<Color> fillColor { {{ 0, 0, 0, 1 }} };
- PaintProperty<Color> fillOutlineColor { {{ 0, 0, 0, -1 }} };
+ PaintProperty<Color> fillColor { { 0, 0, 0, 1 } };
+ PaintProperty<Color> fillOutlineColor { { 0, 0, 0, -1 } };
PaintProperty<std::array<float, 2>> fillTranslate { {{ 0, 0 }} };
PaintProperty<TranslateAnchorType> fillTranslateAnchor { TranslateAnchorType::Map };
PaintProperty<std::string, CrossFadedPropertyEvaluator> fillPattern { "" };
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
new file mode 100644
index 0000000000..017691c8ec
--- /dev/null
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -0,0 +1,100 @@
+<%
+ const type = locals.type;
+ const layoutProperties = locals.layoutProperties;
+ const paintProperties = locals.paintProperties;
+-%>
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/<%- type %>_layer.hpp>
+#include <mbgl/style/layers/<%- type %>_layer_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+<% if (type === 'background') { -%>
+<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID)
+ : Layer(Type::<%- camelize(type) %>, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+}
+<% } else { -%>
+<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const std::string& layerID, const std::string& sourceID)
+ : Layer(Type::<%- camelize(type) %>, std::make_unique<Impl>())
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+ impl->id = layerID;
+ impl->source = sourceID;
+}
+<% } -%>
+
+<%- camelize(type) %>Layer::<%- camelize(type) %>Layer(const Impl& other)
+ : Layer(Type::<%- camelize(type) %>, std::make_unique<Impl>(other))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+<%- camelize(type) %>Layer::~<%- camelize(type) %>Layer() = default;
+
+std::unique_ptr<Layer> <%- camelize(type) %>Layer::Impl::clone() const {
+ return std::make_unique<<%- camelize(type) %>Layer>(*this);
+}
+
+std::unique_ptr<Layer> <%- camelize(type) %>Layer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<<%- camelize(type) %>Layer>(*this);
+ result->impl->id = id_;
+ result->impl->ref = this->id;
+ result->impl->paint = <%- camelize(type) %>PaintProperties();
+ return std::move(result);
+}
+
+<% if (type !== 'background') { -%>
+// Source
+
+const std::string& <%- camelize(type) %>Layer::getSourceID() const {
+ return impl->source;
+}
+
+<% if (type !== 'raster') { -%>
+void <%- camelize(type) %>Layer::setSourceLayer(const std::string& sourceLayer) {
+ impl->sourceLayer = sourceLayer;
+}
+
+const std::string& <%- camelize(type) %>Layer::getSourceLayer() const {
+ return impl->sourceLayer;
+}
+
+// Filter
+
+void <%- camelize(type) %>Layer::setFilter(const Filter& filter) {
+ impl->filter = filter;
+}
+
+const Filter& <%- camelize(type) %>Layer::getFilter() const {
+ return impl->filter;
+}
+<% } -%>
+<% } -%>
+
+// Layout properties
+
+<% for (const property of layoutProperties) { -%>
+PropertyValue<<%- propertyType(property) %>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const {
+ return impl->layout.<%- camelizeWithLeadingLowercase(property.name) %>.get();
+}
+
+void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>> value) {
+ impl->layout.<%- camelizeWithLeadingLowercase(property.name) %>.set(value);
+}
+<% } -%>
+
+// Paint properties
+<% for (const property of paintProperties) { %>
+PropertyValue<<%- propertyType(property) %>> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>() const {
+ return impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.get();
+}
+
+void <%- camelize(type) %>Layer::set<%- camelize(property.name) %>(PropertyValue<<%- propertyType(property) %>> value, const optional<std::string>& klass) {
+ impl->paint.<%- camelizeWithLeadingLowercase(property.name) %>.set(value, klass);
+}
+<% } -%>
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/layer_properties.cpp.ejs b/src/mbgl/style/layers/layer_properties.cpp.ejs
new file mode 100644
index 0000000000..b781a4a9d9
--- /dev/null
+++ b/src/mbgl/style/layers/layer_properties.cpp.ejs
@@ -0,0 +1,38 @@
+<%
+ const type = locals.type;
+ const layoutProperties = locals.layoutProperties;
+ const paintProperties = locals.paintProperties;
+-%>
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#include <mbgl/style/layers/<%- type %>_layer_properties.hpp>
+
+namespace mbgl {
+namespace style {
+
+<% if (layoutProperties.length) { -%>
+void <%- camelize(type) %>LayoutProperties::recalculate(const CalculationParameters& parameters) {
+<% for (const property of layoutProperties) { -%>
+ <%- camelizeWithLeadingLowercase(property.name) %>.calculate(parameters);
+<% } -%>
+}
+
+<% } -%>
+void <%- camelize(type) %>PaintProperties::cascade(const CascadeParameters& parameters) {
+<% for (const property of paintProperties) { -%>
+ <%- camelizeWithLeadingLowercase(property.name) %>.cascade(parameters);
+<% } -%>
+}
+
+bool <%- camelize(type) %>PaintProperties::recalculate(const CalculationParameters& parameters) {
+ bool hasTransitions = false;
+
+<% for (const property of paintProperties) { -%>
+ hasTransitions |= <%- camelizeWithLeadingLowercase(property.name) %>.calculate(parameters);
+<% } -%>
+
+ return hasTransitions;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/layer_properties.hpp.ejs b/src/mbgl/style/layers/layer_properties.hpp.ejs
new file mode 100644
index 0000000000..a485621ac6
--- /dev/null
+++ b/src/mbgl/style/layers/layer_properties.hpp.ejs
@@ -0,0 +1,48 @@
+<%
+ const type = locals.type;
+ const layoutProperties = locals.layoutProperties;
+ const paintProperties = locals.paintProperties;
+-%>
+// This file is generated. Edit scripts/generate-style-code.js, then run `make style-code`.
+
+#pragma once
+
+#include <mbgl/style/types.hpp>
+#include <mbgl/style/layout_property.hpp>
+#include <mbgl/style/paint_property.hpp>
+
+namespace mbgl {
+namespace style {
+
+class CascadeParameters;
+class CalculationParameters;
+
+<% if (layoutProperties.length) { -%>
+class <%- camelize(type) %>LayoutProperties {
+public:
+ void recalculate(const CalculationParameters&);
+
+<% for (const property of layoutProperties) { -%>
+ LayoutProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> };
+<% } -%>
+};
+
+<% } -%>
+class <%- camelize(type) %>PaintProperties {
+public:
+ void cascade(const CascadeParameters&);
+ bool recalculate(const CalculationParameters&);
+
+<% for (const property of paintProperties) { -%>
+<% if (/-pattern$/.test(property.name) || property.name === 'line-dasharray') { -%>
+ PaintProperty<<%- propertyType(property) %>, CrossFadedPropertyEvaluator> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> };
+<% } else if (property.name === 'fill-outline-color') { -%>
+ PaintProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { { 0, 0, 0, -1 } };
+<% } else { -%>
+ PaintProperty<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %> { <%- defaultValue(property) %> };
+<% } -%>
+<% } -%>
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index abe326a672..3ad72cda16 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -6,10 +6,11 @@
namespace mbgl {
namespace style {
-LineLayer::LineLayer(const std::string& layerID)
+LineLayer::LineLayer(const std::string& layerID, const std::string& sourceID)
: Layer(Type::Line, std::make_unique<Impl>())
, impl(static_cast<Impl*>(baseImpl.get())) {
impl->id = layerID;
+ impl->source = sourceID;
}
LineLayer::LineLayer(const Impl& other)
@@ -23,17 +24,24 @@ std::unique_ptr<Layer> LineLayer::Impl::clone() const {
return std::make_unique<LineLayer>(*this);
}
-// Source
-
-void LineLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
- impl->source = sourceID;
- impl->sourceLayer = sourceLayer;
+std::unique_ptr<Layer> LineLayer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<LineLayer>(*this);
+ result->impl->id = id_;
+ result->impl->ref = this->id;
+ result->impl->paint = LinePaintProperties();
+ return std::move(result);
}
+// Source
+
const std::string& LineLayer::getSourceID() const {
return impl->source;
}
+void LineLayer::setSourceLayer(const std::string& sourceLayer) {
+ impl->sourceLayer = sourceLayer;
+}
+
const std::string& LineLayer::getSourceLayer() const {
return impl->sourceLayer;
}
@@ -85,80 +93,80 @@ PropertyValue<float> LineLayer::getLineOpacity() const {
return impl->paint.lineOpacity.get();
}
-void LineLayer::setLineOpacity(PropertyValue<float> value) {
- impl->paint.lineOpacity.set(value);
+void LineLayer::setLineOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.lineOpacity.set(value, klass);
}
PropertyValue<Color> LineLayer::getLineColor() const {
return impl->paint.lineColor.get();
}
-void LineLayer::setLineColor(PropertyValue<Color> value) {
- impl->paint.lineColor.set(value);
+void LineLayer::setLineColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.lineColor.set(value, klass);
}
PropertyValue<std::array<float, 2>> LineLayer::getLineTranslate() const {
return impl->paint.lineTranslate.get();
}
-void LineLayer::setLineTranslate(PropertyValue<std::array<float, 2>> value) {
- impl->paint.lineTranslate.set(value);
+void LineLayer::setLineTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
+ impl->paint.lineTranslate.set(value, klass);
}
PropertyValue<TranslateAnchorType> LineLayer::getLineTranslateAnchor() const {
return impl->paint.lineTranslateAnchor.get();
}
-void LineLayer::setLineTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
- impl->paint.lineTranslateAnchor.set(value);
+void LineLayer::setLineTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
+ impl->paint.lineTranslateAnchor.set(value, klass);
}
PropertyValue<float> LineLayer::getLineWidth() const {
return impl->paint.lineWidth.get();
}
-void LineLayer::setLineWidth(PropertyValue<float> value) {
- impl->paint.lineWidth.set(value);
+void LineLayer::setLineWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.lineWidth.set(value, klass);
}
PropertyValue<float> LineLayer::getLineGapWidth() const {
return impl->paint.lineGapWidth.get();
}
-void LineLayer::setLineGapWidth(PropertyValue<float> value) {
- impl->paint.lineGapWidth.set(value);
+void LineLayer::setLineGapWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.lineGapWidth.set(value, klass);
}
PropertyValue<float> LineLayer::getLineOffset() const {
return impl->paint.lineOffset.get();
}
-void LineLayer::setLineOffset(PropertyValue<float> value) {
- impl->paint.lineOffset.set(value);
+void LineLayer::setLineOffset(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.lineOffset.set(value, klass);
}
PropertyValue<float> LineLayer::getLineBlur() const {
return impl->paint.lineBlur.get();
}
-void LineLayer::setLineBlur(PropertyValue<float> value) {
- impl->paint.lineBlur.set(value);
+void LineLayer::setLineBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.lineBlur.set(value, klass);
}
PropertyValue<std::vector<float>> LineLayer::getLineDasharray() const {
return impl->paint.lineDasharray.get();
}
-void LineLayer::setLineDasharray(PropertyValue<std::vector<float>> value) {
- impl->paint.lineDasharray.set(value);
+void LineLayer::setLineDasharray(PropertyValue<std::vector<float>> value, const optional<std::string>& klass) {
+ impl->paint.lineDasharray.set(value, klass);
}
PropertyValue<std::string> LineLayer::getLinePattern() const {
return impl->paint.linePattern.get();
}
-void LineLayer::setLinePattern(PropertyValue<std::string> value) {
- impl->paint.linePattern.set(value);
+void LineLayer::setLinePattern(PropertyValue<std::string> value, const optional<std::string>& klass) {
+ impl->paint.linePattern.set(value, klass);
}
} // namespace style
diff --git a/src/mbgl/style/layers/line_layer_impl.cpp b/src/mbgl/style/layers/line_layer_impl.cpp
index b7ee9dc5bf..3cdd90b7fd 100644
--- a/src/mbgl/style/layers/line_layer_impl.cpp
+++ b/src/mbgl/style/layers/line_layer_impl.cpp
@@ -8,14 +8,6 @@
namespace mbgl {
namespace style {
-void LineLayer::Impl::parseLayout(const JSValue& value) {
- layout.parse(value);
-}
-
-void LineLayer::Impl::parsePaints(const JSValue& layer) {
- paint.parse(layer);
-}
-
void LineLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
@@ -29,7 +21,7 @@ bool LineLayer::Impl::recalculate(const CalculationParameters& parameters) {
bool hasTransitions = paint.recalculate(parameters);
- passes = (paint.lineOpacity > 0 && paint.lineColor.value[3] > 0 && paint.lineWidth > 0)
+ passes = (paint.lineOpacity > 0 && paint.lineColor.value.a > 0 && paint.lineWidth > 0)
? RenderPass::Translucent : RenderPass::None;
return hasTransitions;
diff --git a/src/mbgl/style/layers/line_layer_impl.hpp b/src/mbgl/style/layers/line_layer_impl.hpp
index 3356dc2ceb..e130bc01bc 100644
--- a/src/mbgl/style/layers/line_layer_impl.hpp
+++ b/src/mbgl/style/layers/line_layer_impl.hpp
@@ -10,9 +10,7 @@ namespace style {
class LineLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
-
- void parseLayout(const JSValue&) override;
- void parsePaints(const JSValue&) override;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
void cascade(const CascadeParameters&) override;
bool recalculate(const CalculationParameters&) override;
diff --git a/src/mbgl/style/layers/line_layer_properties.cpp b/src/mbgl/style/layers/line_layer_properties.cpp
index 7c74f6de04..2d6092745e 100644
--- a/src/mbgl/style/layers/line_layer_properties.cpp
+++ b/src/mbgl/style/layers/line_layer_properties.cpp
@@ -5,13 +5,6 @@
namespace mbgl {
namespace style {
-void LineLayoutProperties::parse(const JSValue& value) {
- lineCap.parse("line-cap", value);
- lineJoin.parse("line-join", value);
- lineMiterLimit.parse("line-miter-limit", value);
- lineRoundLimit.parse("line-round-limit", value);
-}
-
void LineLayoutProperties::recalculate(const CalculationParameters& parameters) {
lineCap.calculate(parameters);
lineJoin.calculate(parameters);
@@ -19,19 +12,6 @@ void LineLayoutProperties::recalculate(const CalculationParameters& parameters)
lineRoundLimit.calculate(parameters);
}
-void LinePaintProperties::parse(const JSValue& value) {
- lineOpacity.parse("line-opacity", value);
- lineColor.parse("line-color", value);
- lineTranslate.parse("line-translate", value);
- lineTranslateAnchor.parse("line-translate-anchor", value);
- lineWidth.parse("line-width", value);
- lineGapWidth.parse("line-gap-width", value);
- lineOffset.parse("line-offset", value);
- lineBlur.parse("line-blur", value);
- lineDasharray.parse("line-dasharray", value);
- linePattern.parse("line-pattern", value);
-}
-
void LinePaintProperties::cascade(const CascadeParameters& parameters) {
lineOpacity.cascade(parameters);
lineColor.cascade(parameters);
diff --git a/src/mbgl/style/layers/line_layer_properties.hpp b/src/mbgl/style/layers/line_layer_properties.hpp
index 01a8534222..e7dbddf442 100644
--- a/src/mbgl/style/layers/line_layer_properties.hpp
+++ b/src/mbgl/style/layers/line_layer_properties.hpp
@@ -2,9 +2,9 @@
#pragma once
+#include <mbgl/style/types.hpp>
#include <mbgl/style/layout_property.hpp>
#include <mbgl/style/paint_property.hpp>
-#include <mbgl/util/rapidjson.hpp>
namespace mbgl {
namespace style {
@@ -14,7 +14,6 @@ class CalculationParameters;
class LineLayoutProperties {
public:
- void parse(const JSValue&);
void recalculate(const CalculationParameters&);
LayoutProperty<LineCapType> lineCap { LineCapType::Butt };
@@ -25,12 +24,11 @@ public:
class LinePaintProperties {
public:
- void parse(const JSValue&);
void cascade(const CascadeParameters&);
bool recalculate(const CalculationParameters&);
PaintProperty<float> lineOpacity { 1 };
- PaintProperty<Color> lineColor { {{ 0, 0, 0, 1 }} };
+ PaintProperty<Color> lineColor { { 0, 0, 0, 1 } };
PaintProperty<std::array<float, 2>> lineTranslate { {{ 0, 0 }} };
PaintProperty<TranslateAnchorType> lineTranslateAnchor { TranslateAnchorType::Map };
PaintProperty<float> lineWidth { 1 };
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
index fb7f08fbe9..d4e121babe 100644
--- a/src/mbgl/style/layers/raster_layer.cpp
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -6,10 +6,11 @@
namespace mbgl {
namespace style {
-RasterLayer::RasterLayer(const std::string& layerID)
+RasterLayer::RasterLayer(const std::string& layerID, const std::string& sourceID)
: Layer(Type::Raster, std::make_unique<Impl>())
, impl(static_cast<Impl*>(baseImpl.get())) {
impl->id = layerID;
+ impl->source = sourceID;
}
RasterLayer::RasterLayer(const Impl& other)
@@ -23,16 +24,21 @@ std::unique_ptr<Layer> RasterLayer::Impl::clone() const {
return std::make_unique<RasterLayer>(*this);
}
-// Source
-
-void RasterLayer::setSource(const std::string& sourceID) {
- impl->source = sourceID;
+std::unique_ptr<Layer> RasterLayer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<RasterLayer>(*this);
+ result->impl->id = id_;
+ result->impl->ref = this->id;
+ result->impl->paint = RasterPaintProperties();
+ return std::move(result);
}
+// Source
+
const std::string& RasterLayer::getSourceID() const {
return impl->source;
}
+
// Layout properties
@@ -42,56 +48,56 @@ PropertyValue<float> RasterLayer::getRasterOpacity() const {
return impl->paint.rasterOpacity.get();
}
-void RasterLayer::setRasterOpacity(PropertyValue<float> value) {
- impl->paint.rasterOpacity.set(value);
+void RasterLayer::setRasterOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.rasterOpacity.set(value, klass);
}
PropertyValue<float> RasterLayer::getRasterHueRotate() const {
return impl->paint.rasterHueRotate.get();
}
-void RasterLayer::setRasterHueRotate(PropertyValue<float> value) {
- impl->paint.rasterHueRotate.set(value);
+void RasterLayer::setRasterHueRotate(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.rasterHueRotate.set(value, klass);
}
PropertyValue<float> RasterLayer::getRasterBrightnessMin() const {
return impl->paint.rasterBrightnessMin.get();
}
-void RasterLayer::setRasterBrightnessMin(PropertyValue<float> value) {
- impl->paint.rasterBrightnessMin.set(value);
+void RasterLayer::setRasterBrightnessMin(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.rasterBrightnessMin.set(value, klass);
}
PropertyValue<float> RasterLayer::getRasterBrightnessMax() const {
return impl->paint.rasterBrightnessMax.get();
}
-void RasterLayer::setRasterBrightnessMax(PropertyValue<float> value) {
- impl->paint.rasterBrightnessMax.set(value);
+void RasterLayer::setRasterBrightnessMax(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.rasterBrightnessMax.set(value, klass);
}
PropertyValue<float> RasterLayer::getRasterSaturation() const {
return impl->paint.rasterSaturation.get();
}
-void RasterLayer::setRasterSaturation(PropertyValue<float> value) {
- impl->paint.rasterSaturation.set(value);
+void RasterLayer::setRasterSaturation(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.rasterSaturation.set(value, klass);
}
PropertyValue<float> RasterLayer::getRasterContrast() const {
return impl->paint.rasterContrast.get();
}
-void RasterLayer::setRasterContrast(PropertyValue<float> value) {
- impl->paint.rasterContrast.set(value);
+void RasterLayer::setRasterContrast(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.rasterContrast.set(value, klass);
}
PropertyValue<float> RasterLayer::getRasterFadeDuration() const {
return impl->paint.rasterFadeDuration.get();
}
-void RasterLayer::setRasterFadeDuration(PropertyValue<float> value) {
- impl->paint.rasterFadeDuration.set(value);
+void RasterLayer::setRasterFadeDuration(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.rasterFadeDuration.set(value, klass);
}
} // namespace style
diff --git a/src/mbgl/style/layers/raster_layer_impl.cpp b/src/mbgl/style/layers/raster_layer_impl.cpp
index 4854ec041d..879bfa4559 100644
--- a/src/mbgl/style/layers/raster_layer_impl.cpp
+++ b/src/mbgl/style/layers/raster_layer_impl.cpp
@@ -4,10 +4,6 @@
namespace mbgl {
namespace style {
-void RasterLayer::Impl::parsePaints(const JSValue& layer) {
- paint.parse(layer);
-}
-
void RasterLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
diff --git a/src/mbgl/style/layers/raster_layer_impl.hpp b/src/mbgl/style/layers/raster_layer_impl.hpp
index 6812b469a6..a5b396e2ed 100644
--- a/src/mbgl/style/layers/raster_layer_impl.hpp
+++ b/src/mbgl/style/layers/raster_layer_impl.hpp
@@ -10,9 +10,7 @@ namespace style {
class RasterLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
-
- void parseLayout(const JSValue&) override {};
- void parsePaints(const JSValue&) override;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
void cascade(const CascadeParameters&) override;
bool recalculate(const CalculationParameters&) override;
diff --git a/src/mbgl/style/layers/raster_layer_properties.cpp b/src/mbgl/style/layers/raster_layer_properties.cpp
index 0e6afc5e9c..68d9d1d35d 100644
--- a/src/mbgl/style/layers/raster_layer_properties.cpp
+++ b/src/mbgl/style/layers/raster_layer_properties.cpp
@@ -5,16 +5,6 @@
namespace mbgl {
namespace style {
-void RasterPaintProperties::parse(const JSValue& value) {
- rasterOpacity.parse("raster-opacity", value);
- rasterHueRotate.parse("raster-hue-rotate", value);
- rasterBrightnessMin.parse("raster-brightness-min", value);
- rasterBrightnessMax.parse("raster-brightness-max", value);
- rasterSaturation.parse("raster-saturation", value);
- rasterContrast.parse("raster-contrast", value);
- rasterFadeDuration.parse("raster-fade-duration", value);
-}
-
void RasterPaintProperties::cascade(const CascadeParameters& parameters) {
rasterOpacity.cascade(parameters);
rasterHueRotate.cascade(parameters);
diff --git a/src/mbgl/style/layers/raster_layer_properties.hpp b/src/mbgl/style/layers/raster_layer_properties.hpp
index 049da87312..ddfb833e12 100644
--- a/src/mbgl/style/layers/raster_layer_properties.hpp
+++ b/src/mbgl/style/layers/raster_layer_properties.hpp
@@ -2,9 +2,9 @@
#pragma once
+#include <mbgl/style/types.hpp>
#include <mbgl/style/layout_property.hpp>
#include <mbgl/style/paint_property.hpp>
-#include <mbgl/util/rapidjson.hpp>
namespace mbgl {
namespace style {
@@ -14,7 +14,6 @@ class CalculationParameters;
class RasterPaintProperties {
public:
- void parse(const JSValue&);
void cascade(const CascadeParameters&);
bool recalculate(const CalculationParameters&);
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index d7d6a02ace..c26123f0ec 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -6,10 +6,11 @@
namespace mbgl {
namespace style {
-SymbolLayer::SymbolLayer(const std::string& layerID)
+SymbolLayer::SymbolLayer(const std::string& layerID, const std::string& sourceID)
: Layer(Type::Symbol, std::make_unique<Impl>())
, impl(static_cast<Impl*>(baseImpl.get())) {
impl->id = layerID;
+ impl->source = sourceID;
}
SymbolLayer::SymbolLayer(const Impl& other)
@@ -23,17 +24,24 @@ std::unique_ptr<Layer> SymbolLayer::Impl::clone() const {
return std::make_unique<SymbolLayer>(*this);
}
-// Source
-
-void SymbolLayer::setSource(const std::string& sourceID, const std::string& sourceLayer) {
- impl->source = sourceID;
- impl->sourceLayer = sourceLayer;
+std::unique_ptr<Layer> SymbolLayer::Impl::cloneRef(const std::string& id_) const {
+ auto result = std::make_unique<SymbolLayer>(*this);
+ result->impl->id = id_;
+ result->impl->ref = this->id;
+ result->impl->paint = SymbolPaintProperties();
+ return std::move(result);
}
+// Source
+
const std::string& SymbolLayer::getSourceID() const {
return impl->source;
}
+void SymbolLayer::setSourceLayer(const std::string& sourceLayer) {
+ impl->sourceLayer = sourceLayer;
+}
+
const std::string& SymbolLayer::getSourceLayer() const {
return impl->sourceLayer;
}
@@ -92,11 +100,11 @@ PropertyValue<bool> SymbolLayer::getIconOptional() const {
void SymbolLayer::setIconOptional(PropertyValue<bool> value) {
impl->layout.iconOptional.set(value);
}
-PropertyValue<RotationAlignmentType> SymbolLayer::getIconRotationAlignment() const {
+PropertyValue<AlignmentType> SymbolLayer::getIconRotationAlignment() const {
return impl->layout.iconRotationAlignment.get();
}
-void SymbolLayer::setIconRotationAlignment(PropertyValue<RotationAlignmentType> value) {
+void SymbolLayer::setIconRotationAlignment(PropertyValue<AlignmentType> value) {
impl->layout.iconRotationAlignment.set(value);
}
PropertyValue<float> SymbolLayer::getIconSize() const {
@@ -106,6 +114,20 @@ PropertyValue<float> SymbolLayer::getIconSize() const {
void SymbolLayer::setIconSize(PropertyValue<float> value) {
impl->layout.iconSize.set(value);
}
+PropertyValue<IconTextFitType> SymbolLayer::getIconTextFit() const {
+ return impl->layout.iconTextFit.get();
+}
+
+void SymbolLayer::setIconTextFit(PropertyValue<IconTextFitType> value) {
+ impl->layout.iconTextFit.set(value);
+}
+PropertyValue<std::array<float, 4>> SymbolLayer::getIconTextFitPadding() const {
+ return impl->layout.iconTextFitPadding.get();
+}
+
+void SymbolLayer::setIconTextFitPadding(PropertyValue<std::array<float, 4>> value) {
+ impl->layout.iconTextFitPadding.set(value);
+}
PropertyValue<std::string> SymbolLayer::getIconImage() const {
return impl->layout.iconImage.get();
}
@@ -141,11 +163,18 @@ PropertyValue<std::array<float, 2>> SymbolLayer::getIconOffset() const {
void SymbolLayer::setIconOffset(PropertyValue<std::array<float, 2>> value) {
impl->layout.iconOffset.set(value);
}
-PropertyValue<RotationAlignmentType> SymbolLayer::getTextRotationAlignment() const {
+PropertyValue<AlignmentType> SymbolLayer::getTextPitchAlignment() const {
+ return impl->layout.textPitchAlignment.get();
+}
+
+void SymbolLayer::setTextPitchAlignment(PropertyValue<AlignmentType> value) {
+ impl->layout.textPitchAlignment.set(value);
+}
+PropertyValue<AlignmentType> SymbolLayer::getTextRotationAlignment() const {
return impl->layout.textRotationAlignment.get();
}
-void SymbolLayer::setTextRotationAlignment(PropertyValue<RotationAlignmentType> value) {
+void SymbolLayer::setTextRotationAlignment(PropertyValue<AlignmentType> value) {
impl->layout.textRotationAlignment.set(value);
}
PropertyValue<std::string> SymbolLayer::getTextField() const {
@@ -274,112 +303,112 @@ PropertyValue<float> SymbolLayer::getIconOpacity() const {
return impl->paint.iconOpacity.get();
}
-void SymbolLayer::setIconOpacity(PropertyValue<float> value) {
- impl->paint.iconOpacity.set(value);
+void SymbolLayer::setIconOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.iconOpacity.set(value, klass);
}
PropertyValue<Color> SymbolLayer::getIconColor() const {
return impl->paint.iconColor.get();
}
-void SymbolLayer::setIconColor(PropertyValue<Color> value) {
- impl->paint.iconColor.set(value);
+void SymbolLayer::setIconColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.iconColor.set(value, klass);
}
PropertyValue<Color> SymbolLayer::getIconHaloColor() const {
return impl->paint.iconHaloColor.get();
}
-void SymbolLayer::setIconHaloColor(PropertyValue<Color> value) {
- impl->paint.iconHaloColor.set(value);
+void SymbolLayer::setIconHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.iconHaloColor.set(value, klass);
}
PropertyValue<float> SymbolLayer::getIconHaloWidth() const {
return impl->paint.iconHaloWidth.get();
}
-void SymbolLayer::setIconHaloWidth(PropertyValue<float> value) {
- impl->paint.iconHaloWidth.set(value);
+void SymbolLayer::setIconHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.iconHaloWidth.set(value, klass);
}
PropertyValue<float> SymbolLayer::getIconHaloBlur() const {
return impl->paint.iconHaloBlur.get();
}
-void SymbolLayer::setIconHaloBlur(PropertyValue<float> value) {
- impl->paint.iconHaloBlur.set(value);
+void SymbolLayer::setIconHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.iconHaloBlur.set(value, klass);
}
PropertyValue<std::array<float, 2>> SymbolLayer::getIconTranslate() const {
return impl->paint.iconTranslate.get();
}
-void SymbolLayer::setIconTranslate(PropertyValue<std::array<float, 2>> value) {
- impl->paint.iconTranslate.set(value);
+void SymbolLayer::setIconTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
+ impl->paint.iconTranslate.set(value, klass);
}
PropertyValue<TranslateAnchorType> SymbolLayer::getIconTranslateAnchor() const {
return impl->paint.iconTranslateAnchor.get();
}
-void SymbolLayer::setIconTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
- impl->paint.iconTranslateAnchor.set(value);
+void SymbolLayer::setIconTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
+ impl->paint.iconTranslateAnchor.set(value, klass);
}
PropertyValue<float> SymbolLayer::getTextOpacity() const {
return impl->paint.textOpacity.get();
}
-void SymbolLayer::setTextOpacity(PropertyValue<float> value) {
- impl->paint.textOpacity.set(value);
+void SymbolLayer::setTextOpacity(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.textOpacity.set(value, klass);
}
PropertyValue<Color> SymbolLayer::getTextColor() const {
return impl->paint.textColor.get();
}
-void SymbolLayer::setTextColor(PropertyValue<Color> value) {
- impl->paint.textColor.set(value);
+void SymbolLayer::setTextColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.textColor.set(value, klass);
}
PropertyValue<Color> SymbolLayer::getTextHaloColor() const {
return impl->paint.textHaloColor.get();
}
-void SymbolLayer::setTextHaloColor(PropertyValue<Color> value) {
- impl->paint.textHaloColor.set(value);
+void SymbolLayer::setTextHaloColor(PropertyValue<Color> value, const optional<std::string>& klass) {
+ impl->paint.textHaloColor.set(value, klass);
}
PropertyValue<float> SymbolLayer::getTextHaloWidth() const {
return impl->paint.textHaloWidth.get();
}
-void SymbolLayer::setTextHaloWidth(PropertyValue<float> value) {
- impl->paint.textHaloWidth.set(value);
+void SymbolLayer::setTextHaloWidth(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.textHaloWidth.set(value, klass);
}
PropertyValue<float> SymbolLayer::getTextHaloBlur() const {
return impl->paint.textHaloBlur.get();
}
-void SymbolLayer::setTextHaloBlur(PropertyValue<float> value) {
- impl->paint.textHaloBlur.set(value);
+void SymbolLayer::setTextHaloBlur(PropertyValue<float> value, const optional<std::string>& klass) {
+ impl->paint.textHaloBlur.set(value, klass);
}
PropertyValue<std::array<float, 2>> SymbolLayer::getTextTranslate() const {
return impl->paint.textTranslate.get();
}
-void SymbolLayer::setTextTranslate(PropertyValue<std::array<float, 2>> value) {
- impl->paint.textTranslate.set(value);
+void SymbolLayer::setTextTranslate(PropertyValue<std::array<float, 2>> value, const optional<std::string>& klass) {
+ impl->paint.textTranslate.set(value, klass);
}
PropertyValue<TranslateAnchorType> SymbolLayer::getTextTranslateAnchor() const {
return impl->paint.textTranslateAnchor.get();
}
-void SymbolLayer::setTextTranslateAnchor(PropertyValue<TranslateAnchorType> value) {
- impl->paint.textTranslateAnchor.set(value);
+void SymbolLayer::setTextTranslateAnchor(PropertyValue<TranslateAnchorType> value, const optional<std::string>& klass) {
+ impl->paint.textTranslateAnchor.set(value, klass);
}
} // namespace style
diff --git a/src/mbgl/style/layers/symbol_layer_impl.cpp b/src/mbgl/style/layers/symbol_layer_impl.cpp
index a4dc264ed2..0243b1dfa5 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.cpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.cpp
@@ -5,14 +5,6 @@
namespace mbgl {
namespace style {
-void SymbolLayer::Impl::parseLayout(const JSValue& value) {
- layout.parse(value);
-}
-
-void SymbolLayer::Impl::parsePaints(const JSValue& layer) {
- paint.parse(layer);
-}
-
void SymbolLayer::Impl::cascade(const CascadeParameters& parameters) {
paint.cascade(parameters);
}
@@ -26,8 +18,8 @@ bool SymbolLayer::Impl::recalculate(const CalculationParameters& parameters) {
iconSize = layout.iconSize;
textSize = layout.textSize;
- passes = ((paint.iconOpacity > 0 && (paint.iconColor.value[3] > 0 || paint.iconHaloColor.value[3] > 0) && iconSize > 0)
- || (paint.textOpacity > 0 && (paint.textColor.value[3] > 0 || paint.textHaloColor.value[3] > 0) && textSize > 0))
+ passes = ((paint.iconOpacity > 0 && (paint.iconColor.value.a > 0 || paint.iconHaloColor.value.a > 0) && iconSize > 0)
+ || (paint.textOpacity > 0 && (paint.textColor.value.a > 0 || paint.textHaloColor.value.a > 0) && textSize > 0))
? RenderPass::Translucent : RenderPass::None;
return hasTransitions;
@@ -45,8 +37,13 @@ std::unique_ptr<Bucket> SymbolLayer::Impl::createBucket(BucketParameters& parame
CalculationParameters p(parameters.tileID.overscaledZ);
bucket->layout.symbolPlacement.calculate(p);
if (bucket->layout.symbolPlacement.value == SymbolPlacementType::Line) {
- bucket->layout.iconRotationAlignment.value = RotationAlignmentType::Map;
- bucket->layout.textRotationAlignment.value = RotationAlignmentType::Map;
+ bucket->layout.iconRotationAlignment.value = AlignmentType::Map;
+ bucket->layout.textRotationAlignment.value = AlignmentType::Map;
+ };
+
+ // If unspecified `text-pitch-alignment` inherits `text-rotation-alignment`
+ if (bucket->layout.textPitchAlignment.value == AlignmentType::Undefined) {
+ bucket->layout.textPitchAlignment.value = bucket->layout.textRotationAlignment.value;
};
bucket->layout.recalculate(p);
diff --git a/src/mbgl/style/layers/symbol_layer_impl.hpp b/src/mbgl/style/layers/symbol_layer_impl.hpp
index 9727cc6480..7765d6790e 100644
--- a/src/mbgl/style/layers/symbol_layer_impl.hpp
+++ b/src/mbgl/style/layers/symbol_layer_impl.hpp
@@ -13,9 +13,7 @@ namespace style {
class SymbolLayer::Impl : public Layer::Impl {
public:
std::unique_ptr<Layer> clone() const override;
-
- void parseLayout(const JSValue&) override;
- void parsePaints(const JSValue&) override;
+ std::unique_ptr<Layer> cloneRef(const std::string& id) const override;
void cascade(const CascadeParameters&) override;
bool recalculate(const CalculationParameters&) override;
diff --git a/src/mbgl/style/layers/symbol_layer_properties.cpp b/src/mbgl/style/layers/symbol_layer_properties.cpp
index ce16ae2e50..59a73d3d59 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.cpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.cpp
@@ -5,40 +5,6 @@
namespace mbgl {
namespace style {
-void SymbolLayoutProperties::parse(const JSValue& value) {
- symbolPlacement.parse("symbol-placement", value);
- symbolSpacing.parse("symbol-spacing", value);
- symbolAvoidEdges.parse("symbol-avoid-edges", value);
- iconAllowOverlap.parse("icon-allow-overlap", value);
- iconIgnorePlacement.parse("icon-ignore-placement", value);
- iconOptional.parse("icon-optional", value);
- iconRotationAlignment.parse("icon-rotation-alignment", value);
- iconSize.parse("icon-size", value);
- iconImage.parse("icon-image", value);
- iconRotate.parse("icon-rotate", value);
- iconPadding.parse("icon-padding", value);
- iconKeepUpright.parse("icon-keep-upright", value);
- iconOffset.parse("icon-offset", value);
- textRotationAlignment.parse("text-rotation-alignment", value);
- textField.parse("text-field", value);
- textFont.parse("text-font", value);
- textSize.parse("text-size", value);
- textMaxWidth.parse("text-max-width", value);
- textLineHeight.parse("text-line-height", value);
- textLetterSpacing.parse("text-letter-spacing", value);
- textJustify.parse("text-justify", value);
- textAnchor.parse("text-anchor", value);
- textMaxAngle.parse("text-max-angle", value);
- textRotate.parse("text-rotate", value);
- textPadding.parse("text-padding", value);
- textKeepUpright.parse("text-keep-upright", value);
- textTransform.parse("text-transform", value);
- textOffset.parse("text-offset", value);
- textAllowOverlap.parse("text-allow-overlap", value);
- textIgnorePlacement.parse("text-ignore-placement", value);
- textOptional.parse("text-optional", value);
-}
-
void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters) {
symbolPlacement.calculate(parameters);
symbolSpacing.calculate(parameters);
@@ -48,11 +14,14 @@ void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters
iconOptional.calculate(parameters);
iconRotationAlignment.calculate(parameters);
iconSize.calculate(parameters);
+ iconTextFit.calculate(parameters);
+ iconTextFitPadding.calculate(parameters);
iconImage.calculate(parameters);
iconRotate.calculate(parameters);
iconPadding.calculate(parameters);
iconKeepUpright.calculate(parameters);
iconOffset.calculate(parameters);
+ textPitchAlignment.calculate(parameters);
textRotationAlignment.calculate(parameters);
textField.calculate(parameters);
textFont.calculate(parameters);
@@ -73,23 +42,6 @@ void SymbolLayoutProperties::recalculate(const CalculationParameters& parameters
textOptional.calculate(parameters);
}
-void SymbolPaintProperties::parse(const JSValue& value) {
- iconOpacity.parse("icon-opacity", value);
- iconColor.parse("icon-color", value);
- iconHaloColor.parse("icon-halo-color", value);
- iconHaloWidth.parse("icon-halo-width", value);
- iconHaloBlur.parse("icon-halo-blur", value);
- iconTranslate.parse("icon-translate", value);
- iconTranslateAnchor.parse("icon-translate-anchor", value);
- textOpacity.parse("text-opacity", value);
- textColor.parse("text-color", value);
- textHaloColor.parse("text-halo-color", value);
- textHaloWidth.parse("text-halo-width", value);
- textHaloBlur.parse("text-halo-blur", value);
- textTranslate.parse("text-translate", value);
- textTranslateAnchor.parse("text-translate-anchor", value);
-}
-
void SymbolPaintProperties::cascade(const CascadeParameters& parameters) {
iconOpacity.cascade(parameters);
iconColor.cascade(parameters);
diff --git a/src/mbgl/style/layers/symbol_layer_properties.hpp b/src/mbgl/style/layers/symbol_layer_properties.hpp
index 38455b5cac..a269969cb8 100644
--- a/src/mbgl/style/layers/symbol_layer_properties.hpp
+++ b/src/mbgl/style/layers/symbol_layer_properties.hpp
@@ -2,9 +2,9 @@
#pragma once
+#include <mbgl/style/types.hpp>
#include <mbgl/style/layout_property.hpp>
#include <mbgl/style/paint_property.hpp>
-#include <mbgl/util/rapidjson.hpp>
namespace mbgl {
namespace style {
@@ -14,7 +14,6 @@ class CalculationParameters;
class SymbolLayoutProperties {
public:
- void parse(const JSValue&);
void recalculate(const CalculationParameters&);
LayoutProperty<SymbolPlacementType> symbolPlacement { SymbolPlacementType::Point };
@@ -23,14 +22,17 @@ public:
LayoutProperty<bool> iconAllowOverlap { false };
LayoutProperty<bool> iconIgnorePlacement { false };
LayoutProperty<bool> iconOptional { false };
- LayoutProperty<RotationAlignmentType> iconRotationAlignment { RotationAlignmentType::Viewport };
+ LayoutProperty<AlignmentType> iconRotationAlignment { AlignmentType::Viewport };
LayoutProperty<float> iconSize { 1 };
+ LayoutProperty<IconTextFitType> iconTextFit { IconTextFitType::None };
+ LayoutProperty<std::array<float, 4>> iconTextFitPadding { {{ 0, 0, 0, 0 }} };
LayoutProperty<std::string> iconImage { "" };
LayoutProperty<float> iconRotate { 0 };
LayoutProperty<float> iconPadding { 2 };
LayoutProperty<bool> iconKeepUpright { false };
LayoutProperty<std::array<float, 2>> iconOffset { {{ 0, 0 }} };
- LayoutProperty<RotationAlignmentType> textRotationAlignment { RotationAlignmentType::Viewport };
+ LayoutProperty<AlignmentType> textPitchAlignment { AlignmentType::Undefined };
+ LayoutProperty<AlignmentType> textRotationAlignment { AlignmentType::Viewport };
LayoutProperty<std::string> textField { "" };
LayoutProperty<std::vector<std::string>> textFont { { "Open Sans Regular", "Arial Unicode MS Regular" } };
LayoutProperty<float> textSize { 16 };
@@ -52,20 +54,19 @@ public:
class SymbolPaintProperties {
public:
- void parse(const JSValue&);
void cascade(const CascadeParameters&);
bool recalculate(const CalculationParameters&);
PaintProperty<float> iconOpacity { 1 };
- PaintProperty<Color> iconColor { {{ 0, 0, 0, 1 }} };
- PaintProperty<Color> iconHaloColor { {{ 0, 0, 0, 0 }} };
+ PaintProperty<Color> iconColor { { 0, 0, 0, 1 } };
+ PaintProperty<Color> iconHaloColor { { 0, 0, 0, 0 } };
PaintProperty<float> iconHaloWidth { 0 };
PaintProperty<float> iconHaloBlur { 0 };
PaintProperty<std::array<float, 2>> iconTranslate { {{ 0, 0 }} };
PaintProperty<TranslateAnchorType> iconTranslateAnchor { TranslateAnchorType::Map };
PaintProperty<float> textOpacity { 1 };
- PaintProperty<Color> textColor { {{ 0, 0, 0, 1 }} };
- PaintProperty<Color> textHaloColor { {{ 0, 0, 0, 0 }} };
+ PaintProperty<Color> textColor { { 0, 0, 0, 1 } };
+ PaintProperty<Color> textHaloColor { { 0, 0, 0, 0 } };
PaintProperty<float> textHaloWidth { 0 };
PaintProperty<float> textHaloBlur { 0 };
PaintProperty<std::array<float, 2>> textTranslate { {{ 0, 0 }} };
diff --git a/src/mbgl/style/layout_property.hpp b/src/mbgl/style/layout_property.hpp
index f5045b47fc..db1a1ebf28 100644
--- a/src/mbgl/style/layout_property.hpp
+++ b/src/mbgl/style/layout_property.hpp
@@ -3,7 +3,6 @@
#include <mbgl/style/property_value.hpp>
#include <mbgl/style/property_parsing.hpp>
#include <mbgl/style/property_evaluator.hpp>
-#include <mbgl/util/rapidjson.hpp>
#include <utility>
@@ -25,12 +24,6 @@ public:
currentValue = value_;
}
- void parse(const char * name, const JSValue& layout) {
- if (layout.HasMember(name)) {
- currentValue = parseProperty<T>(name, layout[name]);
- }
- }
-
void calculate(const CalculationParameters& parameters) {
if (currentValue) {
PropertyEvaluator<T> evaluator(parameters, defaultValue);
diff --git a/src/mbgl/style/observer.hpp b/src/mbgl/style/observer.hpp
index c19f58904f..2c48114669 100644
--- a/src/mbgl/style/observer.hpp
+++ b/src/mbgl/style/observer.hpp
@@ -15,10 +15,10 @@ public:
* In addition to the individual glyph, sprite, and source events, the
* following "rollup" events are provided for convenience. They are
* strictly additive; e.g. when a source is loaded, both `onSourceLoaded`
- * and `onResourceLoaded` will be called.
+ * and `onNeedsRepaint` will be called.
*/
- virtual void onResourceLoaded() {};
- virtual void onResourceError(std::exception_ptr) {};
+ void onNeedsRepaint() override {}
+ virtual void onResourceError(std::exception_ptr) {}
};
} // namespace style
diff --git a/src/mbgl/style/paint_property.hpp b/src/mbgl/style/paint_property.hpp
index 62fd59684e..b982fe76e2 100644
--- a/src/mbgl/style/paint_property.hpp
+++ b/src/mbgl/style/paint_property.hpp
@@ -6,8 +6,8 @@
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/cascade_parameters.hpp>
#include <mbgl/style/calculation_parameters.hpp>
+#include <mbgl/util/constants.hpp>
#include <mbgl/util/interpolate.hpp>
-#include <mbgl/util/std.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <map>
@@ -27,47 +27,28 @@ public:
}
PaintProperty(const PaintProperty& other)
- : values(other.values),
+ : defaultValue(other.defaultValue),
+ values(other.values),
transitions(other.transitions) {
}
+ PaintProperty& operator=(const PaintProperty& other) {
+ defaultValue = other.defaultValue;
+ values = other.values;
+ transitions = other.transitions;
+ return *this;
+ }
+
const PropertyValue<T>& get() const {
return values.at(ClassID::Default);
}
- void set(const PropertyValue<T>& value_) {
- values.emplace(ClassID::Default, value_);
+ void set(const PropertyValue<T>& value_, const optional<std::string>& klass) {
+ values[klass ? ClassDictionary::Get().lookup(*klass) : ClassID::Default] = value_;
}
- void parse(const char* name, const JSValue& layer) {
- mbgl::util::erase_if(values, [] (const auto& p) { return p.first != ClassID::Fallback; });
-
- std::string transitionName = { name };
- transitionName += "-transition";
-
- for (auto it = layer.MemberBegin(); it != layer.MemberEnd(); ++it) {
- const std::string paintName { it->name.GetString(), it->name.GetStringLength() };
- if (paintName.compare(0, 5, "paint") != 0)
- continue;
-
- bool isClass = paintName.compare(0, 6, "paint.") == 0;
- if (isClass && paintName.length() <= 6)
- continue;
-
- ClassID classID = isClass ? ClassDictionary::Get().lookup(paintName.substr(6)) : ClassID::Default;
-
- if (it->value.HasMember(name)) {
- if (auto v = parseProperty<T>(name, it->value[name])) {
- values.emplace(classID, v);
- }
- }
-
- if (it->value.HasMember(transitionName.c_str())) {
- if (auto v = parseTransitionOptions(name, it->value[transitionName.c_str()])) {
- transitions.emplace(classID, *v);
- }
- }
- }
+ void setTransition(const TransitionOptions& transition, const optional<std::string>& klass) {
+ transitions[klass ? ClassDictionary::Get().lookup(*klass) : ClassID::Default] = transition;
}
void cascade(const CascadeParameters& params) {
@@ -118,24 +99,24 @@ private:
TimePoint end_,
PropertyValue<T> value_)
: prior(std::move(prior_)),
- begin(begin_),
- end(end_),
+ begin(std::move(begin_)),
+ end(std::move(end_)),
value(std::move(value_)) {
}
Result calculate(const Evaluator<T>& evaluator, const TimePoint& now) {
- Result final = PropertyValue<T>::visit(value, evaluator);
+ Result finalValue = PropertyValue<T>::visit(value, evaluator);
if (!prior) {
// No prior value.
- return final;
+ return finalValue;
} else if (now >= end) {
// Transition from prior value is now complete.
prior.reset();
- return final;
+ return finalValue;
} else {
// Interpolate between recursively-calculated prior value and final.
float t = std::chrono::duration<float>(now - begin) / (end - begin);
- return util::interpolate(prior->calculate(evaluator, now), final, t);
+ return util::interpolate(prior->calculate(evaluator, now), finalValue, util::DEFAULT_TRANSITION_EASE.solve(t, 0.001));
}
}
diff --git a/src/mbgl/style/parser.cpp b/src/mbgl/style/parser.cpp
index 28a7d2e81b..41b23c1bae 100644
--- a/src/mbgl/style/parser.cpp
+++ b/src/mbgl/style/parser.cpp
@@ -1,107 +1,23 @@
#include <mbgl/style/parser.hpp>
#include <mbgl/style/layer_impl.hpp>
-#include <mbgl/style/layers/fill_layer.hpp>
-#include <mbgl/style/layers/line_layer.hpp>
-#include <mbgl/style/layers/circle_layer.hpp>
-#include <mbgl/style/layers/symbol_layer.hpp>
-#include <mbgl/style/layers/raster_layer.hpp>
-#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/conversion/source.hpp>
+#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/platform/log.hpp>
#include <mapbox/geojsonvt.hpp>
-#include <mapbox/geojsonvt/convert.hpp>
-
-#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/util/mapbox.hpp>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#include <algorithm>
-#include <sstream>
#include <set>
namespace mbgl {
namespace style {
-namespace {
-
-void parseTileJSONMember(const JSValue& value, std::vector<std::string>& target, const char* name) {
- if (!value.HasMember(name)) {
- return;
- }
-
- const JSValue& property = value[name];
- if (!property.IsArray()) {
- return;
- }
-
- for (rapidjson::SizeType i = 0; i < property.Size(); i++) {
- if (!property[i].IsString()) {
- return;
- }
- }
-
- for (rapidjson::SizeType i = 0; i < property.Size(); i++) {
- target.emplace_back(std::string(property[i].GetString(), property[i].GetStringLength()));
- }
-}
-
-void parseTileJSONMember(const JSValue& value, std::string& target, const char* name) {
- if (!value.HasMember(name)) {
- return;
- }
-
- const JSValue& property = value[name];
- if (!property.IsString()) {
- return;
- }
-
- target = { property.GetString(), property.GetStringLength() };
-}
-
-void parseTileJSONMember(const JSValue& value, uint8_t& target, const char* name) {
- if (!value.HasMember(name)) {
- return;
- }
-
- const JSValue& property = value[name];
- if (!property.IsUint()) {
- return;
- }
-
- unsigned int uint = property.GetUint();
- if (uint > std::numeric_limits<uint8_t>::max()) {
- return;
- }
-
- target = uint;
-}
-
-void parseTileJSONMember(const JSValue& value, std::array<double, 4>& target, const char* name) {
- if (!value.HasMember(name)) {
- return;
- }
-
- const JSValue& property = value[name];
- if (!property.IsArray() || property.Size() > 4) {
- return;
- }
-
- for (rapidjson::SizeType i = 0; i < property.Size(); i++) {
- if (!property[i].IsNumber()) {
- return;
- }
- }
-
- for (rapidjson::SizeType i = 0; i < property.Size(); i++) {
- target[i] = property[i].GetDouble();
- }
-}
-
-} // end namespace
-
Parser::~Parser() = default;
void Parser::parse(const std::string& json) {
@@ -149,156 +65,21 @@ void Parser::parseSources(const JSValue& value) {
return;
}
- JSValue::ConstMemberIterator itr = value.MemberBegin();
- for (; itr != value.MemberEnd(); ++itr) {
- const JSValue& nameVal = itr->name;
- const JSValue& sourceVal = itr->value;
-
- if (!sourceVal.HasMember("type")) {
- Log::Warning(Event::ParseStyle, "source must have a type");
- continue;
- }
-
- const JSValue& typeVal = sourceVal["type"];
- if (!typeVal.IsString()) {
- Log::Warning(Event::ParseStyle, "source type must have one of the enum values");
- continue;
- }
-
- const auto type = SourceTypeClass({ typeVal.GetString(), typeVal.GetStringLength() });
-
- // Sources can have URLs, either because they reference an external TileJSON file, or
- // because reference a GeoJSON file. They don't have to have one though when all source
- // parameters are specified inline.
- std::string url;
-
- uint16_t tileSize = util::tileSize;
-
- std::unique_ptr<Tileset> tileset;
- std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> geojsonvt;
-
- switch (type) {
- case SourceType::Raster:
- if (sourceVal.HasMember("tileSize")) {
- const JSValue& tileSizeVal = sourceVal["tileSize"];
- if (tileSizeVal.IsNumber() && tileSizeVal.GetUint64() <= std::numeric_limits<uint16_t>::max()) {
- tileSize = tileSizeVal.GetUint64();
- } else {
- Log::Error(Event::ParseStyle, "invalid tileSize");
- continue;
- }
- }
- // Fall through. Vector sources are forbidden from having a tileSize.
-
- case SourceType::Vector:
- if (sourceVal.HasMember("url")) {
- const JSValue& urlVal = sourceVal["url"];
- if (urlVal.IsString()) {
- url = { urlVal.GetString(), urlVal.GetStringLength() };
- } else {
- Log::Error(Event::ParseStyle, "source url must be a string");
- continue;
- }
- } else {
- tileset = parseTileJSON(sourceVal);
- }
- break;
-
- case SourceType::GeoJSON:
- tileset = std::make_unique<Tileset>();
-
- // We should probably split this up to have URLs in the url property, and actual data
- // in the data property. Until then, we're going to detect the content based on the
- // object type.
- if (sourceVal.HasMember("data")) {
- const JSValue& dataVal = sourceVal["data"];
- if (dataVal.IsString()) {
- // We need to load an external GeoJSON file
- url = { dataVal.GetString(), dataVal.GetStringLength() };
- } else if (dataVal.IsObject()) {
- // We need to parse dataVal as a GeoJSON object
- geojsonvt = parseGeoJSON(dataVal);
- tileset->maxZoom = geojsonvt->options.maxZoom;
- } else {
- Log::Error(Event::ParseStyle, "GeoJSON data must be a URL or an object");
- continue;
- }
- } else {
- Log::Error(Event::ParseStyle, "GeoJSON source must have a data value");
- continue;
- }
-
- break;
+ for (auto it = value.MemberBegin(); it != value.MemberEnd(); ++it) {
+ std::string id = *conversion::toString(it->name);
- default:
- Log::Error(Event::ParseStyle, "source type '%s' is not supported", typeVal.GetString());
+ conversion::Result<std::unique_ptr<Source>> source
+ = conversion::convert<std::unique_ptr<Source>>(it->value, id);
+ if (!source) {
+ Log::Warning(Event::ParseStyle, source.error().message);
continue;
}
- const std::string id { nameVal.GetString(), nameVal.GetStringLength() };
- std::unique_ptr<Source> source = std::make_unique<Source>(type, id, url, tileSize, std::move(tileset), std::move(geojsonvt));
-
- sourcesMap.emplace(id, source.get());
- sources.emplace_back(std::move(source));
+ sourcesMap.emplace(id, (*source).get());
+ sources.emplace_back(std::move(*source));
}
}
-std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> parseGeoJSON(const JSValue& value) {
- using namespace mapbox::geojsonvt;
-
- Options options;
- options.buffer = util::EXTENT / util::tileSize * 128;
- options.extent = util::EXTENT;
-
- try {
- return std::make_unique<GeoJSONVT>(Convert::convert(value, 0), options);
- } catch (const std::exception& ex) {
- Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", ex.what());
- // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for
- // tiles to load.
- return std::make_unique<GeoJSONVT>(std::vector<ProjectedFeature>{}, options);
- }
-}
-
-std::unique_ptr<Tileset> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) {
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
- document.Parse<0>(json.c_str());
-
- if (document.HasParseError()) {
- std::stringstream message;
- message << document.GetErrorOffset() << " - " << rapidjson::GetParseError_En(document.GetParseError());
- throw std::runtime_error(message.str());
- }
-
- std::unique_ptr<Tileset> result = parseTileJSON(document);
-
- // TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with.
- if (util::mapbox::isMapboxURL(sourceURL)) {
- for (auto& url : result->tiles) {
- url = util::mapbox::canonicalizeTileURL(url, type, tileSize);
- }
- }
-
- return result;
-}
-
-std::unique_ptr<Tileset> parseTileJSON(const JSValue& value) {
- auto tileset = std::make_unique<Tileset>();
- parseTileJSONMember(value, tileset->tiles, "tiles");
- parseTileJSONMember(value, tileset->minZoom, "minzoom");
- parseTileJSONMember(value, tileset->maxZoom, "maxzoom");
- parseTileJSONMember(value, tileset->attribution, "attribution");
-
- std::array<double, 4> array;
- parseTileJSONMember(value, array, "center");
- tileset->center = { array[0], array[1] };
- tileset->zoom = array[2];
- parseTileJSONMember(value, array, "bounds");
- tileset->bounds = LatLngBounds::hull({ array[0], array[1] }, { array[2], array[3] });
-
- return tileset;
-}
-
void Parser::parseLayers(const JSValue& value) {
std::vector<std::string> ids;
@@ -392,275 +173,15 @@ void Parser::parseLayer(const std::string& id, const JSValue& value, std::unique
return;
}
- layer = reference->copy(id, ref);
- layer->baseImpl->parsePaints(value);
+ layer = reference->baseImpl->cloneRef(id);
+ conversion::setPaintProperties(*layer, value);
} else {
- // Otherwise, parse the source/source-layer/filter/render keys to form the bucket.
- if (!value.HasMember("type")) {
- Log::Warning(Event::ParseStyle, "layer '%s' is missing a type", id.c_str());
- return;
- }
-
- const JSValue& typeVal = value["type"];
- if (!typeVal.IsString()) {
- Log::Warning(Event::ParseStyle, "layer '%s' has an invalid type", id.c_str());
+ conversion::Result<std::unique_ptr<Layer>> converted = conversion::convert<std::unique_ptr<Layer>>(value);
+ if (!converted) {
+ Log::Warning(Event::ParseStyle, converted.error().message);
return;
}
-
- std::string type { typeVal.GetString(), typeVal.GetStringLength() };
-
- if (type == "fill") {
- layer = std::make_unique<FillLayer>(id);
- } else if (type == "line") {
- layer = std::make_unique<LineLayer>(id);
- } else if (type == "circle") {
- layer = std::make_unique<CircleLayer>(id);
- } else if (type == "symbol") {
- layer = std::make_unique<SymbolLayer>(id);
- } else if (type == "raster") {
- layer = std::make_unique<RasterLayer>(id);
- } else if (type == "background") {
- layer = std::make_unique<BackgroundLayer>(id);
- } else {
- Log::Warning(Event::ParseStyle, "unknown type '%s' for layer '%s'", type.c_str(), id.c_str());
- return;
- }
-
- Layer::Impl* impl = layer->baseImpl.get();
-
- if (value.HasMember("source")) {
- const JSValue& value_source = value["source"];
- if (value_source.IsString()) {
- impl->source = { value_source.GetString(), value_source.GetStringLength() };
- auto source_it = sourcesMap.find(impl->source);
- if (source_it == sourcesMap.end()) {
- Log::Warning(Event::ParseStyle, "can't find source '%s' required for layer '%s'", impl->source.c_str(), impl->id.c_str());
- }
- } else {
- Log::Warning(Event::ParseStyle, "source of layer '%s' must be a string", impl->id.c_str());
- }
- }
-
- if (value.HasMember("source-layer")) {
- const JSValue& value_source_layer = value["source-layer"];
- if (value_source_layer.IsString()) {
- impl->sourceLayer = { value_source_layer.GetString(), value_source_layer.GetStringLength() };
- } else {
- Log::Warning(Event::ParseStyle, "source-layer of layer '%s' must be a string", impl->id.c_str());
- }
- }
-
- if (value.HasMember("filter")) {
- impl->filter = parseFilter(value["filter"]);
- }
-
- if (value.HasMember("minzoom")) {
- const JSValue& min_zoom = value["minzoom"];
- if (min_zoom.IsNumber()) {
- impl->minZoom = min_zoom.GetDouble();
- } else {
- Log::Warning(Event::ParseStyle, "minzoom of layer %s must be numeric", impl->id.c_str());
- }
- }
-
- if (value.HasMember("maxzoom")) {
- const JSValue& max_zoom = value["maxzoom"];
- if (max_zoom.IsNumber()) {
- impl->maxZoom = max_zoom.GetDouble();
- } else {
- Log::Warning(Event::ParseStyle, "maxzoom of layer %s must be numeric", impl->id.c_str());
- }
- }
-
- if (value.HasMember("layout")) {
- parseVisibility(*layer, value["layout"]);
- impl->parseLayout(value["layout"]);
- }
-
- impl->parsePaints(value);
- }
-}
-
-MBGL_DEFINE_ENUM_CLASS(VisibilityTypeClass, VisibilityType, {
- { VisibilityType::Visible, "visible" },
- { VisibilityType::None, "none" },
-});
-
-void Parser::parseVisibility(Layer& layer, const JSValue& value) {
- Layer::Impl& impl = *layer.baseImpl;
- if (!value.HasMember("visibility")) {
- return;
- } else if (!value["visibility"].IsString()) {
- Log::Warning(Event::ParseStyle, "value of 'visibility' must be a string");
- impl.visibility = VisibilityType::Visible;
- return;
- }
- impl.visibility = VisibilityTypeClass({ value["visibility"].GetString(), value["visibility"].GetStringLength() });
-}
-
-Value parseFeatureType(const Value& value) {
- if (value == std::string("Point")) {
- return Value(uint64_t(FeatureType::Point));
- } else if (value == std::string("LineString")) {
- return Value(uint64_t(FeatureType::LineString));
- } else if (value == std::string("Polygon")) {
- return Value(uint64_t(FeatureType::Polygon));
- } else {
- Log::Warning(Event::ParseStyle, "value for $type filter must be Point, LineString, or Polygon");
- return Value(uint64_t(FeatureType::Unknown));
- }
-}
-
-Value parseValue(const JSValue& value) {
- switch (value.GetType()) {
- case rapidjson::kNullType:
- case rapidjson::kFalseType:
- return false;
-
- case rapidjson::kTrueType:
- return true;
-
- case rapidjson::kStringType:
- return std::string { value.GetString(), value.GetStringLength() };
-
- case rapidjson::kNumberType:
- if (value.IsUint64()) return value.GetUint64();
- if (value.IsInt64()) return value.GetInt64();
- return value.GetDouble();
-
- default:
- return false;
- }
-}
-
-template <class Expression>
-Filter parseUnaryFilter(const JSValue& value) {
- Filter empty;
-
- if (value.Size() < 2) {
- Log::Warning(Event::ParseStyle, "filter expression must have 2 elements");
- return empty;
- }
-
- if (!value[1u].IsString()) {
- Log::Warning(Event::ParseStyle, "filter expression key must be a string");
- return empty;
- }
-
- Expression expression;
- expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
- return expression;
-}
-
-template <class Expression>
-Filter parseBinaryFilter(const JSValue& value) {
- Filter empty;
-
- if (value.Size() < 3) {
- Log::Warning(Event::ParseStyle, "filter expression must have 3 elements");
- return empty;
- }
-
- if (!value[1u].IsString()) {
- Log::Warning(Event::ParseStyle, "filter expression key must be a string");
- return empty;
- }
-
- Expression expression;
- expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
- expression.value = parseValue(value[2u]);
-
- if (expression.key == "$type") {
- expression.value = parseFeatureType(expression.value);
- }
-
- return expression;
-}
-
-template <class Expression>
-Filter parseSetFilter(const JSValue& value) {
- Filter empty;
-
- if (value.Size() < 2) {
- Log::Warning(Event::ParseStyle, "filter expression must at least 2 elements");
- return empty;
- }
-
- if (!value[1u].IsString()) {
- Log::Warning(Event::ParseStyle, "filter expression key must be a string");
- return empty;
- }
-
- Expression expression;
- expression.key = { value[1u].GetString(), value[1u].GetStringLength() };
- for (rapidjson::SizeType i = 2; i < value.Size(); ++i) {
- Value parsedValue = parseValue(value[i]);
- if (expression.key == "$type") {
- parsedValue = parseFeatureType(parsedValue);
- }
- expression.values.push_back(parsedValue);
- }
- return expression;
-}
-
-template <class Expression>
-Filter parseCompoundFilter(const JSValue& value) {
- Expression expression;
- for (rapidjson::SizeType i = 1; i < value.Size(); ++i) {
- expression.filters.push_back(parseFilter(value[i]));
- }
- return expression;
-}
-
-Filter parseFilter(const JSValue& value) {
- Filter empty;
-
- if (!value.IsArray()) {
- Log::Warning(Event::ParseStyle, "filter expression must be an array");
- return empty;
- }
-
- if (value.Size() < 1) {
- Log::Warning(Event::ParseStyle, "filter expression must have at least 1 element");
- return empty;
- }
-
- if (!value[0u].IsString()) {
- Log::Warning(Event::ParseStyle, "filter operator must be a string");
- return empty;
- }
-
- std::string op = { value[0u].GetString(), value[0u].GetStringLength() };
-
- if (op == "==") {
- return parseBinaryFilter<EqualsFilter>(value);
- } else if (op == "!=") {
- return parseBinaryFilter<NotEqualsFilter>(value);
- } else if (op == ">") {
- return parseBinaryFilter<GreaterThanFilter>(value);
- } else if (op == ">=") {
- return parseBinaryFilter<GreaterThanEqualsFilter>(value);
- } else if (op == "<") {
- return parseBinaryFilter<LessThanFilter>(value);
- } else if (op == "<=") {
- return parseBinaryFilter<LessThanEqualsFilter>(value);
- } else if (op == "in") {
- return parseSetFilter<InFilter>(value);
- } else if (op == "!in") {
- return parseSetFilter<NotInFilter>(value);
- } else if (op == "all") {
- return parseCompoundFilter<AllFilter>(value);
- } else if (op == "any") {
- return parseCompoundFilter<AnyFilter>(value);
- } else if (op == "none") {
- return parseCompoundFilter<NoneFilter>(value);
- } else if (op == "has") {
- return parseUnaryFilter<HasFilter>(value);
- } else if (op == "!has") {
- return parseUnaryFilter<NotHasFilter>(value);
- } else {
- Log::Warning(Event::ParseStyle, "filter operator must be one of \"==\", \"!=\", \">\", \">=\", \"<\", \"<=\", \"in\", \"!in\", \"all\", \"any\", \"none\", \"has\", or \"!has\"");
- return empty;
+ layer = std::move(*converted);
}
}
diff --git a/src/mbgl/style/parser.hpp b/src/mbgl/style/parser.hpp
index ea821fabde..faf80cee93 100644
--- a/src/mbgl/style/parser.hpp
+++ b/src/mbgl/style/parser.hpp
@@ -2,7 +2,6 @@
#include <mbgl/style/layer.hpp>
#include <mbgl/style/source.hpp>
-#include <mbgl/style/filter.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <mbgl/util/font_stack.hpp>
@@ -16,13 +15,6 @@
namespace mbgl {
namespace style {
-std::unique_ptr<Tileset> parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize);
-std::unique_ptr<Tileset> parseTileJSON(const JSValue&);
-
-std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> parseGeoJSON(const JSValue&);
-
-Filter parseFilter(const JSValue&);
-
class Parser {
public:
~Parser();
@@ -42,7 +34,6 @@ private:
void parseSources(const JSValue&);
void parseLayers(const JSValue&);
void parseLayer(const std::string& id, const JSValue&, std::unique_ptr<Layer>&);
- void parseVisibility(Layer&, const JSValue& value);
std::unordered_map<std::string, const Source*> sourcesMap;
std::unordered_map<std::string, std::pair<const JSValue&, std::unique_ptr<Layer>>> layersMap;
diff --git a/src/mbgl/style/property_evaluator.cpp b/src/mbgl/style/property_evaluator.cpp
index d2e633c782..fd31451d72 100644
--- a/src/mbgl/style/property_evaluator.cpp
+++ b/src/mbgl/style/property_evaluator.cpp
@@ -11,25 +11,27 @@ namespace mbgl {
namespace style {
template <typename T>
-inline T defaultStopsValue();
-
-template <> inline bool defaultStopsValue() { return true; }
-template <> inline float defaultStopsValue() { return 1.0f; }
-template <> inline Color defaultStopsValue() { return {{ 0, 0, 0, 1 }}; }
-template <> inline std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
-template <> inline std::vector<std::string> defaultStopsValue() { return {{}}; }
-template <> inline std::array<float, 2> defaultStopsValue() { return {{ 0, 0 }}; }
-
-template <> inline std::string defaultStopsValue() { return {}; }
-template <> inline TranslateAnchorType defaultStopsValue() { return {}; };
-template <> inline RotateAnchorType defaultStopsValue() { return {}; };
-template <> inline LineCapType defaultStopsValue() { return {}; };
-template <> inline LineJoinType defaultStopsValue() { return {}; };
-template <> inline SymbolPlacementType defaultStopsValue() { return {}; };
-template <> inline TextAnchorType defaultStopsValue() { return {}; };
-template <> inline TextJustifyType defaultStopsValue() { return {}; };
-template <> inline TextTransformType defaultStopsValue() { return {}; };
-template <> inline RotationAlignmentType defaultStopsValue() { return {}; };
+T defaultStopsValue();
+
+template <> bool defaultStopsValue() { return true; }
+template <> float defaultStopsValue() { return 1.0f; }
+template <> Color defaultStopsValue() { return { 0, 0, 0, 1 }; }
+template <> std::vector<float> defaultStopsValue() { return {{ 1, 0 }}; }
+template <> std::vector<std::string> defaultStopsValue() { return {{}}; }
+template <> std::array<float, 2> defaultStopsValue() { return {{ 0, 0 }}; }
+template <> std::array<float, 4> defaultStopsValue() { return {{ 0, 0, 0, 0 }}; }
+
+template <> std::string defaultStopsValue() { return {}; }
+template <> TranslateAnchorType defaultStopsValue() { return {}; }
+template <> RotateAnchorType defaultStopsValue() { return {}; }
+template <> LineCapType defaultStopsValue() { return {}; }
+template <> LineJoinType defaultStopsValue() { return {}; }
+template <> SymbolPlacementType defaultStopsValue() { return {}; }
+template <> TextAnchorType defaultStopsValue() { return {}; }
+template <> TextJustifyType defaultStopsValue() { return {}; }
+template <> TextTransformType defaultStopsValue() { return {}; }
+template <> AlignmentType defaultStopsValue() { return {}; }
+template <> IconTextFitType defaultStopsValue() { return {}; };
template <typename T>
T PropertyEvaluator<T>::operator()(const Function<T>& fn) const {
@@ -87,6 +89,7 @@ template class PropertyEvaluator<Color>;
template class PropertyEvaluator<std::vector<float>>;
template class PropertyEvaluator<std::vector<std::string>>;
template class PropertyEvaluator<std::array<float, 2>>;
+template class PropertyEvaluator<std::array<float, 4>>;
template class PropertyEvaluator<std::string>;
template class PropertyEvaluator<TranslateAnchorType>;
@@ -97,7 +100,8 @@ template class PropertyEvaluator<SymbolPlacementType>;
template class PropertyEvaluator<TextAnchorType>;
template class PropertyEvaluator<TextJustifyType>;
template class PropertyEvaluator<TextTransformType>;
-template class PropertyEvaluator<RotationAlignmentType>;
+template class PropertyEvaluator<AlignmentType>;
+template class PropertyEvaluator<IconTextFitType>;
template <typename T>
Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const Undefined&) const {
@@ -110,7 +114,7 @@ Faded<T> CrossFadedPropertyEvaluator<T>::operator()(const T& constant) const {
}
template <typename T>
-inline T getBiggestStopLessThan(const Function<T>& function, float z) {
+T getBiggestStopLessThan(const Function<T>& function, float z) {
const auto& stops = function.getStops();
for (uint32_t i = 0; i < stops.size(); i++) {
if (stops[i].first > z) {
diff --git a/src/mbgl/style/property_evaluator.hpp b/src/mbgl/style/property_evaluator.hpp
index 77100bda46..a0bce2f499 100644
--- a/src/mbgl/style/property_evaluator.hpp
+++ b/src/mbgl/style/property_evaluator.hpp
@@ -13,9 +13,9 @@ class PropertyEvaluator {
public:
using ResultType = T;
- PropertyEvaluator(const CalculationParameters& parameters_, const T& defaultValue_)
+ PropertyEvaluator(const CalculationParameters& parameters_, T defaultValue_)
: parameters(parameters_),
- defaultValue(defaultValue_) {}
+ defaultValue(std::move(defaultValue_)) {}
T operator()(const Undefined&) const { return defaultValue; }
T operator()(const T& constant) const { return constant; }
@@ -40,9 +40,9 @@ class CrossFadedPropertyEvaluator {
public:
using ResultType = Faded<T>;
- CrossFadedPropertyEvaluator(const CalculationParameters& parameters_, const T& defaultValue_)
+ CrossFadedPropertyEvaluator(const CalculationParameters& parameters_, T defaultValue_)
: parameters(parameters_),
- defaultValue(defaultValue_) {}
+ defaultValue(std::move(defaultValue_)) {}
Faded<T> operator()(const Undefined&) const;
Faded<T> operator()(const T& constant) const;
@@ -61,6 +61,6 @@ namespace util {
template <typename T>
struct Interpolator<style::Faded<T>>
: Uninterpolated {};
-}
+} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/style/property_parsing.cpp b/src/mbgl/style/property_parsing.cpp
index 9f60ddf3b6..16ce0f4adc 100644
--- a/src/mbgl/style/property_parsing.cpp
+++ b/src/mbgl/style/property_parsing.cpp
@@ -1,269 +1,8 @@
#include <mbgl/style/property_parsing.hpp>
-#include <mbgl/platform/log.hpp>
-
-#include <csscolorparser/csscolorparser.hpp>
-
namespace mbgl {
namespace style {
-template <>
-optional<bool> parseConstant(const char* name, const JSValue& value) {
- if (!value.IsBool()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a boolean", name);
- return {};
- }
-
- return value.GetBool();
-}
-
-template <>
-optional<float> parseConstant(const char* name, const JSValue& value) {
- if (!value.IsNumber()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a number, or a number function", name);
- return {};
- }
-
- return value.GetDouble();
-}
-
-template <>
-optional<std::string> parseConstant(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return std::string { value.GetString(), value.GetStringLength() };
-}
-
-template <>
-optional<Color> parseConstant(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- CSSColorParser::Color css_color = CSSColorParser::parse({ value.GetString(), value.GetStringLength() });
-
- // Premultiply the color.
- const float factor = css_color.a / 255;
-
- return Color{{(float)css_color.r * factor,
- (float)css_color.g * factor,
- (float)css_color.b * factor,
- css_color.a}};
-}
-
-MBGL_DEFINE_ENUM_CLASS(TranslateAnchorTypeClass, TranslateAnchorType, {
- { TranslateAnchorType::Map, "map" },
- { TranslateAnchorType::Viewport, "viewport" },
-});
-
-template <>
-optional<TranslateAnchorType> parseConstant(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { TranslateAnchorTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(RotateAnchorTypeClass, RotateAnchorType, {
- { RotateAnchorType::Map, "map" },
- { RotateAnchorType::Viewport, "viewport" },
-});
-
-template <>
-optional<RotateAnchorType> parseConstant<RotateAnchorType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { RotateAnchorTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(LineCapTypeClass, LineCapType, {
- { LineCapType::Round, "round" },
- { LineCapType::Butt, "butt" },
- { LineCapType::Square, "square" },
-});
-
-template <>
-optional<LineCapType> parseConstant<LineCapType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { LineCapTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(LineJoinTypeClass, LineJoinType, {
- { LineJoinType::Miter, "miter" },
- { LineJoinType::Bevel, "bevel" },
- { LineJoinType::Round, "round" },
- { LineJoinType::FakeRound, "fakeround" },
- { LineJoinType::FlipBevel, "flipbevel" },
-});
-
-template <>
-optional<LineJoinType> parseConstant<LineJoinType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { LineJoinTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(SymbolPlacementTypeClass, SymbolPlacementType, {
- { SymbolPlacementType::Point, "point" },
- { SymbolPlacementType::Line, "line" },
-});
-
-template <>
-optional<SymbolPlacementType> parseConstant<SymbolPlacementType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { SymbolPlacementTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(TextAnchorTypeClass, TextAnchorType, {
- { TextAnchorType::Center, "center" },
- { TextAnchorType::Left, "left" },
- { TextAnchorType::Right, "right" },
- { TextAnchorType::Top, "top" },
- { TextAnchorType::Bottom, "bottom" },
- { TextAnchorType::TopLeft, "top-left" },
- { TextAnchorType::TopRight, "top-right" },
- { TextAnchorType::BottomLeft, "bottom-left" },
- { TextAnchorType::BottomRight, "bottom-right" }
-});
-
-template <>
-optional<TextAnchorType> parseConstant<TextAnchorType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { TextAnchorTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(TextJustifyTypeClass, TextJustifyType, {
- { TextJustifyType::Center, "center" },
- { TextJustifyType::Left, "left" },
- { TextJustifyType::Right, "right" },
-});
-
-template <>
-optional<TextJustifyType> parseConstant<TextJustifyType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { TextJustifyTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(TextTransformTypeClass, TextTransformType, {
- { TextTransformType::None, "none" },
- { TextTransformType::Uppercase, "uppercase" },
- { TextTransformType::Lowercase, "lowercase" },
-});
-
-template <>
-optional<TextTransformType> parseConstant<TextTransformType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { TextTransformTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-MBGL_DEFINE_ENUM_CLASS(RotationAlignmentTypeClass, RotationAlignmentType, {
- { RotationAlignmentType::Map, "map" },
- { RotationAlignmentType::Viewport, "viewport" },
-});
-
-template <>
-optional<RotationAlignmentType> parseConstant<RotationAlignmentType>(const char* name, const JSValue& value) {
- if (!value.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be a string", name);
- return {};
- }
-
- return { RotationAlignmentTypeClass({ value.GetString(), value.GetStringLength() }) };
-}
-
-template <>
-optional<std::array<float, 2>> parseConstant(const char* name, const JSValue& value) {
- if (value.IsArray() && value.Size() == 2 &&
- value[rapidjson::SizeType(0)].IsNumber() &&
- value[rapidjson::SizeType(1)].IsNumber()) {
-
- float first = value[rapidjson::SizeType(0)].GetDouble();
- float second = value[rapidjson::SizeType(1)].GetDouble();
- return { {{ first, second }} };
- } else {
- Log::Warning(Event::ParseStyle, "value of '%s' must be an array of two numbers", name);
- return {};
- }
-}
-
-template <>
-optional<std::vector<float>> parseConstant(const char* name, const JSValue& value) {
- if (!value.IsArray()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name);
- return {};
- }
-
- std::vector<float> result;
-
- for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
- const JSValue& part = value[i];
-
- if (!part.IsNumber()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be an array of numbers", name);
- return {};
- }
-
- result.push_back(part.GetDouble());
- }
-
- return result;
-}
-
-template <>
-optional<std::vector<std::string>> parseConstant(const char* name, const JSValue& value) {
- if (!value.IsArray()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be an array of strings", name);
- return {};
- }
-
- std::vector<std::string> result;
-
- for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
- const JSValue& part = value[i];
-
- if (!part.IsString()) {
- Log::Warning(Event::ParseStyle, "value of '%s' must be an array of strings", name);
- return {};
- }
-
- result.push_back({ part.GetString(), part.GetStringLength() });
- }
-
- return result;
-}
-
optional<TransitionOptions> parseTransitionOptions(const char *, const JSValue& value) {
if (!value.IsObject()) {
return {};
@@ -283,7 +22,7 @@ optional<TransitionOptions> parseTransitionOptions(const char *, const JSValue&
return {};
}
- return TransitionOptions(duration, delay);
+ return TransitionOptions { duration, delay };
}
} // namespace style
diff --git a/src/mbgl/style/property_parsing.hpp b/src/mbgl/style/property_parsing.hpp
index bb894c2407..8c2bd2c0f4 100644
--- a/src/mbgl/style/property_parsing.hpp
+++ b/src/mbgl/style/property_parsing.hpp
@@ -1,109 +1,23 @@
#pragma once
-#include <mbgl/style/types.hpp>
#include <mbgl/style/property_value.hpp>
#include <mbgl/style/transition_options.hpp>
-
-#include <mbgl/util/rapidjson.hpp>
-#include <mbgl/util/optional.hpp>
-#include <mbgl/util/color.hpp>
+#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/conversion/property_value.hpp>
#include <mbgl/platform/log.hpp>
-#include <string>
-#include <array>
-#include <vector>
-
namespace mbgl {
namespace style {
template <typename T>
-optional<T> parseConstant(const char* name, const JSValue&);
-
-template <> optional<bool> parseConstant(const char*, const JSValue&);
-template <> optional<float> parseConstant(const char*, const JSValue&);
-template <> optional<std::string> parseConstant(const char*, const JSValue&);
-template <> optional<Color> parseConstant(const char*, const JSValue&);
-template <> optional<TranslateAnchorType> parseConstant(const char*, const JSValue&);
-template <> optional<RotateAnchorType> parseConstant(const char*, const JSValue&);
-template <> optional<LineCapType> parseConstant(const char*, const JSValue&);
-template <> optional<LineJoinType> parseConstant(const char*, const JSValue&);
-template <> optional<SymbolPlacementType> parseConstant(const char*, const JSValue&);
-template <> optional<TextAnchorType> parseConstant(const char*, const JSValue&);
-template <> optional<TextJustifyType> parseConstant(const char*, const JSValue&);
-template <> optional<TextTransformType> parseConstant(const char*, const JSValue&);
-template <> optional<RotationAlignmentType> parseConstant(const char*, const JSValue&);
-template <> optional<std::array<float, 2>> parseConstant(const char*, const JSValue&);
-template <> optional<std::vector<float>> parseConstant(const char*, const JSValue&);
-template <> optional<std::vector<std::string>> parseConstant(const char*, const JSValue&);
-
-template <typename T>
PropertyValue<T> parseProperty(const char* name, const JSValue& value) {
- if (!value.IsObject()) {
- auto constant = parseConstant<T>(name, value);
-
- if (!constant) {
- return {};
- }
-
- return *constant;
- }
-
- if (!value.HasMember("stops")) {
- Log::Warning(Event::ParseStyle, "function must specify a function type");
+ conversion::Result<PropertyValue<T>> result = conversion::convert<PropertyValue<T>>(value);
+ if (!result) {
+ Log::Warning(Event::ParseStyle, "%s: %s", name, result.error().message);
return {};
}
-
- float base = 1.0f;
-
- if (value.HasMember("base")) {
- const JSValue& value_base = value["base"];
-
- if (!value_base.IsNumber()) {
- Log::Warning(Event::ParseStyle, "base must be numeric");
- return {};
- }
-
- base = value_base.GetDouble();
- }
-
- const JSValue& stopsValue = value["stops"];
-
- if (!stopsValue.IsArray()) {
- Log::Warning(Event::ParseStyle, "stops function must specify a stops array");
- return {};
- }
-
- std::vector<std::pair<float, T>> stops;
-
- for (rapidjson::SizeType i = 0; i < stopsValue.Size(); ++i) {
- const JSValue& stop = stopsValue[i];
-
- if (!stop.IsArray()) {
- Log::Warning(Event::ParseStyle, "function argument must be a numeric value");
- return {};
- }
-
- if (stop.Size() != 2) {
- Log::Warning(Event::ParseStyle, "stop must have zoom level and value specification");
- return {};
- }
-
- const JSValue& z = stop[rapidjson::SizeType(0)];
- if (!z.IsNumber()) {
- Log::Warning(Event::ParseStyle, "zoom level in stop must be a number");
- return {};
- }
-
- optional<T> v = parseConstant<T>(name, stop[rapidjson::SizeType(1)]);
- if (!v) {
- return {};
- }
-
- stops.emplace_back(z.GetDouble(), *v);
- }
-
- return Function<T>(stops, base);
+ return *result;
}
optional<TransitionOptions> parseTransitionOptions(const char * name, const JSValue&);
diff --git a/src/mbgl/style/rapidjson_conversion.hpp b/src/mbgl/style/rapidjson_conversion.hpp
new file mode 100644
index 0000000000..ecf044fb64
--- /dev/null
+++ b/src/mbgl/style/rapidjson_conversion.hpp
@@ -0,0 +1,94 @@
+#pragma once
+
+#include <mbgl/util/rapidjson.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/style/conversion.hpp>
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+inline bool isUndefined(const JSValue& value) {
+ return value.IsNull();
+}
+
+inline bool isArray(const JSValue& value) {
+ return value.IsArray();
+}
+
+inline std::size_t arrayLength(const JSValue& value) {
+ return value.Size();
+}
+
+inline const JSValue& arrayMember(const JSValue& value, std::size_t i) {
+ return value[rapidjson::SizeType(i)];
+}
+
+inline bool isObject(const JSValue& value) {
+ return value.IsObject();
+}
+
+inline const JSValue* objectMember(const JSValue& value, const char * name) {
+ if (!value.HasMember(name)) {
+ return nullptr;
+ }
+ return &value[name];
+}
+
+template <class Fn>
+optional<Error> eachMember(const JSValue& value, Fn&& fn) {
+ for (auto it = value.MemberBegin(); it != value.MemberEnd(); ++it) {
+ optional<Error> result = fn({it->name.GetString(), it->name.GetStringLength()}, it->value);
+ if (result) {
+ return result;
+ }
+ }
+ return {};
+}
+
+inline optional<bool> toBool(const JSValue& value) {
+ if (!value.IsBool()) {
+ return {};
+ }
+ return value.GetBool();
+}
+
+inline optional<float> toNumber(const JSValue& value) {
+ if (!value.IsNumber()) {
+ return {};
+ }
+ return value.GetDouble();
+}
+
+inline optional<std::string> toString(const JSValue& value) {
+ if (!value.IsString()) {
+ return {};
+ }
+ return {{ value.GetString(), value.GetStringLength() }};
+}
+
+inline optional<Value> toValue(const JSValue& value) {
+ switch (value.GetType()) {
+ case rapidjson::kNullType:
+ case rapidjson::kFalseType:
+ return { false };
+
+ case rapidjson::kTrueType:
+ return { true };
+
+ case rapidjson::kStringType:
+ return { std::string { value.GetString(), value.GetStringLength() } };
+
+ case rapidjson::kNumberType:
+ if (value.IsUint64()) return { value.GetUint64() };
+ if (value.IsInt64()) return { value.GetInt64() };
+ return { value.GetDouble() };
+
+ default:
+ return {};
+ }
+}
+
+} // namespace conversion
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/source.cpp b/src/mbgl/style/source.cpp
index 8e5973f412..4c83a3ce0e 100644
--- a/src/mbgl/style/source.cpp
+++ b/src/mbgl/style/source.cpp
@@ -1,427 +1,17 @@
#include <mbgl/style/source.hpp>
-#include <mbgl/style/source_observer.hpp>
-#include <mbgl/map/transform.hpp>
-#include <mbgl/tile/tile.hpp>
-#include <mbgl/tile/vector_tile.hpp>
-#include <mbgl/annotation/annotation_tile.hpp>
-#include <mbgl/tile/geojson_tile.hpp>
-#include <mbgl/renderer/painter.hpp>
-#include <mbgl/util/exception.hpp>
-#include <mbgl/util/constants.hpp>
-#include <mbgl/storage/resource.hpp>
-#include <mbgl/storage/response.hpp>
-#include <mbgl/storage/file_source.hpp>
-#include <mbgl/style/layer.hpp>
-#include <mbgl/style/update_parameters.hpp>
-#include <mbgl/style/query_parameters.hpp>
-#include <mbgl/platform/log.hpp>
-#include <mbgl/math/minmax.hpp>
-#include <mbgl/math/clamp.hpp>
-#include <mbgl/util/std.hpp>
-#include <mbgl/util/token.hpp>
-#include <mbgl/util/string.hpp>
-#include <mbgl/util/tile_cover.hpp>
-
-#include <mbgl/tile/vector_tile_data.hpp>
-#include <mbgl/tile/raster_tile_data.hpp>
-#include <mbgl/style/parser.hpp>
-#include <mbgl/gl/debugging.hpp>
-
-#include <mbgl/algorithm/update_renderables.hpp>
-
-#include <mapbox/geojsonvt.hpp>
-#include <mapbox/geojsonvt/convert.hpp>
-#include <mapbox/geometry/envelope.hpp>
-
-#include <rapidjson/error/en.h>
-
-#include <algorithm>
-#include <sstream>
+#include <mbgl/style/source_impl.hpp>
namespace mbgl {
namespace style {
-static SourceObserver nullObserver;
-
-Source::Source(SourceType type_,
- const std::string& id_,
- const std::string& url_,
- uint16_t tileSize_,
- std::unique_ptr<Tileset>&& tileset_,
- std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>&& geojsonvt_)
- : type(type_),
- id(id_),
- url(url_),
- tileSize(tileSize_),
- tileset(std::move(tileset_)),
- geojsonvt(std::move(geojsonvt_)),
- observer(&nullObserver) {
+Source::Source(SourceType type_, std::unique_ptr<Impl> baseImpl_)
+ : baseImpl(std::move(baseImpl_)), type(type_) {
}
Source::~Source() = default;
-bool Source::isLoaded() const {
- if (!loaded) return false;
-
- for (const auto& pair : tileDataMap) {
- if (!pair.second->isComplete()) {
- return false;
- }
- }
-
- return true;
-}
-
-bool Source::isLoading() const {
- return !loaded && req.operator bool();
-}
-
-void Source::load(FileSource& fileSource) {
- if (url.empty()) {
- // In case there is no URL set, we assume that we already have all of the data because the
- // TileJSON was specified inline in the stylesheet.
- loaded = true;
- return;
- }
-
- if (req) {
- // We don't have a Tileset object yet, but there's already a request underway to load
- // the data.
- return;
- }
-
- // URL may either be a TileJSON file, or a GeoJSON file.
- req = fileSource.request(Resource::source(url), [this](Response res) {
- if (res.error) {
- observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(res.error->message)));
- } else if (res.notModified) {
- return;
- } else if (res.noContent) {
- observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error("unexpectedly empty source")));
- } else {
- bool reloadTiles = false;
-
- if (type == SourceType::Vector || type == SourceType::Raster) {
- std::unique_ptr<Tileset> newTileset;
-
- // Create a new copy of the Tileset object that holds the base values we've parsed
- // from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved
- // via the URL.
- try {
- newTileset = style::parseTileJSON(*res.data, url, type, tileSize);
- } catch (...) {
- observer->onSourceError(*this, std::current_exception());
- return;
- }
-
- // Check whether previous information specifies different tile
- if (tileset && tileset->tiles != newTileset->tiles) {
- reloadTiles = true;
-
- // Tile size changed: We need to recalculate the tiles we need to load because we
- // might have to load tiles for a different zoom level
- // This is done automatically when we trigger the onSourceLoaded observer below.
-
- // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles
- // loaded that are outside the new zoom range
- // This is done automatically when we trigger the onSourceLoaded observer below.
-
- // Attribution changed: We need to notify the embedding application that this
- // changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723
- // This is not yet implemented.
-
- // Center/bounds changed: We're not using these values currently
- }
-
- tileset = std::move(newTileset);
- } else if (type == SourceType::GeoJSON) {
- std::unique_ptr<Tileset> newTileset = std::make_unique<Tileset>();
-
- rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d;
- d.Parse<0>(res.data->c_str());
-
- if (d.HasParseError()) {
- std::stringstream message;
- message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError());
- observer->onSourceError(*this, std::make_exception_ptr(std::runtime_error(message.str())));
- return;
- }
-
- geojsonvt = style::parseGeoJSON(d);
- reloadTiles = true;
-
- newTileset->maxZoom = geojsonvt->options.maxZoom;
- tileset = std::move(newTileset);
- }
-
- if (reloadTiles) {
- // Tile information changed because we got new GeoJSON data, or a new tile URL.
- tileDataMap.clear();
- tiles.clear();
- cache.clear();
- }
-
- loaded = true;
- observer->onSourceLoaded(*this);
- }
- });
-}
-
-void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transform) {
- for (auto& pair : tiles) {
- auto& tile = pair.second;
- transform.matrixFor(tile.matrix, tile.id);
- matrix::multiply(tile.matrix, projMatrix, tile.matrix);
- }
-}
-
-void Source::finishRender(Painter &painter) {
- for (auto& pair : tiles) {
- auto& tile = pair.second;
- painter.renderTileDebug(tile);
- }
-}
-
-const std::map<UnwrappedTileID, Tile>& Source::getTiles() const {
- return tiles;
-}
-
-std::unique_ptr<TileData> Source::createTile(const OverscaledTileID& overscaledTileID,
- const UpdateParameters& parameters) {
- std::unique_ptr<TileData> data = cache.get(overscaledTileID);
- if (data) {
- return data;
- }
-
- auto callback = std::bind(&Source::tileLoadingCallback, this, overscaledTileID,
- std::placeholders::_1, true);
-
- // If we don't find working tile data, we're just going to load it.
- if (type == SourceType::Raster) {
- data = std::make_unique<RasterTileData>(overscaledTileID, parameters.pixelRatio,
- tileset->tiles.at(0), parameters.texturePool,
- parameters.worker, parameters.fileSource, callback);
- } else {
- std::unique_ptr<GeometryTileMonitor> monitor;
-
- if (type == SourceType::Vector) {
- monitor = std::make_unique<VectorTileMonitor>(overscaledTileID, parameters.pixelRatio, tileset->tiles.at(0), parameters.fileSource);
- } else if (type == SourceType::Annotations) {
- monitor = std::make_unique<AnnotationTileMonitor>(overscaledTileID, parameters.annotationManager);
- } else if (type == SourceType::GeoJSON) {
- monitor = std::make_unique<GeoJSONTileMonitor>(geojsonvt.get(), overscaledTileID);
- } else {
- Log::Warning(Event::Style, "Source type '%s' is not implemented", SourceTypeClass(type).c_str());
- return nullptr;
- }
-
- data = std::make_unique<VectorTileData>(overscaledTileID, std::move(monitor), id,
- parameters.style, parameters.mode, callback);
- }
-
- return data;
-}
-
-TileData* Source::getTileData(const OverscaledTileID& overscaledTileID) const {
- auto it = tileDataMap.find(overscaledTileID);
- if (it != tileDataMap.end()) {
- return it->second.get();
- } else {
- return nullptr;
- }
-}
-
-bool Source::update(const UpdateParameters& parameters) {
- bool allTilesUpdated = true;
-
- if (!loaded || parameters.animationTime <= updated) {
- return allTilesUpdated;
- }
-
- // Determine the overzooming/underzooming amounts and required tiles.
- int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize);
- int32_t dataTileZoom = overscaledZoom;
-
- std::vector<UnwrappedTileID> idealTiles;
- if (overscaledZoom >= tileset->minZoom) {
- int32_t idealZoom = std::min<int32_t>(tileset->maxZoom, overscaledZoom);
-
- // Make sure we're not reparsing overzoomed raster tiles.
- if (type == SourceType::Raster) {
- dataTileZoom = idealZoom;
- }
-
- idealTiles = util::tileCover(parameters.transformState, idealZoom);
- }
-
- // Stores a list of all the data tiles that we're definitely going to retain. There are two
- // kinds of tiles we need: the ideal tiles determined by the tile cover. They may not yet be in
- // use because they're still loading. In addition to that, we also need to retain all tiles that
- // we're actively using, e.g. as a replacement for tile that aren't loaded yet.
- std::set<OverscaledTileID> retain;
-
- auto retainTileDataFn = [&retain](const TileData& tileData) -> void {
- retain.emplace(tileData.id);
- };
- auto getTileDataFn = [this](const OverscaledTileID& dataTileID) -> TileData* {
- return getTileData(dataTileID);
- };
- auto createTileDataFn = [this, &parameters](const OverscaledTileID& dataTileID) -> TileData* {
- if (auto data = createTile(dataTileID, parameters)) {
- return tileDataMap.emplace(dataTileID, std::move(data)).first->second.get();
- } else {
- return nullptr;
- }
- };
- auto renderTileFn = [this](const UnwrappedTileID& renderTileID, TileData& tileData) {
- tiles.emplace(renderTileID, Tile{ renderTileID, tileData });
- };
-
- tiles.clear();
- algorithm::updateRenderables(getTileDataFn, createTileDataFn, retainTileDataFn, renderTileFn,
- idealTiles, *tileset, dataTileZoom);
-
- if (type != SourceType::Raster && type != SourceType::Annotations && cache.getSize() == 0) {
- size_t conservativeCacheSize =
- ((float)parameters.transformState.getWidth() / util::tileSize) *
- ((float)parameters.transformState.getHeight() / util::tileSize) *
- (parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) *
- 0.5;
- cache.setSize(conservativeCacheSize);
- }
-
- // Remove stale data tiles from the active set of tiles.
- // This goes through the (sorted!) tileDataMap and retain set in lockstep and removes items from
- // tileDataMap that don't have the corresponding key in the retain set.
- auto dataIt = tileDataMap.begin();
- auto retainIt = retain.begin();
- while (dataIt != tileDataMap.end()) {
- if (retainIt == retain.end() || dataIt->first < *retainIt) {
- cache.add(dataIt->first, std::move(dataIt->second));
- tileDataMap.erase(dataIt++);
- } else {
- if (!(*retainIt < dataIt->first)) {
- ++dataIt;
- }
- ++retainIt;
- }
- }
-
- for (auto& pair : tileDataMap) {
- const auto& dataTileID = pair.first;
- auto tileData = pair.second.get();
- if (parameters.shouldReparsePartialTiles && tileData->isIncomplete()) {
- auto callback = std::bind(&Source::tileLoadingCallback, this, dataTileID,
- std::placeholders::_1, false);
-
- if (!tileData->parsePending(callback)) {
- allTilesUpdated = false;
- }
- } else {
- tileData->redoPlacement({ parameters.transformState.getAngle(),
- parameters.transformState.getPitch(),
- parameters.debugOptions & MapDebugOptions::Collision },
- [this]() { observer->onPlacementRedone(); });
- }
- }
-
- updated = parameters.animationTime;
-
- return allTilesUpdated;
-}
-
-static Point<int16_t> coordinateToTilePoint(const UnwrappedTileID& tileID, const Point<double>& p) {
- auto zoomedCoord = TileCoordinate { p, 0 }.zoomTo(tileID.canonical.z);
- return {
- int16_t(util::clamp<int64_t>((zoomedCoord.p.x - tileID.canonical.x - tileID.wrap * std::pow(2, tileID.canonical.z)) * util::EXTENT,
- std::numeric_limits<int16_t>::min(),
- std::numeric_limits<int16_t>::max())),
- int16_t(util::clamp<int64_t>((zoomedCoord.p.y - tileID.canonical.y) * util::EXTENT,
- std::numeric_limits<int16_t>::min(),
- std::numeric_limits<int16_t>::max()))
- };
-}
-
-std::unordered_map<std::string, std::vector<Feature>> Source::queryRenderedFeatures(const QueryParameters& parameters) const {
- LineString<double> queryGeometry;
-
- for (const auto& p : parameters.geometry) {
- queryGeometry.push_back(TileCoordinate::fromScreenCoordinate(
- parameters.transformState, 0, { p.x, parameters.transformState.getHeight() - p.y }).p);
- }
-
- mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry);
-
- std::unordered_map<std::string, std::vector<Feature>> result;
-
- for (const auto& tilePtr : tiles) {
- const Tile& tile = tilePtr.second;
-
- Point<int16_t> tileSpaceBoundsMin = coordinateToTilePoint(tile.id, box.min);
- Point<int16_t> tileSpaceBoundsMax = coordinateToTilePoint(tile.id, box.max);
-
- if (tileSpaceBoundsMin.x >= util::EXTENT || tileSpaceBoundsMin.y >= util::EXTENT ||
- tileSpaceBoundsMax.x < 0 || tileSpaceBoundsMax.y < 0) continue;
-
- GeometryCoordinates tileSpaceQueryGeometry;
-
- for (const auto& c : queryGeometry) {
- tileSpaceQueryGeometry.push_back(coordinateToTilePoint(tile.id, c));
- }
-
- tile.data.queryRenderedFeatures(result,
- tileSpaceQueryGeometry,
- parameters.transformState,
- parameters.layerIDs);
- }
-
- return result;
-}
-
-void Source::setCacheSize(size_t size) {
- cache.setSize(size);
-}
-
-void Source::onLowMemory() {
- cache.clear();
-}
-
-void Source::setObserver(SourceObserver* observer_) {
- observer = observer_;
-}
-
-void Source::tileLoadingCallback(const OverscaledTileID& tileID,
- std::exception_ptr error,
- bool isNewTile) {
- auto it = tileDataMap.find(tileID);
- if (it == tileDataMap.end()) {
- return;
- }
-
- auto& tileData = it->second;
- if (!tileData) {
- return;
- }
-
- if (error) {
- observer->onTileError(*this, tileID, error);
- return;
- }
-
- tileData->redoPlacement([this]() {
- observer->onPlacementRedone();
- });
- observer->onTileLoaded(*this, tileID, isNewTile);
-}
-
-void Source::dumpDebugLogs() const {
- Log::Info(Event::General, "Source::id: %s", id.c_str());
- Log::Info(Event::General, "Source::loaded: %d", loaded);
-
- for (const auto& pair : tileDataMap) {
- auto& tileData = pair.second;
- tileData->dumpDebugLogs();
- }
+const std::string& Source::getID() const {
+ return baseImpl->id;
}
} // namespace style
diff --git a/src/mbgl/style/source.hpp b/src/mbgl/style/source.hpp
deleted file mode 100644
index 07e1aeaf58..0000000000
--- a/src/mbgl/style/source.hpp
+++ /dev/null
@@ -1,112 +0,0 @@
-#pragma once
-
-#include <mbgl/tile/tile_id.hpp>
-#include <mbgl/tile/tile_data.hpp>
-#include <mbgl/tile/tile_cache.hpp>
-#include <mbgl/style/types.hpp>
-
-#include <mbgl/util/mat4.hpp>
-#include <mbgl/util/rapidjson.hpp>
-#include <mbgl/util/feature.hpp>
-#include <mbgl/util/tileset.hpp>
-
-#include <forward_list>
-#include <vector>
-#include <map>
-
-namespace mapbox {
-namespace geojsonvt {
-class GeoJSONVT;
-} // namespace geojsonvt
-} // namespace mapbox
-
-namespace mbgl {
-
-class Painter;
-class FileSource;
-class AsyncRequest;
-class TransformState;
-class Tile;
-struct ClipID;
-
-namespace style {
-
-class Style;
-class UpdateParameters;
-class QueryParameters;
-class SourceObserver;
-
-class Source : private util::noncopyable {
-public:
- Source(SourceType,
- const std::string& id,
- const std::string& url,
- uint16_t tileSize,
- std::unique_ptr<Tileset>&&,
- std::unique_ptr<mapbox::geojsonvt::GeoJSONVT>&&);
- ~Source();
-
- bool loaded = false;
- void load(FileSource&);
- bool isLoading() const;
- bool isLoaded() const;
-
- const Tileset* getTileset() const { return tileset.get(); }
-
- // Request or parse all the tiles relevant for the "TransformState". This method
- // will return true if all the tiles were scheduled for updating of false if
- // they were not. shouldReparsePartialTiles must be set to "true" if there is
- // new data available that a tile in the "partial" state might be interested at.
- bool update(const UpdateParameters&);
-
- template <typename ClipIDGenerator>
- void updateClipIDs(ClipIDGenerator& generator) {
- generator.update(tiles);
- }
-
- void updateMatrices(const mat4 &projMatrix, const TransformState &transform);
- void finishRender(Painter &painter);
-
- const std::map<UnwrappedTileID, Tile>& getTiles() const;
-
- TileData* getTileData(const OverscaledTileID&) const;
-
- std::unordered_map<std::string, std::vector<Feature>>
- queryRenderedFeatures(const QueryParameters&) const;
-
- void setCacheSize(size_t);
- void onLowMemory();
-
- void setObserver(SourceObserver* observer);
- void dumpDebugLogs() const;
-
- const SourceType type;
- const std::string id;
- const std::string url;
- uint16_t tileSize = util::tileSize;
- bool enabled = false;
-
-private:
- void tileLoadingCallback(const OverscaledTileID&, std::exception_ptr, bool isNewTile);
-
- std::unique_ptr<TileData> createTile(const OverscaledTileID&, const UpdateParameters&);
-
-private:
- std::unique_ptr<const Tileset> tileset;
-
- std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> geojsonvt;
-
- // Stores the time when this source was most recently updated.
- TimePoint updated = TimePoint::min();
-
- std::map<UnwrappedTileID, Tile> tiles;
- std::map<OverscaledTileID, std::unique_ptr<TileData>> tileDataMap;
- TileCache cache;
-
- std::unique_ptr<AsyncRequest> req;
-
- SourceObserver* observer = nullptr;
-};
-
-} // namespace style
-} // namespace mbgl
diff --git a/src/mbgl/style/source_impl.cpp b/src/mbgl/style/source_impl.cpp
new file mode 100644
index 0000000000..4223f2b50d
--- /dev/null
+++ b/src/mbgl/style/source_impl.cpp
@@ -0,0 +1,280 @@
+#include <mbgl/style/source_impl.hpp>
+#include <mbgl/style/source_observer.hpp>
+#include <mbgl/map/transform.hpp>
+#include <mbgl/renderer/render_tile.hpp>
+#include <mbgl/renderer/painter.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/style/query_parameters.hpp>
+#include <mbgl/platform/log.hpp>
+#include <mbgl/math/clamp.hpp>
+#include <mbgl/util/tile_cover.hpp>
+#include <mbgl/util/enum.hpp>
+
+#include <mbgl/algorithm/update_renderables.hpp>
+#include <mbgl/algorithm/generate_clip_ids.hpp>
+#include <mbgl/algorithm/generate_clip_ids_impl.hpp>
+
+#include <mapbox/geometry/envelope.hpp>
+
+#include <algorithm>
+
+namespace mbgl {
+namespace style {
+
+static SourceObserver nullObserver;
+
+Source::Impl::Impl(SourceType type_, std::string id_, Source& base_)
+ : type(type_),
+ id(std::move(id_)),
+ base(base_),
+ observer(&nullObserver) {
+}
+
+Source::Impl::~Impl() = default;
+
+bool Source::Impl::isLoaded() const {
+ if (!loaded) return false;
+
+ for (const auto& pair : tiles) {
+ if (!pair.second->isComplete()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void Source::Impl::invalidateTiles() {
+ tiles.clear();
+ renderTiles.clear();
+ cache.clear();
+}
+
+void Source::Impl::startRender(algorithm::ClipIDGenerator& generator,
+ const mat4& projMatrix,
+ const TransformState& transform) {
+ if (type == SourceType::Vector ||
+ type == SourceType::GeoJSON ||
+ type == SourceType::Annotations) {
+ generator.update(renderTiles);
+ }
+
+ for (auto& pair : renderTiles) {
+ auto& tile = pair.second;
+ transform.matrixFor(tile.matrix, tile.id);
+ matrix::multiply(tile.matrix, projMatrix, tile.matrix);
+ }
+}
+
+void Source::Impl::finishRender(Painter& painter) {
+ for (auto& pair : renderTiles) {
+ auto& tile = pair.second;
+ painter.renderTileDebug(tile);
+ }
+}
+
+const std::map<UnwrappedTileID, RenderTile>& Source::Impl::getRenderTiles() const {
+ return renderTiles;
+}
+
+Tile* Source::Impl::getTile(const OverscaledTileID& overscaledTileID) const {
+ auto it = tiles.find(overscaledTileID);
+ if (it != tiles.end()) {
+ return it->second.get();
+ } else {
+ return nullptr;
+ }
+}
+
+bool Source::Impl::update(const UpdateParameters& parameters) {
+ bool allTilesUpdated = true;
+
+ if (!loaded || parameters.animationTime <= updated) {
+ return allTilesUpdated;
+ }
+
+ const uint16_t tileSize = getTileSize();
+ const Range<uint8_t> zoomRange = getZoomRange();
+
+ // Determine the overzooming/underzooming amounts and required tiles.
+ int32_t overscaledZoom = util::coveringZoomLevel(parameters.transformState.getZoom(), type, tileSize);
+ int32_t dataTileZoom = overscaledZoom;
+
+ std::vector<UnwrappedTileID> idealTiles;
+ if (overscaledZoom >= zoomRange.min) {
+ int32_t idealZoom = std::min<int32_t>(zoomRange.max, overscaledZoom);
+
+ // Make sure we're not reparsing overzoomed raster tiles.
+ if (type == SourceType::Raster) {
+ dataTileZoom = idealZoom;
+ }
+
+ idealTiles = util::tileCover(parameters.transformState, idealZoom);
+ }
+
+ // Stores a list of all the data tiles that we're definitely going to retain. There are two
+ // kinds of tiles we need: the ideal tiles determined by the tile cover. They may not yet be in
+ // use because they're still loading. In addition to that, we also need to retain all tiles that
+ // we're actively using, e.g. as a replacement for tile that aren't loaded yet.
+ std::set<OverscaledTileID> retain;
+
+ auto retainTileFn = [&retain](Tile& tile, bool required) -> void {
+ retain.emplace(tile.id);
+ tile.setNecessity(required ? Tile::Necessity::Required
+ : Tile::Necessity::Optional);
+ };
+ auto getTileFn = [this](const OverscaledTileID& dataTileID) -> Tile* {
+ return getTile(dataTileID);
+ };
+ auto createTileFn = [this, &parameters](const OverscaledTileID& dataTileID) -> Tile* {
+ std::unique_ptr<Tile> data = cache.get(dataTileID);
+ if (!data) {
+ data = createTile(dataTileID, parameters);
+ if (data) {
+ data->setObserver(this);
+ }
+ }
+ if (data) {
+ return tiles.emplace(dataTileID, std::move(data)).first->second.get();
+ } else {
+ return nullptr;
+ }
+ };
+ auto renderTileFn = [this](const UnwrappedTileID& renderTileID, Tile& tile) {
+ renderTiles.emplace(renderTileID, RenderTile{ renderTileID, tile });
+ };
+
+ renderTiles.clear();
+ algorithm::updateRenderables(getTileFn, createTileFn, retainTileFn, renderTileFn,
+ idealTiles, zoomRange, dataTileZoom);
+
+ if (type != SourceType::Raster && type != SourceType::Annotations && cache.getSize() == 0) {
+ size_t conservativeCacheSize =
+ ((float)parameters.transformState.getWidth() / util::tileSize) *
+ ((float)parameters.transformState.getHeight() / util::tileSize) *
+ (parameters.transformState.getMaxZoom() - parameters.transformState.getMinZoom() + 1) *
+ 0.5;
+ cache.setSize(conservativeCacheSize);
+ }
+
+ // Remove stale data tiles from the active set of tiles.
+ // This goes through the (sorted!) tiles and retain set in lockstep and removes items from
+ // tiles that don't have the corresponding key in the retain set.
+ auto dataIt = tiles.begin();
+ auto retainIt = retain.begin();
+ while (dataIt != tiles.end()) {
+ if (retainIt == retain.end() || dataIt->first < *retainIt) {
+ dataIt->second->setNecessity(Tile::Necessity::Optional);
+ cache.add(dataIt->first, std::move(dataIt->second));
+ tiles.erase(dataIt++);
+ } else {
+ if (!(*retainIt < dataIt->first)) {
+ ++dataIt;
+ }
+ ++retainIt;
+ }
+ }
+
+ const PlacementConfig newConfig{ parameters.transformState.getAngle(),
+ parameters.transformState.getPitch(),
+ parameters.debugOptions & MapDebugOptions::Collision };
+ for (auto& pair : tiles) {
+ auto tile = pair.second.get();
+ if (parameters.shouldReparsePartialTiles && tile->isIncomplete()) {
+ if (!tile->parsePending()) {
+ allTilesUpdated = false;
+ }
+ } else {
+ tile->redoPlacement(newConfig);
+ }
+ }
+
+ updated = parameters.animationTime;
+
+ return allTilesUpdated;
+}
+
+static Point<int16_t> coordinateToTilePoint(const UnwrappedTileID& tileID, const Point<double>& p) {
+ auto zoomedCoord = TileCoordinate { p, 0 }.zoomTo(tileID.canonical.z);
+ return {
+ int16_t(util::clamp<int64_t>((zoomedCoord.p.x - tileID.canonical.x - tileID.wrap * std::pow(2, tileID.canonical.z)) * util::EXTENT,
+ std::numeric_limits<int16_t>::min(),
+ std::numeric_limits<int16_t>::max())),
+ int16_t(util::clamp<int64_t>((zoomedCoord.p.y - tileID.canonical.y) * util::EXTENT,
+ std::numeric_limits<int16_t>::min(),
+ std::numeric_limits<int16_t>::max()))
+ };
+}
+
+std::unordered_map<std::string, std::vector<Feature>> Source::Impl::queryRenderedFeatures(const QueryParameters& parameters) const {
+ LineString<double> queryGeometry;
+
+ for (const auto& p : parameters.geometry) {
+ queryGeometry.push_back(TileCoordinate::fromScreenCoordinate(
+ parameters.transformState, 0, { p.x, parameters.transformState.getHeight() - p.y }).p);
+ }
+
+ mapbox::geometry::box<double> box = mapbox::geometry::envelope(queryGeometry);
+
+ std::unordered_map<std::string, std::vector<Feature>> result;
+
+ for (const auto& tilePtr : renderTiles) {
+ const RenderTile& tile = tilePtr.second;
+
+ Point<int16_t> tileSpaceBoundsMin = coordinateToTilePoint(tile.id, box.min);
+ Point<int16_t> tileSpaceBoundsMax = coordinateToTilePoint(tile.id, box.max);
+
+ if (tileSpaceBoundsMin.x >= util::EXTENT || tileSpaceBoundsMin.y >= util::EXTENT ||
+ tileSpaceBoundsMax.x < 0 || tileSpaceBoundsMax.y < 0) continue;
+
+ GeometryCoordinates tileSpaceQueryGeometry;
+
+ for (const auto& c : queryGeometry) {
+ tileSpaceQueryGeometry.push_back(coordinateToTilePoint(tile.id, c));
+ }
+
+ tile.tile.queryRenderedFeatures(result,
+ tileSpaceQueryGeometry,
+ parameters.transformState,
+ parameters.layerIDs);
+ }
+
+ return result;
+}
+
+void Source::Impl::setCacheSize(size_t size) {
+ cache.setSize(size);
+}
+
+void Source::Impl::onLowMemory() {
+ cache.clear();
+}
+
+void Source::Impl::setObserver(SourceObserver* observer_) {
+ observer = observer_;
+}
+
+void Source::Impl::onTileLoaded(Tile& tile, bool isNewTile) {
+ observer->onTileLoaded(base, tile.id, isNewTile);
+}
+
+void Source::Impl::onTileError(Tile& tile, std::exception_ptr error) {
+ observer->onTileError(base, tile.id, error);
+}
+
+void Source::Impl::onNeedsRepaint() {
+ observer->onNeedsRepaint();
+}
+
+void Source::Impl::dumpDebugLogs() const {
+ Log::Info(Event::General, "Source::id: %s", base.getID().c_str());
+ Log::Info(Event::General, "Source::loaded: %d", loaded);
+
+ for (const auto& pair : tiles) {
+ auto& tile = pair.second;
+ tile->dumpDebugLogs();
+ }
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/source_impl.hpp b/src/mbgl/style/source_impl.hpp
new file mode 100644
index 0000000000..64651d7e3f
--- /dev/null
+++ b/src/mbgl/style/source_impl.hpp
@@ -0,0 +1,101 @@
+#pragma once
+
+#include <mbgl/style/source.hpp>
+
+#include <mbgl/tile/tile_id.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/tile_cache.hpp>
+#include <mbgl/style/types.hpp>
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/mat4.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/range.hpp>
+
+#include <memory>
+#include <unordered_map>
+#include <vector>
+#include <map>
+
+namespace mbgl {
+
+class Painter;
+class FileSource;
+class TransformState;
+class RenderTile;
+
+namespace algorithm {
+class ClipIDGenerator;
+} // namespace algorithm
+
+namespace style {
+
+class UpdateParameters;
+class QueryParameters;
+class SourceObserver;
+
+class Source::Impl : public TileObserver, private util::noncopyable {
+public:
+ Impl(SourceType, std::string id, Source&);
+ ~Impl() override;
+
+ virtual void load(FileSource&) = 0;
+ bool isLoaded() const;
+
+ // Request or parse all the tiles relevant for the "TransformState". This method
+ // will return true if all the tiles were scheduled for updating of false if
+ // they were not. shouldReparsePartialTiles must be set to "true" if there is
+ // new data available that a tile in the "partial" state might be interested at.
+ bool update(const UpdateParameters&);
+
+ void startRender(algorithm::ClipIDGenerator&,
+ const mat4& projMatrix,
+ const TransformState&);
+ void finishRender(Painter&);
+
+ const std::map<UnwrappedTileID, RenderTile>& getRenderTiles() const;
+
+ Tile* getTile(const OverscaledTileID&) const;
+
+ std::unordered_map<std::string, std::vector<Feature>>
+ queryRenderedFeatures(const QueryParameters&) const;
+
+ void setCacheSize(size_t);
+ void onLowMemory();
+
+ void setObserver(SourceObserver*);
+ void dumpDebugLogs() const;
+
+ const SourceType type;
+ const std::string id;
+
+ bool loaded = false;
+ bool enabled = false;
+
+protected:
+ void invalidateTiles();
+
+ Source& base;
+ SourceObserver* observer = nullptr;
+
+private:
+ // TileObserver implementation.
+ void onTileLoaded(Tile&, bool isNewTile) override;
+ void onTileError(Tile&, std::exception_ptr) override;
+ void onNeedsRepaint() override;
+
+ virtual uint16_t getTileSize() const = 0;
+ virtual Range<uint8_t> getZoomRange() = 0;
+ virtual std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) = 0;
+
+ // Stores the time when this source was most recently updated.
+ TimePoint updated = TimePoint::min();
+
+ std::map<OverscaledTileID, std::unique_ptr<Tile>> tiles;
+ std::map<UnwrappedTileID, RenderTile> renderTiles;
+ TileCache cache;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/source_observer.hpp b/src/mbgl/style/source_observer.hpp
index a669e8e756..020ead4dba 100644
--- a/src/mbgl/style/source_observer.hpp
+++ b/src/mbgl/style/source_observer.hpp
@@ -18,7 +18,7 @@ public:
virtual void onSourceError(Source&, std::exception_ptr) {}
virtual void onTileLoaded(Source&, const OverscaledTileID&, bool /* isNewTile */) {}
virtual void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) {}
- virtual void onPlacementRedone() {}
+ virtual void onNeedsRepaint() {}
};
} // namespace style
diff --git a/src/mbgl/style/sources/geojson_source.cpp b/src/mbgl/style/sources/geojson_source.cpp
new file mode 100644
index 0000000000..a3eec4f4ef
--- /dev/null
+++ b/src/mbgl/style/sources/geojson_source.cpp
@@ -0,0 +1,21 @@
+#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/style/sources/geojson_source_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+GeoJSONSource::GeoJSONSource(const std::string& id)
+ : Source(SourceType::GeoJSON, std::make_unique<GeoJSONSource::Impl>(std::move(id), *this))
+ , impl(static_cast<Impl*>(baseImpl.get())) {
+}
+
+void GeoJSONSource::setURL(const std::string& url) {
+ impl->setURL(url);
+}
+
+void GeoJSONSource::setGeoJSON(GeoJSON&& geoJSON) {
+ impl->setGeoJSON(std::move(geoJSON));
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/geojson_source_impl.cpp b/src/mbgl/style/sources/geojson_source_impl.cpp
new file mode 100644
index 0000000000..d71df28378
--- /dev/null
+++ b/src/mbgl/style/sources/geojson_source_impl.cpp
@@ -0,0 +1,113 @@
+#include <mbgl/style/sources/geojson_source_impl.hpp>
+#include <mbgl/style/source_observer.hpp>
+#include <mbgl/style/conversion/geojson.hpp>
+#include <mbgl/tile/geojson_tile.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/platform/log.hpp>
+#include <mbgl/util/rapidjson.hpp>
+
+#include <mapbox/geojson.hpp>
+#include <mapbox/geojson/rapidjson.hpp>
+#include <mapbox/geojsonvt.hpp>
+#include <mapbox/geojsonvt/convert.hpp>
+
+#include <rapidjson/error/en.h>
+
+#include <sstream>
+
+using namespace mapbox::geojsonvt;
+
+namespace mbgl {
+namespace style {
+namespace conversion {
+
+template <>
+Result<GeoJSON> convertGeoJSON(const JSValue& value) {
+ Options options;
+ options.buffer = util::EXTENT / util::tileSize * 128;
+ options.extent = util::EXTENT;
+
+ try {
+ const auto geojson = mapbox::geojson::convert(value);
+ return GeoJSON { std::make_unique<GeoJSONVT>(geojson, options) };
+ } catch (const std::exception& ex) {
+ return Error { ex.what() };
+ }
+}
+} // namespace conversion
+
+GeoJSONSource::Impl::Impl(std::string id_, Source& base_)
+ : Source::Impl(SourceType::GeoJSON, std::move(id_), base_) {
+}
+
+GeoJSONSource::Impl::~Impl() = default;
+
+void GeoJSONSource::Impl::setURL(std::string url) {
+ urlOrGeoJSON = std::move(url);
+}
+
+void GeoJSONSource::Impl::setGeoJSON(GeoJSON&& geoJSON) {
+ urlOrGeoJSON = std::move(geoJSON);
+}
+
+void GeoJSONSource::Impl::load(FileSource& fileSource) {
+ if (urlOrGeoJSON.is<GeoJSON>()) {
+ loaded = true;
+ return;
+ }
+
+ if (req) {
+ return;
+ }
+
+ const std::string& url = urlOrGeoJSON.get<std::string>();
+ req = fileSource.request(Resource::source(url), [this](Response res) {
+ if (res.error) {
+ observer->onSourceError(base, std::make_exception_ptr(std::runtime_error(res.error->message)));
+ } else if (res.notModified) {
+ return;
+ } else if (res.noContent) {
+ observer->onSourceError(base, std::make_exception_ptr(std::runtime_error("unexpectedly empty GeoJSON")));
+ } else {
+ rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d;
+ d.Parse<0>(res.data->c_str());
+
+ if (d.HasParseError()) {
+ std::stringstream message;
+ message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError());
+ observer->onSourceError(base, std::make_exception_ptr(std::runtime_error(message.str())));
+ return;
+ }
+
+ invalidateTiles();
+
+ conversion::Result<GeoJSON> geoJSON = conversion::convertGeoJSON<JSValue>(d);
+ if (!geoJSON) {
+ Log::Error(Event::ParseStyle, "Failed to parse GeoJSON data: %s", geoJSON.error().message);
+ // Create an empty GeoJSON VT object to make sure we're not infinitely waiting for
+ // tiles to load.
+ mapbox::geojson::feature_collection features;
+ urlOrGeoJSON = GeoJSON { std::make_unique<GeoJSONVT>(features) };
+ } else {
+ urlOrGeoJSON = std::move(*geoJSON);
+ }
+
+ loaded = true;
+ observer->onSourceLoaded(base);
+ }
+ });
+}
+
+Range<uint8_t> GeoJSONSource::Impl::getZoomRange() {
+ assert(loaded);
+ return { 0, urlOrGeoJSON.get<GeoJSON>().impl->options.maxZoom };
+}
+
+std::unique_ptr<Tile> GeoJSONSource::Impl::createTile(const OverscaledTileID& tileID,
+ const UpdateParameters& parameters) {
+ assert(loaded);
+ return std::make_unique<GeoJSONTile>(tileID, base.getID(), parameters, *urlOrGeoJSON.get<GeoJSON>().impl);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/geojson_source_impl.hpp b/src/mbgl/style/sources/geojson_source_impl.hpp
new file mode 100644
index 0000000000..e6e01c06e9
--- /dev/null
+++ b/src/mbgl/style/sources/geojson_source_impl.hpp
@@ -0,0 +1,40 @@
+#pragma once
+
+#include <mbgl/style/sources/geojson_source.hpp>
+#include <mbgl/style/source_impl.hpp>
+#include <mbgl/util/variant.hpp>
+
+namespace mbgl {
+
+class AsyncRequest;
+
+namespace style {
+
+class GeoJSONSource::Impl : public Source::Impl {
+public:
+ Impl(std::string id, Source&);
+ ~Impl() final;
+
+ void setURL(std::string);
+ void setGeoJSON(GeoJSON&&);
+
+ void load(FileSource&) final;
+
+ uint16_t getTileSize() const final {
+ return util::tileSize;
+ }
+
+ const variant<std::string, GeoJSON>& getURLOrGeoJSON() const {
+ return urlOrGeoJSON;
+ }
+
+private:
+ Range<uint8_t> getZoomRange() final;
+ std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
+
+ variant<std::string, GeoJSON> urlOrGeoJSON;
+ std::unique_ptr<AsyncRequest> req;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/raster_source.cpp b/src/mbgl/style/sources/raster_source.cpp
new file mode 100644
index 0000000000..3c65476df0
--- /dev/null
+++ b/src/mbgl/style/sources/raster_source.cpp
@@ -0,0 +1,12 @@
+#include <mbgl/style/sources/raster_source.hpp>
+#include <mbgl/style/sources/raster_source_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+RasterSource::RasterSource(std::string id, variant<std::string, Tileset> urlOrTileset, uint16_t tileSize)
+ : Source(SourceType::Raster, std::make_unique<RasterSource::Impl>(std::move(id), *this, std::move(urlOrTileset), tileSize)) {
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/raster_source_impl.cpp b/src/mbgl/style/sources/raster_source_impl.cpp
new file mode 100644
index 0000000000..b727651260
--- /dev/null
+++ b/src/mbgl/style/sources/raster_source_impl.cpp
@@ -0,0 +1,19 @@
+#include <mbgl/style/sources/raster_source_impl.hpp>
+#include <mbgl/tile/raster_tile.hpp>
+
+namespace mbgl {
+namespace style {
+
+RasterSource::Impl::Impl(std::string id_, Source& base_,
+ variant<std::string, Tileset> urlOrTileset_,
+ uint16_t tileSize_)
+ : TileSourceImpl(SourceType::Raster, std::move(id_), base_, std::move(urlOrTileset_), tileSize_) {
+}
+
+std::unique_ptr<Tile> RasterSource::Impl::createTile(const OverscaledTileID& tileID,
+ const UpdateParameters& parameters) {
+ return std::make_unique<RasterTile>(tileID, parameters, tileset);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/raster_source_impl.hpp b/src/mbgl/style/sources/raster_source_impl.hpp
new file mode 100644
index 0000000000..6f34a050bb
--- /dev/null
+++ b/src/mbgl/style/sources/raster_source_impl.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <mbgl/style/sources/raster_source.hpp>
+#include <mbgl/style/tile_source_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+class RasterSource::Impl : public TileSourceImpl {
+public:
+ Impl(std::string id, Source&, variant<std::string, Tileset>, uint16_t tileSize);
+
+private:
+ std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/vector_source.cpp b/src/mbgl/style/sources/vector_source.cpp
new file mode 100644
index 0000000000..f2a6b166a9
--- /dev/null
+++ b/src/mbgl/style/sources/vector_source.cpp
@@ -0,0 +1,12 @@
+#include <mbgl/style/sources/vector_source.hpp>
+#include <mbgl/style/sources/vector_source_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+VectorSource::VectorSource(std::string id, variant<std::string, Tileset> urlOrTileset)
+ : Source(SourceType::Vector, std::make_unique<VectorSource::Impl>(std::move(id), *this, std::move(urlOrTileset))) {
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/vector_source_impl.cpp b/src/mbgl/style/sources/vector_source_impl.cpp
new file mode 100644
index 0000000000..efe8afbbea
--- /dev/null
+++ b/src/mbgl/style/sources/vector_source_impl.cpp
@@ -0,0 +1,17 @@
+#include <mbgl/style/sources/vector_source_impl.hpp>
+#include <mbgl/tile/vector_tile.hpp>
+
+namespace mbgl {
+namespace style {
+
+VectorSource::Impl::Impl(std::string id_, Source& base_, variant<std::string, Tileset> urlOrTileset_)
+ : TileSourceImpl(SourceType::Vector, std::move(id_), base_, std::move(urlOrTileset_), util::tileSize) {
+}
+
+std::unique_ptr<Tile> VectorSource::Impl::createTile(const OverscaledTileID& tileID,
+ const UpdateParameters& parameters) {
+ return std::make_unique<VectorTile>(tileID, base.getID(), parameters, tileset);
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/sources/vector_source_impl.hpp b/src/mbgl/style/sources/vector_source_impl.hpp
new file mode 100644
index 0000000000..6726fa6955
--- /dev/null
+++ b/src/mbgl/style/sources/vector_source_impl.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <mbgl/style/sources/vector_source.hpp>
+#include <mbgl/style/tile_source_impl.hpp>
+
+namespace mbgl {
+namespace style {
+
+class VectorSource::Impl : public TileSourceImpl {
+public:
+ Impl(std::string id, Source&, variant<std::string, Tileset>);
+
+private:
+ std::unique_ptr<Tile> createTile(const OverscaledTileID&, const UpdateParameters&) final;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 5ca36b030f..9073894cc2 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -1,6 +1,6 @@
#include <mbgl/style/style.hpp>
#include <mbgl/style/observer.hpp>
-#include <mbgl/style/source.hpp>
+#include <mbgl/style/source_impl.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
@@ -19,7 +19,7 @@
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/renderer/render_item.hpp>
-#include <mbgl/tile/tile.hpp>
+#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/platform/log.hpp>
@@ -47,7 +47,7 @@ Style::Style(FileSource& fileSource_, float pixelRatio)
Style::~Style() {
for (const auto& source : sources) {
- source->setObserver(nullptr);
+ source->baseImpl->setObserver(nullptr);
}
glyphStore->setObserver(nullptr);
@@ -107,15 +107,24 @@ void Style::setJSON(const std::string& json) {
}
void Style::addSource(std::unique_ptr<Source> source) {
- source->setObserver(this);
+ source->baseImpl->setObserver(this);
sources.emplace_back(std::move(source));
}
-std::vector<std::unique_ptr<Layer>> Style::getLayers() const {
- std::vector<std::unique_ptr<Layer>> result;
+void Style::removeSource(const std::string& id) {
+ auto it = std::find_if(sources.begin(), sources.end(), [&](const auto& source) {
+ return source->getID() == id;
+ });
+ if (it == sources.end())
+ throw std::runtime_error("no such source");
+ sources.erase(it);
+}
+
+std::vector<const Layer*> Style::getLayers() const {
+ std::vector<const Layer*> result;
result.reserve(layers.size());
for (const auto& layer : layers) {
- result.push_back(layer->baseImpl->clone());
+ result.push_back(layer.get());
}
return result;
}
@@ -132,6 +141,8 @@ Layer* Style::getLayer(const std::string& id) const {
}
void Style::addLayer(std::unique_ptr<Layer> layer, optional<std::string> before) {
+ // TODO: verify source
+
if (SymbolLayer* symbolLayer = layer->as<SymbolLayer>()) {
if (!symbolLayer->impl->spriteAtlas) {
symbolLayer->impl->spriteAtlas = spriteAtlas.get();
@@ -156,7 +167,7 @@ void Style::update(const UpdateParameters& parameters) {
bool allTilesUpdated = true;
for (const auto& source : sources) {
- if (!source->update(parameters)) {
+ if (!source->baseImpl->update(parameters)) {
allTilesUpdated = false;
}
}
@@ -171,7 +182,7 @@ void Style::update(const UpdateParameters& parameters) {
void Style::cascade(const TimePoint& timePoint, MapMode mode) {
// When in continuous mode, we can either have user- or style-defined
// transitions. Still mode is always immediate.
- static const TransitionOptions immediateTransition;
+ static const TransitionOptions immediateTransition {};
std::vector<ClassID> classIDs;
for (const auto& className : classes) {
@@ -195,7 +206,7 @@ void Style::cascade(const TimePoint& timePoint, MapMode mode) {
void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
for (const auto& source : sources) {
- source->enabled = false;
+ source->baseImpl->enabled = false;
}
zoomHistory.update(z, timePoint);
@@ -213,9 +224,9 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
Source* source = getSource(layer->baseImpl->source);
if (source && layer->baseImpl->needsRendering()) {
- source->enabled = true;
- if (!source->loaded && !source->isLoading()) {
- source->load(fileSource);
+ source->baseImpl->enabled = true;
+ if (!source->baseImpl->loaded) {
+ source->baseImpl->load(fileSource);
}
}
}
@@ -223,7 +234,7 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
Source* Style::getSource(const std::string& id) const {
const auto it = std::find_if(sources.begin(), sources.end(), [&](const auto& source) {
- return source->id == id;
+ return source->getID() == id;
});
return it != sources.end() ? it->get() : nullptr;
@@ -239,7 +250,7 @@ bool Style::isLoaded() const {
}
for (const auto& source: sources) {
- if (source->enabled && !source->isLoaded()) return false;
+ if (source->baseImpl->enabled && !source->baseImpl->isLoaded()) return false;
}
if (!spriteStore->isLoaded()) {
@@ -249,11 +260,11 @@ bool Style::isLoaded() const {
return true;
}
-RenderData Style::getRenderData() const {
+RenderData Style::getRenderData(MapDebugOptions debugOptions) const {
RenderData result;
for (const auto& source : sources) {
- if (source->enabled) {
+ if (source->baseImpl->enabled) {
result.sources.insert(source.get());
}
}
@@ -263,14 +274,15 @@ RenderData Style::getRenderData() const {
continue;
if (const BackgroundLayer* background = layer->as<BackgroundLayer>()) {
+ if (debugOptions & MapDebugOptions::Overdraw) {
+ // We want to skip glClear optimization in overdraw mode.
+ result.order.emplace_back(*layer);
+ continue;
+ }
const BackgroundPaintProperties& paint = background->impl->paint;
if (layer.get() == layers[0].get() && paint.backgroundPattern.value.from.empty()) {
// This is a solid background. We can use glClear().
- result.backgroundColor = paint.backgroundColor;
- result.backgroundColor[0] *= paint.backgroundOpacity;
- result.backgroundColor[1] *= paint.backgroundOpacity;
- result.backgroundColor[2] *= paint.backgroundOpacity;
- result.backgroundColor[3] *= paint.backgroundOpacity;
+ result.backgroundColor = paint.backgroundColor * paint.backgroundOpacity;
} else {
// This is a textured background, or not the bottommost layer. We need to render it with a quad.
result.order.emplace_back(*layer);
@@ -289,9 +301,9 @@ RenderData Style::getRenderData() const {
continue;
}
- for (auto& pair : source->getTiles()) {
+ for (auto& pair : source->baseImpl->getRenderTiles()) {
auto& tile = pair.second;
- if (!tile.data.isRenderable()) {
+ if (!tile.tile.isRenderable()) {
continue;
}
@@ -304,7 +316,7 @@ RenderData Style::getRenderData() const {
// already a bucket from this layer that is a parent of this tile. Tiles are ordered
// by zoom level when we obtain them from getTiles().
for (auto it = result.order.rbegin(); it != result.order.rend() && (&it->layer == layer.get()); ++it) {
- if (tile.data.id.isChildOf(it->tile->data.id)) {
+ if (tile.tile.id.isChildOf(it->tile->tile.id)) {
skip = true;
break;
}
@@ -314,7 +326,7 @@ RenderData Style::getRenderData() const {
}
}
- auto bucket = tile.data.getBucket(*layer);
+ auto bucket = tile.tile.getBucket(*layer);
if (bucket) {
result.order.emplace_back(*layer, &tile, bucket);
}
@@ -328,7 +340,7 @@ std::vector<Feature> Style::queryRenderedFeatures(const QueryParameters& paramet
std::unordered_map<std::string, std::vector<Feature>> resultsByLayer;
for (const auto& source : sources) {
- auto sourceResults = source->queryRenderedFeatures(parameters);
+ auto sourceResults = source->baseImpl->queryRenderedFeatures(parameters);
std::move(sourceResults.begin(), sourceResults.end(), std::inserter(resultsByLayer, resultsByLayer.begin()));
}
@@ -356,13 +368,13 @@ float Style::getQueryRadius() const {
void Style::setSourceTileCacheSize(size_t size) {
for (const auto& source : sources) {
- source->setCacheSize(size);
+ source->baseImpl->setCacheSize(size);
}
}
void Style::onLowMemory() {
for (const auto& source : sources) {
- source->onLowMemory();
+ source->baseImpl->onLowMemory();
}
}
@@ -373,7 +385,7 @@ void Style::setObserver(style::Observer* observer_) {
void Style::onGlyphsLoaded(const FontStack& fontStack, const GlyphRange& glyphRange) {
shouldReparsePartialTiles = true;
observer->onGlyphsLoaded(fontStack, glyphRange);
- observer->onResourceLoaded();
+ observer->onNeedsRepaint();
}
void Style::onGlyphsError(const FontStack& fontStack, const GlyphRange& glyphRange, std::exception_ptr error) {
@@ -386,13 +398,13 @@ void Style::onGlyphsError(const FontStack& fontStack, const GlyphRange& glyphRan
void Style::onSourceLoaded(Source& source) {
observer->onSourceLoaded(source);
- observer->onResourceLoaded();
+ observer->onNeedsRepaint();
}
void Style::onSourceError(Source& source, std::exception_ptr error) {
lastError = error;
Log::Error(Event::Style, "Failed to load source %s: %s",
- source.id.c_str(), util::toString(error).c_str());
+ source.getID().c_str(), util::toString(error).c_str());
observer->onSourceError(source, error);
observer->onResourceError(error);
}
@@ -403,25 +415,25 @@ void Style::onTileLoaded(Source& source, const OverscaledTileID& tileID, bool is
}
observer->onTileLoaded(source, tileID, isNewTile);
- observer->onResourceLoaded();
+ observer->onNeedsRepaint();
}
void Style::onTileError(Source& source, const OverscaledTileID& tileID, std::exception_ptr error) {
lastError = error;
Log::Error(Event::Style, "Failed to load tile %s for source %s: %s",
- util::toString(tileID).c_str(), source.id.c_str(), util::toString(error).c_str());
+ util::toString(tileID).c_str(), source.getID().c_str(), util::toString(error).c_str());
observer->onTileError(source, tileID, error);
observer->onResourceError(error);
}
-void Style::onPlacementRedone() {
- observer->onResourceLoaded();
+void Style::onNeedsRepaint() {
+ observer->onNeedsRepaint();
}
void Style::onSpriteLoaded() {
shouldReparsePartialTiles = true;
observer->onSpriteLoaded();
- observer->onResourceLoaded();
+ observer->onNeedsRepaint();
}
void Style::onSpriteError(std::exception_ptr error) {
@@ -433,7 +445,7 @@ void Style::onSpriteError(std::exception_ptr error) {
void Style::dumpDebugLogs() const {
for (const auto& source : sources) {
- source->dumpDebugLogs();
+ source->baseImpl->dumpDebugLogs();
}
spriteStore->dumpDebugLogs();
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 05a975a95a..35369ffca3 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -37,7 +37,7 @@ class Style : public GlyphStoreObserver,
public util::noncopyable {
public:
Style(FileSource&, float pixelRatio);
- ~Style();
+ ~Style() override;
void setJSON(const std::string&);
@@ -60,8 +60,9 @@ public:
Source* getSource(const std::string& id) const;
void addSource(std::unique_ptr<Source>);
+ void removeSource(const std::string& sourceID);
- std::vector<std::unique_ptr<Layer>> getLayers() const;
+ std::vector<const Layer*> getLayers() const;
Layer* getLayer(const std::string& id) const;
void addLayer(std::unique_ptr<Layer>,
optional<std::string> beforeLayerID = {});
@@ -73,7 +74,7 @@ public:
void setClasses(const std::vector<std::string>&, const TransitionOptions& = {});
std::vector<std::string> getClasses() const;
- RenderData getRenderData() const;
+ RenderData getRenderData(MapDebugOptions) const;
std::vector<Feature> queryRenderedFeatures(const QueryParameters&) const;
@@ -112,7 +113,7 @@ private:
void onSourceError(Source&, std::exception_ptr) override;
void onTileLoaded(Source&, const OverscaledTileID&, bool isNewTile) override;
void onTileError(Source&, const OverscaledTileID&, std::exception_ptr) override;
- void onPlacementRedone() override;
+ void onNeedsRepaint() override;
Observer nullObserver;
Observer* observer = &nullObserver;
diff --git a/src/mbgl/style/tile_source_impl.cpp b/src/mbgl/style/tile_source_impl.cpp
new file mode 100644
index 0000000000..3999a88a07
--- /dev/null
+++ b/src/mbgl/style/tile_source_impl.cpp
@@ -0,0 +1,118 @@
+#include <mbgl/style/tile_source_impl.hpp>
+#include <mbgl/style/source_observer.hpp>
+#include <mbgl/style/rapidjson_conversion.hpp>
+#include <mbgl/style/conversion/tileset.hpp>
+#include <mbgl/util/tileset.hpp>
+#include <mbgl/util/mapbox.hpp>
+#include <mbgl/storage/file_source.hpp>
+
+#include <rapidjson/document.h>
+#include <rapidjson/error/en.h>
+
+#include <sstream>
+
+namespace mbgl {
+namespace style {
+
+Tileset TileSourceImpl::parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType type, uint16_t tileSize) {
+ rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> document;
+ document.Parse<0>(json.c_str());
+
+ if (document.HasParseError()) {
+ std::stringstream message;
+ message << document.GetErrorOffset() << " - " << rapidjson::GetParseError_En(document.GetParseError());
+ throw std::runtime_error(message.str());
+ }
+
+ conversion::Result<Tileset> result = conversion::convert<Tileset>(document);
+ if (!result) {
+ throw std::runtime_error(result.error().message);
+ }
+
+ // TODO: Remove this hack by delivering proper URLs in the TileJSON to begin with.
+ if (util::mapbox::isMapboxURL(sourceURL)) {
+ for (auto& url : (*result).tiles) {
+ url = util::mapbox::canonicalizeTileURL(url, type, tileSize);
+ }
+ }
+
+ return *result;
+}
+
+TileSourceImpl::TileSourceImpl(SourceType type_, std::string id_, Source& base_,
+ variant<std::string, Tileset> urlOrTileset_,
+ uint16_t tileSize_)
+ : Impl(type_, std::move(id_), base_),
+ urlOrTileset(std::move(urlOrTileset_)),
+ tileSize(tileSize_) {
+}
+
+TileSourceImpl::~TileSourceImpl() = default;
+
+void TileSourceImpl::load(FileSource& fileSource) {
+ if (urlOrTileset.is<Tileset>()) {
+ tileset = urlOrTileset.get<Tileset>();
+ loaded = true;
+ return;
+ }
+
+ if (req) {
+ return;
+ }
+
+ const std::string& url = urlOrTileset.get<std::string>();
+ req = fileSource.request(Resource::source(url), [this, url](Response res) {
+ if (res.error) {
+ observer->onSourceError(base, std::make_exception_ptr(std::runtime_error(res.error->message)));
+ } else if (res.notModified) {
+ return;
+ } else if (res.noContent) {
+ observer->onSourceError(base, std::make_exception_ptr(std::runtime_error("unexpectedly empty TileJSON")));
+ } else {
+ Tileset newTileset;
+
+ // Create a new copy of the Tileset object that holds the base values we've parsed
+ // from the stylesheet. Then merge in the values parsed from the TileJSON we retrieved
+ // via the URL.
+ try {
+ newTileset = parseTileJSON(*res.data, url, type, tileSize);
+ } catch (...) {
+ observer->onSourceError(base, std::current_exception());
+ return;
+ }
+
+ // Check whether previous information specifies different tile
+ if (tileset.tiles != newTileset.tiles) {
+ // Tile URLs changed: force tiles to be reloaded.
+ invalidateTiles();
+
+ // Tile size changed: We need to recalculate the tiles we need to load because we
+ // might have to load tiles for a different zoom level
+ // This is done automatically when we trigger the onSourceLoaded observer below.
+
+ // Min/Max zoom changed: We need to recalculate what tiles to load, if we have tiles
+ // loaded that are outside the new zoom range
+ // This is done automatically when we trigger the onSourceLoaded observer below.
+
+ // Attribution changed: We need to notify the embedding application that this
+ // changed. See https://github.com/mapbox/mapbox-gl-native/issues/2723
+ // This is not yet implemented.
+
+ // Center/bounds changed: We're not using these values currently
+ }
+
+ tileset = newTileset;
+ loaded = true;
+
+ observer->onSourceLoaded(base);
+ }
+ });
+}
+
+Range<uint8_t> TileSourceImpl::getZoomRange() {
+ assert(loaded);
+ return tileset.zoomRange;
+}
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/tile_source_impl.hpp b/src/mbgl/style/tile_source_impl.hpp
new file mode 100644
index 0000000000..8f420a15d5
--- /dev/null
+++ b/src/mbgl/style/tile_source_impl.hpp
@@ -0,0 +1,48 @@
+#pragma once
+
+#include <mbgl/style/source_impl.hpp>
+#include <mbgl/util/tileset.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/optional.hpp>
+
+namespace mbgl {
+
+class AsyncRequest;
+
+namespace style {
+
+/*
+ Shared implementation for VectorSource and RasterSource. Should eventually
+ be refactored to use composition rather than inheritance.
+*/
+class TileSourceImpl : public Source::Impl {
+public:
+ static Tileset parseTileJSON(const std::string& json, const std::string& sourceURL, SourceType, uint16_t tileSize);
+
+ TileSourceImpl(SourceType, std::string id, Source&,
+ variant<std::string, Tileset> urlOrTileset,
+ uint16_t tileSize);
+ ~TileSourceImpl() override;
+
+ void load(FileSource&) final;
+
+ uint16_t getTileSize() const final {
+ return tileSize;
+ }
+
+ const variant<std::string, Tileset>& getURLOrTileset() const {
+ return urlOrTileset;
+ }
+
+protected:
+ Range<uint8_t> getZoomRange() final;
+
+ const variant<std::string, Tileset> urlOrTileset;
+ const uint16_t tileSize;
+
+ Tileset tileset;
+ std::unique_ptr<AsyncRequest> req;
+};
+
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/types.cpp b/src/mbgl/style/types.cpp
new file mode 100644
index 0000000000..25a1753870
--- /dev/null
+++ b/src/mbgl/style/types.cpp
@@ -0,0 +1,87 @@
+#include <mbgl/style/types.hpp>
+#include <mbgl/util/enum.hpp>
+
+namespace mbgl {
+
+using namespace style;
+
+MBGL_DEFINE_ENUM(SourceType, {
+ { SourceType::Vector, "vector" },
+ { SourceType::Raster, "raster" },
+ { SourceType::GeoJSON, "geojson" },
+ { SourceType::Video, "video" },
+ { SourceType::Annotations, "annotations" },
+});
+
+MBGL_DEFINE_ENUM(VisibilityType, {
+ { VisibilityType::Visible, "visible" },
+ { VisibilityType::None, "none" },
+});
+
+MBGL_DEFINE_ENUM(TranslateAnchorType, {
+ { TranslateAnchorType::Map, "map" },
+ { TranslateAnchorType::Viewport, "viewport" },
+});
+
+MBGL_DEFINE_ENUM(RotateAnchorType, {
+ { RotateAnchorType::Map, "map" },
+ { RotateAnchorType::Viewport, "viewport" },
+});
+
+MBGL_DEFINE_ENUM(LineCapType, {
+ { LineCapType::Round, "round" },
+ { LineCapType::Butt, "butt" },
+ { LineCapType::Square, "square" },
+});
+
+MBGL_DEFINE_ENUM(LineJoinType, {
+ { LineJoinType::Miter, "miter" },
+ { LineJoinType::Bevel, "bevel" },
+ { LineJoinType::Round, "round" },
+ { LineJoinType::FakeRound, "fakeround" },
+ { LineJoinType::FlipBevel, "flipbevel" },
+});
+
+MBGL_DEFINE_ENUM(SymbolPlacementType, {
+ { SymbolPlacementType::Point, "point" },
+ { SymbolPlacementType::Line, "line" },
+});
+
+MBGL_DEFINE_ENUM(TextAnchorType, {
+ { TextAnchorType::Center, "center" },
+ { TextAnchorType::Left, "left" },
+ { TextAnchorType::Right, "right" },
+ { TextAnchorType::Top, "top" },
+ { TextAnchorType::Bottom, "bottom" },
+ { TextAnchorType::TopLeft, "top-left" },
+ { TextAnchorType::TopRight, "top-right" },
+ { TextAnchorType::BottomLeft, "bottom-left" },
+ { TextAnchorType::BottomRight, "bottom-right" }
+});
+
+MBGL_DEFINE_ENUM(TextJustifyType, {
+ { TextJustifyType::Center, "center" },
+ { TextJustifyType::Left, "left" },
+ { TextJustifyType::Right, "right" },
+});
+
+MBGL_DEFINE_ENUM(TextTransformType, {
+ { TextTransformType::None, "none" },
+ { TextTransformType::Uppercase, "uppercase" },
+ { TextTransformType::Lowercase, "lowercase" },
+});
+
+MBGL_DEFINE_ENUM(AlignmentType, {
+ { AlignmentType::Map, "map" },
+ { AlignmentType::Viewport, "viewport" },
+ { AlignmentType::Undefined, "undefined" },
+});
+
+MBGL_DEFINE_ENUM(IconTextFitType, {
+ { IconTextFitType::None, "none" },
+ { IconTextFitType::Both, "both" },
+ { IconTextFitType::Width, "width" },
+ { IconTextFitType::Height, "height" },
+});
+
+} // namespace mbgl
diff --git a/src/mbgl/style/update_parameters.hpp b/src/mbgl/style/update_parameters.hpp
index 9faaa32d6f..bdae4f42b0 100644
--- a/src/mbgl/style/update_parameters.hpp
+++ b/src/mbgl/style/update_parameters.hpp
@@ -7,7 +7,6 @@ namespace mbgl {
class TransformState;
class Worker;
class FileSource;
-namespace gl { class TexturePool; }
class AnnotationManager;
namespace style {
@@ -22,18 +21,16 @@ public:
const TransformState& transformState_,
Worker& worker_,
FileSource& fileSource_,
- gl::TexturePool& texturePool_,
bool shouldReparsePartialTiles_,
const MapMode mode_,
AnnotationManager& annotationManager_,
Style& style_)
: pixelRatio(pixelRatio_),
debugOptions(debugOptions_),
- animationTime(animationTime_),
+ animationTime(std::move(animationTime_)),
transformState(transformState_),
worker(worker_),
fileSource(fileSource_),
- texturePool(texturePool_),
shouldReparsePartialTiles(shouldReparsePartialTiles_),
mode(mode_),
annotationManager(annotationManager_),
@@ -45,7 +42,6 @@ public:
const TransformState& transformState;
Worker& worker;
FileSource& fileSource;
- gl::TexturePool& texturePool;
bool shouldReparsePartialTiles;
const MapMode mode;
AnnotationManager& annotationManager;
diff --git a/src/mbgl/text/check_max_angle.hpp b/src/mbgl/text/check_max_angle.hpp
index 5e1ff6f049..008e70b5da 100644
--- a/src/mbgl/text/check_max_angle.hpp
+++ b/src/mbgl/text/check_max_angle.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
namespace mbgl {
diff --git a/src/mbgl/text/collision_feature.cpp b/src/mbgl/text/collision_feature.cpp
index 57a9da0440..74a41099ff 100644
--- a/src/mbgl/text/collision_feature.cpp
+++ b/src/mbgl/text/collision_feature.cpp
@@ -5,9 +5,9 @@ namespace mbgl {
CollisionFeature::CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor,
const float top, const float bottom, const float left, const float right,
- const float boxScale, const float padding, const bool alongLine, const IndexedSubfeature& indexedFeature_,
+ const float boxScale, const float padding, const bool alongLine, IndexedSubfeature indexedFeature_,
const bool straight)
- : indexedFeature(indexedFeature_) {
+ : indexedFeature(std::move(indexedFeature_)) {
if (top == 0 && bottom == 0 && left == 0 && right == 0) return;
diff --git a/src/mbgl/text/collision_feature.hpp b/src/mbgl/text/collision_feature.hpp
index 0fcc083a19..5c0095bc6d 100644
--- a/src/mbgl/text/collision_feature.hpp
+++ b/src/mbgl/text/collision_feature.hpp
@@ -2,7 +2,7 @@
#include <mbgl/geometry/anchor.hpp>
#include <mbgl/text/shaping.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <vector>
@@ -10,8 +10,8 @@
namespace mbgl {
class CollisionBox {
public:
- explicit CollisionBox(const Point<float> &_anchor, float _x1, float _y1, float _x2, float _y2, float _maxScale) :
- anchor(_anchor), x1(_x1), y1(_y1), x2(_x2), y2(_y2), maxScale(_maxScale) {}
+ explicit CollisionBox(Point<float> _anchor, float _x1, float _y1, float _x2, float _y2, float _maxScale) :
+ anchor(std::move(_anchor)), x1(_x1), y1(_y1), x2(_x2), y2(_y2), maxScale(_maxScale) {}
// the box is centered around the anchor point
Point<float> anchor;
@@ -33,7 +33,7 @@ namespace mbgl {
class CollisionFeature {
public:
// for text
- inline explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor,
+ explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor,
const Shaping &shapedText,
const float boxScale, const float padding, const bool alongLine, const IndexedSubfeature& indexedFeature_)
: CollisionFeature(line, anchor,
@@ -41,7 +41,7 @@ namespace mbgl {
boxScale, padding, alongLine, indexedFeature_, false) {}
// for icons
- inline explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor,
+ explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor,
const PositionedIcon &shapedIcon,
const float boxScale, const float padding, const bool alongLine, const IndexedSubfeature& indexedFeature_)
: CollisionFeature(line, anchor,
@@ -51,7 +51,7 @@ namespace mbgl {
explicit CollisionFeature(const GeometryCoordinates &line, const Anchor &anchor,
const float top, const float bottom, const float left, const float right,
const float boxScale, const float padding, const bool alongLine,
- const IndexedSubfeature&, const bool straight);
+ IndexedSubfeature, const bool straight);
std::vector<CollisionBox> boxes;
diff --git a/src/mbgl/text/collision_tile.cpp b/src/mbgl/text/collision_tile.cpp
index e7824cde3c..982dff1688 100644
--- a/src/mbgl/text/collision_tile.cpp
+++ b/src/mbgl/text/collision_tile.cpp
@@ -9,7 +9,7 @@ namespace mbgl {
auto infinity = std::numeric_limits<float>::infinity();
-CollisionTile::CollisionTile(PlacementConfig config_) : config(config_),
+CollisionTile::CollisionTile(PlacementConfig config_) : config(std::move(config_)),
edges({{
// left
CollisionBox(Point<float>(0, 0), 0, -infinity, 0, infinity, infinity),
diff --git a/src/mbgl/text/get_anchors.cpp b/src/mbgl/text/get_anchors.cpp
index c55f238e52..ce45e05d9c 100644
--- a/src/mbgl/text/get_anchors.cpp
+++ b/src/mbgl/text/get_anchors.cpp
@@ -80,25 +80,25 @@ Anchors getAnchors(const GeometryCoordinates &line, float spacing,
const float angleWindowSize = (textLeft - textRight) != 0.0f ?
3.0f / 5.0f * glyphSize * boxScale :
0;
-
+
const float labelLength = fmax(textRight - textLeft, iconRight - iconLeft);
-
+
// Is the line continued from outside the tile boundary?
const bool continuedLine = (line[0].x == 0 || line[0].x == util::EXTENT || line[0].y == 0 || line[0].y == util::EXTENT);
-
+
// Is the label long, relative to the spacing?
// If so, adjust the spacing so there is always a minimum space of `spacing / 4` between label edges.
if (spacing - labelLength * boxScale < spacing / 4) {
spacing = labelLength * boxScale + spacing / 4;
}
-
+
// Offset the first anchor by:
// Either half the label length plus a fixed extra offset if the line is not continued
// Or half the spacing if the line is continued.
// For non-continued lines, add a bit of fixed extra offset to avoid collisions at T intersections.
const float fixedExtraOffset = glyphSize * 2;
-
+
const float offset = !continuedLine ?
std::fmod((labelLength / 2 + fixedExtraOffset) * boxScale * overscaling, spacing) :
std::fmod(spacing / 2 * overscaling, spacing);
diff --git a/src/mbgl/text/get_anchors.hpp b/src/mbgl/text/get_anchors.hpp
index 9a0a5a650c..b61f8fe0dc 100644
--- a/src/mbgl/text/get_anchors.hpp
+++ b/src/mbgl/text/get_anchors.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/geometry/anchor.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/util/math.hpp>
namespace mbgl {
diff --git a/src/mbgl/text/glyph.hpp b/src/mbgl/text/glyph.hpp
index b5891831d5..975dc4ad23 100644
--- a/src/mbgl/text/glyph.hpp
+++ b/src/mbgl/text/glyph.hpp
@@ -28,10 +28,9 @@ struct GlyphMetrics {
};
struct Glyph {
- inline explicit Glyph() : rect(0, 0, 0, 0), metrics() {}
- inline explicit Glyph(const Rect<uint16_t> &rect_,
- const GlyphMetrics &metrics_)
- : rect(rect_), metrics(metrics_) {}
+ explicit Glyph() : rect(0, 0, 0, 0), metrics() {}
+ explicit Glyph(Rect<uint16_t> rect_, GlyphMetrics metrics_)
+ : rect(std::move(rect_)), metrics(std::move(metrics_)) {}
operator bool() const {
return metrics || rect.hasArea();
@@ -45,7 +44,7 @@ typedef std::map<uint32_t, Glyph> GlyphPositions;
class PositionedGlyph {
public:
- inline explicit PositionedGlyph(uint32_t glyph_, float x_, float y_)
+ explicit PositionedGlyph(uint32_t glyph_, float x_, float y_)
: glyph(glyph_), x(x_), y(y_) {}
uint32_t glyph = 0;
@@ -55,8 +54,8 @@ public:
class Shaping {
public:
- inline explicit Shaping() : top(0), bottom(0), left(0), right(0) {}
- inline explicit Shaping(float x, float y, std::u32string text_)
+ explicit Shaping() : top(0), bottom(0), left(0), right(0) {}
+ explicit Shaping(float x, float y, std::u32string text_)
: text(std::move(text_)), top(y), bottom(y), left(x), right(x) {}
std::vector<PositionedGlyph> positionedGlyphs;
std::u32string text;
diff --git a/src/mbgl/text/glyph_pbf.cpp b/src/mbgl/text/glyph_pbf.cpp
index 9046464c5c..b4dac4ce01 100644
--- a/src/mbgl/text/glyph_pbf.cpp
+++ b/src/mbgl/text/glyph_pbf.cpp
@@ -53,7 +53,7 @@ void parseGlyphPBF(mbgl::GlyphSet& glyphSet, const std::string& data) {
}
}
- glyphSet.insert(glyph.id, glyph);
+ glyphSet.insert(glyph.id, std::move(glyph));
}
}
}
diff --git a/src/mbgl/text/glyph_set.cpp b/src/mbgl/text/glyph_set.cpp
index 8bd7e4ae03..0875a83850 100644
--- a/src/mbgl/text/glyph_set.cpp
+++ b/src/mbgl/text/glyph_set.cpp
@@ -6,11 +6,11 @@
namespace mbgl {
-void GlyphSet::insert(uint32_t id, const SDFGlyph &glyph) {
+void GlyphSet::insert(uint32_t id, SDFGlyph&& glyph) {
auto it = sdfs.find(id);
if (it == sdfs.end()) {
// Glyph doesn't exist yet.
- sdfs.emplace(id, glyph);
+ sdfs.emplace(id, std::move(glyph));
} else if (it->second.metrics == glyph.metrics) {
if (it->second.bitmap != glyph.bitmap) {
// The actual bitmap was updated; this is unsupported.
@@ -18,7 +18,7 @@ void GlyphSet::insert(uint32_t id, const SDFGlyph &glyph) {
}
// At least try to update it in case it's currently unsused.
// If it is already used; we won't attempt to update the glyph atlas texture.
- it->second.bitmap = glyph.bitmap;
+ it->second.bitmap = std::move(glyph.bitmap);
} else {
// The metrics were updated; this is unsupported.
Log::Warning(Event::Glyph, "Modified glyph has different metrics");
diff --git a/src/mbgl/text/glyph_set.hpp b/src/mbgl/text/glyph_set.hpp
index 77e2cb1c95..37ffdb070a 100644
--- a/src/mbgl/text/glyph_set.hpp
+++ b/src/mbgl/text/glyph_set.hpp
@@ -7,7 +7,7 @@ namespace mbgl {
class GlyphSet {
public:
- void insert(uint32_t id, const SDFGlyph &glyph);
+ void insert(uint32_t id, SDFGlyph&&);
const std::map<uint32_t, SDFGlyph> &getSDFs() const;
const Shaping getShaping(const std::u32string &string, float maxWidth, float lineHeight,
float horizontalAlign, float verticalAlign, float justify,
diff --git a/src/mbgl/text/placement_config.hpp b/src/mbgl/text/placement_config.hpp
index 75345b89e8..7e61cabc24 100644
--- a/src/mbgl/text/placement_config.hpp
+++ b/src/mbgl/text/placement_config.hpp
@@ -4,15 +4,15 @@ namespace mbgl {
class PlacementConfig {
public:
- inline PlacementConfig(float angle_ = 0, float pitch_ = 0, bool debug_ = false)
+ PlacementConfig(float angle_ = 0, float pitch_ = 0, bool debug_ = false)
: angle(angle_), pitch(pitch_), debug(debug_) {
}
- inline bool operator==(const PlacementConfig& rhs) const {
+ bool operator==(const PlacementConfig& rhs) const {
return angle == rhs.angle && pitch == rhs.pitch && debug == rhs.debug;
}
- inline bool operator!=(const PlacementConfig& rhs) const {
+ bool operator!=(const PlacementConfig& rhs) const {
return !operator==(rhs);
}
diff --git a/src/mbgl/text/quads.cpp b/src/mbgl/text/quads.cpp
index ce320791c3..727b86f610 100644
--- a/src/mbgl/text/quads.cpp
+++ b/src/mbgl/text/quads.cpp
@@ -1,6 +1,6 @@
#include <mbgl/text/quads.hpp>
#include <mbgl/text/shaping.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/geometry/anchor.hpp>
#include <mbgl/style/layers/symbol_layer_properties.hpp>
#include <mbgl/util/math.hpp>
@@ -15,7 +15,7 @@ const float globalMinScale = 0.5f; // underscale by 1 zoom level
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
const GeometryCoordinates& line, const SymbolLayoutProperties& layout,
- const bool alongLine) {
+ const bool alongLine, const Shaping& shapedText) {
auto image = *(shapedIcon.image);
@@ -24,11 +24,43 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
auto right = left + image.pos.w / image.relativePixelRatio;
auto top = shapedIcon.top - border;
auto bottom = top + image.pos.h / image.relativePixelRatio;
- Point<float> tl{left, top};
- Point<float> tr{right, top};
- Point<float> br{right, bottom};
- Point<float> bl{left, bottom};
-
+ Point<float> tl;
+ Point<float> tr;
+ Point<float> br;
+ Point<float> bl;
+
+ if (layout.iconTextFit != IconTextFitType::None && shapedText) {
+ auto iconWidth = right - left;
+ auto iconHeight = bottom - top;
+ auto size = layout.textSize / 24.0f;
+ auto textLeft = shapedText.left * size;
+ auto textRight = shapedText.right * size;
+ auto textTop = shapedText.top * size;
+ auto textBottom = shapedText.bottom * size;
+ auto textWidth = textRight - textLeft;
+ auto textHeight = textBottom - textTop;;
+ auto padT = layout.iconTextFitPadding.value[0];
+ auto padR = layout.iconTextFitPadding.value[1];
+ auto padB = layout.iconTextFitPadding.value[2];
+ auto padL = layout.iconTextFitPadding.value[3];
+ auto offsetY = layout.iconTextFit == IconTextFitType::Width ? (textHeight - iconHeight) * 0.5 : 0;
+ auto offsetX = layout.iconTextFit == IconTextFitType::Height ? (textWidth - iconWidth) * 0.5 : 0;
+ auto width = layout.iconTextFit == IconTextFitType::Width || layout.iconTextFit == IconTextFitType::Both ? textWidth : iconWidth;
+ auto height = layout.iconTextFit == IconTextFitType::Height || layout.iconTextFit == IconTextFitType::Both ? textHeight : iconHeight;
+ left = textLeft + offsetX - padL;
+ top = textTop + offsetY - padT;
+ right = textLeft + offsetX + padR + width;
+ bottom = textTop + offsetY + padB + height;
+ tl = {left, top};
+ tr = {right, top};
+ br = {right, bottom};
+ bl = {left, bottom};
+ } else {
+ tl = {left, top};
+ tr = {right, top};
+ br = {right, bottom};
+ bl = {left, bottom};
+ }
float angle = layout.iconRotate * util::DEG2RAD;
if (alongLine) {
@@ -57,15 +89,15 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
}
SymbolQuads quads;
- quads.emplace_back(tl, tr, bl, br, image.pos, 0, anchor.point, globalMinScale, std::numeric_limits<float>::infinity());
+ quads.emplace_back(tl, tr, bl, br, image.pos, 0, 0, anchor.point, globalMinScale, std::numeric_limits<float>::infinity());
return quads;
}
struct GlyphInstance {
- explicit GlyphInstance(const Point<float> &anchorPoint_) : anchorPoint(anchorPoint_) {}
- explicit GlyphInstance(const Point<float> &anchorPoint_, float offset_, float minScale_, float maxScale_,
+ explicit GlyphInstance(Point<float> anchorPoint_) : anchorPoint(std::move(anchorPoint_)) {}
+ explicit GlyphInstance(Point<float> anchorPoint_, float offset_, float minScale_, float maxScale_,
float angle_)
- : anchorPoint(anchorPoint_), offset(offset_), minScale(minScale_), maxScale(maxScale_), angle(angle_) {}
+ : anchorPoint(std::move(anchorPoint_)), offset(offset_), minScale(minScale_), maxScale(maxScale_), angle(angle_) {}
const Point<float> anchorPoint;
const float offset = 0.0f;
@@ -102,8 +134,6 @@ void getSegmentGlyphs(std::back_insert_iterator<GlyphInstances> glyphs, Anchor &
float angle = std::atan2(end.y - newAnchorPoint.y, end.x - newAnchorPoint.x);
if (!forward)
angle += M_PI;
- if (upsideDown)
- angle += M_PI;
glyphs = GlyphInstance{
/* anchor */ newAnchorPoint,
@@ -188,12 +218,11 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
Point<float> tr = otr;
Point<float> bl = obl;
Point<float> br = obr;
- const float angle = instance.angle + textRotate;
- if (angle) {
+ if (textRotate) {
// Compute the transformation matrix.
- float angle_sin = std::sin(angle);
- float angle_cos = std::cos(angle);
+ float angle_sin = std::sin(textRotate);
+ float angle_cos = std::cos(textRotate);
std::array<float, 4> matrix = {{angle_cos, -angle_sin, angle_sin, angle_cos}};
tl = util::matrixMultiply(matrix, tl);
@@ -205,8 +234,9 @@ SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
// Prevent label from extending past the end of the line
const float glyphMinScale = std::max(instance.minScale, anchor.scale);
- const float glyphAngle = std::fmod((anchor.angle + textRotate + instance.offset + 2 * M_PI), (2 * M_PI));
- quads.emplace_back(tl, tr, bl, br, rect, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale);
+ const float anchorAngle = std::fmod((anchor.angle + instance.offset + 2 * M_PI), (2 * M_PI));
+ const float glyphAngle = std::fmod((instance.angle + instance.offset + 2 * M_PI), (2 * M_PI));
+ quads.emplace_back(tl, tr, bl, br, rect, anchorAngle, glyphAngle, instance.anchorPoint, glyphMinScale, instance.maxScale);
}
diff --git a/src/mbgl/text/quads.hpp b/src/mbgl/text/quads.hpp
index 0627647f4c..dd64af682a 100644
--- a/src/mbgl/text/quads.hpp
+++ b/src/mbgl/text/quads.hpp
@@ -1,7 +1,7 @@
#pragma once
#include <mbgl/text/glyph.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <vector>
@@ -12,26 +12,26 @@ class PositionedIcon;
namespace style {
class SymbolLayoutProperties;
-}
+} // namespace style
struct SymbolQuad {
- explicit SymbolQuad(const Point<float> &tl_, const Point<float> &tr_,
- const Point<float> &bl_, const Point<float> &br_,
- const Rect<uint16_t> &tex_, float angle_, const Point<float> &anchorPoint_,
+ explicit SymbolQuad(Point<float> tl_, Point<float> tr_, Point<float> bl_, Point<float> br_,
+ Rect<uint16_t> tex_, float anchorAngle_, float glyphAngle_, Point<float> anchorPoint_,
float minScale_, float maxScale_)
- : tl(tl_),
- tr(tr_),
- bl(bl_),
- br(br_),
- tex(tex_),
- angle(angle_),
- anchorPoint(anchorPoint_),
+ : tl(std::move(tl_)),
+ tr(std::move(tr_)),
+ bl(std::move(bl_)),
+ br(std::move(br_)),
+ tex(std::move(tex_)),
+ anchorAngle(anchorAngle_),
+ glyphAngle(glyphAngle_),
+ anchorPoint(std::move(anchorPoint_)),
minScale(minScale_),
maxScale(maxScale_) {}
Point<float> tl, tr, bl, br;
Rect<uint16_t> tex;
- float angle;
+ float anchorAngle, glyphAngle;
Point<float> anchorPoint;
float minScale, maxScale;
};
@@ -40,7 +40,7 @@ typedef std::vector<SymbolQuad> SymbolQuads;
SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
const GeometryCoordinates& line, const style::SymbolLayoutProperties&,
- const bool alongLine);
+ const bool alongLine, const Shaping& shapedText);
SymbolQuads getGlyphQuads(Anchor& anchor, const Shaping& shapedText,
const float boxScale, const GeometryCoordinates& line, const style::SymbolLayoutProperties&,
diff --git a/src/mbgl/text/shaping.hpp b/src/mbgl/text/shaping.hpp
index f81230acec..cd5e8105fd 100644
--- a/src/mbgl/text/shaping.hpp
+++ b/src/mbgl/text/shaping.hpp
@@ -11,12 +11,12 @@ struct SpriteAtlasElement;
namespace style {
class SymbolLayoutProperties;
-}
+} // namespace style
class PositionedIcon {
public:
- inline explicit PositionedIcon() {}
- inline explicit PositionedIcon(const SpriteAtlasElement& _image,
+ explicit PositionedIcon() {}
+ explicit PositionedIcon(const SpriteAtlasElement& _image,
float _top, float _bottom, float _left, float _right) :
image(_image), top(_top), bottom(_bottom), left(_left), right(_right) {}
diff --git a/src/mbgl/tile/geojson_tile.cpp b/src/mbgl/tile/geojson_tile.cpp
index 90147ffd87..0dc4ac9107 100644
--- a/src/mbgl/tile/geojson_tile.cpp
+++ b/src/mbgl/tile/geojson_tile.cpp
@@ -1,100 +1,76 @@
#include <mbgl/tile/geojson_tile.hpp>
-#include <mbgl/storage/file_source.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/style/update_parameters.hpp>
+
#include <mapbox/geojsonvt.hpp>
namespace mbgl {
-GeoJSONTileFeature::GeoJSONTileFeature(FeatureType type_,
- GeometryCollection&& geometries_,
- Feature::property_map&& properties_)
- : type(type_), geometries(std::move(geometries_)), properties(std::move(properties_)) {
-}
-
-FeatureType GeoJSONTileFeature::getType() const {
- return type;
-}
-
-optional<Value> GeoJSONTileFeature::getValue(const std::string& key) const {
- auto it = properties.find(key);
- if (it != properties.end()) {
- return optional<Value>(it->second);
- }
- return optional<Value>();
-}
-
-GeometryCollection GeoJSONTileFeature::getGeometries() const {
- return geometries;
-}
-
-GeoJSONTileLayer::GeoJSONTileLayer(Features&& features_) : features(std::move(features_)) {
-}
-
-std::size_t GeoJSONTileLayer::featureCount() const {
- return features.size();
-}
-
-util::ptr<const GeometryTileFeature> GeoJSONTileLayer::getFeature(std::size_t i) const {
- return features[i];
-}
-
-GeoJSONTile::GeoJSONTile(std::shared_ptr<GeoJSONTileLayer> layer_) : layer(std::move(layer_)) {
-}
-
-util::ptr<GeometryTileLayer> GeoJSONTile::getLayer(const std::string&) const {
- // We're ignoring the layer name because GeoJSON tiles only have one layer.
- return layer;
-}
+// Implements a simple in-memory Tile type that holds GeoJSON values. A GeoJSON tile can only have
+// one layer, and it is always returned regardless of which layer is requested.
+
+class GeoJSONTileFeature : public GeometryTileFeature {
+public:
+ GeoJSONTileFeature(FeatureType, GeometryCollection&&, PropertyMap&&);
+ FeatureType getType() const override;
+ optional<Value> getValue(const std::string&) const override;
+ PropertyMap getProperties() const override { return properties; }
+ GeometryCollection getGeometries() const override;
+
+private:
+ const FeatureType type;
+ const GeometryCollection geometries;
+ const PropertyMap properties;
+};
+
+class GeoJSONTileLayer : public GeometryTileLayer {
+public:
+ using Features = std::vector<std::shared_ptr<const GeoJSONTileFeature>>;
+
+ GeoJSONTileLayer(Features&&);
+ std::size_t featureCount() const override;
+ util::ptr<const GeometryTileFeature> getFeature(std::size_t) const override;
+ std::string getName() const override { return ""; };
+
+private:
+ const Features features;
+};
+
+class GeoJSONTileData : public GeometryTileData {
+public:
+ GeoJSONTileData(std::shared_ptr<GeoJSONTileLayer>);
+ util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
+
+private:
+ const std::shared_ptr<GeoJSONTileLayer> layer;
+};
// Converts the geojsonvt::Tile to a a GeoJSONTile. They have a differing internal structure.
-std::unique_ptr<GeoJSONTile> convertTile(const mapbox::geojsonvt::Tile& tile) {
+std::unique_ptr<GeoJSONTileData> convertTile(const mapbox::geojsonvt::Tile& tile) {
std::shared_ptr<GeoJSONTileLayer> layer;
- if (tile) {
+ if (!tile.features.empty()) {
std::vector<std::shared_ptr<const GeoJSONTileFeature>> features;
GeometryCoordinates line;
+ ToFeatureType toFeatureType;
+ ToGeometryCollection toGeometryCollection;
+
for (auto& feature : tile.features) {
- const FeatureType featureType =
- (feature.type == mapbox::geojsonvt::TileFeatureType::Point
- ? FeatureType::Point
- : (feature.type == mapbox::geojsonvt::TileFeatureType::LineString
- ? FeatureType::LineString
- : (feature.type == mapbox::geojsonvt::TileFeatureType::Polygon
- ? FeatureType::Polygon
- : FeatureType::Unknown)));
+ const FeatureType featureType = apply_visitor(toFeatureType, feature.geometry);
+
if (featureType == FeatureType::Unknown) {
continue;
}
- GeometryCollection geometry;
-
- // Flatten the geometry; GeoJSONVT distinguishes between a Points array and Rings array
- // (Points = GeoJSON types Point, MultiPoint, LineString)
- // (Rings = GeoJSON types MultiLineString, Polygon, MultiPolygon)
- // However, in Mapbox GL, we use one structure for both types, and just have one outer
- // element for Points.
- if (feature.tileGeometry.is<mapbox::geojsonvt::TilePoints>()) {
- line.clear();
- for (auto& point : feature.tileGeometry.get<mapbox::geojsonvt::TilePoints>()) {
- line.emplace_back(point.x, point.y);
- }
- geometry.emplace_back(std::move(line));
- } else if (feature.tileGeometry.is<mapbox::geojsonvt::TileRings>()) {
- for (auto& ring : feature.tileGeometry.get<mapbox::geojsonvt::TileRings>()) {
- line.clear();
- for (auto& point : ring) {
- line.emplace_back(point.x, point.y);
- }
- geometry.emplace_back(std::move(line));
- }
- }
+ GeometryCollection geometry = apply_visitor(toGeometryCollection, feature.geometry);
// https://github.com/mapbox/geojson-vt-cpp/issues/44
if (featureType == FeatureType::Polygon) {
geometry = fixupPolygons(geometry);
}
- Feature::property_map properties { feature.tags.begin(), feature.tags.end() };
+ PropertyMap properties = feature.properties;
features.emplace_back(std::make_shared<GeoJSONTileFeature>(
featureType, std::move(geometry), std::move(properties)));
@@ -103,39 +79,58 @@ std::unique_ptr<GeoJSONTile> convertTile(const mapbox::geojsonvt::Tile& tile) {
layer = std::make_unique<GeoJSONTileLayer>(std::move(features));
}
- return std::make_unique<GeoJSONTile>(layer);
+ return std::make_unique<GeoJSONTileData>(layer);
}
-GeoJSONTileMonitor::GeoJSONTileMonitor(mapbox::geojsonvt::GeoJSONVT* geojsonvt_,
- const OverscaledTileID& id)
- : tileID(id), geojsonvt(geojsonvt_) {
+GeoJSONTile::GeoJSONTile(const OverscaledTileID& overscaledTileID,
+ std::string sourceID_,
+ const style::UpdateParameters& parameters,
+ mapbox::geojsonvt::GeoJSONVT& geojsonvt)
+ : GeometryTile(overscaledTileID, sourceID_, parameters.style, parameters.mode) {
+ setData(convertTile(geojsonvt.getTile(id.canonical.z, id.canonical.x, id.canonical.y)));
}
-GeoJSONTileMonitor::~GeoJSONTileMonitor() = default;
+void GeoJSONTile::setNecessity(Necessity) {}
-// A monitor can have its GeoJSONVT object swapped out (e.g. when loading a new GeoJSON file).
-// In that case, we're sending new notifications to all observers.
-void GeoJSONTileMonitor::setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT* vt) {
- // Don't duplicate notifications in case of nil changes.
- if (geojsonvt != vt) {
- geojsonvt = vt;
- update();
- }
+GeoJSONTileFeature::GeoJSONTileFeature(FeatureType type_,
+ GeometryCollection&& geometries_,
+ PropertyMap&& properties_)
+ : type(type_), geometries(std::move(geometries_)), properties(std::move(properties_)) {
+}
+
+FeatureType GeoJSONTileFeature::getType() const {
+ return type;
}
-void GeoJSONTileMonitor::update() {
- if (geojsonvt) {
- auto tile = convertTile(
- geojsonvt->getTile(tileID.canonical.z, tileID.canonical.x, tileID.canonical.y));
- callback(nullptr, std::move(tile), {}, {});
+optional<Value> GeoJSONTileFeature::getValue(const std::string& key) const {
+ auto it = properties.find(key);
+ if (it != properties.end()) {
+ return optional<Value>(it->second);
}
+ return optional<Value>();
+}
+
+GeometryCollection GeoJSONTileFeature::getGeometries() const {
+ return geometries;
+}
+
+GeoJSONTileLayer::GeoJSONTileLayer(Features&& features_) : features(std::move(features_)) {
+}
+
+std::size_t GeoJSONTileLayer::featureCount() const {
+ return features.size();
+}
+
+util::ptr<const GeometryTileFeature> GeoJSONTileLayer::getFeature(std::size_t i) const {
+ return features[i];
}
-std::unique_ptr<AsyncRequest>
-GeoJSONTileMonitor::monitorTile(const GeometryTileMonitor::Callback& cb) {
- callback = cb;
- update();
- return nullptr;
+GeoJSONTileData::GeoJSONTileData(std::shared_ptr<GeoJSONTileLayer> layer_) : layer(std::move(layer_)) {
+}
+
+util::ptr<GeometryTileLayer> GeoJSONTileData::getLayer(const std::string&) const {
+ // We're ignoring the layer name because GeoJSON tiles only have one layer.
+ return layer;
}
} // namespace mbgl
diff --git a/src/mbgl/tile/geojson_tile.hpp b/src/mbgl/tile/geojson_tile.hpp
index 04ecbc9a24..09fdd1ec9b 100644
--- a/src/mbgl/tile/geojson_tile.hpp
+++ b/src/mbgl/tile/geojson_tile.hpp
@@ -1,9 +1,6 @@
#pragma once
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/tile/tile_id.hpp>
-
-#include <unordered_map>
namespace mapbox {
namespace geojsonvt {
@@ -13,63 +10,18 @@ class GeoJSONVT;
namespace mbgl {
-// Implements a simple in-memory Tile type that holds GeoJSON values. A GeoJSON tile can only have
-// one layer, and it is always returned regardless of which layer is requested.
-
-class GeoJSONTileFeature : public GeometryTileFeature {
-public:
- GeoJSONTileFeature(FeatureType, GeometryCollection&&, Feature::property_map&&);
- FeatureType getType() const override;
- optional<Value> getValue(const std::string&) const override;
- Feature::property_map getProperties() const override { return properties; }
- GeometryCollection getGeometries() const override;
-
-private:
- const FeatureType type;
- const GeometryCollection geometries;
- const Feature::property_map properties;
-};
-
-class GeoJSONTileLayer : public GeometryTileLayer {
-public:
- using Features = std::vector<std::shared_ptr<const GeoJSONTileFeature>>;
-
- GeoJSONTileLayer(Features&&);
- std::size_t featureCount() const override;
- util::ptr<const GeometryTileFeature> getFeature(std::size_t) const override;
- std::string getName() const override { return ""; };
-
-private:
- const Features features;
-};
+namespace style {
+class UpdateParameters;
+} // namespace style
class GeoJSONTile : public GeometryTile {
public:
- GeoJSONTile(std::shared_ptr<GeoJSONTileLayer>);
- util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
-
-private:
- const std::shared_ptr<GeoJSONTileLayer> layer;
-};
-
-class GeoJSONTileMonitor : public GeometryTileMonitor {
-public:
- GeoJSONTileMonitor(mapbox::geojsonvt::GeoJSONVT*, const OverscaledTileID&);
- virtual ~GeoJSONTileMonitor();
-
- std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileMonitor::Callback&) override;
-
- void setGeoJSONVT(mapbox::geojsonvt::GeoJSONVT*);
-
-private:
- void update();
-
-public:
- const OverscaledTileID tileID;
+ GeoJSONTile(const OverscaledTileID&,
+ std::string sourceID,
+ const style::UpdateParameters&,
+ mapbox::geojsonvt::GeoJSONVT&);
-private:
- mapbox::geojsonvt::GeoJSONVT* geojsonvt = nullptr;
- GeometryTileMonitor::Callback callback;
+ void setNecessity(Necessity) final;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 1a74880377..daa358420b 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -1,218 +1,224 @@
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/tile/tile_id.hpp>
-
-#include <clipper/clipper.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/style/layers/background_layer.hpp>
+#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/util/worker.hpp>
+#include <mbgl/util/work_request.hpp>
+#include <mbgl/style/style.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/text/collision_tile.hpp>
+#include <mbgl/map/transform_state.hpp>
namespace mbgl {
-static double signedArea(const GeometryCoordinates& ring) {
- double sum = 0;
-
- for (std::size_t i = 0, len = ring.size(), j = len - 1; i < len; j = i++) {
- const GeometryCoordinate& p1 = ring[i];
- const GeometryCoordinate& p2 = ring[j];
- sum += (p2.x - p1.x) * (p1.y + p2.y);
- }
+using namespace style;
+
+GeometryTile::GeometryTile(const OverscaledTileID& id_,
+ std::string sourceID_,
+ Style& style_,
+ const MapMode mode_)
+ : Tile(id_),
+ sourceID(std::move(sourceID_)),
+ style(style_),
+ worker(style_.workers),
+ tileWorker(id_,
+ *style_.spriteStore,
+ *style_.glyphAtlas,
+ *style_.glyphStore,
+ obsolete,
+ mode_) {
+}
- return sum;
+GeometryTile::~GeometryTile() {
+ cancel();
}
-static ClipperLib::Path toClipperPath(const GeometryCoordinates& ring) {
- ClipperLib::Path result;
- result.reserve(ring.size());
- for (const auto& p : ring) {
- result.emplace_back(p.x, p.y);
- }
- return result;
+void GeometryTile::setError(std::exception_ptr err) {
+ observer->onTileError(*this, err);
}
-static GeometryCoordinates fromClipperPath(const ClipperLib::Path& path) {
- GeometryCoordinates result;
- result.reserve(path.size() + 1);
-
- result.reserve(path.size());
- for (const auto& p : path) {
- using Coordinate = GeometryCoordinates::coordinate_type;
- assert(p.x >= std::numeric_limits<Coordinate>::min());
- assert(p.x <= std::numeric_limits<Coordinate>::max());
- assert(p.y >= std::numeric_limits<Coordinate>::min());
- assert(p.y <= std::numeric_limits<Coordinate>::max());
- result.emplace_back(Coordinate(p.x), Coordinate(p.y));
- }
-
- // Clipper does not repeat initial point, but our geometry model requires it.
- if (!result.empty()) {
- result.push_back(result.front());
+std::vector<std::unique_ptr<Layer>> GeometryTile::cloneStyleLayers() const {
+ std::vector<std::unique_ptr<Layer>> result;
+
+ for (const Layer* layer : style.getLayers()) {
+ // Avoid cloning and including irrelevant layers.
+ if (layer->is<BackgroundLayer>() ||
+ layer->is<CustomLayer>() ||
+ layer->baseImpl->source != sourceID ||
+ id.overscaledZ < std::floor(layer->baseImpl->minZoom) ||
+ id.overscaledZ >= std::ceil(layer->baseImpl->maxZoom) ||
+ layer->baseImpl->visibility == VisibilityType::None) {
+ continue;
+ }
+
+ result.push_back(layer->baseImpl->clone());
}
-
+
return result;
}
-static void processPolynodeBranch(ClipperLib::PolyNode* polynode, GeometryCollection& rings) {
- // Exterior ring.
- rings.push_back(fromClipperPath(polynode->Contour));
- assert(signedArea(rings.back()) > 0);
-
- // Interior rings.
- for (auto * ring : polynode->Childs) {
- rings.push_back(fromClipperPath(ring->Contour));
- assert(signedArea(rings.back()) < 0);
+void GeometryTile::setData(std::unique_ptr<GeometryTileData> data_) {
+ if (!data_) {
+ // This is a 404 response. We're treating these as empty tiles.
+ workRequest.reset();
+ availableData = DataAvailability::All;
+ buckets.clear();
+ redoPlacement();
+ observer->onTileLoaded(*this, true);
+ return;
}
- // PolyNodes may be nested in the case of a polygon inside a hole.
- for (auto * ring : polynode->Childs) {
- for (auto * subRing : ring->Childs) {
- processPolynodeBranch(subRing, rings);
- }
+ // Mark the tile as pending again if it was complete before to prevent signaling a complete
+ // state despite pending parse operations.
+ if (availableData == DataAvailability::All) {
+ availableData = DataAvailability::Some;
}
-}
-GeometryCollection fixupPolygons(const GeometryCollection& rings) {
- ClipperLib::Clipper clipper;
- clipper.StrictlySimple(true);
+ // Kick off a fresh parse of this tile. This happens when the tile is new, or
+ // when tile data changed. Replacing the workdRequest will cancel a pending work
+ // request in case there is one.
+ workRequest.reset();
+ workRequest = worker.parseGeometryTile(tileWorker, cloneStyleLayers(), std::move(data_), targetConfig, [this, config = targetConfig] (TileParseResult result) {
+ workRequest.reset();
- for (const auto& ring : rings) {
- clipper.AddPath(toClipperPath(ring), ClipperLib::ptSubject, true);
- }
+ if (result.is<TileParseResultData>()) {
+ auto& resultBuckets = result.get<TileParseResultData>();
+ availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
- ClipperLib::PolyTree polygons;
- clipper.Execute(ClipperLib::ctUnion, polygons, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
- clipper.Clear();
+ // Persist the configuration we just placed so that we can later check whether we need to
+ // place again in case the configuration has changed.
+ placedConfig = config;
- GeometryCollection result;
- for (auto * polynode : polygons.Childs) {
- processPolynodeBranch(polynode, result);
- }
- return result;
-}
+ // Move over all buckets we received in this parse request, potentially overwriting
+ // existing buckets in case we got a refresh parse.
+ buckets = std::move(resultBuckets.buckets);
-std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
- std::vector<GeometryCollection> polygons;
+ if (isComplete()) {
+ featureIndex = std::move(resultBuckets.featureIndex);
+ data = std::move(resultBuckets.tileData);
+ }
- std::size_t len = rings.size();
+ redoPlacement();
+ observer->onTileLoaded(*this, true);
+ } else {
+ availableData = DataAvailability::All;
+ observer->onTileError(*this, result.get<std::exception_ptr>());
+ }
+ });
+}
- if (len <= 1) {
- polygons.push_back(rings);
- return polygons;
+bool GeometryTile::parsePending() {
+ if (workRequest) {
+ // There's already parsing or placement going on.
+ return false;
}
- GeometryCollection polygon;
- int8_t ccw = 0;
+ workRequest.reset();
+ workRequest = worker.parsePendingGeometryTileLayers(tileWorker, targetConfig, [this, config = targetConfig] (TileParseResult result) {
+ workRequest.reset();
- for (std::size_t i = 0; i < len; i++) {
- double area = signedArea(rings[i]);
+ if (result.is<TileParseResultData>()) {
+ auto& resultBuckets = result.get<TileParseResultData>();
+ availableData = resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
- if (area == 0)
- continue;
+ // Move over all buckets we received in this parse request, potentially overwriting
+ // existing buckets in case we got a refresh parse.
+ for (auto& bucket : resultBuckets.buckets) {
+ buckets[bucket.first] = std::move(bucket.second);
+ }
- if (ccw == 0)
- ccw = (area < 0 ? -1 : 1);
+ // Persist the configuration we just placed so that we can later check whether we need to
+ // place again in case the configuration has changed.
+ placedConfig = config;
+
+ if (isComplete()) {
+ featureIndex = std::move(resultBuckets.featureIndex);
+ data = std::move(resultBuckets.tileData);
+ }
- if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) {
- polygons.push_back(polygon);
- polygon.clear();
+ redoPlacement();
+ observer->onTileLoaded(*this, false);
+ } else {
+ availableData = DataAvailability::All;
+ observer->onTileError(*this, result.get<std::exception_ptr>());
}
+ });
- polygon.push_back(rings[i]);
+ return true;
+}
+
+Bucket* GeometryTile::getBucket(const Layer& layer) {
+ const auto it = buckets.find(layer.baseImpl->bucketName());
+ if (it == buckets.end()) {
+ return nullptr;
}
- if (!polygon.empty())
- polygons.push_back(polygon);
+ assert(it->second);
+ return it->second.get();
+}
- return polygons;
+void GeometryTile::redoPlacement(const PlacementConfig newConfig) {
+ targetConfig = newConfig;
+ redoPlacement();
}
-void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
- if (polygon.size() > 1 + maxHoles) {
- std::nth_element(polygon.begin() + 1,
- polygon.begin() + 1 + maxHoles,
- polygon.end(),
- [] (const auto& a, const auto& b) {
- return signedArea(a) > signedArea(b);
- });
- polygon.resize(1 + maxHoles);
+void GeometryTile::redoPlacement() {
+ // Don't start a new placement request when the current one hasn't completed yet, or when
+ // we are parsing buckets.
+ if (workRequest || targetConfig == placedConfig) {
+ return;
}
-}
-static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
- const double size = util::EXTENT * std::pow(2, tileID.z);
- const double x0 = util::EXTENT * tileID.x;
- const double y0 = util::EXTENT * tileID.y;
-
- auto tileCoordinatesToLatLng = [&] (const Point<int16_t>& p) {
- double y2 = 180 - (p.y + y0) * 360 / size;
- return Point<double>(
- (p.x + x0) * 360 / size - 180,
- 360.0 / M_PI * std::atan(std::exp(y2 * M_PI / 180)) - 90.0
- );
- };
-
- GeometryCollection geometries = geometryTileFeature.getGeometries();
-
- switch (geometryTileFeature.getType()) {
- case FeatureType::Unknown: {
- assert(false);
- return Point<double>(NAN, NAN);
- }
+ workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, config = targetConfig](std::unique_ptr<CollisionTile> collisionTile) {
+ workRequest.reset();
- case FeatureType::Point: {
- MultiPoint<double> multiPoint;
- for (const auto& p : geometries.at(0)) {
- multiPoint.push_back(tileCoordinatesToLatLng(p));
- }
- if (multiPoint.size() == 1) {
- return multiPoint[0];
- } else {
- return multiPoint;
- }
+ // Persist the configuration we just placed so that we can later check whether we need to
+ // place again in case the configuration has changed.
+ placedConfig = config;
+
+ for (auto& bucket : buckets) {
+ bucket.second->swapRenderData();
}
- case FeatureType::LineString: {
- MultiLineString<double> multiLineString;
- for (const auto& g : geometries) {
- LineString<double> lineString;
- for (const auto& p : g) {
- lineString.push_back(tileCoordinatesToLatLng(p));
- }
- multiLineString.push_back(std::move(lineString));
- }
- if (multiLineString.size() == 1) {
- return multiLineString[0];
- } else {
- return multiLineString;
- }
+ if (featureIndex) {
+ featureIndex->setCollisionTile(std::move(collisionTile));
}
- case FeatureType::Polygon: {
- MultiPolygon<double> multiPolygon;
- for (const auto& pg : classifyRings(geometries)) {
- Polygon<double> polygon;
- for (const auto& r : pg) {
- LinearRing<double> linearRing;
- for (const auto& p : r) {
- linearRing.push_back(tileCoordinatesToLatLng(p));
- }
- polygon.push_back(std::move(linearRing));
- }
- multiPolygon.push_back(std::move(polygon));
- }
- if (multiPolygon.size() == 1) {
- return multiPolygon[0];
- } else {
- return multiPolygon;
- }
+ // The target configuration could have changed since we started placement. In this case,
+ // we're starting another placement run.
+ if (placedConfig != targetConfig) {
+ redoPlacement();
+ } else {
+ observer->onNeedsRepaint();
}
- }
+ });
+}
- // Unreachable, but placate GCC.
- return Point<double>();
+void GeometryTile::queryRenderedFeatures(
+ std::unordered_map<std::string, std::vector<Feature>>& result,
+ const GeometryCoordinates& queryGeometry,
+ const TransformState& transformState,
+ const optional<std::vector<std::string>>& layerIDs) {
+
+ if (!featureIndex || !data) return;
+
+ featureIndex->query(result,
+ { queryGeometry },
+ transformState.getAngle(),
+ util::tileSize * id.overscaleFactor(),
+ std::pow(2, transformState.getZoom() - id.overscaledZ),
+ layerIDs,
+ *data,
+ id.canonical,
+ style);
}
-Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
- Feature feature { convertGeometry(geometryTileFeature, tileID) };
- feature.properties = geometryTileFeature.getProperties();
- feature.id = geometryTileFeature.getID();
- return feature;
+void GeometryTile::cancel() {
+ obsolete = true;
+ workRequest.reset();
}
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index 6904c922ba..6072e2b1da 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -1,104 +1,79 @@
#pragma once
-#include <mbgl/util/geometry.hpp>
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/tile_worker.hpp>
+#include <mbgl/text/placement_config.hpp>
+#include <mbgl/util/atomic.hpp>
#include <mbgl/util/feature.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/ptr.hpp>
-#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/optional.hpp>
-#include <mbgl/util/variant.hpp>
-#include <mbgl/util/constants.hpp>
-
-#include <cstdint>
-#include <string>
-#include <vector>
+
+#include <memory>
#include <unordered_map>
-#include <functional>
+#include <vector>
namespace mbgl {
-enum class FeatureType : uint8_t {
- Unknown = 0,
- Point = 1,
- LineString = 2,
- Polygon = 3
-};
-
-class CanonicalTileID;
+class AsyncRequest;
+class GeometryTileData;
+class FeatureIndex;
-// Normalized vector tile coordinates.
-// Each geometry coordinate represents a point in a bidimensional space,
-// varying from -V...0...+V, where V is the maximum extent applicable.
-using GeometryCoordinate = Point<int16_t>;
+namespace style {
+class Style;
+class Layer;
+} // namespace style
-class GeometryCoordinates : public std::vector<GeometryCoordinate> {
+class GeometryTile : public Tile {
public:
- using coordinate_type = int16_t;
- using std::vector<GeometryCoordinate>::vector;
-};
+ GeometryTile(const OverscaledTileID&,
+ std::string sourceID,
+ style::Style&,
+ const MapMode);
-class GeometryCollection : public std::vector<GeometryCoordinates> {
-public:
- using coordinate_type = int16_t;
- using std::vector<GeometryCoordinates>::vector;
-};
+ ~GeometryTile() override;
-class GeometryTileFeature : private util::noncopyable {
-public:
- virtual ~GeometryTileFeature() = default;
- virtual FeatureType getType() const = 0;
- virtual optional<Value> getValue(const std::string& key) const = 0;
- virtual Feature::property_map getProperties() const { return Feature::property_map(); }
- virtual optional<uint64_t> getID() const { return {}; }
- virtual GeometryCollection getGeometries() const = 0;
-};
+ void setError(std::exception_ptr err);
+ void setData(std::unique_ptr<GeometryTileData>);
-class GeometryTileLayer : private util::noncopyable {
-public:
- virtual ~GeometryTileLayer() = default;
- virtual std::size_t featureCount() const = 0;
- virtual util::ptr<const GeometryTileFeature> getFeature(std::size_t) const = 0;
- virtual std::string getName() const = 0;
-};
+ Bucket* getBucket(const style::Layer&) override;
-class GeometryTile : private util::noncopyable {
-public:
- virtual ~GeometryTile() = default;
- virtual util::ptr<GeometryTileLayer> getLayer(const std::string&) const = 0;
-};
+ bool parsePending() override;
-class AsyncRequest;
+ void redoPlacement(PlacementConfig) override;
-class GeometryTileMonitor : private util::noncopyable {
-public:
- virtual ~GeometryTileMonitor() = default;
-
- using Callback = std::function<void (std::exception_ptr,
- std::unique_ptr<GeometryTile>,
- optional<Timestamp> modified,
- optional<Timestamp> expires)>;
- /*
- * Monitor the tile held by this object for changes. When the tile is loaded for the first time,
- * or updates, the callback is executed. If an error occurs, the first parameter will be set.
- * Otherwise it will be null. If there is no data for the requested tile, the second parameter
- * will be null.
- *
- * To cease monitoring, release the returned Request.
- */
- virtual std::unique_ptr<AsyncRequest> monitorTile(const Callback&) = 0;
-};
+ void queryRenderedFeatures(
+ std::unordered_map<std::string, std::vector<Feature>>& result,
+ const GeometryCoordinates& queryGeometry,
+ const TransformState&,
+ const optional<std::vector<std::string>>& layerIDs) override;
-// classifies an array of rings into polygons with outer rings and holes
-std::vector<GeometryCollection> classifyRings(const GeometryCollection&);
+ void cancel() override;
-// Truncate polygon to the largest `maxHoles` inner rings by area.
-void limitHoles(GeometryCollection&, uint32_t maxHoles);
+private:
+ std::vector<std::unique_ptr<style::Layer>> cloneStyleLayers() const;
+ void redoPlacement();
-// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature)
-Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
+ const std::string sourceID;
+ style::Style& style;
+ Worker& worker;
+ TileWorker tileWorker;
-// Fix up possibly-non-V2-compliant polygon geometry using angus clipper.
-// The result is guaranteed to have correctly wound, strictly simple rings.
-GeometryCollection fixupPolygons(const GeometryCollection&);
+ std::unique_ptr<AsyncRequest> workRequest;
+
+ // Contains all the Bucket objects for the tile. Buckets are render
+ // objects and they get added by tile parsing operations.
+ std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
+
+ std::unique_ptr<FeatureIndex> featureIndex;
+ std::unique_ptr<const GeometryTileData> data;
+
+ // Stores the placement configuration of the text that is currently placed on the screen.
+ PlacementConfig placedConfig;
+
+ // Stores the placement configuration of how the text should be placed. This isn't necessarily
+ // the one that is being displayed.
+ PlacementConfig targetConfig;
+
+ // Used to signal the worker that it should abandon parsing this tile as soon as possible.
+ util::Atomic<bool> obsolete { false };
+};
} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile_data.cpp b/src/mbgl/tile/geometry_tile_data.cpp
new file mode 100644
index 0000000000..2e465a6f65
--- /dev/null
+++ b/src/mbgl/tile/geometry_tile_data.cpp
@@ -0,0 +1,217 @@
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/tile/tile_id.hpp>
+
+#include <clipper/clipper.hpp>
+
+namespace mbgl {
+
+static double signedArea(const GeometryCoordinates& ring) {
+ double sum = 0;
+
+ for (std::size_t i = 0, len = ring.size(), j = len - 1; i < len; j = i++) {
+ const GeometryCoordinate& p1 = ring[i];
+ const GeometryCoordinate& p2 = ring[j];
+ sum += (p2.x - p1.x) * (p1.y + p2.y);
+ }
+
+ return sum;
+}
+
+static ClipperLib::Path toClipperPath(const GeometryCoordinates& ring) {
+ ClipperLib::Path result;
+ result.reserve(ring.size());
+ for (const auto& p : ring) {
+ result.emplace_back(p.x, p.y);
+ }
+ return result;
+}
+
+static GeometryCoordinates fromClipperPath(const ClipperLib::Path& path) {
+ GeometryCoordinates result;
+ result.reserve(path.size() + 1);
+
+ for (const auto& p : path) {
+ using Coordinate = GeometryCoordinates::coordinate_type;
+ assert(p.x >= std::numeric_limits<Coordinate>::min());
+ assert(p.x <= std::numeric_limits<Coordinate>::max());
+ assert(p.y >= std::numeric_limits<Coordinate>::min());
+ assert(p.y <= std::numeric_limits<Coordinate>::max());
+ result.emplace_back(Coordinate(p.x), Coordinate(p.y));
+ }
+
+ // Clipper does not repeat initial point, but our geometry model requires it.
+ if (!result.empty()) {
+ result.push_back(result.front());
+ }
+
+ return result;
+}
+
+static void processPolynodeBranch(ClipperLib::PolyNode* polynode, GeometryCollection& rings) {
+ // Exterior ring.
+ rings.push_back(fromClipperPath(polynode->Contour));
+ assert(signedArea(rings.back()) > 0);
+
+ // Interior rings.
+ for (auto * ring : polynode->Childs) {
+ rings.push_back(fromClipperPath(ring->Contour));
+ assert(signedArea(rings.back()) < 0);
+ }
+
+ // PolyNodes may be nested in the case of a polygon inside a hole.
+ for (auto * ring : polynode->Childs) {
+ for (auto * subRing : ring->Childs) {
+ processPolynodeBranch(subRing, rings);
+ }
+ }
+}
+
+GeometryCollection fixupPolygons(const GeometryCollection& rings) {
+ ClipperLib::Clipper clipper;
+ clipper.StrictlySimple(true);
+
+ for (const auto& ring : rings) {
+ clipper.AddPath(toClipperPath(ring), ClipperLib::ptSubject, true);
+ }
+
+ ClipperLib::PolyTree polygons;
+ clipper.Execute(ClipperLib::ctUnion, polygons, ClipperLib::pftEvenOdd, ClipperLib::pftEvenOdd);
+ clipper.Clear();
+
+ GeometryCollection result;
+ for (auto * polynode : polygons.Childs) {
+ processPolynodeBranch(polynode, result);
+ }
+ return result;
+}
+
+std::vector<GeometryCollection> classifyRings(const GeometryCollection& rings) {
+ std::vector<GeometryCollection> polygons;
+
+ std::size_t len = rings.size();
+
+ if (len <= 1) {
+ polygons.push_back(rings);
+ return polygons;
+ }
+
+ GeometryCollection polygon;
+ int8_t ccw = 0;
+
+ for (std::size_t i = 0; i < len; i++) {
+ double area = signedArea(rings[i]);
+
+ if (area == 0)
+ continue;
+
+ if (ccw == 0)
+ ccw = (area < 0 ? -1 : 1);
+
+ if (ccw == (area < 0 ? -1 : 1) && !polygon.empty()) {
+ polygons.push_back(polygon);
+ polygon.clear();
+ }
+
+ polygon.push_back(rings[i]);
+ }
+
+ if (!polygon.empty())
+ polygons.push_back(polygon);
+
+ return polygons;
+}
+
+void limitHoles(GeometryCollection& polygon, uint32_t maxHoles) {
+ if (polygon.size() > 1 + maxHoles) {
+ std::nth_element(polygon.begin() + 1,
+ polygon.begin() + 1 + maxHoles,
+ polygon.end(),
+ [] (const auto& a, const auto& b) {
+ return signedArea(a) > signedArea(b);
+ });
+ polygon.resize(1 + maxHoles);
+ }
+}
+
+static Feature::geometry_type convertGeometry(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
+ const double size = util::EXTENT * std::pow(2, tileID.z);
+ const double x0 = util::EXTENT * tileID.x;
+ const double y0 = util::EXTENT * tileID.y;
+
+ auto tileCoordinatesToLatLng = [&] (const Point<int16_t>& p) {
+ double y2 = 180 - (p.y + y0) * 360 / size;
+ return Point<double>(
+ (p.x + x0) * 360 / size - 180,
+ 360.0 / M_PI * std::atan(std::exp(y2 * M_PI / 180)) - 90.0
+ );
+ };
+
+ GeometryCollection geometries = geometryTileFeature.getGeometries();
+
+ switch (geometryTileFeature.getType()) {
+ case FeatureType::Unknown: {
+ assert(false);
+ return Point<double>(NAN, NAN);
+ }
+
+ case FeatureType::Point: {
+ MultiPoint<double> multiPoint;
+ for (const auto& p : geometries.at(0)) {
+ multiPoint.push_back(tileCoordinatesToLatLng(p));
+ }
+ if (multiPoint.size() == 1) {
+ return multiPoint[0];
+ } else {
+ return multiPoint;
+ }
+ }
+
+ case FeatureType::LineString: {
+ MultiLineString<double> multiLineString;
+ for (const auto& g : geometries) {
+ LineString<double> lineString;
+ for (const auto& p : g) {
+ lineString.push_back(tileCoordinatesToLatLng(p));
+ }
+ multiLineString.push_back(std::move(lineString));
+ }
+ if (multiLineString.size() == 1) {
+ return multiLineString[0];
+ } else {
+ return multiLineString;
+ }
+ }
+
+ case FeatureType::Polygon: {
+ MultiPolygon<double> multiPolygon;
+ for (const auto& pg : classifyRings(geometries)) {
+ Polygon<double> polygon;
+ for (const auto& r : pg) {
+ LinearRing<double> linearRing;
+ for (const auto& p : r) {
+ linearRing.push_back(tileCoordinatesToLatLng(p));
+ }
+ polygon.push_back(std::move(linearRing));
+ }
+ multiPolygon.push_back(std::move(polygon));
+ }
+ if (multiPolygon.size() == 1) {
+ return multiPolygon[0];
+ } else {
+ return multiPolygon;
+ }
+ }
+ }
+
+ // Unreachable, but placate GCC.
+ return Point<double>();
+}
+
+Feature convertFeature(const GeometryTileFeature& geometryTileFeature, const CanonicalTileID& tileID) {
+ Feature feature { convertGeometry(geometryTileFeature, tileID) };
+ feature.properties = geometryTileFeature.getProperties();
+ feature.id = geometryTileFeature.getID();
+ return feature;
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/geometry_tile_data.hpp b/src/mbgl/tile/geometry_tile_data.hpp
new file mode 100644
index 0000000000..4055a80ecf
--- /dev/null
+++ b/src/mbgl/tile/geometry_tile_data.hpp
@@ -0,0 +1,143 @@
+#pragma once
+
+#include <mbgl/util/geometry.hpp>
+#include <mbgl/util/feature.hpp>
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/ptr.hpp>
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/variant.hpp>
+#include <mbgl/util/constants.hpp>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <functional>
+#include <iostream>
+
+namespace mbgl {
+
+class CanonicalTileID;
+
+// Normalized vector tile coordinates.
+// Each geometry coordinate represents a point in a bidimensional space,
+// varying from -V...0...+V, where V is the maximum extent applicable.
+using GeometryCoordinate = Point<int16_t>;
+
+class GeometryCoordinates : public std::vector<GeometryCoordinate> {
+public:
+ using coordinate_type = int16_t;
+ using std::vector<GeometryCoordinate>::vector;
+};
+
+class GeometryCollection : public std::vector<GeometryCoordinates> {
+public:
+ using coordinate_type = int16_t;
+ using std::vector<GeometryCoordinates>::vector;
+};
+
+class GeometryTileFeature : private util::noncopyable {
+public:
+ virtual ~GeometryTileFeature() = default;
+ virtual FeatureType getType() const = 0;
+ virtual optional<Value> getValue(const std::string& key) const = 0;
+ virtual PropertyMap getProperties() const { return PropertyMap(); }
+ virtual optional<FeatureIdentifier> getID() const { return {}; }
+ virtual GeometryCollection getGeometries() const = 0;
+};
+
+class GeometryTileLayer : private util::noncopyable {
+public:
+ virtual ~GeometryTileLayer() = default;
+ virtual std::size_t featureCount() const = 0;
+ virtual util::ptr<const GeometryTileFeature> getFeature(std::size_t) const = 0;
+ virtual std::string getName() const = 0;
+};
+
+class GeometryTileData : private util::noncopyable {
+public:
+ virtual ~GeometryTileData() = default;
+ virtual util::ptr<GeometryTileLayer> getLayer(const std::string&) const = 0;
+};
+
+// classifies an array of rings into polygons with outer rings and holes
+std::vector<GeometryCollection> classifyRings(const GeometryCollection&);
+
+// Truncate polygon to the largest `maxHoles` inner rings by area.
+void limitHoles(GeometryCollection&, uint32_t maxHoles);
+
+// convert from GeometryTileFeature to Feature (eventually we should eliminate GeometryTileFeature)
+Feature convertFeature(const GeometryTileFeature&, const CanonicalTileID&);
+
+// Fix up possibly-non-V2-compliant polygon geometry using angus clipper.
+// The result is guaranteed to have correctly wound, strictly simple rings.
+GeometryCollection fixupPolygons(const GeometryCollection&);
+
+struct ToGeometryCollection {
+ GeometryCollection operator()(const mapbox::geometry::point<int16_t>& geom) const {
+ return { { geom } };
+ }
+ GeometryCollection operator()(const mapbox::geometry::multi_point<int16_t>& geom) const {
+ GeometryCoordinates coordinates;
+ coordinates.reserve(geom.size());
+ for (const auto& point : geom) {
+ coordinates.emplace_back(point);
+ }
+ return { coordinates };
+ }
+ GeometryCollection operator()(const mapbox::geometry::line_string<int16_t>& geom) const {
+ GeometryCoordinates coordinates;
+ coordinates.reserve(geom.size());
+ for (const auto& point : geom) {
+ coordinates.emplace_back(point);
+ }
+ return { coordinates };
+ }
+ GeometryCollection operator()(const mapbox::geometry::multi_line_string<int16_t>& geom) const {
+ GeometryCollection collection;
+ collection.reserve(geom.size());
+ for (const auto& ring : geom) {
+ GeometryCoordinates coordinates;
+ coordinates.reserve(ring.size());
+ for (const auto& point : ring) {
+ coordinates.emplace_back(point);
+ }
+ collection.push_back(std::move(coordinates));
+ }
+ return collection;
+ }
+ GeometryCollection operator()(const mapbox::geometry::polygon<int16_t>& geom) const {
+ GeometryCollection collection;
+ collection.reserve(geom.size());
+ for (const auto& ring : geom) {
+ GeometryCoordinates coordinates;
+ coordinates.reserve(ring.size());
+ for (const auto& point : ring) {
+ coordinates.emplace_back(point);
+ }
+ collection.push_back(std::move(coordinates));
+ }
+ return collection;
+ }
+ GeometryCollection operator()(const mapbox::geometry::multi_polygon<int16_t>& geom) const {
+ GeometryCollection collection;
+ for (auto& polygon : geom) {
+ for (auto& ring : polygon) {
+ GeometryCoordinates coordinates;
+ coordinates.reserve(ring.size());
+ for (auto& point : ring) {
+ coordinates.emplace_back(point);
+ }
+ collection.push_back(std::move(coordinates));
+ }
+ }
+ return collection;
+ }
+ GeometryCollection operator()(const mapbox::geometry::geometry_collection<int16_t>&) const {
+ GeometryCollection collection;
+ return collection;
+ }
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp
new file mode 100644
index 0000000000..2460aac8f9
--- /dev/null
+++ b/src/mbgl/tile/raster_tile.cpp
@@ -0,0 +1,71 @@
+#include <mbgl/tile/raster_tile.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/tile/tile_loader_impl.hpp>
+#include <mbgl/style/source.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/storage/resource.hpp>
+#include <mbgl/storage/response.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/util/worker.hpp>
+#include <mbgl/util/work_request.hpp>
+
+namespace mbgl {
+
+RasterTile::RasterTile(const OverscaledTileID& id_,
+ const style::UpdateParameters& parameters,
+ const Tileset& tileset)
+ : Tile(id_),
+ worker(parameters.worker),
+ loader(*this, id_, parameters, tileset) {
+}
+
+RasterTile::~RasterTile() = default;
+
+void RasterTile::setError(std::exception_ptr err) {
+ observer->onTileError(*this, err);
+}
+
+void RasterTile::setData(std::shared_ptr<const std::string> data,
+ optional<Timestamp> modified_,
+ optional<Timestamp> expires_) {
+ modified = modified_;
+ expires = expires_;
+
+ if (!data) {
+ // This is a 404 response. We're treating these as empty tiles.
+ workRequest.reset();
+ availableData = DataAvailability::All;
+ bucket.reset();
+ observer->onTileLoaded(*this, true);
+ return;
+ }
+
+ workRequest.reset();
+ workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(), data, [this] (RasterTileParseResult result) {
+ workRequest.reset();
+
+ availableData = DataAvailability::All;
+
+ if (result.is<std::unique_ptr<Bucket>>()) {
+ bucket = std::move(result.get<std::unique_ptr<Bucket>>());
+ observer->onTileLoaded(*this, true);
+ } else {
+ bucket.reset();
+ observer->onTileError(*this, result.get<std::exception_ptr>());
+ }
+ });
+}
+
+Bucket* RasterTile::getBucket(const style::Layer&) {
+ return bucket.get();
+}
+
+void RasterTile::setNecessity(Necessity necessity) {
+ loader.setNecessity(necessity);
+}
+
+void RasterTile::cancel() {
+ workRequest.reset();
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile.hpp b/src/mbgl/tile/raster_tile.hpp
new file mode 100644
index 0000000000..496edda6b3
--- /dev/null
+++ b/src/mbgl/tile/raster_tile.hpp
@@ -0,0 +1,46 @@
+#pragma once
+
+#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/tile_loader.hpp>
+#include <mbgl/renderer/raster_bucket.hpp>
+
+namespace mbgl {
+
+class AsyncRequest;
+class Tileset;
+
+namespace style {
+class Layer;
+class UpdateParameters;
+} // namespace style
+
+class RasterTile : public Tile {
+public:
+ RasterTile(const OverscaledTileID&,
+ const style::UpdateParameters&,
+ const Tileset&);
+ ~RasterTile() final;
+
+ void setNecessity(Necessity) final;
+
+ void setError(std::exception_ptr err);
+
+ void setData(std::shared_ptr<const std::string> data,
+ optional<Timestamp> modified_,
+ optional<Timestamp> expires_);
+
+ void cancel() override;
+ Bucket* getBucket(const style::Layer&) override;
+
+private:
+ Worker& worker;
+
+ TileLoader<RasterTile> loader;
+ std::unique_ptr<AsyncRequest> workRequest;
+
+ // Contains the Bucket object for the tile. Buckets are render
+ // objects and they get added by tile parsing operations.
+ std::unique_ptr<Bucket> bucket;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/raster_tile_data.cpp b/src/mbgl/tile/raster_tile_data.cpp
deleted file mode 100644
index 420cb7055e..0000000000
--- a/src/mbgl/tile/raster_tile_data.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <mbgl/tile/raster_tile_data.hpp>
-#include <mbgl/style/source.hpp>
-#include <mbgl/storage/resource.hpp>
-#include <mbgl/storage/response.hpp>
-#include <mbgl/storage/file_source.hpp>
-#include <mbgl/util/worker.hpp>
-#include <mbgl/util/work_request.hpp>
-
-using namespace mbgl;
-
-RasterTileData::RasterTileData(const OverscaledTileID& id_,
- float pixelRatio,
- const std::string& urlTemplate,
- gl::TexturePool &texturePool_,
- Worker& worker_,
- FileSource& fileSource,
- const std::function<void(std::exception_ptr)>& callback)
- : TileData(id_),
- texturePool(texturePool_),
- worker(worker_) {
- const Resource resource =
- Resource::tile(urlTemplate, pixelRatio, id.canonical.x, id.canonical.y, id.canonical.z);
- req = fileSource.request(resource, [callback, this](Response res) {
- if (res.error) {
- callback(std::make_exception_ptr(std::runtime_error(res.error->message)));
- } else if (res.notModified) {
- modified = res.modified;
- expires = res.expires;
- } else if (res.noContent) {
- availableData = DataAvailability::All;
- modified = res.modified;
- expires = res.expires;
- workRequest.reset();
- bucket.reset();
- callback(nullptr);
- } else {
- modified = res.modified;
- expires = res.expires;
-
- workRequest.reset();
- workRequest = worker.parseRasterTile(std::make_unique<RasterBucket>(texturePool), res.data, [this, callback] (RasterTileParseResult result) {
- workRequest.reset();
-
- std::exception_ptr error;
- if (result.is<std::unique_ptr<Bucket>>()) {
- bucket = std::move(result.get<std::unique_ptr<Bucket>>());
- } else {
- error = result.get<std::exception_ptr>();
- bucket.reset();
- }
-
- availableData = DataAvailability::All;
-
- callback(error);
- });
- }
- });
-}
-
-RasterTileData::~RasterTileData() {
- cancel();
-}
-
-Bucket* RasterTileData::getBucket(const style::Layer&) {
- return bucket.get();
-}
-
-void RasterTileData::cancel() {
- req = nullptr;
- workRequest.reset();
-}
diff --git a/src/mbgl/tile/raster_tile_data.hpp b/src/mbgl/tile/raster_tile_data.hpp
deleted file mode 100644
index 62d21d28c4..0000000000
--- a/src/mbgl/tile/raster_tile_data.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-#include <mbgl/tile/tile_data.hpp>
-#include <mbgl/renderer/raster_bucket.hpp>
-
-namespace mbgl {
-
-class FileSource;
-class AsyncRequest;
-
-namespace gl { class TexturePool; }
-
-namespace style {
-class Layer;
-}
-
-class RasterTileData : public TileData {
-public:
- RasterTileData(const OverscaledTileID&,
- float pixelRatio,
- const std::string& urlTemplate,
- gl::TexturePool&,
- Worker&,
- FileSource&,
- const std::function<void(std::exception_ptr)>& callback);
- ~RasterTileData();
-
- void cancel() override;
- Bucket* getBucket(const style::Layer&) override;
-
-private:
- gl::TexturePool& texturePool;
- Worker& worker;
- std::unique_ptr<AsyncRequest> req;
- std::unique_ptr<Bucket> bucket;
- std::unique_ptr<AsyncRequest> workRequest;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp
index a1d36421a4..6595c314ee 100644
--- a/src/mbgl/tile/tile.cpp
+++ b/src/mbgl/tile/tile.cpp
@@ -1,3 +1,36 @@
#include <mbgl/tile/tile.hpp>
+#include <mbgl/tile/tile_observer.hpp>
+#include <mbgl/renderer/debug_bucket.hpp>
+#include <mbgl/util/string.hpp>
-using namespace mbgl;
+namespace mbgl {
+
+static TileObserver nullObserver;
+
+Tile::Tile(OverscaledTileID id_) : id(std::move(id_)), observer(&nullObserver) {
+}
+
+Tile::~Tile() = default;
+
+void Tile::setObserver(TileObserver* observer_) {
+ observer = observer_;
+}
+
+void Tile::setTriedOptional() {
+ triedOptional = true;
+ observer->onNeedsRepaint();
+}
+
+void Tile::dumpDebugLogs() const {
+ Log::Info(Event::General, "Tile::id: %s", util::toString(id).c_str());
+ Log::Info(Event::General, "Tile::renderable: %s", isRenderable() ? "yes" : "no");
+ Log::Info(Event::General, "Tile::complete: %s", isComplete() ? "yes" : "no");
+}
+
+void Tile::queryRenderedFeatures(
+ std::unordered_map<std::string, std::vector<Feature>>&,
+ const GeometryCoordinates&,
+ const TransformState&,
+ const optional<std::vector<std::string>>&) {}
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/tile.hpp b/src/mbgl/tile/tile.hpp
index 1e35e78735..65f3aaa245 100644
--- a/src/mbgl/tile/tile.hpp
+++ b/src/mbgl/tile/tile.hpp
@@ -1,28 +1,111 @@
#pragma once
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/util/chrono.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/feature.hpp>
#include <mbgl/tile/tile_id.hpp>
-#include <mbgl/util/mat4.hpp>
-#include <mbgl/util/ptr.hpp>
-#include <mbgl/util/clip_id.hpp>
+#include <mbgl/renderer/bucket.hpp>
+#include <mbgl/text/placement_config.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/storage/resource.hpp>
+
+#include <string>
+#include <memory>
+#include <functional>
+#include <unordered_map>
namespace mbgl {
-class TileData;
+class Worker;
+class DebugBucket;
+class TransformState;
+class TileObserver;
+
+namespace style {
+class Layer;
+} // namespace style
-class Tile {
+class Tile : private util::noncopyable {
public:
- Tile(const UnwrappedTileID& id_, TileData& data_) : id(id_), data(data_) {
+ Tile(OverscaledTileID);
+ virtual ~Tile();
+
+ void setObserver(TileObserver* observer);
+
+ // Tiles can have two states: optional or required.
+ // - optional means that only low-cost actions should be taken to obtain the data
+ // (e.g. load from cache, but accept stale data)
+ // - required means that every effort should be taken to obtain the data (e.g. load
+ // from internet and keep the data fresh if it expires)
+ using Necessity = Resource::Necessity;
+
+ virtual void setNecessity(Necessity) = 0;
+
+ // Mark this tile as no longer needed and cancel any pending work.
+ virtual void cancel() = 0;
+
+ virtual Bucket* getBucket(const style::Layer&) = 0;
+
+ virtual bool parsePending() { return true; }
+ virtual void redoPlacement(PlacementConfig) {}
+
+ virtual void queryRenderedFeatures(
+ std::unordered_map<std::string, std::vector<Feature>>& result,
+ const GeometryCoordinates& queryGeometry,
+ const TransformState&,
+ const optional<std::vector<std::string>>& layerIDs);
+
+ void setTriedOptional();
+
+ // Returns true when the tile source has received a first response, regardless of whether a load
+ // error occurred or actual data was loaded.
+ bool hasTriedOptional() const {
+ return triedOptional;
}
- Tile(const Tile&) = delete;
- Tile(Tile&&) = default;
- Tile& operator=(const Tile&) = delete;
- Tile& operator=(Tile&&) = default;
+ // Tile data considered "Renderable" can be used for rendering. Data in
+ // partial state is still waiting for network resources but can also
+ // be rendered, although layers will be missing.
+ bool isRenderable() const {
+ return availableData != DataAvailability::None;
+ }
+
+ bool isComplete() const {
+ return availableData == DataAvailability::All;
+ }
+ bool isIncomplete() const {
+ return availableData == DataAvailability::Some;
+ }
+
+ void dumpDebugLogs() const;
+
+ const OverscaledTileID id;
+ optional<Timestamp> modified;
+ optional<Timestamp> expires;
+
+ // Contains the tile ID string for painting debug information.
+ std::unique_ptr<DebugBucket> debugBucket;
+
+protected:
+ bool triedOptional = false;
+
+ enum class DataAvailability : uint8_t {
+ // Still waiting for data to load or parse.
+ None,
+
+ // Tile is partially parsed, some buckets are still waiting for dependencies
+ // to arrive, but it is good for rendering. Partial tiles can also be re-parsed,
+ // but might remain in the same state if dependencies are still missing.
+ Some,
+
+ // Tile is fully parsed, and all buckets are available if they exist.
+ All,
+ };
+
+ DataAvailability availableData = DataAvailability::None;
- const UnwrappedTileID id;
- TileData& data;
- ClipID clip;
- mat4 matrix;
+ TileObserver* observer = nullptr;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/tile_cache.cpp b/src/mbgl/tile/tile_cache.cpp
index e012ef0b7e..3fafb1259c 100644
--- a/src/mbgl/tile/tile_cache.cpp
+++ b/src/mbgl/tile/tile_cache.cpp
@@ -1,5 +1,5 @@
#include <mbgl/tile/tile_cache.hpp>
-#include <mbgl/tile/tile_data.hpp>
+#include <mbgl/tile/tile.hpp>
#include <cassert>
@@ -17,42 +17,42 @@ void TileCache::setSize(size_t size_) {
assert(orderedKeys.size() <= size);
}
-void TileCache::add(const OverscaledTileID& key, std::unique_ptr<TileData> data) {
- if (!data->isRenderable() || !size) {
+void TileCache::add(const OverscaledTileID& key, std::unique_ptr<Tile> tile) {
+ if (!tile->isRenderable() || !size) {
return;
}
- // insert new or query existing data
- if (tiles.emplace(key, std::move(data)).second) {
- // remove existing data key
+ // insert new or query existing tile
+ if (tiles.emplace(key, std::move(tile)).second) {
+ // remove existing tile key
orderedKeys.remove(key);
}
- // (re-)insert data key as newest
+ // (re-)insert tile key as newest
orderedKeys.push_back(key);
- // purge oldest key/data if necessary
+ // purge oldest key/tile if necessary
if (orderedKeys.size() > size) {
get(orderedKeys.front());
}
assert(orderedKeys.size() <= size);
-};
+}
-std::unique_ptr<TileData> TileCache::get(const OverscaledTileID& key) {
+std::unique_ptr<Tile> TileCache::get(const OverscaledTileID& key) {
- std::unique_ptr<TileData> data;
+ std::unique_ptr<Tile> tile;
auto it = tiles.find(key);
if (it != tiles.end()) {
- data = std::move(it->second);
+ tile = std::move(it->second);
tiles.erase(it);
orderedKeys.remove(key);
- assert(data->isRenderable());
+ assert(tile->isRenderable());
}
- return data;
-};
+ return tile;
+}
bool TileCache::has(const OverscaledTileID& key) {
return tiles.find(key) != tiles.end();
diff --git a/src/mbgl/tile/tile_cache.hpp b/src/mbgl/tile/tile_cache.hpp
index edaa6bd680..80fe98a20c 100644
--- a/src/mbgl/tile/tile_cache.hpp
+++ b/src/mbgl/tile/tile_cache.hpp
@@ -8,7 +8,7 @@
namespace mbgl {
-class TileData;
+class Tile;
class TileCache {
public:
@@ -16,13 +16,13 @@ public:
void setSize(size_t);
size_t getSize() const { return size; };
- void add(const OverscaledTileID& key, std::unique_ptr<TileData> data);
- std::unique_ptr<TileData> get(const OverscaledTileID& key);
+ void add(const OverscaledTileID& key, std::unique_ptr<Tile> data);
+ std::unique_ptr<Tile> get(const OverscaledTileID& key);
bool has(const OverscaledTileID& key);
void clear();
private:
- std::map<OverscaledTileID, std::unique_ptr<TileData>> tiles;
+ std::map<OverscaledTileID, std::unique_ptr<Tile>> tiles;
std::list<OverscaledTileID> orderedKeys;
size_t size;
diff --git a/src/mbgl/tile/tile_data.cpp b/src/mbgl/tile/tile_data.cpp
deleted file mode 100644
index e23ae2a727..0000000000
--- a/src/mbgl/tile/tile_data.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-#include <mbgl/tile/tile_data.hpp>
-#include <mbgl/renderer/debug_bucket.hpp>
-#include <mbgl/util/string.hpp>
-
-namespace mbgl {
-
-TileData::TileData(const OverscaledTileID& id_)
- : id(id_) {
-}
-
-TileData::~TileData() = default;
-
-void TileData::dumpDebugLogs() const {
- Log::Info(Event::General, "TileData::id: %s", util::toString(id).c_str());
- Log::Info(Event::General, "TileData::renderable: %s", isRenderable() ? "yes" : "no");
- Log::Info(Event::General, "TileData::complete: %s", isComplete() ? "yes" : "no");
-}
-
-void TileData::queryRenderedFeatures(
- std::unordered_map<std::string, std::vector<Feature>>&,
- const GeometryCoordinates&,
- const TransformState&,
- const optional<std::vector<std::string>>&) {}
-
-} // namespace mbgl
diff --git a/src/mbgl/tile/tile_data.hpp b/src/mbgl/tile/tile_data.hpp
deleted file mode 100644
index 5b6583faf8..0000000000
--- a/src/mbgl/tile/tile_data.hpp
+++ /dev/null
@@ -1,87 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/util/optional.hpp>
-#include <mbgl/util/feature.hpp>
-#include <mbgl/tile/tile_id.hpp>
-#include <mbgl/renderer/bucket.hpp>
-#include <mbgl/text/placement_config.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
-
-#include <string>
-#include <memory>
-#include <functional>
-#include <unordered_map>
-
-namespace mbgl {
-
-class Worker;
-class DebugBucket;
-class TransformState;
-
-namespace style {
-class Layer;
-}
-
-class TileData : private util::noncopyable {
-public:
- TileData(const OverscaledTileID&);
- virtual ~TileData();
-
- // Mark this tile as no longer needed and cancel any pending work.
- virtual void cancel() = 0;
-
- virtual Bucket* getBucket(const style::Layer&) = 0;
-
- virtual bool parsePending(std::function<void (std::exception_ptr)>) { return true; }
- virtual void redoPlacement(PlacementConfig, const std::function<void()>&) {}
- virtual void redoPlacement(const std::function<void()>&) {}
-
- virtual void queryRenderedFeatures(
- std::unordered_map<std::string, std::vector<Feature>>& result,
- const GeometryCoordinates& queryGeometry,
- const TransformState&,
- const optional<std::vector<std::string>>& layerIDs);
-
- // Tile data considered "Renderable" can be used for rendering. Data in
- // partial state is still waiting for network resources but can also
- // be rendered, although layers will be missing.
- bool isRenderable() const {
- return availableData != DataAvailability::None;
- }
-
- bool isComplete() const {
- return availableData == DataAvailability::All;
- }
- bool isIncomplete() const {
- return availableData == DataAvailability::Some;
- }
-
- void dumpDebugLogs() const;
-
- const OverscaledTileID id;
- optional<Timestamp> modified;
- optional<Timestamp> expires;
-
- // Contains the tile ID string for painting debug information.
- std::unique_ptr<DebugBucket> debugBucket;
-
-protected:
- enum class DataAvailability : uint8_t {
- // Still waiting for data to load or parse.
- None,
-
- // TileData is partially parsed, some buckets are still waiting for dependencies
- // to arrive, but it is good for rendering. Partial tiles can also be re-parsed,
- // but might remain in the same state if dependencies are still missing.
- Some,
-
- // TileData is fully parsed, and all buckets are available if they exist.
- All,
- };
-
- DataAvailability availableData = DataAvailability::None;
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/tile/tile_id.hpp b/src/mbgl/tile/tile_id.hpp
index f9afdfa529..f561db9a4d 100644
--- a/src/mbgl/tile/tile_id.hpp
+++ b/src/mbgl/tile/tile_id.hpp
@@ -45,8 +45,7 @@ std::string toString(const CanonicalTileID&);
// z/x/y describe the
class OverscaledTileID {
public:
- OverscaledTileID(uint8_t overscaledZ, const CanonicalTileID&);
- OverscaledTileID(uint8_t overscaledZ, CanonicalTileID&&);
+ OverscaledTileID(uint8_t overscaledZ, CanonicalTileID);
OverscaledTileID(uint8_t overscaledZ, uint8_t z, uint32_t x, uint32_t y);
OverscaledTileID(uint8_t z, uint32_t x, uint32_t y);
explicit OverscaledTileID(const CanonicalTileID&);
@@ -75,8 +74,7 @@ std::string toString(const OverscaledTileID&);
class UnwrappedTileID {
public:
UnwrappedTileID(uint8_t z, int64_t x, int64_t y);
- UnwrappedTileID(int16_t wrap, const CanonicalTileID&);
- UnwrappedTileID(int16_t wrap, CanonicalTileID&&);
+ UnwrappedTileID(int16_t wrap, CanonicalTileID);
bool operator==(const UnwrappedTileID&) const;
bool operator!=(const UnwrappedTileID&) const;
bool operator<(const UnwrappedTileID&) const;
@@ -143,13 +141,8 @@ inline std::array<CanonicalTileID, 4> CanonicalTileID::children() const {
} };
}
-inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, const CanonicalTileID& canonical_)
- : overscaledZ(overscaledZ_), canonical(canonical_) {
- assert(overscaledZ >= canonical.z);
-}
-
-inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, CanonicalTileID&& canonical_)
- : overscaledZ(overscaledZ_), canonical(std::forward<CanonicalTileID>(canonical_)) {
+inline OverscaledTileID::OverscaledTileID(uint8_t overscaledZ_, CanonicalTileID canonical_)
+ : overscaledZ(overscaledZ_), canonical(std::move(canonical_)) {
assert(overscaledZ >= canonical.z);
}
@@ -216,12 +209,8 @@ inline UnwrappedTileID::UnwrappedTileID(uint8_t z_, int64_t x_, int64_t y_)
y_ < 0 ? 0 : std::min(static_cast<uint32_t>(y_), static_cast<uint32_t>(1ull << z_) - 1)) {
}
-inline UnwrappedTileID::UnwrappedTileID(int16_t wrap_, const CanonicalTileID& canonical_)
- : wrap(wrap_), canonical(canonical_) {
-}
-
-inline UnwrappedTileID::UnwrappedTileID(int16_t wrap_, CanonicalTileID&& canonical_)
- : wrap(wrap_), canonical(std::forward<CanonicalTileID>(canonical_)) {
+inline UnwrappedTileID::UnwrappedTileID(int16_t wrap_, CanonicalTileID canonical_)
+ : wrap(wrap_), canonical(std::move(canonical_)) {
}
inline bool UnwrappedTileID::operator==(const UnwrappedTileID& rhs) const {
diff --git a/src/mbgl/tile/tile_loader.hpp b/src/mbgl/tile/tile_loader.hpp
new file mode 100644
index 0000000000..0d64f647d7
--- /dev/null
+++ b/src/mbgl/tile/tile_loader.hpp
@@ -0,0 +1,62 @@
+#pragma once
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/storage/resource.hpp>
+#include <mbgl/tile/tile.hpp>
+
+namespace mbgl {
+
+class FileSource;
+class AsyncRequest;
+class Response;
+class Tileset;
+
+namespace style {
+class UpdateParameters;
+} // namespace style
+
+template <typename T>
+class TileLoader : private util::noncopyable {
+public:
+ TileLoader(T&,
+ const OverscaledTileID&,
+ const style::UpdateParameters&,
+ const Tileset&);
+ ~TileLoader();
+
+ using Necessity = Resource::Necessity;
+
+ void setNecessity(Necessity newNecessity) {
+ if (newNecessity != necessity) {
+ necessity = newNecessity;
+ if (necessity == Necessity::Required) {
+ makeRequired();
+ } else {
+ makeOptional();
+ }
+ }
+ }
+
+private:
+ // called when the tile is one of the ideal tiles that we want to show definitely. the tile source
+ // should try to make every effort (e.g. fetch from internet, or revalidate existing resources).
+ void makeRequired();
+
+ // called when the zoom level no longer corresponds to the displayed one, but
+ // we're still interested in retaining the tile, e.g. for backfill.
+ // subclassed TileSources should cancel actions they are taking to provide
+ // an up-to-date version or load new data
+ void makeOptional();
+
+ void loadOptional();
+ void loadedData(const Response&);
+ void loadRequired();
+
+ T& tile;
+ Necessity necessity;
+ Resource resource;
+ FileSource& fileSource;
+ std::unique_ptr<AsyncRequest> request;
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/tile_loader_impl.hpp b/src/mbgl/tile/tile_loader_impl.hpp
new file mode 100644
index 0000000000..b987d6ec65
--- /dev/null
+++ b/src/mbgl/tile/tile_loader_impl.hpp
@@ -0,0 +1,113 @@
+#pragma once
+
+#include <mbgl/tile/tile_loader.hpp>
+#include <mbgl/storage/file_source.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <mbgl/util/tileset.hpp>
+
+#include <cassert>
+
+namespace mbgl {
+
+template <typename T>
+TileLoader<T>::TileLoader(T& tile_,
+ const OverscaledTileID& id,
+ const style::UpdateParameters& parameters,
+ const Tileset& tileset)
+ : tile(tile_),
+ necessity(Necessity::Optional),
+ resource(Resource::tile(
+ tileset.tiles.at(0),
+ parameters.pixelRatio,
+ id.canonical.x,
+ id.canonical.y,
+ id.canonical.z)),
+ fileSource(parameters.fileSource) {
+ assert(!request);
+ if (fileSource.supportsOptionalRequests()) {
+ // When supported, the first request is always optional, even if the TileLoader
+ // is marked as required. That way, we can let the first optional request continue
+ // to load when the TileLoader is later changed from required to optional. If we
+ // started out with a required request, we'd have to cancel everything, including the
+ // initial optional part of the request.
+ loadOptional();
+ } else {
+ // When the FileSource doesn't support optional requests, we do nothing until the
+ // data is definitely required.
+ if (necessity == Necessity::Required) {
+ loadRequired();
+ } else {
+ // We're using this field to check whether the pending request is optional or required.
+ resource.necessity = Resource::Optional;
+ }
+ }
+}
+
+template <typename T>
+TileLoader<T>::~TileLoader() = default;
+
+template <typename T>
+void TileLoader<T>::loadOptional() {
+ assert(!request);
+
+ resource.necessity = Resource::Optional;
+ request = fileSource.request(resource, [this](Response res) {
+ request.reset();
+
+ tile.setTriedOptional();
+
+ if (res.error && res.error->reason == Response::Error::Reason::NotFound) {
+ // When the optional request could not be satisfied, don't treat it as an error.
+ // Instead, we make sure that the next request knows that there has been an optional
+ // request before by setting one of the prior* fields.
+ resource.priorExpires = Timestamp{ Seconds::zero() };
+ } else {
+ loadedData(res);
+ }
+
+ if (necessity == Necessity::Required) {
+ loadRequired();
+ }
+ });
+}
+
+template <typename T>
+void TileLoader<T>::makeRequired() {
+ if (!request) {
+ loadRequired();
+ }
+}
+
+template <typename T>
+void TileLoader<T>::makeOptional() {
+ if (resource.necessity == Resource::Required && request) {
+ // Abort a potential HTTP request.
+ request.reset();
+ }
+}
+
+template <typename T>
+void TileLoader<T>::loadedData(const Response& res) {
+ if (res.error && res.error->reason != Response::Error::Reason::NotFound) {
+ tile.setError(std::make_exception_ptr(std::runtime_error(res.error->message)));
+ } else if (res.notModified) {
+ resource.priorExpires = res.expires;
+ // Do not notify the tile; when we get this message, it already has the current
+ // version of the data.
+ } else {
+ resource.priorModified = res.modified;
+ resource.priorExpires = res.expires;
+ resource.priorEtag = res.etag;
+ tile.setData(res.noContent ? nullptr : res.data, res.modified, res.expires);
+ }
+}
+
+template <typename T>
+void TileLoader<T>::loadRequired() {
+ assert(!request);
+
+ resource.necessity = Resource::Required;
+ request = fileSource.request(resource, [this](Response res) { loadedData(res); });
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/tile_observer.hpp b/src/mbgl/tile/tile_observer.hpp
new file mode 100644
index 0000000000..96ded11fbb
--- /dev/null
+++ b/src/mbgl/tile/tile_observer.hpp
@@ -0,0 +1,18 @@
+#pragma once
+
+#include <exception>
+
+namespace mbgl {
+
+class Tile;
+
+class TileObserver {
+public:
+ virtual ~TileObserver() = default;
+
+ virtual void onTileLoaded(Tile&, bool /*isNewTile*/) {}
+ virtual void onTileError(Tile&, std::exception_ptr) {}
+ virtual void onNeedsRepaint() {}
+};
+
+} // namespace mbgl
diff --git a/src/mbgl/tile/tile_worker.cpp b/src/mbgl/tile/tile_worker.cpp
index 1890aa7c47..fe75c86741 100644
--- a/src/mbgl/tile/tile_worker.cpp
+++ b/src/mbgl/tile/tile_worker.cpp
@@ -1,9 +1,7 @@
#include <mbgl/text/collision_tile.hpp>
#include <mbgl/tile/tile_worker.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/bucket_parameters.hpp>
-#include <mbgl/style/layers/background_layer.hpp>
-#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include <mbgl/style/layers/symbol_layer_impl.hpp>
#include <mbgl/sprite/sprite_atlas.hpp>
@@ -13,21 +11,20 @@
#include <mbgl/util/constants.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/exception.hpp>
+
#include <utility>
namespace mbgl {
-using namespace mbgl::style;
+using namespace style;
-TileWorker::TileWorker(const OverscaledTileID& id_,
- std::string sourceID_,
+TileWorker::TileWorker(OverscaledTileID id_,
SpriteStore& spriteStore_,
GlyphAtlas& glyphAtlas_,
GlyphStore& glyphStore_,
const util::Atomic<bool>& obsolete_,
const MapMode mode_)
- : id(id_),
- sourceID(std::move(sourceID_)),
+ : id(std::move(id_)),
spriteStore(spriteStore_),
glyphAtlas(glyphAtlas_),
glyphStore(glyphStore_),
@@ -40,14 +37,14 @@ TileWorker::~TileWorker() {
}
TileParseResult TileWorker::parseAllLayers(std::vector<std::unique_ptr<Layer>> layers_,
- std::unique_ptr<const GeometryTile> geometryTile_,
+ std::unique_ptr<const GeometryTileData> tileData_,
PlacementConfig config) {
// We're doing a fresh parse of the tile, because the underlying data has changed.
pending.clear();
placementPending.clear();
partialParse = false;
featureIndex = std::make_unique<FeatureIndex>();
- geometryTile = std::move(geometryTile_);
+ tileData = std::move(tileData_);
// Store the layers for use in redoPlacement.
layers = std::move(layers_);
@@ -98,7 +95,7 @@ TileParseResult TileWorker::prepareResult(const PlacementConfig& config) {
if (result.complete) {
featureIndex->setCollisionTile(placeLayers(config));
result.featureIndex = std::move(featureIndex);
- result.geometryTile = std::move(geometryTile);
+ result.tileData = std::move(tileData);
}
return std::move(result);
@@ -135,19 +132,7 @@ void TileWorker::parseLayer(const Layer* layer) {
if (obsolete)
return;
- // Background and custom layers are special cases.
- if (layer->is<BackgroundLayer>() || layer->is<CustomLayer>())
- return;
-
- // Skip this bucket if we are to not render this
- if ((layer->baseImpl->source != sourceID) ||
- (id.overscaledZ < std::floor(layer->baseImpl->minZoom)) ||
- (id.overscaledZ >= std::ceil(layer->baseImpl->maxZoom)) ||
- (layer->baseImpl->visibility == VisibilityType::None)) {
- return;
- }
-
- auto geometryLayer = geometryTile->getLayer(layer->baseImpl->sourceLayer);
+ auto geometryLayer = tileData->getLayer(layer->baseImpl->sourceLayer);
if (!geometryLayer) {
// The layer specified in the bucket does not exist. Do nothing.
if (debug::tileParseWarnings) {
@@ -188,4 +173,4 @@ void TileWorker::insertBucket(const std::string& name, std::unique_ptr<Bucket> b
}
}
-}
+} // namespace mbgl
diff --git a/src/mbgl/tile/tile_worker.hpp b/src/mbgl/tile/tile_worker.hpp
index 631a8c929f..b25858c955 100644
--- a/src/mbgl/tile/tile_worker.hpp
+++ b/src/mbgl/tile/tile_worker.hpp
@@ -18,7 +18,7 @@
namespace mbgl {
class CollisionTile;
-class GeometryTile;
+class GeometryTileData;
class SpriteStore;
class GlyphAtlas;
class GlyphStore;
@@ -27,7 +27,7 @@ class Bucket;
namespace style {
class Layer;
class SymbolLayer;
-}
+} // namespace style
// We're using this class to shuttle the resulting buckets from the worker thread to the MapContext
// thread. This class is movable-only because the vector contains movable-only value elements.
@@ -36,7 +36,7 @@ public:
bool complete = false;
std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<const GeometryTile> geometryTile;
+ std::unique_ptr<const GeometryTileData> tileData;
};
using TileParseResult = variant<
@@ -45,8 +45,7 @@ using TileParseResult = variant<
class TileWorker : public util::noncopyable {
public:
- TileWorker(const OverscaledTileID&,
- std::string sourceID,
+ TileWorker(OverscaledTileID,
SpriteStore&,
GlyphAtlas&,
GlyphStore&,
@@ -55,7 +54,7 @@ public:
~TileWorker();
TileParseResult parseAllLayers(std::vector<std::unique_ptr<style::Layer>>,
- std::unique_ptr<const GeometryTile> geometryTile,
+ std::unique_ptr<const GeometryTileData> tileData,
PlacementConfig);
TileParseResult parsePendingLayers(PlacementConfig);
@@ -70,7 +69,6 @@ private:
std::unique_ptr<CollisionTile> placeLayers(PlacementConfig);
const OverscaledTileID id;
- const std::string sourceID;
SpriteStore& spriteStore;
GlyphAtlas& glyphAtlas;
@@ -83,7 +81,7 @@ private:
std::vector<std::unique_ptr<style::Layer>> layers;
std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<const GeometryTile> geometryTile;
+ std::unique_ptr<const GeometryTileData> tileData;
// Contains buckets that we couldn't parse so far due to missing resources.
// They will be attempted on subsequent parses.
diff --git a/src/mbgl/tile/vector_tile.cpp b/src/mbgl/tile/vector_tile.cpp
index 5126d0ce83..6a3c51c05d 100644
--- a/src/mbgl/tile/vector_tile.cpp
+++ b/src/mbgl/tile/vector_tile.cpp
@@ -1,14 +1,94 @@
#include <mbgl/tile/vector_tile.hpp>
-#include <mbgl/style/source.hpp>
-#include <mbgl/storage/resource.hpp>
-#include <mbgl/storage/response.hpp>
-#include <mbgl/storage/file_source.hpp>
-#include <mbgl/util/url.hpp>
+#include <mbgl/tile/tile_loader_impl.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
+#include <mbgl/style/update_parameters.hpp>
+#include <protozero/pbf_reader.hpp>
+
+#include <map>
+#include <unordered_map>
+#include <functional>
#include <utility>
namespace mbgl {
+class VectorTileLayer;
+
+using pbf_iter_type = protozero::pbf_reader::const_uint32_iterator;
+using packed_iter_type = std::pair<pbf_iter_type,pbf_iter_type>;
+
+class VectorTileFeature : public GeometryTileFeature {
+public:
+ VectorTileFeature(protozero::pbf_reader, const VectorTileLayer&);
+
+ FeatureType getType() const override { return type; }
+ optional<Value> getValue(const std::string&) const override;
+ std::unordered_map<std::string,Value> getProperties() const override;
+ optional<FeatureIdentifier> getID() const override;
+ GeometryCollection getGeometries() const override;
+
+private:
+ const VectorTileLayer& layer;
+ optional<FeatureIdentifier> id;
+ FeatureType type = FeatureType::Unknown;
+ packed_iter_type tags_iter;
+ packed_iter_type geometry_iter;
+};
+
+class VectorTileLayer : public GeometryTileLayer {
+public:
+ VectorTileLayer(protozero::pbf_reader);
+
+ std::size_t featureCount() const override { return features.size(); }
+ util::ptr<const GeometryTileFeature> getFeature(std::size_t) const override;
+ std::string getName() const override;
+
+private:
+ friend class VectorTileData;
+ friend class VectorTileFeature;
+
+ std::string name;
+ uint32_t version = 1;
+ uint32_t extent = 4096;
+ std::map<std::string, uint32_t> keysMap;
+ std::vector<std::reference_wrapper<const std::string>> keys;
+ std::vector<Value> values;
+ std::vector<protozero::pbf_reader> features;
+};
+
+class VectorTileData : public GeometryTileData {
+public:
+ VectorTileData(std::shared_ptr<const std::string> data);
+
+ util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
+
+private:
+ std::shared_ptr<const std::string> data;
+ mutable bool parsed = false;
+ mutable std::map<std::string, util::ptr<GeometryTileLayer>> layers;
+};
+
+VectorTile::VectorTile(const OverscaledTileID& id_,
+ std::string sourceID_,
+ const style::UpdateParameters& parameters,
+ const Tileset& tileset)
+ : GeometryTile(id_, sourceID_, parameters.style, parameters.mode),
+ loader(*this, id_, parameters, tileset) {
+}
+
+void VectorTile::setNecessity(Necessity necessity) {
+ loader.setNecessity(necessity);
+}
+
+void VectorTile::setData(std::shared_ptr<const std::string> data_,
+ optional<Timestamp> modified_,
+ optional<Timestamp> expires_) {
+ modified = modified_;
+ expires = expires_;
+
+ GeometryTile::setData(data_ ? std::make_unique<VectorTileData>(data_) : nullptr);
+}
+
Value parseValue(protozero::pbf_reader data) {
while (data.next())
{
@@ -40,7 +120,7 @@ VectorTileFeature::VectorTileFeature(protozero::pbf_reader feature_pbf, const Ve
while (feature_pbf.next()) {
switch (feature_pbf.tag()) {
case 1: // id
- id = feature_pbf.get_uint64();
+ id = { feature_pbf.get_uint64() };
break;
case 2: // tags
tags_iter = feature_pbf.get_packed_uint32();
@@ -105,7 +185,7 @@ std::unordered_map<std::string,Value> VectorTileFeature::getProperties() const {
return properties;
}
-optional<uint64_t> VectorTileFeature::getID() const {
+optional<FeatureIdentifier> VectorTileFeature::getID() const {
return id;
}
@@ -159,11 +239,11 @@ GeometryCollection VectorTileFeature::getGeometries() const {
return fixupPolygons(lines);
}
-VectorTile::VectorTile(std::shared_ptr<const std::string> data_)
+VectorTileData::VectorTileData(std::shared_ptr<const std::string> data_)
: data(std::move(data_)) {
}
-util::ptr<GeometryTileLayer> VectorTile::getLayer(const std::string& name) const {
+util::ptr<GeometryTileLayer> VectorTileData::getLayer(const std::string& name) const {
if (!parsed) {
parsed = true;
protozero::pbf_reader tile_pbf(*data);
@@ -220,28 +300,4 @@ std::string VectorTileLayer::getName() const {
return name;
}
-VectorTileMonitor::VectorTileMonitor(const OverscaledTileID& tileID_, float pixelRatio_,
- const std::string& urlTemplate_, FileSource& fileSource_)
- : tileID(tileID_),
- pixelRatio(pixelRatio_),
- urlTemplate(urlTemplate_),
- fileSource(fileSource_) {
-}
-
-std::unique_ptr<AsyncRequest> VectorTileMonitor::monitorTile(const GeometryTileMonitor::Callback& callback) {
- const Resource resource = Resource::tile(urlTemplate, pixelRatio, tileID.canonical.x,
- tileID.canonical.y, tileID.canonical.z);
- return fileSource.request(resource, [callback, this](Response res) {
- if (res.error) {
- callback(std::make_exception_ptr(std::runtime_error(res.error->message)), nullptr, res.modified, res.expires);
- } else if (res.notModified) {
- return;
- } else if (res.noContent) {
- callback(nullptr, nullptr, res.modified, res.expires);
- } else {
- callback(nullptr, std::make_unique<VectorTile>(res.data), res.modified, res.expires);
- }
- });
-}
-
} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile.hpp b/src/mbgl/tile/vector_tile.hpp
index 9e81f0ec8c..2568a277e6 100644
--- a/src/mbgl/tile/vector_tile.hpp
+++ b/src/mbgl/tile/vector_tile.hpp
@@ -1,85 +1,30 @@
#pragma once
#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/tile/tile_id.hpp>
-#include <protozero/pbf_reader.hpp>
-
-#include <map>
-#include <unordered_map>
-#include <functional>
+#include <mbgl/tile/tile_loader.hpp>
namespace mbgl {
-class VectorTileLayer;
-
-using pbf_iter_type = protozero::pbf_reader::const_uint32_iterator;
-using packed_iter_type = std::pair<pbf_iter_type,pbf_iter_type>;
-
-class VectorTileFeature : public GeometryTileFeature {
-public:
- VectorTileFeature(protozero::pbf_reader, const VectorTileLayer&);
+class Tileset;
- FeatureType getType() const override { return type; }
- optional<Value> getValue(const std::string&) const override;
- std::unordered_map<std::string,Value> getProperties() const override;
- optional<uint64_t> getID() const override;
- GeometryCollection getGeometries() const override;
-
-private:
- const VectorTileLayer& layer;
- optional<uint64_t> id;
- FeatureType type = FeatureType::Unknown;
- packed_iter_type tags_iter;
- packed_iter_type geometry_iter;
-};
-
-class VectorTileLayer : public GeometryTileLayer {
-public:
- VectorTileLayer(protozero::pbf_reader);
-
- std::size_t featureCount() const override { return features.size(); }
- util::ptr<const GeometryTileFeature> getFeature(std::size_t) const override;
- std::string getName() const override;
-
-private:
- friend class VectorTile;
- friend class VectorTileFeature;
-
- std::string name;
- uint32_t version = 1;
- uint32_t extent = 4096;
- std::map<std::string, uint32_t> keysMap;
- std::vector<std::reference_wrapper<const std::string>> keys;
- std::vector<Value> values;
- std::vector<protozero::pbf_reader> features;
-};
+namespace style {
+class UpdateParameters;
+} // namespace style
class VectorTile : public GeometryTile {
public:
- VectorTile(std::shared_ptr<const std::string> data);
-
- util::ptr<GeometryTileLayer> getLayer(const std::string&) const override;
-
-private:
- std::shared_ptr<const std::string> data;
- mutable bool parsed = false;
- mutable std::map<std::string, util::ptr<GeometryTileLayer>> layers;
-};
-
-class TileID;
-class FileSource;
-
-class VectorTileMonitor : public GeometryTileMonitor {
-public:
- VectorTileMonitor(const OverscaledTileID&, float pixelRatio, const std::string& urlTemplate, FileSource&);
+ VectorTile(const OverscaledTileID&,
+ std::string sourceID,
+ const style::UpdateParameters&,
+ const Tileset&);
- std::unique_ptr<AsyncRequest> monitorTile(const GeometryTileMonitor::Callback&) override;
+ void setNecessity(Necessity) final;
+ void setData(std::shared_ptr<const std::string> data,
+ optional<Timestamp> modified,
+ optional<Timestamp> expires);
private:
- OverscaledTileID tileID;
- float pixelRatio;
- std::string urlTemplate;
- FileSource& fileSource;
+ TileLoader<VectorTile> loader;
};
} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile_data.cpp b/src/mbgl/tile/vector_tile_data.cpp
deleted file mode 100644
index 1ab2566a25..0000000000
--- a/src/mbgl/tile/vector_tile_data.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-#include <mbgl/tile/vector_tile_data.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
-#include <mbgl/style/layer_impl.hpp>
-#include <mbgl/util/worker.hpp>
-#include <mbgl/util/work_request.hpp>
-#include <mbgl/style/style.hpp>
-#include <mbgl/storage/file_source.hpp>
-#include <mbgl/geometry/feature_index.hpp>
-#include <mbgl/text/collision_tile.hpp>
-#include <mbgl/map/transform_state.hpp>
-
-namespace mbgl {
-
-VectorTileData::VectorTileData(const OverscaledTileID& id_,
- std::unique_ptr<GeometryTileMonitor> monitor_,
- std::string sourceID,
- style::Style& style_,
- const MapMode mode_,
- const std::function<void(std::exception_ptr)>& callback)
- : TileData(id_),
- style(style_),
- worker(style_.workers),
- tileWorker(id_,
- sourceID,
- *style_.spriteStore,
- *style_.glyphAtlas,
- *style_.glyphStore,
- obsolete,
- mode_),
- monitor(std::move(monitor_))
-{
- tileRequest = monitor->monitorTile([callback, this](std::exception_ptr err,
- std::unique_ptr<GeometryTile> tile,
- optional<Timestamp> modified_,
- optional<Timestamp> expires_) {
- if (err) {
- callback(err);
- return;
- }
-
- modified = modified_;
- expires = expires_;
-
- if (!tile) {
- // This is a 404 response. We're treating these as empty tiles.
- workRequest.reset();
- availableData = DataAvailability::All;
- buckets.clear();
- callback(err);
- return;
- }
-
- // Mark the tile as pending again if it was complete before to prevent signaling a complete
- // state despite pending parse operations.
- if (availableData == DataAvailability::All) {
- availableData = DataAvailability::Some;
- }
-
- // Kick off a fresh parse of this tile. This happens when the tile is new, or
- // when tile data changed. Replacing the workdRequest will cancel a pending work
- // request in case there is one.
- workRequest.reset();
- workRequest = worker.parseGeometryTile(tileWorker, style.getLayers(), std::move(tile), targetConfig, [callback, this, config = targetConfig] (TileParseResult result) {
- workRequest.reset();
-
- std::exception_ptr error;
- if (result.is<TileParseResultData>()) {
- auto& resultBuckets = result.get<TileParseResultData>();
- availableData =
- resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
-
- // Persist the configuration we just placed so that we can later check whether we need to
- // place again in case the configuration has changed.
- placedConfig = config;
-
- // Move over all buckets we received in this parse request, potentially overwriting
- // existing buckets in case we got a refresh parse.
- buckets = std::move(resultBuckets.buckets);
-
- if (isComplete()) {
- featureIndex = std::move(resultBuckets.featureIndex);
- geometryTile = std::move(resultBuckets.geometryTile);
- }
-
- } else {
- // This is triggered when parsing fails (e.g. due to an invalid vector tile)
- error = result.get<std::exception_ptr>();
- availableData = DataAvailability::All;
- }
-
- callback(error);
- });
- });
-}
-
-VectorTileData::~VectorTileData() {
- cancel();
-}
-
-bool VectorTileData::parsePending(std::function<void(std::exception_ptr)> callback) {
- if (workRequest) {
- // There's already parsing or placement going on.
- return false;
- }
-
- workRequest.reset();
- workRequest = worker.parsePendingGeometryTileLayers(tileWorker, targetConfig, [this, callback, config = targetConfig] (TileParseResult result) {
- workRequest.reset();
-
- std::exception_ptr error;
- if (result.is<TileParseResultData>()) {
- auto& resultBuckets = result.get<TileParseResultData>();
- availableData =
- resultBuckets.complete ? DataAvailability::All : DataAvailability::Some;
-
- // Move over all buckets we received in this parse request, potentially overwriting
- // existing buckets in case we got a refresh parse.
- for (auto& bucket : resultBuckets.buckets) {
- buckets[bucket.first] = std::move(bucket.second);
- }
-
- // Persist the configuration we just placed so that we can later check whether we need to
- // place again in case the configuration has changed.
- placedConfig = config;
-
- if (isComplete()) {
- featureIndex = std::move(resultBuckets.featureIndex);
- geometryTile = std::move(resultBuckets.geometryTile);
- }
-
- } else {
- error = result.get<std::exception_ptr>();
- availableData = DataAvailability::All;
- }
-
- callback(error);
- });
-
- return true;
-}
-
-Bucket* VectorTileData::getBucket(const style::Layer& layer) {
- const auto it = buckets.find(layer.baseImpl->bucketName());
- if (it == buckets.end()) {
- return nullptr;
- }
-
- assert(it->second);
- return it->second.get();
-}
-
-void VectorTileData::redoPlacement(const PlacementConfig newConfig, const std::function<void()>& callback) {
- if (newConfig != placedConfig) {
- targetConfig = newConfig;
-
- redoPlacement(callback);
- }
-}
-
-void VectorTileData::redoPlacement(const std::function<void()>& callback) {
- // Don't start a new placement request when the current one hasn't completed yet, or when
- // we are parsing buckets.
- if (workRequest) return;
-
- workRequest = worker.redoPlacement(tileWorker, buckets, targetConfig, [this, callback, config = targetConfig](std::unique_ptr<CollisionTile> collisionTile) {
- workRequest.reset();
-
- // Persist the configuration we just placed so that we can later check whether we need to
- // place again in case the configuration has changed.
- placedConfig = config;
-
- for (auto& bucket : buckets) {
- bucket.second->swapRenderData();
- }
-
- if (featureIndex) {
- featureIndex->setCollisionTile(std::move(collisionTile));
- }
-
- // The target configuration could have changed since we started placement. In this case,
- // we're starting another placement run.
- if (placedConfig != targetConfig) {
- redoPlacement(callback);
- } else {
- callback();
- }
- });
-}
-
-void VectorTileData::queryRenderedFeatures(
- std::unordered_map<std::string, std::vector<Feature>>& result,
- const GeometryCoordinates& queryGeometry,
- const TransformState& transformState,
- const optional<std::vector<std::string>>& layerIDs) {
-
- if (!featureIndex || !geometryTile) return;
-
- featureIndex->query(result,
- { queryGeometry },
- transformState.getAngle(),
- util::tileSize * id.overscaleFactor(),
- std::pow(2, transformState.getZoom() - id.overscaledZ),
- layerIDs,
- *geometryTile,
- id.canonical,
- style);
-}
-
-void VectorTileData::cancel() {
- obsolete = true;
- tileRequest.reset();
- workRequest.reset();
-}
-
-} // namespace mbgl
diff --git a/src/mbgl/tile/vector_tile_data.hpp b/src/mbgl/tile/vector_tile_data.hpp
deleted file mode 100644
index df2a23fda6..0000000000
--- a/src/mbgl/tile/vector_tile_data.hpp
+++ /dev/null
@@ -1,75 +0,0 @@
-#pragma once
-
-#include <mbgl/tile/tile_data.hpp>
-#include <mbgl/tile/tile_worker.hpp>
-#include <mbgl/text/placement_config.hpp>
-#include <mbgl/util/atomic.hpp>
-#include <mbgl/util/feature.hpp>
-
-#include <memory>
-#include <unordered_map>
-
-namespace mbgl {
-
-class AsyncRequest;
-class GeometryTileMonitor;
-class FeatureIndex;
-
-namespace style {
-class Style;
-}
-
-class VectorTileData : public TileData {
-public:
- VectorTileData(const OverscaledTileID&,
- std::unique_ptr<GeometryTileMonitor> monitor,
- std::string sourceID,
- style::Style&,
- const MapMode,
- const std::function<void(std::exception_ptr)>& callback);
-
- ~VectorTileData();
-
- Bucket* getBucket(const style::Layer&) override;
-
- bool parsePending(std::function<void(std::exception_ptr)> callback) override;
-
- void redoPlacement(PlacementConfig config, const std::function<void()>&) override;
- void redoPlacement(const std::function<void()>&) override;
-
- void queryRenderedFeatures(
- std::unordered_map<std::string, std::vector<Feature>>& result,
- const GeometryCoordinates& queryGeometry,
- const TransformState&,
- const optional<std::vector<std::string>>& layerIDs) override;
-
- void cancel() override;
-
-private:
- style::Style& style;
- Worker& worker;
- TileWorker tileWorker;
-
- std::unique_ptr<GeometryTileMonitor> monitor;
- std::unique_ptr<AsyncRequest> tileRequest;
- std::unique_ptr<AsyncRequest> workRequest;
-
- // Contains all the Bucket objects for the tile. Buckets are render
- // objects and they get added by tile parsing operations.
- std::unordered_map<std::string, std::unique_ptr<Bucket>> buckets;
-
- std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<const GeometryTile> geometryTile;
-
- // Stores the placement configuration of the text that is currently placed on the screen.
- PlacementConfig placedConfig;
-
- // Stores the placement configuration of how the text should be placed. This isn't necessarily
- // the one that is being displayed.
- PlacementConfig targetConfig;
-
- // Used to signal the worker that it should abandon parsing this tile as soon as possible.
- util::Atomic<bool> obsolete { false };
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/util/clip_id.hpp b/src/mbgl/util/clip_id.hpp
index 064a7acf94..de2dc51919 100644
--- a/src/mbgl/util/clip_id.hpp
+++ b/src/mbgl/util/clip_id.hpp
@@ -11,20 +11,18 @@
namespace mbgl {
-class Tile;
-
struct ClipID {
- inline ClipID() {}
- inline ClipID(const std::string &mask_, const std::string &reference_) : mask(mask_), reference(reference_) {}
+ ClipID() {}
+ ClipID(const std::string &mask_, const std::string &reference_) : mask(mask_), reference(reference_) {}
std::bitset<8> mask;
std::bitset<8> reference;
- inline bool operator==(const ClipID &other) const {
+ bool operator==(const ClipID &other) const {
return mask == other.mask && reference == other.reference;
}
- inline ClipID& operator|=(const ClipID &other) {
+ ClipID& operator|=(const ClipID &other) {
mask |= other.mask;
reference |= other.reference;
return *this;
diff --git a/src/mbgl/util/color.cpp b/src/mbgl/util/color.cpp
new file mode 100644
index 0000000000..eea897d3ab
--- /dev/null
+++ b/src/mbgl/util/color.cpp
@@ -0,0 +1,20 @@
+#include <mbgl/util/color.hpp>
+
+#include <csscolorparser/csscolorparser.hpp>
+
+namespace mbgl {
+
+optional<Color> Color::parse(const std::string& s) {
+ CSSColorParser::Color css_color = CSSColorParser::parse(s);
+
+ // Premultiply the color.
+ const float factor = css_color.a / 255;
+ return {{
+ css_color.r * factor,
+ css_color.g * factor,
+ css_color.b * factor,
+ css_color.a
+ }};
+}
+
+} // namespace mbgl
diff --git a/src/mbgl/util/convert.cpp b/src/mbgl/util/convert.cpp
new file mode 100644
index 0000000000..97bfe9108d
--- /dev/null
+++ b/src/mbgl/util/convert.cpp
@@ -0,0 +1,9 @@
+#include <mbgl/util/convert.hpp>
+
+namespace mbgl {
+namespace util {
+
+template std::array<float, 2> convert(const std::array<int32_t, 2>&);
+
+} // namespace util
+} // namespace mbgl
diff --git a/src/mbgl/util/dtoa.cpp b/src/mbgl/util/dtoa.cpp
index 7ccee345f6..dd4fba0f89 100644
--- a/src/mbgl/util/dtoa.cpp
+++ b/src/mbgl/util/dtoa.cpp
@@ -9,7 +9,7 @@ namespace {
// From https://github.com/miloyip/rapidjson/blob/master/include/rapidjson/internal/dtoa.h
-inline char* Prettify(char* buffer, int length, int k) {
+char* Prettify(char* buffer, int length, int k) {
constexpr int maxDecimalPlaces = 324;
const int kk = length + k; // 10^(kk-1) <= v < 10^kk
@@ -93,5 +93,13 @@ char* dtoa(double value, char* buffer) {
}
}
+std::string dtoa(double value) {
+ std::string data;
+ data.resize(25);
+ auto end = dtoa(value, const_cast<char*>(data.data()));
+ data.resize(end - data.data());
+ return data;
+}
+
} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/util/dtoa.hpp b/src/mbgl/util/dtoa.hpp
index 17614732db..db7d309452 100644
--- a/src/mbgl/util/dtoa.hpp
+++ b/src/mbgl/util/dtoa.hpp
@@ -6,14 +6,7 @@ namespace mbgl {
namespace util {
char* dtoa(double value, char* buffer);
-
-inline std::string dtoa(double value) {
- std::string data;
- data.resize(25);
- auto end = dtoa(value, const_cast<char*>(data.data()));
- data.resize(end - data.data());
- return data;
-}
+std::string dtoa(double value);
} // end namespace util
} // end namespace mbgl
diff --git a/src/mbgl/util/exclusive.hpp b/src/mbgl/util/exclusive.hpp
index 946604af69..844588dc90 100644
--- a/src/mbgl/util/exclusive.hpp
+++ b/src/mbgl/util/exclusive.hpp
@@ -10,12 +10,12 @@ namespace util {
template <class T>
class exclusive {
public:
- inline exclusive(T* val, std::unique_ptr<std::lock_guard<std::mutex>> mtx) : ptr(val), lock(std::move(mtx)) {}
+ exclusive(T* val, std::unique_ptr<std::lock_guard<std::mutex>> mtx) : ptr(val), lock(std::move(mtx)) {}
- inline T* operator->() { return ptr; }
- inline const T* operator->() const { return ptr; }
- inline T* operator*() { return ptr; }
- inline const T* operator*() const { return ptr; }
+ T* operator->() { return ptr; }
+ const T* operator->() const { return ptr; }
+ T* operator*() { return ptr; }
+ const T* operator*() const { return ptr; }
private:
T *ptr;
diff --git a/src/mbgl/util/geo.cpp b/src/mbgl/util/geo.cpp
index dd40af882b..fe24334e82 100644
--- a/src/mbgl/util/geo.cpp
+++ b/src/mbgl/util/geo.cpp
@@ -8,12 +8,12 @@ namespace mbgl {
namespace {
-inline double lat(const uint8_t z, const int64_t y) {
+double lat(const uint8_t z, const int64_t y) {
const double n = M_PI - 2.0 * M_PI * y / std::pow(2.0, z);
return util::RAD2DEG * std::atan(0.5 * (std::exp(n) - std::exp(-n)));
}
-inline double lon(const uint8_t z, const int64_t x) {
+double lon(const uint8_t z, const int64_t x) {
return x / std::pow(2.0, z) * util::DEGREES_MAX - util::LONGITUDE_MAX;
}
diff --git a/src/mbgl/util/geojson.cpp b/src/mbgl/util/geojson.cpp
new file mode 100644
index 0000000000..a17d01f933
--- /dev/null
+++ b/src/mbgl/util/geojson.cpp
@@ -0,0 +1,11 @@
+#include <mbgl/util/geojson.hpp>
+
+#include <mapbox/geojsonvt.hpp>
+
+namespace mbgl {
+
+GeoJSON::GeoJSON(std::unique_ptr<mapbox::geojsonvt::GeoJSONVT> impl_) : impl(std::move(impl_)) {}
+GeoJSON::GeoJSON(GeoJSON&&) = default;
+GeoJSON::~GeoJSON() = default;
+
+} // namespace mbgl
diff --git a/src/mbgl/util/grid_index.cpp b/src/mbgl/util/grid_index.cpp
index 4877a90e72..cf1fcd68c9 100644
--- a/src/mbgl/util/grid_index.cpp
+++ b/src/mbgl/util/grid_index.cpp
@@ -17,7 +17,7 @@ GridIndex<T>::GridIndex(int32_t extent_, int32_t n_, int32_t padding_) :
max(extent + double(padding) / n * extent)
{
cells.resize(d * d);
- };
+ }
template <class T>
void GridIndex<T>::insert(T&& t, const BBox& bbox) {
@@ -79,4 +79,4 @@ int32_t GridIndex<T>::convertToCellCoord(int32_t x) const {
}
template class GridIndex<IndexedSubfeature>;
-}
+} // namespace mbgl
diff --git a/src/mbgl/util/grid_index.hpp b/src/mbgl/util/grid_index.hpp
index 656a4bdbd8..8ef8fb35b7 100644
--- a/src/mbgl/util/grid_index.hpp
+++ b/src/mbgl/util/grid_index.hpp
@@ -35,4 +35,4 @@ private:
};
-}
+} // namespace mbgl
diff --git a/src/mbgl/util/interpolate.hpp b/src/mbgl/util/interpolate.hpp
index 18a9e6bbc5..8b9929fa4a 100644
--- a/src/mbgl/util/interpolate.hpp
+++ b/src/mbgl/util/interpolate.hpp
@@ -5,6 +5,7 @@
#include <string>
#include <type_traits>
#include <utility>
+#include <mbgl/util/color.hpp>
namespace mbgl {
namespace util {
@@ -41,6 +42,19 @@ public:
}
};
+template <>
+struct Interpolator<Color> {
+public:
+ Color operator()(const Color& a, const Color& b, const double t) {
+ return {
+ interpolate(a.r, b.r, t),
+ interpolate(a.g, b.g, t),
+ interpolate(a.b, b.b, t),
+ interpolate(a.a, b.a, t)
+ };
+ }
+};
+
struct Uninterpolated {
template <class T>
T operator()(const T&, const T& b, const double) const {
diff --git a/src/mbgl/util/intersection_tests.cpp b/src/mbgl/util/intersection_tests.cpp
index 3e4ae27cd8..74b3bec388 100644
--- a/src/mbgl/util/intersection_tests.cpp
+++ b/src/mbgl/util/intersection_tests.cpp
@@ -143,5 +143,5 @@ bool multiPolygonIntersectsMultiPolygon(const GeometryCollection& multiPolygonA,
return false;
}
-}
-}
+} // namespace util
+} // namespace mbgl
diff --git a/src/mbgl/util/intersection_tests.hpp b/src/mbgl/util/intersection_tests.hpp
index a3ffe65cbf..be89d14ed6 100644
--- a/src/mbgl/util/intersection_tests.hpp
+++ b/src/mbgl/util/intersection_tests.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
namespace mbgl {
namespace util {
@@ -9,5 +9,5 @@ bool multiPolygonIntersectsBufferedMultiPoint(const GeometryCollection&, const G
bool multiPolygonIntersectsBufferedMultiLine(const GeometryCollection&, const GeometryCollection&, float radius);
bool multiPolygonIntersectsMultiPolygon(const GeometryCollection&, const GeometryCollection&);
-}
+} // namespace util
} // namespace mbgl
diff --git a/src/mbgl/util/io.hpp b/src/mbgl/util/io.hpp
index 2679eb5360..795a465328 100644
--- a/src/mbgl/util/io.hpp
+++ b/src/mbgl/util/io.hpp
@@ -7,7 +7,7 @@ namespace mbgl {
namespace util {
struct IOException : std::runtime_error {
- inline IOException(int err, const char* msg) : std::runtime_error(msg), code(err) {
+ IOException(int err, const char* msg) : std::runtime_error(msg), code(err) {
}
const int code = 0;
};
diff --git a/src/mbgl/util/mapbox.cpp b/src/mbgl/util/mapbox.cpp
index 41959563f0..97c28c0aeb 100644
--- a/src/mbgl/util/mapbox.cpp
+++ b/src/mbgl/util/mapbox.cpp
@@ -20,13 +20,14 @@ bool isMapboxURL(const std::string& url) {
std::vector<std::string> getMapboxURLPathname(const std::string& url) {
std::vector<std::string> pathname;
std::size_t startIndex = protocol.length();
- while (startIndex < url.length()) {
+ std::size_t end = url.find_first_of("?#");
+ if (end == std::string::npos) {
+ end = url.length();
+ }
+ while (startIndex < end) {
std::size_t endIndex = url.find("/", startIndex);
if (endIndex == std::string::npos) {
- endIndex = url.find_first_of("?#");
- }
- if (endIndex == std::string::npos) {
- endIndex = url.length();
+ endIndex = end;
}
pathname.push_back(url.substr(startIndex, endIndex - startIndex));
startIndex = endIndex + 1;
diff --git a/src/mbgl/util/mat2.cpp b/src/mbgl/util/mat2.cpp
index 6910244541..4fb5abafb8 100644
--- a/src/mbgl/util/mat2.cpp
+++ b/src/mbgl/util/mat2.cpp
@@ -24,7 +24,7 @@
#include <cmath>
-using namespace mbgl;
+namespace mbgl {
void matrix::identity(mat2& out) {
out[0] = 1.0f;
@@ -41,7 +41,7 @@ void matrix::rotate(mat2& out, const mat2& a, double rad) {
out[1] = a1 * c + a3 * s;
out[2] = a0 * -s + a2 * c;
out[3] = a1 * -s + a3 * c;
-};
+}
void matrix::scale(mat2& out, const mat2& a, double v0, double v1) {
double a0 = a[0], a1 = a[1], a2 = a[2], a3 = a[3];
@@ -50,3 +50,5 @@ void matrix::scale(mat2& out, const mat2& a, double v0, double v1) {
out[2] = a2 * v1;
out[3] = a3 * v1;
}
+
+} // namespace mbgl
diff --git a/src/mbgl/util/mat3.cpp b/src/mbgl/util/mat3.cpp
index f4ae8841d5..e2200867ce 100644
--- a/src/mbgl/util/mat3.cpp
+++ b/src/mbgl/util/mat3.cpp
@@ -24,7 +24,7 @@
#include <cmath>
-using namespace mbgl;
+namespace mbgl {
void matrix::identity(mat3& out) {
out[0] = 1.0f;
@@ -80,7 +80,7 @@ void matrix::rotate(mat3& out, const mat3& a, double rad) {
out[6] = a20;
out[7] = a21;
out[8] = a22;
-};
+}
void matrix::scale(mat3& out, const mat3& a, double x, double y) {
out[0] = x * a[0];
@@ -93,3 +93,5 @@ void matrix::scale(mat3& out, const mat3& a, double x, double y) {
out[7] = a[7];
out[8] = a[8];
}
+
+} // namespace mbgl
diff --git a/src/mbgl/util/math.cpp b/src/mbgl/util/math.cpp
index 0e86849ad3..7b1516c041 100644
--- a/src/mbgl/util/math.cpp
+++ b/src/mbgl/util/math.cpp
@@ -11,8 +11,8 @@ uint32_t ceil_log2(uint64_t x) {
uint32_t y = (((x & (x - 1)) == 0) ? 0 : 1);
uint32_t j = 32;
- for (int32_t i = 0; i < 6; i++) {
- const uint32_t k = (((x & t[i]) == 0) ? 0 : j);
+ for (const auto& i : t) {
+ const uint32_t k = (((x & i) == 0) ? 0 : j);
y += k;
x >>= k;
j >>= 1;
@@ -24,7 +24,7 @@ uint32_t ceil_log2(uint64_t x) {
double log2(double x) {
// log2() is producing wrong results on ARMv5 binaries
// running on ARMv7+ CPUs.
-#if defined(__ANDROID__) && defined(__ARM_ARCH_5TE__)
+#if defined(__ANDROID__)
return std::log(x) / 0.6931471805599453; // log(x) / log(2)
#else
return ::log2(x);
diff --git a/src/mbgl/util/math.hpp b/src/mbgl/util/math.hpp
index bfedc2a421..5d4220d0a2 100644
--- a/src/mbgl/util/math.hpp
+++ b/src/mbgl/util/math.hpp
@@ -14,18 +14,18 @@ namespace util {
// Find the angle of the two vectors, solving the formula for the cross product
// a x b = |a||b|sin(θ) for θ.
template <typename T = double, typename S>
-inline T angle_between(const Point<S>& a, const Point<S>& b) {
+T angle_between(const Point<S>& a, const Point<S>& b) {
return std::atan2((a.x * b.y - a.y * b.x), a.x * b.x + a.y * b.y);
}
template <typename T = double, typename S>
-inline T angle_to(const Point<S>& a, const Point<S>& b) {
+T angle_to(const Point<S>& a, const Point<S>& b) {
return std::atan2(a.y - b.y, a.x - b.x);
}
// Reflect an angle around 0 degrees
template <typename T>
-inline std::array<T, 2> flip(const std::array<T, 2>& c) {
+std::array<T, 2> flip(const std::array<T, 2>& c) {
return {{
static_cast<T>(2 * M_PI - c[0]),
static_cast<T>(2 * M_PI - c[1])
@@ -33,7 +33,7 @@ inline std::array<T, 2> flip(const std::array<T, 2>& c) {
}
template <typename T, typename S1, typename S2>
-inline Point<T> normal(const S1& a, const S2& b) {
+Point<T> normal(const S1& a, const S2& b) {
T dx = b.x - a.x;
T dy = b.y - a.y;
T c = std::sqrt(dx * dx + dy * dy);
@@ -41,12 +41,12 @@ inline Point<T> normal(const S1& a, const S2& b) {
}
template <typename T>
-inline T perp(const T& a) {
+T perp(const T& a) {
return T(-a.y, a.x);
}
template <typename T, typename S1, typename S2>
-inline T dist(const S1& a, const S2& b) {
+T dist(const S1& a, const S2& b) {
T dx = b.x - a.x;
T dy = b.y - a.y;
T c = std::sqrt(dx * dx + dy * dy);
@@ -54,7 +54,7 @@ inline T dist(const S1& a, const S2& b) {
}
template <typename T, typename S1, typename S2>
-inline T distSqr(const S1& a, const S2& b) {
+T distSqr(const S1& a, const S2& b) {
T dx = b.x - a.x;
T dy = b.y - a.y;
T c = dx * dx + dy * dy;
@@ -62,23 +62,23 @@ inline T distSqr(const S1& a, const S2& b) {
}
template <typename T>
-inline T round(const T& a) {
+T round(const T& a) {
return T(::round(a.x), ::round(a.y));
}
template <typename T>
-inline T length(T a, T b) {
+T length(T a, T b) {
return std::sqrt(a * a + b * b);
}
// Take the magnitude of vector a.
template <typename T = double, typename S>
-inline T mag(const S& a) {
+T mag(const S& a) {
return std::sqrt(a.x * a.x + a.y * a.y);
}
template <typename S>
-inline S unit(const S& a) {
+S unit(const S& a) {
auto magnitude = mag(a);
if (magnitude == 0) {
return a;
@@ -87,7 +87,7 @@ inline S unit(const S& a) {
}
template <typename T, typename S = double>
-inline T rotate(const T& a, S angle) {
+T rotate(const T& a, S angle) {
S cos = std::cos(angle);
S sin = std::sin(angle);
S x = cos * a.x - sin * a.y;
@@ -96,7 +96,7 @@ inline T rotate(const T& a, S angle) {
}
template <typename T>
-inline Point<T> matrixMultiply(const std::array<T, 4>& m, const Point<T>& p) {
+Point<T> matrixMultiply(const std::array<T, 4>& m, const Point<T>& p) {
return Point<T>(m[0] * p.x + m[1] * p.y, m[2] * p.x + m[3] * p.y);
}
diff --git a/src/mbgl/util/ptr.hpp b/src/mbgl/util/ptr.hpp
index 2dc8118181..87c4e9f7cf 100644
--- a/src/mbgl/util/ptr.hpp
+++ b/src/mbgl/util/ptr.hpp
@@ -10,14 +10,14 @@ template <typename T>
class ptr : public ::std::shared_ptr<T> {
public:
template <typename... Args>
- inline ptr(Args &&... args)
+ ptr(Args &&... args)
: ::std::shared_ptr<T>(::std::forward<Args>(args)...) {}
- inline auto operator->() const -> decltype(this->::std::shared_ptr<T>::operator->()) {
+ auto operator->() const -> decltype(this->::std::shared_ptr<T>::operator->()) {
assert(*this);
return ::std::shared_ptr<T>::operator->();
}
- inline auto operator*() const -> decltype(this->::std::shared_ptr<T>::operator*()) {
+ auto operator*() const -> decltype(this->::std::shared_ptr<T>::operator*()) {
assert(*this);
return ::std::shared_ptr<T>::operator*();
}
diff --git a/src/mbgl/util/raster.cpp b/src/mbgl/util/raster.cpp
index 3146a00513..7417c8bcd5 100644
--- a/src/mbgl/util/raster.cpp
+++ b/src/mbgl/util/raster.cpp
@@ -7,59 +7,71 @@
#include <cassert>
#include <cstring>
-using namespace mbgl;
-
-Raster::Raster(gl::TexturePool& texturePool_)
- : texturePool(texturePool_)
-{}
+namespace mbgl {
bool Raster::isLoaded() const {
- std::lock_guard<std::mutex> lock(mtx);
return loaded;
}
-void Raster::load(PremultipliedImage image) {
+void Raster::load(PremultipliedImage image, uint32_t mipmapLevel) {
assert(image.data.get());
- img = std::move(image);
- width = GLsizei(img.width);
- height = GLsizei(img.height);
+ if (images.size() <= mipmapLevel) {
+ images.resize(mipmapLevel + 1);
+ }
+ images.at(mipmapLevel) = std::move(image);
- std::lock_guard<std::mutex> lock(mtx);
loaded = true;
}
+void Raster::bind(gl::ObjectStore& store, Scaling newFilter, MipMap newMipMap) {
+ bool updateFilter = false;
-void Raster::bind(bool linear, gl::ObjectStore& store) {
- if (!width || !height) {
- Log::Error(Event::OpenGL, "trying to bind texture without dimension");
- return;
- }
-
- if (img.data && !texture) {
- upload(store);
- } else if (texture) {
+ if (!texture) {
+ if (images.empty()) {
+ Log::Error(Event::OpenGL, "trying to bind texture without images");
+ return;
+ } else {
+ upload(store);
+ updateFilter = true;
+ }
+ } else {
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
+ updateFilter = (filter != newFilter || mipmap != newMipMap);
}
- GLint new_filter = linear ? GL_LINEAR : GL_NEAREST;
- if (new_filter != this->filter) {
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, new_filter));
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, new_filter));
- filter = new_filter;
+ if (updateFilter) {
+ filter = newFilter;
+ mipmap = newMipMap;
+ MBGL_CHECK_ERROR(glTexParameteri(
+ GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
+ filter == Scaling::Linear
+ ? (mipmap == MipMap::Yes ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR)
+ : (mipmap == MipMap::Yes ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
+ filter == Scaling::Linear ? GL_LINEAR : GL_NEAREST));
}
}
void Raster::upload(gl::ObjectStore& store) {
- if (img.data && !texture) {
- texture = texturePool.acquireTexture(store);
+ if (!images.empty() && !texture) {
+ texture = store.createTexture();
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, *texture));
#ifndef GL_ES_VERSION_2_0
- MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0));
+ MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, images.size()));
#endif
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
MBGL_CHECK_ERROR(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
- MBGL_CHECK_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data.get()));
- img.data.reset();
+ GLint level = 0;
+ for (auto& img : images) {
+ assert(img.data.get());
+ MBGL_CHECK_ERROR(glTexImage2D(
+ GL_TEXTURE_2D, level++, GL_RGBA, static_cast<GLsizei>(img.width),
+ static_cast<GLsizei>(img.height), 0, GL_RGBA, GL_UNSIGNED_BYTE, img.data.get()));
+ }
+ images.clear();
+ images.shrink_to_fit();
}
}
+
+} // namespace mbgl
diff --git a/src/mbgl/util/raster.hpp b/src/mbgl/util/raster.hpp
index b539032d81..6223440bd6 100644
--- a/src/mbgl/util/raster.hpp
+++ b/src/mbgl/util/raster.hpp
@@ -1,26 +1,22 @@
#pragma once
-#include <mbgl/gl/gl.hpp>
-#include <mbgl/gl/texture_pool.hpp>
+#include <mbgl/gl/object_store.hpp>
#include <mbgl/util/image.hpp>
-#include <mbgl/util/ptr.hpp>
-#include <mbgl/util/chrono.hpp>
#include <mbgl/util/optional.hpp>
-
-#include <mutex>
+#include <mbgl/util/atomic.hpp>
namespace mbgl {
-class Raster : public std::enable_shared_from_this<Raster> {
-
+class Raster {
public:
- Raster(gl::TexturePool&);
+ enum class MipMap : bool { No = false, Yes = true };
+ enum class Scaling : bool { Nearest = false, Linear = true };
// load image data
- void load(PremultipliedImage);
+ void load(PremultipliedImage, uint32_t mipmapLevel = 0);
// bind current texture
- void bind(bool linear, gl::ObjectStore&);
+ void bind(gl::ObjectStore&, Scaling = Scaling::Nearest, MipMap = MipMap::No);
// uploads the texture if it hasn't been uploaded yet.
void upload(gl::ObjectStore&);
@@ -28,31 +24,19 @@ public:
// loaded status
bool isLoaded() const;
-public:
- // loaded image dimensions
- GLsizei width = 0;
- GLsizei height = 0;
-
- // GL buffer object handle.
- mbgl::optional<gl::PooledTexture> texture;
-
- // texture opacity
- double opacity = 0;
-
private:
- mutable std::mutex mtx;
-
// raw pixels have been loaded
- bool loaded = false;
-
- // shared texture pool
- gl::TexturePool& texturePool;
+ util::Atomic<bool> loaded { false };
- // min/mag filter
- GLint filter = 0;
+ // filters
+ Scaling filter = Scaling::Nearest;
+ MipMap mipmap = MipMap::No;
// the raw pixels
- PremultipliedImage img;
+ std::vector<PremultipliedImage> images;
+
+ // GL buffer object handle.
+ mbgl::optional<gl::UniqueTexture> texture;
};
} // namespace mbgl
diff --git a/src/mbgl/util/rect.hpp b/src/mbgl/util/rect.hpp
index 2b877db40d..f5937f5c94 100644
--- a/src/mbgl/util/rect.hpp
+++ b/src/mbgl/util/rect.hpp
@@ -4,21 +4,21 @@ namespace mbgl {
template <typename T>
struct Rect {
- inline Rect() = default;
- inline Rect(T x_, T y_, T w_, T h_) : x(x_), y(y_), w(w_), h(h_) {}
+ Rect() = default;
+ Rect(T x_, T y_, T w_, T h_) : x(x_), y(y_), w(w_), h(h_) {}
T x = 0, y = 0;
T w = 0, h = 0;
template <typename Number>
- inline Rect operator *(Number value) const {
+ Rect operator *(Number value) const {
return Rect(x * value, y * value, w * value, h * value);
}
template <typename R>
- inline bool operator==(const R& r) const {
+ bool operator==(const R& r) const {
return x == r.x && y == r.y && w == r.w && h == r.h;
}
- inline bool hasArea() const { return w != 0 && h != 0; }
+ bool hasArea() const { return w != 0 && h != 0; }
};
} // namespace mbgl
diff --git a/src/mbgl/util/stopwatch.cpp b/src/mbgl/util/stopwatch.cpp
index bbc6bfba0c..d588b79254 100644
--- a/src/mbgl/util/stopwatch.cpp
+++ b/src/mbgl/util/stopwatch.cpp
@@ -7,7 +7,8 @@
#include <iostream>
#include <atomic>
-using namespace mbgl::util;
+namespace mbgl {
+namespace util {
stopwatch::stopwatch(Event event_)
: event(event_), start(Clock::now()) {}
@@ -15,11 +16,11 @@ stopwatch::stopwatch(Event event_)
stopwatch::stopwatch(EventSeverity severity_, Event event_)
: severity(severity_), event(event_), start(Clock::now()) {}
-stopwatch::stopwatch(const std::string &name_, Event event_)
- : name(name_), event(event_), start(Clock::now()) {}
+stopwatch::stopwatch(std::string name_, Event event_)
+ : name(std::move(name_)), event(event_), start(Clock::now()) {}
-stopwatch::stopwatch(const std::string &name_, EventSeverity severity_, Event event_)
- : name(name_), severity(severity_), event(event_), start(Clock::now()) {}
+stopwatch::stopwatch(std::string name_, EventSeverity severity_, Event event_)
+ : name(std::move(name_)), severity(severity_), event(event_), start(Clock::now()) {}
void stopwatch::report(const std::string &name_) {
Duration duration = Clock::now() - start;
@@ -33,4 +34,8 @@ stopwatch::~stopwatch() {
report(name);
}
}
+
+} // namespace util
+} // namespace mbgl
+
#endif
diff --git a/src/mbgl/util/stopwatch.hpp b/src/mbgl/util/stopwatch.hpp
index 23086b1747..74cc2c412d 100644
--- a/src/mbgl/util/stopwatch.hpp
+++ b/src/mbgl/util/stopwatch.hpp
@@ -13,8 +13,8 @@ class stopwatch {
public:
stopwatch(Event event = Event::General);
stopwatch(EventSeverity severity, Event event = Event::General);
- stopwatch(const std::string &name, Event event = Event::General);
- stopwatch(const std::string &name, EventSeverity severity, Event event = Event::General);
+ stopwatch(std::string name, Event event = Event::General);
+ stopwatch(std::string name, EventSeverity severity, Event event = Event::General);
void report(const std::string &name);
~stopwatch();
@@ -26,12 +26,12 @@ private:
};
#else
class stopwatch {
- inline stopwatch(Event event = Event::General);
- inline stopwatch(EventSeverity severity, Event event = Event::General);
- inline stopwatch(const std::string &name, Event event = Event::General);
- inline stopwatch(const std::string &name, EventSeverity severity, Event event = Event::General);
- inline void report(const std::string &name) {}
- inline ~stopwatch() {}
+ stopwatch(Event event = Event::General);
+ stopwatch(EventSeverity severity, Event event = Event::General);
+ stopwatch(const std::string &name, Event event = Event::General);
+ stopwatch(const std::string &name, EventSeverity severity, Event event = Event::General);
+ void report(const std::string &name) {}
+ ~stopwatch() {}
};
#endif
} // namespace util
diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp
index c5f9d7338a..0de897d726 100644
--- a/src/mbgl/util/thread.hpp
+++ b/src/mbgl/util/thread.hpp
@@ -87,6 +87,29 @@ private:
RunLoop* loop = nullptr;
};
+inline std::string getCurrentThreadName() {
+ char name[32] = "unknown";
+#if defined(__APPLE__)
+ pthread_getname_np(pthread_self(), name, sizeof(name));
+#elif defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+#if __GLIBC_PREREQ(2, 12)
+ pthread_getname_np(pthread_self(), name, sizeof(name));
+#endif
+#endif
+ return name;
+}
+
+inline void setCurrentThreadName(const std::string& name) {
+#if defined(__APPLE__)
+ pthread_setname_np(name.c_str());
+#elif defined(__GLIBC__) && defined(__GLIBC_PREREQ)
+#if __GLIBC_PREREQ(2, 12)
+ pthread_setname_np(pthread_self(), name.c_str());
+#endif
+#endif
+ (void)name;
+}
+
template <class Object>
template <class... Args>
Thread<Object>::Thread(const ThreadContext& context, Args&&... args) {
@@ -95,13 +118,7 @@ Thread<Object>::Thread(const ThreadContext& context, Args&&... args) {
std::tuple<Args...> params = std::forward_as_tuple(::std::forward<Args>(args)...);
thread = std::thread([&] {
-#if defined(__APPLE__)
- pthread_setname_np(context.name.c_str());
-#elif defined(__GLIBC__) && defined(__GLIBC_PREREQ)
-#if __GLIBC_PREREQ(2, 12)
- pthread_setname_np(pthread_self(), context.name.c_str());
-#endif
-#endif
+ setCurrentThreadName(context.name);
if (context.priority == ThreadPriority::Low) {
platform::makeThreadLowPriority();
diff --git a/src/mbgl/util/thread_context.cpp b/src/mbgl/util/thread_context.cpp
index f728e32df7..fe64c2a686 100644
--- a/src/mbgl/util/thread_context.cpp
+++ b/src/mbgl/util/thread_context.cpp
@@ -1,10 +1,11 @@
#include <mbgl/util/thread_context.hpp>
+#include <utility>
namespace mbgl {
namespace util {
-ThreadContext::ThreadContext(const std::string& name_, ThreadPriority priority_)
- : name(name_),
+ThreadContext::ThreadContext(std::string name_, ThreadPriority priority_)
+ : name(std::move(name_)),
priority(priority_) {
}
diff --git a/src/mbgl/util/thread_context.hpp b/src/mbgl/util/thread_context.hpp
index 60b32b3b2a..a51dede404 100644
--- a/src/mbgl/util/thread_context.hpp
+++ b/src/mbgl/util/thread_context.hpp
@@ -12,7 +12,7 @@ enum class ThreadPriority : bool {
struct ThreadContext {
public:
- ThreadContext(const std::string& name, ThreadPriority priority = ThreadPriority::Regular);
+ ThreadContext(std::string name, ThreadPriority priority = ThreadPriority::Regular);
std::string name;
ThreadPriority priority;
diff --git a/src/mbgl/util/thread_local.hpp b/src/mbgl/util/thread_local.hpp
index c3364c5d42..67e3842ec6 100644
--- a/src/mbgl/util/thread_local.hpp
+++ b/src/mbgl/util/thread_local.hpp
@@ -12,12 +12,12 @@ namespace util {
template <class T>
class ThreadLocal : public noncopyable {
public:
- inline ThreadLocal(T* val) {
+ ThreadLocal(T* val) {
ThreadLocal();
set(val);
}
- inline ThreadLocal() {
+ ThreadLocal() {
int ret = pthread_key_create(&key, [](void *ptr) {
delete reinterpret_cast<T *>(ptr);
});
@@ -27,13 +27,13 @@ public:
}
}
- inline ~ThreadLocal() {
+ ~ThreadLocal() {
if (pthread_key_delete(key)) {
throw std::runtime_error("Failed to delete local storage key.");
}
}
- inline T* get() {
+ T* get() {
T* ret = reinterpret_cast<T*>(pthread_getspecific(key));
if (!ret) {
return nullptr;
@@ -42,7 +42,7 @@ public:
return ret;
}
- inline void set(T* ptr) {
+ void set(T* ptr) {
if (pthread_setspecific(key, ptr)) {
throw std::runtime_error("Failed to set local storage.");
}
diff --git a/src/mbgl/util/tile_coordinate.cpp b/src/mbgl/util/tile_coordinate.cpp
deleted file mode 100644
index d9a0ea352c..0000000000
--- a/src/mbgl/util/tile_coordinate.cpp
+++ /dev/null
@@ -1 +0,0 @@
-#include <mbgl/util/tile_coordinate.hpp>
diff --git a/src/mbgl/util/tileset.hpp b/src/mbgl/util/tileset.hpp
deleted file mode 100644
index 972fc51f8c..0000000000
--- a/src/mbgl/util/tileset.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <mbgl/util/constants.hpp>
-#include <mbgl/util/geo.hpp>
-
-#include <array>
-#include <vector>
-#include <string>
-#include <cstdint>
-
-namespace mbgl {
-
-class Tileset {
-public:
- std::vector<std::string> tiles;
- uint8_t minZoom = 0;
- uint8_t maxZoom = 22;
- std::string attribution;
- LatLng center;
- double zoom = 0;
- LatLngBounds bounds = LatLngBounds::world();
-};
-
-} // namespace mbgl
diff --git a/src/mbgl/util/utf.hpp b/src/mbgl/util/utf.hpp
index 02aabfc4c2..560ca3ba7f 100644
--- a/src/mbgl/util/utf.hpp
+++ b/src/mbgl/util/utf.hpp
@@ -17,5 +17,5 @@ class utf8_to_utf32 {
}
};
-} // namespace mbgl
} // namespace util
+} // namespace mbgl
diff --git a/src/mbgl/util/version_info.cpp b/src/mbgl/util/version_info.cpp
index c545ddcc40..f0fb139bca 100644
--- a/src/mbgl/util/version_info.cpp
+++ b/src/mbgl/util/version_info.cpp
@@ -11,4 +11,4 @@ const char *string = MBGL_VERSION_STRING;
const unsigned int number = MBGL_VERSION;
} // namespace version
-} // namespace mbgl \ No newline at end of file
+} // namespace mbgl
diff --git a/src/mbgl/util/work_task.cpp b/src/mbgl/util/work_task.cpp
deleted file mode 100644
index e69de29bb2..0000000000
--- a/src/mbgl/util/work_task.cpp
+++ /dev/null
diff --git a/src/mbgl/util/worker.cpp b/src/mbgl/util/worker.cpp
index 2bc545c704..50ecb93c02 100644
--- a/src/mbgl/util/worker.cpp
+++ b/src/mbgl/util/worker.cpp
@@ -3,7 +3,7 @@
#include <mbgl/util/work_request.hpp>
#include <mbgl/platform/platform.hpp>
#include <mbgl/renderer/raster_bucket.hpp>
-#include <mbgl/tile/geometry_tile.hpp>
+#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/text/collision_tile.hpp>
@@ -31,11 +31,11 @@ public:
void parseGeometryTile(TileWorker* worker,
std::vector<std::unique_ptr<style::Layer>> layers,
- std::unique_ptr<GeometryTile> tile,
+ std::unique_ptr<GeometryTileData> tileData,
PlacementConfig config,
std::function<void(TileParseResult)> callback) {
try {
- callback(worker->parseAllLayers(std::move(layers), std::move(tile), config));
+ callback(worker->parseAllLayers(std::move(layers), std::move(tileData), config));
} catch (...) {
callback(std::current_exception());
}
@@ -80,12 +80,12 @@ Worker::parseRasterTile(std::unique_ptr<RasterBucket> bucket,
std::unique_ptr<AsyncRequest>
Worker::parseGeometryTile(TileWorker& worker,
std::vector<std::unique_ptr<style::Layer>> layers,
- std::unique_ptr<GeometryTile> tile,
+ std::unique_ptr<GeometryTileData> tileData,
PlacementConfig config,
std::function<void(TileParseResult)> callback) {
current = (current + 1) % threads.size();
return threads[current]->invokeWithCallback(&Worker::Impl::parseGeometryTile, callback, &worker,
- std::move(layers), std::move(tile), config);
+ std::move(layers), std::move(tileData), config);
}
std::unique_ptr<AsyncRequest>
diff --git a/src/mbgl/util/worker.hpp b/src/mbgl/util/worker.hpp
index 678dfaedb3..5ab86d1b9e 100644
--- a/src/mbgl/util/worker.hpp
+++ b/src/mbgl/util/worker.hpp
@@ -41,7 +41,7 @@ public:
Request parseGeometryTile(TileWorker&,
std::vector<std::unique_ptr<style::Layer>>,
- std::unique_ptr<GeometryTile>,
+ std::unique_ptr<GeometryTileData>,
PlacementConfig,
std::function<void(TileParseResult)> callback);