#include "subtitle.h"
#include "compose.hpp"
#include <boost/algorithm/string.hpp>
-#include <boost/bind.hpp>
+#include <boost/bind/bind.hpp>
#include <iostream>
#include <vector>
using boost::optional;
using boost::function;
using namespace boost::algorithm;
+#if BOOST_VERSION >= 106100
+using namespace boost::placeholders;
+#endif
using namespace sub;
/** @param s Subtitle string encoded in UTF-8 */
effect = SHADOW;
}
} else if (keys[i] == "Alignment") {
- /* These values from libass' source code */
- switch ((raw_convert<int> (style[i]) - 1) % 3) {
- case 0:
- horizontal_reference = LEFT_OF_SCREEN;
- break;
- case 1:
- horizontal_reference = HORIZONTAL_CENTRE_OF_SCREEN;
- break;
- case 2:
- horizontal_reference = RIGHT_OF_SCREEN;
- break;
- }
- switch (raw_convert<int> (style[i]) & 12) {
- case 4:
+ if (style[i] == "7" || style[i] == "8" || style[i] == "9") {
vertical_reference = TOP_OF_SCREEN;
- break;
- case 8:
+ } else if (style[i] == "4" || style[i] == "5" || style[i] == "6") {
vertical_reference = VERTICAL_CENTRE_OF_SCREEN;
- break;
- case 0:
+ } else {
vertical_reference = BOTTOM_OF_SCREEN;
- break;
+ }
+ if (style[i] == "1" || style[i] == "4" || style[i] == "7") {
+ horizontal_reference = LEFT_OF_SCREEN;
+ } else if (style[i] == "3" || style[i] == "6" || style[i] == "9") {
+ horizontal_reference = RIGHT_OF_SCREEN;
+ } else {
+ horizontal_reference = HORIZONTAL_CENTRE_OF_SCREEN;
}
} else if (keys[i] == "MarginV") {
vertical_margin = raw_convert<int> (style[i]);
string name;
optional<string> font_name;
- int font_size;
+ int font_size; ///< points
Colour primary_colour;
/** outline colour */
optional<Colour> back_colour;
sub.vertical_position.proportional = raw_convert<float>(bits[2]) / play_res_y;
} else if (boost::starts_with(style, "\\fs")) {
SUB_ASSERT (style.length() > 3);
- sub.font_size.set_points (raw_convert<int>(style.substr(3)));
+ sub.font_size.set_proportional(raw_convert<float>(style.substr(3)) / play_res_y);
} else if (boost::starts_with(style, "\\c")) {
/* \c&Hbbggrr& */
if (style.length() <= 2) {
current.vertical_position.reference = BOTTOM_OF_SCREEN;
}
- if (!current.vertical_position.proportional) {
- current.vertical_position.proportional = 0;
- }
+ /* Any vertical_position that is set in base (and therefore current) is a margin, which
+ * we need to ignore if we end up vertically centering this subtitle.
+ * Clear out vertical_position from current; we'll re-add it from base later
+ * if required.
+ */
+ current.vertical_position.proportional = 0;
/* We must have a font size, as there could be a margin specified
in pixels and in that case we must know how big the subtitle
lines are to work out the position on screen.
*/
- if (!current.font_size.points()) {
- current.font_size.set_points (72);
+ if (!current.font_size.proportional()) {
+ current.font_size.set_proportional(72.0 / play_res_y);
}
/* Count the number of line breaks */
}
}
- /* Imagine that the screen is 792 points (i.e. 11 inches) high (as with DCP) */
- double const line_size = current.font_size.proportional(792) * 1.2;
-
- /* Tweak vertical_position accordingly */
- switch (current.vertical_position.reference.get()) {
- case TOP_OF_SCREEN:
- case TOP_OF_SUBTITLE:
- /* Nothing to do */
- break;
- case VERTICAL_CENTRE_OF_SCREEN:
- current.vertical_position.proportional = current.vertical_position.proportional.get() - ((line_breaks + 1) * line_size) / 2;
- break;
- case BOTTOM_OF_SCREEN:
- current.vertical_position.proportional = current.vertical_position.proportional.get() + line_breaks * line_size;
- break;
- }
+ /* There are vague indications that with ASS 1 point should equal 1 pixel */
+ double const line_size = current.font_size.proportional(play_res_y) * 1.2;
for (size_t i = 0; i < line.length(); ++i) {
char const c = line[i];
subs.push_back (current);
}
+ /* Now we definitely know the vertical position reference we can finish off the position */
+ for (auto& sub: subs) {
+ switch (sub.vertical_position.reference.get()) {
+ case TOP_OF_SCREEN:
+ case TOP_OF_SUBTITLE:
+ /* Just re-add any margins we came in with */
+ sub.vertical_position.proportional = sub.vertical_position.proportional.get() + base.vertical_position.proportional.get_value_or(0);
+ break;
+ case VERTICAL_CENTRE_OF_SCREEN:
+ /* Margins are ignored, but we need to centre */
+ sub.vertical_position.proportional = sub.vertical_position.proportional.get() - ((line_breaks + 1) * line_size) / 2;
+ break;
+ case BOTTOM_OF_SCREEN:
+ /* Re-add margins and account for each line */
+ sub.vertical_position.proportional =
+ sub.vertical_position.proportional.get()
+ + base.vertical_position.proportional.get_value_or(0)
+ + line_breaks * line_size;
+ break;
+ }
+ }
+
return subs;
}
SUB_ASSERT (styles.find(event[i]) != styles.end());
Style style = styles[event[i]];
sub.font = style.font_name;
- sub.font_size = FontSize::from_points (style.font_size);
+ sub.font_size = FontSize::from_proportional(static_cast<float>(style.font_size) / play_res_y);
sub.colour = style.primary_colour;
sub.effect_colour = style.back_colour;
sub.bold = style.bold;
sub.effect = style.effect;
sub.horizontal_position.reference = style.horizontal_reference;
sub.vertical_position.reference = style.vertical_reference;
- sub.vertical_position.proportional = float(style.vertical_margin) / play_res_y;
+ if (sub.vertical_position.reference != sub::VERTICAL_CENTRE_OF_SCREEN) {
+ sub.vertical_position.proportional = float(style.vertical_margin) / play_res_y;
+ }
} else if (event_format[i] == "MarginV") {
- sub.vertical_position.proportional = raw_convert<float>(event[i]) / play_res_y;
+ if (event[i] != "0" && sub.vertical_position.reference != sub::VERTICAL_CENTRE_OF_SCREEN) {
+ /* Override the style if its non-zero */
+ sub.vertical_position.proportional = raw_convert<float>(event[i]) / play_res_y;
+ }
} else if (event_format[i] == "Text") {
for (auto j: parse_line (sub, event[i], play_res_x, play_res_y)) {
_subs.push_back (j);