summaryrefslogtreecommitdiff
path: root/src/text_asset.cc
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2024-11-07 11:40:54 +0100
committerCarl Hetherington <cth@carlh.net>2024-11-07 11:40:54 +0100
commitd9c82bd6ce614bef3cd553ac1aa931a0e0ee102a (patch)
tree05002a78d0a76bb70b697c071079d5e7fc4bb23e /src/text_asset.cc
parentcf052af049d43068fee2ceb205249b35436f6e26 (diff)
Diffstat (limited to 'src/text_asset.cc')
-rw-r--r--src/text_asset.cc174
1 files changed, 101 insertions, 73 deletions
diff --git a/src/text_asset.cc b/src/text_asset.cc
index 1a58d22f..82423862 100644
--- a/src/text_asset.cc
+++ b/src/text_asset.cc
@@ -42,10 +42,11 @@
#include "load_font_node.h"
#include "raw_convert.h"
#include "reel_asset.h"
-#include "text_image.h"
-#include "text_string.h"
#include "text_asset.h"
#include "text_asset_internal.h"
+#include "text_image.h"
+#include "text_ruby.h"
+#include "text_string.h"
#include "util.h"
#include "xml.h"
#include <asdcp/AS_DCP.h>
@@ -229,6 +230,36 @@ TextAsset::text_node_state(xmlpp::Element const * node) const
TextAsset::ParseState
+TextAsset::ruby_node_state(xmlpp::Element const* node) const
+{
+ ParseState ps;
+
+ if (auto size = optional_string_attribute(node, "Size")) {
+ boost::replace_all(*size, "em", "");
+ ps.ruby_size = dcp::raw_convert<float>(*size);
+ }
+
+ if (auto position = optional_string_attribute(node, "Position")) {
+ ps.ruby_position = *position == "before" ? RubyPosition::BEFORE : RubyPosition::AFTER;
+ }
+
+ if (auto offset = optional_string_attribute(node, "Offset")) {
+ boost::replace_all(*offset, "em", "");
+ ps.ruby_offset = dcp::raw_convert<float>(*offset);
+ }
+
+ if (auto spacing = optional_string_attribute(node, "Spacing")) {
+ boost::replace_all(*spacing, "em", "");
+ ps.ruby_spacing = dcp::raw_convert<float>(*spacing);
+ }
+
+ if (auto aspect_adjust = optional_number_attribute<float>(node, "AspectAdjust")) {
+ ps.ruby_aspect_adjust = *aspect_adjust;
+ }
+}
+
+
+TextAsset::ParseState
TextAsset::image_node_state(xmlpp::Element const * node) const
{
ParseState ps;
@@ -275,26 +306,12 @@ TextAsset::fade_time(xmlpp::Element const * node, string name, optional<int> tcr
}
+/** Recursively scan node finding text, image and ruby content, keeping track of the currently applicable attributes so that
+ * TextString, TextImage or TextRuby objects can be added to _texts to reflect the contents of node.
+ */
void
TextAsset::parse_texts(xmlpp::Element const * node, vector<ParseState>& state, optional<int> tcr, Standard standard)
{
- if (node->get_name() == "Font") {
- state.push_back (font_node_state (node, standard));
- } else if (node->get_name() == "Subtitle") {
- state.push_back (subtitle_node_state (node, tcr));
- } else if (node->get_name() == "Text") {
- state.push_back (text_node_state (node));
- } else if (node->get_name() == "SubtitleList") {
- state.push_back (ParseState ());
- } else if (node->get_name() == "Image") {
- state.push_back (image_node_state (node));
- } else {
- throw XMLError ("unexpected node " + node->get_name());
- }
-
- 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()) {
@@ -306,61 +323,74 @@ 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);
- }
+ if (node->get_name() == "Font") {
+ state.push_back (font_node_state (node, standard));
+ } else if (node->get_name() == "Subtitle") {
+ state.push_back (subtitle_node_state (node, tcr));
+ } else if (node->get_name() == "Text") {
+ state.push_back (text_node_state (node));
+ } else if (node->get_name() == "SubtitleList") {
+ state.push_back (ParseState ());
+ } else if (node->get_name() == "Image") {
+ state.push_back (image_node_state (node));
+ } else if (node->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: node->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");
}
+ 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);
}
+ DCP_ASSERT(base);
+ DCP_ASSERT(annotation);
+ ParseState ps(state);
+ _texts.push_back(
+ make_shared<TextRuby>(
+ ps.in.get(),
+ ps.out.get(),
+ ps.h_position.get_value_or(0),
+ ps.h_align.get_value_or(HAlign::CENTER),
+ ps.v_position.get_value_or(0),
+ ps.v_align.get_value_or(VAlign::CENTER),
+ ps.z_position.get_value_or(0),
+ ps.direction.get_value_or (Direction::LTR),
+ *base,
+ *annotation,
+ size.get_value_or(0.5),
+ position.get_value_or(RubyPosition::BEFORE),
+ offset.get_value_or(0),
+ spacing.get_value_or(0),
+ aspect_adjust.get_value_or(1.0)
+ )
+ );
+ } else {
+ throw XMLError ("unexpected node " + node->get_name());
}
+ float space_before = 0;
+
for (auto i: node->get_children()) {
/* Handle actual content e.g. text */
@@ -382,8 +412,8 @@ 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 {
+ parse_texts(e, state, tcr, standard);
}
}
}
@@ -397,8 +427,7 @@ TextAsset::maybe_add_text(
string text,
vector<ParseState> const & parse_state,
float space_before,
- Standard standard,
- vector<Ruby> const& rubies
+ Standard standard
)
{
auto wanted = [](ParseState const& ps) {
@@ -441,8 +470,7 @@ 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;