* 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.
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)
#include <boost/lambda/lambda.hpp>
#include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/property_tree/ptree.hpp>
#include <tbb/atomic.h>
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);
+}
+
}}
#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>
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);
+
}}
{
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;
}
#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>
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(
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
#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_;
{
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)
{
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;
{
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);
}
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);
}
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());
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;
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
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:
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)
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)
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'"));
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);
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
//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);
}
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"));
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
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_;
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
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
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"));
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;
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)
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)
{
do
{
- unsigned char length = 0;
+ std::uint8_t length = 0;
//Get controlbyte
char controlByte = static_cast<char>(stream.read_byte());
{
//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;
}
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_; }
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_; }
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_; }
};
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;
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);
}
}
-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);
}
} //namespace psd
-} //namespace caspar
\ No newline at end of file
+} //namespace caspar
T blue = 0;
T alpha = 0;
- unsigned long to_uint32()
+ std::uint32_t to_uint32()
{
return (alpha << 24) + (red << 16) + (green << 8) + blue;
}
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
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
#include "descriptor.h"
#include <iostream>
+#include <common/log.h>
+
namespace caspar { namespace psd {
psd_document::psd_document()
void psd_document::read_image_resources()
{
- unsigned long section_length = input_.read_long();
+ auto section_length = input_.read_long();
if(section_length > 0)
{
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>());
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)
}
catch(std::exception&)
{
+ CASPAR_LOG_CURRENT_EXCEPTION();
input_.set_position(end_of_layers);
}
}
{
return layers_;
}
- unsigned long width() const
+ std::uint32_t width() const
{
return width_;
}
- unsigned long height() const
+ std::uint32_t height() const
{
return height_;
}
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_;
}
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_;
};
//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;
+ }
}
}
{
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"");
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())
{
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());
}
}
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];
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);
std::wstring bigendian_file_input_stream::read_unicode_string()
{
- unsigned long length = read_long();
+ auto length = read_long();
std::wstring result;
if(length > 0)
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()));
}
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
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();
#include "pdf_reader.h"
+#include <common/log.h>
+
#include <boost/spirit/home/qi.hpp>
+#include <boost/lexical_cast.hpp>
namespace qi = boost::spirit::qi;
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;
}
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();
}
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;
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
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
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)
{
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)