libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNAltoSpace.cpp
Go to the documentation of this file.
1 /* Copyright 2011-2016 CoReNum
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNAltoSpace.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <CRNXml/CRNAlto.h>
23 #include <CRNException.h>
24 #include <algorithm>
25 #include <CRNi18n.h>
26 
27 using namespace crn;
28 using namespace xml;
29 
36 Alto::Layout::Page::Space::Space(const Element &el):
37  Element(el)
38 {
39  if (!el)
40  throw ExceptionInvalidArgument(_("Null node."));
41  GetAttribute<double>("HEIGHT", false); // may throw
42  GetAttribute<double>("WIDTH", false); // may throw
43  GetAttribute<double>("VPOS", false); // may throw
44  GetAttribute<double>("HPOS", false); // may throw
45 
46  update_subelements();
47 }
48 
50 void Alto::Layout::Page::Space::update_subelements()
51 {
52  blocks.clear();
53  id_blocks.clear();
54  textBlocks.clear();
55  id_textBlocks.clear();
56  illustrations.clear();
57  graphicalElements.clear();
58  composedBlocks.clear();
59 
60  for (Element cel = BeginElement(); cel != EndElement(); ++cel)
61  {
62  std::shared_ptr<Block> newblock;
63  StringUTF8 elname(cel.GetName());
64  if (elname == "TextBlock")
65  {
66  newblock.reset(new TextBlock(cel));
67  textBlocks.push_back(std::static_pointer_cast<TextBlock>(newblock));
68  id_textBlocks[newblock->GetId()] = textBlocks.back();
69  }
70  else if (elname == "Illustration")
71  {
72  newblock.reset(new Illustration(cel));
73  illustrations.push_back(std::static_pointer_cast<Illustration>(newblock));
74  }
75  else if (elname == "GraphicalElement")
76  {
77  newblock.reset(new GraphicalElement(cel));
78  graphicalElements.push_back(std::static_pointer_cast<GraphicalElement>(newblock));
79  }
80  else if (elname == "ComposedBlock")
81  {
82  newblock.reset(new ComposedBlock(cel));
83  composedBlocks.push_back(std::static_pointer_cast<ComposedBlock>(newblock));
84  }
85  if (newblock)
86  {
87  blocks.push_back(newblock);
88  id_blocks[newblock->GetId()] = newblock;
89  }
90  }
91 }
92 
101 Alto::Layout::Page::Space::Space(const Element &el, const Id &id_, double x, double y, double w, double h):
102  Element(el)
103 {
104  SetAttribute("ID", id_);
105  SetAttribute("HPOS", x);
106  SetAttribute("VPOS", y);
107  SetAttribute("WIDTH", w);
108  SetAttribute("HEIGHT", h);
109 }
110 
112 Option<Id> Alto::Layout::Page::Space::GetId() const
113 {
114  Option<Id> id;
115  StringUTF8 str = GetAttribute<StringUTF8>("ID");
116  if (str.IsNotEmpty())
117  id = str;
118  return id;
119 }
120 
122 double Alto::Layout::Page::Space::GetHeight() const
123 {
124  return GetAttribute<double>("HEIGHT", false); // should not throw
125 }
126 
128 void Alto::Layout::Page::Space::SetHeight(double d)
129 {
130  SetAttribute("HEIGHT", d);
131 }
132 
134 double Alto::Layout::Page::Space::GetWidth() const
135 {
136  return GetAttribute<double>("WIDTH", false); // should not throw
137 }
138 
140 void Alto::Layout::Page::Space::SetWidth(double d)
141 {
142  SetAttribute("WIDTH", d);
143 }
144 
146 double Alto::Layout::Page::Space::GetHPos() const
147 {
148  return GetAttribute<double>("HPOS", false); // should throw
149 }
150 
152 void Alto::Layout::Page::Space::SetHPos(double d)
153 {
154  SetAttribute("HPOS", d);
155 }
156 
158 double Alto::Layout::Page::Space::GetVPos() const
159 {
160  return GetAttribute<double>("VPOS", false); // should throw
161 }
162 
164 void Alto::Layout::Page::Space::SetVPos(double d)
165 {
166  SetAttribute("VPOS", d);
167 }
168 
170 std::vector<Id> Alto::Layout::Page::Space::GetStyles() const
171 {
172  return GetStyleRefs(*this);
173 }
174 
178 void Alto::Layout::Page::Space::AddStyle(const Id &styleid)
179 {
180  AddStyleRef(*this, styleid);
181 }
182 
186 void Alto::Layout::Page::Space::RemoveStyle(const Id &styleid)
187 {
188  RemoveStyleRef(*this, styleid);
189 }
190 
196 Alto::Layout::Page::Space::Block& Alto::Layout::Page::Space::GetBlock(const Id &bid)
197 {
198  if (GetNbSubelements() != blocks.size())
199  const_cast<Space*>(this)->update_subelements();
200  std::map<Id, std::weak_ptr<Block> >::iterator it(id_blocks.find(bid));
201  if ((it != id_blocks.end()) && !it->second.expired())
202  return *(it->second.lock());
203  for (const BlockPtr &tb : blocks) // probably useless
204  {
205  const std::shared_ptr<Block> stb(tb.lock());
206  if (tb.lock()->GetId() == bid)
207  {
208  id_blocks[bid] = tb;
209  return *tb.lock();
210  }
211  }
212  throw ExceptionNotFound(_("The space contains no block with this id."));
213 }
214 
216 std::vector<Alto::Layout::Page::Space::BlockPtr> Alto::Layout::Page::Space::GetBlocks() const
217 {
218  if (GetNbSubelements() != blocks.size())
219  const_cast<Space*>(this)->update_subelements();
220  return std::vector<BlockPtr>(blocks.begin(), blocks.end());
221 }
222 
227 void Alto::Layout::Page::Space::RemoveBlock(const Id &bid)
228 {
229  Block &b(GetBlock(bid)); // may throw
230  RemoveChild(b);
231  textBlocks.erase(std::remove_if(textBlocks.begin(), textBlocks.end(), [&bid](const TextBlockPtr &p){ return p.lock()->GetId() == bid; }), textBlocks.end());
232  id_textBlocks.erase(bid);
233  illustrations.erase(std::remove_if(illustrations.begin(), illustrations.end(), [&bid](const IllustrationPtr &p){ return p.lock()->GetId() == bid; }), illustrations.end());
234  graphicalElements.erase(std::remove_if(graphicalElements.begin(), graphicalElements.end(), [&bid](const GraphicalElementPtr &p){ return p.lock()->GetId() == bid; }), graphicalElements.end());
235  composedBlocks.erase(std::remove_if(composedBlocks.begin(), composedBlocks.end(), [&bid](const ComposedBlockPtr &p){ return p.lock()->GetId() == bid; }), composedBlocks.end());
236  blocks.erase(std::remove_if(blocks.begin(), blocks.end(), [&bid](const BlockPtr &p){ return p.lock()->GetId() == bid; }), blocks.end());
237  id_blocks.erase(bid);
238 }
239 
241 std::vector<Id> Alto::Layout::Page::Space::Block::GetStyles() const
242 {
243  return GetStyleRefs(*this);
244 }
245 
249 void Alto::Layout::Page::Space::Block::AddStyle(const Id &styleid)
250 {
251  AddStyleRef(*this, styleid);
252 }
253 
257 void Alto::Layout::Page::Space::Block::RemoveStyle(const Id &styleid)
258 {
259  RemoveStyleRef(*this, styleid);
260 }
261 
267 Alto::Layout::Page::Space::TextBlock& Alto::Layout::Page::Space::GetTextBlock(const Id &id)
268 {
269  if (GetNbSubelements() != blocks.size())
270  const_cast<Space*>(this)->update_subelements();
271  std::map<Id, TextBlockPtr>::iterator it(id_textBlocks.find(id));
272  if ((it != id_textBlocks.end()) && !it->second.expired())
273  return *(it->second.lock());
274  for (const TextBlockPtr &tb : textBlocks)
275  {
276  const std::shared_ptr<TextBlock> stb(tb.lock());
277  if (stb->GetId() == id)
278  {
279  id_textBlocks[id] = tb;
280  return *stb;
281  }
282  }
283  throw ExceptionNotFound(_("The space contains no text block with this id."));
284 }
285 
293 Alto::Layout::Page::Space::TextBlock& Alto::Layout::Page::Space::AddTextBlock(const Id &id_, int x, int y, int w, int h)
294 {
295  std::shared_ptr<TextBlock> bl(new TextBlock(PushBackElement("TextBlock"), id_, x, y, w, h));
296  blocks.push_back(bl);
297  id_blocks[id_] = bl;
298  textBlocks.push_back(bl);
299  id_textBlocks[id_] = textBlocks.back();
300  return *bl;
301 }
302 
312 Alto::Layout::Page::Space::TextBlock& Alto::Layout::Page::Space::AddTextBlockAfter(const Id &pred, const Id &id_, int x, int y, int w, int h)
313 {
314  for (std::vector<std::shared_ptr<Block> >::iterator it = blocks.begin(); it != blocks.end(); ++it)
315  {
316  if ((*it)->GetId() == pred)
317  {
318  Element pel(**it);
319  ++it;
320  if (it == blocks.end())
321  return AddTextBlock(id_, x, y, w, h);
322  else
323  {
324  std::shared_ptr<TextBlock> bl(new TextBlock(InsertElement(pel, "TextBlock"), id_, x, y, w, h));
325  blocks.insert(it, bl);
326  id_blocks[id_] = bl;
327  for (; it != blocks.end(); ++it)
328  {
329  if (std::dynamic_pointer_cast<TextBlock>(*it))
330  break;
331  }
332  if (it != blocks.end())
333  textBlocks.insert(std::find_if(textBlocks.begin(), textBlocks.end(), [&it](const TextBlockPtr &p){ return p.lock() == *it; }), bl);
334  else
335  textBlocks.push_back(bl);
336  id_textBlocks[id_] = bl;
337  return *bl;
338  }
339  }
340  }
341  throw ExceptionNotFound(_("Cannot find block."));
342 }
343 
353 Alto::Layout::Page::Space::TextBlock& Alto::Layout::Page::Space::AddTextBlockBefore(const Id &next, const Id &id_, int x, int y, int w, int h)
354 {
355  for (std::vector<std::shared_ptr<Block> >::iterator it = blocks.begin(); it != blocks.end(); ++it)
356  {
357  if ((*it)->GetId() == next)
358  {
359  std::shared_ptr<TextBlock> bl;
360  if (it == blocks.begin())
361  bl.reset(new TextBlock(PushFrontElement("TextBlock"), id_, x, y, w, h));
362  else
363  bl.reset(new TextBlock(InsertElement(**(it - 1), "TextBlock"), id_, x, y, w, h));
364  blocks.insert(it, bl);
365  id_blocks[id_] = bl;
366  for (; it != blocks.end(); ++it)
367  {
368  if (std::dynamic_pointer_cast<TextBlock>(*it))
369  break;
370  }
371  if (it != blocks.end())
372  textBlocks.insert(std::find_if(textBlocks.begin(), textBlocks.end(), [&it](const TextBlockPtr &p){ return p.lock() == *it; }), bl);
373  else
374  textBlocks.push_back(bl);
375  id_textBlocks[id_] = bl;
376  return *bl;
377  }
378  }
379  throw ExceptionNotFound(_("Cannot find block."));
380 }
381 
383 const std::vector<Alto::Layout::Page::Space::IllustrationPtr>& Alto::Layout::Page::Space::GetIllustrations() const
384 {
385  if (GetNbSubelements() != blocks.size())
386  const_cast<Space*>(this)->update_subelements();
387  return illustrations;
388 }
389 
397 Alto::Layout::Page::Space::Illustration& Alto::Layout::Page::Space::AddIllustration(const Id &id_, int x, int y, int w, int h)
398 {
399  std::shared_ptr<Illustration> bl(new Illustration(PushBackElement("Illustration"), id_, x, y, w, h));
400  blocks.push_back(bl);
401  id_blocks[id_] = bl;
402  illustrations.push_back(bl);
403  return *bl;
404 }
405 
415 Alto::Layout::Page::Space::Illustration& Alto::Layout::Page::Space::AddIllustrationAfter(const Id &pred, const Id &id_, int x, int y, int w, int h)
416 {
417  for (std::vector<std::shared_ptr<Block> >::iterator it = blocks.begin(); it != blocks.end(); ++it)
418  {
419  if ((*it)->GetId() == pred)
420  {
421  Element pel(**it);
422  ++it;
423  if (it == blocks.end())
424  return AddIllustration(id_, x, y, w, h);
425  else
426  {
427  std::shared_ptr<Illustration> bl(new Illustration(InsertElement(pel, "Illustration"), id_, x, y, w, h));
428  blocks.insert(it, bl);
429  id_blocks[id_] = bl;
430  for (; it != blocks.end(); ++it)
431  {
432  if (std::dynamic_pointer_cast<Illustration>(*it))
433  break;
434  }
435  if (it != blocks.end())
436  illustrations.insert(std::find_if(illustrations.begin(), illustrations.end(), [&it](const IllustrationPtr &p){ return p.lock() == *it; }), bl);
437  else
438  illustrations.push_back(bl);
439  return *bl;
440  }
441  }
442  }
443  throw ExceptionNotFound(_("Cannot find block."));
444 }
445 
455 Alto::Layout::Page::Space::Illustration& Alto::Layout::Page::Space::AddIllustrationBefore(const Id &next, const Id &id_, int x, int y, int w, int h)
456 {
457  for (std::vector<std::shared_ptr<Block> >::iterator it = blocks.begin(); it != blocks.end(); ++it)
458  {
459  if ((*it)->GetId() == next)
460  {
461  std::shared_ptr<Illustration> bl;
462  if (it == blocks.begin())
463  bl.reset(new Illustration(PushFrontElement("Illustration"), id_, x, y, w, h));
464  else
465  bl.reset(new Illustration(InsertElement(**(it - 1), "Illustration"), id_, x, y, w, h));
466  blocks.insert(it, bl);
467  id_blocks[id_] = bl;
468  for (; it != blocks.end(); ++it)
469  {
470  if (std::dynamic_pointer_cast<Illustration>(*it))
471  break;
472  }
473  if (it != blocks.end())
474  illustrations.insert(std::find_if(illustrations.begin(), illustrations.end(), [&it](const IllustrationPtr &p){ return p.lock() == *it; }), bl);
475  else
476  illustrations.push_back(bl);
477  return *bl;
478  }
479  }
480  throw ExceptionNotFound(_("Cannot find block."));
481 }
482 
484 const std::vector<Alto::Layout::Page::Space::GraphicalElementPtr>& Alto::Layout::Page::Space::GetGraphicalElements() const
485 {
486  if (GetNbSubelements() != blocks.size())
487  const_cast<Space*>(this)->update_subelements();
488  return graphicalElements;
489 }
490 
498 Alto::Layout::Page::Space::GraphicalElement& Alto::Layout::Page::Space::AddGraphicalElement(const Id &id_, int x, int y, int w, int h)
499 {
500  std::shared_ptr<GraphicalElement> bl(new GraphicalElement(PushBackElement("GraphicalElement"), id_, x, y, w, h));
501  blocks.push_back(bl);
502  id_blocks[id_] = bl;
503  graphicalElements.push_back(bl);
504  return *bl;
505 }
506 
516 Alto::Layout::Page::Space::GraphicalElement& Alto::Layout::Page::Space::AddGraphicalElementAfter(const Id &pred, const Id &id_, int x, int y, int w, int h)
517 {
518  for (std::vector<std::shared_ptr<Block> >::iterator it = blocks.begin(); it != blocks.end(); ++it)
519  {
520  if ((*it)->GetId() == pred)
521  {
522  Element pel(**it);
523  ++it;
524  if (it == blocks.end())
525  return AddGraphicalElement(id_, x, y, w, h);
526  else
527  {
528  std::shared_ptr<GraphicalElement> bl(new GraphicalElement(InsertElement(pel, "GraphicalElement"), id_, x, y, w, h));
529  blocks.insert(it, bl);
530  id_blocks[id_] = bl;
531  for (; it != blocks.end(); ++it)
532  {
533  if (std::dynamic_pointer_cast<GraphicalElement>(*it))
534  break;
535  }
536  if (it != blocks.end())
537  graphicalElements.insert(std::find_if(graphicalElements.begin(), graphicalElements.end(), [&it](const GraphicalElementPtr &p){ return p.lock() == *it; }), bl);
538  else
539  graphicalElements.push_back(bl);
540  return *bl;
541  }
542  }
543  }
544  throw ExceptionNotFound(_("Cannot find block."));
545 }
546 
556 Alto::Layout::Page::Space::GraphicalElement& Alto::Layout::Page::Space::AddGraphicalElementBefore(const Id &next, const Id &id_, int x, int y, int w, int h)
557 {
558  for (std::vector<std::shared_ptr<Block> >::iterator it = blocks.begin(); it != blocks.end(); ++it)
559  {
560  if ((*it)->GetId() == next)
561  {
562  std::shared_ptr<GraphicalElement> bl;
563  if (it == blocks.begin())
564  bl.reset(new GraphicalElement(PushFrontElement("GraphicalElement"), id_, x, y, w, h));
565  else
566  bl.reset(new GraphicalElement(InsertElement(**(it - 1), "GraphicalElement"), id_, x, y, w, h));
567  blocks.insert(it, bl);
568  id_blocks[id_] = bl;
569  for (; it != blocks.end(); ++it)
570  {
571  if (std::dynamic_pointer_cast<GraphicalElement>(*it))
572  break;
573  }
574  if (it != blocks.end())
575  graphicalElements.insert(std::find_if(graphicalElements.begin(), graphicalElements.end(), [&it](const GraphicalElementPtr &p){ return p.lock() == *it; }), bl);
576  else
577  graphicalElements.push_back(bl);
578  return *bl;
579  }
580  }
581  throw ExceptionNotFound(_("Cannot find block."));
582 }
583 
585 const std::vector<Alto::Layout::Page::Space::ComposedBlockPtr>& Alto::Layout::Page::Space::GetComposedBlocks() const
586 {
587  if (GetNbSubelements() != blocks.size())
588  const_cast<Space*>(this)->update_subelements();
589  return composedBlocks;
590 }
591 
593 // Block
595 
600 Alto::Layout::Page::Space::Block::Block(const Element &el):
601  Element(el)
602 {
603  if (!el)
604  throw ExceptionInvalidArgument(_("Null node."));
605  id = GetAttribute<StringUTF8>("ID", false); // may throw
606  GetAttribute<int>("HEIGHT", false); // may throw
607  GetAttribute<int>("WIDTH", false); // may throw
608  GetAttribute<int>("HPOS", false); // may throw
609  GetAttribute<int>("VPOS", false); // may throw
610 }
611 
621 Alto::Layout::Page::Space::Block::Block(const Element &el, const Id &id_, int x, int y, int w, int h):
622  Element(el),
623  id(id_)
624 {
625  if (!el)
626  throw ExceptionInvalidArgument(_("Null node."));
627  SetAttribute("ID", id);
628  SetAttribute("HPOS", x);
629  SetAttribute("VPOS", y);
630  SetAttribute("WIDTH", w);
631  SetAttribute("HEIGHT", h);
632 }
633 
635 int Alto::Layout::Page::Space::Block::GetHeight() const
636 {
637  return GetAttribute<int>("HEIGHT", false); // should not throw
638 }
639 
641 void Alto::Layout::Page::Space::Block::SetHeight(int i)
642 {
643  SetAttribute("HEIGHT", i);
644 }
645 
647 int Alto::Layout::Page::Space::Block::GetWidth() const
648 {
649  return GetAttribute<int>("WIDTH", false); // should not throw
650 }
651 
653 void Alto::Layout::Page::Space::Block::SetWidth(int i)
654 {
655  SetAttribute("WIDTH", i);
656 }
657 
659 int Alto::Layout::Page::Space::Block::GetHPos() const
660 {
661  return GetAttribute<int>("HPOS", false); // should not throw
662 }
663 
665 void Alto::Layout::Page::Space::Block::SetHPos(int i)
666 {
667  SetAttribute("HPOS", i);
668 }
669 
671 int Alto::Layout::Page::Space::Block::GetVPos() const
672 {
673  return GetAttribute<int>("VPOS", false); // should not throw
674 }
675 
677 void Alto::Layout::Page::Space::Block::SetVPos(int i)
678 {
679  SetAttribute("VPOS", i);
680 }
681 
683 Option<double> Alto::Layout::Page::Space::Block::GetRotation() const
684 {
685  Option<double> rotation;
686  try { rotation = GetAttribute<double>("ROTATION", false); } catch (...) { }
687  return rotation;
688 }
689 
691 Option<Id> Alto::Layout::Page::Space::Block::GetNextId() const
692 {
693  Option<Id> next;
694  StringUTF8 str = GetAttribute<StringUTF8>("IDNEXT");
695  if (str.IsNotEmpty())
696  next = str;
697  return next;
698 }
699 
701 // Illustration
703 
710 Alto::Layout::Page::Space::Illustration::Illustration(const Element &el):
711  Block(el)
712 { }
713 
722 Alto::Layout::Page::Space::Illustration::Illustration(const Element &el, const Id &id_, int x, int y, int w, int h):
723  Block(el, id_, x, y, w, h)
724 { }
725 
727 Option<StringUTF8> Alto::Layout::Page::Space::Illustration::GetType() const
728 {
729  Option<StringUTF8> type;
730  StringUTF8 str = GetAttribute<StringUTF8>("TYPE");
731  if (str.IsNotEmpty())
732  type = str;
733  return type;
734 }
735 
737 Option<StringUTF8> Alto::Layout::Page::Space::Illustration::GetFileId() const
738 {
739  Option<StringUTF8> fileId;
740  StringUTF8 str = GetAttribute<StringUTF8>("FILEID");
741  if (str.IsNotEmpty())
742  fileId = str;
743  return fileId;
744 }
745 
747 // GraphicalElement
749 
755 Alto::Layout::Page::Space::GraphicalElement::GraphicalElement(const Element &el):
756  Block(el)
757 {
758  if (!el)
759  throw ExceptionInvalidArgument(_("Null node."));
760 }
761 
772 Alto::Layout::Page::Space::GraphicalElement::GraphicalElement(const Element &el, const Id &id_, int x, int y, int w, int h):
773  Block(el, id_, x, y, w, h)
774 {
775  if (!el)
776  throw ExceptionInvalidArgument(_("Null node."));
777 }
778 
780 // ComposedBlock
782 
788 Alto::Layout::Page::Space::ComposedBlock::ComposedBlock(const Element &el):
789  Block(el)
790 {
791  if (!el)
792  throw ExceptionInvalidArgument(_("Null node."));
793 
794  for (Element cel = BeginElement(); cel != EndElement(); ++cel)
795  {
796  std::shared_ptr<Block> newblock;
797  StringUTF8 elname(cel.GetName());
798  if (elname == "TextBlock")
799  {
800  newblock.reset(new TextBlock(cel));
801  textBlocks.push_back(std::static_pointer_cast<TextBlock>(newblock));
802  }
803  else if (elname == "Illustration")
804  {
805  newblock.reset(new Illustration(cel));
806  illustrations.push_back(std::static_pointer_cast<Illustration>(newblock));
807  }
808  else if (elname == "GraphicalElement")
809  {
810  newblock.reset(new GraphicalElement(cel));
811  graphicalElements.push_back(std::static_pointer_cast<GraphicalElement>(newblock));
812  }
813  else if (elname == "ComposedBlock")
814  {
815  newblock.reset(new ComposedBlock(cel));
816  composedBlocks.push_back(std::static_pointer_cast<ComposedBlock>(newblock));
817  }
818  if (newblock)
819  blocks.push_back(newblock);
820  }
821 }
822 
824 Option<StringUTF8> Alto::Layout::Page::Space::ComposedBlock::GetType() const
825 {
826  Option<StringUTF8> type;
827  StringUTF8 str = GetAttribute<StringUTF8>("TYPE");
828  if (str.IsNotEmpty())
829  type = str;
830  return type;
831 }
832 
834 Option<StringUTF8> Alto::Layout::Page::Space::ComposedBlock::GetFileId() const
835 {
836  Option<StringUTF8> fileId;
837  StringUTF8 str = GetAttribute<StringUTF8>("FILEID");
838  if (str.IsNotEmpty())
839  fileId = str;
840  return fileId;
841 }
842 
XML element.
Definition: CRNXml.h:135
#define _(String)
Definition: CRNi18n.h:51
std::vector< Id > GetStyleRefs(const Element &el)
Gets the list of style references.
bool IsNotEmpty() const noexcept
Checks if the string is not empty.
void AddStyleRef(Element &el, const Id &id)
Adds a style reference to an element.
A block.
Definition: CRNBlock.h:52
void RemoveStyleRef(Element &el, const Id &id)
Removes a style reference to an element.
Alto text block.
A character string class.
Definition: CRNStringUTF8.h:49
A class to store an optional value.
Definition: CRNOption.h:33
Invalid argument error (e.g.: nullptr pointer)
Definition: CRNException.h:107
An item was not found in a container.
Definition: CRNException.h:95