Basic support for variable-Z 3D subtitles.
authorCarl Hetherington <cth@carlh.net>
Thu, 20 Mar 2025 22:43:34 +0000 (23:43 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 24 Mar 2025 15:59:24 +0000 (16:59 +0100)
18 files changed:
cscript
src/lib/config.cc
src/lib/dcp_text_track.cc
src/lib/film.cc
src/lib/reel_writer.cc
src/lib/subtitle_film_encoder.cc
src/lib/text_content.cc
src/lib/text_decoder.cc
src/lib/util.cc
src/lib/video_content.cc
src/wx/closed_captions_dialog.cc
src/wx/dcp_panel.cc
src/wx/language_tag_dialog.cc
src/wx/language_tag_widget.cc
test/cpl_metadata_test.cc
test/render_subtitles_test.cc
test/subtitle_metadata_test.cc
test/vf_test.cc

diff --git a/cscript b/cscript
index 0413849fdef2a0b3113260bfd29908faac350e45..08d63cbbfe908a6adc6ff40d36f5cdc10b70fecd 100644 (file)
--- a/cscript
+++ b/cscript
@@ -436,7 +436,7 @@ def build_with_cpp17(target):
 
 
 def dependencies(target, options):
-    deps = [('libdcp', 'v1.10.15', {'c++17': build_with_cpp17(target)})]
+    deps = [('libdcp', 'v1.10.16', {'c++17': build_with_cpp17(target)})]
     deps.append(('libsub', 'v1.6.53'))
     deps.append(('leqm-nrt', '30dcaea1373ac62fba050e02ce5b0c1085797a23'))
     deps.append(('rtaudio', 'f619b76'))
index 49c64e5b6f5d17222f394d0f5783807e99a2dabd..86bc343daa035ae424d325bba7c3d3ccac2b6330 100644 (file)
@@ -807,7 +807,7 @@ Config::write_config() const
        cxml::add_text_child(root, "DefaultAudioDelay", fmt::to_string(_default_audio_delay));
        if (_default_audio_language) {
                /* [XML] DefaultAudioLanguage Default audio language to use for new films */
-               cxml::add_text_child(root, "DefaultAudioLanguage", _default_audio_language->to_string());
+               cxml::add_text_child(root, "DefaultAudioLanguage", _default_audio_language->as_string());
        }
        if (_default_kdm_directory) {
                /* [XML:opt] DefaultKDMDirectory Default directory to write KDMs to. */
@@ -1111,7 +1111,7 @@ Config::write_config() const
                _audio_mapping->as_xml(cxml::add_child(root, "AudioMapping"));
        }
        for (auto const& i: _custom_languages) {
-               cxml::add_text_child(root, "CustomLanguage", i.to_string());
+               cxml::add_text_child(root, "CustomLanguage", i.as_string());
        }
        for (auto const& initial: _initial_paths) {
                if (initial.second) {
index 2929323963d76c4c4561292a657144cd85c43743..ec1d6828b41e73b17f5c41754e74fb83ad278d93 100644 (file)
@@ -50,7 +50,7 @@ DCPTextTrack::DCPTextTrack (string name_, optional<dcp::LanguageTag> language_)
 string
 DCPTextTrack::summary () const
 {
-       return String::compose("%1 (%2)", name, language ? language->to_string() : _("Unknown"));
+       return String::compose("%1 (%2)", name, language ? language->as_string() : _("Unknown"));
 }
 
 void
@@ -58,7 +58,7 @@ DCPTextTrack::as_xml (xmlpp::Element* parent) const
 {
        cxml::add_text_child(parent, "Name", name);
        if (language) {
-               cxml::add_text_child(parent, "Language", language->to_string());
+               cxml::add_text_child(parent, "Language", language->as_string());
        }
 }
 
index 6adc7dff4a852bf8213713ce52481ad29292d944..5c3b6cee9fa57b7accef48bd00eb806a846e50b2 100644 (file)
@@ -442,13 +442,13 @@ Film::metadata(bool with_content_paths) const
        for (auto i: _content_versions) {
                cxml::add_text_child(root, "ContentVersion", i);
        }
-       cxml::add_text_child(root, "NameLanguage", _name_language.to_string());
+       cxml::add_text_child(root, "NameLanguage", _name_language.as_string());
        cxml::add_text_child(root, "TerritoryType", territory_type_to_string(_territory_type));
        if (_release_territory) {
                cxml::add_text_child(root, "ReleaseTerritory", _release_territory->subtag());
        }
        if (_sign_language_video_language) {
-               cxml::add_text_child(root, "SignLanguageVideoLanguage", _sign_language_video_language->to_string());
+               cxml::add_text_child(root, "SignLanguageVideoLanguage", _sign_language_video_language->as_string());
        }
        cxml::add_text_child(root, "VersionNumber", fmt::to_string(_version_number));
        cxml::add_text_child(root, "Status", dcp::status_to_string(_status));
@@ -475,7 +475,7 @@ Film::metadata(bool with_content_paths) const
        cxml::add_text_child(root, "UserExplicitContainer", _user_explicit_container ? "1" : "0");
        cxml::add_text_child(root, "UserExplicitResolution", _user_explicit_resolution ? "1" : "0");
        if (_audio_language) {
-               cxml::add_text_child(root, "AudioLanguage", _audio_language->to_string());
+               cxml::add_text_child(root, "AudioLanguage", _audio_language->as_string());
        }
        _playlist->as_xml(
                cxml::add_child(root, "Playlist"),
@@ -1004,7 +1004,7 @@ Film::isdcf_name(bool if_created_now) const
        auto entry_for_language = [](dcp::LanguageTag const& tag) {
                /* Look up what we should be using for this tag in the DCNC name */
                for (auto const& dcnc: dcp::dcnc_tags()) {
-                       if (tag.to_string() == dcnc.first) {
+                       if (tag.as_string() == dcnc.first) {
                                return dcnc.second;
                        }
                }
index 9037c9ef95b7c0009e3e59126e09189c46317f65..90cd9f26b8408a8ae015a1c8529c5a405384cdfd 100644 (file)
@@ -801,9 +801,9 @@ ReelWriter::empty_text_asset (TextType type, optional<DCPTextTrack> track, bool
                auto s = make_shared<dcp::InteropTextAsset>();
                s->set_movie_title (film()->name());
                if (is_open(type)) {
-                       s->set_language (lang.first ? lang.first->to_string() : "Unknown");
+                       s->set_language(lang.first ? lang.first->as_string() : "Unknown");
                } else if (track->language) {
-                       s->set_language (track->language->to_string());
+                       s->set_language(track->language->as_string());
                }
                s->set_reel_number(fmt::to_string(_reel_index + 1));
                asset = s;
@@ -814,7 +814,7 @@ ReelWriter::empty_text_asset (TextType type, optional<DCPTextTrack> track, bool
                if (is_open(type) && lang.first) {
                        s->set_language (*lang.first);
                } else if (track && track->language) {
-                       s->set_language (dcp::LanguageTag(track->language->to_string()));
+                       s->set_language(dcp::LanguageTag(track->language->as_string()));
                }
                s->set_edit_rate (dcp::Fraction (film()->video_frame_rate(), 1));
                s->set_reel_number (_reel_index + 1);
@@ -843,6 +843,7 @@ ReelWriter::empty_text_asset (TextType type, optional<DCPTextTrack> track, bool
                                0.5,
                                dcp::VAlign::CENTER,
                                0,
+                               vector<dcp::Text::VariableZPosition>(),
                                dcp::Direction::LTR,
                                " ",
                                dcp::Effect::NONE,
@@ -958,11 +959,11 @@ ReelWriter::write(PlayerText subs, TextType type, optional<DCPTextTrack> track,
 
        for (auto i: subs.bitmap) {
                asset->add (
-                       make_shared<dcp::TextImage>(
+                       std::make_shared<dcp::TextImage>(
                                image_as_png(i.image),
                                dcp::Time(period.from.seconds() - _period.from.seconds(), tcr),
                                dcp::Time(period.to.seconds() - _period.from.seconds(), tcr),
-                               i.rectangle.x, dcp::HAlign::LEFT, i.rectangle.y, dcp::VAlign::TOP, 0,
+                               i.rectangle.x, dcp::HAlign::LEFT, i.rectangle.y, dcp::VAlign::TOP, 0, vector<dcp::Text::VariableZPosition>(),
                                dcp::Time(), dcp::Time()
                                )
                        );
index a127ba73fce0b9f3cb4c3d7113834fbaa5474abc..2de74bc67cab63dce3dfa60295abb12cbd0ec882 100644 (file)
@@ -145,7 +145,7 @@ SubtitleFilmEncoder::text(PlayerText subs, TextType type, optional<DCPTextTrack>
                        auto s = make_shared<dcp::InteropTextAsset>();
                        s->set_movie_title (_film->name());
                        if (lang.first) {
-                               s->set_language (lang.first->to_string());
+                               s->set_language(lang.first->as_string());
                        }
                        s->set_reel_number(fmt::to_string(_reel_index + 1));
                        _assets[_reel_index].first = s;
index 4a333bb76da62a1a5a6c03013e8860f50ed311bc..93dad2639ad592e0671bdacfdbefb6897ef65ea0 100644 (file)
@@ -411,7 +411,7 @@ TextContent::as_xml(xmlpp::Element* root) const
        }
        if (_language) {
                auto lang = cxml::add_child(text, "Language");
-               lang->add_child_text (_language->to_string());
+               lang->add_child_text(_language->as_string());
                lang->set_attribute("additional", _language_is_additional ? "1" : "0");
        }
 }
index ab82177f7a0cd2152d2364a339e91e925acafb80..52d6c58d307c0e722e70136311b11cfa657ab94c 100644 (file)
@@ -284,6 +284,7 @@ TextDecoder::emit_plain_start(ContentTime from, sub::Subtitle const & sub_subtit
                                v_position,
                                v_align,
                                0,
+                               vector<dcp::Text::VariableZPosition>(),
                                dcp::Direction::LTR,
                                remove_invalid_characters_for_xml(block.text),
                                dcp::Effect::NONE,
index 1e2f7d61fe1a9d7ccad415f6d844834f7417cd8f..81ae4c4949de5266550b4828dca0b2e48ac69e31 100644 (file)
@@ -479,8 +479,8 @@ LIBDCP_ENABLE_WARNINGS
        /* Render something to fontconfig to create its cache */
        vector<StringText> subs;
        dcp::TextString ss(
-               optional<string>(), false, false, false, dcp::Colour(), 42, 1, dcp::Time(), dcp::Time(), 0, dcp::HAlign::CENTER, 0, dcp::VAlign::CENTER, 0, dcp::Direction::LTR,
-               "Hello dolly", dcp::Effect::NONE, dcp::Colour(), dcp::Time(), dcp::Time(), 0, std::vector<dcp::Ruby>()
+               optional<string>(), false, false, false, dcp::Colour(), 42, 1, dcp::Time(), dcp::Time(), 0, dcp::HAlign::CENTER, 0, dcp::VAlign::CENTER, 0,
+               vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello dolly", dcp::Effect::NONE, dcp::Colour(), dcp::Time(), dcp::Time(), 0, std::vector<dcp::Ruby>()
                );
        subs.push_back(StringText(ss, 0, make_shared<dcpomatic::Font>("foo"), dcp::SubtitleStandard::SMPTE_2014));
        render_text(subs, dcp::Size(640, 480), DCPTime(), 24);
index 56262cd145a2161e70795c1ae763833c6e18a85b..ae13e1eca1ff45cf8a2b2080a9102bf18e1c9f7f 100644 (file)
@@ -304,7 +304,7 @@ VideoContent::as_xml(xmlpp::Element* element) const
        cxml::add_text_child(element, "Range", _range == VideoRange::FULL ? "full" : "video");
        _pixel_quanta.as_xml(cxml::add_child(element, "PixelQuanta"));
        if (_burnt_subtitle_language) {
-               cxml::add_text_child(element, "BurntSubtitleLanguage", _burnt_subtitle_language->to_string());
+               cxml::add_text_child(element, "BurntSubtitleLanguage", _burnt_subtitle_language->as_string());
        }
 }
 
index c8a04993c1ec74711ac35023debea38c7e8cd20f..b8618c0cd648fcc7124735a3e15e2ef772e0d580 100644 (file)
@@ -254,7 +254,7 @@ ClosedCaptionsDialog::update_tracks (shared_ptr<const Film> film)
 
        _track->Clear ();
        for (auto const& i: _tracks) {
-               _track->Append (std_to_wx(String::compose("%1 (%2)", i.name, i.language ? i.language->to_string() : wx_to_std(_("Unknown")))));
+               _track->Append(std_to_wx(String::compose("%1 (%2)", i.name, i.language ? i.language->as_string() : wx_to_std(_("Unknown")))));
        }
 
        if (_track->GetCount() > 0) {
index 0f0edc9719c7f56df424a742d76517abce0ee35d..aeddb2a8db8c3a43980c3b164acbe719a8c902f5 100644 (file)
@@ -484,7 +484,7 @@ DCPPanel::film_changed(FilmProperty p)
        {
                auto al = _film->audio_language();
                checked_set (_enable_audio_language, static_cast<bool>(al));
-               checked_set (_audio_language, al ? std_to_wx(al->to_string()) : wxString{});
+               checked_set(_audio_language, al ? std_to_wx(al->as_string()) : wxString{});
                setup_dcp_name ();
                setup_sensitivity ();
                _audio_panel_sizer->Layout();
index c898d3edba6d24b4aafd16e2fac5b7d3e2b21a1e..f5a239c6c31d69dae5423a3de7d57fdd71779de7 100644 (file)
@@ -96,7 +96,7 @@ LanguageTagDialog::populate_list ()
                        it.SetText (std_to_wx(i.description()));
                        _list->InsertItem (it);
                        it.SetColumn (1);
-                       it.SetText (std_to_wx(i.to_string()));
+                       it.SetText(std_to_wx(i.as_string()));
                        _list->SetItem (it);
                }
        };
index cefa4b90cd6cdbecb741fbd279f1d703c9d4154b..ff2883bc2e1f4429407c40b0937c92e7fc22dadb 100644 (file)
@@ -78,7 +78,7 @@ LanguageTagWidget::set (optional<dcp::LanguageTag> tag)
 {
        _tag = tag;
        if (tag) {
-               checked_set (_language, std_to_wx(tag->to_string()));
+               checked_set(_language, std_to_wx(tag->as_string()));
        } else {
                checked_set(_language, wxString{});
        }
index 59ceed064b84715362bd1dd30ef7f4b0e550f1e9..c0a3c658d36305813629b37e056e82156b88293b 100644 (file)
@@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(main_sound_configuration_test_51_vi)
        BOOST_REQUIRE(msc);
 
        /* We think this should say 51 not 71 at the start (#2580) */
-       BOOST_CHECK_EQUAL(msc->to_string(), "51/L,R,C,LFE,Ls,Rs,-,VIN");
+       BOOST_CHECK_EQUAL(msc->as_string(), "51/L,R,C,LFE,Ls,Rs,-,VIN");
 }
 
 
@@ -117,5 +117,5 @@ BOOST_AUTO_TEST_CASE(main_sound_configuration_test_71)
        auto msc = cpl->main_sound_configuration();
        BOOST_REQUIRE(msc);
 
-       BOOST_CHECK_EQUAL(msc->to_string(), "71/L,R,C,LFE,Lss,Rss,-,VIN,-,-,Lrs,Rrs");
+       BOOST_CHECK_EQUAL(msc->as_string(), "71/L,R,C,LFE,Lss,Rss,-,VIN,-,-,Lrs,Rrs");
 }
index e89890542b8698459ec3bb0863603fd30390a059..1fe43c6d85cb3baa0e1730d1202f25ef216898f3 100644 (file)
@@ -37,6 +37,9 @@
 
 using std::make_shared;
 using std::shared_ptr;
+using std::string;
+using std::vector;
+using boost::optional;
 
 
 static void
@@ -59,6 +62,7 @@ add(std::vector<StringText>& s, std::string text, bool italic, bool bold, bool u
                                1,
                                dcp::VAlign::TOP,
                                0,
+                               vector<dcp::Text::VariableZPosition>(),
                                dcp::Direction::LTR,
                                text,
                                dcp::Effect::NONE,
@@ -133,6 +137,7 @@ BOOST_AUTO_TEST_CASE(render_text_with_newline_test)
                        0.5, dcp::HAlign::CENTER,
                        0.5, dcp::VAlign::CENTER,
                        0.0,
+                       vector<dcp::Text::VariableZPosition>(),
                        dcp::Direction::LTR,
                        "Hello                     world",
                        dcp::Effect::NONE, dcp::Colour(0, 0, 0),
@@ -146,6 +151,7 @@ BOOST_AUTO_TEST_CASE(render_text_with_newline_test)
                        0.5, dcp::HAlign::CENTER,
                        0.5, dcp::VAlign::CENTER,
                        0.0,
+                       vector<dcp::Text::VariableZPosition>(),
                        dcp::Direction::LTR,
                        "\n",
                        dcp::Effect::NONE, dcp::Colour(0, 0, 0),
index d8b88757646db3e0ffa5f75b5f55e8b1fa685907..fcea278d7974f61d23b6233111d1c48da2ebd4a6 100644 (file)
@@ -50,6 +50,6 @@ BOOST_AUTO_TEST_CASE (subtitle_metadata_test1)
 
        auto langs = film->open_text_languages();
        BOOST_REQUIRE (langs.first);
-       BOOST_CHECK_EQUAL (langs.first->to_string(), "de-DE");
+       BOOST_CHECK_EQUAL(langs.first->as_string(), "de-DE");
 }
 
index cb51169109b437da8faf39f6c10852bdacae0b68..2b59b68ba4864fb1698d89b1fef31ee5c742487d 100644 (file)
@@ -59,6 +59,7 @@ using std::make_shared;
 using std::shared_ptr;
 using std::string;
 using std::vector;
+using boost::optional;
 using namespace dcpomatic;
 
 
@@ -465,7 +466,7 @@ BOOST_AUTO_TEST_CASE(test_referencing_ov_with_missing_subtitle_in_some_reels)
                42, 1, dcp::Time(0, 0, 5, 0, 24), dcp::Time(0, 0, 9, 0, 24),
                0, dcp::HAlign::CENTER,
                0, dcp::VAlign::CENTER,
-               0, dcp::Direction::LTR,
+               0, vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR,
                "Hello",
                dcp::Effect::NONE, dcp::Colour(0, 0, 0),
                dcp::Time{}, dcp::Time{},