diff options
| -rw-r--r-- | cmake/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/common/Font.cpp | 117 | ||||
| -rw-r--r-- | src/common/Font.hpp | 43 | ||||
| -rw-r--r-- | src/games/minesweeper/Minesweeper.cpp | 13 | ||||
| -rw-r--r-- | src/games/minesweeper/Minesweeper.hpp | 9 | 
5 files changed, 182 insertions, 1 deletions
diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index fe30b50..8591621 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -27,6 +27,7 @@ endif ()  target_sources(fsarcade PUBLIC      ${FSARCADE_SRC_DIR}/main.cpp      ${FSARCADE_SRC_DIR}/basic/math.cpp +    ${FSARCADE_SRC_DIR}/common/Font.cpp      ${FSARCADE_SRC_DIR}/renderer/Renderer.cpp      ${FSARCADE_SRC_DIR}/renderer/RenderGroup.cpp      ${FSARCADE_SRC_DIR}/games/Game.cpp diff --git a/src/common/Font.cpp b/src/common/Font.cpp new file mode 100644 index 0000000..31a6720 --- /dev/null +++ b/src/common/Font.cpp @@ -0,0 +1,117 @@ +#include <common/Font.hpp> + +#include <fstream> +#include <iostream> + + +Font::~Font() +{ +    Deinit(); +} + + +bool +Font::Init(const char* path, int font_size) +{ +    std::ifstream file(path, std::ios::in|std::ios::binary|std::ios::ate); +    if (!file.is_open()) { +        return false; +    } + + +    std::streampos end = file.tellg(); +    size_t size = static_cast<size_t>(end); +    char *content = new char[size + 1]; + +    file.seekg(0, std::ios::beg); +    file.read(content, end); +    file.close(); +    content[size] = '\0'; + + +    // set font info +    if (!stbtt_InitFont(&m_font_info, (unsigned char*)content, 0)) +    { +        std::cout << "stbtt_InitFont failed.\n"; +        printf("stbtt_InitFont failed\n"); +        delete[] content; +        return false; +    } + + +    // font settings (scale + vmetrics) +    float scale = stbtt_ScaleForPixelHeight(&m_font_info, (float)font_size); +    int baseline, ascent, descent, line_gap; +    stbtt_GetFontVMetrics(&m_font_info, &ascent, &descent, &line_gap); +    baseline = int(scale * (float)-descent); +    ascent   = int(scale * (float)ascent); +    descent  = int(scale * (float)descent); +    line_gap = int(scale * (float)line_gap); + + +    m_font_scale = scale; +    m_font_baseline = baseline; +    m_font_yadvance = ascent - descent + line_gap; +    m_file_content = content; + + +    return true; +} + + +void +Font::LoadGlyph(Glyph& glyph, uint32_t codepoint) +{ +    int bbx0, bby0, bbx1, bby1; +    stbtt_GetCodepointBitmapBox(&m_font_info, (int)codepoint, m_font_scale, m_font_scale, &bbx0, &bby0, &bbx1, &bby1); +    int width = bbx1 - bbx0; +    int height = bby1 - bby0; + + +    size_t size = size_t(width * height); +    uint8_t* bitmap_flipped = new uint8_t[size]; +    uint8_t* bitmap_correct = new uint8_t[size]; + + +    stbtt_MakeCodepointBitmap(&m_font_info, bitmap_flipped, width, height, width, m_font_scale, m_font_scale, (int)codepoint); + +    uint8_t* dest = bitmap_correct; +    for (int y = 0; y < height; ++y) +    { +        uint8_t* src = bitmap_flipped + size_t((height-1-y)*width); +        for (int x = 0; x < width; ++x) +        { +            *dest++ = *src++; +        } +    } +    delete[] bitmap_flipped; + +    glyph.bitmap.width = width; +    glyph.bitmap.height = height; +    glyph.bitmap.pixels = std::unique_ptr<uint8_t>(bitmap_correct); + + +    int xadvance; +    int left_side_bearing; +    stbtt_GetCodepointHMetrics(&m_font_info, (int)codepoint, &xadvance, &left_side_bearing); +    xadvance          = (int)(m_font_scale * (float)xadvance); +    left_side_bearing = (int)(m_font_scale * (float)left_side_bearing); + + +    glyph.xoff = static_cast<int>(m_font_scale * (float)bbx0) + left_side_bearing; +    glyph.yoff = -bby1; +    glyph.xadvance = xadvance; + +} + + +void +Font::Deinit() +{ +    if (m_file_content) { +        delete[] m_file_content; +        m_file_content = nullptr; +    } +} + + diff --git a/src/common/Font.hpp b/src/common/Font.hpp new file mode 100644 index 0000000..a594add --- /dev/null +++ b/src/common/Font.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include <filesystem> +#include <stb_truetype.h> + + +struct MonoBitmap { +    int32_t width; +    int32_t height; +    std::unique_ptr<uint8_t> pixels; +}; + + +struct Glyph { +    int32_t xoff; +    int32_t yoff; +    int32_t xadvance; +    MonoBitmap bitmap; +}; + + +class Font { +public: +    ~Font(); + +    bool Init(const char* path, int font_size); +    void Deinit(); + +    void LoadGlyph(Glyph& glyph, uint32_t codepoint); + + +private: +    const char* m_file_content = nullptr; + +    float m_font_scale; +    int m_font_baseline; +    int m_font_yadvance; + +    stbtt_fontinfo m_font_info; +    Glyph m_glyphs['~' - ' ' + 1]; +}; + + diff --git a/src/games/minesweeper/Minesweeper.cpp b/src/games/minesweeper/Minesweeper.cpp index 6dc77a4..abb9515 100644 --- a/src/games/minesweeper/Minesweeper.cpp +++ b/src/games/minesweeper/Minesweeper.cpp @@ -25,8 +25,11 @@ Minesweeper::Minesweeper()      m_CellOuterViewSize = {cell_size, cell_size};      m_CellInnerViewSize = {cell_size_without_border, cell_size_without_border}; +    m_Font.Init("fonts/dejavu_ttf/DejaVuSansMono.ttf", 32); +    for (uint32_t i = 0; i < m_DigitGlyphs.size(); ++i) { +        m_Font.LoadGlyph(m_DigitGlyphs[i], i + '0'); +    } -    // Todo: assert various stuff      Reinit();  } @@ -278,6 +281,14 @@ void Minesweeper::DrawBoard(RenderGroup &render_group) {      }; +    // Temporary: Drawing Glyph Test +    render_group.PushBitmap( +            {100.0f, 100.0f, 10.0f}, +            m_DigitGlyphs[1].bitmap.width, +            m_DigitGlyphs[1].bitmap.height, +            m_DigitGlyphs[1].bitmap.pixels.get()); + +      for (int32_t y = 0; y < m_MapHeight; y++) {          for (int32_t x = 0; x < m_MapWidth; x++) {              V2F32 world_pos = { diff --git a/src/games/minesweeper/Minesweeper.hpp b/src/games/minesweeper/Minesweeper.hpp index 4906464..b081806 100644 --- a/src/games/minesweeper/Minesweeper.hpp +++ b/src/games/minesweeper/Minesweeper.hpp @@ -1,6 +1,10 @@  #pragma once  #include <games/Game.hpp> +#include <common/Font.hpp> + +#include <array> +  namespace std {      template <> @@ -13,6 +17,7 @@ namespace std {      };  } +  enum class MinesweeperRunState {      Resume,      Pause, @@ -21,6 +26,7 @@ enum class MinesweeperRunState {      Exit  }; +  class Minesweeper : public Game {      public:          Minesweeper(); @@ -76,6 +82,9 @@ class Minesweeper : public Game {          uint32_t m_IsFlaggedBitmap[MAX_MAP_HEIGHT] {};          uint32_t m_IsMineBitmap[MAX_MAP_HEIGHT] {};          int32_t m_AdjacentMineCounters[MAX_MAP_WIDTH * MAX_MAP_HEIGHT] {}; + +        Font m_Font; +        std::array<Glyph, 9> m_DigitGlyphs;  };  | 
