+
+ 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, rubies);
+ space_before = 0;
+ }
+
+ /* Handle other nodes */
+ auto const e = dynamic_cast<xmlpp::Element const *>(i);
+ if (e) {
+ 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 if (e->get_name() != "Ruby") {
+ parse_subtitles (e, state, tcr, standard);
+ }
+ }
+ }
+
+ state.pop_back ();