diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-03-20 21:02:55 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-03-24 00:29:31 +0100 |
| commit | 8edb46702b372b6e672d0ac8f810e151e1aa5707 (patch) | |
| tree | e2a458fc456b3bd98982e6e31c0ec7589ab25274 | |
| parent | 0322c4604bf79c11a99dcd929a6f74685a0a4e31 (diff) | |
Read/write subtitle variable Z.v1.10.16
| -rw-r--r-- | src/text.cc | 17 | ||||
| -rw-r--r-- | src/text.h | 13 | ||||
| -rw-r--r-- | src/text_asset.cc | 52 | ||||
| -rw-r--r-- | src/text_asset.h | 5 | ||||
| -rw-r--r-- | src/text_asset_internal.cc | 46 | ||||
| -rw-r--r-- | src/text_asset_internal.h | 36 | ||||
| -rw-r--r-- | src/text_image.cc | 8 | ||||
| -rw-r--r-- | src/text_image.h | 2 | ||||
| -rw-r--r-- | src/text_string.cc | 8 | ||||
| -rw-r--r-- | src/text_string.h | 2 | ||||
| -rw-r--r-- | test/data/subtitles_with_vZani.xml | 61 | ||||
| -rw-r--r-- | test/data/subtitles_with_vZani_parsed.xml | 59 | ||||
| -rw-r--r-- | test/decryption_test.cc | 2 | ||||
| -rw-r--r-- | test/interop_subtitle_test.cc | 31 | ||||
| -rw-r--r-- | test/load_variable_z_test.cc | 10 | ||||
| -rw-r--r-- | test/shared_subtitle_test.cc | 8 | ||||
| -rw-r--r-- | test/smpte_subtitle_test.cc | 25 | ||||
| -rw-r--r-- | test/test.cc | 1 | ||||
| -rw-r--r-- | test/verify_test.cc | 6 |
19 files changed, 373 insertions, 19 deletions
diff --git a/src/text.cc b/src/text.cc index 158af38c..8f72b953 100644 --- a/src/text.cc +++ b/src/text.cc @@ -44,6 +44,9 @@ using std::shared_ptr; +using std::string; +using std::vector; +using boost::optional; using namespace dcp; @@ -56,6 +59,7 @@ Text::Text( float v_position, VAlign v_align, float z_position, + vector<VariableZPosition> variable_z_positions, Time fade_up_time, Time fade_down_time ) @@ -66,6 +70,7 @@ Text::Text( , _v_position (v_position) , _v_align (v_align) , _z_position(z_position) + , _variable_z_positions(variable_z_positions) , _fade_up_time (fade_up_time) , _fade_down_time (fade_down_time) { @@ -117,6 +122,11 @@ Text::equals(shared_ptr<const Text> other, EqualityOptions const& options, NoteH same = false; } + if (variable_z_positions() != other->variable_z_positions()) { + note(NoteType::ERROR, "text variable Z positions differ"); + same = false; + } + if (fade_up_time() != other->fade_up_time()) { note(NoteType::ERROR, "text fade-up times differ"); same = false; @@ -129,3 +139,10 @@ Text::equals(shared_ptr<const Text> other, EqualityOptions const& options, NoteH return same; } + + +bool dcp::operator==(Text::VariableZPosition a, Text::VariableZPosition b) +{ + return a.position == b.position && a.duration == b.duration; +} + @@ -97,6 +97,10 @@ public: int64_t duration; }; + std::vector<VariableZPosition> variable_z_positions() const { + return _variable_z_positions; + } + Time fade_up_time () const { return _fade_up_time; } @@ -128,6 +132,10 @@ public: _z_position = z; } + void set_variable_z_positions(std::vector<VariableZPosition> z) { + _variable_z_positions = std::move(z); + } + void set_fade_up_time (Time t) { _fade_up_time = t; } @@ -148,6 +156,7 @@ protected: float v_position, VAlign v_align, float z_position, + std::vector<VariableZPosition> variable_z, Time fade_up_time, Time fade_down_time ); @@ -165,11 +174,15 @@ protected: float _v_position = 0; VAlign _v_align = VAlign::CENTER; float _z_position = 0; + std::vector<VariableZPosition> _variable_z_positions; Time _fade_up_time; Time _fade_down_time; }; +bool operator==(Text::VariableZPosition a, Text::VariableZPosition b); + + } diff --git a/src/text_asset.cc b/src/text_asset.cc index c3341452..41690d93 100644 --- a/src/text_asset.cc +++ b/src/text_asset.cc @@ -206,6 +206,10 @@ TextAsset::position_align(TextAsset::ParseState& ps, xmlpp::Element const * node if (auto zp = optional_number_attribute<float>(node, "Zposition")) { ps.z_position = zp.get() / 100; } + + if (auto variable_z = optional_string_attribute(node, "VariableZ")) { + ps.variable_z = *variable_z; + } } @@ -248,6 +252,14 @@ TextAsset::subtitle_node_state(xmlpp::Element const * node, optional<int> tcr) c ps.out = Time (string_attribute(node, "TimeOut"), tcr); ps.fade_up_time = fade_time (node, "FadeUpTime", tcr); ps.fade_down_time = fade_time (node, "FadeDownTime", tcr); + + for (auto child: node->get_children()) { + auto element = dynamic_cast<xmlpp::Element const*>(child); + if (element && element->get_name() == "LoadVariableZ") { + ps.load_variable_z.push_back(LoadVariableZ(element)); + } + } + return ps; } @@ -287,6 +299,8 @@ TextAsset::parse_texts(xmlpp::Element const * node, vector<ParseState>& state, o state.push_back (ParseState ()); } else if (node->get_name() == "Image") { state.push_back (image_node_state (node)); + } else if (node->get_name() == "LoadVariableZ") { + return; } else { throw XMLError ("unexpected node " + node->get_name()); } @@ -453,6 +467,9 @@ TextAsset::maybe_add_text( if (i.z_position) { ps.z_position = i.z_position.get(); } + if (i.variable_z) { + ps.variable_z = i.variable_z.get(); + } if (i.direction) { ps.direction = i.direction.get(); } @@ -471,6 +488,13 @@ TextAsset::maybe_add_text( if (i.type) { ps.type = i.type.get(); } + for (auto j: i.load_variable_z) { + /* j is a LoadVariableZ from this "sub" ParseState. See if we should add it to the end result */ + auto const k = std::find_if(ps.load_variable_z.begin(), ps.load_variable_z.end(), [j](LoadVariableZ const& z) { return j.id() == z.id(); }); + if (k == ps.load_variable_z.end()) { + ps.load_variable_z.push_back(j); + } + } } if (!ps.in || !ps.out) { @@ -482,6 +506,12 @@ TextAsset::maybe_add_text( switch (ps.type.get()) { case ParseState::Type::TEXT: + { + vector<Text::VariableZPosition> variable_z; + auto iter = std::find_if(ps.load_variable_z.begin(), ps.load_variable_z.end(), [&ps](LoadVariableZ const& z) { return z.id() == ps.variable_z; }); + if (iter != ps.load_variable_z.end()) { + variable_z = iter->positions(); + } _texts.push_back ( make_shared<TextString>( ps.font_id, @@ -498,6 +528,7 @@ TextAsset::maybe_add_text( ps.v_position.get_value_or(0), ps.v_align.get_value_or(VAlign::CENTER), ps.z_position.get_value_or(0), + variable_z, ps.direction.get_value_or (Direction::LTR), text, ps.effect.get_value_or (Effect::NONE), @@ -509,6 +540,7 @@ TextAsset::maybe_add_text( ) ); break; + } case ParseState::Type::IMAGE: { switch (standard) { @@ -530,6 +562,12 @@ TextAsset::maybe_add_text( break; } + vector<Text::VariableZPosition> variable_z; + auto iter = std::find_if(ps.load_variable_z.begin(), ps.load_variable_z.end(), [&ps](LoadVariableZ const& z) { return ps.variable_z && z.id() == *ps.variable_z; }); + if (iter != ps.load_variable_z.end()) { + variable_z = iter->positions(); + } + /* Add a text with no image data and we'll fill that in later */ _texts.push_back( make_shared<TextImage>( @@ -542,6 +580,7 @@ TextAsset::maybe_add_text( ps.v_position.get_value_or(0), ps.v_align.get_value_or(VAlign::CENTER), ps.z_position.get_value_or(0), + variable_z, ps.fade_up_time.get_value_or(Time()), ps.fade_down_time.get_value_or(Time()) ) @@ -747,6 +786,7 @@ TextAsset::texts_as_xml(xmlpp::Element* xml_root, int time_code_rate, Standard s float last_v_position; float last_z_position; Direction last_direction; + int load_variable_z_index = 1; for (auto i: sorted) { if (!subtitle || @@ -783,6 +823,7 @@ TextAsset::texts_as_xml(xmlpp::Element* xml_root, int time_code_rate, Standard s is->v_align(), is->v_position(), is->z_position(), + subtitle->find_or_add_variable_z_positions(is->variable_z_positions(), load_variable_z_index), is->direction(), is->rubies() ); @@ -802,7 +843,16 @@ TextAsset::texts_as_xml(xmlpp::Element* xml_root, int time_code_rate, Standard s if (auto ii = dynamic_pointer_cast<TextImage>(i)) { text.reset (); subtitle->children.push_back ( - make_shared<order::Image>(subtitle, ii->id(), ii->png_image(), ii->h_align(), ii->h_position(), ii->v_align(), ii->v_position(), ii->z_position()) + make_shared<order::Image>( + subtitle, ii->id(), + ii->png_image(), + ii->h_align(), + ii->h_position(), + ii->v_align(), + ii->v_position(), + ii->z_position(), + subtitle->find_or_add_variable_z_positions(ii->variable_z_positions(), load_variable_z_index) + ) ); } } diff --git a/src/text_asset.h b/src/text_asset.h index 4d739027..113896f8 100644 --- a/src/text_asset.h +++ b/src/text_asset.h @@ -44,6 +44,7 @@ #include "array_data.h" #include "asset.h" #include "dcp_time.h" +#include "load_variable_z.h" #include "subtitle_standard.h" #include "text_string.h" #include <libcxml/cxml.h> @@ -156,6 +157,7 @@ protected: boost::optional<float> v_position; boost::optional<VAlign> v_align; boost::optional<float> z_position; + boost::optional<std::string> variable_z; boost::optional<Direction> direction; boost::optional<Time> in; boost::optional<Time> out; @@ -167,6 +169,8 @@ protected: }; boost::optional<Type> type; float space_before = 0; + + std::vector<LoadVariableZ> load_variable_z; }; void parse_texts(xmlpp::Element const * node, std::vector<ParseState>& state, boost::optional<int> tcr, Standard standard); @@ -181,6 +185,7 @@ protected: /** All our texts, in no particular order */ std::vector<std::shared_ptr<Text>> _texts; + std::vector<LoadVariableZ> _load_variable_z; class Font { diff --git a/src/text_asset_internal.cc b/src/text_asset_internal.cc index 549bbec9..4ae5dbfe 100644 --- a/src/text_asset_internal.cc +++ b/src/text_asset_internal.cc @@ -44,9 +44,12 @@ #include <cmath> +using std::dynamic_pointer_cast; using std::string; using std::map; using std::shared_ptr; +using std::vector; +using boost::optional; using namespace dcp; @@ -166,7 +169,16 @@ order::Part::write_xml (xmlpp::Element* parent, order::Context& context) const static void -position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, float h_position, VAlign v_align, float v_position, float z_position) +position_align( + xmlpp::Element* e, + order::Context& context, + HAlign h_align, + float h_position, + VAlign v_align, + float v_position, + float z_position, + optional<string> variable_z + ) { if (h_align != HAlign::CENTER) { if (context.standard == Standard::SMPTE) { @@ -207,6 +219,10 @@ position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, floa if (fabs(z_position) > ALIGN_EPSILON && context.standard == Standard::SMPTE) { e->set_attribute("Zposition", fmt::format("{:.6}", z_position * 100)); } + + if (variable_z) { + e->set_attribute("VariableZ", *variable_z); + } } @@ -215,7 +231,7 @@ order::Text::as_xml (xmlpp::Element* parent, Context& context) const { auto e = cxml::add_child(parent, "Text"); - position_align(e, context, _h_align, _h_position, _v_align, _v_position, _z_position); + position_align(e, context, _h_align, _h_position, _v_align, _v_position, _z_position, _variable_z); /* Interop only supports "horizontal" or "vertical" for direction, so only write this for SMPTE. @@ -240,6 +256,24 @@ order::Text::as_xml (xmlpp::Element* parent, Context& context) const } +optional<string> +order::Subtitle::find_or_add_variable_z_positions(vector<dcp::Text::VariableZPosition> const& positions, int& load_variable_z_index) +{ + if (positions.empty()) { + return {}; + } + + auto iter = std::find_if(_load_variable_z.begin(), _load_variable_z.end(), [positions](LoadVariableZ const& load) { return positions == load.positions(); }); + if (iter == _load_variable_z.end()) { + auto const id = fmt::format("Zvector{}", load_variable_z_index++); + _load_variable_z.push_back(LoadVariableZ(id, positions)); + return id; + } + + return iter->id(); +} + + xmlpp::Element* order::Subtitle::as_xml (xmlpp::Element* parent, Context& context) const { @@ -254,6 +288,11 @@ order::Subtitle::as_xml (xmlpp::Element* parent, Context& context) const e->set_attribute("FadeUpTime", fmt::to_string(_fade_up.as_editable_units_ceil(context.time_code_rate))); e->set_attribute("FadeDownTime", fmt::to_string(_fade_down.as_editable_units_ceil(context.time_code_rate))); } + + for (auto const& vz: _load_variable_z) { + vz.as_xml(cxml::add_child(e, "LoadVariableZ")); + } + return e; } @@ -277,7 +316,7 @@ order::Image::as_xml (xmlpp::Element* parent, Context& context) const { auto e = cxml::add_child(parent, "Image"); - position_align(e, context, _h_align, _h_position, _v_align, _v_position, _z_position); + position_align(e, context, _h_align, _h_position, _v_align, _v_position, _z_position, _variable_z); if (context.standard == Standard::SMPTE) { e->add_child_text ("urn:uuid:" + _id); } else { @@ -286,3 +325,4 @@ order::Image::as_xml (xmlpp::Element* parent, Context& context) const return e; } + diff --git a/src/text_asset_internal.h b/src/text_asset_internal.h index ddbc8833..2dfccce9 100644 --- a/src/text_asset_internal.h +++ b/src/text_asset_internal.h @@ -44,6 +44,7 @@ #include "array_data.h" #include "dcp_time.h" #include "h_align.h" +#include "load_variable_z.h" #include "raw_convert.h" #include "v_align.h" #include "warnings.h" @@ -146,25 +147,41 @@ private: class Text : public Part { public: - Text(std::shared_ptr<Part> parent, HAlign h_align, float h_position, VAlign v_align, float v_position, float z_position, Direction direction, std::vector<Ruby> rubies) + Text( + std::shared_ptr<Part> parent, + HAlign h_align, + float h_position, + VAlign v_align, + float v_position, + float z_position, + boost::optional<std::string> variable_z, + Direction direction, + std::vector<Ruby> rubies + ) : Part (parent) , _h_align (h_align) , _h_position (h_position) , _v_align (v_align) , _v_position (v_position) , _z_position(z_position) + , _variable_z(variable_z) , _direction (direction) , _rubies(rubies) {} xmlpp::Element* as_xml (xmlpp::Element* parent, Context& context) const override; + boost::optional<std::string> variable_z() { + return _variable_z; + } + private: HAlign _h_align; float _h_position; VAlign _v_align; float _v_position; float _z_position; + boost::optional<std::string> _variable_z; Direction _direction; std::vector<Ruby> _rubies; }; @@ -181,6 +198,8 @@ public: , _fade_down (fade_down) {} + boost::optional<std::string> find_or_add_variable_z_positions(std::vector<dcp::Text::VariableZPosition> const& positions, int& load_variable_z_index); + xmlpp::Element* as_xml (xmlpp::Element* parent, Context& context) const override; private: @@ -188,13 +207,24 @@ private: Time _out; Time _fade_up; Time _fade_down; + std::vector<LoadVariableZ> _load_variable_z; }; class Image : public Part { public: - Image (std::shared_ptr<Part> parent, std::string id, ArrayData png_data, HAlign h_align, float h_position, VAlign v_align, float v_position, float z_position) + Image( + std::shared_ptr<Part> parent, + std::string id, + ArrayData png_data, + HAlign h_align, + float h_position, + VAlign v_align, + float v_position, + float z_position, + boost::optional<std::string> variable_z + ) : Part (parent) , _png_data (png_data) , _id (id) @@ -203,6 +233,7 @@ public: , _v_align (v_align) , _v_position (v_position) , _z_position(z_position) + , _variable_z(variable_z) {} xmlpp::Element* as_xml (xmlpp::Element* parent, Context& context) const override; @@ -215,6 +246,7 @@ private: VAlign _v_align; float _v_position; float _z_position; + boost::optional<std::string> _variable_z; }; diff --git a/src/text_image.cc b/src/text_image.cc index 7a6c4222..119a6301 100644 --- a/src/text_image.cc +++ b/src/text_image.cc @@ -47,6 +47,8 @@ using std::dynamic_pointer_cast; using std::ostream; using std::shared_ptr; using std::string; +using std::vector; +using boost::optional; using namespace dcp; @@ -59,10 +61,11 @@ TextImage::TextImage( float v_position, VAlign v_align, float z_position, + vector<VariableZPosition> variable_z_positions, Time fade_up_time, Time fade_down_time ) - : Text(in, out, h_position, h_align, v_position, v_align, z_position, fade_up_time, fade_down_time) + : Text(in, out, h_position, h_align, v_position, v_align, z_position, variable_z_positions, fade_up_time, fade_down_time) , _png_image (png_image) , _id (make_uuid ()) { @@ -80,10 +83,11 @@ TextImage::TextImage( float v_position, VAlign v_align, float z_position, + vector<VariableZPosition> variable_z_positions, Time fade_up_time, Time fade_down_time ) - : Text(in, out, h_position, h_align, v_position, v_align, z_position, fade_up_time, fade_down_time) + : Text(in, out, h_position, h_align, v_position, v_align, z_position, variable_z_positions, fade_up_time, fade_down_time) , _png_image (png_image) , _id (id) { diff --git a/src/text_image.h b/src/text_image.h index 1f1e464e..5b78f380 100644 --- a/src/text_image.h +++ b/src/text_image.h @@ -66,6 +66,7 @@ public: float v_position, VAlign v_align, float z_position, + std::vector<VariableZPosition> variable_z_positions, Time fade_up_time, Time fade_down_time ); @@ -80,6 +81,7 @@ public: float v_position, VAlign v_align, float z_position, + std::vector<VariableZPosition> variable_z_positions, Time fade_up_time, Time fade_down_time ); diff --git a/src/text_string.cc b/src/text_string.cc index 32f9e4ed..12e86fce 100644 --- a/src/text_string.cc +++ b/src/text_string.cc @@ -69,6 +69,7 @@ TextString::TextString( float v_position, VAlign v_align, float z_position, + vector<VariableZPosition> variable_z_positions, Direction direction, string text, Effect effect, @@ -78,7 +79,7 @@ TextString::TextString( float space_before, vector<Ruby> rubies ) - : Text(in, out, h_position, h_align, v_position, v_align, z_position, fade_up_time, fade_down_time) + : Text(in, out, h_position, h_align, v_position, v_align, z_position, variable_z_positions, fade_up_time, fade_down_time) , _font (font) , _italic (italic) , _bold (bold) @@ -127,6 +128,7 @@ dcp::operator==(TextString const & a, TextString const & b) a.v_position() == b.v_position() && a.v_align() == b.v_align() && a.z_position() == b.z_position() && + a.variable_z_positions() == b.variable_z_positions() && a.direction() == b.direction() && a.text() == b.text() && a.effect() == b.effect() && @@ -173,8 +175,8 @@ dcp::operator<<(ostream& s, TextString const & sub) << ", colour (" << sub.colour().r << ", " << sub.colour().g << ", " << sub.colour().b << ")" << ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align()) << ", hpos " << sub.h_position() << ", halign " << ((int) sub.h_align()) - << ", zpos " << sub.z_position() - << ", direction " << ((int) sub.direction()) + << ", zpos " << sub.z_position(); + s << ", direction " << ((int) sub.direction()) << ", effect " << ((int) sub.effect()) << ", effect colour (" << sub.effect_colour().r << ", " << sub.effect_colour().g << ", " << sub.effect_colour().b << ")" << ", space before " << sub.space_before(); diff --git a/src/text_string.h b/src/text_string.h index f532bafe..78788786 100644 --- a/src/text_string.h +++ b/src/text_string.h @@ -72,6 +72,7 @@ public: * @param v_align Vertical alignment point * @param z_position Z position as a proportion of the primary picture width between -1 and +1; * +ve moves the image away from the viewer, -ve moves it toward the viewer, 0 is in the plane of the screen. + * @param variable_z_positions List of variable Z positions for this text (or empty). * @param direction Direction of text * @param text The text to display * @param effect Effect to use @@ -95,6 +96,7 @@ public: float v_position, VAlign v_align, float z_position, + std::vector<VariableZPosition> variable_z_positions, Direction direction, std::string text, Effect effect, diff --git a/test/data/subtitles_with_vZani.xml b/test/data/subtitles_with_vZani.xml new file mode 100644 index 00000000..32f08c6a --- /dev/null +++ b/test/data/subtitles_with_vZani.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<SubtitleReel xmlns="http://www.smpte-ra.org/schemas/428-7/2014/DCST" xmlns:xs="http://www.w3.org/2001/XMLSchema"> + <Id>urn:uuid:6382e2f3-8d75-441a-8324-4d0713549056</Id> + <ContentTitleText>Stereoscopic Subtitles: timeline01</ContentTitleText> + <AnnotationText>3D subs made with Davinci</AnnotationText> + <IssueDate>2025-01-28T20:47:47.904-00:00</IssueDate> + <ReelNumber>1</ReelNumber> + <Language>en</Language> + <EditRate>24 1</EditRate> + <TimeCodeRate>24</TimeCodeRate> + <StartTime>00:00:00:00</StartTime> + <DisplayType>MainSubtitle</DisplayType> + <LoadFont ID="MyFont">urn:uuid:d621dedd-089d-4d1f-8c24-fb976e1439df</LoadFont> + <SubtitleList> + <Font ID="MyFont" Color="FFFFFFFF" Weight="normal" Size="45"> + <Subtitle SpotNumber="1" TimeIn="00:00:10:00" TimeOut="00:00:15:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="0.0">subtitle - position 0 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="2" TimeIn="00:00:15:00" TimeOut="00:00:20:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="-0.5">subtitle - position -0.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="3" TimeIn="00:00:20:00" TimeOut="00:00:25:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="-1">subtitle - position -1 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="4" TimeIn="00:00:25:00" TimeOut="00:00:30:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="-1.5">subtitle - position -1.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="5" TimeIn="00:00:30:00" TimeOut="00:00:35:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="-2.0">subtitle - position -2 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="6" TimeIn="00:00:35:00" TimeOut="00:00:40:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="0.0">subtitle - position 0 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="7" TimeIn="00:00:40:00" TimeOut="00:00:45:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="0.5">subtitle - position 0.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="8" TimeIn="00:00:45:00" TimeOut="00:00:50:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="1.0">subtitle - position 1 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="9" TimeIn="00:00:50:00" TimeOut="00:00:55:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="1.5">subtitle - position 1.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="10" TimeIn="00:00:55:00" TimeOut="00:01:00:00"> + <Text Valign="bottom" Vposition="20.00" Zposition="2.0">subtitle - position 2 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="11" TimeIn="00:01:05:00" TimeOut="00:01:20:00"> + <LoadVariableZ ID="Zvector1">-2.0:120 0.0:120 2.0:120</LoadVariableZ> + <Text Valign="bottom" Vposition="10.00" Zposition="-2.0" VariableZ="Zvector1">animation -2 to 0 to 2</Text> + </Subtitle> + <Subtitle SpotNumber="12" TimeIn="00:01:24:00" TimeOut="00:01:39:00"> + <LoadVariableZ ID="Zvector2">0.0:120 2.0:120 -2.0:120</LoadVariableZ> + <Text Valign="bottom" Vposition="10.00" Zposition="0.0" VariableZ="Zvector2">animation 0 to 2 to - 2</Text> + </Subtitle> + <Subtitle SpotNumber="13" TimeIn="00:01:42:13" TimeOut="00:01:57:13"> + <LoadVariableZ ID="Zvector3">2.0:180 0.0:180</LoadVariableZ> + <Text Valign="bottom" Vposition="10.00" Zposition="2.0" VariableZ="Zvector3">animation 2 to 0</Text> + </Subtitle> + </Font> + </SubtitleList> +</SubtitleReel>
\ No newline at end of file diff --git a/test/data/subtitles_with_vZani_parsed.xml b/test/data/subtitles_with_vZani_parsed.xml new file mode 100644 index 00000000..7c9c797d --- /dev/null +++ b/test/data/subtitles_with_vZani_parsed.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<SubtitleReel xmlns="http://www.smpte-ra.org/schemas/428-7/2014/DCST"> + <Id>urn:uuid:6382e2f3-8d75-441a-8324-4d0713549056</Id> + <ContentTitleText>Stereoscopic Subtitles: timeline01</ContentTitleText> + <AnnotationText>3D subs made with Davinci</AnnotationText> + <IssueDate>2025-01-28T20:47:47</IssueDate> + <ReelNumber>1</ReelNumber> + <Language>en</Language> + <EditRate>24 1</EditRate> + <TimeCodeRate>24</TimeCodeRate> + <StartTime>00:00:00:00</StartTime> + <LoadFont ID="MyFont">urn:uuid:d621dedd-089d-4d1f-8c24-fb976e1439df</LoadFont> + <SubtitleList> + <Font AspectAdjust="1.0" Color="FFFFFFFF" Effect="none" EffectColor="FF000000" ID="MyFont" Italic="no" Script="normal" Size="45" Underline="no" Weight="normal"> + <Subtitle SpotNumber="1" TimeIn="00:00:10:00" TimeOut="00:00:15:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20">subtitle - position 0 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="2" TimeIn="00:00:15:00" TimeOut="00:00:20:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="-0.5">subtitle - position -0.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="3" TimeIn="00:00:20:00" TimeOut="00:00:25:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="-1">subtitle - position -1 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="4" TimeIn="00:00:25:00" TimeOut="00:00:30:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="-1.5">subtitle - position -1.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="5" TimeIn="00:00:30:00" TimeOut="00:00:35:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="-2">subtitle - position -2 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="6" TimeIn="00:00:35:00" TimeOut="00:00:40:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20">subtitle - position 0 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="7" TimeIn="00:00:40:00" TimeOut="00:00:45:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="0.5">subtitle - position 0.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="8" TimeIn="00:00:45:00" TimeOut="00:00:50:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="1">subtitle - position 1 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="9" TimeIn="00:00:50:00" TimeOut="00:00:55:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="1.5">subtitle - position 1.5 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="10" TimeIn="00:00:55:00" TimeOut="00:01:00:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <Text Valign="bottom" Vposition="20" Zposition="2">subtitle - position 2 - subtitle</Text> + </Subtitle> + <Subtitle SpotNumber="11" TimeIn="00:01:05:00" TimeOut="00:01:20:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <LoadVariableZ ID="Zvector1">-2.0:120 0.0:120 2.0:120</LoadVariableZ> + <Text Valign="bottom" Vposition="10" Zposition="-2" VariableZ="Zvector1">animation -2 to 0 to 2</Text> + </Subtitle> + <Subtitle SpotNumber="12" TimeIn="00:01:24:00" TimeOut="00:01:39:00" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <LoadVariableZ ID="Zvector2">0.0:120 2.0:120 -2.0:120</LoadVariableZ> + <Text Valign="bottom" Vposition="10" VariableZ="Zvector2">animation 0 to 2 to - 2</Text> + </Subtitle> + <Subtitle SpotNumber="13" TimeIn="00:01:42:13" TimeOut="00:01:57:13" FadeUpTime="00:00:00:02" FadeDownTime="00:00:00:02"> + <LoadVariableZ ID="Zvector3">2.0:180 0.0:180</LoadVariableZ> + <Text Valign="bottom" Vposition="10" Zposition="2" VariableZ="Zvector3">animation 2 to 0</Text> + </Subtitle> + </Font> + </SubtitleList> +</SubtitleReel> diff --git a/test/decryption_test.cc b/test/decryption_test.cc index 3bb62d21..2b34cd25 100644 --- a/test/decryption_test.cc +++ b/test/decryption_test.cc @@ -191,7 +191,7 @@ BOOST_AUTO_TEST_CASE (decryption_test2) dcp::Time(0, 0, 5, 0, 24), 0.5, dcp::HAlign::CENTER, 0.5, dcp::VAlign::CENTER, - 0, + 0, vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello world", dcp::Effect::NONE, diff --git a/test/interop_subtitle_test.cc b/test/interop_subtitle_test.cc index 2d7f4a43..27dcaf23 100644 --- a/test/interop_subtitle_test.cc +++ b/test/interop_subtitle_test.cc @@ -46,6 +46,7 @@ using std::dynamic_pointer_cast; using std::shared_ptr; using std::string; using std::vector; +using boost::optional; /** Load some subtitle content from Interop XML and check that it is read correctly */ @@ -83,6 +84,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1) 0.15, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "My jacket was ", dcp::Effect::BORDER, @@ -108,6 +110,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1) 0.15, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Idi Amin's", dcp::Effect::BORDER, @@ -136,6 +139,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1) 0.21, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "My corset was H.M. The Queen's", dcp::Effect::BORDER, @@ -161,6 +165,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1) 0.15, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "My large wonderbra", dcp::Effect::BORDER, @@ -189,6 +194,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1) 0.15, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Once belonged to the Shah", dcp::Effect::BORDER, @@ -217,6 +223,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1) 0.15, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "And these are Roy Hattersley's jeans", dcp::Effect::BORDER, @@ -251,6 +258,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "At afternoon tea with John Peel", dcp::Effect::BORDER, @@ -276,6 +284,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "I enquired if his accent was real", dcp::Effect::BORDER, @@ -304,6 +313,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "He said \"out of the house", dcp::Effect::BORDER, @@ -329,6 +339,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "I'm incredibly scouse", dcp::Effect::BORDER, @@ -357,6 +368,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "At home it depends how I feel.\"", dcp::Effect::BORDER, @@ -382,6 +394,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "I spent a long weekend in Brighton", dcp::Effect::BORDER, @@ -410,6 +423,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::RTL, "With the legendary Miss Enid Blyton", dcp::Effect::BORDER, @@ -435,6 +449,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::TTB, "She said \"you be Noddy", dcp::Effect::BORDER, @@ -463,6 +478,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::BTT, "That curious creature the Sphinx", dcp::Effect::BORDER, @@ -488,6 +504,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Is smarter than anyone thinks", dcp::Effect::BORDER, @@ -516,6 +533,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "It sits there and smirks", dcp::Effect::BORDER, @@ -541,6 +559,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "And you don't think it works", dcp::Effect::BORDER, @@ -569,6 +588,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Then when you're not looking, it winks.", dcp::Effect::BORDER, @@ -594,6 +614,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "When it snows you will find Sister Sledge", dcp::Effect::BORDER, @@ -622,6 +643,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Out mooning, at night, on the ledge", dcp::Effect::BORDER, @@ -647,6 +669,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "One storey down", dcp::Effect::BORDER, @@ -675,6 +698,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.89, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "HELLO", dcp::Effect::BORDER, @@ -700,6 +724,7 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2) 0.95, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "WORLD", dcp::Effect::BORDER, @@ -747,6 +772,7 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test) 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello world", dcp::Effect::NONE, @@ -774,6 +800,7 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test) 0.4, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "What's going ", dcp::Effect::BORDER, @@ -801,6 +828,7 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test) 0.4, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "on", dcp::Effect::BORDER, @@ -862,6 +890,7 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2) 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello world", dcp::Effect::NONE, @@ -889,6 +918,7 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2) 0.4, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "What's going on", dcp::Effect::BORDER, @@ -944,6 +974,7 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test3) 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Time (0, 0, 0, 0, 24), dcp::Time (0, 0, 0, 0, 24) ) diff --git a/test/load_variable_z_test.cc b/test/load_variable_z_test.cc index 8448480f..07c45a57 100644 --- a/test/load_variable_z_test.cc +++ b/test/load_variable_z_test.cc @@ -33,6 +33,7 @@ #include "load_variable_z.h" +#include "smpte_text_asset.h" #include "warnings.h" #include "compose.hpp" LIBDCP_DISABLE_WARNINGS @@ -89,3 +90,12 @@ BOOST_AUTO_TEST_CASE(variable_z_test) made.set_positions({{-0.6, 2}, {4.2, 9}, {5, 1}}); BOOST_CHECK_EQUAL(xml(made), "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<LoadVariableZ ID=\"baz\">-0.6:2 4.2:9 5.0</LoadVariableZ>\n"); } + + +BOOST_AUTO_TEST_CASE(variable_z_pass_through) +{ + dcp::SMPTETextAsset asset("test/data/subtitles_with_vZani.xml"); + BOOST_CHECK_EQUAL(asset.xml_as_string(), dcp::file_to_string("test/data/subtitles_with_vZani_parsed.xml")); +} + + diff --git a/test/shared_subtitle_test.cc b/test/shared_subtitle_test.cc index 82595cd0..1a7ba853 100644 --- a/test/shared_subtitle_test.cc +++ b/test/shared_subtitle_test.cc @@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE (pull_fonts_test1) auto root = make_shared<dcp::order::Part>(shared_ptr<dcp::order::Part>()); auto sub1 = make_shared<dcp::order::Subtitle>(root, dcp::Time(), dcp::Time(), dcp::Time(), dcp::Time()); root->children.push_back (sub1); - auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, dcp::Direction::LTR, std::vector<dcp::Ruby>()); + auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, optional<string>(), dcp::Direction::LTR, std::vector<dcp::Ruby>()); sub1->children.push_back (text1); text1->font._values["font"] = "Inconsolata"; text1->font._values["size"] = "42"; @@ -127,11 +127,11 @@ BOOST_AUTO_TEST_CASE (pull_fonts_test2) auto root = make_shared<dcp::order::Part>(shared_ptr<dcp::order::Part> ()); auto sub1 = make_shared<dcp::order::Subtitle>(root, dcp::Time(), dcp::Time(), dcp::Time(), dcp::Time()); root->children.push_back (sub1); - auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, dcp::Direction::LTR, std::vector<dcp::Ruby>()); + auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, optional<string>(), dcp::Direction::LTR, std::vector<dcp::Ruby>()); sub1->children.push_back (text1); text1->font._values["font"] = "Inconsolata"; text1->font._values["size"] = "42"; - auto text2 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, dcp::Direction::LTR, std::vector<dcp::Ruby>()); + auto text2 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, optional<string>(), dcp::Direction::LTR, std::vector<dcp::Ruby>()); sub1->children.push_back (text2); text2->font._values["font"] = "Inconsolata"; text2->font._values["size"] = "48"; @@ -152,7 +152,7 @@ BOOST_AUTO_TEST_CASE (pull_fonts_test3) auto root = make_shared<dcp::order::Part>(shared_ptr<dcp::order::Part> ()); auto sub1 = make_shared<dcp::order::Subtitle>(root, dcp::Time(), dcp::Time(), dcp::Time(), dcp::Time()); root->children.push_back (sub1); - auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, dcp::Direction::LTR, std::vector<dcp::Ruby>()); + auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, optional<string>(), dcp::Direction::LTR, std::vector<dcp::Ruby>()); sub1->children.push_back (text1); dcp::order::Font font; font._values["font"] = "Inconsolata"; diff --git a/test/smpte_subtitle_test.cc b/test/smpte_subtitle_test.cc index e1dabc44..5aa6bea6 100644 --- a/test/smpte_subtitle_test.cc +++ b/test/smpte_subtitle_test.cc @@ -66,6 +66,7 @@ BOOST_AUTO_TEST_CASE (smpte_subtitle_id_test) 0.5, dcp::VAlign::CENTER, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello", dcp::Effect::NONE, @@ -196,6 +197,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test) 0.8, dcp::VAlign::TOP, 0.3, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello world", dcp::Effect::NONE, @@ -223,6 +225,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test) 0.4, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::RTL, "What's going ", dcp::Effect::BORDER, @@ -250,6 +253,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test) 0.4, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::RTL, "on", dcp::Effect::BORDER, @@ -318,6 +322,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2) 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Testing is ", dcp::Effect::NONE, @@ -345,6 +350,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2) 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "really", dcp::Effect::NONE, @@ -372,6 +378,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2) 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, " fun", dcp::Effect::NONE, @@ -399,6 +406,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2) 0.9, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "This is the ", dcp::Effect::NONE, @@ -426,6 +434,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2) 0.9, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "second", dcp::Effect::NONE, @@ -453,6 +462,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2) 0.9, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, " line", dcp::Effect::NONE, @@ -511,6 +521,7 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test3) 0.8, dcp::VAlign::TOP, -88, + vector<dcp::Text::VariableZPosition>(), dcp::Time (0, 0, 0, 0, 24), dcp::Time (0, 0, 0, 0, 24) ) @@ -568,6 +579,7 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_top_alignment) 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Top line", dcp::Effect::NONE, @@ -595,6 +607,7 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_top_alignment) 0.9, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Bottom line", dcp::Effect::NONE, @@ -658,6 +671,7 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_bottom_alignment) 0.8, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Top line", dcp::Effect::NONE, @@ -685,6 +699,7 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_bottom_alignment) 0.7, dcp::VAlign::BOTTOM, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Bottom line", dcp::Effect::NONE, @@ -782,3 +797,13 @@ BOOST_AUTO_TEST_CASE(smpte_subtitle_intrinsic_duration_read_correctly) BOOST_CHECK_EQUAL(check.intrinsic_duration(), duration); } + + +BOOST_AUTO_TEST_CASE(pass_through_smpte_subtitle_with_variable_z) +{ + auto source = "test/data/subtitles_with_vZani.xml"; + dcp::SMPTETextAsset test("test/data/subtitles_with_vZani.xml"); + /* _parsed is a version of the source with some changes made by libdcp that are OK */ + check_xml(dcp::file_to_string("test/data/subtitles_with_vZani_parsed.xml"), test.xml_as_string(), { "IssueDate" }, true); +} + diff --git a/test/test.cc b/test/test.cc index 0de9c73c..42619683 100644 --- a/test/test.cc +++ b/test/test.cc @@ -410,6 +410,7 @@ simple_text() 0.8, dcp::VAlign::TOP, 0, + vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello world", dcp::Effect::NONE, diff --git a/test/verify_test.cc b/test/verify_test.cc index 3352b472..6c09cbe0 100644 --- a/test/verify_test.cc +++ b/test/verify_test.cc @@ -2092,7 +2092,7 @@ add_test_subtitle (shared_ptr<dcp::TextAsset> asset, int start_frame, int end_fr dcp::HAlign::CENTER, v_position, v_align, - 0, + 0, vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, text, dcp::Effect::NONE, @@ -5896,7 +5896,7 @@ BOOST_AUTO_TEST_CASE(overlapping_subtitles) dcp::Time(0, 0, 8, 0, 24), 0, dcp::HAlign::CENTER, 0, dcp::VAlign::CENTER, - 0, + 0, vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "", dcp::Effect::NONE, dcp::Colour{}, dcp::Time{}, dcp::Time{}, 0, vector<dcp::Ruby>{} @@ -5909,7 +5909,7 @@ BOOST_AUTO_TEST_CASE(overlapping_subtitles) dcp::Time(0, 0, 4, 0, 24), 0, dcp::HAlign::CENTER, 0, dcp::VAlign::CENTER, - 0, + 0, vector<dcp::Text::VariableZPosition>(), dcp::Direction::LTR, "Hello", dcp::Effect::NONE, dcp::Colour{}, dcp::Time{}, dcp::Time{}, 0, vector<dcp::Ruby>{} |
