Add fix_empty_font_ids() to replace empty Font ids with a dummy string. v1.6.14
authorCarl Hetherington <cth@carlh.net>
Sun, 15 Dec 2019 21:58:21 +0000 (22:58 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 15 Dec 2019 22:05:32 +0000 (23:05 +0100)
Back-ported from abf4f7577877254ecd7a1dc7955e0d7ca49ad07c in master.

src/subtitle_asset.cc
src/subtitle_asset.h
src/subtitle_string.h
src/util.cc
src/util.h
test/util_test.cc

index bb7b0b1ccf4f535d964ee72f2d23d221778b36f0..083a8040d8dce5f8c533dbea43ca5420f2d7866f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
 
     This file is part of libdcp.
 
@@ -40,6 +40,7 @@
 #include "subtitle_string.h"
 #include "subtitle_image.h"
 #include "dcp_assert.h"
+#include "load_font_node.h"
 #include <asdcp/AS_DCP.h>
 #include <asdcp/KM_util.h>
 #include <libxml++/nodes/element.h>
@@ -655,3 +656,40 @@ SubtitleAsset::fonts_with_load_ids () const
        }
        return out;
 }
+
+/** Replace empty IDs in any <LoadFontId> and <Font> tags with
+ *  a dummy string.  Some systems give errors with empty font IDs
+ *  (see DCP-o-matic bug #1689).
+ */
+void
+SubtitleAsset::fix_empty_font_ids ()
+{
+       bool have_empty = false;
+       list<string> ids;
+       BOOST_FOREACH (shared_ptr<LoadFontNode> i, load_font_nodes()) {
+               if (i->id == "") {
+                       have_empty = true;
+               } else {
+                       ids.push_back (i->id);
+               }
+       }
+
+       if (!have_empty) {
+               return;
+       }
+
+       string const empty_id = unique_string (ids, "font");
+
+       BOOST_FOREACH (shared_ptr<LoadFontNode> i, load_font_nodes()) {
+               if (i->id == "") {
+                       i->id = empty_id;
+               }
+       }
+
+       BOOST_FOREACH (shared_ptr<Subtitle> i, _subtitles) {
+               shared_ptr<SubtitleString> j = dynamic_pointer_cast<SubtitleString> (i);
+               if (j && j->font() && j->font().get() == "") {
+                       j->set_font (empty_id);
+               }
+       }
+}
index 59ed1165475a41d5ca7957f9428ced598c2508b5..9f137abe300c1c1aae52af0e0d8c65c522474af4 100644 (file)
@@ -101,6 +101,8 @@ public:
 
        Time latest_subtitle_out () const;
 
+       void fix_empty_font_ids ();
+
        virtual std::list<boost::shared_ptr<LoadFontNode> > load_font_nodes () const = 0;
 
 protected:
index c274152b3bd992bc835fd4a32376b71a6f766e0a..7e84d1033a067be8033fa2a4cca777e9ac49ccb0 100644 (file)
@@ -125,6 +125,10 @@ public:
                return _aspect_adjust;
        }
 
+       void set_font (std::string id) {
+               _font = id;
+       }
+
        void set_size (int s) {
                _size = s;
        }
index d5b6cb9f4eaeed6ccc33a493ea6766eac9389446..bce28f074844035bdafe92703081e4efa08d7a58 100644 (file)
@@ -376,3 +376,20 @@ dcp::indent (xmlpp::Element* element, int initial)
                element->add_child_text (last, "\n" + spaces(initial));
        }
 }
+
+/** Try quite hard to find a string which starts with \ref base and is
+ *  not in \ref existing.
+ */
+string
+dcp::unique_string (list<string> existing, string base)
+{
+       int const max_tries = existing.size() + 1;
+       for (int i = 0; i < max_tries; ++i) {
+               string trial = String::compose("%1%2", base, i);
+               if (find(existing.begin(), existing.end(), trial) == existing.end()) {
+                       return trial;
+               }
+       }
+
+       DCP_ASSERT (false);
+}
index bc109c62a8ee7185117945e315b857fac235b985..0bb36cb02d08e48e304f18aa00caa21793038175 100644 (file)
@@ -75,6 +75,7 @@ extern xmlpp::Node* find_child (xmlpp::Node const * node, std::string name);
 extern std::string openjpeg_version();
 extern std::string spaces (int n);
 extern void indent (xmlpp::Element* element, int initial);
+extern std::string unique_string (std::list<std::string> existing, std::string base);
 
 }
 
index f95001b4a46f3839840679ad7100ec49230ac9f9..4f387aaf3716840cc988c0d1a0095b6fdbef3100 100644 (file)
@@ -23,6 +23,7 @@
 
 using std::ifstream;
 using std::string;
+using std::list;
 
 /** Test dcp::base64_decode */
 BOOST_AUTO_TEST_CASE (base64_decode_test)
@@ -122,3 +123,14 @@ BOOST_AUTO_TEST_CASE (private_key_fingerprint_test)
 {
        BOOST_CHECK_EQUAL (dcp::private_key_fingerprint (dcp::file_to_string ("test/data/private.key")), "Jdz1bFpCcKI7R16Ccx9JHYytag0=");
 }
+
+BOOST_AUTO_TEST_CASE (unique_string_test)
+{
+       list<string> existing;
+       for (int i = 0; i < 16; i++) {
+               string s;
+               BOOST_CHECK_NO_THROW (s = dcp::unique_string(existing, "foo"));
+               BOOST_CHECK (find(existing.begin(), existing.end(), s) == existing.end());
+               existing.push_back (s);
+       }
+}