Fix various SNAFUs with Font ID handling.
authorCarl Hetherington <cth@carlh.net>
Wed, 24 Jun 2015 14:05:19 +0000 (15:05 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 24 Jun 2015 14:05:19 +0000 (15:05 +0100)
12 files changed:
src/asset.cc
src/asset.h
src/dcp.cc
src/font_asset.cc
src/font_asset.h
src/interop_subtitle_asset.cc
src/interop_subtitle_asset.h
src/smpte_subtitle_asset.cc
src/subtitle_asset.cc
src/subtitle_asset.h
test/dcp_font_test.cc
tools/dcpdumpsub.cc

index 3d3978311465df43916321aa885f4dbae56114dc..6a15f21630fb0fac9b7ddb6ff82345efbc781a03 100644 (file)
@@ -49,6 +49,13 @@ Asset::Asset (boost::filesystem::path file)
 
 }
 
+Asset::Asset (string id, boost::filesystem::path file)
+       : Object (id)
+       , _file (file)
+{
+
+}
+
 void
 Asset::write_to_pkl (xmlpp::Node* node, Standard standard) const
 {
index 12fe265749c9f8859f06e6bbd872db1ee67a2599..f5b60bf7b3550df5ee608497856594ceea6346b7 100644 (file)
@@ -47,6 +47,7 @@ class Asset : public Object
 public:
        Asset ();
        Asset (boost::filesystem::path file);
+       Asset (std::string id, boost::filesystem::path file);
 
        virtual bool equals (
                boost::shared_ptr<const Asset> other,
index c1675401082c0e9feccdc620fb1cc9b05baca1e9..b710d61be559dace5de3a7aacd285f2b5dc50724 100644 (file)
@@ -176,7 +176,7 @@ DCP::read (bool keep_going, ReadErrors* errors)
                                        throw DCPReadError ("Unknown MXF essence type");
                        }
                } else if (boost::filesystem::extension (path) == ".ttf") {
-                       other_assets.push_back (shared_ptr<FontAsset> (new FontAsset (path)));
+                       other_assets.push_back (shared_ptr<FontAsset> (new FontAsset (i->first, path)));
                }
        }
 
index 8f8e4ff3ede7d999c112328863e53cfe5ffca87a..2cd03f27c50b673bb5150985dde5cfbc462cfb2a 100644 (file)
@@ -27,8 +27,8 @@ using std::string;
 
 using namespace dcp;
 
-FontAsset::FontAsset (boost::filesystem::path file)
-       : Asset (file)
+FontAsset::FontAsset (string id, boost::filesystem::path file)
+       : Asset (id, file)
 {
 
 }
index d099932251d661992fe54795a206bb0ed25f7a67..8abd6047283486420969f4eabc7c2b0625e10f56 100644 (file)
@@ -31,7 +31,7 @@ namespace dcp {
 class FontAsset : public Asset
 {
 public:
-       FontAsset (boost::filesystem::path file);
+       FontAsset (std::string id, boost::filesystem::path file);
 
 private:
        std::string pkl_type (Standard standard) const;
index ffa7d50b96695d3e258f04c26d24c9305431a6e4..a3850f0408b7b02137336b61449e8d86c16fdee6 100644 (file)
@@ -90,10 +90,10 @@ InteropSubtitleAsset::xml_as_string () const
 }
 
 void
-InteropSubtitleAsset::add_font (string id, boost::filesystem::path file)
+InteropSubtitleAsset::add_font (string load_id, boost::filesystem::path file)
 {
-       add_font_data (id, file);
-       _load_font_nodes.push_back (shared_ptr<InteropLoadFontNode> (new InteropLoadFontNode (id, file.leaf().string ())));
+       _fonts.push_back (Font (load_id, make_uuid(), file));
+       _load_font_nodes.push_back (shared_ptr<InteropLoadFontNode> (new InteropLoadFontNode (load_id, file.leaf().string ())));
 }
 
 bool
@@ -163,10 +163,13 @@ InteropSubtitleAsset::write (boost::filesystem::path p) const
                if (!f) {
                        throw FileError ("could not open font file for writing", file, errno);
                }
-               map<string, FileData>::const_iterator j = _fonts.find (i->id);
+               list<Font>::const_iterator j = _fonts.begin ();
+               while (j->load_id != i->id) {
+                       ++j;
+               }
                if (j != _fonts.end ()) {
-                       fwrite (j->second.data.get(), 1, j->second.size, f);
-                       j->second.file = file;
+                       fwrite (j->data.data.get(), 1, j->data.size, f);
+                       j->file = file;
                }
                fclose (f);
        }
@@ -183,7 +186,7 @@ InteropSubtitleAsset::resolve_fonts (list<shared_ptr<Object> > objects)
 
                BOOST_FOREACH (shared_ptr<InteropLoadFontNode> j, _load_font_nodes) {
                        if (j->uri == font->file().leaf().string ()) {
-                               add_font_data (j->id, font->file ());
+                               _fonts.push_back (Font (j->id, i->id(), font->file ()));
                        }
                }
        }
@@ -192,8 +195,8 @@ InteropSubtitleAsset::resolve_fonts (list<shared_ptr<Object> > objects)
 void
 InteropSubtitleAsset::add_font_assets (list<shared_ptr<Asset> >& assets)
 {
-       for (map<string, FileData>::const_iterator i = _fonts.begin(); i != _fonts.end(); ++i) {
-               DCP_ASSERT (i->second.file);
-               assets.push_back (shared_ptr<FontAsset> (new FontAsset (i->second.file.get ())));
+       BOOST_FOREACH (Font const & i, _fonts) {
+               DCP_ASSERT (i.file);
+               assets.push_back (shared_ptr<FontAsset> (new FontAsset (i.uuid, i.file.get ())));
        }
 }
index 41ed83b3d55503283bb232058545c05a023daa0b..8690d11c3b82205b41e83291c3327012e32d1d9b 100644 (file)
@@ -47,7 +47,7 @@ public:
 
        std::list<boost::shared_ptr<LoadFontNode> > load_font_nodes () const;
 
-       void add_font (std::string id, boost::filesystem::path file);
+       void add_font (std::string load_id, boost::filesystem::path file);
 
        Glib::ustring xml_as_string () const;
        void write (boost::filesystem::path path) const;
index 8ea68362116243a218b7a23a3ef0b4a8128bfdcb..8c0ce11115ff1612c012a345fa4a929160ae3892 100644 (file)
@@ -144,7 +144,7 @@ SMPTESubtitleAsset::SMPTESubtitleAsset (boost::filesystem::path file)
                        }
 
                        if (j != _load_font_nodes.end ()) {
-                               _fonts[(*j)->id] = FileData (data, buffer.Size ());
+                               _fonts.push_back (Font ((*j)->id, (*j)->urn, Data (data, buffer.Size ())));
                        }
                }
        }
@@ -217,7 +217,10 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
        descriptor.EncodingName = "UTF-8";
 
        BOOST_FOREACH (shared_ptr<dcp::SMPTELoadFontNode> i, _load_font_nodes) {
-               map<string, FileData>::const_iterator j = _fonts.find (i->id);
+               list<Font>::const_iterator j = _fonts.begin ();
+               while (j != _fonts.end() && j->load_id != i->id) {
+                       ++j;
+               }
                if (j != _fonts.end ()) {
                        ASDCP::TimedText::TimedTextResourceDescriptor res;
                        unsigned int c;
@@ -245,11 +248,14 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
        }
 
        BOOST_FOREACH (shared_ptr<dcp::SMPTELoadFontNode> i, _load_font_nodes) {
-               map<string, FileData>::const_iterator j = _fonts.find (i->id);
+               list<Font>::const_iterator j = _fonts.begin ();
+               while (j != _fonts.end() && j->load_id != i->id) {
+                       ++j;
+               }
                if (j != _fonts.end ()) {
                        ASDCP::TimedText::FrameBuffer buffer;
-                       buffer.SetData (j->second.data.get(), j->second.size);
-                       buffer.Size (j->second.size);
+                       buffer.SetData (j->data.data.get(), j->data.size);
+                       buffer.Size (j->data.size);
                        r = writer.WriteAncillaryResource (buffer);
                        if (ASDCP_FAILURE (r)) {
                                boost::throw_exception (MXFFileError ("could not write font to timed text resource", p.string(), r));
@@ -341,8 +347,9 @@ SMPTESubtitleAsset::equals (shared_ptr<const Asset> other_asset, EqualityOptions
 }
 
 void
-SMPTESubtitleAsset::add_font (string id, boost::filesystem::path file)
+SMPTESubtitleAsset::add_font (string load_id, boost::filesystem::path file)
 {
-       add_font_data (id, file);
-       _load_font_nodes.push_back (shared_ptr<SMPTELoadFontNode> (new SMPTELoadFontNode (id, make_uuid ())));
+       string const uuid = make_uuid ();
+       _fonts.push_back (Font (load_id, uuid, file));
+       _load_font_nodes.push_back (shared_ptr<SMPTELoadFontNode> (new SMPTELoadFontNode (load_id, uuid)));
 }
index 367c3455f2884488bf683a3c1ce5d2a581b25487..c0ffb75a5d4952637776f802b26922c7f01d56f5 100644 (file)
@@ -30,6 +30,7 @@
 #include <libxml++/nodes/element.h>
 #include <boost/algorithm/string.hpp>
 #include <boost/shared_array.hpp>
+#include <boost/foreach.hpp>
 #include <fstream>
 
 using std::string;
@@ -308,18 +309,12 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* root, int time_code_rate, strin
        }
 }
 
-void
-SubtitleAsset::add_font_data (string id, boost::filesystem::path file)
-{
-       _fonts[id] = FileData (file);
-}
-
 map<string, Data>
-SubtitleAsset::fonts () const
+SubtitleAsset::fonts_with_load_ids () const
 {
        map<string, Data> out;
-       for (map<string, FileData>::const_iterator i = _fonts.begin(); i != _fonts.end(); ++i) {
-               out[i->first] = i->second;
+       BOOST_FOREACH (Font const & i, _fonts) {
+               out[i.load_id] = i.data;
        }
        return out;
 }
index 31afecb338b781f2f04e30de45db6c4500d97ddd..51385b220e3aefc9273dbd707e812ec5af941bec 100644 (file)
@@ -70,7 +70,7 @@ public:
 
        void add (SubtitleString);
        virtual void add_font (std::string id, boost::filesystem::path file) = 0;
-       std::map<std::string, Data> fonts () const;
+       std::map<std::string, Data> fonts_with_load_ids () const;
 
        virtual void write (boost::filesystem::path) const = 0;
        virtual Glib::ustring xml_as_string () const = 0;
@@ -85,32 +85,34 @@ protected:
 
        void parse_subtitles (boost::shared_ptr<cxml::Document> xml, std::list<boost::shared_ptr<FontNode> > font_nodes);
        void subtitles_as_xml (xmlpp::Element* root, int time_code_rate, std::string xmlns) const;
-       void add_font_data (std::string id, boost::filesystem::path file);
 
        /** All our subtitles, in no particular order */
        std::list<SubtitleString> _subtitles;
 
-       class FileData : public Data {
+       class Font
+       {
        public:
-               FileData () {}
-
-               FileData (boost::shared_array<uint8_t> data_, boost::uintmax_t size_)
-                       : Data (data_, size_)
+               Font (std::string load_id_, std::string uuid_, boost::filesystem::path file_)
+                       : load_id (load_id_)
+                       , uuid (uuid_)
+                       , data (file_)
+                       , file (file_)
                {}
 
-               FileData (boost::filesystem::path file_)
-                       : Data (file_)
+               Font (std::string load_id_, std::string uuid_, Data data_)
+                       : load_id (load_id_)
+                       , uuid (uuid_)
+                       , data (data_)
                {}
-
-               /** .ttf file that this data was last written to */
+               
+               std::string load_id;
+               std::string uuid;
+               Data data;
+               /** .ttf file that this data was last written to, if applicable */
                mutable boost::optional<boost::filesystem::path> file;
        };
 
-       /** Font data, keyed by a subclass-dependent identifier.
-        *  For Interop, the string is the font ID from the subtitle file.
-        *  For SMPTE, the string is the font's URN from the subtitle file.
-        */
-       std::map<std::string, FileData> _fonts;
+       std::list<Font> _fonts;
 
 private:
        /** @struct ParseState
index 5be8845dc87388e4cd88a01f8730655146213f5b..daa16940cabfe097aba949fde6b1a3b2575a0751 100644 (file)
@@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE (interop_dcp_font_test)
        fread (ref.get(), 1, size, f);
        fclose (f);
 
-       BOOST_CHECK_EQUAL (memcmp (subs2->_fonts["theFontId"].data.get(), ref.get(), size), 0);
+       BOOST_CHECK_EQUAL (memcmp (subs2->_fonts.front().data.data.get(), ref.get(), size), 0);
 }
 
 /** Create a DCP with SMPTE subtitles and check that the font is written and read back correctly */
@@ -106,6 +106,6 @@ BOOST_AUTO_TEST_CASE (smpte_dcp_font_test)
        fread (ref.get(), 1, size, f);
        fclose (f);
 
-       BOOST_REQUIRE (subs2->_fonts["theFontId"].data);
-       BOOST_CHECK_EQUAL (memcmp (subs2->_fonts["theFontId"].data.get(), ref.get(), size), 0);
+       BOOST_REQUIRE (subs2->_fonts.front().data.data);
+       BOOST_CHECK_EQUAL (memcmp (subs2->_fonts.front().data.data.get(), ref.get(), size), 0);
 }
index 8cc9c90e01da59205e07d0d7f8a1dba7373d7012..ac9c2522aa046dbcd869ee87e8c03a34c22428c5 100644 (file)
@@ -76,7 +76,7 @@ main (int argc, char* argv[])
        cout << sub.xml_as_string() << "\n";
 
        if (extract_fonts) {
-               map<string, dcp::Data> fonts = sub.fonts ();
+               map<string, dcp::Data> fonts = sub.fonts_with_load_ids ();
                for (map<string, dcp::Data>::const_iterator i = fonts.begin(); i != fonts.end(); ++i) {
                        FILE* f = dcp::fopen_boost (i->first + ".ttf", "wb");
                        if (!f) {