Выделил переиспользуемые модули из проекта.

This commit is contained in:
Евгений Титаренко 2024-04-19 22:25:12 +03:00
parent 3fe2a87e35
commit 7c83d9c93e
15 changed files with 287 additions and 207 deletions

18
font-lib/CMakeLists.txt Normal file
View file

@ -0,0 +1,18 @@
add_library(font-lib STATIC "")
set(FONT_LIB_HEADERS
psf.h
)
set(FONT_LIB_SOURCES
psf.cpp
)
target_sources(font-lib
PRIVATE
${FONT_LIB_SOURCES}
PUBLIC
FILE_SET HEADERS
BASE_DIRS ${PROJECT_SOURCE_DIR}
FILES ${FONT_LIB_HEADERS}
)

87
font-lib/psf.cpp Normal file
View file

@ -0,0 +1,87 @@
#include <locale>
#include <codecvt>
#include <vector>
#include "psf.h"
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> conv_utf8_utf16;
Font readPSF(const std::string &filename) {
{
PSF2Header psf2Header;
std::ifstream ifs(filename, std::ios_base::binary);
if (!ifs.good()) {
throw std::runtime_error("File read error");
}
uint8_t magicNumber[4];
ifs.read((char *) magicNumber, 4);
ifs.seekg(0, std::ios_base::beg);
if (magicNumber[0] == 0x36 && magicNumber[1] == 0x04)
throw std::runtime_error("PSF1 not supported");
if (magicNumber[0] != 0x72 || magicNumber[1] != 0xb5 || magicNumber[2] != 0x4a || magicNumber[3] != 0x86)
throw std::runtime_error("Invalid font file");
ifs.read((char *) &psf2Header, sizeof(psf2Header));
auto font = Font(psf2Header.numberOfGlyphs, psf2Header.glyphWidth, psf2Header.glyphHeight);
std::vector<std::shared_ptr<Glyph>> glyphs(psf2Header.numberOfGlyphs);
for (int i = 0; i < psf2Header.numberOfGlyphs; ++i) {
auto glyph = std::make_shared<Glyph>(psf2Header.glyphWidth, psf2Header.glyphHeight);
char glyphBytes[psf2Header.bytesPerGlyph];
ifs.read((char *) &glyphBytes, psf2Header.bytesPerGlyph);
for (int j = 0; j < psf2Header.bytesPerGlyph; ++j) {
for (int k = 0; k < 8; ++k) {
uint8_t bit = (glyphBytes[j] & (1 << k)) != 0; // Получить к-ый бит
glyph->glyph[(j * 8 + k) / psf2Header.glyphWidth][psf2Header.glyphWidth - 1 -
(j * 8 + k) % psf2Header.glyphWidth] = bit;
}
}
glyphs[i] = glyph;
}
// Чтение таблицы unicode
uint32_t curGlyph = 0;
std::vector<unsigned char> vectorOfBytes;
while (not ifs.eof() && curGlyph < psf2Header.numberOfGlyphs) {
unsigned char curByte;
ifs.read((char *) &curByte, 1);
if (curByte != 0xFF) {
vectorOfBytes.push_back(curByte);
} else {
auto bytesCount = vectorOfBytes.size();
unsigned char bytes[bytesCount];
for (int i = 0; i < bytesCount; ++i) {
bytes[i] = vectorOfBytes[i];
}
char chars8[bytesCount + 1];
memcpy(chars8, bytes, bytesCount);
chars8[bytesCount] = 0;
std::string str8(chars8);
std::u16string str16 = conv_utf8_utf16.from_bytes(str8);
for (auto chr: str16) {
font._glyphs[chr] = glyphs[curGlyph];
}
curGlyph++;
vectorOfBytes.clear();
}
}
return font;
}
}
Glyph::Glyph(uint32_t width, uint32_t height) {
this->glyph = new uint8_t *[height];
for (int i = 0; i < height; ++i) {
this->glyph[i] = new uint8_t[width];
}
this->width = width;
this->height = height;
}
Font::Font(uint32_t glyphsCount, uint32_t glyphWidth, uint32_t glyphHeight) {
this->glyphsCount = glyphsCount;
this->glyphWidth = glyphWidth;
this->glyphHeight = glyphHeight;
}
Font::Font() {
}

52
font-lib/psf.h Normal file
View file

@ -0,0 +1,52 @@
#pragma once
#include <string>
#include <fstream>
#include <cstdint>
#include <map>
#include <memory>
#pragma pack(push, 1)
struct PSF1Header {
char magicNumber[2];
uint8_t mode;
uint8_t glyphSize;
};
#pragma pack(pop)
#pragma pack(push, 1)
struct PSF2Header {
uint8_t magicNumber[4];
uint32_t version;
uint32_t headerSize;
uint32_t flags;
uint32_t numberOfGlyphs;
uint32_t bytesPerGlyph;
uint32_t glyphHeight;
uint32_t glyphWidth;
};
#pragma pack(pop)
class Glyph {
public:
uint8_t **glyph;
uint32_t width;
uint32_t height;
Glyph(uint32_t width, uint32_t height);
};
class Font {
public:
std::map<char16_t, std::shared_ptr<Glyph>> _glyphs;
uint32_t glyphWidth;
uint32_t glyphHeight;
uint32_t glyphsCount;
Font();
explicit Font(uint32_t glyphs, uint32_t glyphWidth, uint32_t glyphHeight);
};
Font readPSF(const std::string &filename);