Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : /*
4 : : MIT License
5 : :
6 : : Copyright (c) 2014-2024 Stephane Cuillerdier (aka aiekick)
7 : :
8 : : Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : of this software and associated documentation files (the "Software"), to deal
10 : : in the Software without restriction, including without limitation the rights
11 : : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : copies of the Software, and to permit persons to whom the Software is
13 : : furnished to do so, subject to the following conditions:
14 : :
15 : : The above copyright notice and this permission notice shall be included in all
16 : : copies or substantial portions of the Software.
17 : :
18 : : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 : : SOFTWARE.
25 : : */
26 : :
27 : : // ezFigFont is part of the ezLibs project : https://github.com/aiekick/ezLibs.git
28 : :
29 : : #include <array>
30 : : #include <string>
31 : : #include <vector>
32 : : #include <cstdint>
33 : : #include <sstream>
34 : : #include <fstream>
35 : : #include <iostream>
36 : : #include <unordered_map>
37 : :
38 : : #include "ezLog.hpp"
39 : :
40 : : #ifndef EZ_FIG_FONT
41 : : #define EZ_FIG_FONT
42 : : #endif // EZ_FIG_FONT
43 : :
44 : : namespace ez {
45 : :
46 : : class FigFont {
47 : : private:
48 : : bool m_isValid{false};
49 : : struct Header {
50 : : uint8_t endChar{};
51 : : uint8_t hardblank{}; // Filling char
52 : : int32_t height{}; // char height
53 : : int32_t baseline{}; // base line from top
54 : : int32_t maxLength{}; // max width of achar
55 : : int32_t oldLayout{}; // Old Layout
56 : : int32_t commentLines{}; // Comments line count just after header line
57 : : int32_t printDirection{}; // printing direction
58 : : int32_t fullLayout{}; // Full Layout
59 : : int32_t codetagCount{}; // codeTagCount (optional)
60 : : std::vector<std::string> commentBlock;
61 : : } m_header;
62 : : struct Glyph {
63 : : std::string desc;
64 : : std::vector<std::string> rows;
65 : : };
66 : : std::unordered_map<size_t, Glyph> m_glyphs;
67 : :
68 : : public:
69 : 4 : FigFont() = default;
70 : 0 : FigFont(const std::string& vFilePathName) : m_isValid(m_load(vFilePathName)) {}
71 : 6 : ~FigFont() = default;
72 : 14 : bool isValid() { return m_isValid; }
73 : 6 : FigFont& load(const std::string& vFilePathName) {
74 : 6 : m_isValid = m_load(vFilePathName);
75 : 6 : return *this;
76 : 6 : }
77 : 10 : std::string printString(const std::string& vPattern) {
78 : 10 : return m_printString(vPattern);
79 : 10 : }
80 : :
81 : : private:
82 : 6 : bool m_load(const std::string& vFilePathName) {
83 [ - + ]: 6 : if (vFilePathName.empty()) {
84 : 0 : return false;
85 : 0 : }
86 : 6 : std::ifstream file(vFilePathName);
87 [ + + ]: 6 : if (!file.is_open()) {
88 : 2 : #ifdef EZ_TOOLS_LOG
89 : 2 : LogVarError("Failed to open the file %s", vFilePathName.c_str());
90 : 2 : #endif // EZ_TOOLS_LOG
91 : 2 : return false;
92 : 2 : }
93 : :
94 : 4 : std::string header;
95 : 4 : std::getline(file, header);
96 : 4 : std::istringstream headerStream(header);
97 : 4 : std::string magicNumber;
98 : 4 : headerStream >> magicNumber;
99 [ - + ]: 4 : if (magicNumber.substr(0, 5) != "flf2a") {
100 : 0 : #ifdef EZ_TOOLS_LOG
101 : 0 : LogVarError("%s", "Not a valid FIGfont file");
102 : 0 : #endif // EZ_TOOLS_LOG
103 : 0 : return false;
104 : 0 : }
105 : :
106 : : /*
107 : : flf2a$ 6 5 20 15 3 0 143 229 NOTE: The first five characters in
108 : : | | | | | | | | | | the entire file must be "flf2a".
109 : : / / | | | | | | | \
110 : : Signature / / | | | | | \ Codetag_Count
111 : : Hardblank / / | | | \ Full_Layout*
112 : : Height / | | \ Print_Direction
113 : : Baseline / \ Comment_Lines
114 : : Max_Length Old_Layout*
115 : : */
116 : 4 : m_header.hardblank = magicNumber[5];
117 : 4 : headerStream >> //
118 : 4 : m_header.height >> //
119 : 4 : m_header.baseline >> //
120 : 4 : m_header.oldLayout >> //
121 : 4 : m_header.maxLength >> //
122 : 4 : m_header.commentLines >> //
123 : 4 : m_header.printDirection >> //
124 : 4 : m_header.fullLayout >> //
125 : 4 : m_header.codetagCount;
126 : :
127 : 4 : std::string line;
128 : 4 : m_header.commentBlock.reserve(m_header.commentLines);
129 [ + + ]: 44 : for (int i = 0; i < m_header.commentLines; ++i) {
130 : 40 : std::getline(file, line);
131 : 40 : m_header.commentBlock.push_back(line);
132 : 40 : }
133 : 4 : size_t idx = 0;
134 : 4 : static constexpr size_t baseChar = 32;
135 : 4 : static constexpr size_t required_chars_count = 127 - baseChar;
136 : 4 : static constexpr size_t additionnal_chars_count = 7;
137 : 4 : std::array<size_t, additionnal_chars_count> additionnal_chars{196, 214, 220, 228, 246, 252, 223};
138 : 4 : size_t cChar = baseChar;
139 [ + + ]: 1028 : while (file) {
140 : 1024 : std::vector<std::string> asciiArt;
141 [ + + ]: 1024 : if (idx < required_chars_count) {
142 : 380 : cChar = idx + baseChar;
143 [ - + ]: 380 : if (!m_parseChar(file, cChar)) {
144 : : // return false;
145 : 0 : }
146 [ + + ]: 644 : } else if (idx - required_chars_count < additionnal_chars_count) {
147 : 28 : cChar = additionnal_chars.at(idx - required_chars_count);
148 [ - + ]: 28 : if (!m_parseChar(file, cChar)) {
149 : : // return false;
150 : 0 : }
151 : 616 : } else {
152 [ + + ]: 616 : if (!m_parseChar(file, 0)) {
153 : : // return false;
154 : 4 : }
155 : 616 : }
156 : 1024 : ++idx;
157 : 1024 : }
158 : 4 : return true;
159 : 4 : }
160 : :
161 : 1024 : bool m_parseChar(std::ifstream& vFile, const size_t vChar) {
162 : 1024 : std::string row;
163 : 1024 : size_t charCode = vChar;
164 : 1024 : Glyph glyph;
165 [ + + ]: 1024 : if (charCode < 32) {
166 : 616 : std::getline(vFile, row);
167 : 616 : size_t spacePos = row.find(' ');
168 [ + + ]: 616 : if (spacePos != std::string::npos) {
169 : 612 : const auto numStr = row.substr(0, spacePos);
170 : 612 : const auto descStr = row.substr(spacePos + 1);
171 : 612 : charCode = static_cast<size_t>(std::stoi(numStr));
172 : 612 : } else {
173 : 4 : return false;
174 : 4 : }
175 : 616 : }
176 : 1020 : glyph.rows.reserve(m_header.height);
177 [ + + ]: 9180 : for (int i = 0; i < m_header.height; ++i) {
178 : 8160 : std::getline(vFile, row);
179 [ + - ]: 8160 : if (!row.empty()) {
180 [ + + ]: 17340 : while (row.back() == '@') {
181 : 9180 : row.pop_back();
182 : 9180 : }
183 [ + + ]: 8160 : if (row.front() == ' ') {
184 : 8144 : row = row.substr(1);
185 : 8144 : }
186 [ + + ]: 57808 : for (auto& c : row) {
187 [ + + ]: 57808 : if (c == static_cast<char>(m_header.hardblank)) {
188 : 328 : c = ' ';
189 : 328 : }
190 : 57808 : }
191 : 8160 : }
192 : 8160 : glyph.rows.push_back(row);
193 : 8160 : }
194 : 1020 : m_glyphs[charCode] = glyph;
195 : 1020 : return true;
196 : 1024 : }
197 : :
198 : 10 : std::string m_printString(const std::string& vPattern) {
199 : 10 : std::stringstream ret;
200 : 10 : std::vector<std::string> rows;
201 : 10 : rows.resize(m_header.height);
202 : 10 : size_t row_idx = 0;
203 [ + + ]: 80 : for (auto& row : rows) {
204 [ + + ]: 896 : for (const auto c : vPattern) {
205 : 896 : row += m_getCharRow(c, row_idx);
206 : 896 : }
207 : 80 : ++row_idx;
208 : : // remove empty rows
209 [ + + ]: 80 : if (row.find_first_not_of(" ") != std::string::npos) {
210 : 68 : ret << row << std::endl;
211 : 68 : }
212 : 80 : }
213 : 10 : return ret.str();
214 : 10 : }
215 : :
216 : 896 : std::string m_getCharRow(size_t vC, size_t vRowIdx) {
217 : 896 : auto it = m_glyphs.find(vC);
218 [ + - ]: 896 : if (it != m_glyphs.end()) {
219 [ + - ]: 896 : if (vRowIdx < it->second.rows.size()) {
220 : 896 : return it->second.rows.at(vRowIdx);
221 : 896 : }
222 : 896 : }
223 : 0 : return {};
224 : 896 : }
225 : : };
226 : :
227 : : }
|