}
/** @return TextContents from node or <Text> nodes under node (according to version).
- * The list could be empty if no TextContents are found.
+ * The vector could be empty if no TextContents are found.
*/
-list<shared_ptr<TextContent>>
-TextContent::from_xml (Content* parent, cxml::ConstNodePtr node, int version)
+vector<shared_ptr<TextContent>>
+TextContent::from_xml (Content* parent, cxml::ConstNodePtr node, int version, list<string>& notes)
{
if (version < 34) {
/* With old metadata FFmpeg content has the subtitle-related tags even with no
if (!node->optional_number_child<double>("SubtitleXOffset") && !node->optional_number_child<double>("SubtitleOffset")) {
return {};
}
- return { make_shared<TextContent>(parent, node, version) };
+ return { make_shared<TextContent>(parent, node, version, notes) };
}
- if (!node->optional_node_child("Text")) {
- return {};
- }
-
- list<shared_ptr<TextContent>> c;
+ vector<shared_ptr<TextContent>> content;
for (auto i: node->node_children("Text")) {
- c.push_back (make_shared<TextContent>(parent, i, version));
+ content.push_back(make_shared<TextContent>(parent, i, version, notes));
}
- return c;
+ return content;
}
-TextContent::TextContent (Content* parent, cxml::ConstNodePtr node, int version)
+
+TextContent::TextContent (Content* parent, cxml::ConstNodePtr node, int version, list<string>& notes)
: ContentPart (parent)
, _use (false)
, _burn (false)
_effect = dcp::Effect::BORDER;
} else if (node->optional_bool_child("Shadow").get_value_or(false)) {
_effect = dcp::Effect::SHADOW;
- } else {
- _effect = dcp::Effect::NONE;
}
auto effect = node->optional_string_child("Effect");
auto lang = node->optional_node_child("Language");
if (lang) {
- _language = dcp::LanguageTag(lang->content());
- auto add = lang->optional_bool_attribute("Additional");
- _language_is_additional = add && *add;
+ try {
+ _language = dcp::LanguageTag(lang->content());
+ auto additional = lang->optional_bool_attribute("Additional");
+ if (!additional) {
+ additional = lang->optional_bool_attribute("additional");
+ }
+ _language_is_additional = additional.get_value_or(false);
+ } catch (dcp::LanguageTagError&) {
+ /* The language tag can be empty or invalid if it was loaded from a
+ * 2.14.x metadata file; we'll just ignore it in that case.
+ */
+ if (version <= 37) {
+ if (!lang->content().empty()) {
+ notes.push_back (String::compose(
+ _("A subtitle or closed caption file in this project is marked with the language '%1', "
+ "which DCP-o-matic does not recognise. The file's language has been cleared."), lang->content()));
+ }
+ } else {
+ throw;
+ }
+ }
}
}
/** _mutex must not be held on entry */
void
-TextContent::as_xml (xmlpp::Node* root) const
+TextContent::as_xml(xmlpp::Element* root) const
{
boost::mutex::scoped_lock lm (_mutex);
- auto text = root->add_child ("Text");
+ auto text = cxml::add_child(root, "Text");
- text->add_child("Use")->add_child_text (_use ? "1" : "0");
- text->add_child("Burn")->add_child_text (_burn ? "1" : "0");
- text->add_child("XOffset")->add_child_text (raw_convert<string> (_x_offset));
- text->add_child("YOffset")->add_child_text (raw_convert<string> (_y_offset));
- text->add_child("XScale")->add_child_text (raw_convert<string> (_x_scale));
- text->add_child("YScale")->add_child_text (raw_convert<string> (_y_scale));
+ cxml::add_text_child(text, "Use", _use ? "1" : "0");
+ cxml::add_text_child(text, "Burn", _burn ? "1" : "0");
+ cxml::add_text_child(text, "XOffset", raw_convert<string>(_x_offset));
+ cxml::add_text_child(text, "YOffset", raw_convert<string>(_y_offset));
+ cxml::add_text_child(text, "XScale", raw_convert<string>(_x_scale));
+ cxml::add_text_child(text, "YScale", raw_convert<string>(_y_scale));
if (_colour) {
- text->add_child("Red")->add_child_text (raw_convert<string> (_colour->r));
- text->add_child("Green")->add_child_text (raw_convert<string> (_colour->g));
- text->add_child("Blue")->add_child_text (raw_convert<string> (_colour->b));
+ cxml::add_text_child(text, "Red", raw_convert<string>(_colour->r));
+ cxml::add_text_child(text, "Green", raw_convert<string>(_colour->g));
+ cxml::add_text_child(text, "Blue", raw_convert<string>(_colour->b));
}
if (_effect) {
switch (*_effect) {
case dcp::Effect::NONE:
- text->add_child("Effect")->add_child_text("none");
+ cxml::add_text_child(text, "Effect", "none");
break;
case dcp::Effect::BORDER:
- text->add_child("Effect")->add_child_text("outline");
+ cxml::add_text_child(text, "Effect", "outline");
break;
case dcp::Effect::SHADOW:
- text->add_child("Effect")->add_child_text("shadow");
+ cxml::add_text_child(text, "Effect", "shadow");
break;
}
}
if (_effect_colour) {
- text->add_child("EffectRed")->add_child_text (raw_convert<string> (_effect_colour->r));
- text->add_child("EffectGreen")->add_child_text (raw_convert<string> (_effect_colour->g));
- text->add_child("EffectBlue")->add_child_text (raw_convert<string> (_effect_colour->b));
+ cxml::add_text_child(text, "EffectRed", raw_convert<string>(_effect_colour->r));
+ cxml::add_text_child(text, "EffectGreen", raw_convert<string>(_effect_colour->g));
+ cxml::add_text_child(text, "EffectBlue", raw_convert<string>(_effect_colour->b));
}
- text->add_child("LineSpacing")->add_child_text (raw_convert<string> (_line_spacing));
+ cxml::add_text_child(text, "LineSpacing", raw_convert<string>(_line_spacing));
if (_fade_in) {
- text->add_child("FadeIn")->add_child_text (raw_convert<string> (_fade_in->get()));
+ cxml::add_text_child(text, "FadeIn", raw_convert<string>(_fade_in->get()));
}
if (_fade_out) {
- text->add_child("FadeOut")->add_child_text (raw_convert<string> (_fade_out->get()));
+ cxml::add_text_child(text, "FadeOut", raw_convert<string>(_fade_out->get()));
}
- text->add_child("OutlineWidth")->add_child_text (raw_convert<string> (_outline_width));
+ cxml::add_text_child(text, "OutlineWidth", raw_convert<string>(_outline_width));
for (auto i: _fonts) {
- i->as_xml (text->add_child("Font"));
+ i->as_xml(cxml::add_child(text, "Font"));
}
- text->add_child("Type")->add_child_text (text_type_to_string(_type));
- text->add_child("OriginalType")->add_child_text (text_type_to_string(_original_type));
+ cxml::add_text_child(text, "Type", text_type_to_string(_type));
+ cxml::add_text_child(text, "OriginalType", text_type_to_string(_original_type));
if (_dcp_track) {
- _dcp_track->as_xml(text->add_child("DCPTrack"));
+ _dcp_track->as_xml(cxml::add_child(text, "DCPTrack"));
}
if (_language) {
- auto lang = text->add_child("Language");
+ auto lang = cxml::add_child(text, "Language");
lang->add_child_text (_language->to_string());
- lang->set_attribute ("Additional", _language_is_additional ? "1" : "0");
+ lang->set_attribute("additional", _language_is_additional ? "1" : "0");
}
}
void
TextContent::add_font (shared_ptr<Font> font)
{
+ boost::mutex::scoped_lock lm(_mutex);
+
+ DCPOMATIC_ASSERT(!get_font_unlocked(font->id()));
_fonts.push_back (font);
connect_to_fonts ();
}
set_language (c->_language);
set_language_is_additional (c->_language_is_additional);
}
+
+
+shared_ptr<dcpomatic::Font>
+TextContent::get_font(string id) const
+{
+ boost::mutex::scoped_lock lm(_mutex);
+ return get_font_unlocked(id);
+}
+
+
+shared_ptr<dcpomatic::Font>
+TextContent::get_font_unlocked(string id) const
+{
+ auto iter = std::find_if(_fonts.begin(), _fonts.end(), [&id](shared_ptr<dcpomatic::Font> font) {
+ return font->id() == id;
+ });
+
+ if (iter == _fonts.end()) {
+ return {};
+ }
+
+ return *iter;
+}
+
+
+void
+TextContent::clear_fonts()
+{
+ boost::mutex::scoped_lock lm(_mutex);
+
+ _fonts.clear();
+}
+