#include "reel.h"
#include "reel_picture_asset.h"
#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
+#include "interop_subtitle_asset.h"
#include "mono_picture_asset.h"
#include "mono_picture_frame.h"
#include "stereo_picture_asset.h"
#include <xercesc/dom/DOMAttr.hpp>
#include <xercesc/dom/DOMErrorHandler.hpp>
#include <xercesc/framework/LocalFileInputSource.hpp>
+#include <xercesc/framework/MemBufInputSource.hpp>
#include <boost/noncopyable.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>
add("http://www.digicine.com/PROTO-ASDCP-CPL-20040511.xsd", "PROTO-ASDCP-CPL-20040511.xsd");
add("http://www.digicine.com/PROTO-ASDCP-PKL-20040311.xsd", "PROTO-ASDCP-PKL-20040311.xsd");
add("http://www.digicine.com/PROTO-ASDCP-AM-20040311.xsd", "PROTO-ASDCP-AM-20040311.xsd");
+ add("interop-subs", "DCSubtitle.v1.mattsson.xsd");
+ add("http://www.smpte-ra.org/schemas/428-7/2010/DCST.xsd", "SMPTE-428-7-2010-DCST.xsd");
}
InputSource* resolveEntity(XMLCh const *, XMLCh const * system_id)
boost::filesystem::path _xsd_dtd_directory;
};
-static
+
+static void
+parse (XercesDOMParser& parser, boost::filesystem::path xml)
+{
+ parser.parse(xml.string().c_str());
+}
+
+
+static void
+parse (XercesDOMParser& parser, std::string xml)
+{
+ xercesc::MemBufInputSource buf(reinterpret_cast<unsigned char const*>(xml.c_str()), xml.size(), "");
+ parser.parse(buf);
+}
+
+
+template <class T>
void
-validate_xml (boost::filesystem::path xml_file, boost::filesystem::path xsd_dtd_directory, list<VerificationNote>& notes)
+validate_xml (T xml, boost::filesystem::path xsd_dtd_directory, list<VerificationNote>& notes)
{
try {
XMLPlatformUtils::Initialize ();
schema["http://www.digicine.com/PROTO-ASDCP-CPL-20040511#"] = "PROTO-ASDCP-CPL-20040511.xsd";
schema["http://www.digicine.com/PROTO-ASDCP-PKL-20040311#"] = "PROTO-ASDCP-PKL-20040311.xsd";
schema["http://www.digicine.com/PROTO-ASDCP-AM-20040311#"] = "PROTO-ASDCP-AM-20040311.xsd";
+ schema["interop-subs"] = "DCSubtitle.v1.mattsson.xsd";
+ schema["http://www.smpte-ra.org/schemas/428-7/2010/DCST.xsd"] = "DCDMSubtitle-2010.xsd";
string locations;
for (map<string, string>::const_iterator i = schema.begin(); i != schema.end(); ++i) {
try {
parser.resetDocumentPool();
- parser.parse(xml_file.string().c_str());
+ parse(parser, xml);
} catch (XMLException& e) {
throw MiscError(xml_ch_to_string(e.getMessage()));
} catch (DOMException& e) {
VerificationNote::VERIFY_ERROR,
VerificationNote::XML_VALIDATION_ERROR,
i.message(),
- xml_file,
+ xml,
i.line()
)
);
}
+static void
+verify_main_subtitle_asset (
+ shared_ptr<const Reel> reel,
+ function<void (string, optional<boost::filesystem::path>)> stage,
+ boost::filesystem::path xsd_dtd_directory,
+ list<VerificationNote>& notes
+ )
+{
+ shared_ptr<ReelSubtitleAsset> reel_asset = reel->main_subtitle ();
+ stage ("Checking subtitle XML", reel->main_subtitle()->asset()->file());
+ /* Note: we must not use SubtitleAsset::xml_as_string() here as that will mean the data on disk
+ * gets passed through libdcp which may clean up and therefore hide errors.
+ */
+ validate_xml (reel->main_subtitle()->asset()->raw_xml(), xsd_dtd_directory, notes);
+}
+
+
list<VerificationNote>
dcp::verify (
vector<boost::filesystem::path> directories,
verify_main_picture_asset (dcp, reel, stage, progress, notes);
}
}
+
if (reel->main_sound() && reel->main_sound()->asset_ref().resolved()) {
verify_main_sound_asset (dcp, reel, stage, progress, notes);
}
+
+ if (reel->main_subtitle() && reel->main_subtitle()->asset_ref().resolved()) {
+ verify_main_subtitle_asset (reel, stage, xsd_dtd_directory, notes);
+ }
}
}
#include "openjpeg_image.h"
#include "mono_picture_asset.h"
#include "mono_picture_asset_writer.h"
+#include "interop_subtitle_asset.h"
+#include "smpte_subtitle_asset.h"
+#include "reel_subtitle_asset.h"
#include "compose.hpp"
#include <boost/test/unit_test.hpp>
#include <boost/foreach.hpp>
BOOST_REQUIRE_EQUAL (notes.size(), 0);
}
+
+/* DCP with valid Interop subtitles */
+BOOST_AUTO_TEST_CASE (verify_test18)
+{
+ boost::filesystem::path const dir("build/test/verify_test18");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/subs1.xml", dir / "subs.xml");
+ shared_ptr<dcp::InteropSubtitleAsset> asset(new dcp::InteropSubtitleAsset(dir / "subs.xml"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::INTEROP);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, "xsd");
+ BOOST_REQUIRE_EQUAL (notes.size(), 0);
+}
+
+
+/* DCP with broken Interop subtitles */
+BOOST_AUTO_TEST_CASE (verify_test19)
+{
+ boost::filesystem::path const dir("build/test/verify_test19");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/subs1.xml", dir / "subs.xml");
+ shared_ptr<dcp::InteropSubtitleAsset> asset(new dcp::InteropSubtitleAsset(dir / "subs.xml"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::INTEROP);
+
+ {
+ Editor e (dir / "subs.xml");
+ e.replace ("</ReelNumber>", "</ReelNumber><Foo></Foo>");
+ }
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, "xsd");
+ dump_notes(notes);
+ BOOST_REQUIRE_EQUAL (notes.size(), 2);
+ BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+ BOOST_CHECK_EQUAL (notes.back().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+}
+
+
+/* DCP with valid SMPTE subtitles */
+BOOST_AUTO_TEST_CASE (verify_test20)
+{
+ boost::filesystem::path const dir("build/test/verify_test20");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/subs.mxf", dir / "subs.mxf");
+ shared_ptr<dcp::SMPTESubtitleAsset> asset(new dcp::SMPTESubtitleAsset(dir / "subs.mxf"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::SMPTE);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, "xsd");
+ dump_notes (notes);
+ BOOST_REQUIRE_EQUAL (notes.size(), 0);
+}
+
+
+/* DCP with broken SMPTE subtitles */
+BOOST_AUTO_TEST_CASE (verify_test21)
+{
+ boost::filesystem::path const dir("build/test/verify_test21");
+ boost::filesystem::remove_all (dir);
+ boost::filesystem::create_directories (dir);
+ boost::filesystem::copy_file ("test/data/broken_smpte.mxf", dir / "subs.mxf");
+ shared_ptr<dcp::SMPTESubtitleAsset> asset(new dcp::SMPTESubtitleAsset(dir / "subs.mxf"));
+ shared_ptr<dcp::ReelAsset> reel_asset(new dcp::ReelSubtitleAsset(asset, dcp::Fraction(24, 1), 16 * 24, 0));
+ shared_ptr<dcp::Reel> reel(new dcp::Reel());
+ reel->add (reel_asset);
+ shared_ptr<dcp::CPL> cpl(new dcp::CPL("hello", dcp::FEATURE));
+ cpl->add (reel);
+ shared_ptr<dcp::DCP> dcp(new dcp::DCP(dir));
+ dcp->add (cpl);
+ dcp->write_xml (dcp::SMPTE);
+
+ vector<boost::filesystem::path> dirs;
+ dirs.push_back (dir);
+ list<dcp::VerificationNote> notes = dcp::verify (dirs, &stage, &progress, "xsd");
+ dump_notes (notes);
+ BOOST_REQUIRE_EQUAL (notes.size(), 2);
+ BOOST_CHECK_EQUAL (notes.front().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+ BOOST_CHECK_EQUAL (notes.back().code(), dcp::VerificationNote::XML_VALIDATION_ERROR);
+}
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+\r
+<!--\r
+Copyright (c), Society of Motion Pictures and Television Engineers. All rights reserved.\r
+Redistribution and use in source and binary forms, with or without modification, are permitted\r
+provided that the following conditions are met: 1. Redistributions of source code must retain \r
+the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions\r
+in binary form must reproduce the above copyright notice, this list of conditions and the following\r
+disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the\r
+name of the copyright holder nor the names of its contributors may be used to endorse or promote \r
+products derived from this software without specific prior written permission. \r
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED \r
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR \r
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE \r
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT \r
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS \r
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR \r
+TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF \r
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+-->\r
+\r
+<!--\r
+This document is an element of SMPTE ST 2067-100:2014, which is available at http://standards.smpte.org.\r
+To ensure interoperability, users are encouraged to: (a) retain this notice; (b) retrieve the recent versions \r
+of this document and its companion defining engineering document. In particular, this document alone might not \r
+be sufficient to ensure interoperability; (c) highlight and explain any modification they make to this document;\r
+and (d) report issues to the Director of Standards at https://www.smpte.org/about/staff.\r
+-->\r
+\r
+<xs:schema\r
+ targetNamespace="http://www.smpte-ra.org/schemas/428-7/2010/DCST"\r
+ xmlns:dcst="http://www.smpte-ra.org/schemas/428-7/2010/DCST"\r
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"\r
+ elementFormDefault="qualified" attributeFormDefault="unqualified">\r
+\r
+<!-- This version of the schema was produced for publication with ST 428-7:2014. It has been corrected from its original 2010 published version. Refer to ST 428-7:2014 Section 8 for additional details. -->\r
+\r
+\r
+ <!-- SubtitleReel -->\r
+ <xs:element name="SubtitleReel" type="dcst:SubtitleReelType"/>\r
+ <xs:complexType name="SubtitleReelType">\r
+ <xs:sequence>\r
+ <xs:element name="Id" type="dcst:UUID"/>\r
+ <xs:element name="ContentTitleText" type="dcst:UserText"/>\r
+ <xs:element name="AnnotationText" type="dcst:UserText" minOccurs="0"/>\r
+ <xs:element name="IssueDate" type="xs:dateTime"/>\r
+ <xs:element name="ReelNumber" type="xs:positiveInteger" minOccurs="0"/>\r
+ <xs:element name="Language" type="xs:language" minOccurs="0" default="en"/>\r
+ <xs:element name="EditRate" type="dcst:RationalType"/>\r
+ <xs:element name="TimeCodeRate" type="xs:positiveInteger"/>\r
+ <xs:element name="StartTime" type="dcst:TimeCodeType" minOccurs="0"/>\r
+ <xs:element name="DisplayType" type="dcst:scopedTokenType" minOccurs="0"/>\r
+ <xs:element name="LoadFont" minOccurs="0" maxOccurs="unbounded">\r
+ <xs:complexType>\r
+ <xs:simpleContent>\r
+ <xs:extension base="xs:anyURI">\r
+ <xs:attribute name="ID" type="xs:string" use="optional"/>\r
+ </xs:extension>\r
+ </xs:simpleContent>\r
+ </xs:complexType>\r
+ </xs:element>\r
+ <xs:element name="SubtitleList">\r
+ <xs:complexType>\r
+ <xs:choice maxOccurs="unbounded">\r
+ <xs:element name="Subtitle" type="dcst:SubtitleType"/>\r
+ <xs:element name="Font">\r
+ <xs:complexType mixed="true">\r
+ <xs:complexContent mixed="true">\r
+ <xs:extension base="dcst:FontType">\r
+ <xs:sequence>\r
+ <xs:element name="Subtitle" type="dcst:SubtitleType" maxOccurs="unbounded"/>\r
+ </xs:sequence>\r
+ </xs:extension>\r
+ </xs:complexContent>\r
+ </xs:complexType>\r
+ </xs:element>\r
+ </xs:choice>\r
+ </xs:complexType>\r
+ </xs:element>\r
+ </xs:sequence>\r
+ </xs:complexType>\r
+\r
+ <!-- Subtitle -->\r
+ <xs:complexType name="SubtitleType">\r
+ <xs:choice maxOccurs="unbounded">\r
+ <xs:element name="Text" type="dcst:TextType"/>\r
+ <xs:element name="Image" type="dcst:ImageType"/>\r
+ <xs:element name="Font">\r
+ <xs:complexType mixed="true">\r
+ <xs:complexContent mixed="true">\r
+ <xs:extension base="dcst:FontType">\r
+ <xs:sequence>\r
+ <xs:element name="Text" type="dcst:TextType" maxOccurs="unbounded"/>\r
+ </xs:sequence>\r
+ </xs:extension>\r
+ </xs:complexContent>\r
+ </xs:complexType>\r
+ </xs:element>\r
+ </xs:choice>\r
+ <xs:attribute name="SpotNumber" type="xs:string" use="optional"/>\r
+ <xs:attribute name="TimeIn" type="dcst:TimeCodeType" use="required"/>\r
+ <xs:attribute name="TimeOut" type="dcst:TimeCodeType" use="required"/>\r
+ <xs:attribute name="FadeUpTime" type="dcst:TimeCodeType" use="optional"/>\r
+ <xs:attribute name="FadeDownTime" type="dcst:TimeCodeType" use="optional"/>\r
+ </xs:complexType>\r
+\r
+ <!-- Image -->\r
+ <xs:complexType name="ImageType" mixed="false">\r
+ <xs:simpleContent>\r
+ <xs:extension base="xs:anyURI">\r
+ <xs:attribute name="Halign" use="optional" default="center">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="center"/>\r
+ <xs:enumeration value="left"/>\r
+ <xs:enumeration value="right"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Hposition" use="optional" default="0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-100"/>\r
+ <xs:maxInclusive value="100"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Valign" use="optional" default="center">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="center"/>\r
+ <xs:enumeration value="bottom"/>\r
+ <xs:enumeration value="top"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Vposition" use="optional" default="0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-100"/>\r
+ <xs:maxInclusive value="100"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ </xs:extension>\r
+ </xs:simpleContent>\r
+ </xs:complexType>\r
+\r
+ <!-- Font -->\r
+ <xs:complexType name="FontType" mixed="true">\r
+ <xs:attribute name="Script" use="optional" default="normal">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="normal"/>\r
+ <xs:enumeration value="super"/>\r
+ <xs:enumeration value="sub"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Effect" use="optional" default="shadow">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="none"/>\r
+ <xs:enumeration value="border"/>\r
+ <xs:enumeration value="shadow"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Italic" use="optional" default="no">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="yes"/>\r
+ <xs:enumeration value="no"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Underline" use="optional" default="no">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="yes"/>\r
+ <xs:enumeration value="no"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Weight" use="optional" default="normal">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="bold"/>\r
+ <xs:enumeration value="normal"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="ID" type="xs:string" use="optional"/>\r
+ <xs:attribute name="Color" use="optional" default="FFFFFFFF">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:hexBinary">\r
+ <xs:length value="4"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="EffectColor" use="optional" default="FF000000">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:hexBinary">\r
+ <xs:length value="4"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Size" use="optional" default="42">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:positiveInteger"/>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="AspectAdjust" use="optional" default="1.0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="0.25"/>\r
+ <xs:maxInclusive value="4.0"/>\r
+ </xs:restriction> \r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Spacing" use="optional" default="0.0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-1.0"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ </xs:complexType>\r
+\r
+ <!-- Text -->\r
+ <xs:complexType name="TextType" mixed="true">\r
+ <xs:choice minOccurs="0" maxOccurs="unbounded">\r
+ <xs:element name="Font" type="dcst:FontType"/>\r
+ <xs:element name="Ruby" type="dcst:RubyType"/>\r
+ <xs:element name="Space" type="dcst:SpaceType"/>\r
+ <xs:element name="HGroup" type="xs:string"/>\r
+ <xs:element name="Rotate" type="dcst:RotateType"/>\r
+ </xs:choice>\r
+ <xs:attribute name="Halign" use="optional" default="center">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="center"/>\r
+ <xs:enumeration value="left"/>\r
+ <xs:enumeration value="right"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Hposition" use="optional" default="0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-100"/>\r
+ <xs:maxInclusive value="100"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Valign" use="optional" default="center">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="center"/>\r
+ <xs:enumeration value="bottom"/>\r
+ <xs:enumeration value="top"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Vposition" use="optional" default="0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-100"/>\r
+ <xs:maxInclusive value="100"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Direction" use="optional" default="ltr">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="ltr"/>\r
+ <xs:enumeration value="rtl"/>\r
+ <xs:enumeration value="ttb"/>\r
+ <xs:enumeration value="btt"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ </xs:complexType>\r
+\r
+ <!-- Rational Type -->\r
+ <xs:simpleType name="RationalType">\r
+ <xs:restriction>\r
+ <xs:simpleType>\r
+ <xs:list itemType="xs:long"/>\r
+ </xs:simpleType>\r
+ <xs:length value="2"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+\r
+ <!-- TimeCode Type -->\r
+ <xs:simpleType name="TimeCodeType">\r
+ <xs:restriction base="xs:string">\r
+ <xs:pattern value="[0-2][0-9]:[0-5][0-9]:[0-5][0-9]:[0-9]+"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+\r
+ <!-- Ruby Type -->\r
+ <xs:complexType name="RubyType">\r
+ <xs:sequence>\r
+ <xs:element name="Rb" type="xs:string"/>\r
+ <xs:element name="Rt">\r
+ <xs:complexType>\r
+ <xs:simpleContent>\r
+ <xs:extension base="xs:string">\r
+ <xs:attribute name="Size" use="optional" default="0.5">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minExclusive value="0"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Position" use="optional" default="before">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="before"/>\r
+ <xs:enumeration value="after"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Offset" use="optional" default="0.0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-1.0"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="Spacing" use="optional" default="0.0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-1.0"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ <xs:attribute name="AspectAdjust" use="optional" default="1.0">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="0.25"/>\r
+ <xs:maxInclusive value="4.0"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ </xs:extension>\r
+ </xs:simpleContent>\r
+ </xs:complexType>\r
+ </xs:element>\r
+ </xs:sequence>\r
+ </xs:complexType>\r
+\r
+ <!-- Rotate Type -->\r
+ <xs:complexType name="RotateType">\r
+ <xs:simpleContent>\r
+ <xs:extension base="xs:string">\r
+ <xs:attribute name="Direction" use="optional" default="none">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:string">\r
+ <xs:enumeration value="none"/>\r
+ <xs:enumeration value="left"/>\r
+ <xs:enumeration value="right"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ </xs:extension>\r
+ </xs:simpleContent>\r
+ </xs:complexType>\r
+\r
+ <!-- Space Type -->\r
+ <xs:complexType name="SpaceType">\r
+ <xs:simpleContent>\r
+ <xs:extension base="dcst:EmptyElement">\r
+ <xs:attribute name="Size" use="optional" default="0.5">\r
+ <xs:simpleType>\r
+ <xs:restriction base="xs:decimal">\r
+ <xs:minInclusive value="-1.0"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+ </xs:attribute>\r
+ </xs:extension>\r
+ </xs:simpleContent>\r
+ </xs:complexType>\r
+\r
+ <!-- UUID Type -->\r
+ <xs:simpleType name="UUID">\r
+ <xs:restriction base="xs:anyURI">\r
+ <xs:pattern value="urn:uuid:[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+\r
+ <!-- UserText Type -->\r
+ <xs:complexType name="UserText">\r
+ <xs:simpleContent>\r
+ <xs:extension base="xs:string">\r
+ <xs:attribute name="language" type="xs:language" use="optional" default="en"/>\r
+ </xs:extension>\r
+ </xs:simpleContent>\r
+ </xs:complexType>\r
+\r
+ <!-- Scoped Token Type -->\r
+ <xs:complexType name="scopedTokenType">\r
+ <xs:simpleContent>\r
+ <xs:extension base="xs:token">\r
+ <xs:attribute name="scope" type="xs:anyURI" use="optional"/>\r
+ </xs:extension>\r
+ </xs:simpleContent>\r
+ </xs:complexType>\r
+\r
+ <!-- EmptyElement Type -->\r
+ <xs:simpleType name="EmptyElement">\r
+ <xs:restriction base="xs:string">\r
+ <xs:length value="0"/>\r
+ </xs:restriction>\r
+ </xs:simpleType>\r
+</xs:schema>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <xs:element name="DCSubtitle">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="SubtitleID" type="UUIDType"/>
+ <xs:element name="MovieTitle" type="xs:string"/>
+ <xs:element name="ReelNumber" type="xs:string"/>
+ <xs:element name="Language" type="xs:string"/>
+ <xs:element ref="LoadFont" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="Font" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element ref="Subtitle" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <xs:attribute name="Version" use="required">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="1.0"/>
+ <xs:enumeration value="1.1"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="LoadFont">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="spaceType">
+ <xs:attribute name="Id" use="required" type="xs:string"/>
+ <xs:attribute name="URI" use="required" type="xs:anyURI"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Font">
+ <xs:complexType mixed="true">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="Font"/>
+ <xs:element ref="Subtitle"/>
+ <xs:element ref="Text"/>
+ <xs:element ref="Image"/>
+ </xs:choice>
+ <xs:attribute name="Id" type="xs:string"/>
+ <xs:attribute name="Color" type="fontColorType"/>
+ <xs:attribute name="Effect">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="border"/>
+ <xs:enumeration value="shadow"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="EffectColor" type="fontColorType"/>
+ <xs:attribute name="Italic" type="yesNoType"/>
+ <xs:attribute name="Script">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="normal"/>
+ <xs:enumeration value="super"/>
+ <xs:enumeration value="sub"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="Size" type="xs:positiveInteger"/>
+ <xs:attribute name="AspectAdjust">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ <xs:minInclusive value="0.25"/>
+ <xs:maxInclusive value="4.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="Underlined" type="yesNoType"/>
+ <xs:attribute name="Weight">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="bold"/>
+ <xs:enumeration value="normal"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="Spacing" type="spacingType"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Subtitle">
+ <xs:complexType>
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="Font"/>
+ <xs:element ref="Text"/>
+ <xs:element ref="Image"/>
+ </xs:choice>
+ <xs:attribute name="SpotNumber" use="required" type="xs:string"/>
+ <xs:attribute name="TimeIn" use="required" type="timeType"/>
+ <xs:attribute name="TimeOut" use="required" type="timeType"/>
+ <xs:attribute name="FadeUpTime" type="fadeTimeType"/>
+ <xs:attribute name="FadeDownTime" type="fadeTimeType"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Text">
+ <xs:complexType mixed="true">
+ <xs:choice minOccurs="0" maxOccurs="unbounded">
+ <xs:element ref="Font"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="Ruby"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="Space"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="HGroup"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="Rotate"/>
+ </xs:choice>
+ <xs:attribute name="Direction">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="horizontal"/>
+ <xs:enumeration value="vertical"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="HAlign" type="hAlignType"/>
+ <xs:attribute name="HPosition" type="positionType"/>
+ <xs:attribute name="VAlign" type="vAlignType" />
+ <xs:attribute name="VPosition" type="positionType"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Ruby">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="Rb"/>
+ <xs:element ref="Rt"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Rb" type="xs:string"/>
+ <xs:element name="Rt">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="Size" type="sizeType"/>
+ <xs:attribute name="Position">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="before"/>
+ <xs:enumeration value="after"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ <xs:attribute name="Offset" type="spacingType"/>
+ <xs:attribute name="Spacing" type="spacingType"/>
+ <xs:attribute name="AspectAdjust">
+ <xs:simpleType>
+ <xs:restriction base="xs:decimal">
+ <xs:minInclusive value="0.25"/>
+ <xs:maxInclusive value="4.0"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Space">
+ <xs:complexType>
+ <xs:attribute name="Size" type="sizeType"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="HGroup" type="xs:string"/>
+ <xs:element name="Rotate">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="Direction">
+ <xs:simpleType>
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="right"/>
+ <xs:enumeration value="left"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="Image">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:anyURI">
+ <xs:attribute name="HAlign" type="hAlignType"/>
+ <xs:attribute name="HPosition" type="positionType"/>
+ <xs:attribute name="VAlign" type="vAlignType"/>
+ <xs:attribute name="VPosition" type="positionType"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+ <xs:simpleType name="spaceType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="\s*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="UUIDType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="\s*[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\s*"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="yesNoType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="yes"/>
+ <xs:enumeration value="no"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="hAlignType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="left"/>
+ <xs:enumeration value="right"/>
+ <xs:enumeration value="center"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="vAlignType">
+ <xs:restriction base="xs:string">
+ <xs:enumeration value="top"/>
+ <xs:enumeration value="bottom"/>
+ <xs:enumeration value="center"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="spacingType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="-?(\d+|\d+\.\d+)em"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="sizeType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="(\d+|\d+\.\d+)em"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="timeType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="\d\d:\d\d:\d\d(:(([0-1][0-9][0-9])|([2][0-4][0-9]))|(\.\d{1,3}))"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="fadeTimeType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="(\d\d:\d\d:\d\d(:|\.)(\d){1,3})|(\d){1,3}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="fontColorType">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9A-Fa-f]{8}"/>
+ </xs:restriction>
+ </xs:simpleType>
+ <xs:simpleType name="positionType">
+ <xs:restriction base="xs:decimal">
+ <xs:minInclusive value="-100"/>
+ <xs:maxInclusive value="100"/>
+ </xs:restriction>
+ </xs:simpleType>
+</xs:schema>