diff options
| author | Carl Hetherington <cth@carlh.net> | 2016-06-09 15:32:34 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2016-06-09 15:32:34 +0100 |
| commit | ca9dfb8c67721ad667e204e22908f4e5c723c2ce (patch) | |
| tree | 512b6f335a077d26a9c5b8cd2054cc89a1be9834 /src | |
| parent | dca56d88f34daa66d0df30e966030f84e99b4bea (diff) | |
Various work on improving vertical position handling.
Diffstat (limited to 'src')
| -rw-r--r-- | src/font_size.cc | 6 | ||||
| -rw-r--r-- | src/font_size.h | 2 | ||||
| -rw-r--r-- | src/ssa_reader.cc | 92 | ||||
| -rw-r--r-- | src/ssa_reader.h | 6 | ||||
| -rw-r--r-- | src/vertical_position.cc | 2 |
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 { |
