From 03d5e2da80111e225c2478286b60dd4e9b7ec527 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Tue, 19 May 2015 09:52:01 -0400 Subject: [PATCH] port sprite atlas pollution fix fixes #1398 js: 212760981493460b438f1cc117001825773fad91 https://github.com/mapbox/mapbox-gl-js/pull/1195 The sprite atlas already had two empty pixels between each each icon. But the icon's real boundary isn't used for drawing. Drawing uses an icon's box rounded up to the nearest multiple of four. Sometimes this rounded boundary was directly on the edge of another icon. When the icon was sampled with linear interpolation it's edge would get polluted with values from the other icon. This commit shifts all icons and glyphs by 1px so that there is padding on all sides of the box being drawn. The quads used for drawing are shifted in the opposite direction by 1px to compensate for this. --- src/mbgl/geometry/glyph_atlas.cpp | 7 ++++--- src/mbgl/geometry/sprite_atlas.cpp | 12 ++++++++---- src/mbgl/text/placement.cpp | 8 +++++--- 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/mbgl/geometry/glyph_atlas.cpp b/src/mbgl/geometry/glyph_atlas.cpp index bb230e4ef..02271b9c7 100644 --- a/src/mbgl/geometry/glyph_atlas.cpp +++ b/src/mbgl/geometry/glyph_atlas.cpp @@ -69,8 +69,9 @@ Rect GlyphAtlas::addGlyph(uintptr_t tileUID, uint16_t buffered_height = glyph.metrics.height + buffer * 2; // Add a 1px border around every image. - uint16_t pack_width = buffered_width; - uint16_t pack_height = buffered_height; + const uint16_t padding = 1; + uint16_t pack_width = buffered_width + 2 * padding; + uint16_t pack_height = buffered_height + 2 * padding; // Increase to next number divisible by 4, but at least 1. // This is so we can scale down the texture coordinates and pack them @@ -92,7 +93,7 @@ Rect GlyphAtlas::addGlyph(uintptr_t tileUID, // Copy the bitmap const uint8_t* source = reinterpret_cast(glyph.bitmap.data()); for (uint32_t y = 0; y < buffered_height; y++) { - uint32_t y1 = width * (rect.y + y) + rect.x; + uint32_t y1 = width * (rect.y + y + padding) + rect.x + padding; uint32_t y2 = buffered_width * y; for (uint32_t x = 0; x < buffered_width; x++) { data[y1 + x] = source[y2 + x]; diff --git a/src/mbgl/geometry/sprite_atlas.cpp b/src/mbgl/geometry/sprite_atlas.cpp index 5d47793cf..4e05c94ad 100644 --- a/src/mbgl/geometry/sprite_atlas.cpp +++ b/src/mbgl/geometry/sprite_atlas.cpp @@ -127,10 +127,12 @@ SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, bool repea rect.h = pos.height / pos.pixelRatio; } + const float padding = 1; + return SpriteAtlasPosition { {{ float(rect.w), float(rect.h) }}, - {{ float(rect.x) / width, float(rect.y) / height }}, - {{ float(rect.x + rect.w) / width, float(rect.y + rect.h) / height }} + {{ float(rect.x + padding) / width, float(rect.y + padding) / height }}, + {{ float(rect.x + padding + rect.w) / width, float(rect.y + padding + rect.h) / height }} }; } @@ -151,12 +153,14 @@ void SpriteAtlas::copy(const Rect& dst, const SpritePosition& src, co const vec2 srcSize { sprite->raster->getWidth(), sprite->raster->getHeight() }; const Rect srcPos { src.x, src.y, src.width, src.height }; + const int offset = 1; + allocate(); uint32_t *const dstData = data.get(); const vec2 dstSize { static_cast(width * pixelRatio), static_cast(height * pixelRatio) }; - const Rect dstPos { static_cast(dst.x * pixelRatio), - static_cast(dst.y * pixelRatio), + const Rect dstPos { static_cast((offset + dst.x) * pixelRatio), + static_cast((offset + dst.y) * pixelRatio), static_cast(dst.originalW * pixelRatio), static_cast(dst.originalH * pixelRatio) }; diff --git a/src/mbgl/text/placement.cpp b/src/mbgl/text/placement.cpp index bee3a073e..6c24d26fd 100644 --- a/src/mbgl/text/placement.cpp +++ b/src/mbgl/text/placement.cpp @@ -135,11 +135,12 @@ GlyphBox getMergedBoxes(const GlyphBoxes &glyphs, const Anchor &anchor) { Placement Placement::getIcon(Anchor &anchor, const Rect &image, float boxScale, const std::vector &line, const StyleLayoutSymbol &layout) { + const float padding = 1.0f; const float dx = layout.icon.offset[0]; const float dy = layout.icon.offset[1]; - float x1 = dx - image.originalW / 2.0f; + float x1 = dx - image.originalW / 2.0f - padding; float x2 = x1 + image.w; - float y1 = dy - image.originalH / 2.0f; + float y1 = dy - image.originalH / 2.0f - padding; float y2 = y1 + image.h; vec2 tl{x1, y1}; @@ -212,7 +213,8 @@ Placement Placement::getGlyphs(Anchor &anchor, const vec2 &origin, const Placement placement; - const uint32_t buffer = 3; + const uint32_t glyphPadding = 1; + const uint32_t buffer = 3 + glyphPadding; for (const auto& shape : shaping) { auto face_it = face.find(shape.glyph);