1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /*
3  * This file is part of the libetonyek project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  */
9 
10 #ifndef IWAPARSER_H_INCLUDED
11 #define IWAPARSER_H_INCLUDED
12 
13 #include <deque>
14 #include <functional>
15 #include <map>
16 #include <memory>
17 #include <string>
18 #include <unordered_map>
19 
20 #include <boost/optional.hpp>
21 #include <boost/variant.hpp>
22 
23 #if defined(__GNUC__) && !defined(__clang__)
24 #pragma GCC diagnostic push
25 #pragma GCC diagnostic ignored "-Weffc++"
26 #endif
27 #include <mdds/flat_segment_tree.hpp>
28 #if defined(__GNUC__) && !defined(__clang__)
29 #pragma GCC diagnostic pop
30 #endif
31 
32 #include "libetonyek_utils.h"
33 #include "IWAMessage.h"
34 #include "IWAObjectIndex.h"
35 #include "IWORKLanguageManager.h"
36 #include "IWORKOutputElements.h"
37 #include "IWORKStyle_fwd.h"
38 #include "IWORKTypes.h"
39 
40 namespace libetonyek
41 {
42 
43 class IWORKCollector;
44 class IWAObjectIndex;
45 class IWORKPropertyMap;
46 class IWORKTable;
47 class IWORKText;
48 
49 class IWAParser
50 {
51   friend class IWAObjectIndex; // for readColor
52 
53   // disable copying
54   IWAParser(const IWAParser &);
55   IWAParser &operator=(const IWAParser &);
56 public:
57   IWAParser(const RVNGInputStreamPtr_t &fragments, const RVNGInputStreamPtr_t &package, IWORKCollector &collector);
~IWAParser()58   virtual ~IWAParser()
59   {
60   }
61 
62   bool parse();
63 
64 protected:
65   class ObjectMessage
66   {
67   public:
68     ObjectMessage(IWAParser &parser, unsigned id, unsigned type = 0);
69     ~ObjectMessage();
70 
71     operator bool() const;
72     const IWAMessage &get() const;
73 
74     unsigned getType() const;
75 
get(const ObjectMessage & msg)76     friend const IWAMessage &get(const ObjectMessage &msg)
77     {
78       return msg.get();
79     }
80 
81   private:
82     IWAParser &m_parser;
83     boost::optional<IWAMessage> m_message;
84     const unsigned m_id;
85     unsigned m_type;
86   };
87   friend class ObjectMessage;
88 
89   typedef std::map<unsigned, IWORKStylePtr_t> StyleMap_t;
90   typedef std::function<void(unsigned, IWORKStylePtr_t &)> StyleParseFun_t;
91 
92 protected:
93   static boost::optional<unsigned> readRef(const IWAMessage &msg, unsigned field);
94   static std::deque<unsigned> readRefs(const IWAMessage &msg, unsigned field);
95   static boost::optional<IWORKPosition> readPosition(const IWAMessage &msg, unsigned field);
96   static boost::optional<IWORKSize> readSize(const IWAMessage &msg, unsigned field);
97   static boost::optional<IWORKColor> readColor(const IWAMessage &msg, unsigned field);
98   static boost::optional<std::string> readUUID(const IWAMessage &msg, unsigned field);
99   static boost::optional<uint64_t> readUID(const IWAMessage &msg, unsigned field);
100   static std::deque<uint64_t> readUIDs(const IWAMessage &msg, unsigned field);
101   static void readStroke(const IWAMessage &msg, IWORKStroke &stroke);
102   bool readFill(const IWAMessage &msg, IWORKFill &fill);
103   static void readGradient(const IWAMessage &msg, IWORKGradient &gradient);
104   static void readShadow(const IWAMessage &msg, IWORKShadow &shadow);
105   static void readPadding(const IWAMessage &msg, IWORKPadding &padding);
106 
107   bool dispatchShape(unsigned id);
108   bool dispatchShapeWithMessage(const IWAMessage &msg, unsigned type);
109   bool parseText(unsigned id, bool createNoteAsFootnote=true, const std::function<void(unsigned, IWORKStylePtr_t)> &openPageSpan=nullptr);
110   void parseComment(unsigned id);
111   void parseAuthorInComment(unsigned id);
112   void parseCustomFormat(unsigned id);
113 
114   virtual bool parseShapePlacement(const IWAMessage &msg, IWORKGeometryPtr_t &geometry, boost::optional<unsigned> &flags);
115   void parseMask(unsigned id, IWORKGeometryPtr_t &geometry, IWORKPathPtr_t &path);
116   void updateGeometryUsingTextRef(unsigned id, IWORKGeometry &geometry, unsigned flags);
117 
118   const IWORKStylePtr_t queryCharacterStyle(unsigned id) const;
119   const IWORKStylePtr_t queryParagraphStyle(unsigned id) const;
120   const IWORKStylePtr_t querySectionStyle(unsigned id) const;
121 
122   const IWORKStylePtr_t queryGraphicStyle(unsigned id) const;
123   const IWORKStylePtr_t queryMediaStyle(unsigned id) const;
124   const IWORKStylePtr_t queryCellStyle(unsigned id) const;
125   const IWORKStylePtr_t queryTableStyle(unsigned id) const;
126   const IWORKStylePtr_t queryListStyle(unsigned id) const;
127 
128   const IWORKStylePtr_t queryStyle(unsigned id, StyleMap_t &styleMap, StyleParseFun_t parse) const;
129   boost::optional<unsigned> getObjectType(unsigned id) const;
130 
131 protected:
132   IWORKLanguageManager m_langManager;
133   IWORKTableNameMapPtr_t m_tableNameMap;
134   std::shared_ptr<IWORKText> m_currentText;
135 
136 private:
137   struct Format
138   {
139     Format();
140     boost::optional<IWORKCellType> m_type;
141     boost::variant<IWORKNumberFormat,IWORKDateTimeFormat,IWORKDurationFormat> m_format;
142   };
143 
144   struct PageMaster
145   {
146     PageMaster();
147     IWORKStylePtr_t m_style;
148     bool m_headerFootersSameAsPrevious;
149   };
150 
151   struct TableHeader
152   {
153     TableHeader(unsigned count, float defValue=0);
154 
155     mdds::flat_segment_tree<unsigned, float> m_sizes;
156     mdds::flat_segment_tree<unsigned, bool> m_hidden;
157   };
158 
159   typedef std::map<unsigned, boost::variant<std::string, unsigned, IWORKFormulaPtr_t, Format> > DataList_t;
160 
161   struct TableInfo
162   {
163     TableInfo(const std::shared_ptr<IWORKTable> &table, unsigned columns, unsigned rows);
164 
165     std::shared_ptr<IWORKTable> m_table;
166 
167     const unsigned m_columns;
168     const unsigned m_rows;
169 
170     IWORKStylePtr_t m_style;
171 
172     TableHeader m_columnHeader;
173     TableHeader m_rowHeader;
174 
175     DataList_t m_simpleTextList;
176     DataList_t m_cellStyleList;
177     DataList_t m_formattedTextList;
178     DataList_t m_formulaList;
179     DataList_t m_formatList;
180     DataList_t m_commentList;
181   };
182 
183 private:
184   virtual bool parseDocument() = 0;
185 
186 private:
187   void queryObject(unsigned id, unsigned &type, boost::optional<IWAMessage> &msg) const;
188   const RVNGInputStreamPtr_t queryFile(unsigned id) const;
189 
190   void parseObjectIndex();
191 
192   void parseCharacterStyle(unsigned id, IWORKStylePtr_t &style);
193   void parseParagraphStyle(unsigned id, IWORKStylePtr_t &style);
194   void parseSectionStyle(unsigned id, IWORKStylePtr_t &style);
195 
196   void parseGraphicStyle(unsigned id, IWORKStylePtr_t &style);
197   void parseMediaStyle(unsigned id, IWORKStylePtr_t &style);
198   void parseCellStyle(unsigned id, IWORKStylePtr_t &style);
199   void parseTableStyle(unsigned id, IWORKStylePtr_t &style);
200   void parseListStyle(unsigned id, IWORKStylePtr_t &style);
201 
202   void parseHeaderAndFooter(unsigned id, IWORKPageMaster &hf);
203   void parsePageMaster(unsigned id, PageMaster &pageMaster);
204 
205   void parseTabularModel(unsigned id);
206   void parseDataList(unsigned id, DataList_t &dataList);
207   void parseTile(unsigned id);
208   void parseTableHeaders(unsigned id, TableHeader &header);
209   void parseTableGridLines(unsigned id, IWORKGridLineMap_t (&gridLines)[4]);
210   void parseTableGridLine(unsigned id, IWORKGridLineMap_t &gridLines);
211   void parseLink(unsigned id, std::string &url);
212 
213   bool parseAttachment(unsigned id);
214   bool parseDrawableShape(const IWAMessage &msg, bool isConnectionLine=false);
215   bool parseGroup(const IWAMessage &msg);
216   bool parseShapePlacement(const IWAMessage &msg);
217   bool parseImage(const IWAMessage &msg);
218   bool parseTabularInfo(const IWAMessage &msg);
219   bool parsePath(const IWAMessage &msg, IWORKPathPtr_t &path);
220   bool parseFormula(const IWAMessage &msg, IWORKFormulaPtr_t &formula);
221   bool parseFormat(const IWAMessage &msg, Format &format);
222   virtual bool parseStickyNote(const IWAMessage &msg);
223 
224   bool parseArrowProperties(const IWAMessage &msg, IWORKPropertyMap &props, bool headArrow);
225   void parseCharacterProperties(const IWAMessage &msg, IWORKPropertyMap &props);
226   void parseColumnsProperties(const IWAMessage &msg, IWORKPropertyMap &props);
227 
228 private:
229   IWORKCollector &m_collector;
230 
231   IWAObjectIndex m_index;
232 
233   std::deque<unsigned> m_visited;
234 
235   mutable StyleMap_t m_charStyles;
236   mutable StyleMap_t m_paraStyles;
237   mutable StyleMap_t m_sectionStyles;
238 
239   mutable StyleMap_t m_graphicStyles;
240   mutable StyleMap_t m_mediaStyles;
241   mutable StyleMap_t m_cellStyles;
242   mutable StyleMap_t m_tableStyles;
243   mutable StyleMap_t m_listStyles;
244 
245   std::shared_ptr<TableInfo> m_currentTable;
246   std::map<uint64_t,Format> m_uidFormatMap;
247 };
248 
249 }
250 
251 #endif
252 
253 /* vim:set shiftwidth=2 softtabstop=2 expandtab: */
254