]> git.sesse.net Git - casparcg/blobdiff - modules/psd/descriptor.cpp
[scene_producer] Added possibility to CALL/CG PLAY/CG STOP/CG NEXT/CG INVOKE layers...
[casparcg] / modules / psd / descriptor.cpp
index 82dd18a26f1d7968e3c4cb49b9bcd759308d13a4..56a3ed6681976010241b6046ab7fbe5c8a24bfaa 100644 (file)
 
 #include "descriptor.h"
 #include "misc.h"
+#include "util/pdf_reader.h"
+
+#include <common/log.h>
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/locale.hpp>
+
+#include <memory>
 
 namespace caspar { namespace psd {
 
-bool descriptor::has_item(const std::wstring& key) const
-{
-       return (items_.find(key) != items_.end());
-}
+       class descriptor::context::scoped_holder
+       {
+               descriptor::context::ptr_type ctx_;
+       public:
+               explicit scoped_holder(const std::wstring& key, descriptor::context::ptr_type ctx) : ctx_(ctx) 
+               {
+                       Ptree *parent = ctx_->stack.back();
+                       Ptree *child = &parent->push_back(std::make_pair(key, Ptree()))->second;
+                       ctx_->stack.push_back(child);
+               }
+               ~scoped_holder()
+               {
+                       ctx_->stack.pop_back();
+               }
+       };
 
-const descriptor_item& descriptor::get_item(const std::wstring& key) const
+       descriptor::descriptor(const std::wstring& debug_name) : context_(std::make_shared<context>(debug_name))
+       {
+               context_->stack.push_back(&context_->root);
+       }
+       descriptor::descriptor(const std::wstring& key, context::ptr_type context) : context_(context)
+       {
+               Ptree *parent = context_->stack.back();
+               Ptree *child = &parent->push_back(std::make_pair(key, Ptree()))->second;
+               context->stack.push_back(child);
+       }
+       descriptor::~descriptor()
+       {
+               context_->stack.pop_back();
+       }
+
+void descriptor::populate(bigendian_file_input_stream& stream)
 {
-       return (*(items_.find(key))).second;
+       stream.read_unicode_string();
+       stream.read_id_string();
+       int element_count = stream.read_long();
+       for (int element_index = 0; element_index < element_count; ++element_index)
+       {
+               std::wstring key = stream.read_id_string();
+               read_value(key, stream);
+       }
+
+       if (context_->stack.size() == 1)
+               log::print_child(boost::log::trivial::trace, context_->debug_name + L": ", L"", context_->root);
 }
 
-bool descriptor::populate(BEFileInputStream& stream)
+void descriptor::read_value(const std::wstring& key, bigendian_file_input_stream& stream)
 {
-       bool result = true;
+       auto value_type = stream.read_long();
 
-       try
+       switch(value_type)
        {
-               stream.read_unicode_string();
-               stream.read_id_string();
-               unsigned long element_count = stream.read_long();
-               for(int element_index = 0; element_index < element_count; ++element_index)
+       case 'Objc': 
                {
-                       descriptor_item item;
+                       descriptor desc(key, context_);
+                       desc.populate(stream);
+               }
+               break;
 
-                       std::wstring key = stream.read_id_string();
-                       item.type = stream.read_long();
+       case 'doub': 
+               {
+                       context_->stack.back()->put(key, stream.read_double());
+               }
+               break;
 
-                       switch(item.type)
+       case 'TEXT':
+               {
+                       context_->stack.back()->put(key, stream.read_unicode_string());
+               }
+               break;
+
+       case 'enum':
+               {
+                       auto k = stream.read_id_string();
+                       auto v = stream.read_id_string();
+                       context_->stack.back()->put(k, v);
+               }
+               break;
+
+       case 'long':
+               {
+                       std::int32_t value = stream.read_long();
+                       context_->stack.back()->put(key, value);
+               }
+               break;
+
+       case 'bool': 
+               {
+                       context_->stack.back()->put(key, stream.read_byte());
+               }
+               break;
+
+       case 'VlLs': 
+               {
+                       context::scoped_holder list(key, context_);
+                       int count = stream.read_long();
+
+                       for (int i = 0; i < count; ++i)
                        {
-                       case 'obj ': break;
-                       case 'Objc': break;
-                       case 'VlLs': break;
-                       case 'doub': break;
-                       case 'UntF': break;
-
-                       case 'TEXT':
-                               {
-                                       item.text_text = stream.read_unicode_string();
-                               }
-                               break;
-                       case 'enum':
-                               {
-                                       item.enum_key = stream.read_id_string();
-                                       item.enum_val = stream.read_id_string();
-                               }
-                               break;
-
-                       case 'long':
-                               {
-                                       item.long_value = stream.read_long();
-                               }
-                               break;
-
-                       case 'bool': break;
-                       case 'GlbO': break;
-                       case 'type':
-                       case 'GlbC':
-                               break;
-                       case 'alis': break;
-
-                       case 'tdta':
-                               {
-                                       unsigned long rawdata_length = stream.read_long();
-                                       item.rawdata_data.resize(rawdata_length);
-                                       stream.read(item.rawdata_data.data(), rawdata_length);                          
-                               }
-                               break;
-
-                       default:
-                               //descriptor type not supported yet
-                               throw PSDFileFormatException();
+                               read_value(L"li", stream);
                        }
+               }
+               break;
 
-                       items_.insert(std::pair<std::wstring, descriptor_item>(key, item));
+       case 'tdta':
+               {
+                       auto rawdata_length = stream.read_long();
+                       std::vector<char> rawdata(rawdata_length);
+                       stream.read(rawdata.data(), rawdata_length);
+                       std::wstring data_str(rawdata.begin(), rawdata.end());
+                       context_->stack.back()->put(key, data_str);
                }
-       }
-       catch(std::exception& ex)
-       {
-               result = false;
-       }
+               break;
 
-       return result;
+       case 'UntF': 
+               {
+                       context::scoped_holder list(key, context_);
+                       auto unit = stream.read_long();
+                       std::string type(reinterpret_cast<char*>(&unit), 4);
+                       std::wstring wtype(type.rbegin(), type.rend());
+                       context_->stack.back()->put(wtype, stream.read_double());
+               }
+               break;
+
+       case 'obj ': 
+       case 'GlbO': 
+       case 'type':
+       case 'GlbC':
+       case 'alis':
+       default:
+               //descriptor type not supported yet
+               CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("descriptor type not supported yet"));
+       }
 }
 
 }      //namespace psd
-}      //namespace caspar
\ No newline at end of file
+}      //namespace caspar