*/
-#include "raw_convert.h"
#include "compose.hpp"
+#include "dcp_assert.h"
+#include "load_font_node.h"
+#include "raw_convert.h"
+#include "reel_asset.h"
#include "subtitle_asset.h"
#include "subtitle_asset_internal.h"
+#include "subtitle_image.h"
+#include "subtitle_string.h"
#include "util.h"
#include "xml.h"
-#include "subtitle_string.h"
-#include "subtitle_image.h"
-#include "dcp_assert.h"
-#include "load_font_node.h"
-#include "reel_asset.h"
#include <asdcp/AS_DCP.h>
#include <asdcp/KM_util.h>
#include <libxml++/nodes/element.h>
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") {
boost::replace_all(size, "em", "");
}
space_before += raw_convert<float>(size);
- } else {
+ } else if (e->get_name() != "Ruby") {
parse_subtitles (e, state, tcr, standard);
}
}
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);
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;
}
-/* XXX: this needs a test */
-vector<shared_ptr<const Subtitle>>
-SubtitleAsset::subtitles_in_reel (shared_ptr<const dcp::ReelAsset> asset) const
-{
- auto frame_rate = asset->edit_rate().as_float();
- auto start = dcp::Time(asset->entry_point().get_value_or(0), frame_rate, time_code_rate());
- auto during = subtitles_during (start, start + dcp::Time(asset->intrinsic_duration(), frame_rate, time_code_rate()), false);
-
- vector<shared_ptr<const dcp::Subtitle>> corrected;
- for (auto i: during) {
- auto c = make_shared<dcp::Subtitle>(*i);
- c->set_in (c->in() - start);
- c->set_out (c->out() - start);
- corrected.push_back (c);
- }
-
- return corrected;
-}
-
-
void
SubtitleAsset::add (shared_ptr<Subtitle> 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 ();