2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
4 * This file is part of CasparCG (www.casparcg.com).
6 * CasparCG is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * CasparCG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
19 * Author: Niklas P Andersson, niklas.p.andersson@svt.se
22 #include "pdf_reader.h"
24 #include <common/log.h>
27 #pragma warning(disable: 4459)
28 #pragma warning(disable: 4244)
29 #include <boost/spirit/home/qi.hpp>
32 #include <boost/lexical_cast.hpp>
36 namespace qi = boost::spirit::qi;
38 namespace caspar { namespace psd {
42 typedef boost::property_tree::wptree Ptree;
43 typedef std::vector<char>::iterator It;
49 std::vector<Ptree*> stack;
61 stack.push_back(&root);
64 Ptree* parent = stack.back();
65 Ptree* child = &parent->push_back(std::make_pair(name, Ptree()))->second;
66 stack.push_back(child);
74 BOOST_ASSERT(stack.size() >= 1);
78 std::string get_indent() const
80 return std::string(stack.size() * 4, ' ');
83 void set_name(const std::string& str)
85 name.assign(str.begin(), str.end());
86 CASPAR_LOG(debug) << get_indent() << name;
89 void add_char(std::uint8_t c)
91 char_flag = !char_flag;
94 value.push_back(c << 8);
96 value[value.size()-1] = value[value.size()-1] + c;
99 void set_value(bool val)
101 value = val ? L"true" : L"false";
104 void set_value(double val)
106 value = boost::lexical_cast<std::wstring>(val);
112 CASPAR_LOG(debug) << get_indent() << value;
114 stack.back()->push_back(std::make_pair(name, Ptree(value)));
119 template<typename Iterator>
120 struct pdf_grammar : qi::grammar<Iterator, qi::space_type>
122 qi::rule<Iterator, qi::space_type> root, object, member, value, list;
123 qi::rule<Iterator, qi::space_type> string;
124 qi::rule<Iterator, std::string()> name_str;
125 qi::rule<Iterator> escape;
126 qi::rule<Iterator> name;
128 mutable pdf_context context;
130 pdf_grammar() : pdf_grammar::base_type(root, "pdf-grammar")
136 = qi::lit("<<")[a_object_start(context)] >> *member >> qi::lit(">>")[a_object_end(context)];
139 = qi::char_('/') >> name >> value;
142 = name_str[a_name(context)];
145 = (qi::alpha >> *qi::alnum);
148 = qi::char_('[')[a_list_start(context)] >> *value >> qi::char_(']')[a_list_end(context)];
151 = qi::lexeme[qi::lit("(\xfe\xff") >>
153 (qi::char_('\0')[a_char(context)] >> escape)
154 | (qi::char_ - ')')[a_char(context)]
160 = ('\x5c' > qi::char_("nrtbf()\\")[a_char(context)]) | qi::char_[a_char(context)];
163 = qi::double_[a_numeral(context)] | list | object | string[a_string(context)] | qi::lit("true")[a_bool(true, context)] | qi::lit("false")[a_bool(false, context)];
166 struct a_object_start
169 explicit a_object_start(pdf_context& c) : c(c) {}
171 void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const
180 explicit a_object_end(pdf_context& c) : c(c) {}
182 void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const
190 explicit a_list_start(pdf_context& c) : c(c) {}
192 void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const
201 explicit a_list_end(pdf_context& c) : c(c) {}
203 void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const
212 explicit a_name(pdf_context& c) : c(c) {}
214 void operator()(std::string const& n, qi::unused_type, qi::unused_type) const
223 explicit a_numeral(pdf_context& c) : c(c) {}
225 void operator()(double const& n, qi::unused_type, qi::unused_type) const
234 explicit a_string(pdf_context& c) : c(c) {}
236 void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const
246 a_bool(bool val, pdf_context& c) : val(val), c(c) {}
248 void operator()(qi::unused_type, qi::unused_type, qi::unused_type) const
257 explicit a_char(pdf_context& c) : c(c) {}
259 void operator()(std::uint8_t n, qi::unused_type, qi::unused_type) const
266 bool read_pdf(boost::property_tree::wptree& tree, const std::string& s)
268 typedef std::string::const_iterator iterator_type;
270 pdf_grammar<iterator_type> g;
276 result = qi::phrase_parse(it, s.end(), g, qi::space);
278 tree.swap(g.context.root);
280 catch(std::exception&)
282 CASPAR_LOG_CURRENT_EXCEPTION();