LCOV - code coverage report
Current view: top level - source/graphics - FontManager.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 55 67 82.1 %
Date: 2023-01-19 00:18:29 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* Copyright (C) 2022 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "FontManager.h"
      21             : 
      22             : #include "graphics/Font.h"
      23             : #include "graphics/TextureManager.h"
      24             : #include "ps/CLogger.h"
      25             : #include "ps/CStr.h"
      26             : #include "ps/CStrInternStatic.h"
      27             : #include "ps/Filesystem.h"
      28             : #include "renderer/Renderer.h"
      29             : 
      30             : #include <limits>
      31             : 
      32        3083 : std::shared_ptr<CFont> CFontManager::LoadFont(CStrIntern fontName)
      33             : {
      34        3083 :     FontsMap::iterator it = m_Fonts.find(fontName);
      35        3083 :     if (it != m_Fonts.end())
      36        3078 :         return it->second;
      37             : 
      38          10 :     std::shared_ptr<CFont> font(new CFont());
      39             : 
      40           5 :     if (!ReadFont(font.get(), fontName))
      41             :     {
      42             :         // Fall back to default font (unless this is the default font)
      43           0 :         if (fontName == str_sans_10)
      44           0 :             font.reset();
      45             :         else
      46           0 :             font = LoadFont(str_sans_10);
      47             :     }
      48             : 
      49           5 :     m_Fonts[fontName] = font;
      50           5 :     return font;
      51             : }
      52             : 
      53           5 : bool CFontManager::ReadFont(CFont* font, CStrIntern fontName)
      54             : {
      55          10 :     const VfsPath path(L"fonts/");
      56             : 
      57             :     // Read font definition file into a stringstream
      58          10 :     std::shared_ptr<u8> buffer;
      59             :     size_t size;
      60          10 :     const VfsPath fntName(fontName.string() + ".fnt");
      61           5 :     if (g_VFS->LoadFile(path / fntName, buffer, size) < 0)
      62             :     {
      63           0 :         LOGERROR("Failed to open font file %s", (path / fntName).string8());
      64           0 :         return false;
      65             :     }
      66             :     std::istringstream fontStream(
      67          10 :         std::string(reinterpret_cast<const char*>(buffer.get()), size));
      68             : 
      69             :     int version;
      70           5 :     fontStream >> version;
      71             :     // Make sure this is from a recent version of the font builder.
      72           5 :     if (version != 101)
      73             :     {
      74           0 :         LOGERROR("Font %s has invalid version", fontName.c_str());
      75           0 :         return false;
      76             :     }
      77             : 
      78             :     int textureWidth, textureHeight;
      79           5 :     fontStream >> textureWidth >> textureHeight;
      80             : 
      81          10 :     std::string format;
      82           5 :     fontStream >> format;
      83           5 :     if (format == "rgba")
      84           0 :         font->m_HasRGB = true;
      85           5 :     else if (format == "a")
      86           5 :         font->m_HasRGB = false;
      87             :     else
      88             :     {
      89           0 :         LOGWARNING("Invalid .fnt format string");
      90           0 :         return false;
      91             :     }
      92             : 
      93             :     int mumberOfGlyphs;
      94           5 :     fontStream >> mumberOfGlyphs;
      95             : 
      96           5 :     fontStream >> font->m_LineSpacing;
      97           5 :     fontStream >> font->m_Height;
      98             : 
      99           5 :     font->m_BoundsX0 = std::numeric_limits<float>::max();
     100           5 :     font->m_BoundsY0 = std::numeric_limits<float>::max();
     101           5 :     font->m_BoundsX1 = -std::numeric_limits<float>::max();
     102           5 :     font->m_BoundsY1 = -std::numeric_limits<float>::max();
     103             : 
     104        5910 :     for (int i = 0; i < mumberOfGlyphs; ++i)
     105             :     {
     106             :         int codepoint, textureX, textureY, width, height, offsetX, offsetY, advance;
     107        5905 :         fontStream >> codepoint
     108        5905 :             >> textureX >> textureY >> width >> height
     109        5905 :             >> offsetX >> offsetY >> advance;
     110             : 
     111        5905 :         if (codepoint < 0 || codepoint > 0xFFFF)
     112             :         {
     113           0 :             LOGWARNING("Font %s has invalid codepoint 0x%x", fontName.c_str(), codepoint);
     114           0 :             continue;
     115             :         }
     116             : 
     117        5905 :         const float u = static_cast<float>(textureX) / textureWidth;
     118        5905 :         const float v = static_cast<float>(textureY) / textureHeight;
     119        5905 :         const float w = static_cast<float>(width) / textureWidth;
     120        5905 :         const float h = static_cast<float>(height) / textureHeight;
     121             : 
     122        5905 :         CFont::GlyphData g =
     123             :         {
     124       17715 :             u, -v, u + w, -v + h,
     125             :             static_cast<i16>(offsetX), static_cast<i16>(-offsetY),
     126       11810 :             static_cast<i16>(offsetX + width), static_cast<i16>(-offsetY + height),
     127             :             static_cast<i16>(advance)
     128       35430 :         };
     129        5905 :         font->m_Glyphs.set(static_cast<u16>(codepoint), g);
     130             : 
     131        5905 :         font->m_BoundsX0 = std::min(font->m_BoundsX0, static_cast<float>(g.x0));
     132        5905 :         font->m_BoundsY0 = std::min(font->m_BoundsY0, static_cast<float>(g.y0));
     133        5905 :         font->m_BoundsX1 = std::max(font->m_BoundsX1, static_cast<float>(g.x1));
     134        5905 :         font->m_BoundsY1 = std::max(font->m_BoundsY1, static_cast<float>(g.y1));
     135             :     }
     136             : 
     137             :     // Ensure the height has been found (which should always happen if the font includes an 'I').
     138           5 :     ENSURE(font->m_Height);
     139             : 
     140             :     // Load glyph texture
     141          10 :     const VfsPath imageName(fontName.string() + ".png");
     142          10 :     CTextureProperties textureProps(path / imageName,
     143          15 :         font->m_HasRGB ? Renderer::Backend::Format::R8G8B8A8_UNORM : Renderer::Backend::Format::A8_UNORM);
     144           5 :     textureProps.SetIgnoreQuality(true);
     145           5 :     font->m_Texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
     146             : 
     147           5 :     return true;
     148           3 : }

Generated by: LCOV version 1.13