Выделил переиспользуемые модули из проекта.
This commit is contained in:
parent
3fe2a87e35
commit
7c83d9c93e
15 changed files with 287 additions and 207 deletions
18
font-lib/CMakeLists.txt
Normal file
18
font-lib/CMakeLists.txt
Normal 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
87
font-lib/psf.cpp
Normal 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
52
font-lib/psf.h
Normal 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);
|
Loading…
Add table
Add a link
Reference in a new issue