Преглед на файлове

TTF fonts can now be used as fallback for H3 fonts

Ivan Savenko преди 2 години
родител
ревизия
0770a1a153
променени са 5 файла, в които са добавени 55 реда и са изтрити 5 реда
  1. 0 1
      client/render/IFont.cpp
  2. 19 1
      client/renderSDL/CBitmapFont.cpp
  3. 5 0
      client/renderSDL/CBitmapFont.h
  4. 26 3
      client/renderSDL/CTrueTypeFont.cpp
  5. 5 0
      client/renderSDL/CTrueTypeFont.h

+ 0 - 1
client/render/IFont.cpp

@@ -13,7 +13,6 @@
 
 #include "../../lib/Point.h"
 #include "../../lib/TextOperations.h"
-//
 
 size_t IFont::getStringWidth(const std::string & data) const
 {

+ 19 - 1
client/renderSDL/CBitmapFont.cpp

@@ -70,7 +70,7 @@ CBitmapFont::CBitmapFont(const std::string & filename):
 
 	loadModFont("core", resource);
 
-	for (auto const & modName : VLC->modh->getActiveMods())
+	for(const auto & modName : VLC->modh->getActiveMods())
 	{
 		if (CResourceHandler::get(modName)->existsResource(resource))
 			loadModFont(modName, resource);
@@ -94,6 +94,24 @@ size_t CBitmapFont::getGlyphWidth(const char * data) const
 	return iter->second.leftOffset + iter->second.width + iter->second.rightOffset;
 }
 
+bool CBitmapFont::canRepresentCharacter(const char *data) const
+{
+	CodePoint localChar = TextOperations::getUnicodeCodepoint(data, 4);
+
+	auto iter = chars.find(localChar);
+
+	return iter != chars.end();
+}
+
+bool CBitmapFont::canRepresentString(const std::string & data) const
+{
+	for(size_t i=0; i<data.size(); i += TextOperations::getUnicodeCharacterSize(data[i]))
+		if (!canRepresentCharacter(data.data() + i))
+			return false;
+
+	return true;
+}
+
 void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const
 {
 	Rect clipRect;

+ 5 - 0
client/renderSDL/CBitmapFont.h

@@ -41,6 +41,11 @@ public:
 	size_t getLineHeight() const override;
 	size_t getGlyphWidth(const char * data) const override;
 
+	/// returns true if this font contains provided utf-8 character
+	bool canRepresentCharacter(const char * data) const;
+	bool canRepresentString(const std::string & data) const;
+
 	friend class CBitmapHanFont;
+	friend class CTrueTypeFont;
 };
 

+ 26 - 3
client/renderSDL/CTrueTypeFont.cpp

@@ -10,6 +10,8 @@
 #include "StdInc.h"
 #include "CTrueTypeFont.h"
 
+#include "CBitmapFont.h"
+
 #include "../render/Colors.h"
 #include "../renderSDL/SDL_Extensions.h"
 
@@ -52,30 +54,45 @@ int CTrueTypeFont::getFontStyle(const JsonNode &config)
 CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig):
 	data(loadData(fontConfig)),
 	font(loadFont(fontConfig), TTF_CloseFont),
+	dropShadow(fontConfig["blend"].Bool()),
 	blended(fontConfig["blend"].Bool())
 {
 	assert(font);
 
 	TTF_SetFontStyle(font.get(), getFontStyle(fontConfig));
+
+	std::string fallbackName = fontConfig["fallback"].String();
+
+	if (!fallbackName.empty())
+		fallbackFont = std::make_unique<CBitmapFont>(fallbackName);
 }
 
+CTrueTypeFont::~CTrueTypeFont() = default;
+
 size_t CTrueTypeFont::getLineHeight() const
 {
+	if (fallbackFont)
+		fallbackFont->getLineHeight();
+
 	return TTF_FontHeight(font.get());
 }
 
 size_t CTrueTypeFont::getGlyphWidth(const char *data) const
 {
+	if (fallbackFont && fallbackFont->canRepresentCharacter(data))
+		return fallbackFont->getGlyphWidth(data);
+
 	return getStringWidth(std::string(data, TextOperations::getUnicodeCharacterSize(*data)));
-	/*
 	int advance;
 	TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance);
 	return advance;
-	*/
 }
 
 size_t CTrueTypeFont::getStringWidth(const std::string & data) const
 {
+	if (fallbackFont && fallbackFont->canRepresentString(data))
+		return fallbackFont->getStringWidth(data);
+
 	int width;
 	TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr);
 	return width;
@@ -83,7 +100,13 @@ size_t CTrueTypeFont::getStringWidth(const std::string & data) const
 
 void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
 {
-	if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
+	if (fallbackFont && fallbackFont->canRepresentString(data))
+	{
+		fallbackFont->renderText(surface, data, color, pos);
+		return;
+	}
+
+	if (dropShadow && color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
 		renderText(surface, data, Colors::BLACK, pos + Point(1,1));
 
 	if (!data.empty())

+ 5 - 0
client/renderSDL/CTrueTypeFont.h

@@ -15,14 +15,18 @@ VCMI_LIB_NAMESPACE_BEGIN
 class JsonNode;
 VCMI_LIB_NAMESPACE_END
 
+class CBitmapFont;
+
 typedef struct _TTF_Font TTF_Font;
 
 class CTrueTypeFont : public IFont
 {
+	std::unique_ptr<CBitmapFont> fallbackFont;
 	const std::pair<std::unique_ptr<ui8[]>, ui64> data;
 
 	const std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> font;
 	const bool blended;
+	const bool dropShadow;
 
 	std::pair<std::unique_ptr<ui8[]>, ui64> loadData(const JsonNode & config);
 	TTF_Font * loadFont(const JsonNode & config);
@@ -31,6 +35,7 @@ class CTrueTypeFont : public IFont
 	void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override;
 public:
 	CTrueTypeFont(const JsonNode & fontConfig);
+	~CTrueTypeFont();
 
 	size_t getLineHeight() const override;
 	size_t getGlyphWidth(const char * data) const override;