]> git.sesse.net Git - casparcg/commitdiff
Merge branch '2.1.0' of https://github.com/CasparCG/Server into 2.1.0
authorHelge Norberg <helge.norberg@svt.se>
Fri, 23 Aug 2013 20:10:28 +0000 (22:10 +0200)
committerHelge Norberg <helge.norberg@svt.se>
Fri, 23 Aug 2013 20:10:28 +0000 (22:10 +0200)
Conflicts:
core/core.vcxproj.filters

12 files changed:
core/core.vcxproj
core/core.vcxproj.filters
core/producer/text/text_producer.cpp
core/producer/text/text_producer.h
core/producer/text/utils/text_info.h [new file with mode: 0644]
core/producer/text/utils/texture_font.cpp
core/producer/text/utils/texture_font.h
modules/psd/layer.cpp
modules/psd/layer.h
modules/psd/misc.h
modules/psd/psd_scene_producer.cpp
test/psd-test/psd-test.cpp

index e58bf843291eb9d4ce50739f4d2fec513c543390..feeb25c42a873773db1e60bd4054c43b3792111e 100644 (file)
     <ClInclude Include="producer\text\utils\string_metrics.h" />\r
     <ClInclude Include="producer\text\utils\texture_atlas.h" />\r
     <ClInclude Include="producer\text\utils\texture_font.h" />\r
+    <ClInclude Include="producer\text\utils\text_info.h" />\r
     <ClInclude Include="producer\variable.h" />\r
     <ClInclude Include="video_channel.h" />\r
     <ClInclude Include="consumer\output.h" />\r
index 83dc27134915a221d06b1eab38e4eca32a6dc35a..788d617cfb4156bbac355b1855cc314c595a1c8e 100644 (file)
     </ClInclude>\r
     <ClInclude Include="producer\scene\expression_parser.h">\r
       <Filter>source\producer\scene</Filter>\r
+    <ClInclude Include="producer\text\utils\text_info.h">\r
+      <Filter>source\producer\text\utils</Filter>\r
     </ClInclude>\r
   </ItemGroup>\r
   <ItemGroup>\r
index 18669fc62c269ff4469eda661c9a9cb79ee44cfa..7389a48c266a6c7d322fca27d721265115a6b947 100644 (file)
@@ -118,10 +118,12 @@ namespace caspar { namespace core {
                                register_producer_factory(&create_text_producer);
                }
 
-               std::wstring find_font_file(const std::wstring& font_name)
+               text_info& find_font_file(text_info& info)
                {
+                       auto& font_name = info.font;
                        auto it = std::find_if(fonts.begin(), fonts.end(), font_comparer(font_name));
-                       return (it != fonts.end()) ? (*it).second : L"";
+                       info.font_file = (it != fonts.end()) ? (*it).second : L"";
+                       return info;
                }
        }
        
@@ -141,13 +143,13 @@ struct text_producer::impl
        text::texture_font font_;
 
 public:
-       explicit impl(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, const text::text_info& text_info, long parent_width, long parent_height, bool standalone) 
+       explicit impl(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, text::text_info& text_info, long parent_width, long parent_height, bool standalone) 
                : frame_factory_(frame_factory)
                , constraints_(parent_width, parent_height)
                , x_(x), y_(y), parent_width_(parent_width), parent_height_(parent_height)
                , standalone_(standalone)
                , atlas_(512,512,4)
-               , font_(atlas_, text::find_font_file(text_info.font), text_info.size, !standalone)
+               , font_(atlas_, text::find_font_file(text_info), !standalone)
        {
                //TODO: examine str to determine which unicode_blocks to load
                font_.load_glyphs(text::Basic_Latin, text_info.color);
@@ -271,7 +273,7 @@ public:
        }
 };
 
-text_producer::text_producer(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, const text::text_info& text_info, long parent_width, long parent_height, bool standalone)
+text_producer::text_producer(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, text::text_info& text_info, long parent_width, long parent_height, bool standalone)
        : impl_(new impl(frame_factory, x, y, str, text_info, parent_width, parent_height, standalone))
 {}
 
@@ -291,7 +293,7 @@ binding<std::wstring>& text_producer::text() { return impl_->text(); }
 const binding<int>& text_producer::current_bearing_y() const { return impl_->current_bearing_y(); }
 const binding<int>& text_producer::current_protrude_under_y() const { return impl_->current_protrude_under_y(); }
 
-spl::shared_ptr<text_producer> text_producer::create(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, const text::text_info& text_info, long parent_width, long parent_height, bool standalone)
+spl::shared_ptr<text_producer> text_producer::create(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, text::text_info& text_info, long parent_width, long parent_height, bool standalone)
 {
        return spl::make_shared<text_producer>(frame_factory, x, y, str, text_info, parent_width, parent_height, standalone);
 }
index 022e1be24582faf808d15bc27e266b1110ffbe89..d0a3f9c4dea414862e821f85614bdf6dbe70a1ed 100644 (file)
 
 #include "utils/color.h"
 #include "utils/string_metrics.h"
+#include "utils/text_info.h"
 
 namespace caspar { namespace core {
        namespace text 
        {
                void init();
-
-               struct text_info
-               {
-                       std::wstring font;
-                       float size;
-                       color<float> color;
-               };
        }
 
 class text_producer : public frame_producer_base
 {
 public:
-       text_producer(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, const text::text_info& text_info, long parent_width, long parent_height, bool standalone);
-       static spl::shared_ptr<text_producer> create(const spl::shared_ptr<class frame_factory>& frame_factory, int x, int y, const std::wstring& str, const text::text_info& text_info, long parent_width, long parent_height, bool standalone = false);
+       text_producer(const spl::shared_ptr<frame_factory>& frame_factory, int x, int y, const std::wstring& str, text::text_info& text_info, long parent_width, long parent_height, bool standalone);
+       static spl::shared_ptr<text_producer> create(const spl::shared_ptr<class frame_factory>& frame_factory, int x, int y, const std::wstring& str, text::text_info& text_info, long parent_width, long parent_height, bool standalone = false);
        
        draw_frame receive_impl() override;
        boost::unique_future<std::wstring> call(const std::vector<std::wstring>& param) override;
diff --git a/core/producer/text/utils/text_info.h b/core/producer/text/utils/text_info.h
new file mode 100644 (file)
index 0000000..bc1ade0
--- /dev/null
@@ -0,0 +1,19 @@
+#pragma once
+
+#include <string>
+#include "color.h"
+
+namespace caspar { namespace core { namespace text {
+
+       struct text_info
+       {
+               std::wstring font;
+               std::wstring font_file;
+
+               float size;
+               color<float> color;
+               int baseline_shift;
+               int tracking;
+       };
+
+}}}
\ No newline at end of file
index 5b264e6a37ec8463d053bf233c99da7b43f1c4df..6cd41263dca5be6c94493725cce30f34c7607a78 100644 (file)
@@ -44,11 +44,12 @@ private:
        FT_Face                 face_;
        texture_atlas   atlas_;
        float                   size_;
+       float                   tracking_;
        bool                    normalize_;
        std::map<int, glyph_info> glyphs_;
 
 public:
-       impl::impl(texture_atlas& atlas, const std::wstring& filename, float size, bool normalize_coordinates) : lib_(nullptr), face_(nullptr), atlas_(atlas), size_(size), normalize_(normalize_coordinates)
+       impl::impl(texture_atlas& atlas, const text_info& info, bool normalize_coordinates) : lib_(nullptr), face_(nullptr), atlas_(atlas), size_(info.size), tracking_(info.size*info.tracking/1000.0f), normalize_(normalize_coordinates)
        {
                try
                {
@@ -56,10 +57,10 @@ public:
                        err = FT_Init_FreeType(&lib_);
                        if(err) throw freetype_exception("Failed to initialize freetype");
 
-                       err = FT_New_Face(lib_, u8(filename).c_str(), 0, &face_);
+                       err = FT_New_Face(lib_, u8(info.font_file).c_str(), 0, &face_);
                        if(err) throw freetype_exception("Failed to load font");
 
-                       err = FT_Set_Char_Size(face_, (FT_F26Dot6)(size*64), 0, 72, 72);
+                       err = FT_Set_Char_Size(face_, static_cast<FT_F26Dot6>(size_*64), 0, 72, 72);
                        if(err) throw freetype_exception("Failed to set font size");
                }
                catch(std::exception& ex)
@@ -205,6 +206,7 @@ public:
                                        maxHeight = maxBearingY + maxProtrudeUnderY;
 
                                pos_x += face_->glyph->advance.x / 64.0f;
+                               pos_x += tracking_;
                                previous = glyph_index;
                        }
                        else
@@ -286,7 +288,7 @@ public:
        }
 }; 
 
-texture_font::texture_font(texture_atlas& atlas, const std::wstring& filename, float size, bool normalize_coordinates) : impl_(new impl(atlas, filename, size, normalize_coordinates)) {}
+texture_font::texture_font(texture_atlas& atlas, const text_info& info, bool normalize_coordinates) : impl_(new impl(atlas, info, normalize_coordinates)) {}
 void texture_font::load_glyphs(unicode_block range, const color<float>& col) { impl_->load_glyphs(range, col); }
 std::vector<float> texture_font::create_vertex_stream(const std::wstring& str, int x, int y, int parent_width, int parent_height, string_metrics* metrics) { return impl_->create_vertex_stream(str, x, y, parent_width, parent_height, metrics); }
 string_metrics texture_font::measure_string(const std::wstring& str) { return impl_->measure_string(str); }
index e6acf8d72172fab8ea27f85d29db56d18fdc8467..8e977d34f2e98d34d9ddb798cf19e10c3e20b0eb 100644 (file)
@@ -5,6 +5,7 @@
 #include <common/memory.h>
 
 #include "string_metrics.h"
+#include "text_info.h"
 
 namespace caspar { namespace core { namespace text {
 
@@ -18,7 +19,7 @@ class texture_font
        const texture_font& operator=(const texture_font&);
 
 public:
-       texture_font(texture_atlas&, const std::wstring& filename, float size, bool normalize_coordinates);
+       texture_font(texture_atlas&, const text_info&, bool normalize_coordinates);
        void load_glyphs(unicode_block block, const color<float>& col);
        std::vector<float> create_vertex_stream(const std::wstring& str, int x, int y, int parent_width, int parent_height, string_metrics* metrics);
        string_metrics measure_string(const std::wstring& str);
index 8369c5d0fa17e22a65416ec6a8cd75cb457ac877..40906e0ae2fb8475a2eb3a615bfe8e9aaeb22357 100644 (file)
@@ -22,6 +22,7 @@
 #include "layer.h"
 #include "doc.h"
 #include "descriptor.h"
+#include <common/log.h>
 #include "util\pdf_reader.h"
 
 #include <algorithm>
@@ -74,7 +75,7 @@ struct layer::impl
 {
        friend class layer;
 
-       impl() : blend_mode_(InvalidBlendMode), link_group_id_(0), opacity_(255), baseClipping_(false), flags_(0), protection_flags_(0), masks_count_(0)
+       impl() : blend_mode_(InvalidBlendMode), link_group_id_(0), opacity_(255), sheet_color_(0), baseClipping_(false), flags_(0), protection_flags_(0), masks_count_(0), text_scale_(1.0f)
        {}
 
 private:
@@ -82,11 +83,13 @@ private:
        blend_mode                                              blend_mode_;
        int                                                             link_group_id_;
        unsigned char                                   opacity_;
+       unsigned short                                  sheet_color_;
        bool                                                    baseClipping_;
        unsigned char                                   flags_;
        int                                                             protection_flags_;
        std::wstring                                    name_;
        char                                                    masks_count_;
+       float                                                   text_scale_;
 
        rect<long>                                              vector_mask_;
        layer::layer_mask_info                  mask_;
@@ -191,6 +194,10 @@ public:
                        case 'shmd':    //metadata
                                read_metadata(stream, doc);
                                break;
+
+                       case 'lclr':
+                               sheet_color_ = stream.read_short();
+                               break;
                                
                        case 'lyvr':    //layer version
                                break;
@@ -212,9 +219,10 @@ public:
                                break;
                        }
                }
-               catch(PSDFileFormatException&)
+               catch(PSDFileFormatException& ex)
                {
                        //ignore failed chunks silently
+                       CASPAR_LOG(warning) << ex.what();
                }
 
                stream.set_position(end_of_chunk);
@@ -227,7 +235,7 @@ public:
 
                descriptor solid_descriptor;
                if(!solid_descriptor.populate(stream))
-                       throw PSDFileFormatException();
+                       throw PSDFileFormatException("Failed to read solid color data");
                else
                {
                        solid_color_.red = static_cast<unsigned char>(solid_descriptor.items().get(L"Clr .Rd  ", 0.0) + 0.5);
@@ -326,16 +334,20 @@ public:
                double yy = stream.read_double();
                double tx = stream.read_double();
                double ty = stream.read_double();
+               if(xx != yy || (xy != 0 && yx != 0))
+                       throw PSDFileFormatException("Rotation and non-uniform scaling of dynamic textfields is not supported yet");
+
+               text_scale_ = static_cast<float>(xx);
 
                if(stream.read_short() != 50)   //"text version" should be 50
-                       throw PSDFileFormatException();
+                       throw PSDFileFormatException("invalid text version");
 
                if(stream.read_long() != 16)    //"descriptor version" should be 16
-                       throw PSDFileFormatException();
+                       throw PSDFileFormatException("Invalid descriptor version while reading text-data");
 
                descriptor text_descriptor;
                if(!text_descriptor.populate(stream))
-                       throw PSDFileFormatException();
+                       throw PSDFileFormatException("Failed to read text-info");
                else
                {
                        auto text_info = text_descriptor.items().get_optional<std::wstring>(L"EngineData");
@@ -347,16 +359,21 @@ public:
                }
 
                if(stream.read_short() != 1)    //"warp version" should be 1
-                       throw PSDFileFormatException();
+                       throw PSDFileFormatException("invalid warp version");
 
                if(stream.read_long() != 16)    //"descriptor version" should be 16
-                       throw PSDFileFormatException();
+                       throw PSDFileFormatException("Invalid descriptor version while reading text warp-data");
 
                descriptor warp_descriptor;
                if(!warp_descriptor.populate(stream))
-                       throw PSDFileFormatException();
+                       throw PSDFileFormatException("Failed to read text warp-data");
                else
-                       stream.discard_bytes(4*8);      //top, left, right, bottom
+               {
+                       double w_top = stream.read_double();
+                       double w_left = stream.read_double();
+                       double w_right = stream.read_double();
+                       double w_bottom = stream.read_double();
+               }
        }
 
        //TODO: implement
@@ -543,11 +560,12 @@ void layer::read_channel_data(BEFileInputStream& stream) { impl_->read_channel_d
 
 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_; }
 
 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_; }
 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_; }
 
index 5677e02ab5f1e88492d092f0892d7deab4eb8894..d094b679e2c950b38ec3a464d92cf4645a41c0f5 100644 (file)
@@ -74,9 +74,11 @@ public:
 
        const std::wstring& name() const;
        unsigned char opacity() const;
+       unsigned short sheet_color() const;
        bool is_visible();
        bool is_position_protected();
 
+       float text_scale() const;
        bool is_text() const;
        const boost::property_tree::wptree& text_data() const;
 
index 9651f6becc17e8cdfe31883fbbf188e03feea2c7..886c91bbed8bf11125ba418c0573a149dc9abc9b 100644 (file)
@@ -75,6 +75,11 @@ struct rect
 class PSDFileFormatException : public std::exception
 {
 public:
+       PSDFileFormatException() : std::exception()
+       {}
+       explicit PSDFileFormatException(const char* msg) : std::exception(msg)
+       {}
+
        virtual ~PSDFileFormatException()
        {}
        virtual const char *what() const
index e5fde8677a41dd8e0bd30e246686b2cd3eff6421..3e0a50e0dab666f3e3ac3f1561689e6da0cfefbb 100644 (file)
@@ -55,6 +55,10 @@ core::text::text_info get_text_info(const boost::property_tree::wptree& ptree)
        core::text::text_info result;
        int font_index = ptree.get(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.Font", 0);
        result.size = ptree.get(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.FontSize", 30.0f);
+       //result.leading = ptree.get(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.Leading", 0);
+       result.tracking = ptree.get(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.Tracking", 0);
+       result.baseline_shift = ptree.get(L"EngineDict.StyleRun.RunArray..StyleSheet.StyleSheetData.BaselineShift", 0);
+       //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");
@@ -308,11 +312,13 @@ spl::shared_ptr<core::frame_producer> create_psd_scene_producer(const spl::share
        {
                if((*it)->is_visible())
                {
-                       if((*it)->is_text())
+                       if((*it)->is_text() && (*it)->sheet_color() == 4)
                        {
                                std::wstring str = (*it)->text_data().get(L"EngineDict.Editor.Text", L"");
                        
                                core::text::text_info text_info(std::move(get_text_info((*it)->text_data())));
+                               text_info.size *= (*it)->text_scale();
+
                                auto text_producer = core::text_producer::create(frame_factory, 0, 0, str, text_info, doc.width(), doc.height());
                        
                                core::text::string_metrics metrics = text_producer->measure_string(str);
index e302f06a9322ea4b06b4d2d2a0d5f1f1887fd359..3888f88766f8ea0ad32e6f38639db2c911a78c7d 100644 (file)
@@ -46,8 +46,8 @@ int _tmain(int argc, _TCHAR* argv[])
                                if(layer->is_text())
                                {
                                        trace << L"                     <text value='" << (*it)->text_data().get(L"EngineDict.Editor.Text", L"") << L"' />" << std::endl;
-                                       //boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);
-                                       //boost::property_tree::write_xml(trace, (*it)->text_data(), w);
+                                       boost::property_tree::xml_writer_settings<wchar_t> w(' ', 3);
+                                       boost::property_tree::write_xml(trace, (*it)->text_data(), w);
                                }
                                if(layer->has_timeline())
                                {