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