/src/libetonyek/src/lib/KEY1Parser.cpp
Line | Count | Source |
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 | | #include <boost/spirit/include/qi.hpp> |
11 | | |
12 | | #include <glm/glm.hpp> |
13 | | #include <memory> |
14 | | |
15 | | #include "KEY1Parser.h" |
16 | | |
17 | | #include "libetonyek_xml.h" |
18 | | |
19 | | #include "IWORKDiscardContext.h" |
20 | | #include "IWORKProperties.h" |
21 | | #include "IWORKRecorder.h" |
22 | | #include "IWORKText.h" |
23 | | #include "IWORKTokenizer.h" |
24 | | #include "KEYCollector.h" |
25 | | #include "KEYEnum.h" |
26 | | #include "KEY1ContentElement.h" |
27 | | #include "KEY1Dictionary.h" |
28 | | #include "KEY1DivElement.h" |
29 | | #include "KEY1FillElement.h" |
30 | | #include "KEY1ParserState.h" |
31 | | #include "KEY1SpanElement.h" |
32 | | #include "KEY1StringConverter.h" |
33 | | #include "KEY1StylesContext.h" |
34 | | #include "KEY1TableElement.h" |
35 | | #include "KEY1Token.h" |
36 | | #include "KEY1XMLContextBase.h" |
37 | | |
38 | | using boost::optional; |
39 | | |
40 | | namespace libetonyek |
41 | | { |
42 | | |
43 | | namespace |
44 | | { |
45 | | |
46 | | class MetadataElement : public KEY1XMLElementContextBase |
47 | | { |
48 | | public: |
49 | | explicit MetadataElement(KEY1ParserState &state); |
50 | | |
51 | | protected: |
52 | | IWORKXMLContextPtr_t element(int name) override; |
53 | | void endOfElement() override; |
54 | | |
55 | | private: |
56 | | boost::optional<std::string> m_author; |
57 | | boost::optional<std::string> m_title; |
58 | | boost::optional<std::string> m_keywords; |
59 | | boost::optional<std::string> m_comment; |
60 | | }; |
61 | | |
62 | | MetadataElement::MetadataElement(KEY1ParserState &state) |
63 | 0 | : KEY1XMLElementContextBase(state) |
64 | 0 | , m_author() |
65 | 0 | , m_title() |
66 | 0 | , m_keywords() |
67 | 0 | , m_comment() |
68 | 0 | { |
69 | 0 | } |
70 | | |
71 | | IWORKXMLContextPtr_t MetadataElement::element(const int name) |
72 | 0 | { |
73 | 0 | switch (name) |
74 | 0 | { |
75 | | // find application-name, application-version, time-stamp |
76 | 0 | default: |
77 | 0 | break; |
78 | 0 | } |
79 | | |
80 | 0 | return IWORKXMLContextPtr_t(); |
81 | 0 | } |
82 | | |
83 | | void MetadataElement::endOfElement() |
84 | 0 | { |
85 | 0 | IWORKMetadata metadata; |
86 | |
|
87 | 0 | if (m_author) |
88 | 0 | metadata.m_author = get(m_author); |
89 | 0 | if (m_title) |
90 | 0 | metadata.m_title = get(m_title); |
91 | 0 | if (m_keywords) |
92 | 0 | metadata.m_keywords = get(m_keywords); |
93 | 0 | if (m_comment) |
94 | 0 | metadata.m_comment = get(m_comment); |
95 | |
|
96 | 0 | if (isCollector()) |
97 | 0 | getCollector().collectMetadata(metadata); |
98 | 0 | } |
99 | | |
100 | | } |
101 | | |
102 | | namespace |
103 | | { |
104 | | |
105 | | class CDATAElement : public KEY1XMLElementContextBase |
106 | | { |
107 | | public: |
108 | | explicit CDATAElement(KEY1ParserState &state, boost::optional<std::string> &description); |
109 | | |
110 | | private: |
111 | | IWORKXMLContextPtr_t element(int name) override; |
112 | | void CDATA(const char *value) override; |
113 | | |
114 | | private: |
115 | | boost::optional<std::string> &m_description; |
116 | | }; |
117 | | |
118 | | CDATAElement::CDATAElement(KEY1ParserState &state, boost::optional<std::string> &description) |
119 | 0 | : KEY1XMLElementContextBase(state) |
120 | 0 | , m_description(description) |
121 | 0 | { |
122 | 0 | } |
123 | | |
124 | | void CDATAElement::CDATA(const char *value) |
125 | 0 | { |
126 | 0 | m_description=value; |
127 | 0 | } |
128 | | |
129 | | |
130 | | IWORKXMLContextPtr_t CDATAElement::element(const int /*name*/) |
131 | 0 | { |
132 | 0 | ETONYEK_DEBUG_MSG(("CDATAElement::element[KEY1Parser.cpp]: unknown element\n")); |
133 | |
|
134 | 0 | return IWORKXMLContextPtr_t(); |
135 | 0 | } |
136 | | |
137 | | } |
138 | | |
139 | | namespace |
140 | | { |
141 | | |
142 | | class TransitionStyleElement : public KEY1XMLElementContextBase |
143 | | { |
144 | | public: |
145 | | explicit TransitionStyleElement(KEY1ParserState &state); |
146 | | |
147 | | private: |
148 | | void attribute(int name, const char *value) override; |
149 | | IWORKXMLContextPtr_t element(int name) override; |
150 | | |
151 | | private: |
152 | | KEYTransition m_transitionStyle; |
153 | | }; |
154 | | |
155 | | TransitionStyleElement::TransitionStyleElement(KEY1ParserState &state) |
156 | 0 | : KEY1XMLElementContextBase(state) |
157 | 0 | , m_transitionStyle() |
158 | 0 | { |
159 | 0 | } |
160 | | |
161 | | void TransitionStyleElement::attribute(const int name, const char *const value) |
162 | 0 | { |
163 | 0 | switch (name) |
164 | 0 | { |
165 | 0 | case KEY1Token::duration : |
166 | 0 | m_transitionStyle.m_duration=try_double_cast(value); |
167 | 0 | break; |
168 | 0 | case KEY1Token::type : |
169 | 0 | switch (getState().getTokenizer().getId(value)) |
170 | 0 | { |
171 | 0 | case KEY1Token::none : |
172 | 0 | m_transitionStyle.m_type=KEY_TRANSITION_STYLE_TYPE_NONE; |
173 | 0 | break; |
174 | 0 | case KEY1Token::inherited : |
175 | 0 | m_transitionStyle.m_type=KEY_TRANSITION_STYLE_TYPE_INHERITED; |
176 | 0 | break; |
177 | 0 | default : |
178 | 0 | { |
179 | 0 | m_transitionStyle.m_type=KEY_TRANSITION_STYLE_TYPE_NAMED; |
180 | 0 | m_transitionStyle.m_name=value; |
181 | 0 | static bool first=true; |
182 | 0 | if (first) |
183 | 0 | { |
184 | 0 | first=false; |
185 | 0 | ETONYEK_DEBUG_MSG(("TransitionStyleElement::attribute[KEY1Parser.cpp]: find some unexpected type=%s\n", value)); |
186 | 0 | } |
187 | 0 | break; |
188 | 0 | } |
189 | 0 | } |
190 | 0 | break; |
191 | 0 | default : |
192 | 0 | ETONYEK_DEBUG_MSG(("TransitionStyleElement::attribute[KEY1Parser.cpp]: unexpected attribute\n")); |
193 | 0 | break; |
194 | 0 | } |
195 | 0 | } |
196 | | |
197 | | IWORKXMLContextPtr_t TransitionStyleElement::element(const int /*name*/) |
198 | 0 | { |
199 | 0 | ETONYEK_DEBUG_MSG(("TransitionStyleElement::element[KEY1Parser.cpp]: unknown element\n")); |
200 | 0 | return IWORKXMLContextPtr_t(); |
201 | 0 | } |
202 | | } |
203 | | |
204 | | namespace |
205 | | { |
206 | | struct BulletStyle |
207 | | { |
208 | | BulletStyle() |
209 | 0 | : m_relative(true) |
210 | 0 | , m_size() |
211 | 0 | { |
212 | 0 | } |
213 | | bool m_relative; |
214 | | boost::optional<double> m_size; |
215 | | }; |
216 | | } |
217 | | |
218 | | namespace |
219 | | { |
220 | | |
221 | | class BulletCharacterStyleElement : public KEY1XMLElementContextBase |
222 | | { |
223 | | public: |
224 | | explicit BulletCharacterStyleElement(KEY1ParserState &state); |
225 | | |
226 | | private: |
227 | | void attribute(int name, const char *value) override; |
228 | | IWORKXMLContextPtr_t element(int name) override; |
229 | | |
230 | | private: |
231 | | BulletStyle m_bulletStyle; |
232 | | }; |
233 | | |
234 | | BulletCharacterStyleElement::BulletCharacterStyleElement(KEY1ParserState &state) |
235 | 0 | : KEY1XMLElementContextBase(state) |
236 | 0 | , m_bulletStyle() |
237 | 0 | { |
238 | 0 | } |
239 | | |
240 | | void BulletCharacterStyleElement::attribute(const int name, const char *const value) |
241 | 0 | { |
242 | 0 | switch (name) |
243 | 0 | { |
244 | 0 | case KEY1Token::size_technique : |
245 | 0 | switch (getState().getTokenizer().getId(value)) |
246 | 0 | { |
247 | 0 | case KEY1Token::relative : |
248 | 0 | m_bulletStyle.m_relative=true; |
249 | 0 | break; |
250 | 0 | default : |
251 | 0 | ETONYEK_DEBUG_MSG(("BulletCharacterStyleElement::attribute[KEY1Parser.cpp]: unexpected size technique %s\n", value)); |
252 | 0 | break; |
253 | 0 | } |
254 | 0 | break; |
255 | 0 | case KEY1Token::size : |
256 | 0 | m_bulletStyle.m_size=try_double_cast(value); |
257 | 0 | break; |
258 | 0 | default : |
259 | 0 | ETONYEK_DEBUG_MSG(("BulletCharacterStyleElement::attribute[KEY1Parser.cpp]: unexpected attribute\n")); |
260 | 0 | break; |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | | IWORKXMLContextPtr_t BulletCharacterStyleElement::element(const int name) |
265 | 0 | { |
266 | 0 | switch (name) |
267 | 0 | { |
268 | 0 | case +KEY1Token::bullet_characters | KEY1Token::NS_URI_KEY : // README |
269 | 0 | break; |
270 | 0 | default : |
271 | 0 | ETONYEK_DEBUG_MSG(("BulletCharacterStyleElement::element[KEY1Parser.cpp]: unknown element\n")); |
272 | 0 | break; |
273 | 0 | } |
274 | | |
275 | 0 | return IWORKXMLContextPtr_t(); |
276 | 0 | } |
277 | | } |
278 | | |
279 | | namespace |
280 | | { |
281 | | |
282 | | class BulletElement : public KEY1XMLElementContextBase |
283 | | { |
284 | | public: |
285 | | explicit BulletElement(KEY1ParserState &state); |
286 | | |
287 | | private: |
288 | | void attribute(int name, const char *value) override; |
289 | | IWORKXMLContextPtr_t element(int name) override; |
290 | | void endOfElement() override; |
291 | | |
292 | | void ensureOpened(); |
293 | | |
294 | | private: |
295 | | KEY1Bullet m_bullet; |
296 | | bool m_opened; |
297 | | }; |
298 | | |
299 | | BulletElement::BulletElement(KEY1ParserState &state) |
300 | 0 | : KEY1XMLElementContextBase(state) |
301 | 0 | , m_bullet() |
302 | 0 | , m_opened(false) |
303 | 0 | { |
304 | 0 | } |
305 | | |
306 | | void BulletElement::attribute(const int name, const char *const value) |
307 | 0 | { |
308 | 0 | switch (name) |
309 | 0 | { |
310 | 0 | case KEY1Token::level : |
311 | 0 | m_bullet.m_level=try_int_cast(value); |
312 | 0 | break; |
313 | 0 | case KEY1Token::marker_type : |
314 | 0 | switch (getState().getTokenizer().getId(value)) |
315 | 0 | { |
316 | 0 | case KEY1Token::none : |
317 | 0 | m_bullet.m_type=KEY1_BULLETTYPE_NONE; |
318 | 0 | break; |
319 | 0 | case KEY1Token::character : |
320 | 0 | m_bullet.m_type=KEY1_BULLETTYPE_CHARACTER; |
321 | 0 | break; |
322 | 0 | case KEY1Token::image : |
323 | 0 | m_bullet.m_type=KEY1_BULLETTYPE_IMAGE; |
324 | 0 | break; |
325 | 0 | case KEY1Token::inherited : |
326 | 0 | m_bullet.m_type=KEY1_BULLETTYPE_INHERITED; |
327 | 0 | break; |
328 | 0 | case KEY1Token::sequence : |
329 | 0 | m_bullet.m_type=KEY1_BULLETTYPE_SEQUENCE; |
330 | 0 | break; |
331 | 0 | default : |
332 | 0 | ETONYEK_DEBUG_MSG(("BulletElement::attribute[KEY1Parser.cpp]: unexpected type %s\n", value)); |
333 | 0 | break; |
334 | 0 | } |
335 | 0 | break; |
336 | 0 | case KEY1Token::spacing : |
337 | 0 | m_bullet.m_spacing=try_double_cast(value); |
338 | 0 | break; |
339 | 0 | default : |
340 | 0 | ETONYEK_DEBUG_MSG(("BulletElement::attribute[KEY1Parser.cpp]: unexpected attribute\n")); |
341 | 0 | break; |
342 | 0 | } |
343 | 0 | } |
344 | | |
345 | | IWORKXMLContextPtr_t BulletElement::element(const int name) |
346 | 0 | { |
347 | 0 | ensureOpened(); |
348 | 0 | switch (name) |
349 | 0 | { |
350 | 0 | case +KEY1Token::character_bullet_style | KEY1Token::NS_URI_KEY : |
351 | 0 | return std::make_shared<BulletCharacterStyleElement>(getState()); |
352 | 0 | case +KEY1Token::image_bullet_style | KEY1Token::NS_URI_KEY : // README |
353 | 0 | case +KEY1Token::sequence_bullet_style | KEY1Token::NS_URI_KEY : // README |
354 | 0 | break; |
355 | 0 | case +KEY1Token::content | KEY1Token::NS_URI_KEY : |
356 | 0 | return std::make_shared<KEY1ContentElement>(getState()); |
357 | 0 | default : |
358 | 0 | ETONYEK_DEBUG_MSG(("BulletElement::element[KEY1Parser.cpp]: unknown element\n")); |
359 | 0 | break; |
360 | 0 | } |
361 | | |
362 | 0 | return IWORKXMLContextPtr_t(); |
363 | 0 | } |
364 | | |
365 | | void BulletElement::endOfElement() |
366 | 0 | { |
367 | 0 | if (!m_opened) return; |
368 | 0 | getState().closeBullet(); |
369 | 0 | m_opened=false; |
370 | 0 | } |
371 | | |
372 | | void BulletElement::ensureOpened() |
373 | 0 | { |
374 | 0 | if (m_opened) return; |
375 | 0 | getState().openBullet(m_bullet); |
376 | 0 | m_opened=true; |
377 | 0 | } |
378 | | |
379 | | } |
380 | | |
381 | | namespace |
382 | | { |
383 | | |
384 | | class BulletsElement : public KEY1XMLElementContextBase |
385 | | { |
386 | | public: |
387 | | explicit BulletsElement(KEY1ParserState &state, bool prototype); |
388 | | |
389 | | private: |
390 | | void startOfElement() override; |
391 | | IWORKXMLContextPtr_t element(int name) override; |
392 | | void endOfElement() override; |
393 | | |
394 | | private: |
395 | | bool m_prototype; |
396 | | }; |
397 | | |
398 | | BulletsElement::BulletsElement(KEY1ParserState &state, bool prototype) |
399 | 0 | : KEY1XMLElementContextBase(state) |
400 | 0 | , m_prototype(prototype) |
401 | 0 | { |
402 | 0 | } |
403 | | |
404 | | void BulletsElement::startOfElement() |
405 | 0 | { |
406 | 0 | getState().pushIsPrototype(m_prototype); |
407 | 0 | getState().openBullets(); |
408 | 0 | } |
409 | | |
410 | | IWORKXMLContextPtr_t BulletsElement::element(const int name) |
411 | 0 | { |
412 | 0 | switch (name) |
413 | 0 | { |
414 | 0 | case +KEY1Token::bullet | KEY1Token::NS_URI_KEY : |
415 | 0 | return std::make_shared<BulletElement>(getState()); |
416 | 0 | default : |
417 | 0 | ETONYEK_DEBUG_MSG(("BulletsElement::element[KEY1Parser.cpp]: unknown element\n")); |
418 | 0 | break; |
419 | 0 | } |
420 | | |
421 | 0 | return IWORKXMLContextPtr_t(); |
422 | 0 | } |
423 | | |
424 | | void BulletsElement::endOfElement() |
425 | 0 | { |
426 | 0 | getState().closeBullets(); |
427 | 0 | getState().popIsPrototype(); |
428 | 0 | } |
429 | | |
430 | | } |
431 | | |
432 | | namespace |
433 | | { |
434 | | |
435 | | class BasicShapeElement : public KEY1XMLElementContextBase |
436 | | { |
437 | | public: |
438 | | explicit BasicShapeElement(KEY1ParserState &state); |
439 | | |
440 | | protected: |
441 | | void attribute(int name, const char *value) override; |
442 | | void startOfElement() override; |
443 | | IWORKXMLContextPtr_t element(int name) override; |
444 | | void endOfElement() override; |
445 | | |
446 | | IWORKStylePtr_t getStyle() const |
447 | 0 | { |
448 | 0 | return m_style; |
449 | 0 | } |
450 | | private: |
451 | | IWORKStylePtr_t m_style; |
452 | | boost::optional<IWORKColor> m_strokeColor; |
453 | | boost::optional<double> m_strokeWidth; |
454 | | boost::optional<double> m_opacity; |
455 | | }; |
456 | | |
457 | | BasicShapeElement::BasicShapeElement(KEY1ParserState &state) |
458 | 0 | : KEY1XMLElementContextBase(state) |
459 | 0 | , m_style() |
460 | 0 | , m_strokeColor() |
461 | 0 | , m_strokeWidth() |
462 | 0 | , m_opacity() |
463 | 0 | { |
464 | 0 | } |
465 | | |
466 | | void BasicShapeElement::attribute(const int name, const char *const value) |
467 | 0 | { |
468 | 0 | switch (name) |
469 | 0 | { |
470 | 0 | case KEY1Token::id : |
471 | 0 | setId(value); |
472 | 0 | break; |
473 | 0 | case KEY1Token::opacity : |
474 | 0 | m_opacity=try_double_cast(value); |
475 | 0 | break; |
476 | 0 | case KEY1Token::stroke_color : |
477 | 0 | m_strokeColor=KEY1StringConverter<IWORKColor>::convert(value); |
478 | 0 | break; |
479 | 0 | case KEY1Token::stroke_width : |
480 | 0 | m_strokeWidth=try_double_cast(value); |
481 | 0 | break; |
482 | 0 | default : |
483 | 0 | ETONYEK_DEBUG_MSG(("BasicShapeElement::attribute[KEY1Parser.cpp]: unexpected attribute\n")); |
484 | 0 | break; |
485 | 0 | } |
486 | 0 | } |
487 | | |
488 | | void BasicShapeElement::startOfElement() |
489 | 0 | { |
490 | 0 | } |
491 | | |
492 | | IWORKXMLContextPtr_t BasicShapeElement::element(const int name) |
493 | 0 | { |
494 | 0 | switch (name) |
495 | 0 | { |
496 | 0 | case +KEY1Token::styles | KEY1Token::NS_URI_KEY : |
497 | 0 | return std::make_shared<KEY1StylesContext>(getState(), m_style, IWORKStylePtr_t()); |
498 | 0 | default : |
499 | 0 | ETONYEK_DEBUG_MSG(("BasicShapeElement::element[KEY1Parser.cpp]: unknown element\n")); |
500 | 0 | break; |
501 | 0 | } |
502 | 0 | return IWORKXMLContextPtr_t(); |
503 | 0 | } |
504 | | |
505 | | void BasicShapeElement::endOfElement() |
506 | 0 | { |
507 | 0 | if (getState().m_isPrototype&& (!m_strokeColor && !m_strokeWidth && !m_opacity)) |
508 | 0 | return; |
509 | 0 | if (!m_style) |
510 | 0 | m_style = std::make_shared<IWORKStyle>(IWORKPropertyMap(), boost::none, IWORKStylePtr_t()); |
511 | 0 | if (m_opacity) |
512 | 0 | m_style->getPropertyMap().put<property::Opacity>(get(m_opacity)); |
513 | 0 | if (m_strokeColor || m_strokeWidth) |
514 | 0 | { |
515 | 0 | IWORKStroke stroke; |
516 | 0 | if (m_style->has<property::Stroke>()) |
517 | 0 | stroke=m_style->get<property::Stroke>(); |
518 | 0 | else |
519 | 0 | stroke.m_pattern.m_type = IWORK_STROKE_TYPE_SOLID; |
520 | 0 | if (m_strokeColor) stroke.m_color=get(m_strokeColor); |
521 | 0 | if (m_strokeWidth) stroke.m_width=get(m_strokeWidth); |
522 | 0 | m_style->getPropertyMap().put<property::Stroke>(stroke); |
523 | 0 | } |
524 | 0 | } |
525 | | |
526 | | } |
527 | | |
528 | | namespace |
529 | | { |
530 | | |
531 | | class ImageElement : public BasicShapeElement |
532 | | { |
533 | | public: |
534 | | explicit ImageElement(KEY1ParserState &state); |
535 | | |
536 | | private: |
537 | | void attribute(int name, const char *value) override; |
538 | | void startOfElement() override; |
539 | | void endOfElement() override; |
540 | | private: |
541 | | boost::optional<std::string> m_displayName; |
542 | | boost::optional<std::string> m_imageName; |
543 | | bool m_lockAspectRatio; |
544 | | bool m_locked; |
545 | | boost::optional<IWORKSize> m_naturalSize; |
546 | | boost::optional<glm::dmat3> m_transformation; |
547 | | }; |
548 | | |
549 | | ImageElement::ImageElement(KEY1ParserState &state) |
550 | 0 | : BasicShapeElement(state) |
551 | 0 | , m_displayName() |
552 | 0 | , m_imageName() |
553 | 0 | , m_lockAspectRatio(false) |
554 | 0 | , m_locked(false) |
555 | 0 | , m_naturalSize() |
556 | 0 | , m_transformation() |
557 | 0 | { |
558 | 0 | } |
559 | | |
560 | | void ImageElement::attribute(const int name, const char *const value) |
561 | 0 | { |
562 | 0 | switch (name) |
563 | 0 | { |
564 | 0 | case KEY1Token::display_name : |
565 | 0 | m_displayName=value; |
566 | 0 | break; |
567 | 0 | case KEY1Token::image_data : |
568 | 0 | m_imageName=value; |
569 | 0 | break; |
570 | 0 | case KEY1Token::locked : |
571 | 0 | m_locked = bool_cast(value); |
572 | 0 | break; |
573 | 0 | case KEY1Token::lock_aspect_ratio : |
574 | 0 | m_lockAspectRatio = bool_cast(value); |
575 | 0 | break; |
576 | 0 | case KEY1Token::natural_size : |
577 | 0 | m_naturalSize = KEY1StringConverter<IWORKSize>::convert(value); |
578 | 0 | break; |
579 | 0 | case KEY1Token::transformation : |
580 | 0 | m_transformation=KEY1StringConverter<glm::dmat3>::convert(value); |
581 | 0 | break; |
582 | 0 | case KEY1Token::byte_size : // the image size |
583 | 0 | break; |
584 | 0 | default : |
585 | 0 | BasicShapeElement::attribute(name,value); |
586 | 0 | break; |
587 | 0 | } |
588 | 0 | } |
589 | | |
590 | | void ImageElement::startOfElement() |
591 | 0 | { |
592 | 0 | BasicShapeElement::startOfElement(); |
593 | 0 | if (!getState().m_isPrototype&& isCollector()) |
594 | 0 | getCollector().startLevel(); |
595 | 0 | } |
596 | | |
597 | | void ImageElement::endOfElement() |
598 | 0 | { |
599 | 0 | BasicShapeElement::endOfElement(); |
600 | 0 | IWORKMediaContentPtr_t content; |
601 | |
|
602 | 0 | if (m_imageName) |
603 | 0 | { |
604 | 0 | content = std::make_shared<IWORKMediaContent>(); |
605 | 0 | content->m_data = std::make_shared<IWORKData>(); |
606 | 0 | content->m_data->m_stream.reset(getState().getParser().getPackage()->getSubStreamByName(get(m_imageName).c_str())); |
607 | 0 | content->m_size=m_naturalSize; |
608 | 0 | } |
609 | 0 | IWORKGeometryPtr_t geometry; |
610 | 0 | if (m_transformation && m_naturalSize) |
611 | 0 | { |
612 | 0 | geometry = std::make_shared<IWORKGeometry>(); |
613 | 0 | glm::dvec3 pos=get(m_transformation)*glm::dvec3(0,0,1); |
614 | 0 | geometry->m_position=IWORKPosition(pos[0],pos[1]); |
615 | 0 | glm::dvec3 dim=get(m_transformation)*glm::dvec3(get(m_naturalSize).m_width,get(m_naturalSize).m_height,0); |
616 | 0 | geometry->m_size=IWORKSize(dim[0],dim[1]); |
617 | 0 | } |
618 | 0 | if (getId() && content) |
619 | 0 | getState().getDictionary().m_images[get(getId())]=content; |
620 | |
|
621 | 0 | IWORKStylePtr_t style=getStyle(); |
622 | 0 | getState().getDictionary().storeImageStyle(style, getState().m_isPrototype); |
623 | 0 | if (!getState().m_isPrototype&& isCollector()) |
624 | 0 | { |
625 | 0 | if (geometry && content) |
626 | 0 | { |
627 | 0 | getCollector().collectGeometry(geometry); |
628 | 0 | getCollector().setGraphicStyle(style); |
629 | 0 | getCollector().collectImage(content, IWORKGeometryPtr_t(), boost::none, m_locked); |
630 | 0 | } |
631 | 0 | getCollector().endLevel(); |
632 | 0 | } |
633 | 0 | } |
634 | | } |
635 | | |
636 | | namespace |
637 | | { |
638 | | |
639 | | class LineElement : public BasicShapeElement |
640 | | { |
641 | | public: |
642 | | explicit LineElement(KEY1ParserState &state); |
643 | | |
644 | | private: |
645 | | void attribute(int name, const char *value) override; |
646 | | void startOfElement() override; |
647 | | void endOfElement() override; |
648 | | private: |
649 | | boost::optional<IWORKPosition> m_head; |
650 | | boost::optional<IWORKPosition> m_tail; |
651 | | }; |
652 | | |
653 | | LineElement::LineElement(KEY1ParserState &state) |
654 | 0 | : BasicShapeElement(state) |
655 | 0 | , m_head() |
656 | 0 | , m_tail() |
657 | 0 | { |
658 | 0 | } |
659 | | |
660 | | void LineElement::attribute(const int name, const char *const value) |
661 | 0 | { |
662 | 0 | switch (name) |
663 | 0 | { |
664 | 0 | case KEY1Token::head : |
665 | 0 | m_head=KEY1StringConverter<IWORKPosition>::convert(value); |
666 | 0 | break; |
667 | 0 | case KEY1Token::tail : |
668 | 0 | m_tail=KEY1StringConverter<IWORKPosition>::convert(value); |
669 | 0 | break; |
670 | 0 | default : |
671 | 0 | BasicShapeElement::attribute(name,value); |
672 | 0 | break; |
673 | 0 | } |
674 | 0 | } |
675 | | |
676 | | void LineElement::startOfElement() |
677 | 0 | { |
678 | 0 | BasicShapeElement::startOfElement(); |
679 | 0 | if (!getState().m_isPrototype&& isCollector()) |
680 | 0 | getCollector().startLevel(); |
681 | 0 | } |
682 | | |
683 | | void LineElement::endOfElement() |
684 | 0 | { |
685 | 0 | BasicShapeElement::endOfElement(); |
686 | 0 | IWORKLinePtr_t line(new IWORKLine()); |
687 | 0 | if (m_tail) |
688 | 0 | { |
689 | 0 | line->m_x1 = get(m_tail).m_x; |
690 | 0 | line->m_y1 = get(m_tail).m_y; |
691 | 0 | } |
692 | 0 | if (m_head) |
693 | 0 | { |
694 | 0 | line->m_x2 = get(m_head).m_x; |
695 | 0 | line->m_y2 = get(m_head).m_y; |
696 | 0 | } |
697 | 0 | IWORKStylePtr_t style=getStyle(); |
698 | 0 | getState().getDictionary().storeLineStyle(style, getState().m_isPrototype); |
699 | 0 | if (!getState().m_isPrototype&& isCollector()) |
700 | 0 | { |
701 | 0 | getCollector().setGraphicStyle(style); |
702 | 0 | getCollector().collectLine(line); |
703 | 0 | getCollector().endLevel(); |
704 | 0 | } |
705 | 0 | } |
706 | | } |
707 | | |
708 | | namespace |
709 | | { |
710 | | |
711 | | class ShapeElement : public BasicShapeElement |
712 | | { |
713 | | public: |
714 | | explicit ShapeElement(KEY1ParserState &state); |
715 | | |
716 | | private: |
717 | | void attribute(int name, const char *value) override; |
718 | | void startOfElement() override; |
719 | | void endOfElement() override; |
720 | | private: |
721 | | IWORKPathPtr_t m_path; |
722 | | boost::optional<glm::dmat3> m_transformation; |
723 | | }; |
724 | | |
725 | | ShapeElement::ShapeElement(KEY1ParserState &state) |
726 | 0 | : BasicShapeElement(state) |
727 | 0 | , m_path() |
728 | 0 | , m_transformation() |
729 | 0 | { |
730 | 0 | } |
731 | | |
732 | | void ShapeElement::attribute(const int name, const char *const value) |
733 | 0 | { |
734 | 0 | switch (name) |
735 | 0 | { |
736 | 0 | case KEY1Token::path : |
737 | 0 | try |
738 | 0 | { |
739 | 0 | m_path = std::make_shared<IWORKPath>(value); |
740 | 0 | } |
741 | 0 | catch (const IWORKPath::InvalidException &) |
742 | 0 | { |
743 | 0 | ETONYEK_DEBUG_MSG(("ShapeElement::attribute[KEY1Parser.cpp]: '%s' is not a valid path\n", value)); |
744 | 0 | } |
745 | 0 | break; |
746 | 0 | case KEY1Token::transformation : |
747 | 0 | m_transformation=KEY1StringConverter<glm::dmat3>::convert(value); |
748 | 0 | break; |
749 | 0 | default : |
750 | 0 | BasicShapeElement::attribute(name, value); |
751 | 0 | break; |
752 | 0 | } |
753 | 0 | } |
754 | | |
755 | | void ShapeElement::startOfElement() |
756 | 0 | { |
757 | 0 | BasicShapeElement::startOfElement(); |
758 | 0 | if (!getState().m_isPrototype&& isCollector()) |
759 | 0 | getCollector().startLevel(); |
760 | 0 | } |
761 | | |
762 | | void ShapeElement::endOfElement() |
763 | 0 | { |
764 | 0 | BasicShapeElement::endOfElement(); |
765 | 0 | IWORKStylePtr_t style=getStyle(); |
766 | 0 | getState().getDictionary().storeShapeStyle(style, getState().m_isPrototype); |
767 | 0 | if (!getState().m_isPrototype&& isCollector()) |
768 | 0 | { |
769 | 0 | if (m_path) |
770 | 0 | { |
771 | 0 | getCollector().setGraphicStyle(style); |
772 | 0 | if (m_transformation) |
773 | 0 | *m_path *= get(m_transformation); |
774 | 0 | getCollector().collectBezier(m_path); |
775 | 0 | getCollector().collectShape(); |
776 | 0 | } |
777 | 0 | getCollector().endLevel(); |
778 | 0 | } |
779 | 0 | } |
780 | | } |
781 | | |
782 | | namespace |
783 | | { |
784 | | class TextAttributesElement : public KEY1XMLElementContextBase |
785 | | { |
786 | | public: |
787 | | TextAttributesElement(KEY1ParserState &state, IWORKStylePtr_t &spanStyle, IWORKStylePtr_t &divStyle); |
788 | | |
789 | | protected: |
790 | | void attribute(int name, const char *value) override; |
791 | | IWORKXMLContextPtr_t element(int name) override; |
792 | | void endOfElement() override; |
793 | | |
794 | | private: |
795 | | KEY1DivStyle m_divStyle; |
796 | | KEY1SpanStyle m_spanStyle; |
797 | | |
798 | | IWORKStylePtr_t &m_divStylePtr; |
799 | | IWORKStylePtr_t &m_spanStylePtr; |
800 | | }; |
801 | | |
802 | | TextAttributesElement::TextAttributesElement(KEY1ParserState &state, IWORKStylePtr_t &spanStyle, IWORKStylePtr_t &divStyle) |
803 | 0 | : KEY1XMLElementContextBase(state) |
804 | 0 | , m_divStyle(state, IWORKStylePtr_t()) |
805 | 0 | , m_spanStyle(state, IWORKStylePtr_t()) |
806 | 0 | , m_divStylePtr(divStyle) |
807 | 0 | , m_spanStylePtr(spanStyle) |
808 | 0 | { |
809 | 0 | } |
810 | | |
811 | | void TextAttributesElement::attribute(const int name, const char *const value) |
812 | 0 | { |
813 | 0 | if (m_divStyle.readAttribute(name, value) || |
814 | 0 | m_spanStyle.readAttribute(name, value)) |
815 | 0 | return; |
816 | 0 | switch (name) |
817 | 0 | { |
818 | 0 | case KEY1Token::id : |
819 | 0 | setId(value); |
820 | 0 | break; |
821 | 0 | default: |
822 | 0 | ETONYEK_DEBUG_MSG(("TextAttributesElement::attribute[KEY1Parser.cpp] attribute with value=%s\n", value)); |
823 | 0 | } |
824 | 0 | } |
825 | | |
826 | | IWORKXMLContextPtr_t TextAttributesElement::element(const int name) |
827 | 0 | { |
828 | 0 | switch (name) |
829 | 0 | { |
830 | 0 | default: |
831 | 0 | ETONYEK_DEBUG_MSG(("TextAttributesElement::element[KEY1Parser.cpp]: unknown element\n")); |
832 | 0 | } |
833 | 0 | return IWORKXMLContextPtr_t(); |
834 | 0 | } |
835 | | |
836 | | void TextAttributesElement::endOfElement() |
837 | 0 | { |
838 | 0 | m_divStylePtr = m_divStyle.getStyle(); |
839 | 0 | m_spanStylePtr = m_spanStyle.getStyle(); |
840 | 0 | } |
841 | | |
842 | | } |
843 | | |
844 | | namespace |
845 | | { |
846 | | class PlaceholderElement : public BasicShapeElement |
847 | | { |
848 | | public: |
849 | | explicit PlaceholderElement(KEY1ParserState &state); |
850 | | |
851 | | KEYPlaceholderPtr_t getPlaceholder(); |
852 | | |
853 | | protected: |
854 | | void attribute(int name, const char *value) override; |
855 | | IWORKXMLContextPtr_t element(int name) override; |
856 | | |
857 | | private: |
858 | | boost::optional<IWORKPosition> m_location; |
859 | | boost::optional<IWORKSize> m_size; |
860 | | IWORKStylePtr_t m_paragraphStyle; |
861 | | IWORKStylePtr_t m_spanStyle; |
862 | | boost::optional<IWORKVerticalAlignment> m_verticalAlignment; |
863 | | boost::optional<bool> m_visible; |
864 | | }; |
865 | | |
866 | | PlaceholderElement::PlaceholderElement(KEY1ParserState &state) |
867 | 0 | : BasicShapeElement(state) |
868 | 0 | , m_location() |
869 | 0 | , m_size() |
870 | 0 | , m_paragraphStyle() |
871 | 0 | , m_spanStyle() |
872 | 0 | , m_verticalAlignment() |
873 | 0 | , m_visible() |
874 | 0 | { |
875 | 0 | } |
876 | | |
877 | | void PlaceholderElement::attribute(const int name, const char *const value) |
878 | 0 | { |
879 | 0 | switch (name) |
880 | 0 | { |
881 | 0 | case KEY1Token::location : |
882 | 0 | m_location=KEY1StringConverter<IWORKPosition>::convert(value); |
883 | 0 | break; |
884 | 0 | case KEY1Token::size : |
885 | 0 | m_size=KEY1StringConverter<IWORKSize>::convert(value); |
886 | 0 | break; |
887 | 0 | case KEY1Token::vertical_alignment : |
888 | 0 | switch (getState().getTokenizer().getId(value)) |
889 | 0 | { |
890 | 0 | case KEY1Token::bottom : |
891 | 0 | m_verticalAlignment = IWORK_VERTICAL_ALIGNMENT_BOTTOM; |
892 | 0 | break; |
893 | 0 | case KEY1Token::middle : |
894 | 0 | m_verticalAlignment = IWORK_VERTICAL_ALIGNMENT_MIDDLE; |
895 | 0 | break; |
896 | 0 | case KEY1Token::top : |
897 | 0 | m_verticalAlignment = IWORK_VERTICAL_ALIGNMENT_TOP; |
898 | 0 | break; |
899 | 0 | case KEY1Token::tracks_master : |
900 | 0 | break; |
901 | 0 | default : |
902 | 0 | ETONYEK_DEBUG_MSG(("PlaceHolderElement::attribute[KEY1Parser.cpp]: unexpected vertical align %s\n", value)); |
903 | 0 | break; |
904 | 0 | } |
905 | 0 | break; |
906 | 0 | case KEY1Token::visibility : |
907 | 0 | switch (getState().getTokenizer().getId(value)) |
908 | 0 | { |
909 | 0 | case KEY1Token::hidden : |
910 | 0 | m_visible = false; |
911 | 0 | break; |
912 | 0 | case KEY1Token::visible : |
913 | 0 | m_visible = true; |
914 | 0 | break; |
915 | 0 | case KEY1Token::tracks_master : |
916 | 0 | break; |
917 | 0 | default : |
918 | 0 | ETONYEK_DEBUG_MSG(("PlaceHolderElement::attribute[KEY1Parser.cpp]: unexpected visibily align %s\n", value)); |
919 | 0 | break; |
920 | 0 | } |
921 | 0 | break; |
922 | 0 | default : |
923 | 0 | BasicShapeElement::attribute(name, value); |
924 | 0 | break; |
925 | 0 | } |
926 | 0 | } |
927 | | |
928 | | IWORKXMLContextPtr_t PlaceholderElement::element(const int name) |
929 | 0 | { |
930 | 0 | switch (name) |
931 | 0 | { |
932 | 0 | case +KEY1Token::text_attributes | KEY1Token::NS_URI_KEY : |
933 | 0 | return std::make_shared<TextAttributesElement>(getState(), m_spanStyle, m_paragraphStyle); |
934 | 0 | default: |
935 | 0 | break; |
936 | 0 | } |
937 | 0 | return BasicShapeElement::element(name); |
938 | 0 | } |
939 | | |
940 | | KEYPlaceholderPtr_t PlaceholderElement::getPlaceholder() |
941 | 0 | { |
942 | 0 | KEYPlaceholderPtr_t res(new KEYPlaceholder); |
943 | 0 | res->m_style = getStyle(); |
944 | 0 | res->m_paragraphStyle = m_paragraphStyle; |
945 | 0 | res->m_spanStyle = m_spanStyle; |
946 | 0 | if (m_location && m_size) |
947 | 0 | { |
948 | 0 | IWORKGeometryPtr_t geometry(new IWORKGeometry); |
949 | 0 | geometry->m_position=get(m_location); |
950 | 0 | geometry->m_naturalSize=geometry->m_size=get(m_size); |
951 | 0 | res->m_geometry=geometry; |
952 | 0 | } |
953 | 0 | res->m_visible=m_visible; |
954 | |
|
955 | 0 | return res; |
956 | 0 | } |
957 | | |
958 | | } |
959 | | |
960 | | namespace |
961 | | { |
962 | | class BodyElement : public PlaceholderElement |
963 | | { |
964 | | public: |
965 | | explicit BodyElement(KEY1ParserState &state); |
966 | | |
967 | | private: |
968 | | void attribute(int name, const char *value) override; |
969 | | void endOfElement() override; |
970 | | private: |
971 | | std::deque<double> m_indents; |
972 | | }; |
973 | | |
974 | | BodyElement::BodyElement(KEY1ParserState &state) |
975 | 0 | : PlaceholderElement(state) |
976 | 0 | , m_indents() |
977 | 0 | { |
978 | 0 | } |
979 | | |
980 | | void BodyElement::attribute(const int name, const char *const value) |
981 | 0 | { |
982 | 0 | switch (name) |
983 | 0 | { |
984 | 0 | case KEY1Token::bullet_indentation : |
985 | 0 | { |
986 | 0 | std::string val(value); |
987 | 0 | std::string::const_iterator it(val.begin()), end(val.end()); |
988 | |
|
989 | 0 | namespace ascii = boost::spirit::ascii; |
990 | 0 | namespace qi = boost::spirit::qi; |
991 | 0 | if (qi::phrase_parse(it, end, qi::double_ >> *(qi::double_), ascii::space, m_indents) && it==end) |
992 | 0 | ; |
993 | 0 | else |
994 | 0 | { |
995 | 0 | ETONYEK_DEBUG_MSG(("BodyElement::attribute[KEY1Parser.cpp]: unexpected bullet indentation %s\n", value)); |
996 | 0 | } |
997 | 0 | break; |
998 | 0 | } |
999 | 0 | default : |
1000 | 0 | PlaceholderElement::attribute(name, value); |
1001 | 0 | } |
1002 | 0 | } |
1003 | | |
1004 | | void BodyElement::endOfElement() |
1005 | 0 | { |
1006 | 0 | KEYPlaceholderPtr_t placeHolder=getPlaceholder(); |
1007 | 0 | if (!placeHolder) return; |
1008 | 0 | placeHolder->m_bulletIndentations=m_indents; |
1009 | 0 | getState().getDictionary().storeBodyPlaceholder(placeHolder); |
1010 | 0 | } |
1011 | | } |
1012 | | |
1013 | | namespace |
1014 | | { |
1015 | | class PageNumberElement : public PlaceholderElement |
1016 | | { |
1017 | | public: |
1018 | | explicit PageNumberElement(KEY1ParserState &state); |
1019 | | |
1020 | | private: |
1021 | | void endOfElement() override; |
1022 | | private: |
1023 | | }; |
1024 | | |
1025 | | PageNumberElement::PageNumberElement(KEY1ParserState &state) |
1026 | 0 | : PlaceholderElement(state) |
1027 | 0 | { |
1028 | 0 | } |
1029 | | |
1030 | | void PageNumberElement::endOfElement() |
1031 | 0 | { |
1032 | 0 | getState().getDictionary().storePageNumberPlaceholder(getPlaceholder()); |
1033 | 0 | } |
1034 | | } |
1035 | | |
1036 | | namespace |
1037 | | { |
1038 | | class TitleElement : public PlaceholderElement |
1039 | | { |
1040 | | public: |
1041 | | explicit TitleElement(KEY1ParserState &state); |
1042 | | |
1043 | | private: |
1044 | | void endOfElement() override; |
1045 | | private: |
1046 | | }; |
1047 | | |
1048 | | TitleElement::TitleElement(KEY1ParserState &state) |
1049 | 0 | : PlaceholderElement(state) |
1050 | 0 | { |
1051 | 0 | } |
1052 | | |
1053 | | void TitleElement::endOfElement() |
1054 | 0 | { |
1055 | 0 | getState().getDictionary().storeTitlePlaceholder(getPlaceholder()); |
1056 | 0 | } |
1057 | | } |
1058 | | |
1059 | | namespace |
1060 | | { |
1061 | | |
1062 | | class TextboxElement : public BasicShapeElement |
1063 | | { |
1064 | | public: |
1065 | | explicit TextboxElement(KEY1ParserState &state); |
1066 | | |
1067 | | private: |
1068 | | void attribute(int name, const char *value) override; |
1069 | | void startOfElement() override; |
1070 | | IWORKXMLContextPtr_t element(int name) override; |
1071 | | void endOfElement() override; |
1072 | | private: |
1073 | | boost::optional<IWORKSize> m_size; |
1074 | | boost::optional<glm::dmat3> m_transformation; |
1075 | | boost::optional<bool> m_growHorizontally; |
1076 | | }; |
1077 | | |
1078 | | TextboxElement::TextboxElement(KEY1ParserState &state) |
1079 | 0 | : BasicShapeElement(state) |
1080 | 0 | , m_size() |
1081 | 0 | , m_transformation() |
1082 | 0 | , m_growHorizontally() |
1083 | 0 | { |
1084 | 0 | } |
1085 | | |
1086 | | void TextboxElement::attribute(const int name, const char *const value) |
1087 | 0 | { |
1088 | 0 | switch (name) |
1089 | 0 | { |
1090 | 0 | case KEY1Token::grow_horizontally : |
1091 | 0 | m_growHorizontally = try_bool_cast(value); |
1092 | 0 | break; |
1093 | 0 | case KEY1Token::size : |
1094 | 0 | m_size=KEY1StringConverter<IWORKSize>::convert(value); |
1095 | 0 | break; |
1096 | 0 | case KEY1Token::transformation : |
1097 | 0 | m_transformation=KEY1StringConverter<glm::dmat3>::convert(value); |
1098 | 0 | break; |
1099 | 0 | default : |
1100 | 0 | BasicShapeElement::attribute(name, value); |
1101 | 0 | break; |
1102 | 0 | } |
1103 | 0 | } |
1104 | | |
1105 | | void TextboxElement::startOfElement() |
1106 | 0 | { |
1107 | 0 | BasicShapeElement::startOfElement(); |
1108 | 0 | if (!getState().m_isPrototype&& isCollector()) |
1109 | 0 | { |
1110 | 0 | getCollector().startLevel(); |
1111 | 0 | assert(!getState().m_currentText); |
1112 | 0 | getState().m_currentText = getCollector().createText(getState().m_langManager); |
1113 | 0 | } |
1114 | 0 | } |
1115 | | |
1116 | | IWORKXMLContextPtr_t TextboxElement::element(const int name) |
1117 | 0 | { |
1118 | 0 | switch (name) |
1119 | 0 | { |
1120 | 0 | case +KEY1Token::content | KEY1Token::NS_URI_KEY : |
1121 | 0 | return std::make_shared<KEY1ContentElement>(getState()); |
1122 | 0 | default: |
1123 | 0 | break; |
1124 | 0 | } |
1125 | 0 | return BasicShapeElement::element(name); |
1126 | 0 | } |
1127 | | |
1128 | | void TextboxElement::endOfElement() |
1129 | 0 | { |
1130 | 0 | BasicShapeElement::endOfElement(); |
1131 | 0 | IWORKStylePtr_t style=getStyle(); |
1132 | 0 | getState().getDictionary().storeTextboxStyle(style, getState().m_isPrototype); |
1133 | 0 | if (!getState().m_isPrototype && isCollector()) |
1134 | 0 | { |
1135 | 0 | getCollector().setGraphicStyle(style); |
1136 | 0 | if (m_transformation && m_size) |
1137 | 0 | { |
1138 | 0 | IWORKGeometryPtr_t geometry(new IWORKGeometry); |
1139 | 0 | glm::dvec3 pos=get(m_transformation)*glm::dvec3(0,0,1); |
1140 | 0 | geometry->m_position=IWORKPosition(pos[0],pos[1]); |
1141 | 0 | glm::dvec3 dim=get(m_transformation)*glm::dvec3(get(m_size).m_width,get(m_size).m_height,0); |
1142 | 0 | geometry->m_naturalSize=geometry->m_size=IWORKSize(dim[0],dim[1]); |
1143 | 0 | getCollector().collectGeometry(geometry); |
1144 | 0 | } |
1145 | 0 | IWORKPathPtr_t path=makeRoundedRectanglePath(/*m_size ? get(m_size) : */IWORKSize(1,1), 0); |
1146 | 0 | getCollector().collectBezier(path); |
1147 | 0 | if (bool(getState().m_currentText) && !getState().m_currentText->empty()) |
1148 | 0 | getCollector().collectText(getState().m_currentText); |
1149 | 0 | getState().m_currentText.reset(); |
1150 | 0 | getCollector().collectShape(); |
1151 | |
|
1152 | 0 | getCollector().endLevel(); |
1153 | 0 | } |
1154 | 0 | } |
1155 | | } |
1156 | | |
1157 | | namespace |
1158 | | { |
1159 | | |
1160 | | class PluginDataElement : public KEY1XMLElementContextBase |
1161 | | { |
1162 | | public: |
1163 | | PluginDataElement(KEY1ParserState &state, boost::optional<IWORKSize> &size, bool prototype); |
1164 | | |
1165 | | protected: |
1166 | | void attribute(int name, const char *value) override; |
1167 | | void startOfElement() override; |
1168 | | IWORKXMLContextPtr_t element(int name) override; |
1169 | | void endOfElement() override; |
1170 | | |
1171 | | private: |
1172 | | bool m_prototype; |
1173 | | boost::optional<IWORKSize> &m_size; |
1174 | | }; |
1175 | | |
1176 | | PluginDataElement::PluginDataElement(KEY1ParserState &state, boost::optional<IWORKSize> &size, bool prototype) |
1177 | 0 | : KEY1XMLElementContextBase(state) |
1178 | 0 | , m_prototype(prototype) |
1179 | 0 | , m_size(size) |
1180 | 0 | { |
1181 | 0 | } |
1182 | | |
1183 | | #ifndef DEBUG |
1184 | | void PluginDataElement::attribute(const int name, const char *const) |
1185 | | #else |
1186 | | void PluginDataElement::attribute(const int name, const char *const value) |
1187 | | #endif |
1188 | 0 | { |
1189 | 0 | switch (name) |
1190 | 0 | { |
1191 | 0 | default: |
1192 | 0 | ETONYEK_DEBUG_MSG(("PluginDataElement::attribute[KEY1Parser.cpp]: unknown attribute with value=%s\n", value)); |
1193 | 0 | } |
1194 | 0 | } |
1195 | | |
1196 | | void PluginDataElement::startOfElement() |
1197 | 0 | { |
1198 | 0 | getState().pushIsPrototype(m_prototype); |
1199 | 0 | } |
1200 | | |
1201 | | IWORKXMLContextPtr_t PluginDataElement::element(const int name) |
1202 | 0 | { |
1203 | 0 | switch (name) |
1204 | 0 | { |
1205 | 0 | case +KEY1Token::array | KEY1Token::NS_URI_KEY : // with list of number |
1206 | 0 | case +KEY1Token::chart_prototype | KEY1Token::NS_URI_KEY : |
1207 | 0 | case +KEY1Token::color | KEY1Token::NS_URI_KEY : |
1208 | 0 | case +KEY1Token::content | KEY1Token::NS_URI_KEY : |
1209 | 0 | case +KEY1Token::dict | KEY1Token::NS_URI_KEY : // with child size, rect, ... |
1210 | 0 | case +KEY1Token::dash_style | KEY1Token::NS_URI_KEY : |
1211 | 0 | case +KEY1Token::fill_style | KEY1Token::NS_URI_KEY : |
1212 | 0 | case +KEY1Token::number | KEY1Token::NS_URI_KEY : |
1213 | 0 | case +KEY1Token::reference | KEY1Token::NS_URI_KEY : // style reference |
1214 | 0 | case +KEY1Token::string | KEY1Token::NS_URI_KEY : // with value dictionary, root |
1215 | 0 | break; |
1216 | 0 | case +KEY1Token::table | KEY1Token::NS_URI_KEY : |
1217 | 0 | return std::make_shared<KEY1TableElement>(getState(), m_size); |
1218 | 0 | default: |
1219 | 0 | ETONYEK_DEBUG_MSG(("PluginDataElement::element[KEY1Parser.cpp]: unknown element\n")); |
1220 | 0 | } |
1221 | 0 | return IWORKXMLContextPtr_t(); |
1222 | 0 | } |
1223 | | |
1224 | | void PluginDataElement::endOfElement() |
1225 | 0 | { |
1226 | 0 | getState().popIsPrototype(); |
1227 | 0 | } |
1228 | | |
1229 | | } |
1230 | | |
1231 | | namespace |
1232 | | { |
1233 | | |
1234 | | class PluginElement : public BasicShapeElement |
1235 | | { |
1236 | | public: |
1237 | | explicit PluginElement(KEY1ParserState &state); |
1238 | | |
1239 | | protected: |
1240 | | void attribute(int name, const char *value) override; |
1241 | | IWORKXMLContextPtr_t element(int name) override; |
1242 | | void endOfElement() override; |
1243 | | |
1244 | | private: |
1245 | | boost::optional<std::string> m_key; |
1246 | | boost::optional<glm::dmat3> m_transformation; |
1247 | | boost::optional<IWORKSize> m_size; |
1248 | | }; |
1249 | | |
1250 | | PluginElement::PluginElement(KEY1ParserState &state) |
1251 | 0 | : BasicShapeElement(state) |
1252 | 0 | , m_key() |
1253 | 0 | , m_transformation() |
1254 | 0 | , m_size() |
1255 | 0 | { |
1256 | 0 | } |
1257 | | |
1258 | | void PluginElement::attribute(const int name, const char *const value) |
1259 | 0 | { |
1260 | 0 | switch (name) |
1261 | 0 | { |
1262 | 0 | case KEY1Token::key : |
1263 | 0 | m_key = value; |
1264 | 0 | break; |
1265 | 0 | case KEY1Token::transformation : |
1266 | 0 | m_transformation=KEY1StringConverter<glm::dmat3>::convert(value); |
1267 | 0 | break; |
1268 | 0 | default : |
1269 | 0 | BasicShapeElement::attribute(name,value); |
1270 | 0 | break; |
1271 | 0 | } |
1272 | 0 | } |
1273 | | |
1274 | | IWORKXMLContextPtr_t PluginElement::element(const int name) |
1275 | 0 | { |
1276 | 0 | switch (name) |
1277 | 0 | { |
1278 | 0 | case +KEY1Token::plugin_data | KEY1Token::NS_URI_KEY : |
1279 | 0 | return std::make_shared<PluginDataElement>(getState(), m_size, false); |
1280 | 0 | case +KEY1Token::prototype_data | KEY1Token::NS_URI_KEY : |
1281 | 0 | return std::make_shared<PluginDataElement>(getState(), m_size, true); |
1282 | 0 | default : |
1283 | 0 | return BasicShapeElement::element(name); |
1284 | 0 | } |
1285 | 0 | } |
1286 | | |
1287 | | void PluginElement::endOfElement() |
1288 | 0 | { |
1289 | 0 | if (!isCollector()) |
1290 | 0 | return; |
1291 | 0 | IWORKStylePtr_t style=getStyle(); |
1292 | | // CHANGEME: check the plugin-data has created a table, if so, send it |
1293 | 0 | if (getState().m_currentTable) |
1294 | 0 | { |
1295 | 0 | getCollector().setGraphicStyle(style); |
1296 | 0 | if (m_transformation && m_size) |
1297 | 0 | { |
1298 | 0 | IWORKGeometryPtr_t geometry(new IWORKGeometry); |
1299 | 0 | glm::dvec3 pos=get(m_transformation)*glm::dvec3(0,0,1); |
1300 | 0 | geometry->m_position=IWORKPosition(pos[0],pos[1]); |
1301 | 0 | glm::dvec3 dim=get(m_transformation)*glm::dvec3(get(m_size).m_width,get(m_size).m_height,0); |
1302 | 0 | geometry->m_naturalSize=geometry->m_size=IWORKSize(dim[0],dim[1]); |
1303 | 0 | getCollector().collectGeometry(geometry); |
1304 | 0 | } |
1305 | 0 | getCollector().collectTable(getState().m_currentTable); |
1306 | 0 | getState().m_currentTable.reset(); |
1307 | 0 | } |
1308 | 0 | } |
1309 | | |
1310 | | } |
1311 | | |
1312 | | namespace |
1313 | | { |
1314 | | |
1315 | | class GroupElement : public BasicShapeElement |
1316 | | { |
1317 | | public: |
1318 | | explicit GroupElement(KEY1ParserState &state); |
1319 | | |
1320 | | protected: |
1321 | | void attribute(int name, const char *value) override; |
1322 | | IWORKXMLContextPtr_t element(int name) override; |
1323 | | |
1324 | | private: |
1325 | | boost::optional<glm::dmat3> m_transformation; |
1326 | | }; |
1327 | | |
1328 | | GroupElement::GroupElement(KEY1ParserState &state) |
1329 | 0 | : BasicShapeElement(state) |
1330 | 0 | , m_transformation() |
1331 | 0 | { |
1332 | 0 | } |
1333 | | |
1334 | | void GroupElement::attribute(const int name, const char *const value) |
1335 | 0 | { |
1336 | 0 | switch (name) |
1337 | 0 | { |
1338 | 0 | case KEY1Token::transformation : |
1339 | 0 | m_transformation=KEY1StringConverter<glm::dmat3>::convert(value); |
1340 | 0 | break; |
1341 | 0 | default : |
1342 | 0 | BasicShapeElement::attribute(name,value); |
1343 | 0 | break; |
1344 | 0 | } |
1345 | 0 | } |
1346 | | |
1347 | | IWORKXMLContextPtr_t GroupElement::element(const int name) |
1348 | 0 | { |
1349 | 0 | switch (name) |
1350 | 0 | { |
1351 | 0 | case +KEY1Token::g | KEY1Token::NS_URI_KEY : |
1352 | 0 | return std::make_shared<GroupElement>(getState()); |
1353 | 0 | case +KEY1Token::image | KEY1Token::NS_URI_KEY : |
1354 | 0 | return std::make_shared<ImageElement>(getState()); |
1355 | 0 | case +KEY1Token::line | KEY1Token::NS_URI_KEY : |
1356 | 0 | return std::make_shared<LineElement>(getState()); |
1357 | 0 | case +KEY1Token::page_number | KEY1Token::NS_URI_KEY : |
1358 | 0 | return std::make_shared<PageNumberElement>(getState()); |
1359 | 0 | case +KEY1Token::plugin | KEY1Token::NS_URI_KEY : |
1360 | 0 | return std::make_shared<PluginElement>(getState()); |
1361 | 0 | case +KEY1Token::shape | KEY1Token::NS_URI_KEY : |
1362 | 0 | return std::make_shared<ShapeElement>(getState()); |
1363 | 0 | case +KEY1Token::textbox | KEY1Token::NS_URI_KEY : |
1364 | 0 | return std::make_shared<TextboxElement>(getState()); |
1365 | 0 | default : |
1366 | 0 | return BasicShapeElement::element(name); |
1367 | 0 | } |
1368 | 0 | } |
1369 | | |
1370 | | } |
1371 | | |
1372 | | namespace |
1373 | | { |
1374 | | |
1375 | | class DrawablesElement : public KEY1XMLElementContextBase |
1376 | | { |
1377 | | public: |
1378 | | explicit DrawablesElement(KEY1ParserState &state, bool prototype); |
1379 | | |
1380 | | private: |
1381 | | void startOfElement() override; |
1382 | | IWORKXMLContextPtr_t element(int name) override; |
1383 | | void endOfElement() override; |
1384 | | |
1385 | | private: |
1386 | | bool m_prototype; |
1387 | | }; |
1388 | | |
1389 | | DrawablesElement::DrawablesElement(KEY1ParserState &state, bool prototype) |
1390 | 0 | : KEY1XMLElementContextBase(state) |
1391 | 0 | , m_prototype(prototype) |
1392 | 0 | { |
1393 | 0 | } |
1394 | | |
1395 | | void DrawablesElement::startOfElement() |
1396 | 0 | { |
1397 | 0 | getState().pushIsPrototype(m_prototype); |
1398 | 0 | if (isCollector()) |
1399 | 0 | getCollector().startLevel(); |
1400 | 0 | } |
1401 | | |
1402 | | IWORKXMLContextPtr_t DrawablesElement::element(const int name) |
1403 | 0 | { |
1404 | 0 | switch (name) |
1405 | 0 | { |
1406 | 0 | case +KEY1Token::body | KEY1Token::NS_URI_KEY : |
1407 | 0 | return std::make_shared<BodyElement>(getState()); |
1408 | 0 | case +KEY1Token::g | KEY1Token::NS_URI_KEY : |
1409 | 0 | return std::make_shared<GroupElement>(getState()); |
1410 | 0 | case +KEY1Token::image | KEY1Token::NS_URI_KEY : |
1411 | 0 | return std::make_shared<ImageElement>(getState()); |
1412 | 0 | case +KEY1Token::line | KEY1Token::NS_URI_KEY : |
1413 | 0 | return std::make_shared<LineElement>(getState()); |
1414 | 0 | case +KEY1Token::page_number | KEY1Token::NS_URI_KEY : |
1415 | 0 | return std::make_shared<PageNumberElement>(getState()); |
1416 | 0 | case +KEY1Token::plugin | KEY1Token::NS_URI_KEY : |
1417 | 0 | return std::make_shared<PluginElement>(getState()); |
1418 | 0 | case +KEY1Token::shape | KEY1Token::NS_URI_KEY : |
1419 | 0 | return std::make_shared<ShapeElement>(getState()); |
1420 | 0 | case +KEY1Token::textbox | KEY1Token::NS_URI_KEY : |
1421 | 0 | return std::make_shared<TextboxElement>(getState()); |
1422 | 0 | case +KEY1Token::title | KEY1Token::NS_URI_KEY : |
1423 | 0 | return std::make_shared<TitleElement>(getState()); |
1424 | 0 | default : |
1425 | 0 | ETONYEK_DEBUG_MSG(("DrawablesElement::element[KEY1Parser.cpp]: unknown element\n")); |
1426 | 0 | break; |
1427 | 0 | } |
1428 | | |
1429 | 0 | return IWORKXMLContextPtr_t(); |
1430 | 0 | } |
1431 | | |
1432 | | void DrawablesElement::endOfElement() |
1433 | 0 | { |
1434 | 0 | if (isCollector()) |
1435 | 0 | getCollector().endLevel(); |
1436 | 0 | getState().popIsPrototype(); |
1437 | 0 | } |
1438 | | |
1439 | | } |
1440 | | |
1441 | | namespace |
1442 | | { |
1443 | | |
1444 | | class PluginsElement : public KEY1XMLElementContextBase |
1445 | | { |
1446 | | public: |
1447 | | explicit PluginsElement(KEY1ParserState &state, bool prototype); |
1448 | | |
1449 | | private: |
1450 | | void startOfElement() override; |
1451 | | IWORKXMLContextPtr_t element(int name) override; |
1452 | | void endOfElement() override; |
1453 | | |
1454 | | private: |
1455 | | bool m_prototype; |
1456 | | }; |
1457 | | |
1458 | | PluginsElement::PluginsElement(KEY1ParserState &state, bool prototype) |
1459 | 0 | : KEY1XMLElementContextBase(state) |
1460 | 0 | , m_prototype(prototype) |
1461 | 0 | { |
1462 | 0 | } |
1463 | | |
1464 | | void PluginsElement::startOfElement() |
1465 | 0 | { |
1466 | 0 | getState().pushIsPrototype(m_prototype); |
1467 | 0 | } |
1468 | | |
1469 | | IWORKXMLContextPtr_t PluginsElement::element(const int name) |
1470 | 0 | { |
1471 | 0 | switch (name) |
1472 | 0 | { |
1473 | 0 | case +KEY1Token::prototype_plugin | KEY1Token::NS_URI_KEY : |
1474 | 0 | return std::make_shared<PluginElement>(getState()); |
1475 | 0 | default : |
1476 | 0 | ETONYEK_DEBUG_MSG(("PluginsElement::element[KEY1Parser.cpp]: unknown element\n")); |
1477 | 0 | break; |
1478 | 0 | } |
1479 | | |
1480 | 0 | return IWORKXMLContextPtr_t(); |
1481 | 0 | } |
1482 | | |
1483 | | void PluginsElement::endOfElement() |
1484 | 0 | { |
1485 | 0 | getState().popIsPrototype(); |
1486 | 0 | } |
1487 | | } |
1488 | | |
1489 | | namespace |
1490 | | { |
1491 | | |
1492 | | class SlideElement : public KEY1XMLElementContextBase |
1493 | | { |
1494 | | public: |
1495 | | explicit SlideElement(KEY1ParserState &state, bool isMasterSlide); |
1496 | | |
1497 | | private: |
1498 | | void attribute(int name, const char *value) override; |
1499 | | void startOfElement() override; |
1500 | | IWORKXMLContextPtr_t element(int name) override; |
1501 | | void endOfElement() override; |
1502 | | |
1503 | | private: |
1504 | | bool m_isMasterSlide; |
1505 | | optional<ID_t> m_styleRef; |
1506 | | optional<ID_t> m_masterRef; |
1507 | | |
1508 | | boost::optional<std::string> m_name; // master name |
1509 | | boost::optional<IWORKFill> m_background; |
1510 | | |
1511 | | // we need to record the layer as the main style are not read |
1512 | | std::shared_ptr<IWORKRecorder> m_recorder; |
1513 | | boost::optional<std::string> m_notes; |
1514 | | }; |
1515 | | |
1516 | | SlideElement::SlideElement(KEY1ParserState &state, bool isMasterSlide) |
1517 | 0 | : KEY1XMLElementContextBase(state) |
1518 | 0 | , m_isMasterSlide(isMasterSlide) |
1519 | 0 | , m_styleRef() |
1520 | 0 | , m_masterRef() |
1521 | 0 | , m_name() |
1522 | 0 | , m_background() |
1523 | 0 | , m_recorder() |
1524 | 0 | , m_notes() |
1525 | 0 | { |
1526 | 0 | } |
1527 | | |
1528 | | |
1529 | | void SlideElement::attribute(int name, const char *value) |
1530 | 0 | { |
1531 | 0 | switch (name) |
1532 | 0 | { |
1533 | 0 | case KEY1Token::name : |
1534 | 0 | m_name=value; |
1535 | 0 | break; |
1536 | 0 | case KEY1Token::id : |
1537 | 0 | setId(value); |
1538 | 0 | break; |
1539 | 0 | case KEY1Token::master_slide_id : |
1540 | 0 | m_masterRef=value; |
1541 | 0 | break; |
1542 | 0 | case KEY1Token::floating_content : // when exist with value=true, probably meaning has floating content |
1543 | 0 | break; |
1544 | 0 | default : |
1545 | 0 | ETONYEK_DEBUG_MSG(("SlideElement::attribute[KEY1Parser.cpp]: unknown attribute\n")); |
1546 | 0 | break; |
1547 | 0 | } |
1548 | 0 | } |
1549 | | |
1550 | | void SlideElement::startOfElement() |
1551 | 0 | { |
1552 | 0 | getState().pushIsMasterSlide(m_isMasterSlide); |
1553 | 0 | getState().getDictionary().pushStylesContext(); |
1554 | 0 | if (isCollector()) |
1555 | 0 | { |
1556 | 0 | getCollector().startPage(); |
1557 | 0 | getCollector().startLayer(); |
1558 | 0 | m_recorder = std::make_shared<IWORKRecorder>(); |
1559 | 0 | getCollector().setRecorder(m_recorder); |
1560 | 0 | } |
1561 | 0 | } |
1562 | | |
1563 | | IWORKXMLContextPtr_t SlideElement::element(const int name) |
1564 | 0 | { |
1565 | 0 | switch (name) |
1566 | 0 | { |
1567 | 0 | case +KEY1Token::bullets | KEY1Token::NS_URI_KEY : |
1568 | 0 | return std::make_shared<BulletsElement>(getState(), false); |
1569 | 0 | case +KEY1Token::drawables | KEY1Token::NS_URI_KEY : |
1570 | 0 | return std::make_shared<DrawablesElement>(getState(), false); |
1571 | 0 | case +KEY1Token::guides | KEY1Token::NS_URI_KEY : // list of guide, safe to ignore? |
1572 | 0 | break; |
1573 | 0 | case +KEY1Token::notes | KEY1Token::NS_URI_KEY : |
1574 | 0 | return std::make_shared<CDATAElement>(getState(), m_notes); |
1575 | 0 | case +KEY1Token::prototype_bullets | KEY1Token::NS_URI_KEY : |
1576 | 0 | return std::make_shared<BulletsElement>(getState(), true); |
1577 | 0 | case +KEY1Token::prototype_drawables | KEY1Token::NS_URI_KEY : |
1578 | 0 | return std::make_shared<DrawablesElement>(getState(), true); |
1579 | 0 | case +KEY1Token::prototype_plugins | KEY1Token::NS_URI_KEY : |
1580 | 0 | return std::make_shared<PluginsElement>(getState(), true); |
1581 | 0 | case +KEY1Token::background_fill_style | KEY1Token::NS_URI_KEY : |
1582 | 0 | return std::make_shared<KEY1FillElement>(getState(), m_background); |
1583 | 0 | case +KEY1Token::transition_style | KEY1Token::NS_URI_KEY : |
1584 | 0 | return std::make_shared<TransitionStyleElement>(getState()); |
1585 | 0 | case +KEY1Token::thumbnails | KEY1Token::NS_URI_KEY : // ok to ignore |
1586 | 0 | break; |
1587 | 0 | default : |
1588 | 0 | ETONYEK_DEBUG_MSG(("SlideElement::element[KEY1Parser.cpp]: unknown element\n")); |
1589 | 0 | break; |
1590 | 0 | } |
1591 | | |
1592 | 0 | return IWORKXMLContextPtr_t(); |
1593 | 0 | } |
1594 | | |
1595 | | void SlideElement::endOfElement() |
1596 | 0 | { |
1597 | 0 | getState().getDictionary().linkStylesContext(m_masterRef); |
1598 | 0 | if (m_isMasterSlide && getId()) getState().getDictionary().collectStylesContext(get(getId())); |
1599 | 0 | if (isCollector()) |
1600 | 0 | { |
1601 | 0 | if (m_background) |
1602 | 0 | { |
1603 | 0 | IWORKPropertyMap props; |
1604 | 0 | props.put<property::Fill>(get(m_background)); |
1605 | 0 | IWORKStylePtr_t style(new IWORKStyle(props, boost::none, boost::none)); |
1606 | |
|
1607 | 0 | getCollector().setSlideStyle(style); |
1608 | 0 | } |
1609 | 0 | if (!m_isMasterSlide) |
1610 | 0 | { |
1611 | 0 | for (int i=0; i<2; ++i) |
1612 | 0 | { |
1613 | 0 | KEYPlaceholderPtr_t placeholder=i==0 ? getState().getDictionary().getTitlePlaceholder() : |
1614 | 0 | getState().getDictionary().getBodyPlaceholder(); |
1615 | 0 | if (!placeholder || (placeholder->m_visible && !get(placeholder->m_visible))) |
1616 | 0 | continue; |
1617 | 0 | getCollector().insertTextPlaceholder(placeholder); |
1618 | 0 | } |
1619 | 0 | } |
1620 | 0 | const KEYLayerPtr_t layer(getCollector().collectLayer()); |
1621 | 0 | getCollector().endLayer(); |
1622 | 0 | if (bool(layer)) |
1623 | 0 | getCollector().insertLayer(layer); |
1624 | 0 | if (m_notes) |
1625 | 0 | { |
1626 | 0 | assert(!getState().m_currentText); |
1627 | 0 | getState().m_currentText = getCollector().createText(getState().m_langManager); |
1628 | 0 | getState().m_currentText->insertText(get(m_notes).c_str()); |
1629 | 0 | getCollector().collectText(getState().m_currentText); |
1630 | 0 | getState().m_currentText.reset(); |
1631 | 0 | getCollector().collectNote(); |
1632 | 0 | } |
1633 | 0 | KEYSlidePtr_t slide=getCollector().collectSlide(); |
1634 | 0 | getCollector().endPage(); |
1635 | 0 | if (!slide) |
1636 | 0 | return; |
1637 | 0 | slide->m_name=m_name; |
1638 | 0 | if (m_masterRef && m_isMasterSlide) |
1639 | 0 | { |
1640 | 0 | ETONYEK_DEBUG_MSG(("SlideElement::endOfElement[KEY1Parser.cpp]: find a master slide with masterRef\n")); |
1641 | 0 | } |
1642 | 0 | else if (m_masterRef) |
1643 | 0 | { |
1644 | 0 | const KEYSlideMap_t::const_iterator it = getState().getDictionary().m_masterSlides.find(get(m_masterRef)); |
1645 | 0 | if (it != getState().getDictionary().m_masterSlides.end()) |
1646 | 0 | slide->m_masterSlide=it->second; |
1647 | 0 | else |
1648 | 0 | { |
1649 | 0 | ETONYEK_DEBUG_MSG(("SlideElement::endOfElement[KEY1Parser.cpp]: unknown master %s\n", get(m_masterRef).c_str())); |
1650 | 0 | } |
1651 | 0 | } |
1652 | 0 | if (!m_isMasterSlide) |
1653 | 0 | getState().getDictionary().m_slides.push_back(slide); |
1654 | 0 | else if (getId()) |
1655 | 0 | getState().getDictionary().m_masterSlides[get(getId())]=slide; |
1656 | 0 | else |
1657 | 0 | { |
1658 | 0 | ETONYEK_DEBUG_MSG(("SlideElement::endOfElement[KEY1Parser.cpp]: can not find a master id\n")); |
1659 | 0 | } |
1660 | 0 | } |
1661 | 0 | getState().getDictionary().popStylesContext(); |
1662 | 0 | getState().popIsMasterSlide(); |
1663 | 0 | } |
1664 | | |
1665 | | } |
1666 | | |
1667 | | namespace |
1668 | | { |
1669 | | |
1670 | | class SlideListElement : public KEY1XMLElementContextBase |
1671 | | { |
1672 | | public: |
1673 | | explicit SlideListElement(KEY1ParserState &state); |
1674 | | |
1675 | | private: |
1676 | | void startOfElement() override; |
1677 | | IWORKXMLContextPtr_t element(int name) override; |
1678 | | void endOfElement() override; |
1679 | | }; |
1680 | | |
1681 | | SlideListElement::SlideListElement(KEY1ParserState &state) |
1682 | 0 | : KEY1XMLElementContextBase(state) |
1683 | 0 | { |
1684 | 0 | } |
1685 | | |
1686 | | void SlideListElement::startOfElement() |
1687 | 0 | { |
1688 | 0 | if (isCollector()) |
1689 | 0 | getCollector().startSlides(); |
1690 | 0 | } |
1691 | | |
1692 | | IWORKXMLContextPtr_t SlideListElement::element(const int name) |
1693 | 0 | { |
1694 | 0 | switch (name) |
1695 | 0 | { |
1696 | 0 | case +KEY1Token::slide | KEY1Token::NS_URI_KEY : |
1697 | 0 | return std::make_shared<SlideElement>(getState(), false); |
1698 | 0 | default : |
1699 | 0 | ETONYEK_DEBUG_MSG(("SlideListElement::element[KEY1Parser.cpp]: unexpected element\n")); |
1700 | 0 | break; |
1701 | 0 | } |
1702 | | |
1703 | 0 | return IWORKXMLContextPtr_t(); |
1704 | 0 | } |
1705 | | |
1706 | | void SlideListElement::endOfElement() |
1707 | 0 | { |
1708 | 0 | if (isCollector()) |
1709 | 0 | getCollector().endSlides(); |
1710 | 0 | } |
1711 | | |
1712 | | } |
1713 | | |
1714 | | namespace |
1715 | | { |
1716 | | |
1717 | | class MasterSlidesElement : public KEY1XMLElementContextBase |
1718 | | { |
1719 | | public: |
1720 | | explicit MasterSlidesElement(KEY1ParserState &state); |
1721 | | |
1722 | | private: |
1723 | | void startOfElement() override; |
1724 | | IWORKXMLContextPtr_t element(int name) override; |
1725 | | void endOfElement() override; |
1726 | | }; |
1727 | | |
1728 | | MasterSlidesElement::MasterSlidesElement(KEY1ParserState &state) |
1729 | 0 | : KEY1XMLElementContextBase(state) |
1730 | 0 | { |
1731 | 0 | } |
1732 | | |
1733 | | void MasterSlidesElement::startOfElement() |
1734 | 0 | { |
1735 | 0 | if (isCollector()) |
1736 | 0 | getCollector().startSlides(); |
1737 | 0 | } |
1738 | | |
1739 | | IWORKXMLContextPtr_t MasterSlidesElement::element(const int name) |
1740 | 0 | { |
1741 | 0 | switch (name) |
1742 | 0 | { |
1743 | 0 | case +KEY1Token::master_slide | KEY1Token::NS_URI_KEY : |
1744 | 0 | return std::make_shared<SlideElement>(getState(), true); |
1745 | 0 | default : |
1746 | 0 | ETONYEK_DEBUG_MSG(("MasterSlidesElement::element[KEY1Parser.cpp]: unexpected element\n")); |
1747 | 0 | break; |
1748 | 0 | } |
1749 | | |
1750 | 0 | return IWORKXMLContextPtr_t(); |
1751 | 0 | } |
1752 | | |
1753 | | void MasterSlidesElement::endOfElement() |
1754 | 0 | { |
1755 | 0 | if (isCollector()) |
1756 | 0 | getCollector().endSlides(); |
1757 | 0 | } |
1758 | | } |
1759 | | |
1760 | | namespace |
1761 | | { |
1762 | | class ThemeElement : public KEY1XMLElementContextBase |
1763 | | { |
1764 | | public: |
1765 | | explicit ThemeElement(KEY1ParserState &state); |
1766 | | |
1767 | | private: |
1768 | | void attribute(int name, const char *value) override; |
1769 | | IWORKXMLContextPtr_t element(int name) override; |
1770 | | |
1771 | | private: |
1772 | | boost::optional<std::string> m_description; |
1773 | | }; |
1774 | | |
1775 | | ThemeElement::ThemeElement(KEY1ParserState &state) |
1776 | 0 | : KEY1XMLElementContextBase(state) |
1777 | 0 | , m_description() |
1778 | 0 | { |
1779 | 0 | } |
1780 | | |
1781 | | void ThemeElement::attribute(int name, const char *value) |
1782 | 0 | { |
1783 | 0 | switch (name) |
1784 | 0 | { |
1785 | 0 | case KEY1Token::slide_size : |
1786 | 0 | { |
1787 | 0 | boost::optional<IWORKSize> size=KEY1StringConverter<IWORKSize>::convert(value); |
1788 | 0 | if (size && isCollector()) |
1789 | 0 | getCollector().collectPresentationSize(get(size)); |
1790 | 0 | break; |
1791 | 0 | } |
1792 | 0 | default : |
1793 | 0 | ETONYEK_DEBUG_MSG(("ThemeElement::attribute[KEY1Parser.cpp]: unexpected attribute\n")); |
1794 | 0 | break; |
1795 | 0 | } |
1796 | 0 | } |
1797 | | |
1798 | | IWORKXMLContextPtr_t ThemeElement::element(const int name) |
1799 | 0 | { |
1800 | 0 | switch (name) |
1801 | 0 | { |
1802 | 0 | case +KEY1Token::description | KEY1Token::NS_URI_KEY : |
1803 | 0 | return std::make_shared<CDATAElement>(getState(), m_description); |
1804 | 0 | case +KEY1Token::prototype_drawables | KEY1Token::NS_URI_KEY : |
1805 | 0 | return std::make_shared<DrawablesElement>(getState(), true); |
1806 | 0 | case +KEY1Token::prototype_plugins | KEY1Token::NS_URI_KEY : |
1807 | 0 | return std::make_shared<PluginsElement>(getState(), true); |
1808 | 0 | case +KEY1Token::master_slides | KEY1Token::NS_URI_KEY : |
1809 | 0 | return std::make_shared<MasterSlidesElement>(getState()); |
1810 | 0 | default : |
1811 | 0 | ETONYEK_DEBUG_MSG(("ThemeElement::element[KEY1Parser.cpp]: unexpected element\n")); |
1812 | 0 | break; |
1813 | 0 | } |
1814 | | |
1815 | 0 | return IWORKXMLContextPtr_t(); |
1816 | 0 | } |
1817 | | } |
1818 | | |
1819 | | namespace |
1820 | | { |
1821 | | class PresentationElement : public KEY1XMLElementContextBase |
1822 | | { |
1823 | | public: |
1824 | | explicit PresentationElement(KEY1ParserState &state); |
1825 | | |
1826 | | private: |
1827 | | void attribute(int name, const char *value) override; |
1828 | | void startOfElement() override; |
1829 | | IWORKXMLContextPtr_t element(int name) override; |
1830 | | void endOfElement() override; |
1831 | | |
1832 | | private: |
1833 | | }; |
1834 | | |
1835 | | PresentationElement::PresentationElement(KEY1ParserState &state) |
1836 | 0 | : KEY1XMLElementContextBase(state) |
1837 | 0 | { |
1838 | 0 | } |
1839 | | |
1840 | | void PresentationElement::startOfElement() |
1841 | 0 | { |
1842 | 0 | if (isCollector()) |
1843 | 0 | { |
1844 | 0 | getCollector().startDocument(); |
1845 | 0 | getCollector().setAccumulateTransformTo(false); |
1846 | 0 | } |
1847 | 0 | } |
1848 | | |
1849 | | void PresentationElement::attribute(const int name, const char *const /*value*/) |
1850 | 0 | { |
1851 | 0 | switch (name) |
1852 | 0 | { |
1853 | 0 | case KEY1Token::version : // find 36 |
1854 | 0 | break; |
1855 | 0 | default : |
1856 | | // normally only the namespace xmlns:plugin |
1857 | 0 | break; |
1858 | 0 | } |
1859 | 0 | } |
1860 | | |
1861 | | IWORKXMLContextPtr_t PresentationElement::element(const int name) |
1862 | 0 | { |
1863 | 0 | switch (name) |
1864 | 0 | { |
1865 | 0 | case +KEY1Token::metadata | KEY1Token::NS_URI_KEY : |
1866 | 0 | return std::make_shared<MetadataElement>(getState()); |
1867 | 0 | case +KEY1Token::theme | KEY1Token::NS_URI_KEY : |
1868 | 0 | return std::make_shared<ThemeElement>(getState()); |
1869 | 0 | case +KEY1Token::slide_list | KEY1Token::NS_URI_KEY : |
1870 | 0 | return std::make_shared<SlideListElement>(getState()); |
1871 | 0 | case +KEY1Token::ui_state | KEY1Token::NS_URI_KEY : // safe to ignore |
1872 | 0 | break; |
1873 | 0 | default : |
1874 | 0 | ETONYEK_DEBUG_MSG(("PresentationElement::element[KEY1Parser.cpp]: unexpected element\n")); |
1875 | 0 | break; |
1876 | 0 | } |
1877 | | |
1878 | 0 | return IWORKXMLContextPtr_t(); |
1879 | 0 | } |
1880 | | |
1881 | | void PresentationElement::endOfElement() |
1882 | 0 | { |
1883 | 0 | if (isCollector()) |
1884 | 0 | { |
1885 | 0 | getCollector().sendSlides(getState().getDictionary().m_slides); |
1886 | 0 | getCollector().endDocument(); |
1887 | 0 | } |
1888 | 0 | } |
1889 | | |
1890 | | } |
1891 | | |
1892 | | namespace |
1893 | | { |
1894 | | |
1895 | | class XMLDocument : public KEY1XMLElementContextBase |
1896 | | { |
1897 | | public: |
1898 | | explicit XMLDocument(KEY1ParserState &state); |
1899 | | |
1900 | | private: |
1901 | | IWORKXMLContextPtr_t element(int name) override; |
1902 | | }; |
1903 | | |
1904 | | XMLDocument::XMLDocument(KEY1ParserState &state) |
1905 | 0 | : KEY1XMLElementContextBase(state) |
1906 | 0 | { |
1907 | 0 | } |
1908 | | |
1909 | | IWORKXMLContextPtr_t XMLDocument::element(const int name) |
1910 | 0 | { |
1911 | 0 | switch (name) |
1912 | 0 | { |
1913 | 0 | case +KEY1Token::presentation | KEY1Token::NS_URI_KEY : |
1914 | 0 | return std::make_shared<PresentationElement>(m_state); |
1915 | 0 | default: |
1916 | 0 | ETONYEK_DEBUG_MSG(("XMLDocument::element[KEY1Parser.cpp]: unexpected element\n")); |
1917 | 0 | break; |
1918 | 0 | } |
1919 | | |
1920 | 0 | return IWORKXMLContextPtr_t(); |
1921 | 0 | } |
1922 | | |
1923 | | } |
1924 | | |
1925 | | namespace |
1926 | | { |
1927 | | |
1928 | | class DiscardContext : public KEY1XMLContextBase<IWORKDiscardContext> |
1929 | | { |
1930 | | public: |
1931 | | explicit DiscardContext(KEY1ParserState &state); |
1932 | | ~DiscardContext(); |
1933 | | |
1934 | | private: |
1935 | | IWORKXMLContextPtr_t element(int name) override; |
1936 | | |
1937 | | }; |
1938 | | |
1939 | | DiscardContext::DiscardContext(KEY1ParserState &state) |
1940 | 0 | : KEY1XMLContextBase<IWORKDiscardContext>(state) |
1941 | 0 | { |
1942 | 0 | } |
1943 | | |
1944 | | DiscardContext::~DiscardContext() |
1945 | | { |
1946 | | } |
1947 | | |
1948 | | IWORKXMLContextPtr_t DiscardContext::element(const int name) |
1949 | 0 | { |
1950 | 0 | return KEY1XMLContextBase<IWORKDiscardContext>::element(name); |
1951 | 0 | } |
1952 | | |
1953 | | } |
1954 | | |
1955 | | KEY1Parser::KEY1Parser(const RVNGInputStreamPtr_t &input, const RVNGInputStreamPtr_t &package, KEYCollector &collector, KEY1Dictionary &dict) |
1956 | 0 | : IWORKParser(input, package) |
1957 | 0 | , m_state(*this, collector, dict) |
1958 | 0 | , m_data() |
1959 | 0 | { |
1960 | |
|
1961 | 0 | } |
1962 | | |
1963 | | KEY1Parser::~KEY1Parser() |
1964 | 0 | { |
1965 | 0 | } |
1966 | | |
1967 | | IWORKXMLContextPtr_t KEY1Parser::createDocumentContext() |
1968 | 0 | { |
1969 | 0 | return std::make_shared<XMLDocument>(m_state); |
1970 | 0 | } |
1971 | | |
1972 | | IWORKXMLContextPtr_t KEY1Parser::createDiscardContext() |
1973 | 0 | { |
1974 | 0 | return std::make_shared<DiscardContext>(m_state); |
1975 | 0 | } |
1976 | | |
1977 | | const IWORKTokenizer &KEY1Parser::getTokenizer() const |
1978 | 0 | { |
1979 | 0 | return KEY1Token::getTokenizer(); |
1980 | 0 | } |
1981 | | |
1982 | | } |
1983 | | |
1984 | | /* vim:set shiftwidth=2 softtabstop=2 expandtab: */ |