[core] match icon rendering with -js
port https://github.com/mapbox/mapbox-gl-js/pull/1919/files
This commit is contained in:
@@ -26,7 +26,7 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"aws-sdk": "^2.2.21",
|
||||
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#46c907f48d2b3b8ae6531963cdc40cb07958fd01",
|
||||
"mapbox-gl-test-suite": "mapbox/mapbox-gl-test-suite#c401ec0acb064f819cddd182c63ee9e019bfb18f",
|
||||
"node-gyp": "^3.2.1",
|
||||
"request": "^2.67.0",
|
||||
"tape": "^4.2.2"
|
||||
|
||||
@@ -187,8 +187,9 @@ void Painter::renderSymbol(SymbolBucket& bucket, const SymbolLayer& layer, const
|
||||
const float fontScale = fontSize / 1.0f;
|
||||
|
||||
SpriteAtlas* activeSpriteAtlas = layer.spriteAtlas;
|
||||
activeSpriteAtlas->bind(state.isChanging() || layout.placement == PlacementType::Line
|
||||
|| angleOffset != 0 || fontScale != 1 || sdf || state.getPitch() != 0);
|
||||
const bool iconScaled = fontScale != 1 || data.pixelRatio != activeSpriteAtlas->getPixelRatio() || bucket.iconsNeedLinear;
|
||||
const bool iconTransformed = layout.placement == PlacementType::Line || angleOffset != 0 || state.getPitch() != 0;
|
||||
activeSpriteAtlas->bind(sdf || state.isChanging() || iconScaled || iconTransformed);
|
||||
|
||||
if (sdf) {
|
||||
renderSDF(bucket,
|
||||
|
||||
@@ -248,11 +248,14 @@ void SymbolBucket::addFeatures(uintptr_t tileUID,
|
||||
if (feature.sprite.length()) {
|
||||
auto image = spriteAtlas.getImage(feature.sprite, false);
|
||||
if (image) {
|
||||
shapedIcon = shapeIcon((*image).pos, layout);
|
||||
shapedIcon = shapeIcon(*image, layout);
|
||||
assert((*image).texture);
|
||||
if ((*image).texture->sdf) {
|
||||
sdfIcons = true;
|
||||
}
|
||||
if ((*image).relativePixelRatio != 1.0f) {
|
||||
iconsNeedLinear = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@ private:
|
||||
public:
|
||||
SymbolLayoutProperties layout;
|
||||
bool sdfIcons = false;
|
||||
bool iconsNeedLinear = false;
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -27,7 +27,11 @@ SpriteAtlas::SpriteAtlas(dimension width_, dimension height_, float pixelRatio_,
|
||||
dirty(true) {
|
||||
}
|
||||
|
||||
Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(const size_t pixel_width, const size_t pixel_height) {
|
||||
Rect<SpriteAtlas::dimension> SpriteAtlas::allocateImage(float src_width, float src_height) {
|
||||
|
||||
const uint16_t pixel_width = std::ceil(src_width / pixelRatio);
|
||||
const uint16_t pixel_height = std::ceil(src_height / pixelRatio);
|
||||
|
||||
// Increase to next number divisible by 4, but at least 1.
|
||||
// This is so we can scale down the texture coordinates and pack them
|
||||
// into 2 bytes rather than 4 bytes.
|
||||
@@ -52,7 +56,7 @@ mapbox::util::optional<SpriteAtlasElement> SpriteAtlas::getImage(const std::stri
|
||||
|
||||
auto rect_it = images.find({ name, wrap });
|
||||
if (rect_it != images.end()) {
|
||||
return SpriteAtlasElement { rect_it->second.pos, rect_it->second.texture };
|
||||
return SpriteAtlasElement { rect_it->second.pos, rect_it->second.texture, rect_it->second.texture->pixelRatio / pixelRatio };
|
||||
}
|
||||
|
||||
auto sprite = store.getSprite(name);
|
||||
@@ -60,7 +64,7 @@ mapbox::util::optional<SpriteAtlasElement> SpriteAtlas::getImage(const std::stri
|
||||
return {};
|
||||
}
|
||||
|
||||
Rect<dimension> rect = allocateImage(sprite->width, sprite->height);
|
||||
Rect<dimension> rect = allocateImage(sprite->width * sprite->pixelRatio, sprite->height * sprite->pixelRatio);
|
||||
if (rect.w == 0) {
|
||||
if (debug::spriteWarnings) {
|
||||
Log::Warning(Event::Sprite, "sprite atlas bitmap overflow");
|
||||
@@ -71,7 +75,7 @@ mapbox::util::optional<SpriteAtlasElement> SpriteAtlas::getImage(const std::stri
|
||||
const Holder& holder = images.emplace(Key{ name, wrap }, Holder{ sprite, rect }).first->second;
|
||||
copy(holder, wrap);
|
||||
|
||||
return SpriteAtlasElement { rect, sprite };
|
||||
return SpriteAtlasElement { rect, sprite, sprite->pixelRatio / pixelRatio };
|
||||
}
|
||||
|
||||
mapbox::util::optional<SpriteAtlasPosition> SpriteAtlas::getPosition(const std::string& name, bool repeating) {
|
||||
@@ -83,25 +87,17 @@ mapbox::util::optional<SpriteAtlasPosition> SpriteAtlas::getPosition(const std::
|
||||
}
|
||||
|
||||
auto rect = (*img).pos;
|
||||
if (repeating) {
|
||||
// When the image is repeating, get the correct position of the image, rather than the
|
||||
// one rounded up to 4 pixels.
|
||||
// TODO: Can't we just use originalW/originalH?
|
||||
auto sprite = store.getSprite(name);
|
||||
if (!sprite) {
|
||||
return SpriteAtlasPosition {};
|
||||
}
|
||||
|
||||
rect.w = sprite->width;
|
||||
rect.h = sprite->height;
|
||||
}
|
||||
|
||||
const float padding = 1;
|
||||
auto image = (*img).texture;
|
||||
|
||||
const float w = image->width * (*img).relativePixelRatio;
|
||||
const float h = image->height * (*img).relativePixelRatio;
|
||||
|
||||
return SpriteAtlasPosition {
|
||||
{{ float(rect.w), float(rect.h) }},
|
||||
{{ float(rect.x + padding) / width, float(rect.y + padding) / height }},
|
||||
{{ float(rect.x + padding + rect.w) / width, float(rect.y + padding + rect.h) / height }}
|
||||
{{ float(image->width), float(image->height) }},
|
||||
{{ float(rect.x + padding) / width, float(rect.y + padding) / height }},
|
||||
{{ float(rect.x + padding + w) / width, float(rect.y + padding + h) / height }}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ struct SpriteAtlasPosition {
|
||||
struct SpriteAtlasElement {
|
||||
const Rect<uint16_t> pos;
|
||||
const std::shared_ptr<const SpriteImage> texture;
|
||||
const float relativePixelRatio;
|
||||
};
|
||||
|
||||
class SpriteAtlas : public util::noncopyable {
|
||||
@@ -83,7 +84,7 @@ private:
|
||||
|
||||
using Key = std::pair<std::string, bool>;
|
||||
|
||||
Rect<SpriteAtlas::dimension> allocateImage(size_t width, size_t height);
|
||||
Rect<SpriteAtlas::dimension> allocateImage(float width, float height);
|
||||
void copy(const Holder& holder, const bool wrap);
|
||||
|
||||
std::recursive_mutex mtx;
|
||||
|
||||
@@ -13,11 +13,13 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
|
||||
const std::vector<Coordinate>& line, const SymbolLayoutProperties& layout,
|
||||
const bool alongLine) {
|
||||
|
||||
auto image = *(shapedIcon.image);
|
||||
|
||||
const float border = 1.0;
|
||||
auto left = shapedIcon.left - border;
|
||||
auto right = left + shapedIcon.image.w;
|
||||
auto right = left + image.pos.w / image.relativePixelRatio;
|
||||
auto top = shapedIcon.top - border;
|
||||
auto bottom = top + shapedIcon.image.h;
|
||||
auto bottom = top + image.pos.h / image.relativePixelRatio;
|
||||
vec2<float> tl{left, top};
|
||||
vec2<float> tr{right, top};
|
||||
vec2<float> br{right, bottom};
|
||||
@@ -51,7 +53,7 @@ SymbolQuads getIconQuads(Anchor& anchor, const PositionedIcon& shapedIcon,
|
||||
}
|
||||
|
||||
SymbolQuads quads;
|
||||
quads.emplace_back(tl, tr, bl, br, shapedIcon.image, 0, anchor, globalMinScale, std::numeric_limits<float>::infinity());
|
||||
quads.emplace_back(tl, tr, bl, br, image.pos, 0, anchor, globalMinScale, std::numeric_limits<float>::infinity());
|
||||
return quads;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
PositionedIcon shapeIcon(const Rect<uint16_t>& image, const SymbolLayoutProperties& layout) {
|
||||
PositionedIcon shapeIcon(const SpriteAtlasElement& image, const SymbolLayoutProperties& layout) {
|
||||
float dx = layout.icon.offset.value[0];
|
||||
float dy = layout.icon.offset.value[1];
|
||||
float x1 = dx - image.originalW / 2.0f;
|
||||
float x2 = x1 + image.originalW;
|
||||
float y1 = dy - image.originalH / 2.0f;
|
||||
float y2 = y1 + image.originalH;
|
||||
float x1 = dx - image.texture->width / 2.0f;
|
||||
float x2 = x1 + image.texture->width;
|
||||
float y1 = dy - image.texture->height / 2.0f;
|
||||
float y2 = y1 + image.texture->height;
|
||||
|
||||
return PositionedIcon(image, y1, y2, x1, x2);
|
||||
}
|
||||
|
||||
@@ -2,29 +2,35 @@
|
||||
#define MBGL_TEXT_SHAPING
|
||||
|
||||
#include <mbgl/text/glyph.hpp>
|
||||
#include <mbgl/sprite/sprite_atlas.hpp>
|
||||
#include <mbgl/sprite/sprite_image.hpp>
|
||||
#include <mapbox/optional.hpp>
|
||||
|
||||
#include <mbgl/util/vec.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct SpriteAtlasElement;
|
||||
|
||||
class PositionedIcon {
|
||||
public:
|
||||
inline explicit PositionedIcon() {}
|
||||
inline explicit PositionedIcon(Rect<uint16_t> _image,
|
||||
inline explicit PositionedIcon(const SpriteAtlasElement& _image,
|
||||
float _top, float _bottom, float _left, float _right) :
|
||||
image(_image), top(_top), bottom(_bottom), left(_left), right(_right) {}
|
||||
Rect<uint16_t> image;
|
||||
|
||||
mapbox::util::optional<SpriteAtlasElement> image;
|
||||
float top = 0;
|
||||
float bottom = 0;
|
||||
float left = 0;
|
||||
float right = 0;
|
||||
|
||||
operator bool() const { return image.hasArea(); }
|
||||
operator bool() const { return image && (*image).pos.hasArea(); }
|
||||
};
|
||||
|
||||
class SymbolLayoutProperties;
|
||||
|
||||
PositionedIcon shapeIcon(const Rect<uint16_t>& image, const SymbolLayoutProperties&);
|
||||
PositionedIcon shapeIcon(const SpriteAtlasElement& image, const SymbolLayoutProperties&);
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
|
||||
Reference in New Issue
Block a user