summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/text_asset.cc148
-rw-r--r--src/text_asset.h5
-rw-r--r--src/text_asset_internal.cc28
-rw-r--r--src/text_asset_internal.h21
-rw-r--r--src/text_string.cc120
-rw-r--r--src/text_string.h83
-rw-r--r--src/verify.cc8
7 files changed, 283 insertions, 130 deletions
diff --git a/src/text_asset.cc b/src/text_asset.cc
index 41690d93..05969d82 100644
--- a/src/text_asset.cc
+++ b/src/text_asset.cc
@@ -307,7 +307,6 @@ TextAsset::parse_texts(xmlpp::Element const * node, vector<ParseState>& state, o
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()) {
@@ -319,73 +318,14 @@ TextAsset::parse_texts(xmlpp::Element const * node, vector<ParseState>& state, o
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_text(v->get_content(), state, space_before, standard, rubies);
+ if (auto const v = dynamic_cast<xmlpp::ContentNode const *>(i)) {
+ maybe_add_text(string{v->get_content()}, state, space_before, standard);
space_before = 0;
}
- /* Handle other nodes */
- auto const e = dynamic_cast<xmlpp::Element const *>(i);
- if (e) {
+ if (auto const e = dynamic_cast<xmlpp::Element const *>(i)) {
if (e->get_name() == "Space") {
if (node->get_name() != "Text") {
throw XMLError ("Space node found outside Text");
@@ -395,8 +335,57 @@ TextAsset::parse_texts(xmlpp::Element const * node, vector<ParseState>& state, o
boost::replace_all(size, "em", "");
}
space_before += raw_convert<float>(size);
- } else if (e->get_name() != "Ruby") {
- parse_texts (e, state, tcr, standard);
+ } else if (e->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: e->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;
+ }
+ maybe_add_text(ruby, state, space_before, standard);
+ } else {
+ parse_texts(e, state, tcr, standard);
}
}
}
@@ -408,11 +397,10 @@ TextAsset::parse_texts(xmlpp::Element const * node, vector<ParseState>& state, o
void
TextAsset::maybe_add_text(
- string text,
+ boost::variant<string, Ruby> text,
vector<ParseState> const & parse_state,
float space_before,
- Standard standard,
- vector<Ruby> const& rubies
+ Standard standard
)
{
auto wanted = [](ParseState const& ps) {
@@ -535,19 +523,20 @@ TextAsset::maybe_add_text(
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,
- rubies
+ space_before
)
);
break;
}
case ParseState::Type::IMAGE:
{
+ DCP_ASSERT(text.which() == 0);
+ auto text_string = boost::get<string>(text);
switch (standard) {
case Standard::INTEROP:
- if (text.size() >= 4) {
+ if (text_string.size() >= 4) {
/* Remove file extension */
- text = text.substr(0, text.size() - 4);
+ text_string = text_string.substr(0, text_string.size() - 4);
}
break;
case Standard::SMPTE:
@@ -556,8 +545,8 @@ TextAsset::maybe_add_text(
* a) it is not (always) used in the field, or
* b) nobody noticed / complained.
*/
- if (text.substr(0, 9) == "urn:uuid:") {
- text = text.substr(9);
+ if (text_string.substr(0, 9) == "urn:uuid:") {
+ text_string = text_string.substr(9);
}
break;
}
@@ -572,7 +561,7 @@ TextAsset::maybe_add_text(
_texts.push_back(
make_shared<TextImage>(
ArrayData(),
- text,
+ text_string,
ps.in.get(),
ps.out.get(),
ps.h_position.get_value_or(0),
@@ -824,8 +813,7 @@ TextAsset::texts_as_xml(xmlpp::Element* xml_root, int time_code_rate, Standard s
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()
+ is->direction()
);
subtitle->children.push_back (text);
@@ -837,7 +825,11 @@ TextAsset::texts_as_xml(xmlpp::Element* xml_root, int time_code_rate, Standard s
last_direction = is->direction ();
}
- text->children.push_back (make_shared<order::String>(text, order::Font (is, standard), is->text(), is->space_before()));
+ if (is->string_text()) {
+ text->children.push_back(make_shared<order::String>(text, order::Font (is, standard), *is->string_text(), is->space_before()));
+ } else if (is->ruby_text()) {
+ text->children.push_back(make_shared<order::Ruby>(text, order::Font(is, standard), *is->ruby_text()));
+ }
}
if (auto ii = dynamic_pointer_cast<TextImage>(i)) {
diff --git a/src/text_asset.h b/src/text_asset.h
index 113896f8..44e2c0c1 100644
--- a/src/text_asset.h
+++ b/src/text_asset.h
@@ -222,11 +222,10 @@ private:
friend struct ::pull_fonts_test3;
void maybe_add_text(
- std::string text,
+ boost::variant<std::string, Ruby> text,
std::vector<ParseState> const & parse_state,
float space_before,
- Standard standard,
- std::vector<Ruby> const& rubies
+ Standard standard
);
static void pull_fonts (std::shared_ptr<order::Part> part);
diff --git a/src/text_asset_internal.cc b/src/text_asset_internal.cc
index 4ae5dbfe..b800aa46 100644
--- a/src/text_asset_internal.cc
+++ b/src/text_asset_internal.cc
@@ -240,22 +240,26 @@ 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 = cxml::add_child(e, "Ruby");
- cxml::add_child(xml, "Rb")->add_child_text(ruby.base);
- auto rt = cxml::add_child(xml, "Rt");
- rt->add_child_text(ruby.annotation);
- rt->set_attribute("Size", fmt::format("{:.6}", ruby.size));
- rt->set_attribute("Position", ruby.position == RubyPosition::BEFORE ? "before" : "after");
- rt->set_attribute("Offset", fmt::format("{:.6}", ruby.offset));
- rt->set_attribute("Spacing", fmt::format("{:.6}", ruby.spacing));
- rt->set_attribute("AspectAdjust", fmt::format("{:.6}", ruby.aspect_adjust));
- }
-
return e;
}
+xmlpp::Element*
+order::Ruby::as_xml(xmlpp::Element* parent, Context&) const
+{
+ auto xml = cxml::add_child(parent, "Ruby");
+ cxml::add_child(xml, "Rb")->add_child_text(_ruby.base);
+ auto rt = cxml::add_child(xml, "Rt");
+ rt->add_child_text(_ruby.annotation);
+ rt->set_attribute("Size", fmt::format("{:.6}", _ruby.size));
+ rt->set_attribute("Position", _ruby.position == RubyPosition::BEFORE ? "before" : "after");
+ rt->set_attribute("Offset", fmt::format("{:.6}", _ruby.offset));
+ rt->set_attribute("Spacing", fmt::format("{:.6}", _ruby.spacing));
+ rt->set_attribute("AspectAdjust", fmt::format("{:.6}", _ruby.aspect_adjust));
+ return xml;
+}
+
+
optional<string>
order::Subtitle::find_or_add_variable_z_positions(vector<dcp::Text::VariableZPosition> const& positions, int& load_variable_z_index)
{
diff --git a/src/text_asset_internal.h b/src/text_asset_internal.h
index 2dfccce9..be22719d 100644
--- a/src/text_asset_internal.h
+++ b/src/text_asset_internal.h
@@ -46,6 +46,7 @@
#include "h_align.h"
#include "load_variable_z.h"
#include "raw_convert.h"
+#include "ruby.h"
#include "v_align.h"
#include "warnings.h"
LIBDCP_DISABLE_WARNINGS
@@ -144,6 +145,21 @@ private:
};
+class Ruby : public Part
+{
+public:
+ Ruby(std::shared_ptr<Part> parent, Font font, dcp::Ruby ruby)
+ : Part(parent, font)
+ , _ruby(ruby)
+ {}
+
+ virtual xmlpp::Element* as_xml(xmlpp::Element* parent, Context &) const override;
+
+private:
+ dcp::Ruby _ruby;
+};
+
+
class Text : public Part
{
public:
@@ -155,8 +171,7 @@ public:
float v_position,
float z_position,
boost::optional<std::string> variable_z,
- Direction direction,
- std::vector<Ruby> rubies
+ Direction direction
)
: Part (parent)
, _h_align (h_align)
@@ -166,7 +181,6 @@ public:
, _z_position(z_position)
, _variable_z(variable_z)
, _direction (direction)
- , _rubies(rubies)
{}
xmlpp::Element* as_xml (xmlpp::Element* parent, Context& context) const override;
@@ -183,7 +197,6 @@ private:
float _z_position;
boost::optional<std::string> _variable_z;
Direction _direction;
- std::vector<Ruby> _rubies;
};
diff --git a/src/text_string.cc b/src/text_string.cc
index 12e86fce..baa7832b 100644
--- a/src/text_string.cc
+++ b/src/text_string.cc
@@ -40,6 +40,7 @@
#include "compose.hpp"
#include "text_string.h"
#include "xml.h"
+#include <fmt/format.h>
#include <cmath>
@@ -51,6 +52,7 @@ using std::shared_ptr;
using std::string;
using std::vector;
using boost::optional;
+using boost::variant;
using namespace dcp;
@@ -76,8 +78,7 @@ TextString::TextString(
Colour effect_colour,
Time fade_up_time,
Time fade_down_time,
- float space_before,
- vector<Ruby> rubies
+ float space_before
)
: Text(in, out, h_position, h_align, v_position, v_align, z_position, variable_z_positions, fade_up_time, fade_down_time)
, _font (font)
@@ -92,7 +93,90 @@ TextString::TextString(
, _effect (effect)
, _effect_colour (effect_colour)
, _space_before (space_before)
- , _rubies(rubies)
+{
+ _aspect_adjust = max(min(_aspect_adjust, 4.0f), 0.25f);
+}
+
+
+TextString::TextString(
+ optional<string> font,
+ bool italic,
+ bool bold,
+ bool underline,
+ Colour colour,
+ int size,
+ float aspect_adjust,
+ Time in,
+ Time out,
+ float h_position,
+ HAlign h_align,
+ float v_position,
+ VAlign v_align,
+ float z_position,
+ vector<VariableZPosition> variable_z_positions,
+ Direction direction,
+ Ruby text,
+ Effect effect,
+ Colour effect_colour,
+ Time fade_up_time,
+ Time fade_down_time,
+ float space_before
+ )
+ : 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)
+ , _underline(underline)
+ , _colour(colour)
+ , _size(size)
+ , _aspect_adjust(aspect_adjust)
+ , _direction(direction)
+ , _text(text)
+ , _effect(effect)
+ , _effect_colour(effect_colour)
+ , _space_before(space_before)
+{
+ _aspect_adjust = max(min(_aspect_adjust, 4.0f), 0.25f);
+}
+
+
+TextString::TextString(
+ optional<string> font,
+ bool italic,
+ bool bold,
+ bool underline,
+ Colour colour,
+ int size,
+ float aspect_adjust,
+ Time in,
+ Time out,
+ float h_position,
+ HAlign h_align,
+ float v_position,
+ VAlign v_align,
+ float z_position,
+ vector<VariableZPosition> variable_z_positions,
+ Direction direction,
+ variant<string, Ruby> text,
+ Effect effect,
+ Colour effect_colour,
+ Time fade_up_time,
+ Time fade_down_time,
+ float space_before
+ )
+ : 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)
+ , _underline(underline)
+ , _colour(colour)
+ , _size(size)
+ , _aspect_adjust(aspect_adjust)
+ , _direction(direction)
+ , _text(text)
+ , _effect(effect)
+ , _effect_colour(effect_colour)
+ , _space_before(space_before)
{
_aspect_adjust = max(min(_aspect_adjust, 4.0f), 0.25f);
}
@@ -135,8 +219,7 @@ dcp::operator==(TextString const & a, TextString 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 &&
- a.rubies() == b.rubies()
+ fabs (a.space_before() - b.space_before()) < SPACE_BEFORE_EPSILON
);
}
@@ -151,7 +234,15 @@ dcp::operator!=(TextString const & a, TextString const & b)
ostream&
dcp::operator<<(ostream& s, TextString const & sub)
{
- s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
+ s << "\n`";
+
+ if (sub.string_text()) {
+ s << *sub.string_text();
+ } else {
+ s << "[Ruby]";
+ }
+
+ s << "' from " << sub.in() << " to " << sub.out() << ";\n"
<< "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
<< "font " << sub.font().get_value_or ("[default]") << ", ";
@@ -181,10 +272,6 @@ dcp::operator<<(ostream& s, TextString 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;
}
@@ -245,7 +332,13 @@ TextString::equals(shared_ptr<const Text> other_sub, EqualityOptions const& opti
}
if (_text != other->_text) {
- note(NoteType::ERROR, String::compose("text text differs: %1 vs %2", _text, other->_text));
+ if ((!string_text() && ruby_text()) || (string_text() && !ruby_text())) {
+ note(NoteType::ERROR, "text text differs: one is a ruby and the other a string");
+ } else if (string_text()) {
+ note(NoteType::ERROR, fmt::format("text text differs: {} vs {}", *string_text(), *other->string_text()));
+ } else {
+ note(NoteType::ERROR, "text text differs: rubies differ");
+ }
same = false;
}
@@ -264,11 +357,6 @@ TextString::equals(shared_ptr<const Text> other_sub, EqualityOptions const& opti
same = false;
}
- if (_rubies != other->_rubies) {
- note(NoteType::ERROR, "rubies differ");
- same = false;
- }
-
return same;
}
diff --git a/src/text_string.h b/src/text_string.h
index 78788786..bd668a0d 100644
--- a/src/text_string.h
+++ b/src/text_string.h
@@ -45,6 +45,7 @@
#include "ruby.h"
#include "text.h"
#include <boost/optional.hpp>
+#include <boost/variant.hpp>
#include <string>
@@ -52,7 +53,7 @@ namespace dcp {
/** @class TextString
- * @brief A single line of subtitle text with all the associated attributes.
+ * @brief A single piece of subtitle text with all the associated attributes.
*/
class TextString : public Text
{
@@ -103,8 +104,57 @@ public:
Colour effect_colour,
Time fade_up_time,
Time fade_down_time,
- float space_before,
- std::vector<Ruby> rubies
+ float space_before
+ );
+
+ TextString(
+ boost::optional<std::string> font,
+ bool italic,
+ bool bold,
+ bool underline,
+ Colour colour,
+ int size,
+ float aspect_adjust,
+ Time in,
+ Time out,
+ float h_position,
+ HAlign h_align,
+ float v_position,
+ VAlign v_align,
+ float z_position,
+ std::vector<VariableZPosition> variable_z_positions,
+ Direction direction,
+ Ruby text,
+ Effect effect,
+ Colour effect_colour,
+ Time fade_up_time,
+ Time fade_down_time,
+ float space_before
+ );
+
+ TextString(
+ boost::optional<std::string> font,
+ bool italic,
+ bool bold,
+ bool underline,
+ Colour colour,
+ int size,
+ float aspect_adjust,
+ Time in,
+ Time out,
+ float h_position,
+ HAlign h_align,
+ float v_position,
+ VAlign v_align,
+ float z_position,
+ std::vector<VariableZPosition> variable_z_positions,
+ Direction direction,
+ boost::variant<std::string, Ruby> text,
+ Effect effect,
+ Colour effect_colour,
+ Time fade_up_time,
+ Time fade_down_time,
+ float space_before
);
/** @return font ID */
@@ -128,10 +178,24 @@ public:
return _colour;
}
- std::string text () const {
+ boost::variant<std::string, Ruby> text() const {
return _text;
}
+ boost::optional<std::string> string_text() const {
+ if (_text.which() != 0) {
+ return {};
+ }
+ return boost::get<std::string>(_text);
+ }
+
+ boost::optional<Ruby> ruby_text() const {
+ if (_text.which() != 1) {
+ return {};
+ }
+ return boost::get<Ruby>(_text);
+ }
+
Direction direction () const {
return _direction;
}
@@ -162,10 +226,6 @@ public:
return _aspect_adjust;
}
- std::vector<Ruby> const& rubies() const {
- return _rubies;
- }
-
void set_font (std::string id) {
_font = id;
}
@@ -198,10 +258,6 @@ public:
_effect_colour = c;
}
- void set_rubies(std::vector<Ruby> rubies) {
- _rubies = std::move(rubies);
- }
-
bool equals(std::shared_ptr<const dcp::Text> other_sub, EqualityOptions const& options, NoteHandler node) const override;
private:
@@ -221,11 +277,10 @@ private:
int _size;
float _aspect_adjust;
Direction _direction;
- std::string _text;
+ boost::variant<std::string, Ruby> _text;
Effect _effect;
Colour _effect_colour;
float _space_before;
- std::vector<Ruby> _rubies;
};
diff --git a/src/verify.cc b/src/verify.cc
index 6f958fa8..bc6c3304 100644
--- a/src/verify.cc
+++ b/src/verify.cc
@@ -1204,9 +1204,11 @@ dcp::verify_text_lines_and_characters(
/* Make a list of "subtitle starts" and "subtitle ends" events */
for (auto j: asset->texts()) {
if (auto text = dynamic_pointer_cast<const TextString>(j)) {
- auto in = make_shared<Event>(text->in(), position(text), text->text().length());
- events.push_back(in);
- events.push_back(make_shared<Event>(text->out(), in));
+ if (auto string_text = text->string_text()) {
+ auto in = make_shared<Event>(text->in(), position(text), string_text->length());
+ events.push_back(in);
+ events.push_back(make_shared<Event>(text->out(), in));
+ }
}
}