[core] match icon rendering with -js

port https://github.com/mapbox/mapbox-gl-js/pull/1919/files
This commit is contained in:
Ansis Brammanis
2016-01-12 12:58:55 -08:00
parent 618902e06c
commit bdfa1277a5
9 changed files with 46 additions and 36 deletions

View File

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

View File

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

View File

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

View File

@@ -112,6 +112,7 @@ private:
public:
SymbolLayoutProperties layout;
bool sdfIcons = false;
bool iconsNeedLinear = false;
private:

View File

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

View File

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

View File

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

View File

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

View File

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