summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2016-06-09 15:32:34 +0100
committerCarl Hetherington <cth@carlh.net>2016-06-09 15:32:34 +0100
commitca9dfb8c67721ad667e204e22908f4e5c723c2ce (patch)
tree512b6f335a077d26a9c5b8cd2054cc89a1be9834 /src
parentdca56d88f34daa66d0df30e966030f84e99b4bea (diff)
Various work on improving vertical position handling.
Diffstat (limited to 'src')
-rw-r--r--src/font_size.cc6
-rw-r--r--src/font_size.h2
-rw-r--r--src/ssa_reader.cc92
-rw-r--r--src/ssa_reader.h6
-rw-r--r--src/vertical_position.cc2
5 files changed, 93 insertions, 15 deletions
diff --git a/src/font_size.cc b/src/font_size.cc
index f3e6c89..5e5fd4c 100644
--- a/src/font_size.cc
+++ b/src/font_size.cc
@@ -48,3 +48,9 @@ FontSize::from_points (int p)
s.set_points (p);
return s;
}
+
+bool
+FontSize::specified () const
+{
+ return _proportional || _points;
+}
diff --git a/src/font_size.h b/src/font_size.h
index 62bbd09..2ff4a7c 100644
--- a/src/font_size.h
+++ b/src/font_size.h
@@ -49,6 +49,8 @@ public:
return _points;
}
+ bool specified () const;
+
float proportional (int screen_height_in_points) const;
int points (int screen_height_in_points) const;
diff --git a/src/ssa_reader.cc b/src/ssa_reader.cc
index c76a78d..b3df458 100644
--- a/src/ssa_reader.cc
+++ b/src/ssa_reader.cc
@@ -57,17 +57,21 @@ class Style
{
public:
Style ()
- : font_size (24)
+ : font_size (72)
, primary_colour (255, 255, 255)
, bold (false)
, italic (false)
+ , vertical_reference (BOTTOM_OF_SCREEN)
+ , vertical_margin (0)
{}
Style (string format_line, string style_line)
- : font_size (24)
+ : font_size (72)
, primary_colour (255, 255, 255)
, bold (false)
, italic (false)
+ , vertical_reference (BOTTOM_OF_SCREEN)
+ , vertical_margin (0)
{
vector<string> keys;
split (keys, format_line, is_any_of (","));
@@ -99,6 +103,21 @@ public:
if (style[i] == "1") {
effect = SHADOW;
}
+ } else if (keys[i] == "Alignment") {
+ /* These values from libass' source code */
+ switch (raw_convert<int> (style[i]) & 12) {
+ case 4:
+ vertical_reference = TOP_OF_SCREEN;
+ break;
+ case 8:
+ vertical_reference = CENTRE_OF_SCREEN;
+ break;
+ case 0:
+ vertical_reference = BOTTOM_OF_SCREEN;
+ break;
+ }
+ } else if (keys[i] == "MarginV") {
+ vertical_margin = raw_convert<int> (style[i]);
}
}
}
@@ -112,6 +131,8 @@ public:
bool bold;
bool italic;
optional<Effect> effect;
+ VerticalReference vertical_reference;
+ int vertical_margin;
private:
Colour colour (int c) const
@@ -139,7 +160,7 @@ SSAReader::parse_time (string t) const
}
/** @param base RawSubtitle filled in with any required common values.
- * @param line SSA line string.
+ * @param line SSA line string (i.e. just the subtitle, possibly with embedded stuff)
* @return List of RawSubtitles to represent line with vertical reference TOP_OF_SUBTITLE.
*/
list<RawSubtitle>
@@ -155,10 +176,46 @@ SSAReader::parse_line (RawSubtitle base, string line)
RawSubtitle current = base;
string style;
- current.vertical_position.line = 0;
- /* XXX: arbitrary */
- current.vertical_position.lines = 32;
- current.vertical_position.reference = TOP_OF_SUBTITLE;
+ if (!current.vertical_position.reference) {
+ current.vertical_position.reference = BOTTOM_OF_SCREEN;
+ }
+
+ if (!current.vertical_position.proportional) {
+ 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);
+ }
+
+ /* Count the number of line breaks */
+ int line_breaks = 0;
+ for (size_t i = 0; i < line.length() - 1; ++i) {
+ if (line[i] == '\\' && (line[i+1] == 'n' || line[i+1] == 'N')) {
+ ++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 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;
+ }
for (size_t i = 0; i < line.length(); ++i) {
char const c = line[i];
@@ -193,7 +250,12 @@ SSAReader::parse_line (RawSubtitle base, string line)
if ((c == 'n' || c == 'N') && !current.text.empty ()) {
subs.push_back (current);
current.text = "";
- current.vertical_position.line = current.vertical_position.line.get() + 1;
+ /* Move down one line (1.2 times the font size) */
+ if (current.vertical_position.reference.get() == BOTTOM_OF_SCREEN) {
+ current.vertical_position.proportional = current.vertical_position.proportional.get() - line_size;
+ } else {
+ current.vertical_position.proportional = current.vertical_position.proportional.get() + line_size;
+ }
}
state = TEXT;
break;
@@ -216,6 +278,7 @@ SSAReader::read (function<optional<string> ()> get_line)
EVENTS
} part = INFO;
+ int play_res_y = 288;
map<string, Style> styles;
string style_format_line;
vector<string> event_format;
@@ -253,6 +316,9 @@ SSAReader::read (function<optional<string> ()> get_line)
switch (part) {
case INFO:
+ if (type == "PlayResY") {
+ play_res_y = raw_convert<int> (body);
+ }
break;
case STYLES:
if (type == "Format") {
@@ -304,12 +370,10 @@ SSAReader::read (function<optional<string> ()> get_line)
sub.bold = style.bold;
sub.italic = style.italic;
sub.effect = style.effect;
-
- /* XXX: arbitrary */
- sub.vertical_position.lines = 32;
- sub.vertical_position.reference = TOP_OF_SUBTITLE;
- sub.vertical_position.line = 0;
-
+ sub.vertical_position.reference = style.vertical_reference;
+ 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;
} else if (event_format[i] == "Text") {
BOOST_FOREACH (sub::RawSubtitle j, parse_line (sub, event[i])) {
_subs.push_back (j);
diff --git a/src/ssa_reader.h b/src/ssa_reader.h
index 1fe64f3..59c9e86 100644
--- a/src/ssa_reader.h
+++ b/src/ssa_reader.h
@@ -29,6 +29,12 @@
namespace sub {
+/** @class SSAReader
+ * @brief Reader for SubStation Alpha (SSA) and Advanced Substation Alpha (ASS) subtitles.
+ *
+ * This reader implements some of the SSA and ASS "standards", as gathered from various
+ * documents on the web.
+ */
class SSAReader : public Reader
{
public:
diff --git a/src/vertical_position.cc b/src/vertical_position.cc
index a680188..817c366 100644
--- a/src/vertical_position.cc
+++ b/src/vertical_position.cc
@@ -18,10 +18,10 @@
*/
#include "vertical_position.h"
+#include <iostream>
using namespace sub;
-
float
VerticalPosition::fraction_from_screen_top () const
{