diff --git a/src/modules/graphics/opengl/Font.cpp b/src/modules/graphics/opengl/Font.cpp index cec2dbc82..e1370ecd9 100644 --- a/src/modules/graphics/opengl/Font.cpp +++ b/src/modules/graphics/opengl/Font.cpp @@ -41,7 +41,7 @@ namespace opengl int Font::fontCount = 0; Font::Font(love::font::Rasterizer *r, const Texture::Filter &filter) - : rasterizer(r) + : rasterizers({r}) , height(r->getHeight()) , lineHeight(1) , textureWidth(128) @@ -201,7 +201,7 @@ love::font::GlyphData *Font::getRasterizerGlyphData(uint32 glyph) // Use spaces for the tab 'glyph'. if (glyph == 9 && useSpacesAsTab) { - love::font::GlyphData *spacegd = rasterizer->getGlyphData(32); + love::font::GlyphData *spacegd = rasterizers[0]->getGlyphData(32); love::font::GlyphData::Format fmt = spacegd->getFormat(); love::font::GlyphMetrics gm = {}; @@ -214,7 +214,13 @@ love::font::GlyphData *Font::getRasterizerGlyphData(uint32 glyph) return new love::font::GlyphData(glyph, gm, fmt); } - return rasterizer->getGlyphData(glyph); + for (const StrongRef &r : rasterizers) + { + if (r->hasGlyph(glyph)) + return r->getGlyphData(glyph); + } + + return rasterizers[0]->getGlyphData(glyph); } const Font::Glyph &Font::addGlyph(uint32 glyph) @@ -757,12 +763,12 @@ void Font::unloadVolatile() int Font::getAscent() const { - return rasterizer->getAscent(); + return rasterizers[0]->getAscent(); } int Font::getDescent() const { - return rasterizer->getDescent(); + return rasterizers[0]->getDescent(); } float Font::getBaseline() const @@ -773,12 +779,54 @@ float Font::getBaseline() const bool Font::hasGlyph(uint32 glyph) const { - return rasterizer->hasGlyph(glyph); + for (const StrongRef &r : rasterizers) + { + if (r->hasGlyph(glyph)) + return true; + } + + return false; } bool Font::hasGlyphs(const std::string &text) const { - return rasterizer->hasGlyphs(text); + if (text.size() == 0) + return false; + + try + { + utf8::iterator i(text.begin(), text.begin(), text.end()); + utf8::iterator end(text.end(), text.begin(), text.end()); + + while (i != end) + { + uint32 codepoint = *i++; + + if (!hasGlyph(codepoint)) + return false; + } + } + catch (utf8::exception &e) + { + throw love::Exception("UTF-8 decoding error: %s", e.what()); + } + + return true; +} + +void Font::setFallbacks(const std::vector &fallbacks) +{ + for (const Font *f : fallbacks) + { + if (f->type != this->type) + throw love::Exception("Font fallbacks must be of the same font type."); + } + + rasterizers.resize(1); + + // NOTE: this won't invalidate already-rasterized glyphs. + for (const Font *f : fallbacks) + rasterizers.push_back(f->rasterizers[0]); } uint32 Font::getTextureCacheID() const diff --git a/src/modules/graphics/opengl/Font.h b/src/modules/graphics/opengl/Font.h index a252f4ca8..d7f031a31 100644 --- a/src/modules/graphics/opengl/Font.h +++ b/src/modules/graphics/opengl/Font.h @@ -175,6 +175,8 @@ public: bool hasGlyph(uint32 glyph) const; bool hasGlyphs(const std::string &text) const; + void setFallbacks(const std::vector &fallbacks); + uint32 getTextureCacheID() const; static bool getConstant(const char *in, AlignMode &out); @@ -211,7 +213,7 @@ private: const Glyph &findGlyph(uint32 glyph); void printv(const Matrix &t, const std::vector &drawcommands, const std::vector &vertices); - StrongRef rasterizer; + std::vector> rasterizers; int height; float lineHeight; diff --git a/src/modules/graphics/opengl/wrap_Font.cpp b/src/modules/graphics/opengl/wrap_Font.cpp index eea025755..22836c842 100644 --- a/src/modules/graphics/opengl/wrap_Font.cpp +++ b/src/modules/graphics/opengl/wrap_Font.cpp @@ -172,6 +172,18 @@ int w_Font_hasGlyphs(lua_State *L) return 1; } +int w_Font_setFallbacks(lua_State *L) +{ + Font *t = luax_checkfont(L, 1); + std::vector fallbacks; + + for (int i = 2; i <= lua_gettop(L); i++) + fallbacks.push_back(luax_checkfont(L, i)); + + luax_catchexcept(L, [&](){ t->setFallbacks(fallbacks); }); + return 0; +} + static const luaL_Reg functions[] = { { "getHeight", w_Font_getHeight }, @@ -185,6 +197,7 @@ static const luaL_Reg functions[] = { "getDescent", w_Font_getDescent }, { "getBaseline", w_Font_getBaseline }, { "hasGlyphs", w_Font_hasGlyphs }, + { "setFallbacks", w_Font_setFallbacks }, { 0, 0 } }; diff --git a/src/modules/graphics/opengl/wrap_Font.h b/src/modules/graphics/opengl/wrap_Font.h index c38d2c223..172cc90ce 100644 --- a/src/modules/graphics/opengl/wrap_Font.h +++ b/src/modules/graphics/opengl/wrap_Font.h @@ -44,6 +44,7 @@ int w_Font_getAscent(lua_State *L); int w_Font_getDescent(lua_State *L); int w_Font_getBaseline(lua_State *L); int w_Font_hasGlyphs(lua_State *L); +int w_Font_setFallbacks(lua_State *L); extern "C" int luaopen_font(lua_State *L); } // opengl