aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorfschildt <florian.schildt@protonmail.com>2025-10-13 13:59:54 +0200
committerfschildt <florian.schildt@protonmail.com>2025-10-13 13:59:54 +0200
commitabb22cda9a82a323fd8f1d077adefd6970a1abaa (patch)
tree126a2de5c91f659b888ba776b7b821b9779e7bfe /src/common
parent6f3590341312b0ffff2304d02b24ac6a5d14b182 (diff)
minesweeper: draw colored mine counters
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Font.cpp90
-rw-r--r--src/common/Font.hpp25
2 files changed, 80 insertions, 35 deletions
diff --git a/src/common/Font.cpp b/src/common/Font.cpp
index b5b177c..82f6ad8 100644
--- a/src/common/Font.cpp
+++ b/src/common/Font.cpp
@@ -2,44 +2,40 @@
#include <fstream>
#include <iostream>
+#include <cstring>
-Font::~Font()
+static inline bool
+is_ch_ascii(char32_t ch)
{
- Deinit();
+ bool result = ch >= ' ' && ch <= '~';
+ return result;
}
+Font::~Font()
+{
+ delete[] m_file_content;
+}
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()) {
+ if (!ReadFile(path)) {
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))
+ if (!stbtt_InitFont(&m_font_info, (unsigned char*)m_file_content, 0))
{
std::cout << "stbtt_InitFont failed.\n";
- printf("stbtt_InitFont failed\n");
- delete[] content;
+ delete[] m_file_content;
+ m_file_content = nullptr;
return false;
}
- // font settings (scale + vmetrics)
+ // set 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);
@@ -49,21 +45,48 @@ Font::Init(const char* path, int font_size)
line_gap = int(scale * (float)line_gap);
+ // init members
m_font_scale = scale;
m_font_baseline = baseline;
m_font_yadvance = ascent - descent + line_gap;
- m_file_content = content;
+
+
+ // load glyphs
+ for (char c = first_ascii_ch; c <= last_ascii_ch; ++c) {
+ LoadGlyph(m_glyphs[c-first_ascii_ch], static_cast<char32_t>(c));
+ }
+ memset((void*)&m_fail_glyph, 0, sizeof(m_fail_glyph));
return true;
}
+bool
+Font::ReadFile(const char* path)
+{
+ 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';
+
+ m_file_content = content;
+ return m_file_content;
+}
void
-Font::LoadGlyph(Glyph& glyph, uint32_t codepoint)
+Font::LoadGlyph(Glyph& glyph, char32_t c)
{
int bbx0, bby0, bbx1, bby1;
- stbtt_GetCodepointBitmapBox(&m_font_info, (int)codepoint, m_font_scale, m_font_scale, &bbx0, &bby0, &bbx1, &bby1);
+ stbtt_GetCodepointBitmapBox(&m_font_info, (int)c, m_font_scale, m_font_scale, &bbx0, &bby0, &bbx1, &bby1);
int width = bbx1 - bbx0;
int height = bby1 - bby0;
@@ -73,7 +96,7 @@ Font::LoadGlyph(Glyph& glyph, uint32_t codepoint)
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);
+ stbtt_MakeCodepointBitmap(&m_font_info, bitmap_flipped, width, height, width, m_font_scale, m_font_scale, (int)c);
uint8_t* dest = bitmap_correct;
for (int y = 0; y < height; ++y)
@@ -93,7 +116,7 @@ Font::LoadGlyph(Glyph& glyph, uint32_t codepoint)
int xadvance;
int left_side_bearing;
- stbtt_GetCodepointHMetrics(&m_font_info, (int)codepoint, &xadvance, &left_side_bearing);
+ stbtt_GetCodepointHMetrics(&m_font_info, (int)c, &xadvance, &left_side_bearing);
xadvance = (int)(m_font_scale * (float)xadvance);
left_side_bearing = (int)(m_font_scale * (float)left_side_bearing);
@@ -104,14 +127,23 @@ Font::LoadGlyph(Glyph& glyph, uint32_t codepoint)
}
-
-void
-Font::Deinit()
+AlphaBitmap&
+Font::GetAlphaBitmap(char32_t c)
{
- if (m_file_content) {
- delete[] m_file_content;
- m_file_content = nullptr;
+ if (is_ch_ascii(c)) {
+ return m_glyphs[c - first_ascii_ch].bitmap;
}
+
+ return m_fail_glyph.bitmap;
}
+Glyph&
+Font::GetGlyph(char32_t c)
+{
+ if (is_ch_ascii(c)) {
+ return m_glyphs[c - first_ascii_ch];
+ }
+
+ return m_fail_glyph;
+}
diff --git a/src/common/Font.hpp b/src/common/Font.hpp
index 91afe06..af4ddb5 100644
--- a/src/common/Font.hpp
+++ b/src/common/Font.hpp
@@ -1,10 +1,12 @@
#pragma once
-#include <filesystem>
+#include <common/defs.hpp>
#include <stb_truetype.h>
+#include <memory>
-struct MonoBitmap {
+
+struct AlphaBitmap {
int32_t w;
int32_t h;
std::unique_ptr<uint8_t> pixels;
@@ -15,7 +17,7 @@ struct Glyph {
int32_t xoff;
int32_t yoff;
int32_t xadvance;
- MonoBitmap bitmap;
+ AlphaBitmap bitmap;
};
@@ -24,12 +26,22 @@ public:
~Font();
bool Init(const char* path, int font_size);
- void Deinit();
+ AlphaBitmap& GetAlphaBitmap(char32_t c);
+ Glyph& GetGlyph(char32_t c);
+
+
- void LoadGlyph(Glyph& glyph, uint32_t codepoint);
+private:
+ bool ReadFile(const char* path);
+ void LoadGlyph(Glyph& glyph, char32_t c);
private:
+ static constexpr char first_ascii_ch = ' ';
+ static constexpr char last_ascii_ch = '~';
+ static constexpr char ascii_glyph_count = last_ascii_ch - first_ascii_ch + 1;
+
+
const char* m_file_content = nullptr;
float m_font_scale;
@@ -37,7 +49,8 @@ private:
int m_font_yadvance;
stbtt_fontinfo m_font_info;
- Glyph m_glyphs['~' - ' ' + 1];
+ Glyph m_glyphs[ascii_glyph_count];
+ Glyph m_fail_glyph;
};