Nearly pretty-print subtitle XML (though not in <Text> nodes). v1.8.12
authorCarl Hetherington <cth@carlh.net>
Tue, 15 Mar 2022 14:32:49 +0000 (15:32 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 20 Mar 2022 20:20:58 +0000 (21:20 +0100)
This is an attempt to fix DoM bug #2205.

src/interop_subtitle_asset.cc
src/smpte_subtitle_asset.cc
src/subtitle_asset.cc
src/subtitle_asset.h
test/interop_subtitle_test.cc
test/ref/write_interop_subtitle_test3/ASSETMAP
test/ref/write_interop_subtitle_test3/pkl_e94b8a0d-27f7-408a-af16-78d3df419a91.xml
test/ref/write_interop_subtitle_test3/subs.xml
test/shared_subtitle_test.cc
test/smpte_subtitle_test.cc
test/verify_test.cc

index d51472845c66e92c93d63194e806941d83fecff9..bb0cad701fee2b67427aa67265e5c6c3a7b4946e 100644 (file)
@@ -125,7 +125,7 @@ InteropSubtitleAsset::xml_as_string () const
 
        subtitles_as_xml (root, 250, Standard::INTEROP);
 
-       return doc.write_to_string ("UTF-8");
+       return format_xml(doc, {});
 }
 
 
index f09d99f37ff21e474fc913704c55b17a1ef87809..0693323cf5861f3f2e2f4c0f5251379e66ba32e1 100644 (file)
@@ -344,8 +344,6 @@ SMPTESubtitleAsset::xml_as_string () const
 {
        xmlpp::Document doc;
        auto root = doc.create_root_node ("SubtitleReel");
-       root->set_namespace_declaration (subtitle_smpte_ns);
-       root->set_namespace_declaration ("http://www.w3.org/2001/XMLSchema", "xs");
 
        DCP_ASSERT (_xml_id);
        root->add_child("Id")->add_child_text("urn:uuid:" + *_xml_id);
@@ -374,7 +372,7 @@ SMPTESubtitleAsset::xml_as_string () const
 
        subtitles_as_xml (root->add_child("SubtitleList"), _time_code_rate, Standard::SMPTE);
 
-       return doc.write_to_string ("UTF-8");
+       return format_xml(doc, { {"", subtitle_smpte_ns}, {"xs", "http://www.w3.org/2001/XMLSchema"} });
 }
 
 
index 22781196ac5c485ca042ba8813895e06a85db7f1..bd8bb993edb9874658418036c210324865622751 100644 (file)
 #include <boost/algorithm/string.hpp>
 #include <boost/lexical_cast.hpp>
 #include <boost/shared_array.hpp>
+#include <algorithm>
 
 
-using std::dynamic_pointer_cast;
-using std::string;
-using std::cout;
 using std::cerr;
+using std::cout;
+using std::dynamic_pointer_cast;
+using std::make_shared;
 using std::map;
+using std::pair;
 using std::shared_ptr;
+using std::string;
 using std::vector;
-using std::make_shared;
-using boost::optional;
 using boost::lexical_cast;
+using boost::optional;
 using namespace dcp;
 
 
@@ -799,3 +801,115 @@ SubtitleAsset::fix_empty_font_ids ()
                }
        }
 }
+
+
+namespace {
+
+struct State
+{
+       int indent;
+       string xml;
+       int disable_formatting;
+};
+
+}
+
+
+static
+void
+format_xml_node (xmlpp::Node const* node, State& state)
+{
+       if (auto text_node = dynamic_cast<const xmlpp::TextNode*>(node)) {
+               string content = text_node->get_content();
+               boost::replace_all(content, "&", "&amp;");
+               boost::replace_all(content, "<", "&lt;");
+               boost::replace_all(content, ">", "&gt;");
+               state.xml += content;
+       } else if (auto element = dynamic_cast<const xmlpp::Element*>(node)) {
+               ++state.indent;
+
+               auto children = element->get_children();
+               auto const should_disable_formatting =
+                       std::any_of(
+                               children.begin(), children.end(),
+                               [](xmlpp::Node const* node) { return static_cast<bool>(dynamic_cast<const xmlpp::ContentNode*>(node)); }
+                               ) || element->get_name() == "Text";
+
+               if (!state.disable_formatting) {
+                       state.xml += "\n" + string(state.indent * 2, ' ');
+               }
+
+               state.xml += "<" + element->get_name();
+
+               for (auto attribute: element->get_attributes()) {
+                       state.xml += String::compose(" %1=\"%2\"", attribute->get_name().raw(), attribute->get_value().raw());
+               }
+
+               if (children.empty()) {
+                       state.xml += "/>";
+               } else {
+                       state.xml += ">";
+
+                       if (should_disable_formatting) {
+                               ++state.disable_formatting;
+                       }
+
+                       for (auto child: children) {
+                               format_xml_node(child, state);
+                       }
+
+                       if (!state.disable_formatting) {
+                               state.xml += "\n" + string(state.indent * 2, ' ');
+                       }
+
+                       state.xml += String::compose("</%1>", element->get_name().raw());
+
+                       if (should_disable_formatting) {
+                               --state.disable_formatting;
+                       }
+               }
+
+               --state.indent;
+       }
+}
+
+
+/** Format XML much as write_to_string_formatted() would do, except without adding any white space
+ *  to <Text> nodes.  This is an attempt to avoid changing what is actually displayed as subtitles
+ *  while also formatting the XML in such a way as to avoid DoM bug 2205.
+ *
+ *  namespace is a list of namespaces for the root node; it would be nicer to set these up with
+ *  set_namespace_declaration in the caller and then to extract them here but I couldn't find a way
+ *  to get all namespaces with the libxml++ API.
+ */
+string
+SubtitleAsset::format_xml (xmlpp::Document const& document, vector<pair<string, string>> const& namespaces)
+{
+       auto root = document.get_root_node();
+
+       State state = {};
+       state.xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<" + root->get_name();
+
+       for (auto const& ns: namespaces) {
+               if (ns.first.empty()) {
+                       state.xml += String::compose(" xmlns=\"%1\"", ns.second);
+               } else {
+                       state.xml += String::compose(" xmlns:%1=\"%2\"", ns.first, ns.second);
+               }
+       }
+
+       for (auto attribute: root->get_attributes()) {
+               state.xml += String::compose(" %1=\"%2\"", attribute->get_name().raw(), attribute->get_value().raw());
+       }
+
+       state.xml += ">";
+
+       for (auto child: document.get_root_node()->get_children()) {
+               format_xml_node(child, state);
+       }
+
+       state.xml += String::compose("\n</%1>\n", root->get_name().raw());
+
+       return state.xml;
+}
+
index f51906e22aabfe49c87611a3531dee868d942182..88b5378cab2986661b27af9f38bd3371a3f24d64 100644 (file)
 #include <libcxml/cxml.h>
 #include <boost/shared_array.hpp>
 #include <map>
+#include <string>
+#include <utility>
+#include <vector>
 
 
 namespace xmlpp {
+       class Document;
        class Element;
 }
 
@@ -128,6 +132,8 @@ public:
                return _raw_xml;
        }
 
+       static std::string format_xml (xmlpp::Document const& document, std::vector<std::pair<std::string, std::string>> const& namespaces);
+
 protected:
        friend struct ::interop_dcp_font_test;
        friend struct ::smpte_dcp_font_test;
index ff0940b095c9627c9ba2d4c59da2d43e3eeeab60..3369fc24f7fb7a02ce7347a52bdab0d4f2ccd8c1 100644 (file)
@@ -762,21 +762,21 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
        c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
 
        check_xml (
-               "<DCSubtitle Version=\"1.0\">"
-                 "<SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>"
-                 "<MovieTitle>Test</MovieTitle>"
-                 "<ReelNumber>1</ReelNumber>"
-                 "<Language>EN</Language>"
-                 "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">"
-                   "<Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">"
-                     "<Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>"
-                   "</Subtitle>"
-                 "</Font>"
-                 "<Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">"
-                   "<Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">"
-                     "<Text VAlign=\"bottom\" VPosition=\"40\">What's going <Space Size=\"9em\"/>on</Text>"
-                   "</Subtitle>"
-                 "</Font>"
+               "<DCSubtitle Version=\"1.0\">\n"
+               "  <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
+               "  <MovieTitle>Test</MovieTitle>\n"
+               "  <ReelNumber>1</ReelNumber>\n"
+               "  <Language>EN</Language>\n"
+               "  <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
+               "    <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
+               "      <Text VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
+               "    </Subtitle>\n"
+               "  </Font>\n"
+               "  <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
+               "    <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
+               "      <Text VAlign=\"bottom\" VPosition=\"40\">What's going <Space Size=\"9em\"/>on</Text>\n"
+               "    </Subtitle>\n"
+               "  </Font>\n"
                "</DCSubtitle>",
                c.xml_as_string (),
                vector<string>()
@@ -846,21 +846,21 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
        c._id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
 
        check_xml (
-               "<DCSubtitle Version=\"1.0\">"
-                 "<SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>"
-                 "<MovieTitle>Test</MovieTitle>"
-                 "<ReelNumber>1</ReelNumber>"
-                 "<Language>EN</Language>"
-                 "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">"
-                   "<Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">"
-                     "<Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>"
-                   "</Subtitle>"
-                 "</Font>"
-                 "<Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">"
-                   "<Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">"
-                     "<Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>"
-                   "</Subtitle>"
-                 "</Font>"
+               "<DCSubtitle Version=\"1.0\">\n"
+               "  <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>\n"
+               "  <MovieTitle>Test</MovieTitle>\n"
+               "  <ReelNumber>1</ReelNumber>\n"
+               "  <Language>EN</Language>\n"
+               "  <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" Id=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underlined=\"no\" Weight=\"normal\">\n"
+               "    <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:229\" TimeOut=\"00:04:11:229\" FadeUpTime=\"0\" FadeDownTime=\"0\">\n"
+               "      <Text HPosition=\"-20\" VAlign=\"top\" VPosition=\"80\">Hello world</Text>\n"
+               "    </Subtitle>\n"
+               "  </Font>\n"
+               "  <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underlined=\"yes\" Weight=\"bold\">\n"
+               "    <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:219\" TimeOut=\"06:12:15:219\" FadeUpTime=\"930792\" FadeDownTime=\"4591834\">\n"
+               "      <Text HPosition=\"-20\" VAlign=\"bottom\" VPosition=\"40\">What's going on</Text>\n"
+               "    </Subtitle>\n"
+               "  </Font>\n"
                "</DCSubtitle>",
                c.xml_as_string (),
                vector<string>()
index 7c90151373efbcc32ee39f9a6326d546568fa117..570b0d5b9edc6cd83c90cb60b96dda44858a1173 100644 (file)
@@ -37,7 +37,7 @@
           <Path>subs.xml</Path>
           <VolumeIndex>1</VolumeIndex>
           <Offset>0</Offset>
-          <Length>414</Length>
+          <Length>438</Length>
         </Chunk>
       </ChunkList>
     </Asset>
index 2da8e9106bf01bda254ffba7340be7859976d170..6f192259981a21926372c1c6f2d71e7fc86da42e 100644 (file)
@@ -9,15 +9,15 @@
     <Asset>
       <Id>urn:uuid:46c3eb45-15e5-47d6-8684-d8641e4dc516</Id>
       <AnnotationText>46c3eb45-15e5-47d6-8684-d8641e4dc516</AnnotationText>
-      <Hash>614bJ4VLsNZ6mLbdXbZXjGuoSsY=</Hash>
+      <Hash>Y8rZTMi93JjmkgwFK7Fu3W5rz/Y=</Hash>
       <Size>1061</Size>
       <Type>text/xml;asdcpKind=CPL</Type>
     </Asset>
     <Asset>
       <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>
       <AnnotationText>a6c58cff-3e1e-4b38-acec-a42224475ef6</AnnotationText>
-      <Hash>cVnFjMLTQnSIAlIzJpNB/p7B230=</Hash>
-      <Size>414</Size>
+      <Hash>ilLkOSjxgHZxkAdOPVJBoDFiUh8=</Hash>
+      <Size>438</Size>
       <Type>text/xml;asdcpKind=Subtitle</Type>
     </Asset>
     <Asset>
index d1c8fa7e4b3162132ae4635ed43d3d8c6fe08b36..050ee93053a39e6a5eefa2707b6cd549dea74382 100644 (file)
@@ -1,2 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<DCSubtitle Version="1.0"><SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID><MovieTitle>Test</MovieTitle><ReelNumber>1</ReelNumber><Language>EN</Language><Subtitle SpotNumber="1" TimeIn="00:04:09:229" TimeOut="00:04:11:229" FadeUpTime="0" FadeDownTime="0"><Image VAlign="top" VPosition="80">d36f4bb3-c4fa-4a95-9915-6fec3110cd71.png</Image></Subtitle></DCSubtitle>
+<DCSubtitle Version="1.0">
+  <SubtitleID>a6c58cff-3e1e-4b38-acec-a42224475ef6</SubtitleID>
+  <MovieTitle>Test</MovieTitle>
+  <ReelNumber>1</ReelNumber>
+  <Language>EN</Language>
+  <Subtitle SpotNumber="1" TimeIn="00:04:09:229" TimeOut="00:04:11:229" FadeUpTime="0" FadeDownTime="0">
+    <Image VAlign="top" VPosition="80">d36f4bb3-c4fa-4a95-9915-6fec3110cd71.png</Image>
+  </Subtitle>
+</DCSubtitle>
index f18b03db680db453fe8a40425f41d44f44647634..ae05642a091bd96e297e3fece714e5ab57a06603 100644 (file)
@@ -167,3 +167,53 @@ BOOST_AUTO_TEST_CASE (pull_fonts_test3)
        BOOST_CHECK_EQUAL (sub1->font._values["size"], "42");
 }
 
+
+/* Check that subtitle XML is prettily formatted without inserting any white space into
+ * <Text> node, which I think has the potential to alter appearance.
+ */
+BOOST_AUTO_TEST_CASE (format_xml_test1)
+{
+       xmlpp::Document doc;
+       auto root = doc.create_root_node("Foo");
+       root->add_child("Empty");
+       root->add_child("Text")->add_child_text("Hello world");
+       root->add_child("Font")->add_child("Text")->add_child_text("Say what");
+       auto fred = root->add_child("Text")->add_child("Font");
+       fred->set_attribute("bob", "job");
+       fred->add_child_text("Fred");
+       fred->add_child("Text")->add_child_text("Jim");
+       fred->add_child_text("Sheila");
+       BOOST_REQUIRE_EQUAL (dcp::SubtitleAsset::format_xml(doc, { {"", "fred"}, {"jim", "sheila"} }),
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+"<Foo xmlns=\"fred\" xmlns:jim=\"sheila\">\n"
+"  <Empty/>\n"
+"  <Text>Hello world</Text>\n"
+"  <Font>\n"
+"    <Text>Say what</Text>\n"
+"  </Font>\n"
+"  <Text><Font bob=\"job\">Fred<Text>Jim</Text>Sheila</Font></Text>\n"
+"</Foo>\n");
+}
+
+
+BOOST_AUTO_TEST_CASE (format_xml_test2)
+{
+       xmlpp::DomParser parser;
+       auto path = private_test / "DKH_UT_EN20160601def.xml";
+       parser.parse_file(path.string().c_str());
+       auto document = parser.get_document();
+       check_xml (dcp::file_to_string(private_test / "DKH_UT_EN20160601def.reformatted.xml"), dcp::SubtitleAsset::format_xml(*document, {}), {});
+}
+
+
+BOOST_AUTO_TEST_CASE (format_xml_entities_test)
+{
+       xmlpp::Document doc;
+       auto root = doc.create_root_node("Foo");
+       root->add_child("Bar")->add_child_text("Don't panic &amp; xml \"is\" 'great' & < > —");
+       BOOST_REQUIRE_EQUAL(dcp::SubtitleAsset::format_xml(doc, {}),
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+"<Foo>\n"
+"  <Bar>Don't panic &amp;amp; xml \"is\" 'great' &amp; &lt; &gt; —</Bar>\n"
+"</Foo>\n");
+}
index 2b8491a35443b36ae9a005210dbca94b965b2c12..f1f66bfb645dd2e0f272c8abad9826a0564b8228 100644 (file)
@@ -257,27 +257,27 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test)
        c._xml_id = "a6c58cff-3e1e-4b38-acec-a42224475ef6";
 
        check_xml (
-               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
-                 "<Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>"
-                 "<ContentTitleText>Test</ContentTitleText>"
-                 "<IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>"
-                 "<ReelNumber>1</ReelNumber>"
-                 "<Language>en</Language>"
-                 "<EditRate>24 1</EditRate>"
-                 "<TimeCodeRate>24</TimeCodeRate>"
-                 "<SubtitleList>"
-                   "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">"
-                     "<Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:22\" TimeOut=\"00:04:11:22\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">"
-                       "<Text Valign=\"top\" Vposition=\"80\">Hello world</Text>"
-                     "</Subtitle>"
-                   "</Font>"
-                   "<Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underline=\"yes\" Weight=\"bold\">"
-                     "<Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:21\" TimeOut=\"06:12:15:21\" FadeUpTime=\"01:02:03:04\" FadeDownTime=\"05:06:07:08\">"
-                       "<Text Valign=\"bottom\" Vposition=\"40\" Direction=\"rtl\">What's going <Space Size=\"4.2\"/>on</Text>"
-                     "</Subtitle>"
-                   "</Font>"
-                 "</SubtitleList>"
+               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+               "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
+               "  <ContentTitleText>Test</ContentTitleText>\n"
+               "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
+               "  <ReelNumber>1</ReelNumber>\n"
+               "  <Language>en</Language>\n"
+               "  <EditRate>24 1</EditRate>\n"
+               "  <TimeCodeRate>24</TimeCodeRate>\n"
+               "  <SubtitleList>\n"
+               "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Frutiger\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
+               "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:04:09:22\" TimeOut=\"00:04:11:22\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
+               "        <Text Valign=\"top\" Vposition=\"80\">Hello world</Text>\n"
+               "      </Subtitle>\n"
+               "    </Font>\n"
+               "    <Font AspectAdjust=\"1.0\" Color=\"FF800040\" Effect=\"border\" EffectColor=\"FF010203\" Italic=\"yes\" Script=\"normal\" Size=\"91\" Underline=\"yes\" Weight=\"bold\">\n"
+               "      <Subtitle SpotNumber=\"2\" TimeIn=\"05:41:00:21\" TimeOut=\"06:12:15:21\" FadeUpTime=\"01:02:03:04\" FadeDownTime=\"05:06:07:08\">\n"
+               "        <Text Valign=\"bottom\" Vposition=\"40\" Direction=\"rtl\">What's going <Space Size=\"4.2\"/>on</Text>\n"
+               "      </Subtitle>\n"
+               "    </Font>\n"
+               "  </SubtitleList>\n"
                "</SubtitleReel>",
                c.xml_as_string (),
                vector<string>()
@@ -449,31 +449,23 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
 
        check_xml (
                c.xml_as_string(),
-               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
-                 "<Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>"
-                 "<ContentTitleText>Test</ContentTitleText>"
-                 "<IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>"
-                 "<ReelNumber>1</ReelNumber>"
-                 "<Language>en</Language>"
-                 "<EditRate>24 1</EditRate>"
-                 "<TimeCodeRate>24</TimeCodeRate>"
-                 "<SubtitleList>"
-                   "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">"
-                     "<Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">"
-                       "<Text Valign=\"top\" Vposition=\"80\">"
-                         "<Font Italic=\"no\">Testing is </Font>"
-                         "<Font Italic=\"yes\">really</Font>"
-                         "<Font Italic=\"no\"> fun</Font>"
-                       "</Text>"
-                       "<Text Valign=\"top\" Vposition=\"90\">"
-                         "<Font Italic=\"no\">This is the </Font>"
-                         "<Font Italic=\"yes\">second</Font>"
-                         "<Font Italic=\"no\"> line</Font>"
-                       "</Text>"
-                     "</Subtitle>"
-                   "</Font>"
-                 "</SubtitleList>"
+               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+               "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
+               "  <ContentTitleText>Test</ContentTitleText>\n"
+               "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
+               "  <ReelNumber>1</ReelNumber>\n"
+               "  <Language>en</Language>\n"
+               "  <EditRate>24 1</EditRate>\n"
+               "  <TimeCodeRate>24</TimeCodeRate>\n"
+               "  <SubtitleList>\n"
+               "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
+               "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
+               "        <Text Valign=\"top\" Vposition=\"80\"><Font Italic=\"no\">Testing is </Font><Font Italic=\"yes\">really</Font><Font Italic=\"no\"> fun</Font></Text>\n"
+               "        <Text Valign=\"top\" Vposition=\"90\"><Font Italic=\"no\">This is the </Font><Font Italic=\"yes\">second</Font><Font Italic=\"no\"> line</Font></Text>\n"
+               "      </Subtitle>\n"
+               "    </Font>\n"
+               "  </SubtitleList>\n"
                "</SubtitleReel>",
                vector<string>()
                );
@@ -593,23 +585,23 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_top_alignment)
 
        check_xml (
                c.xml_as_string(),
-               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
-                 "<Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>"
-                 "<ContentTitleText>Test</ContentTitleText>"
-                 "<IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>"
-                 "<ReelNumber>1</ReelNumber>"
-                 "<Language>en</Language>"
-                 "<EditRate>24 1</EditRate>"
-                 "<TimeCodeRate>24</TimeCodeRate>"
-                 "<SubtitleList>"
-                   "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">"
-                     "<Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">"
-                       "<Text Valign=\"top\" Vposition=\"80\">Top line</Text>"
-                       "<Text Valign=\"top\" Vposition=\"90\">Bottom line</Text>"
-                     "</Subtitle>"
-                   "</Font>"
-                 "</SubtitleList>"
+               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+               "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
+               "  <ContentTitleText>Test</ContentTitleText>\n"
+               "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
+               "  <ReelNumber>1</ReelNumber>\n"
+               "  <Language>en</Language>\n"
+               "  <EditRate>24 1</EditRate>\n"
+               "  <TimeCodeRate>24</TimeCodeRate>\n"
+               "  <SubtitleList>\n"
+               "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
+               "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
+               "        <Text Valign=\"top\" Vposition=\"80\">Top line</Text>\n"
+               "        <Text Valign=\"top\" Vposition=\"90\">Bottom line</Text>\n"
+               "      </Subtitle>\n"
+               "    </Font>\n"
+               "  </SubtitleList>\n"
                "</SubtitleReel>",
                {}
                );
@@ -679,23 +671,23 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_bottom_alignment)
 
        check_xml (
                c.xml_as_string(),
-               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">"
-                 "<Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>"
-                 "<ContentTitleText>Test</ContentTitleText>"
-                 "<IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>"
-                 "<ReelNumber>1</ReelNumber>"
-                 "<Language>en</Language>"
-                 "<EditRate>24 1</EditRate>"
-                 "<TimeCodeRate>24</TimeCodeRate>"
-                 "<SubtitleList>"
-                   "<Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">"
-                     "<Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">"
-                       "<Text Valign=\"bottom\" Vposition=\"80\">Top line</Text>"
-                       "<Text Valign=\"bottom\" Vposition=\"70\">Bottom line</Text>"
-                     "</Subtitle>"
-                   "</Font>"
-                 "</SubtitleList>"
+               "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+               "<SubtitleReel xmlns=\"http://www.smpte-ra.org/schemas/428-7/2010/DCST\" xmlns:xs=\"http://www.w3.org/2001/XMLSchema\">\n"
+               "  <Id>urn:uuid:a6c58cff-3e1e-4b38-acec-a42224475ef6</Id>\n"
+               "  <ContentTitleText>Test</ContentTitleText>\n"
+               "  <IssueDate>2016-04-01T03:52:00.000+00:00</IssueDate>\n"
+               "  <ReelNumber>1</ReelNumber>\n"
+               "  <Language>en</Language>\n"
+               "  <EditRate>24 1</EditRate>\n"
+               "  <TimeCodeRate>24</TimeCodeRate>\n"
+               "  <SubtitleList>\n"
+               "    <Font AspectAdjust=\"1.0\" Color=\"FFFFFFFF\" Effect=\"none\" EffectColor=\"FF000000\" ID=\"Arial\" Italic=\"no\" Script=\"normal\" Size=\"48\" Underline=\"no\" Weight=\"normal\">\n"
+               "      <Subtitle SpotNumber=\"1\" TimeIn=\"00:00:01:00\" TimeOut=\"00:00:09:00\" FadeUpTime=\"00:00:00:00\" FadeDownTime=\"00:00:00:00\">\n"
+               "        <Text Valign=\"bottom\" Vposition=\"80\">Top line</Text>\n"
+               "        <Text Valign=\"bottom\" Vposition=\"70\">Bottom line</Text>\n"
+               "      </Subtitle>\n"
+               "    </Font>\n"
+               "  </SubtitleList>\n"
                "</SubtitleReel>",
                {}
                );
index b2e98981c9cec82d01f029fd6d4990cdf3fc77dd..6a3dacc43fac2ce46c0bb42d6e39f711576da092 100644 (file)
@@ -1292,7 +1292,7 @@ BOOST_AUTO_TEST_CASE (verify_invalid_closed_caption_xml_size_in_bytes)
                        {
                                dcp::VerificationNote::Type::BV21_ERROR,
                                dcp::VerificationNote::Code::INVALID_CLOSED_CAPTION_XML_SIZE_IN_BYTES,
-                               string("372207"),
+                               string("419346"),
                                canonical(dir / "subs.mxf")
                        },
                        { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },
@@ -1332,7 +1332,7 @@ verify_timed_text_asset_too_large (string name)
        check_verify_result (
                { dir },
                {
-                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695136"), canonical(dir / "subs.mxf") },
+                       { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_SIZE_IN_BYTES, string("121695542"), canonical(dir / "subs.mxf") },
                        { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::INVALID_TIMED_TEXT_FONT_SIZE_IN_BYTES, string("121634816"), canonical(dir / "subs.mxf") },
                        { dcp::VerificationNote::Type::BV21_ERROR, dcp::VerificationNote::Code::MISSING_SUBTITLE_START_TIME, canonical(dir / "subs.mxf") },
                        { dcp::VerificationNote::Type::WARNING, dcp::VerificationNote::Code::INVALID_SUBTITLE_FIRST_TEXT_TIME },