From bfec00b0227472431e6518c9f920c52047c9a5ad Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Wed, 1 Feb 2023 15:42:21 +0200 Subject: [PATCH] Remove duplicated code in new files --- client/render/CBitmapFont.cpp | 250 -------------------------- client/render/CBitmapFont.h | 79 --------- client/render/CBitmapHanFont.cpp | 267 ---------------------------- client/render/CBitmapHanFont.h | 69 ------- client/render/CTrueTypeFont.cpp | 296 ------------------------------- client/render/CTrueTypeFont.h | 91 ---------- client/render/IFont.cpp | 83 +++++++++ client/render/IFont.h | 72 -------- 8 files changed, 83 insertions(+), 1124 deletions(-) create mode 100644 client/render/IFont.cpp diff --git a/client/render/CBitmapFont.cpp b/client/render/CBitmapFont.cpp index 9eb024aaf..345ed7e68 100644 --- a/client/render/CBitmapFont.cpp +++ b/client/render/CBitmapFont.cpp @@ -18,69 +18,6 @@ #include "../../lib/filesystem/Filesystem.h" #include "../../lib/CGeneralTextHandler.h" -size_t IFont::getStringWidth(const std::string & data) const -{ - size_t width = 0; - - for(size_t i=0; i & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - - for(const std::string & line : data) - { - renderTextLeft(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - currPos.y -= (int)data.size() * (int)getLineHeight(); - - for(const std::string & line : data) - { - renderTextRight(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - currPos.y -= (int)data.size() * (int)getLineHeight() / 2; - - for(const std::string & line : data) - { - renderTextCenter(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - std::array CBitmapFont::loadChars() const { std::array ret; @@ -203,190 +140,3 @@ void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, co SDL_UnlockSurface(surface); } -std::pair, ui64> CTrueTypeFont::loadData(const JsonNode & config) -{ - std::string filename = "Data/" + config["file"].String(); - return CResourceHandler::get()->load(ResourceID(filename, EResType::TTF_FONT))->readAll(); -} - -TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config) -{ - int pointSize = static_cast(config["size"].Float()); - - if(!TTF_WasInit() && TTF_Init()==-1) - throw std::runtime_error(std::string("Failed to initialize true type support: ") + TTF_GetError() + "\n"); - - return TTF_OpenFontRW(SDL_RWFromConstMem(data.first.get(), (int)data.second), 1, pointSize); -} - -int CTrueTypeFont::getFontStyle(const JsonNode &config) -{ - const JsonVector & names = config["style"].Vector(); - int ret = 0; - for(const JsonNode & node : names) - { - if (node.String() == "bold") - ret |= TTF_STYLE_BOLD; - else if (node.String() == "italic") - ret |= TTF_STYLE_ITALIC; - } - return ret; -} - -CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig): - data(loadData(fontConfig)), - font(loadFont(fontConfig), TTF_CloseFont), - blended(fontConfig["blend"].Bool()) -{ - assert(font); - - TTF_SetFontStyle(font.get(), getFontStyle(fontConfig)); -} - -size_t CTrueTypeFont::getLineHeight() const -{ - return TTF_FontHeight(font.get()); -} - -size_t CTrueTypeFont::getGlyphWidth(const char *data) const -{ - return getStringWidth(std::string(data, Unicode::getCharacterSize(*data))); - /* - int advance; - TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance); - return advance; - */ -} - -size_t CTrueTypeFont::getStringWidth(const std::string & data) const -{ - int width; - TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr); - return width; -} - -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 - renderText(surface, data, Colors::BLACK, pos + Point(1,1)); - - if (!data.empty()) - { - SDL_Surface * rendered; - if (blended) - rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), color); - else - rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), color); - - assert(rendered); - - CSDL_Ext::blitSurface(rendered, surface, pos); - SDL_FreeSurface(rendered); - } -} - -size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const -{ - size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up - size_t charSize = rowSize * size; // glyph contains "size" rows - return index * charSize; -} - -size_t CBitmapHanFont::getCharacterIndex(ui8 first, ui8 second) const -{ - if (second > 0x7f ) - second--; - - return (first - 0x81) * (12*16 - 2) + (second - 0x40); -} - -void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const -{ - //TODO: somewhat duplicated with CBitmapFont::renderCharacter(); - Rect clipRect; - CSDL_Ext::getClipRect(surface, clipRect); - - CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0); - uint8_t bpp = surface->format->BytesPerPixel; - - // start of line, may differ from 0 due to end of surface or clipped surface - int lineBegin = std::max(0, clipRect.y - posY); - int lineEnd = std::min((int)size, clipRect.y + clipRect.h - posY); - - // start end end of each row, may differ from 0 - int rowBegin = std::max(0, clipRect.x - posX); - int rowEnd = std::min((int)size, clipRect.x + clipRect.w - posX); - - //for each line in symbol - for(int dy = lineBegin; dy pixels; - uint8_t *source = data.first.get() + getCharacterDataOffset(characterIndex); - - // shift source\destination pixels to current position - dstLine += (posY+dy) * surface->pitch + posX * bpp; - source += ((size + 7) / 8) * dy; - - //for each column in line - for(int dx = rowBegin; dx < rowEnd; dx++) - { - // select current bit in bitmap - int bit = (source[dx / 8] << (dx % 8)) & 0x80; - - uint8_t* dstPixel = dstLine + dx*bpp; - if (bit != 0) - colorPutter(dstPixel, color.r, color.g, color.b); - } - } - posX += (int)size + 1; -} - -void CBitmapHanFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const -{ - int posX = pos.x; - int posY = pos.y; - - SDL_LockSurface(surface); - - for(size_t i=0; irenderCharacter(surface, fallback->chars[ui8(localChar[0])], color, posX, posY); - - if (localChar.size() == 2) - renderCharacter(surface, (int)getCharacterIndex(localChar[0], localChar[1]), color, posX, posY); - } - SDL_UnlockSurface(surface); -} - -CBitmapHanFont::CBitmapHanFont(const JsonNode &config): - fallback(new CBitmapFont(config["fallback"].String())), - data(CResourceHandler::get()->load(ResourceID("data/" + config["name"].String(), EResType::OTHER))->readAll()), - size((size_t)config["size"].Float()) -{ - // basic tests to make sure that fonts are OK - // 1) fonts must contain 190 "sections", 126 symbols each. - assert(getCharacterIndex(0xfe, 0xff) == 190*126); - // 2) ensure that font size is correct - enough to fit all possible symbols - assert(getCharacterDataOffset(getCharacterIndex(0xfe, 0xff)) == data.second); -} - -size_t CBitmapHanFont::getLineHeight() const -{ - return std::max(size + 1, fallback->getLineHeight()); -} - -size_t CBitmapHanFont::getGlyphWidth(const char * data) const -{ - std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0]))); - - if (localChar.size() == 1) - return fallback->getGlyphWidth(data); - - if (localChar.size() == 2) - return size + 1; - - return 0; -} diff --git a/client/render/CBitmapFont.h b/client/render/CBitmapFont.h index 2811a79a3..c4b608a6b 100644 --- a/client/render/CBitmapFont.h +++ b/client/render/CBitmapFont.h @@ -24,44 +24,6 @@ typedef struct _TTF_Font TTF_Font; class CBitmapFont; class CBitmapHanFont; -class IFont -{ -protected: - /// Internal function to render font, see renderTextLeft - virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0; - -public: - virtual ~IFont() - {} - - /// Returns height of font - virtual size_t getLineHeight() const = 0; - /// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes - virtual size_t getGlyphWidth(const char * data) const = 0; - /// Return width of the string - virtual size_t getStringWidth(const std::string & data) const; - - /** - * @param surface - destination to print text on - * @param data - string to print - * @param color - font color - * @param pos - position of rendered font - */ - /// pos = topleft corner of the text - void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - /// pos = center of the text - void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - /// pos = bottomright corner of the text - void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - - /// pos = topleft corner of the text - void renderTextLinesLeft(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; - /// pos = center of the text - void renderTextLinesRight(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; - /// pos = bottomright corner of the text - void renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; -}; - class CBitmapFont : public IFont { static const size_t totalChars = 256; @@ -93,44 +55,3 @@ public: friend class CBitmapHanFont; }; -/// supports multi-byte characters for such languages like Chinese -class CBitmapHanFont : public IFont -{ - std::unique_ptr fallback; - // data, directly copied from file - const std::pair, ui64> data; - - // size of the font. Not available in file but needed for proper rendering - const size_t size; - - size_t getCharacterDataOffset(size_t index) const; - size_t getCharacterIndex(ui8 first, ui8 second) const; - - void renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const; - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CBitmapHanFont(const JsonNode & config); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; -}; - -class CTrueTypeFont : public IFont -{ - const std::pair, ui64> data; - - const std::unique_ptr font; - const bool blended; - - std::pair, ui64> loadData(const JsonNode & config); - TTF_Font * loadFont(const JsonNode & config); - int getFontStyle(const JsonNode & config); - - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CTrueTypeFont(const JsonNode & fontConfig); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; - size_t getStringWidth(const std::string & data) const override; -}; diff --git a/client/render/CBitmapHanFont.cpp b/client/render/CBitmapHanFont.cpp index 9eb024aaf..e474495ee 100644 --- a/client/render/CBitmapHanFont.cpp +++ b/client/render/CBitmapHanFont.cpp @@ -18,273 +18,6 @@ #include "../../lib/filesystem/Filesystem.h" #include "../../lib/CGeneralTextHandler.h" -size_t IFont::getStringWidth(const std::string & data) const -{ - size_t width = 0; - - for(size_t i=0; i & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - - for(const std::string & line : data) - { - renderTextLeft(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - currPos.y -= (int)data.size() * (int)getLineHeight(); - - for(const std::string & line : data) - { - renderTextRight(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - currPos.y -= (int)data.size() * (int)getLineHeight() / 2; - - for(const std::string & line : data) - { - renderTextCenter(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -std::array CBitmapFont::loadChars() const -{ - std::array ret; - - size_t offset = 32; - - for (auto & elem : ret) - { - elem.leftOffset = read_le_u32(data.first.get() + offset); offset+=4; - elem.width = read_le_u32(data.first.get() + offset); offset+=4; - elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4; - } - - for (auto & elem : ret) - { - int pixelOffset = read_le_u32(data.first.get() + offset); offset+=4; - elem.pixels = data.first.get() + 4128 + pixelOffset; - - assert(pixelOffset + 4128 < data.second); - } - return ret; -} - -CBitmapFont::CBitmapFont(const std::string & filename): - data(CResourceHandler::get()->load(ResourceID("data/" + filename, EResType::BMP_FONT))->readAll()), - chars(loadChars()), - height(data.first.get()[5]) -{} - -size_t CBitmapFont::getLineHeight() const -{ - return height; -} - -size_t CBitmapFont::getGlyphWidth(const char * data) const -{ - std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0]))); - - if (localChar.size() == 1) - { - const BitmapChar & ch = chars[ui8(localChar[0])]; - return ch.leftOffset + ch.width + ch.rightOffset; - } - return 0; -} - -void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const -{ - Rect clipRect; - CSDL_Ext::getClipRect(surface, clipRect); - - posX += character.leftOffset; - - CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0); - - uint8_t bpp = surface->format->BytesPerPixel; - - // start of line, may differ from 0 due to end of surface or clipped surface - int lineBegin = std::max(0, clipRect.y - posY); - int lineEnd = std::min(height, clipRect.y + clipRect.h - posY - 1); - - // start end end of each row, may differ from 0 - int rowBegin = std::max(0, clipRect.x - posX); - int rowEnd = std::min(character.width, clipRect.x + clipRect.w - posX - 1); - - //for each line in symbol - for(int dy = lineBegin; dy pixels; - uint8_t *srcLine = character.pixels; - - // shift source\destination pixels to current position - dstLine += (posY+dy) * surface->pitch + posX * bpp; - srcLine += dy * character.width; - - //for each column in line - for(int dx = rowBegin; dx < rowEnd; dx++) - { - uint8_t* dstPixel = dstLine + dx*bpp; - switch(srcLine[dx]) - { - case 1: //black "shadow" - colorPutter(dstPixel, 0, 0, 0); - break; - case 255: //text colour - colorPutter(dstPixel, color.r, color.g, color.b); - break; - default : - break; //transparency - } - } - } - posX += character.width; - posX += character.rightOffset; -} - -void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const -{ - if (data.empty()) - return; - - assert(surface); - - int posX = pos.x; - int posY = pos.y; - - // Should be used to detect incorrect text parsing. Disabled right now due to some old UI code (mostly pregame and battles) - //assert(data[0] != '{'); - //assert(data[data.size()-1] != '}'); - - SDL_LockSurface(surface); - - for(size_t i=0; i, ui64> CTrueTypeFont::loadData(const JsonNode & config) -{ - std::string filename = "Data/" + config["file"].String(); - return CResourceHandler::get()->load(ResourceID(filename, EResType::TTF_FONT))->readAll(); -} - -TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config) -{ - int pointSize = static_cast(config["size"].Float()); - - if(!TTF_WasInit() && TTF_Init()==-1) - throw std::runtime_error(std::string("Failed to initialize true type support: ") + TTF_GetError() + "\n"); - - return TTF_OpenFontRW(SDL_RWFromConstMem(data.first.get(), (int)data.second), 1, pointSize); -} - -int CTrueTypeFont::getFontStyle(const JsonNode &config) -{ - const JsonVector & names = config["style"].Vector(); - int ret = 0; - for(const JsonNode & node : names) - { - if (node.String() == "bold") - ret |= TTF_STYLE_BOLD; - else if (node.String() == "italic") - ret |= TTF_STYLE_ITALIC; - } - return ret; -} - -CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig): - data(loadData(fontConfig)), - font(loadFont(fontConfig), TTF_CloseFont), - blended(fontConfig["blend"].Bool()) -{ - assert(font); - - TTF_SetFontStyle(font.get(), getFontStyle(fontConfig)); -} - -size_t CTrueTypeFont::getLineHeight() const -{ - return TTF_FontHeight(font.get()); -} - -size_t CTrueTypeFont::getGlyphWidth(const char *data) const -{ - return getStringWidth(std::string(data, Unicode::getCharacterSize(*data))); - /* - int advance; - TTF_GlyphMetrics(font.get(), *data, nullptr, nullptr, nullptr, nullptr, &advance); - return advance; - */ -} - -size_t CTrueTypeFont::getStringWidth(const std::string & data) const -{ - int width; - TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr); - return width; -} - -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 - renderText(surface, data, Colors::BLACK, pos + Point(1,1)); - - if (!data.empty()) - { - SDL_Surface * rendered; - if (blended) - rendered = TTF_RenderUTF8_Blended(font.get(), data.c_str(), color); - else - rendered = TTF_RenderUTF8_Solid(font.get(), data.c_str(), color); - - assert(rendered); - - CSDL_Ext::blitSurface(rendered, surface, pos); - SDL_FreeSurface(rendered); - } -} - size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const { size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up diff --git a/client/render/CBitmapHanFont.h b/client/render/CBitmapHanFont.h index 2811a79a3..605415f91 100644 --- a/client/render/CBitmapHanFont.h +++ b/client/render/CBitmapHanFont.h @@ -24,75 +24,6 @@ typedef struct _TTF_Font TTF_Font; class CBitmapFont; class CBitmapHanFont; -class IFont -{ -protected: - /// Internal function to render font, see renderTextLeft - virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0; - -public: - virtual ~IFont() - {} - - /// Returns height of font - virtual size_t getLineHeight() const = 0; - /// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes - virtual size_t getGlyphWidth(const char * data) const = 0; - /// Return width of the string - virtual size_t getStringWidth(const std::string & data) const; - - /** - * @param surface - destination to print text on - * @param data - string to print - * @param color - font color - * @param pos - position of rendered font - */ - /// pos = topleft corner of the text - void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - /// pos = center of the text - void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - /// pos = bottomright corner of the text - void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - - /// pos = topleft corner of the text - void renderTextLinesLeft(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; - /// pos = center of the text - void renderTextLinesRight(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; - /// pos = bottomright corner of the text - void renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; -}; - -class CBitmapFont : public IFont -{ - static const size_t totalChars = 256; - - struct BitmapChar - { - si32 leftOffset; - ui32 width; - si32 rightOffset; - ui8 *pixels; // pixels of this character, part of BitmapFont::data - }; - - const std::pair, ui64> data; - - const std::array chars; - const ui8 height; - - std::array loadChars() const; - - void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const; - - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CBitmapFont(const std::string & filename); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; - - friend class CBitmapHanFont; -}; - /// supports multi-byte characters for such languages like Chinese class CBitmapHanFont : public IFont { diff --git a/client/render/CTrueTypeFont.cpp b/client/render/CTrueTypeFont.cpp index 9eb024aaf..5b1f2ad4f 100644 --- a/client/render/CTrueTypeFont.cpp +++ b/client/render/CTrueTypeFont.cpp @@ -18,197 +18,6 @@ #include "../../lib/filesystem/Filesystem.h" #include "../../lib/CGeneralTextHandler.h" -size_t IFont::getStringWidth(const std::string & data) const -{ - size_t width = 0; - - for(size_t i=0; i & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - - for(const std::string & line : data) - { - renderTextLeft(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - currPos.y -= (int)data.size() * (int)getLineHeight(); - - for(const std::string & line : data) - { - renderTextRight(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const -{ - Point currPos = pos; - currPos.y -= (int)data.size() * (int)getLineHeight() / 2; - - for(const std::string & line : data) - { - renderTextCenter(surface, line, color, currPos); - currPos.y += (int)getLineHeight(); - } -} - -std::array CBitmapFont::loadChars() const -{ - std::array ret; - - size_t offset = 32; - - for (auto & elem : ret) - { - elem.leftOffset = read_le_u32(data.first.get() + offset); offset+=4; - elem.width = read_le_u32(data.first.get() + offset); offset+=4; - elem.rightOffset = read_le_u32(data.first.get() + offset); offset+=4; - } - - for (auto & elem : ret) - { - int pixelOffset = read_le_u32(data.first.get() + offset); offset+=4; - elem.pixels = data.first.get() + 4128 + pixelOffset; - - assert(pixelOffset + 4128 < data.second); - } - return ret; -} - -CBitmapFont::CBitmapFont(const std::string & filename): - data(CResourceHandler::get()->load(ResourceID("data/" + filename, EResType::BMP_FONT))->readAll()), - chars(loadChars()), - height(data.first.get()[5]) -{} - -size_t CBitmapFont::getLineHeight() const -{ - return height; -} - -size_t CBitmapFont::getGlyphWidth(const char * data) const -{ - std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0]))); - - if (localChar.size() == 1) - { - const BitmapChar & ch = chars[ui8(localChar[0])]; - return ch.leftOffset + ch.width + ch.rightOffset; - } - return 0; -} - -void CBitmapFont::renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const -{ - Rect clipRect; - CSDL_Ext::getClipRect(surface, clipRect); - - posX += character.leftOffset; - - CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0); - - uint8_t bpp = surface->format->BytesPerPixel; - - // start of line, may differ from 0 due to end of surface or clipped surface - int lineBegin = std::max(0, clipRect.y - posY); - int lineEnd = std::min(height, clipRect.y + clipRect.h - posY - 1); - - // start end end of each row, may differ from 0 - int rowBegin = std::max(0, clipRect.x - posX); - int rowEnd = std::min(character.width, clipRect.x + clipRect.w - posX - 1); - - //for each line in symbol - for(int dy = lineBegin; dy pixels; - uint8_t *srcLine = character.pixels; - - // shift source\destination pixels to current position - dstLine += (posY+dy) * surface->pitch + posX * bpp; - srcLine += dy * character.width; - - //for each column in line - for(int dx = rowBegin; dx < rowEnd; dx++) - { - uint8_t* dstPixel = dstLine + dx*bpp; - switch(srcLine[dx]) - { - case 1: //black "shadow" - colorPutter(dstPixel, 0, 0, 0); - break; - case 255: //text colour - colorPutter(dstPixel, color.r, color.g, color.b); - break; - default : - break; //transparency - } - } - } - posX += character.width; - posX += character.rightOffset; -} - -void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const -{ - if (data.empty()) - return; - - assert(surface); - - int posX = pos.x; - int posY = pos.y; - - // Should be used to detect incorrect text parsing. Disabled right now due to some old UI code (mostly pregame and battles) - //assert(data[0] != '{'); - //assert(data[data.size()-1] != '}'); - - SDL_LockSurface(surface); - - for(size_t i=0; i, ui64> CTrueTypeFont::loadData(const JsonNode & config) -{ - std::string filename = "Data/" + config["file"].String(); - return CResourceHandler::get()->load(ResourceID(filename, EResType::TTF_FONT))->readAll(); -} - TTF_Font * CTrueTypeFont::loadFont(const JsonNode &config) { int pointSize = static_cast(config["size"].Float()); @@ -285,108 +94,3 @@ void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, } } -size_t CBitmapHanFont::getCharacterDataOffset(size_t index) const -{ - size_t rowSize = (size + 7) / 8; // 1 bit per pixel, rounded up - size_t charSize = rowSize * size; // glyph contains "size" rows - return index * charSize; -} - -size_t CBitmapHanFont::getCharacterIndex(ui8 first, ui8 second) const -{ - if (second > 0x7f ) - second--; - - return (first - 0x81) * (12*16 - 2) + (second - 0x40); -} - -void CBitmapHanFont::renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const -{ - //TODO: somewhat duplicated with CBitmapFont::renderCharacter(); - Rect clipRect; - CSDL_Ext::getClipRect(surface, clipRect); - - CSDL_Ext::TColorPutter colorPutter = CSDL_Ext::getPutterFor(surface, 0); - uint8_t bpp = surface->format->BytesPerPixel; - - // start of line, may differ from 0 due to end of surface or clipped surface - int lineBegin = std::max(0, clipRect.y - posY); - int lineEnd = std::min((int)size, clipRect.y + clipRect.h - posY); - - // start end end of each row, may differ from 0 - int rowBegin = std::max(0, clipRect.x - posX); - int rowEnd = std::min((int)size, clipRect.x + clipRect.w - posX); - - //for each line in symbol - for(int dy = lineBegin; dy pixels; - uint8_t *source = data.first.get() + getCharacterDataOffset(characterIndex); - - // shift source\destination pixels to current position - dstLine += (posY+dy) * surface->pitch + posX * bpp; - source += ((size + 7) / 8) * dy; - - //for each column in line - for(int dx = rowBegin; dx < rowEnd; dx++) - { - // select current bit in bitmap - int bit = (source[dx / 8] << (dx % 8)) & 0x80; - - uint8_t* dstPixel = dstLine + dx*bpp; - if (bit != 0) - colorPutter(dstPixel, color.r, color.g, color.b); - } - } - posX += (int)size + 1; -} - -void CBitmapHanFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const -{ - int posX = pos.x; - int posY = pos.y; - - SDL_LockSurface(surface); - - for(size_t i=0; irenderCharacter(surface, fallback->chars[ui8(localChar[0])], color, posX, posY); - - if (localChar.size() == 2) - renderCharacter(surface, (int)getCharacterIndex(localChar[0], localChar[1]), color, posX, posY); - } - SDL_UnlockSurface(surface); -} - -CBitmapHanFont::CBitmapHanFont(const JsonNode &config): - fallback(new CBitmapFont(config["fallback"].String())), - data(CResourceHandler::get()->load(ResourceID("data/" + config["name"].String(), EResType::OTHER))->readAll()), - size((size_t)config["size"].Float()) -{ - // basic tests to make sure that fonts are OK - // 1) fonts must contain 190 "sections", 126 symbols each. - assert(getCharacterIndex(0xfe, 0xff) == 190*126); - // 2) ensure that font size is correct - enough to fit all possible symbols - assert(getCharacterDataOffset(getCharacterIndex(0xfe, 0xff)) == data.second); -} - -size_t CBitmapHanFont::getLineHeight() const -{ - return std::max(size + 1, fallback->getLineHeight()); -} - -size_t CBitmapHanFont::getGlyphWidth(const char * data) const -{ - std::string localChar = Unicode::fromUnicode(std::string(data, Unicode::getCharacterSize(data[0]))); - - if (localChar.size() == 1) - return fallback->getGlyphWidth(data); - - if (localChar.size() == 2) - return size + 1; - - return 0; -} diff --git a/client/render/CTrueTypeFont.h b/client/render/CTrueTypeFont.h index 2811a79a3..d4b67710a 100644 --- a/client/render/CTrueTypeFont.h +++ b/client/render/CTrueTypeFont.h @@ -24,97 +24,6 @@ typedef struct _TTF_Font TTF_Font; class CBitmapFont; class CBitmapHanFont; -class IFont -{ -protected: - /// Internal function to render font, see renderTextLeft - virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0; - -public: - virtual ~IFont() - {} - - /// Returns height of font - virtual size_t getLineHeight() const = 0; - /// Returns width, in pixels of a character glyph. Pointer must contain at least characterSize valid bytes - virtual size_t getGlyphWidth(const char * data) const = 0; - /// Return width of the string - virtual size_t getStringWidth(const std::string & data) const; - - /** - * @param surface - destination to print text on - * @param data - string to print - * @param color - font color - * @param pos - position of rendered font - */ - /// pos = topleft corner of the text - void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - /// pos = center of the text - void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - /// pos = bottomright corner of the text - void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const; - - /// pos = topleft corner of the text - void renderTextLinesLeft(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; - /// pos = center of the text - void renderTextLinesRight(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; - /// pos = bottomright corner of the text - void renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; -}; - -class CBitmapFont : public IFont -{ - static const size_t totalChars = 256; - - struct BitmapChar - { - si32 leftOffset; - ui32 width; - si32 rightOffset; - ui8 *pixels; // pixels of this character, part of BitmapFont::data - }; - - const std::pair, ui64> data; - - const std::array chars; - const ui8 height; - - std::array loadChars() const; - - void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const; - - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CBitmapFont(const std::string & filename); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; - - friend class CBitmapHanFont; -}; - -/// supports multi-byte characters for such languages like Chinese -class CBitmapHanFont : public IFont -{ - std::unique_ptr fallback; - // data, directly copied from file - const std::pair, ui64> data; - - // size of the font. Not available in file but needed for proper rendering - const size_t size; - - size_t getCharacterDataOffset(size_t index) const; - size_t getCharacterIndex(ui8 first, ui8 second) const; - - void renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const; - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CBitmapHanFont(const JsonNode & config); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; -}; - class CTrueTypeFont : public IFont { const std::pair, ui64> data; diff --git a/client/render/IFont.cpp b/client/render/IFont.cpp new file mode 100644 index 000000000..5c99bf020 --- /dev/null +++ b/client/render/IFont.cpp @@ -0,0 +1,83 @@ +/* + * Fonts.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "Fonts.h" + +#include + +#include "SDL_Extensions.h" +#include "../../lib/JsonNode.h" +#include "../../lib/vcmi_endian.h" +#include "../../lib/filesystem/Filesystem.h" +#include "../../lib/CGeneralTextHandler.h" + +size_t IFont::getStringWidth(const std::string & data) const +{ + size_t width = 0; + + for(size_t i=0; i & data, const SDL_Color & color, const Point & pos) const +{ + Point currPos = pos; + + for(const std::string & line : data) + { + renderTextLeft(surface, line, color, currPos); + currPos.y += (int)getLineHeight(); + } +} + +void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const +{ + Point currPos = pos; + currPos.y -= (int)data.size() * (int)getLineHeight(); + + for(const std::string & line : data) + { + renderTextRight(surface, line, color, currPos); + currPos.y += (int)getLineHeight(); + } +} + +void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const +{ + Point currPos = pos; + currPos.y -= (int)data.size() * (int)getLineHeight() / 2; + + for(const std::string & line : data) + { + renderTextCenter(surface, line, color, currPos); + currPos.y += (int)getLineHeight(); + } +} + diff --git a/client/render/IFont.h b/client/render/IFont.h index 2811a79a3..a73c81b1c 100644 --- a/client/render/IFont.h +++ b/client/render/IFont.h @@ -62,75 +62,3 @@ public: void renderTextLinesCenter(SDL_Surface * surface, const std::vector & data, const SDL_Color & color, const Point & pos) const; }; -class CBitmapFont : public IFont -{ - static const size_t totalChars = 256; - - struct BitmapChar - { - si32 leftOffset; - ui32 width; - si32 rightOffset; - ui8 *pixels; // pixels of this character, part of BitmapFont::data - }; - - const std::pair, ui64> data; - - const std::array chars; - const ui8 height; - - std::array loadChars() const; - - void renderCharacter(SDL_Surface * surface, const BitmapChar & character, const SDL_Color & color, int &posX, int &posY) const; - - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CBitmapFont(const std::string & filename); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; - - friend class CBitmapHanFont; -}; - -/// supports multi-byte characters for such languages like Chinese -class CBitmapHanFont : public IFont -{ - std::unique_ptr fallback; - // data, directly copied from file - const std::pair, ui64> data; - - // size of the font. Not available in file but needed for proper rendering - const size_t size; - - size_t getCharacterDataOffset(size_t index) const; - size_t getCharacterIndex(ui8 first, ui8 second) const; - - void renderCharacter(SDL_Surface * surface, int characterIndex, const SDL_Color & color, int &posX, int &posY) const; - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CBitmapHanFont(const JsonNode & config); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; -}; - -class CTrueTypeFont : public IFont -{ - const std::pair, ui64> data; - - const std::unique_ptr font; - const bool blended; - - std::pair, ui64> loadData(const JsonNode & config); - TTF_Font * loadFont(const JsonNode & config); - int getFontStyle(const JsonNode & config); - - void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const override; -public: - CTrueTypeFont(const JsonNode & fontConfig); - - size_t getLineHeight() const override; - size_t getGlyphWidth(const char * data) const override; - size_t getStringWidth(const std::string & data) const override; -};