using std::shared_ptr;
using std::vector;
using std::make_shared;
-using boost::shared_array;
using boost::optional;
using boost::lexical_cast;
using namespace dcp;
throw XMLError ("unexpected node " + node->get_name());
}
+ float space_before = 0;
+
for (auto i: node->get_children()) {
auto const v = dynamic_cast<xmlpp::ContentNode const *>(i);
if (v) {
- maybe_add_subtitle (v->get_content(), state, standard);
+ maybe_add_subtitle (v->get_content(), state, space_before, standard);
+ space_before = 0;
}
auto const e = dynamic_cast<xmlpp::Element const *>(i);
if (e) {
- parse_subtitles (e, state, tcr, standard);
+ if (e->get_name() == "Space") {
+ if (node->get_name() != "Text") {
+ throw XMLError ("Space node found outside Text");
+ }
+ auto size = optional_string_attribute(e, "Size").get_value_or("0.5");
+ if (standard == dcp::Standard::INTEROP) {
+ boost::replace_all(size, "em", "");
+ }
+ space_before += raw_convert<float>(size);
+ } else {
+ parse_subtitles (e, state, tcr, standard);
+ }
}
}
void
-SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse_state, Standard standard)
+SubtitleAsset::maybe_add_subtitle (string text, vector<ParseState> const & parse_state, float space_before, Standard standard)
{
if (empty_or_white_space (text)) {
return;
ps.effect.get_value_or (Effect::NONE),
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())
+ ps.fade_down_time.get_value_or(Time()),
+ space_before
)
);
break;
case ParseState::Type::IMAGE:
+ {
+ switch (standard) {
+ case Standard::INTEROP:
+ if (text.size() >= 4) {
+ /* Remove file extension */
+ text = text.substr(0, text.size() - 4);
+ }
+ break;
+ case Standard::SMPTE:
+ /* It looks like this urn:uuid: is required, but DoM wasn't expecting it (and not writing it)
+ * until around 2.15.140 so I guess either:
+ * 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);
+ }
+ break;
+ }
+
/* Add a subtitle with no image data and we'll fill that in later */
_subtitles.push_back (
make_shared<SubtitleImage>(
ArrayData(),
- standard == Standard::INTEROP ? text.substr(0, text.size() - 4) : text,
+ text,
ps.in.get(),
ps.out.get(),
ps.h_position.get_value_or(0),
);
break;
}
+ }
}
if (a->in() != b->in()) {
return a->in() < b->in();
}
+ if (a->v_align() == VAlign::BOTTOM) {
+ return a->v_position() > b->v_position();
+ }
return a->v_position() < b->v_position();
}
};
fabs(last_v_position - is->v_position()) > ALIGN_EPSILON ||
last_direction != is->direction()
) {
- text.reset (new order::Text (subtitle, is->h_align(), is->h_position(), is->v_align(), is->v_position(), is->direction()));
+ text = make_shared<order::Text>(subtitle, is->h_align(), is->h_position(), is->v_align(), is->v_position(), is->direction());
subtitle->children.push_back (text);
last_h_align = is->h_align ();
last_direction = is->direction ();
}
- text->children.push_back (shared_ptr<order::String> (new order::String (text, order::Font (is, standard), is->text())));
+ text->children.push_back (make_shared<order::String>(text, order::Font (is, standard), is->text(), is->space_before()));
}
auto ii = dynamic_pointer_cast<SubtitleImage>(i);
if (ii) {
text.reset ();
subtitle->children.push_back (
- shared_ptr<order::Image> (new order::Image (subtitle, ii->id(), ii->png_image(), ii->h_align(), ii->h_position(), ii->v_align(), ii->v_position()))
+ make_shared<order::Image>(subtitle, ii->id(), ii->png_image(), ii->h_align(), ii->h_position(), ii->v_align(), ii->v_position())
);
}
}