From fcf5d1b8af5ca01f8634107f00fbc843c892dd48 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 13 Apr 2017 12:15:23 -0700 Subject: [core] Combine two GlyphID-keyed maps in GlyphAtlas::Entry --- src/mbgl/text/glyph_atlas.cpp | 79 ++++++++++++++++++------------------------- src/mbgl/text/glyph_atlas.hpp | 14 ++++---- 2 files changed, 39 insertions(+), 54 deletions(-) diff --git a/src/mbgl/text/glyph_atlas.cpp b/src/mbgl/text/glyph_atlas.cpp index 04b48f11c9..4feaab01f9 100644 --- a/src/mbgl/text/glyph_atlas.cpp +++ b/src/mbgl/text/glyph_atlas.cpp @@ -96,10 +96,14 @@ void GlyphAtlas::processResponse(const Response& res, const FontStack& fontStack } for (auto& glyph : glyphs) { - auto it = entry.sdfs.find(glyph.id); - if (it == entry.sdfs.end()) { + auto it = entry.glyphs.find(glyph.id); + if (it == entry.glyphs.end()) { // Glyph doesn't exist yet. - entry.sdfs.emplace(glyph.id, std::move(glyph)); + entry.glyphs.emplace(glyph.id, GlyphValue { + std::move(glyph.bitmap), + std::move(glyph.metrics), + {}, {} + }); } else if (it->second.metrics == glyph.metrics) { if (it->second.bitmap != glyph.bitmap) { // The actual bitmap was updated; this is unsupported. @@ -146,17 +150,19 @@ void GlyphAtlas::addGlyphs(GlyphRequestor& requestor, const GlyphDependencies& g Entry& entry = entries[fontStack]; for (const auto& glyphID : glyphIDs) { + // Make a glyph position entry even if we didn't get an SDF for the glyph. During layout, + // an empty optional is treated as "loaded but nothing to show", wheras no entry in the + // positions map means "not loaded yet". optional& glyph = positions[glyphID]; - auto it = entry.sdfs.find(glyphID); - if (it == entry.sdfs.end()) + auto it = entry.glyphs.find(glyphID); + if (it == entry.glyphs.end()) continue; - addGlyph(requestor, fontStack, it->second); + it->second.ids.insert(&requestor); - auto valueIt = entry.glyphValues.find(glyphID); glyph = Glyph { - valueIt == entry.glyphValues.end() ? Rect() : valueIt->second.rect, + addGlyph(it->second), it->second.metrics }; } @@ -165,31 +171,21 @@ void GlyphAtlas::addGlyphs(GlyphRequestor& requestor, const GlyphDependencies& g requestor.onGlyphsAvailable(glyphPositions); } -void GlyphAtlas::addGlyph(GlyphRequestor& requestor, - const FontStack& fontStack, - const SDFGlyph& glyph) -{ - std::map& face = entries[fontStack].glyphValues; - auto it = face.find(glyph.id); - +Rect GlyphAtlas::addGlyph(GlyphValue& value) { // The glyph is already in this texture. - if (it != face.end()) { - GlyphValue& value = it->second; - value.ids.insert(&requestor); - return; + if (value.rect) { + return *value.rect; } - // Guard against glyphs that are too large, or that we don't need to place into the atlas since - // they don't have any pixels. - if (glyph.metrics.width == 0 || glyph.metrics.width >= 256 || - glyph.metrics.height == 0 || glyph.metrics.height >= 256) { - return; + // We don't need to add glyphs without a bitmap (e.g. whitespace). + if (!value.bitmap.valid()) { + return {}; } // Add a 1px border around every image. const uint32_t padding = 1; - uint16_t width = glyph.bitmap.size.width + 2 * padding; - uint16_t height = glyph.bitmap.size.height + 2 * padding; + uint16_t width = value.bitmap.size.width + 2 * padding; + uint16_t height = value.bitmap.size.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 @@ -200,23 +196,21 @@ void GlyphAtlas::addGlyph(GlyphRequestor& requestor, Rect rect = bin.allocate(width, height); if (rect.w == 0) { Log::Error(Event::OpenGL, "glyph bitmap overflow"); - return; + return {}; } - face.emplace(glyph.id, GlyphValue { rect, &requestor }); - - AlphaImage::copy(glyph.bitmap, image, { 0, 0 }, { rect.x + padding, rect.y + padding }, glyph.bitmap.size); - + AlphaImage::copy(value.bitmap, image, { 0, 0 }, { rect.x + padding, rect.y + padding }, value.bitmap.size); + value.rect = rect; dirty = true; + + return rect; } -void GlyphAtlas::removeGlyphValues(GlyphRequestor& requestor, std::map& face) { - for (auto it = face.begin(); it != face.end(); /* we advance in the body */) { +void GlyphAtlas::removeGlyphValues(GlyphRequestor& requestor, std::map& values) { + for (auto it = values.begin(); it != values.end(); it++) { GlyphValue& value = it->second; - value.ids.erase(&requestor); - - if (value.ids.empty()) { - const Rect& rect = value.rect; + if (value.ids.erase(&requestor) && value.ids.empty() && value.rect) { + const Rect& rect = *value.rect; // Clear out the bitmap. uint8_t *target = image.data.get(); @@ -228,14 +222,7 @@ void GlyphAtlas::removeGlyphValues(GlyphRequestor& requestor, std::map #include #include -#include #include #include #include @@ -71,9 +70,9 @@ private: std::string glyphURL; struct GlyphValue { - GlyphValue(Rect rect_, GlyphRequestor* id) - : rect(std::move(rect_)), ids({ id }) {} - Rect rect; + AlphaImage bitmap; + GlyphMetrics metrics; + optional> rect; std::unordered_set ids; }; @@ -85,8 +84,7 @@ private: struct Entry { std::map ranges; - std::map sdfs; - std::map glyphValues; + std::map glyphs; }; std::unordered_map entries; @@ -95,9 +93,9 @@ private: void processResponse(const Response&, const FontStack&, const GlyphRange&); void addGlyphs(GlyphRequestor&, const GlyphDependencies&); - void addGlyph(GlyphRequestor&, const FontStack&, const SDFGlyph&); + Rect addGlyph(GlyphValue&); - void removeGlyphValues(GlyphRequestor&, std::map&); + void removeGlyphValues(GlyphRequestor&, std::map&); void removePendingRanges(GlyphRequestor&, std::map&); GlyphAtlasObserver* observer = nullptr; -- cgit v1.2.1