summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libass/ass.c124
1 files changed, 95 insertions, 29 deletions
diff --git a/libass/ass.c b/libass/ass.c
index ca76347..cb0e9ac 100644
--- a/libass/ass.c
+++ b/libass/ass.c
@@ -77,6 +77,22 @@ struct parser_priv {
uint32_t header_flags;
};
+static const char *const ass_style_format =
+ "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, "
+ "OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, "
+ "ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, "
+ "Alignment, MarginL, MarginR, MarginV, Encoding";
+static const char *const ass_event_format =
+ "Layer, Start, End, Style, Name, "
+ "MarginL, MarginR, MarginV, Effect, Text";
+static const char *const ssa_style_format =
+ "Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, "
+ "TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline, "
+ "Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding";
+static const char *const ssa_event_format =
+ "Marked, Start, End, Style, Name, "
+ "MarginL, MarginR, MarginV, Effect, Text";
+
#define ASS_STYLES_ALLOC 20
int ass_library_version(void)
@@ -301,25 +317,31 @@ static long long string2timecode(ASS_Library *library, char *p)
} else if (ass_strcasecmp(tname, #name) == 0) { \
target->name = lookup_style(track, token);
+// skip spaces in str beforehand, or trim leading spaces afterwards
+static inline void advance_token_pos(const char **const str,
+ const char **const start,
+ const char **const end)
+{
+ *start = *str;
+ *end = *start;
+ while (**end != '\0' && **end != ',') ++*end;
+ *str = *end + (**end == ',');
+ rskip_spaces((char**)end, (char*)*start);
+}
+
static char *next_token(char **str)
{
- char *p = *str;
+ char *p;
char *start;
- skip_spaces(&p);
- if (*p == '\0') {
- *str = p;
+ skip_spaces(str);
+ if (**str == '\0') {
return 0;
}
- start = p; // start of the token
- for (; (*p != '\0') && (*p != ','); ++p) {
- }
- if (*p == '\0') {
- *str = p; // eos found, str will point to '\0' at exit
- } else {
- *p = '\0';
- *str = p + 1; // ',' found, str will point to the next char (beginning of the next token)
- }
- rskip_spaces(&p, start); // end of current token: the first space character, or '\0'
+
+ advance_token_pos((const char**)str,
+ (const char**)&start,
+ (const char**)&p);
+
*p = '\0';
return start;
}
@@ -494,18 +516,9 @@ static int process_style(ASS_Track *track, char *str)
// no style format header
// probably an ancient script version
if (track->track_type == TRACK_TYPE_SSA)
- track->style_format =
- strdup
- ("Name, Fontname, Fontsize, PrimaryColour, SecondaryColour,"
- "TertiaryColour, BackColour, Bold, Italic, BorderStyle, Outline,"
- "Shadow, Alignment, MarginL, MarginR, MarginV, AlphaLevel, Encoding");
+ track->style_format = strdup(ssa_style_format);
else
- track->style_format =
- strdup
- ("Name, Fontname, Fontsize, PrimaryColour, SecondaryColour,"
- "OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut,"
- "ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow,"
- "Alignment, MarginL, MarginR, MarginV, Encoding");
+ track->style_format = strdup(ass_style_format);
}
q = format = strdup(track->style_format);
@@ -590,6 +603,53 @@ static int process_style(ASS_Track *track, char *str)
}
+static bool format_line_compare(const char *fmt1, const char *fmt2)
+{
+ while (true) {
+ const char *tk1_start, *tk2_start;
+ const char *tk1_end, *tk2_end;
+
+ skip_spaces((char**)&fmt1);
+ skip_spaces((char**)&fmt2);
+ if (!*fmt1 || !*fmt2)
+ break;
+
+ advance_token_pos(&fmt1, &tk1_start, &tk1_end);
+ advance_token_pos(&fmt2, &tk2_start, &tk2_end);
+
+ if ((tk1_end-tk1_start) != (tk2_end-tk2_start))
+ return false;
+ if (ass_strncasecmp(tk1_start, tk2_start, tk1_end-tk1_start))
+ return false;
+ }
+ return *fmt1 == *fmt2;
+}
+
+
+/**
+ * \brief Set SBAS=1 if not set explicitly in case of custom format line
+ * \param track track
+ * \param fmt format line of file
+ * \param std standard format line
+ *
+ * As of writing libass is the only renderer accepting custom format lines.
+ * For years libass defaultet SBAS to yes instead of no.
+ * To avoid breaking released scripts with custom format lines,
+ * keep SBAS=1 default for custom format files.
+ */
+static void custom_format_line_compatibility(ASS_Track *const track,
+ const char *const fmt,
+ const char *const std)
+{
+ if (!(track->parser_priv->header_flags & SINFO_SCALEDBORDER)
+ && !format_line_compare(fmt, std)) {
+ ass_msg(track->library, MSGL_INFO,
+ "Track has custom format line(s). "
+ "'ScaledBorderAndShadow' will default to 'yes'.");
+ track->ScaledBorderAndShadow = 1;
+ }
+}
+
static int process_styles_line(ASS_Track *track, char *str)
{
if (!strncmp(str, "Format:", 7)) {
@@ -599,6 +659,10 @@ static int process_styles_line(ASS_Track *track, char *str)
track->style_format = strdup(p);
ass_msg(track->library, MSGL_DBG2, "Style format: %s",
track->style_format);
+ if (track->track_type == TRACK_TYPE_ASS)
+ custom_format_line_compatibility(track, p, ass_style_format);
+ else
+ custom_format_line_compatibility(track, p, ssa_style_format);
} else if (!strncmp(str, "Style:", 6)) {
char *p = str + 6;
skip_spaces(&p);
@@ -657,11 +721,9 @@ static void event_format_fallback(ASS_Track *track)
{
track->parser_priv->state = PST_EVENTS;
if (track->track_type == TRACK_TYPE_SSA)
- track->event_format = strdup("Marked, Start, End, Style, "
- "Name, MarginL, MarginR, MarginV, Effect, Text");
+ track->event_format = strdup(ssa_event_format);
else
- track->event_format = strdup("Layer, Start, End, Style, "
- "Actor, MarginL, MarginR, MarginV, Effect, Text");
+ track->event_format = strdup(ass_event_format);
ass_msg(track->library, MSGL_V,
"No event format found, using fallback");
}
@@ -674,6 +736,10 @@ static int process_events_line(ASS_Track *track, char *str)
free(track->event_format);
track->event_format = strdup(p);
ass_msg(track->library, MSGL_DBG2, "Event format: %s", track->event_format);
+ if (track->track_type == TRACK_TYPE_ASS)
+ custom_format_line_compatibility(track, p, ass_event_format);
+ else
+ custom_format_line_compatibility(track, p, ssa_event_format);
} else if (!strncmp(str, "Dialogue:", 9)) {
// This should never be reached for embedded subtitles.
// They have slightly different format and are parsed in ass_process_chunk,