From b651392d70d7e37ce5a8a20da81d86e5d19aadd8 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 15 Dec 2019 22:58:21 +0100 Subject: [PATCH] Add fix_empty_font_ids() to replace empty Font ids with a dummy string. Back-ported from abf4f7577877254ecd7a1dc7955e0d7ca49ad07c in master. --- src/subtitle_asset.cc | 40 +++++++++++++++++++++++++++++++++++++++- src/subtitle_asset.h | 2 ++ src/subtitle_string.h | 4 ++++ src/util.cc | 17 +++++++++++++++++ src/util.h | 1 + test/util_test.cc | 12 ++++++++++++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index bb7b0b1c..083a8040 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington + Copyright (C) 2012-2019 Carl Hetherington 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 #include #include @@ -655,3 +656,40 @@ SubtitleAsset::fonts_with_load_ids () const } return out; } + +/** Replace empty IDs in any and 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 ids; + BOOST_FOREACH (shared_ptr 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 i, load_font_nodes()) { + if (i->id == "") { + i->id = empty_id; + } + } + + BOOST_FOREACH (shared_ptr i, _subtitles) { + shared_ptr j = dynamic_pointer_cast (i); + if (j && j->font() && j->font().get() == "") { + j->set_font (empty_id); + } + } +} diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 59ed1165..9f137abe 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -101,6 +101,8 @@ public: Time latest_subtitle_out () const; + void fix_empty_font_ids (); + virtual std::list > load_font_nodes () const = 0; protected: diff --git a/src/subtitle_string.h b/src/subtitle_string.h index c274152b..7e84d103 100644 --- a/src/subtitle_string.h +++ b/src/subtitle_string.h @@ -125,6 +125,10 @@ public: return _aspect_adjust; } + void set_font (std::string id) { + _font = id; + } + void set_size (int s) { _size = s; } diff --git a/src/util.cc b/src/util.cc index d5b6cb9f..bce28f07 100644 --- a/src/util.cc +++ b/src/util.cc @@ -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 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); +} diff --git a/src/util.h b/src/util.h index bc109c62..0bb36cb0 100644 --- a/src/util.h +++ b/src/util.h @@ -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 existing, std::string base); } diff --git a/test/util_test.cc b/test/util_test.cc index f95001b4..4f387aaf 100644 --- a/test/util_test.cc +++ b/test/util_test.cc @@ -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 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); + } +} -- 2.30.2