#include #include #include #include "psf.h" std::wstring_convert, 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> glyphs(psf2Header.numberOfGlyphs); for (int i = 0; i < psf2Header.numberOfGlyphs; ++i) { auto glyph = std::make_shared(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 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() { }