summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2023-11-15 20:14:55 +0100
committerCarl Hetherington <cth@carlh.net>2023-11-15 20:14:55 +0100
commite3fa86ef35f212b14b593dd36dbff66e845d37e4 (patch)
treec5d6ed58fc19b0fcd08c02a67df66d7023337728
parent24ba38ed1d695a67aebc8a6084444345787112f9 (diff)
Simple pass-through of <Ruby> tags in subtitles.
-rw-r--r--src/ruby.cc57
-rw-r--r--src/ruby.h71
-rw-r--r--src/subtitle_asset.cc97
-rw-r--r--src/subtitle_asset.h8
-rw-r--r--src/subtitle_asset_internal.cc12
-rw-r--r--src/subtitle_asset_internal.h5
-rw-r--r--src/subtitle_string.cc17
-rw-r--r--src/subtitle_string.h14
-rw-r--r--src/types.h5
-rw-r--r--src/wscript2
-rw-r--r--test/data/ruby1.xml14
-rw-r--r--test/decryption_test.cc2
-rw-r--r--test/interop_subtitle_test.cc87
-rw-r--r--test/shared_subtitle_test.cc17
-rw-r--r--test/smpte_subtitle_test.cc42
-rw-r--r--test/test.cc3
-rw-r--r--test/verify_test.cc3
17 files changed, 396 insertions, 60 deletions
diff --git a/src/ruby.cc b/src/ruby.cc
new file mode 100644
index 00000000..6adfbcbc
--- /dev/null
+++ b/src/ruby.cc
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "ruby.h"
+#include "types.h"
+
+
+using namespace dcp;
+
+
+bool dcp::operator==(Ruby const& a, Ruby const& b)
+{
+ return a.base == b.base &&
+ a.annotation == b.annotation &&
+ fabs(a.size - b.size) < SIZE_EPSILON &&
+ a. position == b.position &&
+ fabs(a.offset - b.offset) < OFFSET_EPSILON &&
+ fabs(a.spacing - b.spacing) < SPACING_EPSILON &&
+ fabs(a.aspect_adjust - b.aspect_adjust) < ASPECT_ADJUST_EPSILON;
+}
+
+
+bool dcp::operator!=(Ruby const& a, Ruby const& b)
+{
+ return !(a == b);
+}
diff --git a/src/ruby.h b/src/ruby.h
new file mode 100644
index 00000000..343583dd
--- /dev/null
+++ b/src/ruby.h
@@ -0,0 +1,71 @@
+/*
+ Copyright (C) 2023 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ libdcp is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include <string>
+
+
+namespace dcp {
+
+
+enum class RubyPosition
+{
+ BEFORE,
+ AFTER
+};
+
+
+class Ruby
+{
+public:
+ Ruby(std::string base_, std::string annotation_)
+ : base(base_)
+ , annotation(annotation_)
+ {}
+
+ std::string base;
+ std::string annotation;
+ float size = 0.5;
+ RubyPosition position = RubyPosition::BEFORE;
+ float offset = 0;
+ float spacing = 0;
+ float aspect_adjust = 1;
+};
+
+
+bool operator==(Ruby const& a, Ruby const& b);
+bool operator!=(Ruby const& a, Ruby const& b);
+
+
+}
+
diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc
index 4deb366a..1cd4fc07 100644
--- a/src/subtitle_asset.cc
+++ b/src/subtitle_asset.cc
@@ -294,12 +294,83 @@ SubtitleAsset::parse_subtitles (xmlpp::Element const * node, vector<ParseState>&
float space_before = 0;
+ /* Collect <Ruby>s first */
+ auto get_text_content = [](xmlpp::Element const* element) {
+ string all_content;
+ for (auto child: element->get_children()) {
+ auto content = dynamic_cast<xmlpp::ContentNode const*>(child);
+ if (content) {
+ all_content += content->get_content();
+ }
+ }
+ return all_content;
+ };
+
+ vector<Ruby> rubies;
+ for (auto child: node->get_children()) {
+ auto element = dynamic_cast<xmlpp::Element const*>(child);
+ if (element && element->get_name() == "Ruby") {
+ optional<string> base;
+ optional<string> annotation;
+ optional<float> size;
+ optional<RubyPosition> position;
+ optional<float> offset;
+ optional<float> spacing;
+ optional<float> aspect_adjust;
+ for (auto ruby_child: element->get_children()) {
+ if (auto ruby_element = dynamic_cast<xmlpp::Element const*>(ruby_child)) {
+ if (ruby_element->get_name() == "Rb") {
+ base = get_text_content(ruby_element);
+ } else if (ruby_element->get_name() == "Rt") {
+ annotation = get_text_content(ruby_element);
+ size = optional_number_attribute<float>(ruby_element, "Size");
+ if (auto position_string = optional_string_attribute(ruby_element, "Position")) {
+ if (*position_string == "before") {
+ position = RubyPosition::BEFORE;
+ } else if (*position_string == "after") {
+ position = RubyPosition::AFTER;
+ } else {
+ DCP_ASSERT(false);
+ }
+ }
+ offset = optional_number_attribute<float>(ruby_element, "Offset");
+ spacing = optional_number_attribute<float>(ruby_element, "Spacing");
+ aspect_adjust = optional_number_attribute<float>(ruby_element, "AspectAdjust");
+ }
+ }
+ }
+ DCP_ASSERT(base);
+ DCP_ASSERT(annotation);
+ auto ruby = Ruby{*base, *annotation};
+ if (size) {
+ ruby.size = *size;
+ }
+ if (position) {
+ ruby.position = *position;
+ }
+ if (offset) {
+ ruby.offset = *offset;
+ }
+ if (spacing) {
+ ruby.spacing = *spacing;
+ }
+ if (aspect_adjust) {
+ ruby.aspect_adjust = *aspect_adjust;
+ }
+ rubies.push_back(ruby);
+ }
+ }
+
for (auto i: node->get_children()) {
+
+ /* Handle actual content e.g. text */
auto const v = dynamic_cast<xmlpp::ContentNode const *>(i);
if (v) {
- maybe_add_subtitle (v->get_content(), state, space_before, standard);
+ maybe_add_subtitle (v->get_content(), state, space_before, standard, rubies);
space_before = 0;
}
+
+ /* Handle other nodes */
auto const e = dynamic_cast<xmlpp::Element const *>(i);
if (e) {
if (e->get_name() == "Space") {
@@ -311,7 +382,7 @@ SubtitleAsset::parse_subtitles (xmlpp::Element const * node, vector<ParseState>&
boost::replace_all(size, "em", "");
}
space_before += raw_convert<float>(size);
- } else {
+ } else if (e->get_name() != "Ruby") {
parse_subtitles (e, state, tcr, standard);
}
}
@@ -322,7 +393,13 @@ SubtitleAsset::parse_subtitles (xmlpp::Element const * node, vector<ParseState>&
void
-SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse_state, float space_before, Standard standard)
+SubtitleAsset::maybe_add_subtitle(
+ string text,
+ vector<ParseState> const & parse_state,
+ float space_before,
+ Standard standard,
+ vector<Ruby> const& rubies
+ )
{
auto wanted = [](ParseState const& ps) {
return ps.type && (ps.type.get() == ParseState::Type::TEXT || ps.type.get() == ParseState::Type::IMAGE);
@@ -427,7 +504,8 @@ SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse
ps.effect_colour.get_value_or (dcp::Colour (0, 0, 0)),
ps.fade_up_time.get_value_or(Time()),
ps.fade_down_time.get_value_or(Time()),
- space_before
+ space_before,
+ rubies
)
);
break;
@@ -698,7 +776,16 @@ SubtitleAsset::subtitles_as_xml (xmlpp::Element* xml_root, int time_code_rate, S
fabs(last_z_position - is->z_position()) > ALIGN_EPSILON ||
last_direction != is->direction()
) {
- text = make_shared<order::Text>(subtitle, is->h_align(), is->h_position(), is->v_align(), is->v_position(), is->z_position(), is->direction());
+ text = make_shared<order::Text>(
+ subtitle,
+ is->h_align(),
+ is->h_position(),
+ is->v_align(),
+ is->v_position(),
+ is->z_position(),
+ is->direction(),
+ is->rubies()
+ );
subtitle->children.push_back (text);
last_h_align = is->h_align ();
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
index 42030288..25758c2e 100644
--- a/src/subtitle_asset.h
+++ b/src/subtitle_asset.h
@@ -216,7 +216,13 @@ private:
friend struct ::pull_fonts_test2;
friend struct ::pull_fonts_test3;
- void maybe_add_subtitle (std::string text, std::vector<ParseState> const & parse_state, float space_before, Standard standard);
+ void maybe_add_subtitle(
+ std::string text,
+ std::vector<ParseState> const & parse_state,
+ float space_before,
+ Standard standard,
+ std::vector<Ruby> const& rubies
+ );
static void pull_fonts (std::shared_ptr<order::Part> part);
};
diff --git a/src/subtitle_asset_internal.cc b/src/subtitle_asset_internal.cc
index bb67b45a..99d8411b 100644
--- a/src/subtitle_asset_internal.cc
+++ b/src/subtitle_asset_internal.cc
@@ -223,6 +223,18 @@ order::Text::as_xml (xmlpp::Element* parent, Context& context) const
e->set_attribute ("Direction", direction_to_string (_direction));
}
+ for (auto const& ruby: _rubies) {
+ auto xml = e->add_child("Ruby");
+ xml->add_child("Rb")->add_child_text(ruby.base);
+ auto rt = xml->add_child("Rt");
+ rt->add_child_text(ruby.annotation);
+ rt->set_attribute("Size", dcp::raw_convert<string>(ruby.size, 6));
+ rt->set_attribute("Position", ruby.position == RubyPosition::BEFORE ? "before" : "after");
+ rt->set_attribute("Offset", dcp::raw_convert<string>(ruby.offset, 6));
+ rt->set_attribute("Spacing", dcp::raw_convert<string>(ruby.spacing, 6));
+ rt->set_attribute("AspectAdjust", dcp::raw_convert<string>(ruby.aspect_adjust, 6));
+ }
+
return e;
}
diff --git a/src/subtitle_asset_internal.h b/src/subtitle_asset_internal.h
index adf2c994..557db2e4 100644
--- a/src/subtitle_asset_internal.h
+++ b/src/subtitle_asset_internal.h
@@ -62,6 +62,7 @@ struct pull_fonts_test3;
namespace dcp {
+class Ruby;
class SubtitleString;
@@ -145,7 +146,7 @@ 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)
+ 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)
: Part (parent)
, _h_align (h_align)
, _h_position (h_position)
@@ -153,6 +154,7 @@ public:
, _v_position (v_position)
, _z_position(z_position)
, _direction (direction)
+ , _rubies(rubies)
{}
xmlpp::Element* as_xml (xmlpp::Element* parent, Context& context) const override;
@@ -164,6 +166,7 @@ private:
float _v_position;
float _z_position;
Direction _direction;
+ std::vector<Ruby> _rubies;
};
diff --git a/src/subtitle_string.cc b/src/subtitle_string.cc
index b627240b..af61d928 100644
--- a/src/subtitle_string.cc
+++ b/src/subtitle_string.cc
@@ -49,6 +49,7 @@ using std::min;
using std::ostream;
using std::shared_ptr;
using std::string;
+using std::vector;
using boost::optional;
using namespace dcp;
@@ -74,7 +75,8 @@ SubtitleString::SubtitleString (
Colour effect_colour,
Time fade_up_time,
Time fade_down_time,
- float space_before
+ float space_before,
+ vector<Ruby> rubies
)
: Subtitle(in, out, h_position, h_align, v_position, v_align, z_position, fade_up_time, fade_down_time)
, _font (font)
@@ -89,6 +91,7 @@ SubtitleString::SubtitleString (
, _effect (effect)
, _effect_colour (effect_colour)
, _space_before (space_before)
+ , _rubies(rubies)
{
_aspect_adjust = max(min(_aspect_adjust, 4.0f), 0.25f);
}
@@ -130,7 +133,8 @@ dcp::operator== (SubtitleString const & a, SubtitleString const & b)
a.effect_colour() == b.effect_colour() &&
a.fade_up_time() == b.fade_up_time() &&
a.fade_down_time() == b.fade_down_time() &&
- fabs (a.space_before() - b.space_before()) < SPACE_BEFORE_EPSILON
+ fabs (a.space_before() - b.space_before()) < SPACE_BEFORE_EPSILON &&
+ a.rubies() == b.rubies()
);
}
@@ -175,6 +179,10 @@ dcp::operator<< (ostream& s, SubtitleString const & sub)
<< ", effect colour (" << sub.effect_colour().r << ", " << sub.effect_colour().g << ", " << sub.effect_colour().b << ")"
<< ", space before " << sub.space_before();
+ for (auto ruby: sub.rubies()) {
+ s << ", ruby " << ruby.base << " " << ruby.annotation;
+ }
+
return s;
}
@@ -254,6 +262,11 @@ SubtitleString::equals(shared_ptr<const Subtitle> other_sub, EqualityOptions con
same = false;
}
+ if (_rubies != other->_rubies) {
+ note(NoteType::ERROR, "rubies differ");
+ same = false;
+ }
+
return same;
}
diff --git a/src/subtitle_string.h b/src/subtitle_string.h
index 4eb64a68..1ef57ff2 100644
--- a/src/subtitle_string.h
+++ b/src/subtitle_string.h
@@ -42,6 +42,7 @@
#include "dcp_time.h"
+#include "ruby.h"
#include "subtitle.h"
#include <boost/optional.hpp>
#include <string>
@@ -100,7 +101,8 @@ public:
Colour effect_colour,
Time fade_up_time,
Time fade_down_time,
- float space_before
+ float space_before,
+ std::vector<Ruby> rubies
);
/** @return font ID */
@@ -158,6 +160,10 @@ public:
return _aspect_adjust;
}
+ std::vector<Ruby> const& rubies() const {
+ return _rubies;
+ }
+
void set_font (std::string id) {
_font = id;
}
@@ -190,6 +196,10 @@ public:
_effect_colour = c;
}
+ void set_rubies(std::vector<Ruby> rubies) {
+ _rubies = std::move(rubies);
+ }
+
bool equals(std::shared_ptr<const dcp::Subtitle> other_sub, EqualityOptions const& options, NoteHandler node) const override;
private:
@@ -213,6 +223,7 @@ private:
Effect _effect;
Colour _effect_colour;
float _space_before;
+ std::vector<Ruby> _rubies;
};
bool operator== (SubtitleString const & a, SubtitleString const & b);
@@ -224,3 +235,4 @@ std::ostream& operator<< (std::ostream& s, SubtitleString const & sub);
#endif
+
diff --git a/src/types.h b/src/types.h
index bcb6da5b..183ce638 100644
--- a/src/types.h
+++ b/src/types.h
@@ -277,6 +277,11 @@ constexpr float ALIGN_EPSILON = 1e-3;
constexpr float SPACE_BEFORE_EPSILON = 1e-3;
+constexpr float SIZE_EPSILON = 1e-3;
+constexpr float OFFSET_EPSILON = 1e-3;
+constexpr float SPACING_EPSILON = 1e-3;
+
+
enum class Marker {
FFOC, ///< first frame of composition
LFOC, ///< last frame of composition
diff --git a/src/wscript b/src/wscript
index e6bee6f2..3bc8537b 100644
--- a/src/wscript
+++ b/src/wscript
@@ -101,6 +101,7 @@ def build(bld):
reel_subtitle_asset.cc
ref.cc
rgb_xyz.cc
+ ruby.cc
s_gamut3_transfer_function.cc
search.cc
smpte_load_font_node.cc
@@ -205,6 +206,7 @@ def build(bld):
reel_stereo_picture_asset.h
reel_subtitle_asset.h
ref.h
+ ruby.h
s_gamut3_transfer_function.h
search.h
smpte_load_font_node.h
diff --git a/test/data/ruby1.xml b/test/data/ruby1.xml
new file mode 100644
index 00000000..fe1d8adc
--- /dev/null
+++ b/test/data/ruby1.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DCSubtitle Version="1.0">
+ <SubtitleID>cab5c268-222b-41d2-88ae-6d6999441b17</SubtitleID>
+ <MovieTitle>Movie Title</MovieTitle>
+ <ReelNumber>1</ReelNumber>
+ <Language>French</Language>
+ <LoadFont Id="theFontId" URI="arial.ttf"/>
+ <Font AspectAdjust="1.0" Color="FFFFFFFF" Effect="border" EffectColor="FF000000" Id="theFontId" Italic="no" Script="normal" Size="39" Underlined="no" Weight="normal">
+ <Subtitle SpotNumber="1" TimeIn="00:00:05:198" TimeOut="00:00:07:115" FadeUpTime="1" FadeDownTime="1">
+ <Text VAlign="center" VPosition="0"><Ruby><Rb>Base</Rb><Rt Size="0.7" Position="after" Offset="0.1" Spacing="0.4" AspectAdjust="0.9">Annotate</Rt></Ruby>Hello world</Text>
+ </Subtitle>
+ </Font>
+</DCSubtitle>
+
diff --git a/test/decryption_test.cc b/test/decryption_test.cc
index 1e2ca94b..8f3dbff7 100644
--- a/test/decryption_test.cc
+++ b/test/decryption_test.cc
@@ -196,7 +196,7 @@ BOOST_AUTO_TEST_CASE (decryption_test2)
"Hello world",
dcp::Effect::NONE,
dcp::Colour(0, 0, 0),
- dcp::Time(), dcp::Time(), 0
+ dcp::Time(), dcp::Time(), 0, std::vector<dcp::Ruby>()
));
subs_asset->write (dir / "subs.mxf");
diff --git a/test/interop_subtitle_test.cc b/test/interop_subtitle_test.cc
index b477346c..0efca007 100644
--- a/test/interop_subtitle_test.cc
+++ b/test/interop_subtitle_test.cc
@@ -89,7 +89,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 1, 250),
dcp::Time (0, 0, 0, 1, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -113,7 +114,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 1, 250),
dcp::Time (0, 0, 0, 1, 250),
- 6
+ 6,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 0, 7, 190, 250), dcp::Time (0, 0, 7, 191, 250), false);
@@ -140,7 +142,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 1, 250),
dcp::Time (0, 0, 0, 1, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -164,7 +167,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 1, 250),
dcp::Time (0, 0, 0, 1, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 0, 11, 95, 250), dcp::Time (0, 0, 11, 96, 250), false);
@@ -191,7 +195,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 1, 250),
dcp::Time (0, 0, 0, 1, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 0, 14, 42, 250), dcp::Time (0, 0, 14, 43, 250), false);
@@ -218,7 +223,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test1)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 1, 250),
dcp::Time (0, 0, 0, 1, 250),
- 0
+ 0,
+ {}
));
}
@@ -251,7 +257,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 250),
dcp::Time (0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -275,7 +282,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 250),
dcp::Time (0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 0, 50, 50, 250), dcp::Time (0, 0, 50, 51, 250), false);
@@ -302,7 +310,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 250),
dcp::Time (0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -326,7 +335,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 250),
dcp::Time (0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 1, 2, 300, 250), dcp::Time (0, 1, 2, 301, 250), false);
@@ -353,7 +363,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -377,7 +388,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 1, 15, 50, 250), dcp::Time (0, 1, 15, 51, 250), false);
@@ -404,7 +416,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -428,7 +441,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 1, 27, 200, 250), dcp::Time (0, 1, 27, 201, 250), false);
@@ -455,7 +469,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -479,7 +494,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 1, 42, 300, 250), dcp::Time (0, 1, 42, 301, 250), false);
@@ -506,7 +522,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -530,7 +547,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 1, 45, 200, 250), dcp::Time (0, 1, 45, 201, 250), false);
@@ -557,7 +575,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -581,7 +600,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 1, 47, 249, 250), dcp::Time (0, 1, 47, 250, 250), false);
@@ -608,7 +628,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -632,7 +653,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
s = subs.subtitles_during (dcp::Time (0, 2, 6, 210, 250), dcp::Time (0, 2, 6, 211, 250), false);
@@ -659,7 +681,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
BOOST_REQUIRE (dynamic_pointer_cast<const dcp::SubtitleString>(s.back()));
BOOST_CHECK_EQUAL (*dynamic_pointer_cast<const dcp::SubtitleString>(s.back()), dcp::SubtitleString (
@@ -683,7 +706,8 @@ BOOST_AUTO_TEST_CASE (read_interop_subtitle_test2)
dcp::Colour(0, 0, 0),
dcp::Time(0, 0, 0, 0, 250),
dcp::Time(0, 0, 0, 0, 250),
- 0
+ 0,
+ {}
));
}
@@ -729,7 +753,8 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -755,7 +780,8 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
dcp::Colour (1, 2, 3),
dcp::Time (1, 2, 3, 4, 24),
dcp::Time (5, 6, 7, 8, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -781,7 +807,8 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test)
dcp::Colour (1, 2, 3),
dcp::Time (1, 2, 3, 4, 24),
dcp::Time (5, 6, 7, 8, 24),
- 9
+ 9,
+ std::vector<dcp::Ruby>()
)
);
@@ -841,7 +868,8 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -867,7 +895,8 @@ BOOST_AUTO_TEST_CASE (write_interop_subtitle_test2)
dcp::Colour (1, 2, 3),
dcp::Time (1, 2, 3, 4, 24),
dcp::Time (5, 6, 7, 8, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
diff --git a/test/shared_subtitle_test.cc b/test/shared_subtitle_test.cc
index 69ae2be4..7ac20e10 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);
+ auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, 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);
+ auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, 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);
+ auto text2 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, 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);
+ auto text1 = make_shared<dcp::order::Text>(sub1, dcp::HAlign::CENTER, 0, dcp::VAlign::TOP, 0, 0, dcp::Direction::LTR, std::vector<dcp::Ruby>());
sub1->children.push_back (text1);
dcp::order::Font font;
font._values["font"] = "Inconsolata";
@@ -217,3 +217,12 @@ BOOST_AUTO_TEST_CASE (format_xml_entities_test)
" <Bar>Don't panic &amp;amp; xml \"is\" 'great' &amp; &lt; &gt; —</Bar>\n"
"</Foo>\n");
}
+
+
+BOOST_AUTO_TEST_CASE(ruby_round_trip_test)
+{
+ dcp::InteropSubtitleAsset asset("test/data/ruby1.xml");
+ check_xml(dcp::file_to_string("test/data/ruby1.xml"), asset.xml_as_string(), {}, false);
+}
+
+
diff --git a/test/smpte_subtitle_test.cc b/test/smpte_subtitle_test.cc
index 414d392d..eca5cd1f 100644
--- a/test/smpte_subtitle_test.cc
+++ b/test/smpte_subtitle_test.cc
@@ -72,7 +72,8 @@ BOOST_AUTO_TEST_CASE (smpte_subtitle_id_test)
dcp::Colour(),
dcp::Time(0, 0, 0, 0, 24),
dcp::Time(0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
subs.write("build/test/smpte_subtitle_id_test.mxf");
@@ -201,7 +202,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -227,7 +229,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test)
dcp::Colour (1, 2, 3),
dcp::Time (1, 2, 3, 4, 24),
dcp::Time (5, 6, 7, 8, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -253,7 +256,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test)
dcp::Colour (1, 2, 3),
dcp::Time (1, 2, 3, 4, 24),
dcp::Time (5, 6, 7, 8, 24),
- 4.2
+ 4.2,
+ std::vector<dcp::Ruby>()
)
);
@@ -320,7 +324,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -346,7 +351,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -372,7 +378,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -398,7 +405,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -424,7 +432,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -450,7 +459,8 @@ BOOST_AUTO_TEST_CASE (write_smpte_subtitle_test2)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -564,7 +574,8 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_top_alignment)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -590,7 +601,8 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_top_alignment)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -652,7 +664,8 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_bottom_alignment)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
@@ -678,7 +691,8 @@ BOOST_AUTO_TEST_CASE (write_subtitles_in_vertical_order_with_bottom_alignment)
dcp::Colour (0, 0, 0),
dcp::Time (0, 0, 0, 0, 24),
dcp::Time (0, 0, 0, 0, 24),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
diff --git a/test/test.cc b/test/test.cc
index bff647d7..d384bdfa 100644
--- a/test/test.cc
+++ b/test/test.cc
@@ -417,7 +417,8 @@ simple_subtitle ()
dcp::Colour(255, 255, 255),
dcp::Time(),
dcp::Time(),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
);
}
diff --git a/test/verify_test.cc b/test/verify_test.cc
index 2de443e3..a1a2d280 100644
--- a/test/verify_test.cc
+++ b/test/verify_test.cc
@@ -1335,7 +1335,8 @@ add_test_subtitle (shared_ptr<dcp::SubtitleAsset> asset, int start_frame, int en
dcp::Colour(),
dcp::Time(),
dcp::Time(),
- 0
+ 0,
+ std::vector<dcp::Ruby>()
)
);
}