]> git.sesse.net Git - casparcg/commitdiff
* Fixed bug where lexical_cast from double to string in Linux where swprintf was...
authorHelge Norberg <helge.norberg@svt.se>
Tue, 1 Sep 2015 20:55:27 +0000 (22:55 +0200)
committerHelge Norberg <helge.norberg@svt.se>
Tue, 1 Sep 2015 20:55:27 +0000 (22:55 +0200)
* Added better info() to scene_producer.
* PSD producer is now implemented with more portable cstdint types where applicable.
* Added a lot of trace logging to PSD producer to debug file format easier when developing.
* Fixed serious bug in PSD producer where the code was dependant on function arg evaluation order (unspecified in C++).
* Fixed bug in PSD producer where PSD 'long' types should be interpreted as signed 32 bit values instead of unsigned.
* Fixed bug in PSD producer where EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.FillColor.Values was not optional.

21 files changed:
CMakeLists.txt
common/log.cpp
common/log.h
core/producer/scene/scene_producer.cpp
core/producer/scene/xml_scene_producer.cpp
modules/psd/channel.h
modules/psd/descriptor.cpp
modules/psd/descriptor.h
modules/psd/image.h
modules/psd/layer.cpp
modules/psd/layer.h
modules/psd/misc.cpp
modules/psd/misc.h
modules/psd/psd_document.cpp
modules/psd/psd_document.h
modules/psd/psd_scene_producer.cpp
modules/psd/util/bigendian_file_input_stream.cpp
modules/psd/util/bigendian_file_input_stream.h
modules/psd/util/pdf_reader.cpp
modules/psd/util/pdf_reader.h
shell/main.cpp

index d17ab5e1d1e81995537101314c6c3abf80a9ac76..3683c49fc95900a3b8daa1a6d9b70afa31cf6add 100644 (file)
@@ -86,6 +86,7 @@ elseif (CMAKE_COMPILER_IS_GNUCXX)
        add_compile_options( -pthread )
        add_compile_options( -fPIC )
        add_compile_options( -fnon-call-exceptions ) # Allow signal handler to throw exception
+       add_definitions( -DBOOST_NO_SWPRINTF ) # swprintf on Linux seems to always use , as decimal point regardless of C-locale or C++-locale
 endif ()
 
 if (POLICY CMP0045)
index 0dd326cab49fce8bf3114d2f9168686dc237252c..4a3df32783605be6bc763467252af1ca4762fd41 100644 (file)
@@ -54,6 +54,7 @@
 #include <boost/lambda/lambda.hpp>
 #include <boost/bind.hpp>
 #include <boost/lexical_cast.hpp>
+#include <boost/property_tree/ptree.hpp>
 
 #include <tbb/atomic.h>
 
@@ -196,4 +197,21 @@ void set_log_level(const std::wstring& lvl)
                boost::log::core::get()->set_filter(boost::log::trivial::severity >= boost::log::trivial::fatal);
 }
 
+void print_child(
+               boost::log::trivial::severity_level level,
+               const std::wstring& indent,
+               const std::wstring& elem,
+               const boost::property_tree::wptree& tree)
+{
+       auto& data = tree.data();
+
+       if (!data.empty())
+               BOOST_LOG_STREAM_WITH_PARAMS(log::logger::get(), (boost::log::keywords::severity = level)) << indent << elem << L" " << replace_nonprintable_copy(data, L'?');
+       else if (tree.size() == 0)
+               BOOST_LOG_STREAM_WITH_PARAMS(log::logger::get(), (boost::log::keywords::severity = level)) << indent << elem;
+
+       for (auto& child : tree)
+               print_child(level, indent + (elem.empty() ? L"" : elem + L"."), child.first, child.second);
+}
+
 }}
index e9f57110fdfa93cbd9d4a7d0c088acf42c55a5c5..441837116dff836e5ef37be480059117344bc960 100644 (file)
@@ -28,6 +28,7 @@
 #include <boost/log/trivial.hpp>
 #include <boost/log/sources/global_logger_storage.hpp>
 #include <boost/exception/all.hpp>
+#include <boost/property_tree/ptree_fwd.hpp>
 
 #include <string>
 #include <locale>
@@ -84,5 +85,11 @@ BOOST_LOG_INLINE_GLOBAL_LOGGER_INIT(logger, caspar_logger)
        
 void set_log_level(const std::wstring& lvl);
 
+void print_child(
+               boost::log::trivial::severity_level level,
+               const std::wstring& indent,
+               const std::wstring& elem,
+               const boost::property_tree::wptree& tree);
+
 }}
 
index 2f4956063324e630f6b7a958ecd2efed89316e79..88d03e21e01a466e7a9b5c55f298b7fd972ac814 100644 (file)
@@ -503,6 +503,33 @@ struct scene_producer::impl
        {
                boost::property_tree::wptree info;
                info.add(L"type", L"scene");
+               info.add(L"frame-number", frame_number_.get());
+
+               for (auto& var : variables_)
+               {
+                       boost::property_tree::wptree variable_info;
+
+                       variable_info.add(L"name", var.first);
+                       variable_info.add(L"public", var.second->is_public());
+                       variable_info.add(L"value", var.second->to_string());
+
+                       info.add_child(L"variables.variable", variable_info);
+               }
+
+               for (auto& layer : layers_)
+               {
+                       boost::property_tree::wptree layer_info;
+
+                       layer_info.add(L"name", layer.name.get());
+                       layer_info.add_child(L"producer", layer.producer.get()->info());
+                       layer_info.add(L"x", layer.position.x.get());
+                       layer_info.add(L"y", layer.position.y.get());
+                       layer_info.add(L"width", layer.producer.get()->pixel_constraints().width.get());
+                       layer_info.add(L"height", layer.producer.get()->pixel_constraints().height.get());
+
+                       info.add_child(L"layers.layer", layer_info);
+               }
+
                return info;
        }
 
index df95d820d48e72000f875ff5c0cca6f147208be6..8ad65fa249deed79e8caa8f519b0b0afaa29067c 100644 (file)
@@ -30,6 +30,7 @@
 #include <boost/property_tree/xml_parser.hpp>
 
 #include <common/env.h>
+#include <common/os/filesystem.h>
 #include <core/producer/frame_producer.h>
 #include <core/help/help_repository.h>
 #include <core/help/help_sink.h>
@@ -81,11 +82,12 @@ spl::shared_ptr<core::frame_producer> create_xml_scene_producer(
        if (params.empty())
                return core::frame_producer::empty();
 
-       std::wstring filename = env::template_folder() + L"/" + params.at(0) + L".scene";
-       
-       if (!boost::filesystem::is_regular_file(boost::filesystem::path(filename)))
+       auto found = find_case_insensitive(env::template_folder() + L"/" + params.at(0) + L".scene");
+       if (!found)
                return core::frame_producer::empty();
 
+       std::wstring filename = *found;
+
        boost::property_tree::wptree root;
        boost::filesystem::wifstream file(filename);
        boost::property_tree::read_xml(
index 42926127363a25a1c74558f939d3efdc9b29852c..be12fa1739541cb153f9218fca23e06dc7058de0 100644 (file)
@@ -30,10 +30,10 @@ namespace caspar { namespace psd {
 struct channel
 {
 public:
-       channel(short id1, unsigned long len) : id(id1), data_length(len) {}
+       channel(std::int16_t id1, std::uint32_t len) : id(id1), data_length(len) {}
 
-       short id;
-       unsigned long data_length;
+       std::int16_t id;
+       std::uint32_t data_length;
 };
 
 }      //namespace psd
index a91f36c6be93db89739c65531ccd59887b141264..90e07a259fc9873ee475d8053022bde3141f7982 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 {
 
-       std::wstring debug_ptree(const boost::property_tree::wptree& tree)
-       {
-               std::wstringstream str;
-               boost::property_tree::xml_writer_settings<std::wstring> w(' ', 3);
-               boost::property_tree::write_xml(str, tree, w);
-               str.flush();
-               return str.str();
-       }
-
        class descriptor::context::scoped_holder
        {
                descriptor::context::ptr_type ctx_;
@@ -75,20 +68,20 @@ void descriptor::populate(bigendian_file_input_stream& stream)
 {
        stream.read_unicode_string();
        stream.read_id_string();
-       unsigned long element_count = stream.read_long();
-       for (unsigned long element_index = 0; element_index < element_count; ++element_index)
+       auto element_count = stream.read_long();
+       for (std::uint32_t 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)
-               CASPAR_LOG(trace) << context_->debug_name << L":\n\n" << debug_ptree(context_->root) << L"\n";
+               log::print_child(boost::log::trivial::trace, context_->debug_name + L": ", L"", context_->root);
 }
 
 void descriptor::read_value(const std::wstring& key, bigendian_file_input_stream& stream)
 {
-       unsigned int type = stream.read_long();
+       auto type = stream.read_long();
 
        switch(type)
        {
@@ -113,13 +106,16 @@ void descriptor::read_value(const std::wstring& key, bigendian_file_input_stream
 
        case 'enum':
                {
-                       context_->stack.back()->put(stream.read_id_string(), stream.read_id_string());
+                       auto k = stream.read_id_string();
+                       auto v = stream.read_id_string();
+                       context_->stack.back()->put(k, v);
                }
                break;
 
        case 'long':
                {
-                       context_->stack.back()->put(key, static_cast<long>(stream.read_long()));
+                       std::int32_t value = stream.read_long();
+                       context_->stack.back()->put(key, value);
                }
                break;
 
@@ -133,7 +129,7 @@ void descriptor::read_value(const std::wstring& key, bigendian_file_input_stream
                {
                        context::scoped_holder list(key, context_);
                        auto count = stream.read_long();
-                       for(unsigned long i = 0; i < count; ++i)
+                       for(std::uint32_t i = 0; i < count; ++i)
                        {
                                read_value(L"li", stream);
                        }
@@ -142,10 +138,9 @@ void descriptor::read_value(const std::wstring& key, bigendian_file_input_stream
 
        case 'tdta':
                {
-                       unsigned long rawdata_length = stream.read_long();
+                       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);
                }
@@ -154,7 +149,7 @@ void descriptor::read_value(const std::wstring& key, bigendian_file_input_stream
        case 'UntF': 
                {
                        context::scoped_holder list(key, context_);
-                       unsigned long unit = stream.read_long();
+                       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());
index c48963787f99edb6f6f9e95b588053496aa713bb..4f233398ba3cd1fb042699b9053fdd5194e8cd43 100644 (file)
 
 namespace caspar { namespace psd {
 
-       //struct descriptor_item
-       //{
-       //      unsigned long type;
-
-       //      std::wstring enum_key;
-       //      std::wstring enum_val;
-
-       //      std::wstring text_text;
-
-       //      unsigned long long_value;
-       //      
-       //      std::vector<char> rawdata_data;
-       //};
-
 class descriptor
 {
        typedef boost::property_tree::wptree Ptree;
index 02630d231c9931f53d499421e6184d576e2351bf..82b992b271c000cdcb53d0c5a8824e4d1dc1f0d7 100644 (file)
@@ -26,31 +26,31 @@ template<typename T>
 class image
 {
 public:
-       image(unsigned long width, unsigned long height, unsigned char channels) : width_(width), height_(height), channels_(channels) 
+       image(std::uint32_t width, std::uint32_t height, std::uint8_t channels) : width_(width), height_(height), channels_(channels)
        {
                data_.resize(width*height*channels);
        }
 
-       int width() const { return width_; }
-       int height() const { return height_; }
-       unsigned char channel_count() const { return channels_; }
+       std::uint32_t width() const { return width_; }
+       std::uint32_t height() const { return height_; }
+       std::uint8_t channel_count() const { return channels_; }
 
        T* data() { return data_.data(); }
 
 private:
        std::vector<T> data_;
-       unsigned long width_;
-       unsigned long height_;
-       unsigned char channels_;
+       std::uint32_t width_;
+       std::uint32_t height_;
+       std::uint8_t channels_;
 };
 
-typedef image<unsigned char> image8bit; 
-typedef image<unsigned short> image16bit; 
-typedef image<unsigned long> image32bit; 
+typedef image<std::uint8_t>            image8bit;
+typedef image<std::uint16_t>   image16bit;
+typedef image<std::uint32_t>   image32bit;
 
-typedef std::shared_ptr<image8bit>  image8bit_ptr;
-typedef std::shared_ptr<image16bit>  image16bit_ptr;
-typedef std::shared_ptr<image32bit>  image32bit_ptr;
+typedef std::shared_ptr<image8bit>     image8bit_ptr;
+typedef std::shared_ptr<image16bit>    image16bit_ptr;
+typedef std::shared_ptr<image32bit>    image32bit_ptr;
 
 }      //namespace psd
 }      //namespace caspar
index 20a2f9dc98e5814946d0ba312150bc563f0dd66c..b4107b841e17bb26a09fec597379132516606dbf 100644 (file)
@@ -38,7 +38,7 @@ namespace caspar { namespace psd {
 
 void layer::layer_mask_info::read_mask_data(bigendian_file_input_stream& stream)
 {
-       unsigned long length = stream.read_long();
+       auto length = stream.read_long();
        switch(length)
        {
        case 0:
@@ -85,25 +85,25 @@ private:
        std::vector<channel>                    channels_;
        blend_mode                                              blend_mode_;
        int                                                             link_group_id_;
-       unsigned char                                   opacity_;
-       unsigned short                                  sheet_color_;
+       std::uint8_t                                    opacity_;
+       std::uint16_t                                   sheet_color_;
        bool                                                    baseClipping_;
-       unsigned char                                   flags_;
-       int                                                             protection_flags_;
+       std::uint8_t                                    flags_;
+       std::uint32_t                                   protection_flags_;
        std::wstring                                    name_;
-       char                                                    masks_count_;
-       float                                                   text_scale_;
+       int                                                             masks_count_;
+       double                                                  text_scale_;
 
-       rect<long>                                              vector_mask_;
+       rect<std::int32_t>                              vector_mask_;
        layer::layer_mask_info                  mask_;
 
-       rect<long>                                              bitmap_rect_;
+       rect<std::int32_t>                              bitmap_rect_;
        image8bit_ptr                                   bitmap_;
 
        boost::property_tree::wptree    text_layer_info_;
        boost::property_tree::wptree    timeline_info_;
 
-       color<unsigned char>                    solid_color_;
+       color<std::uint8_t>                             solid_color_;
 
 public:
        void populate(bigendian_file_input_stream& stream, const psd_document& doc)
@@ -114,10 +114,10 @@ public:
                bitmap_rect_.size.width = stream.read_long() - bitmap_rect_.location.x;
 
                //Get info about the channels in the layer
-               unsigned short channelCount = stream.read_short();
+               auto channelCount = stream.read_short();
                for(int channelIndex = 0; channelIndex < channelCount; ++channelIndex)
                {
-                       short id = static_cast<short>(stream.read_short());
+                       auto id = static_cast<std::int16_t>(stream.read_short());
                        channel c(id, stream.read_long());
 
                        if(c.id < -1)
@@ -126,7 +126,7 @@ public:
                        channels_.push_back(c);
                }
 
-               unsigned long blendModeSignature = stream.read_long();
+               auto blendModeSignature = stream.read_long();
                if(blendModeSignature != '8BIM')
                        CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("blendModeSignature != '8BIM'"));
 
@@ -137,7 +137,7 @@ public:
 
                stream.discard_bytes(1);        //padding
 
-               unsigned long extras_size = stream.read_long();
+               auto extras_size = stream.read_long();
                auto position = stream.current_position();
                mask_.read_mask_data(stream);
                read_blending_ranges(stream);
@@ -238,15 +238,15 @@ public:
 
                descriptor solid_descriptor(L"solid_color");
                solid_descriptor.populate(stream);
-               solid_color_.red = static_cast<unsigned char>(solid_descriptor.items().get(L"Clr .Rd  ", 0.0) + 0.5);
-               solid_color_.green = static_cast<unsigned char>(solid_descriptor.items().get(L"Clr .Grn ", 0.0) + 0.5);
-               solid_color_.blue = static_cast<unsigned char>(solid_descriptor.items().get(L"Clr .Bl  ", 0.0) + 0.5);
+               solid_color_.red = static_cast<std::uint8_t>(solid_descriptor.items().get(L"Clr .Rd  ", 0.0) + 0.5);
+               solid_color_.green = static_cast<std::uint8_t>(solid_descriptor.items().get(L"Clr .Grn ", 0.0) + 0.5);
+               solid_color_.blue = static_cast<std::uint8_t>(solid_descriptor.items().get(L"Clr .Bl  ", 0.0) + 0.5);
                solid_color_.alpha = 255;
        }
 
-       void read_vector_mask(unsigned long length, bigendian_file_input_stream& stream, long doc_width, long doc_height)
+       void read_vector_mask(std::uint32_t length, bigendian_file_input_stream& stream, std::uint32_t doc_width, std::uint32_t doc_height)
        {
-               typedef std::pair<unsigned long, unsigned long> path_point;
+               typedef std::pair<std::uint32_t, std::uint32_t> path_point;
 
                stream.read_long(); // version
                stream.read_long(); // flags
@@ -293,16 +293,16 @@ public:
                //the path_points are given in fixed-point 8.24 as a ratio with regards to the width/height of the document. we need to divide by 16777215.0f to get the real ratio.
                float x_ratio = doc_width / 16777215.0f;
                float y_ratio = doc_height / 16777215.0f;
-               vector_mask_.location.x = static_cast<long>(knots[0].first * x_ratio +0.5f);                                                            //add .5 to get propper rounding when converting to integer
-               vector_mask_.location.y = static_cast<long>(knots[0].second * y_ratio +0.5f);                                                           //add .5 to get propper rounding when converting to integer
-               vector_mask_.size.width = static_cast<long>(knots[1].first * x_ratio +0.5f)     - vector_mask_.location.x;              //add .5 to get propper rounding when converting to integer
-               vector_mask_.size.height = static_cast<long>(knots[2].second * y_ratio +0.5f) - vector_mask_.location.y;        //add .5 to get propper rounding when converting to integer
+               vector_mask_.location.x = static_cast<std::int32_t>(knots[0].first * x_ratio +0.5f);                                                            //add .5 to get propper rounding when converting to integer
+               vector_mask_.location.y = static_cast<std::int32_t>(knots[0].second * y_ratio +0.5f);                                                           //add .5 to get propper rounding when converting to integer
+               vector_mask_.size.width = static_cast<std::int32_t>(knots[1].first * x_ratio +0.5f)     - vector_mask_.location.x;              //add .5 to get propper rounding when converting to integer
+               vector_mask_.size.height = static_cast<std::int32_t>(knots[2].second * y_ratio +0.5f) - vector_mask_.location.y;        //add .5 to get propper rounding when converting to integer
        }
 
        void read_metadata(bigendian_file_input_stream& stream, const psd_document& doc)
        {
                auto count = stream.read_long();
-               for(unsigned long index = 0; index < count; ++index)
+               for(int index = 0; index < count; ++index)
                        read_chunk(stream, doc, true);
        }
 
@@ -332,7 +332,7 @@ public:
                if(xx != yy || (xy != 0 && yx != 0))
                        CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("Rotation and non-uniform scaling of dynamic textfields is not supported yet"));
 
-               text_scale_ = static_cast<float>(xx);
+               text_scale_ = xx;
 
                if(stream.read_short() != 50)   //"text version" should be 50
                        CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("invalid text version"));
@@ -343,10 +343,10 @@ public:
                descriptor text_descriptor(L"text");
                text_descriptor.populate(stream);
                auto text_info = text_descriptor.items().get_optional<std::wstring>(L"EngineData");
-               if(text_info.is_initialized())
+               if(text_info)
                {
-                       std::string str(text_info.get().begin(), text_info.get().end());
-                       read_pdf(text_layer_info_, str);
+                       read_pdf(text_layer_info_, *text_info);
+                       log::print_child(boost::log::trivial::trace, L"", L"text_layer_info", text_layer_info_);
                }
 
                if(stream.read_short() != 1)    //"warp version" should be 1
@@ -382,7 +382,7 @@ public:
 
                bool has_transparency = has_channel(channel_type::transparency);
        
-               rect<long> clip_rect;
+               rect<std::int32_t> clip_rect;
                if(!bitmap_rect_.empty())
                {
                        clip_rect = bitmap_rect_;
@@ -403,9 +403,9 @@ public:
 
                for(auto it = channels_.begin(); it != channels_.end(); ++it)
                {
-                       psd::rect<long> src_rect;
+                       psd::rect<std::int32_t> src_rect;
                        image8bit_ptr target;
-                       unsigned char offset = 0;
+                       std::uint8_t offset = 0;
                        bool discard_channel = false;
 
                        //determine target bitmap and offset
@@ -414,7 +414,7 @@ public:
                        else if((*it).id >= -1) //BGRA-data
                        {
                                target = bitmap;
-                               offset = static_cast<unsigned char>(((*it).id >= 0) ? 2 - (*it).id : 3);
+                               offset = static_cast<std::uint8_t>(((*it).id >= 0) ? 2 - (*it).id : 3);
                                src_rect = bitmap_rect_;
                        }
                        else if(mask)   //mask
@@ -460,9 +460,9 @@ public:
                mask_.bitmap_ = mask;
        }
 
-       void read_raw_image_data(bigendian_file_input_stream& stream, unsigned long data_length, image8bit_ptr target, unsigned char offset)
+       void read_raw_image_data(bigendian_file_input_stream& stream, std::uint32_t data_length, image8bit_ptr target, std::uint8_t offset)
        {
-               unsigned long total_length = target->width() * target->height();
+               std::uint32_t total_length = target->width() * target->height();
                if(total_length != data_length)
                        CASPAR_THROW_EXCEPTION(psd_file_format_exception() << msg_info("total_length != data_length"));
 
@@ -473,12 +473,12 @@ public:
                        stream.read(reinterpret_cast<char*>(data + offset), total_length);
                else
                {
-                       for(unsigned long index=0; index < total_length; ++index)
-                               data[index*stride+offset] = stream.read_byte();
+                       for(std::uint32_t index = 0; index < total_length; ++index)
+                               data[index * stride + offset] = stream.read_byte();
                }
        }
 
-       void read_rle_image_data(bigendian_file_input_stream& stream, const rect<long>&src_rect, const rect<long>&clip_rect, image8bit_ptr target, unsigned char offset)
+       void read_rle_image_data(bigendian_file_input_stream& stream, const rect<std::int32_t>&src_rect, const rect<std::int32_t>&clip_rect, image8bit_ptr target, std::uint8_t offset)
        {
                auto width = src_rect.size.width;
                auto height = src_rect.size.height;
@@ -487,7 +487,7 @@ public:
                int offset_x = clip_rect.location.x - src_rect.location.x;
                int offset_y = clip_rect.location.y - src_rect.location.y;
 
-               std::vector<unsigned short> scanline_lengths;
+               std::vector<std::uint8_t> scanline_lengths;
                scanline_lengths.reserve(height);
 
                for (long scanlineIndex = 0; scanlineIndex < height; ++scanlineIndex)
@@ -495,7 +495,7 @@ public:
 
                auto target_data = target->data();
 
-               std::vector<unsigned char> line(width);
+               std::vector<std::uint8_t> line(width);
 
                for(long scanlineIndex=0; scanlineIndex < height; ++scanlineIndex)
                {
@@ -506,7 +506,7 @@ public:
 
                        do
                        {
-                               unsigned char length = 0;
+                               std::uint8_t length = 0;
 
                                //Get controlbyte
                                char controlByte = static_cast<char>(stream.read_byte());
@@ -514,15 +514,15 @@ public:
                                {
                                        //Read uncompressed string
                                        length = controlByte+1;
-                                       for(unsigned long index=0; index < length; ++index)
+                                       for(int index=0; index < length; ++index)
                                                line[colIndex+index] = stream.read_byte();
                                }
                                else if(controlByte > -128)
                                {
                                        //Repeat next byte
                                        length = -controlByte+1;
-                                       unsigned char value = stream.read_byte();
-                                       for(unsigned long index=0; index < length; ++index)
+                                       auto value = stream.read_byte();
+                                       for(int index=0; index < length; ++index)
                                                line[colIndex+index] = value;
                                }
 
@@ -546,13 +546,13 @@ void layer::populate(bigendian_file_input_stream& stream, const psd_document& do
 void layer::read_channel_data(bigendian_file_input_stream& stream) { impl_->read_channel_data(stream); }
 
 const std::wstring& layer::name() const { return impl_->name_; }
-unsigned char layer::opacity() const { return impl_->opacity_; }
-unsigned short layer::sheet_color() const { return impl_->sheet_color_; }
+std::uint8_t layer::opacity() const { return impl_->opacity_; }
+std::uint16_t layer::sheet_color() const { return impl_->sheet_color_; }
 
 bool layer::is_visible() { return (impl_->flags_ & 2) == 0; }  //the (PSD file-format) documentation is is saying the opposite but what the heck
 bool layer::is_position_protected() { return (impl_->protection_flags_& 4) == 4; }
 
-float layer::text_scale() const { return impl_->text_scale_; }
+double layer::text_scale() const { return impl_->text_scale_; }
 bool layer::is_text() const { return !impl_->text_layer_info_.empty(); }
 const boost::property_tree::wptree& layer::text_data() const { return impl_->text_layer_info_; }
 
@@ -560,9 +560,9 @@ bool layer::has_timeline() const { return !impl_->timeline_info_.empty(); }
 const boost::property_tree::wptree& layer::timeline_data() const { return impl_->timeline_info_; }
 
 bool layer::is_solid() const { return impl_->solid_color_.alpha != 0; }
-color<unsigned char> layer::solid_color() const { return impl_->solid_color_; }
+color<std::uint8_t> layer::solid_color() const { return impl_->solid_color_; }
 
-const point<long>& layer::location() const { return impl_->bitmap_rect_.location; }
+const point<std::int32_t>& layer::location() const { return impl_->bitmap_rect_.location; }
 const image8bit_ptr& layer::bitmap() const { return impl_->bitmap_; }
 
 int layer::link_group_id() const { return impl_->link_group_id_; }
index b6427c351eab400203290d1e321df5eed5d28487..d9cff17e68943db9b08b7deb495cff6e8c14638c 100644 (file)
@@ -50,18 +50,18 @@ public:
 
                void read_mask_data(bigendian_file_input_stream&);
 
-               image8bit_ptr   bitmap_;
-               unsigned char   default_value_;
-               unsigned char   flags_;
-               char                    mask_id_;
-               rect<long>              rect_;
+               image8bit_ptr           bitmap_;
+               std::uint8_t            default_value_;
+               std::uint8_t            flags_;
+               char                            mask_id_;
+               rect<std::int32_t>      rect_;
 
        public:
                bool enabled() const { return (flags_ & 2) == 0; }
                bool linked() const { return (flags_ & 1) == 0;  }
                bool inverted() const { return (flags_ & 4) == 4; }
 
-               const point<long>& location() const { return rect_.location; }
+               const point<std::int32_t>& location() const { return rect_.location; }
                const image8bit_ptr& bitmap() const { return bitmap_; }
        };
 
@@ -71,22 +71,22 @@ public:
        void read_channel_data(bigendian_file_input_stream&);
 
        const std::wstring& name() const;
-       unsigned char opacity() const;
-       unsigned short sheet_color() const;
+       std::uint8_t opacity() const;
+       std::uint16_t sheet_color() const;
        bool is_visible();
        bool is_position_protected();
 
-       float text_scale() const;
+       double text_scale() const;
        bool is_text() const;
        const boost::property_tree::wptree& text_data() const;
 
        bool is_solid() const;
-       color<unsigned char> solid_color() const;
+       color<std::uint8_t> solid_color() const;
 
        bool has_timeline() const;
        const boost::property_tree::wptree& timeline_data() const;
 
-       const point<long>& location() const;
+       const point<std::int32_t>& location() const;
        const image8bit_ptr& bitmap() const;
 
        int link_group_id() const;
index 8f83410db1611b2dbb83a7fb8f315dd09dfe4b35..54c3923368cb8615a78305c66a9f1c189c11abe5 100644 (file)
@@ -24,7 +24,7 @@
 
 namespace caspar { namespace psd {
 
-blend_mode int_to_blend_mode(unsigned long x)
+blend_mode int_to_blend_mode(std::uint32_t x)
 {
        blend_mode mode = static_cast<blend_mode>(x);
 
@@ -78,7 +78,7 @@ std::wstring blend_mode_to_string(blend_mode b)
        }
 }
 
-color_mode int_to_color_mode(unsigned short x)
+color_mode int_to_color_mode(std::uint16_t x)
 {
        color_mode mode = static_cast<color_mode>(x);
 
@@ -115,4 +115,4 @@ std::wstring color_mode_to_string(color_mode c)
 }
 
 }      //namespace psd
-}      //namespace caspar
\ No newline at end of file
+}      //namespace caspar
index f9456451d3f03e33cd8887d7eee7b1bb82ba6c29..cdcf7dbdc2ede495d8fdac92a87736a9ac00a042 100644 (file)
@@ -44,7 +44,7 @@ struct color
        T blue          = 0;
        T alpha         = 0;
 
-       unsigned long to_uint32()
+       std::uint32_t to_uint32()
        {
                return (alpha << 24) + (red << 16) + (green << 8) + blue;
        }
@@ -102,7 +102,7 @@ enum class blend_mode
        ColorBurn = 'idiv'
 };
 
-blend_mode int_to_blend_mode(unsigned long x);
+blend_mode int_to_blend_mode(std::uint32_t x);
 std::wstring blend_mode_to_string(blend_mode b);
 
 enum class color_mode
@@ -118,7 +118,7 @@ enum class color_mode
        Lab = 9
 };
 
-color_mode int_to_color_mode(unsigned short x);
+color_mode int_to_color_mode(std::uint16_t x);
 std::wstring color_mode_to_string(color_mode c);
 
 }      //namespace psd
index a69c75913072db98714386fe310ecf21c3e8dce8..909b2f567d6bec9f8b9d6b8e339bb3b3b8ee7d1f 100644 (file)
@@ -23,6 +23,8 @@
 #include "descriptor.h"
 #include <iostream>
 
+#include <common/log.h>
+
 namespace caspar { namespace psd {
 
 psd_document::psd_document()
@@ -68,7 +70,7 @@ void psd_document::read_color_mode()
 
 void psd_document::read_image_resources()
 {
-       unsigned long section_length = input_.read_long();
+       auto section_length = input_.read_long();
 
        if(section_length > 0)
        {
@@ -99,7 +101,7 @@ void psd_document::read_image_resources()
                                                        int layer_count = resource_length / 2;
                                                        for(int i = 0; i < layer_count; ++i)
                                                        {
-                                                               short id = input_.read_short();
+                                                               std::int16_t id = input_.read_short();
 
                                                                if(i == layers_.size())
                                                                        layers_.push_back(std::make_shared<layer>());
@@ -192,7 +194,7 @@ void psd_document::read_layers()
                        auto layer_info_length = input_.read_long();    //length of "Layer info" section
                        auto end_of_layers_info = input_.current_position() + layer_info_length;
 
-                       auto layers_count = std::abs(static_cast<short>(input_.read_short()));
+                       auto layers_count = std::abs(static_cast<std::int16_t>(input_.read_short()));
                        //std::clog << "Expecting " << layers_count << " layers" << std::endl;
 
                        for(int layer_index = 0; layer_index < layers_count; ++layer_index)
@@ -220,6 +222,7 @@ void psd_document::read_layers()
        }
        catch(std::exception&)
        {
+               CASPAR_LOG_CURRENT_EXCEPTION();
                input_.set_position(end_of_layers);
        }
 }
index bbdda4af706e9f46985be37f5d671d7bd4d4fb24..60104adec9f30cedc2aa02e8bc0f0027a3dca090 100644 (file)
@@ -41,11 +41,11 @@ public:
        {
                return layers_;
        }
-       unsigned long width() const
+       std::uint32_t width() const
        {
                return width_;
        }
-       unsigned long height() const
+       std::uint32_t height() const
        {
                return height_;
        }
@@ -55,11 +55,11 @@ public:
                return color_mode_;
        }
 
-       unsigned short color_depth() const
+       std::uint16_t color_depth() const
        {
                return depth_;
        }
-       unsigned short channels_count() const
+       std::uint16_t channels_count() const
        {
                return channels_;
        }
@@ -90,10 +90,10 @@ private:
 
        std::vector<layer_ptr>                  layers_;
 
-       unsigned short                                  channels_;
-       unsigned long                                   width_;
-       unsigned long                                   height_;
-       unsigned short                                  depth_;
+       std::uint16_t                                   channels_;
+       std::uint32_t                                   width_;
+       std::uint32_t                                   height_;
+       std::uint16_t                                   depth_;
        psd::color_mode                                 color_mode_;
        boost::property_tree::wptree    timeline_desc_;
 };
index 5a75cfa6e62ea70a4dbf8e8d7d93887329ad59f6..600de0e645da7d7ff9f012676bf838ffcc6f233c 100644 (file)
@@ -62,17 +62,21 @@ core::text::text_info get_text_info(const boost::property_tree::wptree& ptree)
        //result.kerning = ptree.get(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.Kerning", 0);
 
        int child_index = 0;
-       auto color_node = ptree.get_child(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.FillColor.Values");
-       for(auto it = color_node.begin(); it != color_node.end(); ++it, ++child_index)
+       auto color_node = ptree.get_child_optional(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.FillColor.Values");
+
+       if (color_node)
        {
-               auto& value_node = (*it).second;
-               float value = value_node.get_value(0.0f);
-               switch(child_index)
+               for(auto it = color_node->begin(); it != color_node->end(); ++it, ++child_index)
                {
-               case 0: result.color.a = value; break;
-               case 1: result.color.r = value; break;
-               case 2: result.color.g = value; break;
-               case 3: result.color.b = value; break;
+                       auto& value_node = (*it).second;
+                       float value = value_node.get_value(0.0f);
+                       switch(child_index)
+                       {
+                       case 0: result.color.a = value; break;
+                       case 1: result.color.r = value; break;
+                       case 2: result.color.g = value; break;
+                       case 3: result.color.b = value; break;
+                       }
                }
        }
 
@@ -369,7 +373,10 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const core::fram
        {
                if((*it)->is_visible())
                {
-                       if((*it)->is_text() && (*it)->sheet_color() == 4)
+                       bool is_text = (*it)->is_text();
+                       bool is_marked_as_dynamic = (*it)->sheet_color() == 4;
+                       std::wstring layer_name = (*it)->name();
+                       if(is_text && is_marked_as_dynamic)
                        {
                                std::wstring str = (*it)->text_data().get(L"EngineDict.Editor.Text", L"");
                        
@@ -392,11 +399,10 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const core::fram
                                if((*it)->link_group_id() != 0)
                                        link_constructor.add(&new_layer, (*it)->link_group_id(), (*it)->is_position_protected(), -adjustment_x, -adjustment_y);
 
-                               text_producers_by_layer_name.push_back(std::make_pair((*it)->name(), text_producer));
+                               text_producers_by_layer_name.push_back(std::make_pair(layer_name, text_producer));
                        }
                        else
                        {
-                               std::wstring layer_name = (*it)->name();
                                std::shared_ptr<core::frame_producer> layer_producer;
                                if((*it)->is_solid())
                                {
@@ -416,7 +422,9 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const core::fram
                                                pfd.planes.push_back(core::pixel_format_desc::plane((*it)->bitmap()->width(), (*it)->bitmap()->height(), 4));
 
                                                auto frame = dependencies.frame_factory->create_frame(it->get(), pfd);
-                                               memcpy(frame.image_data().data(), (*it)->bitmap()->data(), frame.image_data().size());
+                                               auto destination = frame.image_data().data();
+                                               auto source = (*it)->bitmap()->data();
+                                               memcpy(destination, source, frame.image_data().size());
 
                                                layer_producer = core::create_const_producer(core::draw_frame(std::move(frame)), (*it)->bitmap()->width(), (*it)->bitmap()->height());
                                        }
index ba1b40df99f0575b92ed33207f1d278684486e46..950a4bc1ea2cc59ca93c0377c38b39190863c2a3 100644 (file)
@@ -112,17 +112,17 @@ void bigendian_file_input_stream::discard_bytes(std::streamoff length)
 }
 void bigendian_file_input_stream::discard_to_next_word()
 {
-       unsigned const char padding = 2;
+       const std::uint8_t padding = 2;
        discard_bytes((padding - (current_position() % padding)) % padding);
 }
 
 void bigendian_file_input_stream::discard_to_next_dword()
 {
-       unsigned const char padding = 4;
+       const std::uint8_t padding = 4;
        discard_bytes((padding - (current_position() % padding)) % padding);
 }
 
-std::wstring bigendian_file_input_stream::read_pascal_string(unsigned char padding)
+std::wstring bigendian_file_input_stream::read_pascal_string(std::uint8_t padding)
 {
        char buffer[256];
 
@@ -131,7 +131,7 @@ std::wstring bigendian_file_input_stream::read_pascal_string(unsigned char paddi
        buffer[length] = 0;
        this->read(buffer, length);
 
-       unsigned char padded_bytes = (padding - ((length + 1) % padding)) % padding;
+       auto padded_bytes = (padding - ((length + 1) % padding)) % padding;
        this->discard_bytes(padded_bytes);
 
        return caspar::u16(buffer);
@@ -139,7 +139,7 @@ std::wstring bigendian_file_input_stream::read_pascal_string(unsigned char paddi
 
 std::wstring bigendian_file_input_stream::read_unicode_string()
 {
-       unsigned long length = read_long();
+       auto length = read_long();
        std::wstring result;
 
        if(length > 0)
@@ -147,7 +147,7 @@ std::wstring bigendian_file_input_stream::read_unicode_string()
                result.reserve(length);
 
                //can be optimized. Reads and swaps byte-order, one char at the time
-               for (unsigned long i = 0; i < length; ++i)
+               for (std::uint32_t i = 0; i < length; ++i)
                        result.append(1, static_cast<wchar_t>(read_short()));
        }
 
@@ -157,13 +157,13 @@ std::wstring bigendian_file_input_stream::read_unicode_string()
 std::wstring bigendian_file_input_stream::read_id_string()
 {
        std::string result;
-       unsigned long length = read_long();
+       auto length = read_long();
        
        if(length > 0)
        {
                result.reserve(length);
 
-               for (unsigned long i = 0; i < length; ++i)
+               for (std::uint32_t i = 0; i < length; ++i)
                        result.append(1, read_byte());
        }
        else
index be01f401e81242b4fe8a3bc8ffc1557b49e64f51..e602111e0f747dac9df124eaf42aefc07f4b61ac 100644 (file)
@@ -45,7 +45,7 @@ public:
        std::uint8_t read_byte();
        std::uint16_t read_short();
        std::uint32_t read_long();
-       std::wstring read_pascal_string(unsigned char padding = 1);
+       std::wstring read_pascal_string(std::uint8_t padding = 1);
        std::wstring read_unicode_string();
        std::wstring read_id_string();
        double read_double();
index 17c4ac15b2b0928b0e1bef741c12ae876ee36175..1343d42030b6a357be0cdf5ad1727ef7d0197cf1 100644 (file)
 
 #include "pdf_reader.h"
 
+#include <common/log.h>
+
 #include <boost/spirit/home/qi.hpp>
+#include <boost/lexical_cast.hpp>
 
 namespace qi = boost::spirit::qi;
 
@@ -65,12 +68,18 @@ struct pdf_context
                stack.pop_back();
        }
 
+       std::string get_indent() const
+       {
+               return std::string(stack.size() * 4, ' ');
+       }
+
        void set_name(const std::string& str)
        {
                name.assign(str.begin(), str.end());
+               CASPAR_LOG(trace) << get_indent() << name;
        }
 
-       void add_char(unsigned char c)
+       void add_char(std::uint8_t c)
        {
                char_flag = !char_flag;
 
@@ -87,12 +96,14 @@ struct pdf_context
        }
        void set_value(double val)
        {
-               value = std::to_wstring((long double)val);
+               value = boost::lexical_cast<std::wstring>(val);
                set_value();
        }
 
        void set_value()
        {
+               CASPAR_LOG(trace) << get_indent() << value;
+
                stack.back()->push_back(std::make_pair(name, Ptree(value)));
                clear_state();
        }
@@ -238,16 +249,16 @@ struct pdf_grammar : qi::grammar<Iterator, qi::space_type>
                pdf_context &c;
                explicit a_char(pdf_context& c) : c(c) {}
 
-               void operator()(unsigned char n, qi::unused_type, qi::unused_type) const
+               void operator()(std::uint8_t n, qi::unused_type, qi::unused_type) const
                {
                        c.add_char(n);
                }
        };
 };
 
-bool read_pdf(boost::property_tree::wptree& tree, const std::string& s)
+bool read_pdf(boost::property_tree::wptree& tree, const std::wstring& s)
 {
-       typedef std::string::const_iterator iterator_type;
+       typedef std::wstring::const_iterator iterator_type;
 
        pdf_grammar<iterator_type> g;
        bool result = false;
@@ -260,10 +271,12 @@ bool read_pdf(boost::property_tree::wptree& tree, const std::string& s)
                        tree.swap(g.context.root);
        }
        catch(std::exception&)
-       {}
+       {
+               CASPAR_LOG_CURRENT_EXCEPTION();
+       }
 
        return result;
 }
 
 }      //namespace psd
-}      //namespace caspar
\ No newline at end of file
+}      //namespace caspar
index ba86508518ea2dbe70deb7f1bb605019cf42ea6b..5c3cb68e9bea4b9385508d043be9dbd7afd8a686 100644 (file)
@@ -26,7 +26,7 @@
 
 namespace caspar { namespace psd { 
 
-bool read_pdf(boost::property_tree::wptree& tree, const std::string& s);
+bool read_pdf(boost::property_tree::wptree& tree, const std::wstring& s);
 
 }      //namespace psd
-}      //namespace caspar
\ No newline at end of file
+}      //namespace caspar
index d806e90a97007b57c8e23dd4ce64d346de5653ec..3fb48ba3f55a6e73f2fe44246768ba877d09caab 100644 (file)
@@ -89,18 +89,6 @@ void print_info()
        CASPAR_LOG(info) << system_product_name();
 }
 
-void print_child(const std::wstring& indent, const std::wstring& elem, const boost::property_tree::wptree& tree)
-{
-       auto data = tree.data();
-
-       if (data.empty())
-               CASPAR_LOG(info) << indent << elem;
-       else
-               CASPAR_LOG(info) << indent << elem << L" " << tree.data();
-
-       for (auto& child : tree)
-               print_child(indent + L"    ", child.first, child.second);
-}
 
 void print_system_info(const spl::shared_ptr<core::system_info_provider_repository>& repo)
 {
@@ -108,7 +96,7 @@ void print_system_info(const spl::shared_ptr<core::system_info_provider_reposito
        repo->fill_information(info);
 
        for (auto& elem : info.get_child(L"system"))
-               print_child(L"", elem.first, elem.second);
+               log::print_child(boost::log::trivial::info, L"", elem.first, elem.second);
 }
 
 void do_run(std::weak_ptr<caspar::IO::protocol_strategy<wchar_t>> amcp, std::promise<bool>& shutdown_server_now)