diff options
Diffstat (limited to 'src/mbgl/text/glyph_atlas.cpp')
-rw-r--r-- | src/mbgl/text/glyph_atlas.cpp | 79 |
1 files changed, 23 insertions, 56 deletions
diff --git a/src/mbgl/text/glyph_atlas.cpp b/src/mbgl/text/glyph_atlas.cpp index dc1fe2b1d9..1b3f7518b5 100644 --- a/src/mbgl/text/glyph_atlas.cpp +++ b/src/mbgl/text/glyph_atlas.cpp @@ -23,16 +23,17 @@ GlyphAtlas::GlyphAtlas(const Size size, FileSource& fileSource_) GlyphAtlas::~GlyphAtlas() = default; void GlyphAtlas::requestGlyphRange(const FontStack& fontStack, const GlyphRange& range) { - std::lock_guard<std::mutex> lock(rangesMutex); - auto& rangeSets = ranges[fontStack]; + std::lock_guard<std::mutex> lock(mutex); + auto& rangeSets = entries[fontStack].ranges; const auto& rangeSetsIt = rangeSets.find(range); if (rangeSetsIt != rangeSets.end()) { return; } - rangeSets.emplace(range, - std::make_unique<GlyphPBF>(this, fontStack, range, observer, fileSource)); + rangeSets.emplace(std::piecewise_construct, + std::forward_as_tuple(range), + std::forward_as_tuple(this, fontStack, range, observer, fileSource)); } bool GlyphAtlas::hasGlyphRanges(const FontStack& fontStack, const GlyphRangeSet& glyphRanges) { @@ -40,8 +41,8 @@ bool GlyphAtlas::hasGlyphRanges(const FontStack& fontStack, const GlyphRangeSet& return true; } - std::lock_guard<std::mutex> lock(rangesMutex); - const auto& rangeSets = ranges[fontStack]; + std::lock_guard<std::mutex> lock(mutex); + const auto& rangeSets = entries[fontStack].ranges; bool hasRanges = true; for (const auto& range : glyphRanges) { @@ -55,7 +56,7 @@ bool GlyphAtlas::hasGlyphRanges(const FontStack& fontStack, const GlyphRangeSet& continue; } - if (!rangeSetsIt->second->isParsed()) { + if (!rangeSetsIt->second.isParsed()) { hasRanges = false; } } @@ -64,16 +65,8 @@ bool GlyphAtlas::hasGlyphRanges(const FontStack& fontStack, const GlyphRangeSet& } util::exclusive<GlyphSet> GlyphAtlas::getGlyphSet(const FontStack& fontStack) { - auto lock = std::make_unique<std::lock_guard<std::mutex>>(glyphSetsMutex); - - auto it = glyphSets.find(fontStack); - if (it == glyphSets.end()) { - it = glyphSets.emplace(fontStack, std::make_unique<GlyphSet>()).first; - } - - // FIXME: We lock all GlyphSets, but what we should - // really do is lock only the one we are returning. - return { it->second.get(), std::move(lock) }; + auto lock = std::make_unique<std::lock_guard<std::mutex>>(mutex); + return { &entries[fontStack].glyphSet, std::move(lock) }; } void GlyphAtlas::setObserver(GlyphAtlasObserver* observer_) { @@ -83,12 +76,10 @@ void GlyphAtlas::setObserver(GlyphAtlasObserver* observer_) { void GlyphAtlas::addGlyphs(uintptr_t tileUID, const std::u16string& text, const FontStack& fontStack, - const GlyphSet& glyphSet, + const util::exclusive<GlyphSet>& glyphSet, GlyphPositions& face) { - std::lock_guard<std::mutex> lock(mtx); - - const std::map<uint32_t, SDFGlyph>& sdfs = glyphSet.getSDFs(); + const std::map<uint32_t, SDFGlyph>& sdfs = glyphSet->getSDFs(); for (char16_t chr : text) { @@ -107,7 +98,7 @@ Rect<uint16_t> GlyphAtlas::addGlyph(uintptr_t tileUID, const FontStack& fontStack, const SDFGlyph& glyph) { - std::map<uint32_t, GlyphValue>& face = index[fontStack]; + std::map<uint32_t, GlyphValue>& face = entries[fontStack].glyphValues; auto it = face.find(glyph.id); // The glyph is already in this texture. @@ -124,48 +115,26 @@ Rect<uint16_t> GlyphAtlas::addGlyph(uintptr_t tileUID, return Rect<uint16_t>{ 0, 0, 0, 0 }; } - uint16_t buffered_width = glyph.metrics.width + SDFGlyph::borderSize * 2; - uint16_t buffered_height = glyph.metrics.height + SDFGlyph::borderSize * 2; - - // Guard against mismatches between the glyph bitmap size and the size mandated by - // its metrics. - if (size_t(buffered_width * buffered_height) != glyph.bitmap.size()) { - return Rect<uint16_t>{ 0, 0, 0, 0 }; - } - // Add a 1px border around every image. - const uint16_t padding = 1; - uint16_t pack_width = buffered_width + 2 * padding; - uint16_t pack_height = buffered_height + 2 * padding; + const uint32_t padding = 1; + uint16_t width = glyph.bitmap.size.width + 2 * padding; + uint16_t height = glyph.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 // into 2 bytes rather than 4 bytes. - pack_width += (4 - pack_width % 4); - pack_height += (4 - pack_height % 4); + width += (4 - width % 4); + height += (4 - height % 4); - Rect<uint16_t> rect = bin.allocate(pack_width, pack_height); + Rect<uint16_t> rect = bin.allocate(width, height); if (rect.w == 0) { Log::Error(Event::OpenGL, "glyph bitmap overflow"); return rect; } - // Verify that binpack didn't produce a rect that goes beyond the size of the image. - // This should never happen. - assert(rect.x + rect.w <= image.size.width); - assert(rect.y + rect.h <= image.size.height); - face.emplace(glyph.id, GlyphValue { rect, tileUID }); - // Copy the bitmap - const uint8_t* source = reinterpret_cast<const uint8_t*>(glyph.bitmap.data()); - for (uint32_t y = 0; y < buffered_height; y++) { - uint32_t y1 = image.size.width * (rect.y + y + padding) + rect.x + padding; - uint32_t y2 = buffered_width * y; - for (uint32_t x = 0; x < buffered_width; x++) { - image.data[y1 + x] = source[y2 + x]; - } - } + AlphaImage::copy(glyph.bitmap, image, { 0, 0 }, { rect.x + padding, rect.y + padding }, glyph.bitmap.size); dirty = true; @@ -173,10 +142,10 @@ Rect<uint16_t> GlyphAtlas::addGlyph(uintptr_t tileUID, } void GlyphAtlas::removeGlyphs(uintptr_t tileUID) { - std::lock_guard<std::mutex> lock(mtx); + std::lock_guard<std::mutex> lock(mutex); - for (auto& faces : index) { - std::map<uint32_t, GlyphValue>& face = faces.second; + for (auto& entry : entries) { + std::map<uint32_t, GlyphValue>& face = entry.second.glyphValues; for (auto it = face.begin(); it != face.end(); /* we advance in the body */) { GlyphValue& value = it->second; value.ids.erase(tileUID); @@ -212,8 +181,6 @@ Size GlyphAtlas::getSize() const { } void GlyphAtlas::upload(gl::Context& context, gl::TextureUnit unit) { - std::lock_guard<std::mutex> lock(mtx); - if (!texture) { texture = context.createTexture(image, unit); } else if (dirty) { |