1 // Copyright (c) 2018
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE
20 //
21 // @license: http://www.opensource.org/licenses/mit-license.php
22 // @author: see AUTHORS file
23 
24 #include <xlnt/drawing/spreadsheet_drawing.hpp>
25 #include <detail/constants.hpp>
26 
27 #include <detail/external/include_libstudxml.hpp>
28 
29 namespace {
30 // copy elements to the serializer provided and extract the embed ids
31 // from blip elements
copy_and_extract(xml::parser & p,xml::serializer & s)32 std::vector<std::string> copy_and_extract(xml::parser &p, xml::serializer &s)
33 {
34     std::vector<std::string> embed_ids;
35     int nest_level = 0;
36     while (nest_level > 0 || (p.peek() != xml::parser::event_type::end_element && p.peek() != xml::parser::event_type::eof))
37     {
38         switch (p.next())
39         {
40         case xml::parser::start_element: {
41             ++nest_level;
42             auto attribs = p.attribute_map();
43             auto current_ns = p.namespace_();
44             s.start_element(p.qname());
45             s.namespace_decl(current_ns, p.prefix());
46             if (p.qname().name() == "blip")
47             {
48                 embed_ids.push_back(attribs.at(xml::qname(xlnt::constants::ns("r"), "embed")).value);
49             }
50             p.peek();
51             auto new_ns = p.namespace_();
52             if (new_ns != current_ns)
53             {
54                 auto pref = p.prefix();
55                 s.namespace_decl(new_ns, pref);
56             }
57             for (auto &ele : attribs)
58             {
59                 s.attribute(ele.first, ele.second.value);
60             }
61             break;
62         }
63         case xml::parser::end_element: {
64             --nest_level;
65             s.end_element();
66             break;
67         }
68         case xml::parser::start_namespace_decl: {
69             s.namespace_decl(p.namespace_(), p.prefix());
70             break;
71         }
72         case xml::parser::end_namespace_decl: { // nothing required here
73             break;
74         }
75         case xml::parser::characters: {
76             s.characters(p.value());
77             break;
78         }
79         case xml::parser::eof:
80             return embed_ids;
81         case xml::parser::start_attribute:
82         case xml::parser::end_attribute:
83         default:
84             break;
85         }
86     }
87     return embed_ids;
88 }
89 } // namespace
90 
91 namespace xlnt {
92 namespace drawing {
93 
spreadsheet_drawing(xml::parser & parser)94 spreadsheet_drawing::spreadsheet_drawing(xml::parser &parser)
95 {
96     std::ostringstream serialization_stream;
97     xml::serializer s(serialization_stream, "", 0);
98     embed_ids_ = copy_and_extract(parser, s);
99     serialized_value_ = serialization_stream.str();
100 }
101 
102 // void spreadsheet_drawing::serialize(xml::serializer &serializer, const std::string& ns)
serialize(xml::serializer & serializer)103 void spreadsheet_drawing::serialize(xml::serializer &serializer)
104 {
105     std::istringstream ser(serialized_value_);
106     xml::parser p(ser, "", xml::parser::receive_default);
107     copy_and_extract(p, serializer);
108 }
109 
get_embed_ids()110 std::vector<std::string> spreadsheet_drawing::get_embed_ids()
111 {
112     return embed_ids_;
113 }
114 
115 } // namespace drawing
116 } // namespace xlnt
117