Browse Source

Added Font:setFallbacks(otherfont, ...). Resolves issue #1041.

Note that general font metrics are largely still based on the original (non-fallback) font, whereas glyph sizes are based on the fallback fonts when those are used to get the glyph.
Alex Szpakowski 10 years ago
parent
commit
a35ccb4426

+ 55 - 7
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<love::font::Rasterizer> &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<love::font::Rasterizer> &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<std::string::const_iterator> i(text.begin(), text.begin(), text.end());
+		utf8::iterator<std::string::const_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<Font *> &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

+ 3 - 1
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<Font *> &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<DrawCommand> &drawcommands, const std::vector<GlyphVertex> &vertices);
 
-	StrongRef<love::font::Rasterizer> rasterizer;
+	std::vector<StrongRef<love::font::Rasterizer>> rasterizers;
 
 	int height;
 	float lineHeight;

+ 13 - 0
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<Font *> 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 }
 };
 

+ 1 - 0
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