OdbDesignLib
OdbDesign ODB++ Parsing Library
 
Loading...
Searching...
No Matches
StandardFontsFile.cpp
1#include "StandardFontsFile.h"
2#include "Logger.h"
3#include <fstream>
4#include "str_utils.h"
5#include "../../Constants.h"
6#include "../../Text/Utf8Sanitizer.h"
7#include "../parse_error.h"
8#include "../invalid_odb_error.h"
9#include "enums.pb.h"
10
11
12namespace Odb::Lib::FileModel::Design
13{
14 StandardFontsFile::~StandardFontsFile()
15 {
16 m_characterBlocks.clear();
17 }
18
19 bool StandardFontsFile::Parse(std::filesystem::path path)
20 {
21 std::ifstream standardFile;
22 int lineNumber = 0;
23 std::string line;
24
25 try
26 {
27 if (!OdbFile::Parse(path))
28 {
29 auto message = "fonts directory does not exist: [" + path.string() + "]";
30 throw invalid_odb_error(message);
31 }
32
33 auto fontsStandardFile = path / "standard";
34 if (!std::filesystem::exists(fontsStandardFile))
35 {
36 auto message = "fonts/standard file does not exist: [" + fontsStandardFile.string() + "]";
37 throw invalid_odb_error(message);
38 }
39
40 standardFile.open(fontsStandardFile, std::ios::in);
41 if (!standardFile.is_open())
42 {
43 auto message = "unable to open fonts/standard file: [" + fontsStandardFile.string() + "]";
44 throw invalid_odb_error(message);
45 }
46
47 std::shared_ptr<CharacterBlock> pCurrentCharacterBlock;
48 std::shared_ptr<CharacterBlock::LineRecord> pCurrentLineRecord;
49 bool beginTokenFound = false;
50
51 while (std::getline(standardFile, line))
52 {
53 lineNumber++;
54
55 // trim whitespace from beginning and end of line
56 Utils::str_trim(line);
57 if (!line.empty())
58 {
59 std::stringstream lineStream(line);
60 if (line.find(Constants::COMMENT_TOKEN) == 0)
61 {
62 // comment line
63 }
64 else if (line.find("XSIZE") == 0)
65 {
66 std::string token;
67 if (!(lineStream >> token))
68 {
69 throw_parse_error(m_path, line, token, lineNumber);
70 }
71
72 if (token != "XSIZE")
73 {
74 throw_parse_error(m_path, line, token, lineNumber);
75 }
76
77 if (!(lineStream >> token))
78 {
79 throw_parse_error(m_path, line, token, lineNumber);
80 }
81
82 m_xSize = std::stof(token);
83 }
84 else if (line.find("YSIZE") == 0)
85 {
86 std::string token;
87 if (!(lineStream >> token))
88 {
89 throw_parse_error(m_path, line, token, lineNumber);
90 }
91
92 if (token != "YSIZE")
93 {
94 throw_parse_error(m_path, line, token, lineNumber);
95 }
96
97 if (!(lineStream >> token))
98 {
99 throw_parse_error(m_path, line, token, lineNumber);
100 }
101
102 m_ySize = std::stof(token);
103 }
104 else if (line.find("OFFSET") == 0)
105 {
106 std::string token;
107 if (!(lineStream >> token))
108 {
109 throw_parse_error(m_path, line, token, lineNumber);
110 }
111
112 if (token != "OFFSET")
113 {
114 throw_parse_error(m_path, line, token, lineNumber);
115 }
116
117 if (!(lineStream >> token))
118 {
119 throw_parse_error(m_path, line, token, lineNumber);
120 }
121
122 m_offset = std::stof(token);
123 }
124 else if (line.find(CharacterBlock::BEGIN_TOKEN) == 0)
125 {
126 pCurrentCharacterBlock = std::make_shared<CharacterBlock>();
127 beginTokenFound = true;
128
129 std::string token;
130 if (!(lineStream >> token))
131 {
132 throw_parse_error(m_path, line, token, lineNumber);
133 }
134
135 if (token != CharacterBlock::BEGIN_TOKEN)
136 {
137 throw_parse_error(m_path, line, token, lineNumber);
138 }
139
140 if (!(lineStream >> token))
141 {
142 throw_parse_error(m_path, line, token, lineNumber);
143 }
144
145 Utils::str_trim(token);
146 if (token.length() != 1)
147 {
148 throw_parse_error(m_path, line, token, lineNumber);
149 }
150
151 pCurrentCharacterBlock->character = token;
152 }
153 else if (line.find(CharacterBlock::END_TOKEN) == 0)
154 {
155 if (pCurrentCharacterBlock != nullptr && beginTokenFound)
156 {
157 m_characterBlocks.push_back(pCurrentCharacterBlock);
158 beginTokenFound = false;
159 pCurrentCharacterBlock.reset();
160 }
161 else
162 {
163 throw_parse_error(m_path, line, "", lineNumber);
164 }
165 }
166 else if (line.find(CharacterBlock::LineRecord::RECORD_TOKEN) == 0)
167 {
168 std::string token;
169 if (!(lineStream >> token))
170 {
171 throw_parse_error(m_path, line, token, lineNumber);
172 }
173
174 if (token != CharacterBlock::LineRecord::RECORD_TOKEN)
175 {
176 throw_parse_error(m_path, line, token, lineNumber);
177 }
178
179 if (pCurrentCharacterBlock == nullptr || !beginTokenFound)
180 {
181 throw_parse_error(m_path, line, token, lineNumber);
182 }
183
184 auto pLineRecord = std::make_shared<CharacterBlock::LineRecord>();
185
186 if (!(lineStream >> token))
187 {
188 throw_parse_error(m_path, line, token, lineNumber);
189 }
190 pLineRecord->xStart = std::stof(token);
191
192 if (!(lineStream >> token))
193 {
194 throw_parse_error(m_path, line, token, lineNumber);
195 }
196 pLineRecord->yStart = std::stof(token);
197
198 if (!(lineStream >> token))
199 {
200 throw_parse_error(m_path, line, token, lineNumber);
201 }
202 pLineRecord->xEnd = std::stof(token);
203
204 if (!(lineStream >> token))
205 {
206 throw_parse_error(m_path, line, token, lineNumber);
207 }
208 pLineRecord->yEnd = std::stof(token);
209
210 // polarity
211 if (!(lineStream >> token))
212 {
213 throw_parse_error(m_path, line, token, lineNumber);
214 }
215 Utils::str_trim(token);
216
217 if (token.length() != 1)
218 {
219 throw_parse_error(m_path, line, token, lineNumber);
220 }
221
222 switch (token[0])
223 {
224 case 'P': pLineRecord->polarity = Polarity::Positive; break;
225 case 'N': pLineRecord->polarity = Polarity::Negative; break;
226 default: throw_parse_error(m_path, line, token, lineNumber);
227 }
228
229 // shape
230 if (!(lineStream >> token))
231 {
232 throw_parse_error(m_path, line, token, lineNumber);
233 }
234 Utils::str_trim(token);
235
236 if (token.length() != 1)
237 {
238 throw_parse_error(m_path, line, token, lineNumber);
239 }
240
241 switch (token[0])
242 {
243 case 'R': pLineRecord->shape = LineShape::Round; break;
244 case 'S': pLineRecord->shape = LineShape::Square; break;
245 default: throw_parse_error(m_path, line, token, lineNumber);
246 }
247
248 // width
249 if (!(lineStream >> token))
250 {
251 throw_parse_error(m_path, line, token, lineNumber);
252 }
253 pLineRecord->width = std::stof(token);
254
255 pCurrentCharacterBlock->m_lineRecords.push_back(pLineRecord);
256 }
257 else
258 {
259 logwarn("unrecognized line: " + line);
260 throw_parse_error(m_path, line, "", lineNumber);
261 }
262 }
263 }
264
265 standardFile.close();
266 }
267 catch (parse_error& pe)
268 {
269 auto m = pe.toString("Parse Error:");
270 logerror(m);
271 // cleanup file
272 standardFile.close();
273 throw pe;
274 }
275 catch (invalid_odb_error& ioe)
276 {
277 parse_info pi(m_path, line, lineNumber);
278 const auto m = pi.toString();
279 logexception_msg(ioe, m);
280 // cleanup file
281 standardFile.close();
282 throw ioe;
283 }
284
285 return true;
286 }
287
288 std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile> StandardFontsFile::to_protobuf() const
289 {
290 auto pStandardFontsFileMessage = std::make_unique<Odb::Lib::Protobuf::StandardFontsFile>();
291 pStandardFontsFileMessage->set_xsize(m_xSize);
292 pStandardFontsFileMessage->set_ysize(m_ySize);
293 pStandardFontsFileMessage->set_offset(m_offset);
294 for (const auto& characterBlock : m_characterBlocks)
295 {
296 pStandardFontsFileMessage->add_m_characterblocks()->CopyFrom(*characterBlock->to_protobuf());
297 }
298 return pStandardFontsFileMessage;
299 }
300
301 void StandardFontsFile::from_protobuf(const Odb::Lib::Protobuf::StandardFontsFile& message)
302 {
303 m_xSize = message.xsize();
304 m_ySize = message.ysize();
305 m_offset = message.offset();
306 for (const auto& characterBlockMessage : message.m_characterblocks())
307 {
308 auto pCharacterBlock = std::make_shared<CharacterBlock>();
309 pCharacterBlock->from_protobuf(characterBlockMessage);
310 m_characterBlocks.push_back(pCharacterBlock);
311 }
312 }
313
314 bool StandardFontsFile::Save(std::ostream& os)
315 {
316 return true;
317 }
318
319 StandardFontsFile::CharacterBlock::~CharacterBlock()
320 {
321 m_lineRecords.clear();
322 }
323
324 std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock> StandardFontsFile::CharacterBlock::to_protobuf() const
325 {
326 std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock> pCharacterBlockMessage(new Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock);
327 pCharacterBlockMessage->set_character(Odb::Lib::Text::ToUtf8(character));
328 for (const auto& lineRecord : m_lineRecords)
329 {
330 pCharacterBlockMessage->add_m_linerecords()->CopyFrom(*lineRecord->to_protobuf());
331 }
332 return pCharacterBlockMessage;
333 }
334
335 void StandardFontsFile::CharacterBlock::from_protobuf(const Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock& message)
336 {
337 if (! message.character().empty()) character = message.character();
338
339 for (const auto& lineRecordMessage : message.m_linerecords())
340 {
341 auto pLineRecord = std::make_shared<LineRecord>();
342 pLineRecord->from_protobuf(lineRecordMessage);
343 m_lineRecords.push_back(pLineRecord);
344 }
345 }
346
347 std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord> StandardFontsFile::CharacterBlock::LineRecord::to_protobuf() const
348 {
349 std::unique_ptr<Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord> pLineRecordMessage(new Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord);
350 pLineRecordMessage->set_xstart(xStart);
351 pLineRecordMessage->set_ystart(yStart);
352 pLineRecordMessage->set_xend(xEnd);
353 pLineRecordMessage->set_yend(yEnd);
354 pLineRecordMessage->set_polarity(static_cast<Odb::Lib::Protobuf::Polarity>(polarity));
355 pLineRecordMessage->set_shape(static_cast<Odb::Lib::Protobuf::LineShape>(shape));
356 pLineRecordMessage->set_width(width);
357 return pLineRecordMessage;
358 }
359
360 void StandardFontsFile::CharacterBlock::LineRecord::from_protobuf(const Odb::Lib::Protobuf::StandardFontsFile::CharacterBlock::LineRecord& message)
361 {
362 xStart = message.xstart();
363 yStart = message.ystart();
364 xEnd = message.xend();
365 yEnd = message.yend();
366 polarity = static_cast<Odb::Lib::Polarity>(message.polarity());
367 shape = static_cast<LineShape>(message.shape());
368 width = message.width();
369 }
370
371}