summaryrefslogtreecommitdiff
path: root/src/mbgl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mbgl')
-rw-r--r--src/mbgl/geometry/line_atlas.cpp29
-rw-r--r--src/mbgl/geometry/line_atlas.hpp2
-rw-r--r--src/mbgl/geometry/sprite_atlas.cpp32
-rw-r--r--src/mbgl/geometry/static_vertex_buffer.cpp2
-rw-r--r--src/mbgl/map/map.cpp136
-rw-r--r--src/mbgl/map/source.cpp24
-rw-r--r--src/mbgl/map/tile_data.hpp14
-rw-r--r--src/mbgl/map/tile_parser.cpp142
-rw-r--r--src/mbgl/map/tile_parser.hpp3
-rw-r--r--src/mbgl/map/vector_tile.cpp48
-rw-r--r--src/mbgl/map/vector_tile.hpp2
-rw-r--r--src/mbgl/renderer/debug_bucket.cpp2
-rw-r--r--src/mbgl/renderer/fill_bucket.cpp13
-rw-r--r--src/mbgl/renderer/fill_bucket.hpp6
-rw-r--r--src/mbgl/renderer/line_bucket.cpp14
-rw-r--r--src/mbgl/renderer/line_bucket.hpp7
-rw-r--r--src/mbgl/renderer/painter.cpp33
-rw-r--r--src/mbgl/renderer/painter.hpp2
-rw-r--r--src/mbgl/renderer/painter_clipping.cpp2
-rw-r--r--src/mbgl/renderer/painter_debug.cpp2
-rw-r--r--src/mbgl/renderer/painter_line.cpp2
-rw-r--r--src/mbgl/renderer/painter_raster.cpp1
-rw-r--r--src/mbgl/renderer/painter_symbol.cpp2
-rw-r--r--src/mbgl/renderer/symbol_bucket.cpp16
-rw-r--r--src/mbgl/renderer/symbol_bucket.hpp6
-rw-r--r--src/mbgl/style/style.cpp33
-rw-r--r--src/mbgl/style/style.hpp21
-rw-r--r--src/mbgl/style/style_layer.cpp11
-rw-r--r--src/mbgl/style/style_layer.hpp4
-rw-r--r--src/mbgl/style/style_layer_group.cpp34
-rw-r--r--src/mbgl/style/style_layer_group.hpp24
-rw-r--r--src/mbgl/style/style_parser.cpp96
-rw-r--r--src/mbgl/style/style_parser.hpp14
-rw-r--r--src/mbgl/text/collision.cpp12
-rw-r--r--src/mbgl/text/collision.hpp1
-rw-r--r--src/mbgl/text/glyph_store.cpp6
-rw-r--r--src/mbgl/text/placement.cpp8
-rw-r--r--src/mbgl/text/rotation_range.cpp2
-rw-r--r--src/mbgl/util/clip_ids.cpp6
-rw-r--r--src/mbgl/util/mapbox.cpp18
-rw-r--r--src/mbgl/util/mapbox.hpp1
-rw-r--r--src/mbgl/util/merge_lines.cpp46
-rw-r--r--src/mbgl/util/scaling.cpp27
-rw-r--r--src/mbgl/util/scaling.hpp2
44 files changed, 420 insertions, 488 deletions
diff --git a/src/mbgl/geometry/line_atlas.cpp b/src/mbgl/geometry/line_atlas.cpp
index 507cc7b087..f64989d661 100644
--- a/src/mbgl/geometry/line_atlas.cpp
+++ b/src/mbgl/geometry/line_atlas.cpp
@@ -4,6 +4,8 @@
#include <mbgl/platform/log.hpp>
#include <mbgl/platform/platform.hpp>
+#include <boost/functional/hash.hpp>
+
#include <sstream>
#include <cmath>
@@ -26,21 +28,22 @@ LineAtlas::~LineAtlas() {
}
LinePatternPos LineAtlas::getDashPosition(const std::vector<float> &dasharray, bool round) {
- std::lock_guard<std::recursive_mutex> lock(mtx);
-
- std::ostringstream sskey;
-
- for (const float &part : dasharray) {
- sskey << part << "-";
+ size_t key = round ? std::numeric_limits<size_t>::min() : std::numeric_limits<size_t>::max();
+ for (const float part : dasharray) {
+ boost::hash_combine<float>(key, part);
}
- sskey << round;
- std::string key = sskey.str();
- if (positions.find(key) == positions.end()) {
- positions[key] = addDash(dasharray, round);
- }
+ // Note: We're not handling hash collisions here.
- return positions[key];
+ std::lock_guard<std::recursive_mutex> lock(mtx);
+ const auto it = positions.find(key);
+ if (it == positions.end()) {
+ auto inserted = positions.emplace(key, addDash(dasharray, round));
+ assert(inserted.second);
+ return inserted.first->second;
+ } else {
+ return it->second;
+ }
}
LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool round) {
@@ -55,7 +58,7 @@ LinePatternPos LineAtlas::addDash(const std::vector<float> &dasharray, bool roun
}
float length = 0;
- for (const float &part : dasharray) {
+ for (const float part : dasharray) {
length += part;
}
diff --git a/src/mbgl/geometry/line_atlas.hpp b/src/mbgl/geometry/line_atlas.hpp
index 191dc0c4d4..df60a2dec5 100644
--- a/src/mbgl/geometry/line_atlas.hpp
+++ b/src/mbgl/geometry/line_atlas.hpp
@@ -33,7 +33,7 @@ private:
std::atomic<bool> dirty;
uint32_t texture = 0;
int nextRow = 0;
- std::map<std::string, LinePatternPos> positions;
+ std::map<size_t, LinePatternPos> positions;
};
};
diff --git a/src/mbgl/geometry/sprite_atlas.cpp b/src/mbgl/geometry/sprite_atlas.cpp
index bf31c6e38e..c2686e2f34 100644
--- a/src/mbgl/geometry/sprite_atlas.cpp
+++ b/src/mbgl/geometry/sprite_atlas.cpp
@@ -73,7 +73,7 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(const size_t pixel_width
// This is so we can scale down the texture coordinates and pack them
// into 2 bytes rather than 4 bytes.
const uint16_t pack_width = (pixel_width + 1) + (4 - (pixel_width + 1) % 4);
- const uint16_t pack_height = (pixel_height + 1) + (4 - (pixel_width + 1) % 4);
+ const uint16_t pack_height = (pixel_height + 1) + (4 - (pixel_height + 1) % 4);
// We have to allocate a new area in the bin, and store an empty image in it.
// Add a 1px border around every image.
@@ -165,37 +165,37 @@ void SpriteAtlas::copy(const Rect<dimension>& dst, const SpritePosition& src, co
static_cast<uint32_t>(dst.originalW * pixelRatio),
static_cast<uint32_t>(dst.originalH * pixelRatio) };
- util::bilinearScale(srcData, srcSize, srcPos, dstData, dstSize, dstPos);
+ util::bilinearScale(srcData, srcSize, srcPos, dstData, dstSize, dstPos, wrap);
// Add borders around the copied image if required.
if (wrap) {
// We're copying from the same image so we don't have to scale again.
const uint32_t border = 1;
+ const uint32_t borderX = dstPos.x != 0 ? border : 0;
+ const uint32_t borderY = dstPos.y != 0 ? border : 0;
+
// Left border
- if (dstPos.x >= border) {
- util::nearestNeighborScale(
- dstData, dstSize, { dstPos.x + dstPos.w - border - 1, dstPos.y, border, dstPos.h },
- dstData, dstSize, { dstPos.x - border, dstPos.y, border, dstPos.h });
- }
+ util::nearestNeighborScale(
+ dstData, dstSize, { dstPos.x + dstPos.w - borderX, dstPos.y, borderX, dstPos.h },
+ dstData, dstSize, { dstPos.x - borderX, dstPos.y, borderX, dstPos.h });
+
// Right border
util::nearestNeighborScale(dstData, dstSize, { dstPos.x, dstPos.y, border, dstPos.h },
dstData, dstSize,
{ dstPos.x + dstPos.w, dstPos.y, border, dstPos.h });
// Top border
- if (dstPos.y >= border) {
- util::nearestNeighborScale(
- dstData, dstSize, { dstPos.x - border, dstPos.y + dstPos.h - border - 1,
- dstPos.w + 2 * border, border },
- dstData, dstSize,
- { dstPos.x - border, dstPos.y - border, dstPos.w + 2 * border, border });
- }
+ util::nearestNeighborScale(
+ dstData, dstSize, { dstPos.x - borderX, dstPos.y + dstPos.h - borderY,
+ dstPos.w + border + borderX, borderY },
+ dstData, dstSize,
+ { dstPos.x - borderX, dstPos.y - borderY, dstPos.w + 2 * borderX, borderY });
// Bottom border
util::nearestNeighborScale(
- dstData, dstSize, { dstPos.x - border, dstPos.y, dstPos.w + 2 * border, border },
+ dstData, dstSize, { dstPos.x - borderX, dstPos.y, dstPos.w + 2 * borderX, border },
dstData, dstSize,
- { dstPos.x - border, dstPos.y + dstPos.h, dstPos.w + 2 * border, border });
+ { dstPos.x - borderX, dstPos.y + dstPos.h, dstPos.w + border + borderX, border });
}
dirty = true;
diff --git a/src/mbgl/geometry/static_vertex_buffer.cpp b/src/mbgl/geometry/static_vertex_buffer.cpp
index c86211c50f..c1e8caab9e 100644
--- a/src/mbgl/geometry/static_vertex_buffer.cpp
+++ b/src/mbgl/geometry/static_vertex_buffer.cpp
@@ -4,7 +4,7 @@
namespace mbgl {
StaticVertexBuffer::StaticVertexBuffer(std::initializer_list<std::pair<int16_t, int16_t>> init) {
- for (const std::pair<int16_t, int16_t> &vertex : init) {
+ for (const auto& vertex : init) {
vertex_type *vertices = static_cast<vertex_type *>(addElement());
vertices[0] = vertex.first;
vertices[1] = vertex.second;
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 24f72e8dca..c4ad6efc53 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -18,7 +18,6 @@
#include <mbgl/text/glyph_store.hpp>
#include <mbgl/geometry/glyph_atlas.hpp>
#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_layer_group.hpp>
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/util/texture_pool.hpp>
#include <mbgl/geometry/sprite_atlas.hpp>
@@ -129,14 +128,22 @@ void Map::start(bool startPaused) {
// Remove all of these to make sure they are destructed in the correct thread.
style.reset();
+
+ // Since we don't have a stylesheet anymore, this will disable all Sources and cancel
+ // their associated requests.
+ updateSources();
+ assert(activeSources.empty());
+
+ // It's now safe to destroy/join the workers since there won't be any more callbacks that
+ // could dispatch to the worker pool.
workers.reset();
- activeSources.clear();
terminating = true;
// Closes all open handles on the loop. This means that the loop will automatically terminate.
asyncRender.reset();
asyncUpdate.reset();
+ asyncInvoke.reset();
asyncTerminate.reset();
});
@@ -144,6 +151,10 @@ void Map::start(bool startPaused) {
update();
});
+ asyncInvoke = util::make_unique<uv::async>(env->loop, [this] {
+ processTasks();
+ });
+
asyncRender = util::make_unique<uv::async>(env->loop, [this] {
// Must be called in Map thread.
assert(Environment::currentlyOn(ThreadType::Map));
@@ -315,6 +326,42 @@ void Map::triggerRender() {
asyncRender->send();
}
+// Runs the function in the map thread.
+void Map::invokeTask(std::function<void()>&& fn) {
+ {
+ std::lock_guard<std::mutex> lock(mutexTask);
+ tasks.emplace(::std::forward<std::function<void()>>(fn));
+ }
+
+ // TODO: Once we have aligned static and continuous rendering, this should always dispatch
+ // to the async queue.
+ if (asyncInvoke) {
+ asyncInvoke->send();
+ } else {
+ processTasks();
+ }
+}
+
+template <typename Fn> auto Map::invokeSyncTask(const Fn& fn) -> decltype(fn()) {
+ std::promise<decltype(fn())> promise;
+ invokeTask([&fn, &promise] { promise.set_value(fn()); });
+ return promise.get_future().get();
+}
+
+// Processes the functions that should be run in the map thread.
+void Map::processTasks() {
+ std::queue<std::function<void()>> queue;
+ {
+ std::lock_guard<std::mutex> lock(mutexTask);
+ queue.swap(tasks);
+ }
+
+ while (!queue.empty()) {
+ queue.front()();
+ queue.pop();
+ }
+}
+
void Map::checkForPause() {
std::unique_lock<std::mutex> lockRun (mutexRun);
while (pausing) {
@@ -352,13 +399,15 @@ void Map::setup() {
void Map::setStyleURL(const std::string &url) {
assert(Environment::currentlyOn(ThreadType::Main));
- const size_t pos = url.rfind('/');
+ const std::string styleURL = mbgl::util::mapbox::normalizeStyleURL(url, getAccessToken());
+
+ const size_t pos = styleURL.rfind('/');
std::string base = "";
if (pos != std::string::npos) {
- base = url.substr(0, pos + 1);
+ base = styleURL.substr(0, pos + 1);
}
- data->setStyleInfo({ url, base, "" });
+ data->setStyleInfo({ styleURL, base, "" });
triggerUpdate(Update::StyleInfo);
}
@@ -542,21 +591,31 @@ std::string Map::getAccessToken() const {
void Map::setDefaultPointAnnotationSymbol(const std::string& symbol) {
assert(Environment::currentlyOn(ThreadType::Main));
- annotationManager->setDefaultPointAnnotationSymbol(symbol);
+ invokeTask([=] {
+ annotationManager->setDefaultPointAnnotationSymbol(symbol);
+ });
}
-uint32_t Map::addPointAnnotation(const LatLng& point, const std::string& symbol) {
+double Map::getTopOffsetPixelsForAnnotationSymbol(const std::string& symbol) {
assert(Environment::currentlyOn(ThreadType::Main));
- std::vector<LatLng> points({ point });
- std::vector<std::string> symbols({ symbol });
- return addPointAnnotations(points, symbols)[0];
+ return invokeSyncTask([&] {
+ assert(sprite);
+ const SpritePosition pos = sprite->getSpritePosition(symbol);
+ return -pos.height / pos.pixelRatio / 2;
+ });
+}
+
+uint32_t Map::addPointAnnotation(const LatLng& point, const std::string& symbol) {
+ return addPointAnnotations({ point }, { symbol }).front();
}
std::vector<uint32_t> Map::addPointAnnotations(const std::vector<LatLng>& points, const std::vector<std::string>& symbols) {
assert(Environment::currentlyOn(ThreadType::Main));
- auto result = annotationManager->addPointAnnotations(points, symbols, *this);
- updateAnnotationTiles(result.first);
- return result.second;
+ return invokeSyncTask([&] {
+ auto result = annotationManager->addPointAnnotations(points, symbols, *this);
+ updateAnnotationTiles(result.first);
+ return result.second;
+ });
}
void Map::removeAnnotation(uint32_t annotation) {
@@ -566,22 +625,28 @@ void Map::removeAnnotation(uint32_t annotation) {
void Map::removeAnnotations(const std::vector<uint32_t>& annotations) {
assert(Environment::currentlyOn(ThreadType::Main));
- auto result = annotationManager->removeAnnotations(annotations, *this);
- updateAnnotationTiles(result);
+ invokeTask([=] {
+ auto result = annotationManager->removeAnnotations(annotations, *this);
+ updateAnnotationTiles(result);
+ });
}
-std::vector<uint32_t> Map::getAnnotationsInBounds(const LatLngBounds& bounds) const {
+std::vector<uint32_t> Map::getAnnotationsInBounds(const LatLngBounds& bounds) {
assert(Environment::currentlyOn(ThreadType::Main));
- return annotationManager->getAnnotationsInBounds(bounds, *this);
+ return invokeSyncTask([&] {
+ return annotationManager->getAnnotationsInBounds(bounds, *this);
+ });
}
-LatLngBounds Map::getBoundsForAnnotations(const std::vector<uint32_t>& annotations) const {
+LatLngBounds Map::getBoundsForAnnotations(const std::vector<uint32_t>& annotations) {
assert(Environment::currentlyOn(ThreadType::Main));
- return annotationManager->getBoundsForAnnotations(annotations);
+ return invokeSyncTask([&] {
+ return annotationManager->getBoundsForAnnotations(annotations);
+ });
}
void Map::updateAnnotationTiles(const std::vector<Tile::ID>& ids) {
- assert(Environment::currentlyOn(ThreadType::Main));
+ assert(Environment::currentlyOn(ThreadType::Map));
for (const auto &source : activeSources) {
if (source->info.type == SourceType::Annotations) {
source->source->invalidateTiles(*this, ids);
@@ -657,7 +722,11 @@ void Map::updateSources() {
// Then, reenable all of those that we actually use when drawing this layer.
if (style) {
- updateSources(style->layers);
+ for (const auto& layer : style->layers) {
+ if (layer->bucket && layer->bucket->style_source) {
+ (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true;
+ }
+ }
}
// Then, construct or destroy the actual source object, depending on enabled state.
@@ -678,23 +747,9 @@ void Map::updateSources() {
});
}
-void Map::updateSources(const util::ptr<StyleLayerGroup> &group) {
- assert(Environment::currentlyOn(ThreadType::Map));
- if (!group) {
- return;
- }
- for (const util::ptr<StyleLayer> &layer : group->layers) {
- if (!layer) continue;
- if (layer->bucket && layer->bucket->style_source) {
- (*activeSources.emplace(layer->bucket->style_source).first)->enabled = true;
- }
-
- }
-}
-
void Map::updateTiles() {
assert(Environment::currentlyOn(ThreadType::Map));
- for (const auto &source : activeSources) {
+ for (const auto& source : activeSources) {
source->source->update(*this, getWorker(), style, *glyphAtlas, *glyphStore,
*spriteAtlas, getSprite(), *texturePool, [this]() {
assert(Environment::currentlyOn(ThreadType::Map));
@@ -741,7 +796,7 @@ void Map::loadStyleJSON(const std::string& json, const std::string& base) {
style = std::make_shared<Style>();
style->base = base;
style->loadJSON((const uint8_t *)json.c_str());
- style->cascadeClasses(data->getClasses());
+ style->cascade(data->getClasses());
style->setDefaultTransitionDuration(data->getDefaultTransitionDuration());
const std::string glyphURL = util::mapbox::normalizeGlyphsURL(style->glyph_url, getAccessToken());
@@ -754,7 +809,7 @@ void Map::prepare() {
assert(Environment::currentlyOn(ThreadType::Map));
const auto u = updated.exchange(static_cast<UpdateType>(Update::Nothing));
- if (u & static_cast<UpdateType>(Update::StyleInfo)) {
+ if ((u & static_cast<UpdateType>(Update::StyleInfo)) || !style) {
reloadStyle();
}
if (u & static_cast<UpdateType>(Update::Debug)) {
@@ -768,7 +823,7 @@ void Map::prepare() {
}
if (u & static_cast<UpdateType>(Update::Classes)) {
if (style) {
- style->cascadeClasses(data->getClasses());
+ style->cascade(data->getClasses());
}
}
@@ -784,7 +839,7 @@ void Map::prepare() {
if (style) {
updateSources();
- style->updateProperties(state.getNormalizedZoom(), animationTime);
+ style->recalculate(state.getNormalizedZoom(), animationTime);
// Allow the sprite atlas to potentially pull new sprite images if needed.
spriteAtlas->resize(state.getPixelRatio());
@@ -804,6 +859,7 @@ void Map::render() {
// Cleanup OpenGL objects that we abandoned since the last render call.
env->performCleanup();
+ assert(style);
assert(painter);
painter->render(*style, activeSources,
state, data->getAnimationTime());
diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp
index 8189068886..0cf74147e4 100644
--- a/src/mbgl/map/source.cpp
+++ b/src/mbgl/map/source.cpp
@@ -78,7 +78,7 @@ void Source::updateClipIDs(const std::map<Tile::ID, ClipID> &mapping) {
}
void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transform) {
- for (std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair : tiles) {
+ for (const auto& pair : tiles) {
Tile &tile = *pair.second;
transform.matrixFor(tile.matrix, tile.id);
matrix::multiply(tile.matrix, projMatrix, tile.matrix);
@@ -90,7 +90,7 @@ size_t Source::getTileCount() const {
}
void Source::drawClippingMasks(Painter &painter) {
- for (std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair : tiles) {
+ for (const auto& pair : tiles) {
Tile &tile = *pair.second;
gl::group group(std::string { "mask: " } + std::string(tile.id));
painter.drawClippingMask(tile.matrix, tile.clip);
@@ -99,7 +99,7 @@ void Source::drawClippingMasks(Painter &painter) {
void Source::render(Painter &painter, const StyleLayer &layer_desc) {
gl::group group(std::string { "layer: " } + layer_desc.id);
- for (const std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair : tiles) {
+ for (const auto& pair : tiles) {
Tile &tile = *pair.second;
if (tile.data && tile.data->state == TileData::State::parsed) {
painter.renderTileLayer(tile, layer_desc, tile.matrix);
@@ -115,7 +115,7 @@ void Source::render(Painter &painter, const StyleLayer &layer_desc, const Tile::
}
void Source::finishRender(Painter &painter) {
- for (std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair : tiles) {
+ for (const auto& pair : tiles) {
Tile &tile = *pair.second;
painter.renderTileDebug(tile);
}
@@ -252,7 +252,7 @@ bool Source::findLoadedChildren(const Tile::ID& id, int32_t maxCoveringZoom, std
bool complete = true;
int32_t z = id.z;
auto ids = id.children(z + 1);
- for (const Tile::ID& child_id : ids) {
+ for (const auto& child_id : ids) {
const TileData::State state = hasTile(child_id);
if (state == TileData::State::parsed) {
retain.emplace_front(child_id);
@@ -301,8 +301,6 @@ void Source::update(Map &map,
return;
}
- bool changed = false;
-
int32_t zoom = std::floor(getZoom(map.getState()));
std::forward_list<Tile::ID> required = coveringTiles(map.getState());
@@ -316,7 +314,7 @@ void Source::update(Map &map,
std::forward_list<Tile::ID> retain(required);
// Add existing child/parent tiles if the actual tile is not yet loaded
- for (const Tile::ID& id : required) {
+ for (const auto& id : required) {
const TileData::State state = addTile(map, worker, style, glyphAtlas, glyphStore,
spriteAtlas, sprite, texturePool, id, callback);
@@ -334,21 +332,15 @@ void Source::update(Map &map,
findLoadedParent(id, minCoveringZoom, retain);
}
}
-
- if (state == TileData::State::initial) {
- changed = true;
- }
}
// Remove tiles that we definitely don't need, i.e. tiles that are not on
// the required list.
std::set<Tile::ID> retain_data;
- util::erase_if(tiles, [&retain, &retain_data, &changed](std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair) {
+ util::erase_if(tiles, [&retain, &retain_data](std::pair<const Tile::ID, std::unique_ptr<Tile>> &pair) {
Tile &tile = *pair.second;
bool obsolete = std::find(retain.begin(), retain.end(), tile.id) == retain.end();
- if (obsolete) {
- changed = true;
- } else {
+ if (!obsolete) {
retain_data.insert(tile.data->id);
}
return obsolete;
diff --git a/src/mbgl/map/tile_data.hpp b/src/mbgl/map/tile_data.hpp
index cce346d835..a5598fee3b 100644
--- a/src/mbgl/map/tile_data.hpp
+++ b/src/mbgl/map/tile_data.hpp
@@ -9,8 +9,6 @@
#include <mbgl/util/ptr.hpp>
#include <atomic>
-#include <exception>
-#include <iosfwd>
#include <string>
#include <functional>
@@ -22,7 +20,6 @@ typedef struct uv_loop_s uv_loop_t;
namespace mbgl {
-class Map;
class Environment;
class Painter;
class SourceInfo;
@@ -32,12 +29,6 @@ class Request;
class TileData : public std::enable_shared_from_this<TileData>,
private util::noncopyable {
public:
- struct exception : std::exception {};
- struct geometry_too_long_exception : exception {};
-
-public:
- typedef util::ptr<TileData> Ptr;
-
enum class State {
invalid,
initial,
@@ -47,7 +38,6 @@ public:
obsolete
};
-public:
TileData(Tile::ID const &id, const SourceInfo &);
~TileData();
@@ -65,16 +55,14 @@ public:
virtual void render(Painter &painter, const StyleLayer &layer_desc, const mat4 &matrix) = 0;
virtual bool hasData(StyleLayer const &layer_desc) const = 0;
-public:
const Tile::ID id;
const std::string name;
std::atomic<State> state;
-public:
+protected:
const SourceInfo& source;
Environment& env;
-protected:
Request *req = nullptr;
std::string data;
diff --git a/src/mbgl/map/tile_parser.cpp b/src/mbgl/map/tile_parser.cpp
index fa7f4c093f..bc6de40565 100644
--- a/src/mbgl/map/tile_parser.cpp
+++ b/src/mbgl/map/tile_parser.cpp
@@ -3,8 +3,7 @@
#include <mbgl/platform/log.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_layer_group.hpp>
-#include <mbgl/style/style_layout.hpp>
+#include <mbgl/style/style_source.hpp>
#include <mbgl/renderer/fill_bucket.hpp>
#include <mbgl/renderer/line_bucket.hpp>
#include <mbgl/renderer/symbol_bucket.hpp>
@@ -49,18 +48,10 @@ TileParser::TileParser(const GeometryTile& geometryTile_,
assert(collision);
}
-void TileParser::parse() {
- parseStyleLayers(style->layers);
-}
-
bool TileParser::obsolete() const { return tile.state == TileData::State::obsolete; }
-void TileParser::parseStyleLayers(util::ptr<const StyleLayerGroup> group) {
- if (!group) {
- return;
- }
-
- for (const util::ptr<const StyleLayer> &layer_desc : group->layers) {
+void TileParser::parse() {
+ for (const auto& layer_desc : style->layers) {
// Cancel early when parsing.
if (obsolete()) {
return;
@@ -122,65 +113,6 @@ void applyLayoutProperty(PropertyKey key, const ClassProperties &classProperties
}
}
-std::unique_ptr<StyleLayoutFill> parseStyleLayoutFill(const StyleBucket &/*bucket*/, const float /*z*/) {
- // no-op; Fill buckets don't currently have any applicable layout properties
- auto fillPtr = util::make_unique<StyleLayoutFill>();
- return fillPtr;
-}
-
-std::unique_ptr<StyleLayoutLine> parseStyleLayoutLine(const StyleBucket &bucket_desc, const float z) {
- auto linePtr = util::make_unique<StyleLayoutLine>();
- auto &line = *linePtr;
- applyLayoutProperty(PropertyKey::LineCap, bucket_desc.layout, line.cap, z);
- applyLayoutProperty(PropertyKey::LineJoin, bucket_desc.layout, line.join, z);
- applyLayoutProperty(PropertyKey::LineMiterLimit, bucket_desc.layout, line.miter_limit, z);
- applyLayoutProperty(PropertyKey::LineRoundLimit, bucket_desc.layout, line.round_limit, z);
- return linePtr;
-}
-
-std::unique_ptr<StyleLayoutSymbol> parseStyleLayoutSymbol(const StyleBucket &bucket_desc, const float z) {
- auto symbolPtr = util::make_unique<StyleLayoutSymbol>();
- auto &symbol = *symbolPtr;
- applyLayoutProperty(PropertyKey::SymbolPlacement, bucket_desc.layout, symbol.placement, z);
- if (symbol.placement == PlacementType::Line) {
- symbol.icon.rotation_alignment = RotationAlignmentType::Map;
- symbol.text.rotation_alignment = RotationAlignmentType::Map;
- };
- applyLayoutProperty(PropertyKey::SymbolMinDistance, bucket_desc.layout, symbol.min_distance, z);
- applyLayoutProperty(PropertyKey::SymbolAvoidEdges, bucket_desc.layout, symbol.avoid_edges, z);
-
- applyLayoutProperty(PropertyKey::IconAllowOverlap, bucket_desc.layout, symbol.icon.allow_overlap, z);
- applyLayoutProperty(PropertyKey::IconIgnorePlacement, bucket_desc.layout, symbol.icon.ignore_placement, z);
- applyLayoutProperty(PropertyKey::IconOptional, bucket_desc.layout, symbol.icon.optional, z);
- applyLayoutProperty(PropertyKey::IconRotationAlignment, bucket_desc.layout, symbol.icon.rotation_alignment, z);
- applyLayoutProperty(PropertyKey::IconMaxSize, bucket_desc.layout, symbol.icon.max_size, z);
- applyLayoutProperty(PropertyKey::IconImage, bucket_desc.layout, symbol.icon.image, z);
- applyLayoutProperty(PropertyKey::IconPadding, bucket_desc.layout, symbol.icon.padding, z);
- applyLayoutProperty(PropertyKey::IconRotate, bucket_desc.layout, symbol.icon.rotate, z);
- applyLayoutProperty(PropertyKey::IconKeepUpright, bucket_desc.layout, symbol.icon.keep_upright, z);
- applyLayoutProperty(PropertyKey::IconOffset, bucket_desc.layout, symbol.icon.offset, z);
-
- applyLayoutProperty(PropertyKey::TextRotationAlignment, bucket_desc.layout, symbol.text.rotation_alignment, z);
- applyLayoutProperty(PropertyKey::TextField, bucket_desc.layout, symbol.text.field, z);
- applyLayoutProperty(PropertyKey::TextFont, bucket_desc.layout, symbol.text.font, z);
- applyLayoutProperty(PropertyKey::TextMaxSize, bucket_desc.layout, symbol.text.max_size, z);
- applyLayoutProperty(PropertyKey::TextMaxWidth, bucket_desc.layout, symbol.text.max_width, z);
- applyLayoutProperty(PropertyKey::TextLineHeight, bucket_desc.layout, symbol.text.line_height, z);
- applyLayoutProperty(PropertyKey::TextLetterSpacing, bucket_desc.layout, symbol.text.letter_spacing, z);
- applyLayoutProperty(PropertyKey::TextMaxAngle, bucket_desc.layout, symbol.text.max_angle, z);
- applyLayoutProperty(PropertyKey::TextRotate, bucket_desc.layout, symbol.text.rotate, z);
- applyLayoutProperty(PropertyKey::TextPadding, bucket_desc.layout, symbol.text.padding, z);
- applyLayoutProperty(PropertyKey::TextIgnorePlacement, bucket_desc.layout, symbol.text.ignore_placement, z);
- applyLayoutProperty(PropertyKey::TextOptional, bucket_desc.layout, symbol.text.optional, z);
- applyLayoutProperty(PropertyKey::TextJustify, bucket_desc.layout, symbol.text.justify, z);
- applyLayoutProperty(PropertyKey::TextAnchor, bucket_desc.layout, symbol.text.anchor, z);
- applyLayoutProperty(PropertyKey::TextKeepUpright, bucket_desc.layout, symbol.text.keep_upright, z);
- applyLayoutProperty(PropertyKey::TextTransform, bucket_desc.layout, symbol.text.transform, z);
- applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, symbol.text.offset, z);
- applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, symbol.text.allow_overlap, z);
- return symbolPtr;
-}
-
std::unique_ptr<Bucket> TileParser::createBucket(const StyleBucket &bucketDesc) {
// Skip this bucket if we are to not render this
if (tile.id.z < std::floor(bucketDesc.min_zoom) && std::floor(bucketDesc.min_zoom) < tile.source.max_zoom) return nullptr;
@@ -230,32 +162,78 @@ void TileParser::addBucketGeometries(Bucket& bucket, const GeometryTileLayer& la
std::unique_ptr<Bucket> TileParser::createFillBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
- auto fill = parseStyleLayoutFill(bucket_desc, tile.id.z);
- auto bucket = util::make_unique<FillBucket>(std::move(fill),
- tile.fillVertexBuffer,
+ auto bucket = util::make_unique<FillBucket>(tile.fillVertexBuffer,
tile.triangleElementsBuffer,
tile.lineElementsBuffer);
addBucketGeometries(bucket, layer, bucket_desc.filter);
- return obsolete() ? nullptr : std::move(bucket);
+ return std::move(bucket);
}
std::unique_ptr<Bucket> TileParser::createLineBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
- auto line = parseStyleLayoutLine(bucket_desc, tile.id.z);
- auto bucket = util::make_unique<LineBucket>(std::move(line),
- tile.lineVertexBuffer,
+ auto bucket = util::make_unique<LineBucket>(tile.lineVertexBuffer,
tile.triangleElementsBuffer,
tile.pointElementsBuffer);
+
+ const float z = tile.id.z;
+ auto& layout = bucket->layout;
+
+ applyLayoutProperty(PropertyKey::LineCap, bucket_desc.layout, layout.cap, z);
+ applyLayoutProperty(PropertyKey::LineJoin, bucket_desc.layout, layout.join, z);
+ applyLayoutProperty(PropertyKey::LineMiterLimit, bucket_desc.layout, layout.miter_limit, z);
+ applyLayoutProperty(PropertyKey::LineRoundLimit, bucket_desc.layout, layout.round_limit, z);
+
addBucketGeometries(bucket, layer, bucket_desc.filter);
- return obsolete() ? nullptr : std::move(bucket);
+ return std::move(bucket);
}
std::unique_ptr<Bucket> TileParser::createSymbolBucket(const GeometryTileLayer& layer,
const StyleBucket& bucket_desc) {
- auto symbol = parseStyleLayoutSymbol(bucket_desc, tile.id.z);
- auto bucket = util::make_unique<SymbolBucket>(std::move(symbol), *collision);
+ auto bucket = util::make_unique<SymbolBucket>(*collision);
+
+ const float z = tile.id.z;
+ auto& layout = bucket->layout;
+
+ applyLayoutProperty(PropertyKey::SymbolPlacement, bucket_desc.layout, layout.placement, z);
+ if (layout.placement == PlacementType::Line) {
+ layout.icon.rotation_alignment = RotationAlignmentType::Map;
+ layout.text.rotation_alignment = RotationAlignmentType::Map;
+ };
+ applyLayoutProperty(PropertyKey::SymbolMinDistance, bucket_desc.layout, layout.min_distance, z);
+ applyLayoutProperty(PropertyKey::SymbolAvoidEdges, bucket_desc.layout, layout.avoid_edges, z);
+
+ applyLayoutProperty(PropertyKey::IconAllowOverlap, bucket_desc.layout, layout.icon.allow_overlap, z);
+ applyLayoutProperty(PropertyKey::IconIgnorePlacement, bucket_desc.layout, layout.icon.ignore_placement, z);
+ applyLayoutProperty(PropertyKey::IconOptional, bucket_desc.layout, layout.icon.optional, z);
+ applyLayoutProperty(PropertyKey::IconRotationAlignment, bucket_desc.layout, layout.icon.rotation_alignment, z);
+ applyLayoutProperty(PropertyKey::IconMaxSize, bucket_desc.layout, layout.icon.max_size, z);
+ applyLayoutProperty(PropertyKey::IconImage, bucket_desc.layout, layout.icon.image, z);
+ applyLayoutProperty(PropertyKey::IconPadding, bucket_desc.layout, layout.icon.padding, z);
+ applyLayoutProperty(PropertyKey::IconRotate, bucket_desc.layout, layout.icon.rotate, z);
+ applyLayoutProperty(PropertyKey::IconKeepUpright, bucket_desc.layout, layout.icon.keep_upright, z);
+ applyLayoutProperty(PropertyKey::IconOffset, bucket_desc.layout, layout.icon.offset, z);
+
+ applyLayoutProperty(PropertyKey::TextRotationAlignment, bucket_desc.layout, layout.text.rotation_alignment, z);
+ applyLayoutProperty(PropertyKey::TextField, bucket_desc.layout, layout.text.field, z);
+ applyLayoutProperty(PropertyKey::TextFont, bucket_desc.layout, layout.text.font, z);
+ applyLayoutProperty(PropertyKey::TextMaxSize, bucket_desc.layout, layout.text.max_size, z);
+ applyLayoutProperty(PropertyKey::TextMaxWidth, bucket_desc.layout, layout.text.max_width, z);
+ applyLayoutProperty(PropertyKey::TextLineHeight, bucket_desc.layout, layout.text.line_height, z);
+ applyLayoutProperty(PropertyKey::TextLetterSpacing, bucket_desc.layout, layout.text.letter_spacing, z);
+ applyLayoutProperty(PropertyKey::TextMaxAngle, bucket_desc.layout, layout.text.max_angle, z);
+ applyLayoutProperty(PropertyKey::TextRotate, bucket_desc.layout, layout.text.rotate, z);
+ applyLayoutProperty(PropertyKey::TextPadding, bucket_desc.layout, layout.text.padding, z);
+ applyLayoutProperty(PropertyKey::TextIgnorePlacement, bucket_desc.layout, layout.text.ignore_placement, z);
+ applyLayoutProperty(PropertyKey::TextOptional, bucket_desc.layout, layout.text.optional, z);
+ applyLayoutProperty(PropertyKey::TextJustify, bucket_desc.layout, layout.text.justify, z);
+ applyLayoutProperty(PropertyKey::TextAnchor, bucket_desc.layout, layout.text.anchor, z);
+ applyLayoutProperty(PropertyKey::TextKeepUpright, bucket_desc.layout, layout.text.keep_upright, z);
+ applyLayoutProperty(PropertyKey::TextTransform, bucket_desc.layout, layout.text.transform, z);
+ applyLayoutProperty(PropertyKey::TextOffset, bucket_desc.layout, layout.text.offset, z);
+ applyLayoutProperty(PropertyKey::TextAllowOverlap, bucket_desc.layout, layout.text.allow_overlap, z);
+
bucket->addFeatures(
layer, bucket_desc.filter, reinterpret_cast<uintptr_t>(&tile), spriteAtlas, *sprite, glyphAtlas, glyphStore);
- return obsolete() ? nullptr : std::move(bucket);
+ return std::move(bucket);
}
}
diff --git a/src/mbgl/map/tile_parser.hpp b/src/mbgl/map/tile_parser.hpp
index 0ad42fdc91..2c16d2a2fd 100644
--- a/src/mbgl/map/tile_parser.hpp
+++ b/src/mbgl/map/tile_parser.hpp
@@ -28,7 +28,6 @@ class StyleLayoutFill;
class StyleLayoutRaster;
class StyleLayoutLine;
class StyleLayoutSymbol;
-class StyleLayerGroup;
class VectorTileData;
class Collision;
@@ -48,7 +47,6 @@ public:
private:
bool obsolete() const;
- void parseStyleLayers(util::ptr<const StyleLayerGroup> group);
std::unique_ptr<Bucket> createBucket(const StyleBucket&);
std::unique_ptr<Bucket> createFillBucket(const GeometryTileLayer&, const StyleBucket&);
@@ -58,7 +56,6 @@ private:
template <class Bucket>
void addBucketGeometries(Bucket&, const GeometryTileLayer&, const FilterExpression&);
-private:
const GeometryTile& geometryTile;
VectorTileData& tile;
diff --git a/src/mbgl/map/vector_tile.cpp b/src/mbgl/map/vector_tile.cpp
index dca2168a47..01d52a348a 100644
--- a/src/mbgl/map/vector_tile.cpp
+++ b/src/mbgl/map/vector_tile.cpp
@@ -35,26 +35,7 @@ VectorTileFeature::VectorTileFeature(pbf feature_pbf, const VectorTileLayer& lay
if (feature_pbf.tag == 1) { // id
id = feature_pbf.varint<uint64_t>();
} else if (feature_pbf.tag == 2) { // tags
- // tags are packed varints. They should have an even length.
- pbf tags = feature_pbf.message();
- while (tags) {
- uint32_t tag_key = tags.varint();
-
- if (layer.keys.size() <= tag_key) {
- throw std::runtime_error("feature referenced out of range key");
- }
-
- if (!tags) {
- throw std::runtime_error("uneven number of feature tag ids");
- }
-
- uint32_t tag_val = tags.varint();
- if (layer.values.size() <= tag_val) {
- throw std::runtime_error("feature referenced out of range value");
- }
-
- properties.emplace(tag_key, tag_val);
- }
+ tags_pbf = feature_pbf.message();
} else if (feature_pbf.tag == 3) { // type
type = (FeatureType)feature_pbf.varint();
} else if (feature_pbf.tag == 4) { // geometry
@@ -70,11 +51,30 @@ mapbox::util::optional<Value> VectorTileFeature::getValue(const std::string& key
if (keyIter == layer.keys.end()) {
return mapbox::util::optional<Value>();
}
- auto propIter = properties.find(keyIter->second);
- if (propIter == properties.end()) {
- return mapbox::util::optional<Value>();
+
+ pbf tags = tags_pbf;
+ while (tags) {
+ uint32_t tag_key = tags.varint();
+
+ if (layer.keys.size() <= tag_key) {
+ throw std::runtime_error("feature referenced out of range key");
+ }
+
+ if (!tags) {
+ throw std::runtime_error("uneven number of feature tag ids");
+ }
+
+ uint32_t tag_val = tags.varint();
+ if (layer.values.size() <= tag_val) {
+ throw std::runtime_error("feature referenced out of range value");
+ }
+
+ if (tag_key == keyIter->second) {
+ return layer.values[tag_val];
+ }
}
- return layer.values[propIter->second];
+
+ return mapbox::util::optional<Value>();
}
GeometryCollection VectorTileFeature::getGeometries() const {
diff --git a/src/mbgl/map/vector_tile.hpp b/src/mbgl/map/vector_tile.hpp
index 9a23c3b189..77a0b4ab16 100644
--- a/src/mbgl/map/vector_tile.hpp
+++ b/src/mbgl/map/vector_tile.hpp
@@ -22,7 +22,7 @@ private:
const VectorTileLayer& layer;
uint64_t id = 0;
FeatureType type = FeatureType::Unknown;
- std::unordered_map<uint32_t, uint32_t> properties;
+ pbf tags_pbf;
pbf geometry_pbf;
};
diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp
index 3c56401e1e..6104e2456b 100644
--- a/src/mbgl/renderer/debug_bucket.cpp
+++ b/src/mbgl/renderer/debug_bucket.cpp
@@ -5,8 +5,6 @@
#include <cassert>
-struct geometry_too_long_exception : std::exception {};
-
using namespace mbgl;
DebugBucket::DebugBucket(DebugFontBuffer& fontBuffer_)
diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp
index 26d0d1f4be..958ea3d998 100644
--- a/src/mbgl/renderer/fill_bucket.cpp
+++ b/src/mbgl/renderer/fill_bucket.cpp
@@ -28,12 +28,10 @@ void FillBucket::free(void *, void *ptr) {
::free(ptr);
}
-FillBucket::FillBucket(std::unique_ptr<const StyleLayoutFill> styleLayout_,
- FillVertexBuffer &vertexBuffer_,
+FillBucket::FillBucket(FillVertexBuffer &vertexBuffer_,
TriangleElementsBuffer &triangleElementsBuffer_,
LineElementsBuffer &lineElementsBuffer_)
- : styleLayout(std::move(styleLayout_)),
- allocator(new TESSalloc{
+ : allocator(new TESSalloc{
&alloc,
&realloc,
&free,
@@ -53,7 +51,6 @@ FillBucket::FillBucket(std::unique_ptr<const StyleLayoutFill> styleLayout_,
triangle_elements_start(triangleElementsBuffer_.index()),
line_elements_start(lineElementsBuffer.index()) {
assert(tesselator);
- assert(styleLayout);
}
FillBucket::~FillBucket() {
@@ -95,7 +92,7 @@ void FillBucket::tessellate() {
}
size_t total_vertex_count = 0;
- for (const std::vector<ClipperLib::IntPoint>& polygon : polygons) {
+ for (const auto& polygon : polygons) {
total_vertex_count += polygon.size();
}
@@ -112,12 +109,12 @@ void FillBucket::tessellate() {
line_group_type& lineGroup = *lineGroups.back();
uint32_t lineIndex = lineGroup.vertex_length;
- for (const std::vector<ClipperLib::IntPoint>& polygon : polygons) {
+ for (const auto& polygon : polygons) {
const size_t group_count = polygon.size();
assert(group_count >= 3);
std::vector<TESSreal> clipped_line;
- for (const ClipperLib::IntPoint& pt : polygon) {
+ for (const auto& pt : polygon) {
clipped_line.push_back(pt.X);
clipped_line.push_back(pt.Y);
vertexBuffer.add(pt.X, pt.Y);
diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp
index 46b8f53857..937fd540ac 100644
--- a/src/mbgl/renderer/fill_bucket.hpp
+++ b/src/mbgl/renderer/fill_bucket.hpp
@@ -6,6 +6,7 @@
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/fill_buffer.hpp>
#include <mbgl/style/style_bucket.hpp>
+#include <mbgl/style/style_layout.hpp>
#include <clipper/clipper.hpp>
#include <libtess2/tesselator.h>
@@ -39,8 +40,7 @@ class FillBucket : public Bucket {
typedef ElementGroup<1> line_group_type;
public:
- FillBucket(std::unique_ptr<const StyleLayoutFill> styleLayout,
- FillVertexBuffer &vertexBuffer,
+ FillBucket(FillVertexBuffer &vertexBuffer,
TriangleElementsBuffer &triangleElementsBuffer,
LineElementsBuffer &lineElementsBuffer);
~FillBucket() override;
@@ -57,7 +57,7 @@ public:
void drawVertices(OutlineShader& shader);
public:
- const std::unique_ptr<const StyleLayoutFill> styleLayout;
+ StyleLayoutFill layout;
private:
TESSalloc *allocator;
diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp
index 6eea0d8d0f..5404398ca0 100644
--- a/src/mbgl/renderer/line_bucket.cpp
+++ b/src/mbgl/renderer/line_bucket.cpp
@@ -12,22 +12,17 @@
#include <cassert>
-struct geometry_too_long_exception : std::exception {};
-
using namespace mbgl;
-LineBucket::LineBucket(std::unique_ptr<const StyleLayoutLine> styleLayout_,
- LineVertexBuffer &vertexBuffer_,
+LineBucket::LineBucket(LineVertexBuffer &vertexBuffer_,
TriangleElementsBuffer &triangleElementsBuffer_,
PointElementsBuffer &pointElementsBuffer_)
- : styleLayout(std::move(styleLayout_)),
- vertexBuffer(vertexBuffer_),
+ : vertexBuffer(vertexBuffer_),
triangleElementsBuffer(triangleElementsBuffer_),
pointElementsBuffer(pointElementsBuffer_),
vertex_start(vertexBuffer_.index()),
triangle_elements_start(triangleElementsBuffer_.index()),
point_elements_start(pointElementsBuffer_.index()) {
- assert(styleLayout);
}
LineBucket::~LineBucket() {
@@ -48,7 +43,6 @@ void LineBucket::addGeometry(const GeometryCollection& geometryCollection) {
}
void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
- auto &layout = *styleLayout;
// TODO: use roundLimit
// const float roundLimit = geometry.round_limit;
@@ -302,7 +296,7 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
assert(triangleGroups.back());
triangle_group_type& group = *triangleGroups.back();
- for (const TriangleElement& triangle : triangle_store) {
+ for (const auto& triangle : triangle_store) {
triangleElementsBuffer.add(
group.vertex_length + triangle.a,
group.vertex_length + triangle.b,
@@ -323,7 +317,7 @@ void LineBucket::addGeometry(const std::vector<Coordinate>& vertices) {
assert(pointGroups.back());
point_group_type& group = *pointGroups.back();
- for (PointElement point : point_store) {
+ for (const auto point : point_store) {
pointElementsBuffer.add(group.vertex_length + point);
}
diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp
index 25b2190176..e6e5f66d57 100644
--- a/src/mbgl/renderer/line_bucket.hpp
+++ b/src/mbgl/renderer/line_bucket.hpp
@@ -7,6 +7,7 @@
#include <mbgl/geometry/elements_buffer.hpp>
#include <mbgl/geometry/line_buffer.hpp>
#include <mbgl/style/style_bucket.hpp>
+#include <mbgl/style/style_layout.hpp>
#include <mbgl/util/vec.hpp>
#include <vector>
@@ -14,7 +15,6 @@
namespace mbgl {
class Style;
-class StyleLayoutLine;
class LineVertexBuffer;
class TriangleElementsBuffer;
class LineShader;
@@ -27,8 +27,7 @@ class LineBucket : public Bucket {
typedef ElementGroup<1> point_group_type;
public:
- LineBucket(std::unique_ptr<const StyleLayoutLine> styleLayout,
- LineVertexBuffer &vertexBuffer,
+ LineBucket(LineVertexBuffer &vertexBuffer,
TriangleElementsBuffer &triangleElementsBuffer,
PointElementsBuffer &pointElementsBuffer);
~LineBucket() override;
@@ -48,7 +47,7 @@ public:
void drawPoints(LinejoinShader& shader);
public:
- const std::unique_ptr<const StyleLayoutLine> styleLayout;
+ StyleLayoutLine layout;
private:
LineVertexBuffer& vertexBuffer;
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index dae9c766cc..0219ccec7f 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -2,7 +2,6 @@
#include <mbgl/platform/log.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_layer_group.hpp>
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/string.hpp>
@@ -226,7 +225,7 @@ void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>&
// Update all clipping IDs.
ClipIDGenerator generator;
- for (const util::ptr<StyleSource> &source : sources) {
+ for (const auto& source : sources) {
generator.update(source->source->getLoadedTiles());
source->source->updateMatrices(projMatrix, state);
}
@@ -237,23 +236,9 @@ void Painter::render(const Style& style, const std::set<util::ptr<StyleSource>>&
// Actually render the layers
if (debug::renderTree) { Log::Info(Event::Render, "{"); indent++; }
- if (style.layers) {
- renderLayers(*style.layers);
- }
- if (debug::renderTree) { Log::Info(Event::Render, "}"); indent--; }
-
- // Finalize the rendering, e.g. by calling debug render calls per tile.
- // This guarantees that we have at least one function per tile called.
- // When only rendering layers via the stylesheet, it's possible that we don't
- // ever visit a tile during rendering.
- for (const util::ptr<StyleSource> &source : sources) {
- source->source->finishRender(*this);
- }
-}
-void Painter::renderLayers(const StyleLayerGroup &group) {
// TODO: Correctly compute the number of layers recursively beforehand.
- float strata_thickness = 1.0f / (group.layers.size() + 1);
+ float strata_thickness = 1.0f / (style.layers.size() + 1);
// - FIRST PASS ------------------------------------------------------------
// Render everything top-to-bottom by using reverse iterators. Render opaque
@@ -263,7 +248,7 @@ void Painter::renderLayers(const StyleLayerGroup &group) {
Log::Info(Event::Render, "%*s%s", indent++ * 4, "", "OPAQUE {");
}
int i = 0;
- for (auto it = group.layers.rbegin(), end = group.layers.rend(); it != end; ++it, ++i) {
+ for (auto it = style.layers.rbegin(), end = style.layers.rend(); it != end; ++it, ++i) {
setOpaque();
setStrata(i * strata_thickness);
renderLayer(**it);
@@ -279,7 +264,7 @@ void Painter::renderLayers(const StyleLayerGroup &group) {
Log::Info(Event::Render, "%*s%s", indent++ * 4, "", "TRANSLUCENT {");
}
--i;
- for (auto it = group.layers.begin(), end = group.layers.end(); it != end; ++it, --i) {
+ for (auto it = style.layers.begin(), end = style.layers.end(); it != end; ++it, --i) {
setTranslucent();
setStrata(i * strata_thickness);
renderLayer(**it);
@@ -287,6 +272,16 @@ void Painter::renderLayers(const StyleLayerGroup &group) {
if (debug::renderTree) {
Log::Info(Event::Render, "%*s%s", --indent * 4, "", "}");
}
+
+ if (debug::renderTree) { Log::Info(Event::Render, "}"); indent--; }
+
+ // Finalize the rendering, e.g. by calling debug render calls per tile.
+ // This guarantees that we have at least one function per tile called.
+ // 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->source->finishRender(*this);
+ }
}
void Painter::renderLayer(const StyleLayer &layer_desc, const Tile::ID* id, const mat4* matrix) {
diff --git a/src/mbgl/renderer/painter.hpp b/src/mbgl/renderer/painter.hpp
index 9c9c6a4642..485098c116 100644
--- a/src/mbgl/renderer/painter.hpp
+++ b/src/mbgl/renderer/painter.hpp
@@ -43,7 +43,6 @@ class GlyphAtlas;
class LineAtlas;
class Source;
class StyleSource;
-class StyleLayerGroup;
class FillBucket;
class LineBucket;
@@ -81,7 +80,6 @@ public:
TransformState state,
std::chrono::steady_clock::time_point time);
- void renderLayers(const StyleLayerGroup &group);
void renderLayer(const StyleLayer &layer_desc, const Tile::ID* id = nullptr, const mat4* matrix = nullptr);
// Renders a particular layer from a tile.
diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp
index 942be3e9bb..574cbe50af 100644
--- a/src/mbgl/renderer/painter_clipping.cpp
+++ b/src/mbgl/renderer/painter_clipping.cpp
@@ -17,7 +17,7 @@ void Painter::drawClippingMasks(const std::set<util::ptr<StyleSource>> &sources)
coveringPlainArray.bind(*plainShader, tileStencilBuffer, BUFFER_OFFSET(0));
- for (const util::ptr<StyleSource> &source : sources) {
+ for (const auto& source : sources) {
source->source->drawClippingMasks(*this);
}
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index 2c861aac00..7f9c990776 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -77,7 +77,7 @@ void Painter::renderDebugText(const std::vector<std::string> &strings) {
DebugFontBuffer debugFontBuffer;
int line = 25;
- for (const std::string &str : strings) {
+ for (const auto& str : strings) {
debugFontBuffer.addText(str.c_str(), 10, line, 0.75);
line += 20;
}
diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp
index 679e4db7b0..a19d9873af 100644
--- a/src/mbgl/renderer/painter_line.cpp
+++ b/src/mbgl/renderer/painter_line.cpp
@@ -18,7 +18,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
depthMask(false);
const auto &properties = layer_desc.getProperties<LineProperties>();
- const auto &layout = *bucket.styleLayout;
+ const auto &layout = bucket.layout;
// the distance over which the line edge fades out.
// Retina devices need a smaller distance to avoid aliasing.
diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp
index 5e72676b92..72d15aabd0 100644
--- a/src/mbgl/renderer/painter_raster.cpp
+++ b/src/mbgl/renderer/painter_raster.cpp
@@ -2,7 +2,6 @@
#include <mbgl/platform/gl.hpp>
#include <mbgl/renderer/raster_bucket.hpp>
#include <mbgl/style/style_layer.hpp>
-#include <mbgl/style/style_layer_group.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/map/map.hpp>
diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp
index 9476146e95..e1b4d88193 100644
--- a/src/mbgl/renderer/painter_symbol.cpp
+++ b/src/mbgl/renderer/painter_symbol.cpp
@@ -119,7 +119,7 @@ void Painter::renderSymbol(SymbolBucket &bucket, const StyleLayer &layer_desc, c
}
const auto &properties = layer_desc.getProperties<SymbolProperties>();
- const auto &layout = *bucket.styleLayout;
+ const auto &layout = bucket.layout;
MBGL_CHECK_ERROR(glDisable(GL_STENCIL_TEST));
depthMask(false);
diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp
index ad54581e10..d5940eccf1 100644
--- a/src/mbgl/renderer/symbol_bucket.cpp
+++ b/src/mbgl/renderer/symbol_bucket.cpp
@@ -22,9 +22,8 @@
namespace mbgl {
-SymbolBucket::SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout_, Collision &collision_)
- : styleLayout(std::move(styleLayout_)), collision(collision_) {
- assert(styleLayout);
+SymbolBucket::SymbolBucket(Collision &collision_)
+ : collision(collision_) {
}
SymbolBucket::~SymbolBucket() {
@@ -46,7 +45,6 @@ std::vector<SymbolFeature> SymbolBucket::processFeatures(const GeometryTileLayer
const FilterExpression& filter,
GlyphStore &glyphStore,
const Sprite &sprite) {
- auto &layout = *styleLayout;
const bool has_text = layout.text.field.size();
const bool has_icon = layout.icon.image.size();
@@ -129,7 +127,6 @@ void SymbolBucket::addFeatures(const GeometryTileLayer& layer,
Sprite& sprite,
GlyphAtlas& glyphAtlas,
GlyphStore& glyphStore) {
- auto &layout = *styleLayout;
const std::vector<SymbolFeature> features = processFeatures(layer, filter, glyphStore, sprite);
float horizontalAlign = 0.5;
@@ -175,7 +172,7 @@ void SymbolBucket::addFeatures(const GeometryTileLayer& layer,
const auto &fontStack = glyphStore.getFontStack(layout.text.font);
- for (const SymbolFeature &feature : features) {
+ for (const auto& feature : features) {
if (!feature.geometry.size()) continue;
Shaping shaping;
@@ -212,7 +209,7 @@ void SymbolBucket::addFeatures(const GeometryTileLayer& layer,
// if either shaping or icon position is present, add the feature
if (shaping.size() || image) {
- for (const std::vector<Coordinate> &line : feature.geometry) {
+ for (const auto& line : feature.geometry) {
if (line.size()) {
addFeature(line, shaping, face, image);
}
@@ -228,7 +225,6 @@ const PlacementRange fullRange{{2 * M_PI, 0}};
void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping &shaping,
const GlyphPositions &face, const Rect<uint16_t> &image) {
assert(line.size());
- auto &layout = *styleLayout;
const float minScale = 0.5f;
const float glyphSize = 24.0f;
@@ -276,7 +272,7 @@ void SymbolBucket::addFeature(const std::vector<Coordinate> &line, const Shaping
// TODO: figure out correct ascender height.
const vec2<float> origin = {0, -17};
- for (Anchor &anchor : anchors) {
+ for (auto& anchor : anchors) {
// Calculate the scales at which the text and icons can be first shown without overlap
Placement glyphPlacement;
@@ -363,7 +359,7 @@ void SymbolBucket::addSymbols(Buffer &buffer, const PlacedGlyphs &symbols, float
const float placementZoom = std::log(scale) / std::log(2) + zoom;
- for (const PlacedGlyph &symbol : symbols) {
+ for (const auto& symbol : symbols) {
const auto &tl = symbol.tl;
const auto &tr = symbol.tr;
const auto &bl = symbol.bl;
diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp
index b7291c186c..4f425a49ec 100644
--- a/src/mbgl/renderer/symbol_bucket.hpp
+++ b/src/mbgl/renderer/symbol_bucket.hpp
@@ -10,7 +10,7 @@
#include <mbgl/text/types.hpp>
#include <mbgl/text/glyph.hpp>
#include <mbgl/style/style_bucket.hpp>
-#include <mbgl/util/ptr.hpp>
+#include <mbgl/style/style_layout.hpp>
#include <memory>
#include <map>
@@ -56,7 +56,7 @@ class SymbolBucket : public Bucket {
typedef ElementGroup<2> IconElementGroup;
public:
- SymbolBucket(std::unique_ptr<const StyleLayoutSymbol> styleLayout, Collision &collision);
+ SymbolBucket(Collision &collision);
~SymbolBucket() override;
void render(Painter &painter, const StyleLayer &layer_desc, const Tile::ID &id,
@@ -90,7 +90,7 @@ private:
void addSymbols(Buffer &buffer, const PlacedGlyphs &symbols, float scale, PlacementRange placementRange);
public:
- const std::unique_ptr<const StyleLayoutSymbol> styleLayout;
+ StyleLayoutSymbol layout;
bool sdfIcons = false;
private:
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 45217950f6..d0adfe27c2 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -1,6 +1,6 @@
#include <mbgl/style/style.hpp>
#include <mbgl/map/sprite.hpp>
-#include <mbgl/style/style_layer_group.hpp>
+#include <mbgl/style/style_layer.hpp>
#include <mbgl/style/style_parser.hpp>
#include <mbgl/style/style_bucket.hpp>
#include <mbgl/util/constants.hpp>
@@ -25,19 +25,21 @@ Style::Style()
// for deleting the std::unique_ptr<uv::rwlock>.
Style::~Style() {}
-void Style::updateProperties(float z, std::chrono::steady_clock::time_point now) {
+void Style::cascade(const std::vector<std::string>& classes) {
+ std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+
+ for (const auto& layer : layers) {
+ layer->setClasses(classes, now, defaultTransition);
+ }
+}
+
+void Style::recalculate(float z, std::chrono::steady_clock::time_point now) {
uv::writelock lock(mtx);
zoomHistory.update(z, now);
- if (layers) {
- layers->updateProperties(z, now, zoomHistory);
- }
-
- // Apply transitions after the first time.
- if (!initial_render_complete) {
- initial_render_complete = true;
- return;
+ for (const auto& layer : layers) {
+ layer->updateProperties(z, now, zoomHistory);
}
}
@@ -49,22 +51,15 @@ void Style::setDefaultTransitionDuration(std::chrono::steady_clock::duration dur
defaultTransition.duration = duration;
}
-void Style::cascadeClasses(const std::vector<std::string>& classes) {
- if (layers) {
- layers->setClasses(classes, std::chrono::steady_clock::now(), defaultTransition);
- }
-}
-
bool Style::hasTransitions() const {
- if (layers) {
- if (layers->hasTransitions()) {
+ for (const auto& layer : layers) {
+ if (layer->hasTransitions()) {
return true;
}
}
return false;
}
-
void Style::loadJSON(const uint8_t *const data) {
uv::writelock lock(mtx);
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 4de827a38c..453ebacff5 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -2,54 +2,43 @@
#define MBGL_STYLE_STYLE
#include <mbgl/style/property_transition.hpp>
-#include <mbgl/style/style_source.hpp>
#include <mbgl/style/zoom_history.hpp>
#include <mbgl/util/uv.hpp>
#include <mbgl/util/ptr.hpp>
+#include <mbgl/util/noncopyable.hpp>
#include <cstdint>
-#include <map>
#include <string>
-#include <unordered_map>
#include <vector>
-#include <set>
#include <chrono>
namespace mbgl {
-class Sprite;
class StyleLayer;
-class StyleLayerGroup;
class Style : public util::noncopyable {
public:
- struct exception : std::runtime_error { exception(const char *msg) : std::runtime_error(msg) {} };
-
Style();
~Style();
void loadJSON(const uint8_t *const data);
- size_t layerCount() const;
- void updateProperties(float z, std::chrono::steady_clock::time_point now);
-
- void setDefaultTransitionDuration(std::chrono::steady_clock::duration duration = std::chrono::steady_clock::duration::zero());
- void cascadeClasses(const std::vector<std::string>&);
+ void cascade(const std::vector<std::string>&);
+ void recalculate(float z, std::chrono::steady_clock::time_point now);
+ void setDefaultTransitionDuration(std::chrono::steady_clock::duration);
bool hasTransitions() const;
const std::string &getSpriteURL() const;
- util::ptr<StyleLayerGroup> layers;
- std::vector<std::string> appliedClasses;
+ std::vector<util::ptr<StyleLayer>> layers;
std::string glyph_url;
std::string base;
private:
std::string sprite_url;
PropertyTransition defaultTransition;
- bool initial_render_complete = false;
std::unique_ptr<uv::rwlock> mtx;
ZoomHistory zoomHistory;
};
diff --git a/src/mbgl/style/style_layer.cpp b/src/mbgl/style/style_layer.cpp
index 1a4354be27..705d9800b1 100644
--- a/src/mbgl/style/style_layer.cpp
+++ b/src/mbgl/style/style_layer.cpp
@@ -1,6 +1,5 @@
#include <mbgl/style/style_layer.hpp>
#include <mbgl/style/style_bucket.hpp>
-#include <mbgl/style/style_layer_group.hpp>
#include <mbgl/style/property_fallback.hpp>
#include <mbgl/util/interpolate.hpp>
@@ -32,7 +31,7 @@ void StyleLayer::setClasses(const std::vector<std::string> &class_names, const s
// Make sure that we also transition to the fallback value for keys that aren't changed by
// any applied classes.
- for (std::pair<const PropertyKey, AppliedClassProperties> &property_pair : appliedStyle) {
+ for (auto& property_pair : appliedStyle) {
const PropertyKey key = property_pair.first;
if (already_applied.find(key) != already_applied.end()) {
// This property has already been set by a previous class, so we don't need to
@@ -66,7 +65,7 @@ void StyleLayer::applyClassProperties(const ClassID class_id,
// Loop through all the properties in this style, and add transitions to them, if they're
// not already the most recent transition.
const ClassProperties &class_properties = style_it->second;
- for (const std::pair<PropertyKey, PropertyValue> &property_pair : class_properties) {
+ for (const auto& property_pair : class_properties) {
PropertyKey key = property_pair.first;
if (already_applied.find(key) != already_applied.end()) {
// This property has already been set by a previous class.
@@ -126,7 +125,7 @@ void StyleLayer::applyStyleProperty(PropertyKey key, T &target, const float z, c
AppliedClassProperties &applied = it->second;
// Iterate through all properties that we need to apply in order.
const PropertyEvaluator<T> evaluator(z, zoomHistory);
- for (AppliedClassProperty &property : applied.properties) {
+ for (auto& property : applied.properties) {
if (now >= property.begin) {
// We overwrite the current property with the new value.
target = mapbox::util::apply_visitor(evaluator, property.value);
@@ -144,7 +143,7 @@ void StyleLayer::applyTransitionedStyleProperty(PropertyKey key, T &target, cons
AppliedClassProperties &applied = it->second;
// Iterate through all properties that we need to apply in order.
const PropertyEvaluator<T> evaluator(z, zoomHistory);
- for (AppliedClassProperty &property : applied.properties) {
+ for (auto& property : applied.properties) {
if (now >= property.end) {
// We overwrite the current property with the new value.
target = mapbox::util::apply_visitor(evaluator, property.value);
@@ -250,7 +249,7 @@ void StyleLayer::updateProperties(float z, const std::chrono::steady_clock::time
}
bool StyleLayer::hasTransitions() const {
- for (const std::pair<PropertyKey, AppliedClassProperties> &pair : appliedStyle) {
+ for (const auto& pair : appliedStyle) {
if (pair.second.hasTransitions()) {
return true;
}
diff --git a/src/mbgl/style/style_layer.hpp b/src/mbgl/style/style_layer.hpp
index 6e1fc7912b..e33d510975 100644
--- a/src/mbgl/style/style_layer.hpp
+++ b/src/mbgl/style/style_layer.hpp
@@ -8,6 +8,7 @@
#include <mbgl/style/zoom_history.hpp>
#include <mbgl/util/ptr.hpp>
+#include <mbgl/util/noncopyable.hpp>
#include <vector>
#include <string>
@@ -18,9 +19,8 @@
namespace mbgl {
class StyleBucket;
-class StyleLayerGroup;
-class StyleLayer {
+class StyleLayer : public util::noncopyable {
public:
StyleLayer(const std::string &id, std::map<ClassID, ClassProperties> &&styles);
diff --git a/src/mbgl/style/style_layer_group.cpp b/src/mbgl/style/style_layer_group.cpp
deleted file mode 100644
index f57ec5cc7b..0000000000
--- a/src/mbgl/style/style_layer_group.cpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#include <mbgl/style/style_layer_group.hpp>
-
-namespace mbgl {
-
-void StyleLayerGroup::setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
- const PropertyTransition &defaultTransition) {
- for (const util::ptr<StyleLayer> &layer : layers) {
- if (layer) {
- layer->setClasses(class_names, now, defaultTransition);
- }
- }
-}
-
-void StyleLayerGroup::updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory) {
- for (const util::ptr<StyleLayer> &layer: layers) {
- if (layer) {
- layer->updateProperties(z, now, zoomHistory);
- }
- }
-}
-
-bool StyleLayerGroup::hasTransitions() const {
- for (const util::ptr<const StyleLayer> &layer: layers) {
- if (layer) {
- if (layer->hasTransitions()) {
- return true;
- }
- }
- }
- return false;
-}
-
-
-}
diff --git a/src/mbgl/style/style_layer_group.hpp b/src/mbgl/style/style_layer_group.hpp
deleted file mode 100644
index 79b75a55e9..0000000000
--- a/src/mbgl/style/style_layer_group.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef MBGL_STYLE_STYLE_LAYER_GROUP
-#define MBGL_STYLE_STYLE_LAYER_GROUP
-
-#include <mbgl/style/style_layer.hpp>
-
-#include <vector>
-#include <chrono>
-
-namespace mbgl {
-
-class StyleLayerGroup {
-public:
- void setClasses(const std::vector<std::string> &class_names, std::chrono::steady_clock::time_point now,
- const PropertyTransition &defaultTransition);
- void updateProperties(float z, std::chrono::steady_clock::time_point now, ZoomHistory &zoomHistory);
-
- bool hasTransitions() const;
-public:
- std::vector<util::ptr<StyleLayer>> layers;
-};
-
-}
-
-#endif
diff --git a/src/mbgl/style/style_parser.cpp b/src/mbgl/style/style_parser.cpp
index 66938987fb..7024853704 100644
--- a/src/mbgl/style/style_parser.cpp
+++ b/src/mbgl/style/style_parser.cpp
@@ -1,6 +1,6 @@
#include <mbgl/style/style_source.hpp>
#include <mbgl/style/style_parser.hpp>
-#include <mbgl/style/style_layer_group.hpp>
+#include <mbgl/style/style_layer.hpp>
#include <mbgl/map/annotation.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/std.hpp>
@@ -9,6 +9,13 @@
#include <mbgl/platform/log.hpp>
#include <csscolorparser/csscolorparser.hpp>
+#pragma GCC diagnostic push
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
+#endif
+#include <boost/algorithm/string.hpp>
+#pragma GCC diagnostic pop
+
#include <algorithm>
namespace mbgl {
@@ -28,8 +35,7 @@ void StyleParser::parse(JSVal document) {
}
if (document.HasMember("layers")) {
- root = createLayers(document["layers"]);
- parseLayers();
+ parseLayers(document["layers"]);
// create point annotations layer
//
@@ -38,8 +44,8 @@ void StyleParser::parse(JSVal document) {
std::map<ClassID, ClassProperties> paints;
util::ptr<StyleLayer> annotations = std::make_shared<StyleLayer>(id, std::move(paints));
annotations->type = StyleLayerType::Symbol;
- layers.emplace(id, std::pair<JSVal, util::ptr<StyleLayer>> { JSVal(id), annotations });
- root->layers.emplace_back(annotations);
+ layersMap.emplace(id, std::pair<JSVal, util::ptr<StyleLayer>> { JSVal(id), annotations });
+ layers.emplace_back(annotations);
util::ptr<StyleBucket> pointBucket = std::make_shared<StyleBucket>(annotations->type);
pointBucket->name = annotations->id;
@@ -447,6 +453,13 @@ bool StyleParser::parseOptionalProperty(const char *property_name, PropertyKey k
}
}
+std::string normalizeFontStack(const std::string &name) {
+ namespace algo = boost::algorithm;
+ std::vector<std::string> parts;
+ algo::split(parts, name, algo::is_any_of(","), algo::token_compress_on);
+ std::for_each(parts.begin(), parts.end(), [](std::string& str) { algo::trim(str); });
+ return algo::join(parts, ", ");
+}
template<> std::tuple<bool, std::string> StyleParser::parseProperty(JSVal value, const char *property_name) {
if (!value.IsString()) {
@@ -454,7 +467,13 @@ template<> std::tuple<bool, std::string> StyleParser::parseProperty(JSVal value,
return std::tuple<bool, std::string> { false, std::string() };
}
- return std::tuple<bool, std::string> { true, { value.GetString(), value.GetStringLength() } };
+ if (std::string { "text-font" } == property_name) {
+ return std::tuple<bool, std::string> {
+ true, normalizeFontStack({ value.GetString(), value.GetStringLength() })
+ };
+ } else {
+ return std::tuple<bool, std::string> { true, { value.GetString(), value.GetStringLength() } };
+ }
}
template<> std::tuple<bool, bool> StyleParser::parseProperty(JSVal value, const char *property_name) {
@@ -662,61 +681,48 @@ template<> std::tuple<bool, PiecewiseConstantFunction<Faded<std::string>>> Style
#pragma mark - Parse Layers
-std::unique_ptr<StyleLayerGroup> StyleParser::createLayers(JSVal value) {
- if (value.IsArray()) {
- std::unique_ptr<StyleLayerGroup> group = util::make_unique<StyleLayerGroup>();
- for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
- util::ptr<StyleLayer> layer = createLayer(value[i]);
- if (layer) {
- group->layers.emplace_back(layer);
- }
- }
- return group;
- } else {
+void StyleParser::parseLayers(JSVal value) {
+ if (!value.IsArray()) {
Log::Warning(Event::ParseStyle, "layers must be an array");
- return nullptr;
+ return;
}
-}
-util::ptr<StyleLayer> StyleParser::createLayer(JSVal value) {
- if (value.IsObject()) {
- if (!value.HasMember("id")) {
+ for (rapidjson::SizeType i = 0; i < value.Size(); ++i) {
+ JSVal layerValue = value[i];
+
+ if (!layerValue.IsObject()) {
+ Log::Warning(Event::ParseStyle, "layer must be an object");
+ continue;
+ }
+
+ if (!layerValue.HasMember("id")) {
Log::Warning(Event::ParseStyle, "layer must have an id");
- return nullptr;
+ continue;
}
- JSVal id = value["id"];
+ JSVal id = layerValue["id"];
if (!id.IsString()) {
Log::Warning(Event::ParseStyle, "layer id must be a string");
- return nullptr;
+ continue;
}
- const std::string layer_id = { id.GetString(), id.GetStringLength() };
-
- if (layers.find(layer_id) != layers.end()) {
- Log::Warning(Event::ParseStyle, "duplicate layer id %s", layer_id.c_str());
- return nullptr;
+ const std::string layerID = { id.GetString(), id.GetStringLength() };
+ if (layersMap.find(layerID) != layersMap.end()) {
+ Log::Warning(Event::ParseStyle, "duplicate layer id %s", layerID.c_str());
+ continue;
}
// Parse paints already, as they can't be inherited anyway.
std::map<ClassID, ClassProperties> paints;
- parsePaints(value, paints);
-
- util::ptr<StyleLayer> layer = std::make_shared<StyleLayer>(
- layer_id, std::move(paints));
+ parsePaints(layerValue, paints);
- // Store the layer ID so we can reference it later.
- layers.emplace(layer_id, std::pair<JSVal, util::ptr<StyleLayer>> { value, layer });
+ util::ptr<StyleLayer> layer = std::make_shared<StyleLayer>(layerID, std::move(paints));
- return layer;
- } else {
- Log::Warning(Event::ParseStyle, "layer must be an object");
- return nullptr;
+ layers.emplace_back(layer);
+ layersMap.emplace(layerID, std::pair<JSVal, util::ptr<StyleLayer>> { layerValue, layer });
}
-}
-void StyleParser::parseLayers() {
- for (std::pair<const std::string, std::pair<JSVal, util::ptr<StyleLayer>>> &pair : layers) {
+ for (auto& pair : layersMap) {
parseLayer(pair.second);
}
}
@@ -904,8 +910,8 @@ void StyleParser::parseReference(JSVal value, util::ptr<StyleLayer> &layer) {
return;
}
const std::string ref { value.GetString(), value.GetStringLength() };
- auto it = layers.find(ref);
- if (it == layers.end()) {
+ auto it = layersMap.find(ref);
+ if (it == layersMap.end()) {
Log::Warning(Event::ParseStyle, "layer '%s' references unknown layer %s", layer->id.c_str(), ref.c_str());
// We cannot parse this layer further.
return;
diff --git a/src/mbgl/style/style_parser.hpp b/src/mbgl/style/style_parser.hpp
index 736cb9e9fa..9ef74c8dc1 100644
--- a/src/mbgl/style/style_parser.hpp
+++ b/src/mbgl/style/style_parser.hpp
@@ -17,7 +17,6 @@ namespace mbgl {
enum class ClassID : uint32_t;
class StyleLayer;
-class StyleLayerGroup;
class StyleParser {
public:
@@ -27,8 +26,8 @@ public:
void parse(JSVal document);
- util::ptr<StyleLayerGroup> getLayers() {
- return root;
+ std::vector<util::ptr<StyleLayer>> getLayers() {
+ return layers;
}
std::string getSprite() const {
@@ -44,10 +43,7 @@ private:
JSVal replaceConstant(JSVal value);
void parseSources(JSVal value);
-
- std::unique_ptr<StyleLayerGroup> createLayers(JSVal value);
- util::ptr<StyleLayer> createLayer(JSVal value);
- void parseLayers();
+ void parseLayers(JSVal value);
void parseLayer(std::pair<JSVal, util::ptr<StyleLayer>> &pair);
void parsePaints(JSVal value, std::map<ClassID, ClassProperties> &paints);
void parsePaint(JSVal, ClassProperties &properties);
@@ -97,10 +93,10 @@ private:
std::unordered_map<std::string, const util::ptr<StyleSource>> sources;
// This stores the root layer.
- util::ptr<StyleLayerGroup> root;
+ std::vector<util::ptr<StyleLayer>> layers;
// This maps ids to Layer objects, with all items being at the root level.
- std::unordered_map<std::string, std::pair<JSVal, util::ptr<StyleLayer>>> layers;
+ std::unordered_map<std::string, std::pair<JSVal, util::ptr<StyleLayer>>> layersMap;
// Store a stack of layers we're parsing right now. This is to prevent reference cycles.
std::forward_list<StyleLayer *> stack;
diff --git a/src/mbgl/text/collision.cpp b/src/mbgl/text/collision.cpp
index 2e0ec6dce2..422cd0a60a 100644
--- a/src/mbgl/text/collision.cpp
+++ b/src/mbgl/text/collision.cpp
@@ -91,7 +91,7 @@ GlyphBox getMergedGlyphs(const GlyphBoxes &boxes, const CollisionAnchor &anchor)
mergedGlyphs.anchor = anchor;
CollisionRect &box = mergedGlyphs.box;
- for (const GlyphBox &glyph : boxes) {
+ for (const auto& glyph : boxes) {
const CollisionRect &gbox = glyph.box;
box.tl.x = util::min(box.tl.x, gbox.tl.x);
box.tl.y = util::min(box.tl.y, gbox.tl.y);
@@ -105,7 +105,7 @@ GlyphBox getMergedGlyphs(const GlyphBoxes &boxes, const CollisionAnchor &anchor)
float Collision::getPlacementScale(const GlyphBoxes &glyphs, float minPlacementScale, bool avoidEdges) {
- for (const GlyphBox &glyph : glyphs) {
+ for (const auto& glyph : glyphs) {
const CollisionRect &box = glyph.box;
const CollisionRect &bbox = glyph.hBox ? glyph.hBox.get() : glyph.box;
const CollisionAnchor &anchor = glyph.anchor;
@@ -141,7 +141,7 @@ float Collision::getPlacementScale(const GlyphBoxes &glyphs, float minPlacementS
const CollisionAnchor &na = anchor; // new anchor
const CollisionRect &nb = box; // new box
- for (const PlacementValue &value : blocking) {
+ for (const auto& value : blocking) {
const PlacementBox &placement = std::get<1>(value);
const CollisionAnchor &oa = placement.anchor; // old anchor
const CollisionRect &ob = placement.box; // old box
@@ -198,7 +198,7 @@ PlacementRange Collision::getPlacementRange(const GlyphBoxes &glyphs, float plac
bool horizontal) {
PlacementRange placementRange = {{2.0f * M_PI, 0}};
- for (const GlyphBox &glyph : glyphs) {
+ for (const auto& glyph : glyphs) {
const CollisionRect &bbox = glyph.hBox ? glyph.hBox.get() : glyph.box;
const CollisionAnchor &anchor = glyph.anchor;
@@ -216,7 +216,7 @@ PlacementRange Collision::getPlacementRange(const GlyphBoxes &glyphs, float plac
cTree.query(bgi::intersects(query_box), std::back_inserter(blocking));
}
- for (const PlacementValue &value : blocking) {
+ for (const auto& value : blocking) {
const Box &s = std::get<0>(value);
const PlacementBox &b = std::get<1>(value);
const CollisionRect &bbox2 = b.hBox ? b.hBox.get() : b.box;
@@ -265,7 +265,7 @@ void Collision::insert(const GlyphBoxes &glyphs, const CollisionAnchor &anchor,
std::vector<PlacementValue> allBounds;
allBounds.reserve(glyphs.size());
- for (const GlyphBox &glyph : glyphs) {
+ for (const auto& glyph : glyphs) {
const CollisionRect &box = glyph.box;
const CollisionRect &bbox = glyph.hBox ? glyph.hBox.get() : glyph.box;
diff --git a/src/mbgl/text/collision.hpp b/src/mbgl/text/collision.hpp
index b009982997..bba07b0fb1 100644
--- a/src/mbgl/text/collision.hpp
+++ b/src/mbgl/text/collision.hpp
@@ -4,6 +4,7 @@
#include <mbgl/text/types.hpp>
#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wshadow"
diff --git a/src/mbgl/text/glyph_store.cpp b/src/mbgl/text/glyph_store.cpp
index ab1776c04b..fd8f99ea5b 100644
--- a/src/mbgl/text/glyph_store.cpp
+++ b/src/mbgl/text/glyph_store.cpp
@@ -68,7 +68,7 @@ void align(Shaping &shaping, const float justify, const float horizontalAlign,
const float shiftX = (justify - horizontalAlign) * maxLineLength;
const float shiftY = (-verticalAlign * (line + 1) + 0.5) * lineHeight;
- for (PositionedGlyph &glyph : shaping) {
+ for (auto& glyph : shaping) {
glyph.x += shiftX;
glyph.y += shiftY;
}
@@ -251,7 +251,7 @@ void GlyphStore::waitForGlyphRanges(const std::string &fontStack, const std::set
// Attempt to load the glyph range. If the GlyphSet already exists, we are getting back
// the same shared_future.
- for (GlyphRange range : glyphRanges) {
+ for (const auto range : glyphRanges) {
futures.emplace_back(loadGlyphRange(fontStack, rangeSets, range));
}
}
@@ -259,7 +259,7 @@ void GlyphStore::waitForGlyphRanges(const std::string &fontStack, const std::set
// Now that we potentially created all GlyphSets, we are waiting for the results, one by one.
// When we get a result (or the GlyphSet is aready loaded), we are attempting to parse the
// GlyphSet.
- for (std::shared_future<GlyphPBF &> &future : futures) {
+ for (const auto& future : futures) {
future.get().parse(stack);
}
}
diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp
index 9d9e82c75c..6a142cdf65 100644
--- a/src/mbgl/text/placement.cpp
+++ b/src/mbgl/text/placement.cpp
@@ -110,7 +110,7 @@ GlyphBox getMergedBoxes(const GlyphBoxes &glyphs, const Anchor &anchor) {
CollisionRect &box = mergedglyphs.box;
- for (const GlyphBox &glyph : glyphs) {
+ for (const auto& glyph : glyphs) {
const CollisionRect &gbox = glyph.box;
box.tl.x = util::min(box.tl.x, gbox.tl.x);
box.tl.y = util::min(box.tl.y, gbox.tl.y);
@@ -211,7 +211,7 @@ Placement Placement::getGlyphs(Anchor &anchor, const vec2<float> &origin, const
const uint32_t buffer = 3;
- for (const PositionedGlyph &shape : shaping) {
+ for (const auto& shape : shaping) {
auto face_it = face.find(shape.glyph);
if (face_it == face.end())
continue;
@@ -250,7 +250,7 @@ Placement Placement::getGlyphs(Anchor &anchor, const vec2<float> &origin, const
const CollisionRect obox{boxScale * x1, boxScale * y1, boxScale * x2, boxScale * y2};
- for (const GlyphInstance &instance : glyphInstances) {
+ for (const auto& instance : glyphInstances) {
vec2<float> tl = otl;
vec2<float> tr = otr;
vec2<float> bl = obl;
@@ -301,7 +301,7 @@ Placement Placement::getGlyphs(Anchor &anchor, const vec2<float> &origin, const
const float minPlacementScale = anchor.scale;
placement.minScale = std::numeric_limits<float>::infinity();
- for (const GlyphBox &box : placement.boxes) {
+ for (const auto& box : placement.boxes) {
placement.minScale = util::min(placement.minScale, box.minScale);
}
placement.minScale = util::max(minPlacementScale, Placement::globalMinScale);
diff --git a/src/mbgl/text/rotation_range.cpp b/src/mbgl/text/rotation_range.cpp
index 664ea9c709..efaa1c67ed 100644
--- a/src/mbgl/text/rotation_range.cpp
+++ b/src/mbgl/text/rotation_range.cpp
@@ -17,7 +17,7 @@ CollisionRange mergeCollisions(const CollisionList &collisions,
float min = 2.0f * M_PI;
float max = 0.0f;
- for (CollisionRange collision : collisions) {
+ for (const auto& collision : collisions) {
bool entryOutside =
ignoreRange[0] <= collision[0] && collision[0] <= ignoreRange[1];
bool exitOutside =
diff --git a/src/mbgl/util/clip_ids.cpp b/src/mbgl/util/clip_ids.cpp
index 8b1dcf8dd0..e7833b679f 100644
--- a/src/mbgl/util/clip_ids.cpp
+++ b/src/mbgl/util/clip_ids.cpp
@@ -18,7 +18,7 @@ ClipIDGenerator::Leaf::Leaf(Tile &tile_) : tile(tile_) {}
void ClipIDGenerator::Leaf::add(const Tile::ID &p) {
if (p.isChildOf(tile.id)) {
// Ensure that no already present child is a parent of the new p.
- for (const Tile::ID &child : children) {
+ for (const auto& child : children) {
if (p.isChildOf(child))
return;
}
@@ -31,7 +31,7 @@ bool ClipIDGenerator::Leaf::operator==(const Leaf &other) const {
}
bool ClipIDGenerator::reuseExisting(Leaf &leaf) {
- for (const std::vector<Leaf> &pool : pools) {
+ for (const auto& pool : pools) {
auto existing = std::find(pool.begin(), pool.end(), leaf);
if (existing != pool.end()) {
leaf.tile.clip = existing->tile.clip;
@@ -80,7 +80,7 @@ void ClipIDGenerator::update(std::forward_list<Tile *> tiles) {
// We are starting our count with 1 since we need at least 1 bit set to distinguish between
// areas without any tiles whatsoever and the current area.
uint8_t count = 1;
- for (Leaf &leaf : pool) {
+ for (auto& leaf : pool) {
leaf.tile.clip.mask = mask;
leaf.tile.clip.reference = count++ << bit_offset;
}
diff --git a/src/mbgl/util/mapbox.cpp b/src/mbgl/util/mapbox.cpp
index 5d9c630c11..a8da81d1fd 100644
--- a/src/mbgl/util/mapbox.cpp
+++ b/src/mbgl/util/mapbox.cpp
@@ -8,11 +8,12 @@ namespace mapbox {
const std::string mapbox = "mapbox://";
-std::string normalizeURL(const std::string& url, const std::string& accessToken) {
+std::string normalizeURL(const std::string& url, const std::string& pathPrefix, const std::string& accessToken) {
if (accessToken.empty())
throw std::runtime_error("You must provide a Mapbox API access token for Mapbox tile sources");
- return std::string("https://api.tiles.mapbox.com/v4/")
+ return std::string("https://api.tiles.mapbox.com")
+ + pathPrefix
+ url.substr(mapbox.length())
+ "?access_token="
+ accessToken;
@@ -22,7 +23,7 @@ std::string normalizeSourceURL(const std::string& url, const std::string& access
if (url.compare(0, mapbox.length(), mapbox) != 0)
return url;
- std::string result = normalizeURL(url + ".json", accessToken);
+ std::string result = normalizeURL(url + ".json", "/v4/", accessToken);
// TileJSON requests need a secure flag appended to their URLs so
// that the server knows to send SSL-ified resource references.
@@ -31,11 +32,20 @@ std::string normalizeSourceURL(const std::string& url, const std::string& access
return result;
}
+std::string normalizeStyleURL(const std::string& url, const std::string& accessToken) {
+ if (url.compare(0, mapbox.length(), mapbox) != 0)
+ return url;
+
+ const std::string user = url.substr(mapbox.length(), url.find('.') - mapbox.length());
+
+ return normalizeURL(url, "/styles/v1/" + user + "/", accessToken);
+}
+
std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken) {
if (url.compare(0, mapbox.length(), mapbox) != 0)
return url;
- return normalizeURL(url, accessToken);
+ return normalizeURL(url, "/v4/", accessToken);
}
std::string normalizeTileURL(const std::string& url, const std::string& sourceURL, SourceType sourceType) {
diff --git a/src/mbgl/util/mapbox.hpp b/src/mbgl/util/mapbox.hpp
index 8ad92c0b40..86ea349b8c 100644
--- a/src/mbgl/util/mapbox.hpp
+++ b/src/mbgl/util/mapbox.hpp
@@ -9,6 +9,7 @@ namespace util {
namespace mapbox {
std::string normalizeSourceURL(const std::string& url, const std::string& accessToken);
+std::string normalizeStyleURL(const std::string& url, const std::string& accessToken);
std::string normalizeGlyphsURL(const std::string& url, const std::string& accessToken);
std::string normalizeTileURL(const std::string& url, const std::string& sourceURL, SourceType sourceType);
diff --git a/src/mbgl/util/merge_lines.cpp b/src/mbgl/util/merge_lines.cpp
index 7eb8306707..4ff1caaf76 100644
--- a/src/mbgl/util/merge_lines.cpp
+++ b/src/mbgl/util/merge_lines.cpp
@@ -1,13 +1,16 @@
#include "merge_lines.hpp"
-#include <sstream>
+
+#include <boost/functional/hash.hpp>
namespace mbgl {
namespace util {
+using Index = std::map<size_t, unsigned int>;
+
unsigned int mergeFromRight(std::vector<SymbolFeature> &features,
- std::map<std::string, unsigned int> &rightIndex,
- std::map<std::string, unsigned int>::iterator left,
- std::string &rightKey,
+ Index &rightIndex,
+ Index::iterator left,
+ size_t rightKey,
std::vector<std::vector<Coordinate>> &geom) {
unsigned int index = left->second;
@@ -21,9 +24,9 @@ unsigned int mergeFromRight(std::vector<SymbolFeature> &features,
}
unsigned int mergeFromLeft(std::vector<SymbolFeature> &features,
- std::map<std::string, unsigned int> &leftIndex,
- std::string &leftKey,
- std::map<std::string, unsigned int>::iterator right,
+ Index &leftIndex,
+ size_t leftKey,
+ Index::iterator right,
std::vector<std::vector<Coordinate>> &geom) {
unsigned int index = right->second;
@@ -37,21 +40,20 @@ unsigned int mergeFromLeft(std::vector<SymbolFeature> &features,
return index;
}
-std::string
-getKey(const std::u32string &text, const std::vector<std::vector<Coordinate>> &geom, bool onRight) {
- const Coordinate &coord = onRight ? geom[0].back() : geom[0].front();
- std::ostringstream key;
- for (const char32_t &c : text) {
- key << (char)c;
- }
- key << ":" << coord.x << ":" << coord.y;
- return key.str();
+size_t
+getKey(const std::u32string& text, const std::vector<std::vector<Coordinate>>& geom, bool onRight) {
+ const Coordinate& coord = onRight ? geom[0].back() : geom[0].front();
+
+ auto hash = std::hash<std::u32string>()(text);
+ boost::hash_combine(hash, coord.x);
+ boost::hash_combine(hash, coord.y);
+ return hash;
}
void mergeLines(std::vector<SymbolFeature> &features) {
- std::map<std::string, unsigned int> leftIndex;
- std::map<std::string, unsigned int> rightIndex;
+ Index leftIndex;
+ Index rightIndex;
for (unsigned int k = 0; k < features.size(); k++) {
SymbolFeature &feature = features[k];
@@ -61,11 +63,11 @@ void mergeLines(std::vector<SymbolFeature> &features) {
continue;
}
- std::string leftKey = getKey(feature.label, geometry, false);
- std::string rightKey = getKey(feature.label, geometry, true);
+ const auto leftKey = getKey(feature.label, geometry, false);
+ const auto rightKey = getKey(feature.label, geometry, true);
- auto left = rightIndex.find(leftKey);
- auto right = leftIndex.find(rightKey);
+ const auto left = rightIndex.find(leftKey);
+ const auto right = leftIndex.find(rightKey);
if ((left != rightIndex.end()) && (right != leftIndex.end()) &&
(left->second != right->second)) {
diff --git a/src/mbgl/util/scaling.cpp b/src/mbgl/util/scaling.cpp
index a554b2e137..efc2709df3 100644
--- a/src/mbgl/util/scaling.cpp
+++ b/src/mbgl/util/scaling.cpp
@@ -49,38 +49,39 @@ namespace util {
void bilinearScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize,
const Rect<uint32_t>& srcPos, uint32_t* dstData, const vec2<uint32_t>& dstSize,
- const Rect<uint32_t>& dstPos) {
+ const Rect<uint32_t>& dstPos, bool wrap) {
const auto factor = getFactor(srcPos, dstPos);
const auto bounds = getBounds(srcSize, srcPos, dstSize, dstPos, factor);
- double fractSrcY = srcPos.y;
- double fractSrcX;
uint32_t x, y;
size_t i = dstSize.x * dstPos.y + dstPos.x;
for (y = 0; y < bounds.y; y++) {
- fractSrcX = srcPos.x;
- const uint32_t srcY0 = fractSrcY;
- const uint32_t srcY1 = std::min(srcY0 + 1, srcSize.y - 1);
+ const double fractY = y * factor.y;
+ const uint32_t Y0 = fractY;
+ const uint32_t Y1 = wrap ? (Y0 + 1) % srcPos.h : (Y0 + 1);
+ const uint32_t srcY0 = srcPos.y + Y0;
+ const uint32_t srcY1 = std::min(srcPos.y + Y1, srcSize.y - 1);
for (x = 0; x < bounds.x; x++) {
- const uint32_t srcX0 = fractSrcX;
- const uint32_t srcX1 = std::min(srcX0 + 1, srcSize.x - 1);
+ const double fractX = x * factor.x;
+ const uint32_t X0 = fractX;
+ const uint32_t X1 = wrap ? (X0 + 1) % srcPos.w : (X0 + 1);
+ const uint32_t srcX0 = srcPos.x + X0;
+ const uint32_t srcX1 = std::min(srcPos.x + X1, srcSize.x - 1);
const uint32_t tl = srcData[srcSize.x * srcY0 + srcX0];
const uint32_t tr = srcData[srcSize.x * srcY0 + srcX1];
const uint32_t bl = srcData[srcSize.x * srcY1 + srcX0];
const uint32_t br = srcData[srcSize.x * srcY1 + srcX1];
- const double dx = fractSrcX - srcX0;
- const double dy = fractSrcY - srcY0;
+ const double dx = fractX - X0;
+ const double dy = fractY - Y0;
uint32_t& dst = dstData[i + x];
b<0>(dst) = bilinearInterpolate(b<0>(tl), b<0>(tr), b<0>(bl), b<0>(br), dx, dy);
b<1>(dst) = bilinearInterpolate(b<1>(tl), b<1>(tr), b<1>(bl), b<1>(br), dx, dy);
b<2>(dst) = bilinearInterpolate(b<2>(tl), b<2>(tr), b<2>(bl), b<2>(br), dx, dy);
b<3>(dst) = bilinearInterpolate(b<3>(tl), b<3>(tr), b<3>(bl), b<3>(br), dx, dy);
- fractSrcX += factor.x;
}
i += dstSize.x;
- fractSrcY += factor.y;
}
}
@@ -108,4 +109,4 @@ void nearestNeighborScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize
}
}
-} \ No newline at end of file
+}
diff --git a/src/mbgl/util/scaling.hpp b/src/mbgl/util/scaling.hpp
index d2625e9219..74a43eb621 100644
--- a/src/mbgl/util/scaling.hpp
+++ b/src/mbgl/util/scaling.hpp
@@ -12,7 +12,7 @@ namespace util {
void bilinearScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize,
const Rect<uint32_t>& srcPos, uint32_t* dstData, const vec2<uint32_t>& dstSize,
- const Rect<uint32_t>& dstPos);
+ const Rect<uint32_t>& dstPos, bool wrap);
void nearestNeighborScale(const uint32_t* srcData, const vec2<uint32_t>& srcSize,
const Rect<uint32_t>& srcPos, uint32_t* dstData,