libdcp
subtitle_asset_internal.cc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2012-2021 Carl Hetherington <cth@carlh.net>
3 
4  This file is part of libdcp.
5 
6  libdcp is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  libdcp is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with libdcp. If not, see <http://www.gnu.org/licenses/>.
18 
19  In addition, as a special exception, the copyright holders give
20  permission to link the code of portions of this program with the
21  OpenSSL library under certain conditions as described in each
22  individual source file, and distribute linked combinations
23  including the two.
24 
25  You must obey the GNU General Public License in all respects
26  for all of the code used other than OpenSSL. If you modify
27  file(s) with this exception, you may extend this exception to your
28  version of the file(s), but you are not obligated to do so. If you
29  do not wish to do so, delete this exception statement from your
30  version. If you delete this exception statement from all source
31  files in the program, then also delete it here.
32 */
33 
34 
41 #include "subtitle_string.h"
42 #include "compose.hpp"
43 #include <cmath>
44 
45 
46 using std::string;
47 using std::map;
48 using std::shared_ptr;
49 using namespace dcp;
50 
51 
52 order::Font::Font (shared_ptr<SubtitleString> s, Standard standard)
53 {
54  if (s->font()) {
55  if (standard == Standard::SMPTE) {
56  _values["ID"] = s->font().get ();
57  } else {
58  _values["Id"] = s->font().get ();
59  }
60  }
61  _values["Italic"] = s->italic() ? "yes" : "no";
62  _values["Color"] = s->colour().to_argb_string();
63  _values["Size"] = raw_convert<string> (s->size());
64  _values["AspectAdjust"] = raw_convert<string>(s->aspect_adjust(), 1, true);
65  _values["Effect"] = effect_to_string (s->effect());
66  _values["EffectColor"] = s->effect_colour().to_argb_string();
67  _values["Script"] = "normal";
68  if (standard == Standard::SMPTE) {
69  _values["Underline"] = s->underline() ? "yes" : "no";
70  } else {
71  _values["Underlined"] = s->underline() ? "yes" : "no";
72  }
73  _values["Weight"] = s->bold() ? "bold" : "normal";
74 }
75 
76 
77 xmlpp::Element*
78 order::Font::as_xml (xmlpp::Element* parent, Context&) const
79 {
80  auto e = parent->add_child("Font");
81  for (const auto& i: _values) {
82  e->set_attribute (i.first, i.second);
83  }
84  return e;
85 }
86 
87 
91 void
93 {
94  map<string, string> inter;
95 
96  for (auto const& i: other._values) {
97  auto t = _values.find (i.first);
98  if (t != _values.end() && t->second == i.second) {
99  inter.insert (i);
100  }
101  }
102 
103  _values = inter;
104 }
105 
106 
108 void
110 {
111  map<string, string> diff;
112  for (auto const& i: _values) {
113  if (other._values.find (i.first) == other._values.end()) {
114  diff.insert (i);
115  }
116  }
117 
118  _values = diff;
119 }
120 
121 
122 bool
123 order::Font::empty () const
124 {
125  return _values.empty ();
126 }
127 
128 
129 xmlpp::Element*
130 order::Part::as_xml (xmlpp::Element* parent, Context &) const
131 {
132  return parent;
133 }
134 
135 
136 xmlpp::Element*
137 order::String::as_xml (xmlpp::Element* parent, Context& context) const
138 {
139  if (fabs(_space_before) > SPACE_BEFORE_EPSILON) {
140  auto space = parent->add_child("Space");
141  auto size = raw_convert<string>(_space_before, 2);
142  if (context.standard == Standard::INTEROP) {
143  size += "em";
144  }
145  space->set_attribute("Size", size);
146  }
147  parent->add_child_text (_text);
148  return 0;
149 }
150 
151 
152 void
153 order::Part::write_xml (xmlpp::Element* parent, order::Context& context) const
154 {
155  if (!font.empty ()) {
156  parent = font.as_xml (parent, context);
157  }
158 
159  parent = as_xml (parent, context);
160 
161  for (auto i: children) {
162  i->write_xml (parent, context);
163  }
164 }
165 
166 
167 static void
168 position_align (xmlpp::Element* e, order::Context& context, HAlign h_align, float h_position, VAlign v_align, float v_position)
169 {
170  if (h_align != HAlign::CENTER) {
171  if (context.standard == Standard::SMPTE) {
172  e->set_attribute ("Halign", halign_to_string (h_align));
173  } else {
174  e->set_attribute ("HAlign", halign_to_string (h_align));
175  }
176  }
177 
178  if (fabs(h_position) > ALIGN_EPSILON) {
179  if (context.standard == Standard::SMPTE) {
180  e->set_attribute ("Hposition", raw_convert<string> (h_position * 100, 6));
181  } else {
182  e->set_attribute ("HPosition", raw_convert<string> (h_position * 100, 6));
183  }
184  }
185 
186  if (context.standard == Standard::SMPTE) {
187  e->set_attribute ("Valign", valign_to_string (v_align));
188  } else {
189  e->set_attribute ("VAlign", valign_to_string (v_align));
190  }
191 
192  if (fabs(v_position) > ALIGN_EPSILON) {
193  if (context.standard == Standard::SMPTE) {
194  e->set_attribute ("Vposition", raw_convert<string> (v_position * 100, 6));
195  } else {
196  e->set_attribute ("VPosition", raw_convert<string> (v_position * 100, 6));
197  }
198  } else {
199  if (context.standard == Standard::SMPTE) {
200  e->set_attribute ("Vposition", "0");
201  } else {
202  e->set_attribute ("VPosition", "0");
203  }
204  }
205 }
206 
207 
208 xmlpp::Element*
209 order::Text::as_xml (xmlpp::Element* parent, Context& context) const
210 {
211  auto e = parent->add_child ("Text");
212 
213  position_align (e, context, _h_align, _h_position, _v_align, _v_position);
214 
215  /* Interop only supports "horizontal" or "vertical" for direction, so only write this
216  for SMPTE.
217  */
218  if (_direction != Direction::LTR && context.standard == Standard::SMPTE) {
219  e->set_attribute ("Direction", direction_to_string (_direction));
220  }
221 
222  return e;
223 }
224 
225 
226 xmlpp::Element*
227 order::Subtitle::as_xml (xmlpp::Element* parent, Context& context) const
228 {
229  auto e = parent->add_child ("Subtitle");
230  e->set_attribute ("SpotNumber", raw_convert<string> (context.spot_number++));
231  e->set_attribute ("TimeIn", _in.rebase(context.time_code_rate).as_string(context.standard));
232  e->set_attribute ("TimeOut", _out.rebase(context.time_code_rate).as_string(context.standard));
233  if (context.standard == Standard::SMPTE) {
234  e->set_attribute ("FadeUpTime", _fade_up.rebase(context.time_code_rate).as_string(context.standard));
235  e->set_attribute ("FadeDownTime", _fade_down.rebase(context.time_code_rate).as_string(context.standard));
236  } else {
237  e->set_attribute ("FadeUpTime", raw_convert<string> (_fade_up.as_editable_units_ceil(context.time_code_rate)));
238  e->set_attribute ("FadeDownTime", raw_convert<string> (_fade_down.as_editable_units_ceil(context.time_code_rate)));
239  }
240  return e;
241 }
242 
243 
244 bool
245 order::Font::operator== (Font const & other) const
246 {
247  return _values == other._values;
248 }
249 
250 
251 void
252 order::Font::clear ()
253 {
254  _values.clear ();
255 }
256 
257 
258 xmlpp::Element *
259 order::Image::as_xml (xmlpp::Element* parent, Context& context) const
260 {
261  auto e = parent->add_child ("Image");
262 
263  position_align (e, context, _h_align, _h_position, _v_align, _v_position);
264  if (context.standard == Standard::SMPTE) {
265  e->add_child_text ("urn:uuid:" + _id);
266  } else {
267  e->add_child_text (_id + ".png");
268  }
269 
270  return e;
271 }
void take_difference(Font other)
void take_intersection(Font other)
Namespace for everything in libdcp.
Definition: array_data.h:50
@ LTR
left-to-right
HAlign
Definition: types.h:166
@ CENTER
horizontal position is distance from centre of screen to centre of subtitle
constexpr float SPACE_BEFORE_EPSILON
Definition: types.h:355
VAlign
Definition: types.h:178
constexpr float ALIGN_EPSILON
Definition: types.h:349
Internal SubtitleAsset helpers.
SubtitleString class.