*
* This file is part of libass.
*
- * libass is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * libass is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with libass; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <inttypes.h>
+#include <ctype.h>
#ifdef CONFIG_ICONV
#include <iconv.h>
#include "ass_utils.h"
#include "ass_library.h"
+#define ass_atof(STR) (ass_strtod((STR),NULL))
+
typedef enum {
PST_UNKNOWN = 0,
PST_INFO,
int i;
if (track->parser_priv) {
- if (track->parser_priv->fontname)
- free(track->parser_priv->fontname);
- if (track->parser_priv->fontdata)
- free(track->parser_priv->fontdata);
+ free(track->parser_priv->fontname);
+ free(track->parser_priv->fontdata);
free(track->parser_priv);
}
- if (track->style_format)
- free(track->style_format);
- if (track->event_format)
- free(track->event_format);
+ free(track->style_format);
+ free(track->event_format);
+ free(track->Language);
if (track->styles) {
for (i = 0; i < track->n_styles; ++i)
ass_free_style(track, i);
- free(track->styles);
}
+ free(track->styles);
if (track->events) {
for (i = 0; i < track->n_events; ++i)
ass_free_event(track, i);
- free(track->events);
}
+ free(track->events);
free(track->name);
free(track);
}
void ass_free_event(ASS_Track *track, int eid)
{
ASS_Event *event = track->events + eid;
- if (event->Name)
- free(event->Name);
- if (event->Effect)
- free(event->Effect);
- if (event->Text)
- free(event->Text);
- if (event->render_priv)
- free(event->render_priv);
+
+ free(event->Name);
+ free(event->Effect);
+ free(event->Text);
+ free(event->render_priv);
}
void ass_free_style(ASS_Track *track, int sid)
{
ASS_Style *style = track->styles + sid;
- if (style->Name)
- free(style->Name);
- if (style->FontName)
- free(style->FontName);
+
+ free(style->Name);
+ free(style->FontName);
}
// ==============================================================================================
}
/**
- * \brief find style by name
- * \param track track
- * \param name style name
- * \return index in track->styles
- * Returnes 0 if no styles found => expects at least 1 style.
- * Parsing code always adds "Default" style in the end.
+ * \brief Set up default style
+ * \param style style to edit to defaults
+ * The parameters are mostly taken directly from VSFilter source for
+ * best compatibility.
*/
-static int lookup_style(ASS_Track *track, char *name)
+static void set_default_style(ASS_Style *style)
{
- int i;
- if (*name == '*')
- ++name; // FIXME: what does '*' really mean ?
- for (i = track->n_styles - 1; i >= 0; --i) {
- // FIXME: mb strcasecmp ?
- if (strcmp(track->styles[i].Name, name) == 0)
- return i;
- }
- i = track->default_style;
- ass_msg(track->library, MSGL_WARN,
- "[%p]: Warning: no style named '%s' found, using '%s'",
- track, name, track->styles[i].Name);
- return i; // use the first style
+ style->Name = strdup("Default");
+ style->FontName = strdup("Arial");
+ style->FontSize = 18;
+ style->PrimaryColour = 0xffffff00;
+ style->SecondaryColour = 0x00ffff00;
+ style->OutlineColour = 0x00000000;
+ style->BackColour = 0x00000080;
+ style->Bold = 200;
+ style->ScaleX = 1.0;
+ style->ScaleY = 1.0;
+ style->Spacing = 0;
+ style->BorderStyle = 1;
+ style->Outline = 2;
+ style->Shadow = 3;
+ style->Alignment = 2;
+ style->MarginL = style->MarginR = style->MarginV = 20;
}
static uint32_t string2color(ASS_Library *library, char *p)
ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
#define INTVAL(name) ANYVAL(name,atoi)
-#define FPVAL(name) ANYVAL(name,atof)
+#define FPVAL(name) ANYVAL(name,ass_atof)
#define TIMEVAL(name) \
} else if (strcasecmp(tname, #name) == 0) { \
target->name = string2timecode(track->library, token); \
// add "Default" style to the end
// will be used if track does not contain a default style (or even does not contain styles at all)
int sid = ass_alloc_style(track);
- track->styles[sid].Name = strdup("Default");
- track->styles[sid].FontName = strdup("Arial");
+ set_default_style(&track->styles[sid]);
+ track->default_style = sid;
}
for (i = 0; i < n_ignored; ++i) {
else if (!strcasecmp(*fs, "PlayResY"))
track->PlayResY = atoi(token);
else if (!strcasecmp(*fs, "Timer"))
- track->Timer = atof(token);
+ track->Timer = ass_atof(token);
else if (!strcasecmp(*fs, "WrapStyle"))
track->WrapStyle = atoi(token);
else if (!strcasecmp(*fs, "ScaledBorderAndShadow"))
track->ScaledBorderAndShadow = parse_bool(token);
+ else if (!strcasecmp(*fs, "Kerning"))
+ track->Kerning = parse_bool(token);
dt = strrchr(*fs, '.');
if (dt) {
FPVAL(ScaleY)
FPVAL(Outline)
FPVAL(Shadow)
+ FPVAL(Blur)
}
}
}
q = format = strdup(track->style_format);
+ // Add default style first
+ if (track->n_styles == 0) {
+ // will be used if track does not contain a default style (or even does not contain styles at all)
+ int sid = ass_alloc_style(track);
+ set_default_style(&track->styles[sid]);
+ track->default_style = sid;
+ }
+
ass_msg(track->library, MSGL_V, "[%p] Style: %s", track, str);
sid = ass_alloc_style(track);
INTVAL(Underline)
INTVAL(StrikeOut)
FPVAL(Spacing)
- INTVAL(Angle)
+ FPVAL(Angle)
INTVAL(BorderStyle)
INTVAL(Alignment)
if (track->track_type == TRACK_TYPE_ASS)
style->Name = strdup("Default");
if (!style->FontName)
style->FontName = strdup("Arial");
- // skip '@' at the start of the font name
- if (*style->FontName == '@') {
- p = style->FontName;
- style->FontName = strdup(p + 1);
- free(p);
- }
free(format);
return 0;
} else if (!strncmp(str, "PlayResY:", 9)) {
track->PlayResY = atoi(str + 9);
} else if (!strncmp(str, "Timer:", 6)) {
- track->Timer = atof(str + 6);
+ track->Timer = ass_atof(str + 6);
} else if (!strncmp(str, "WrapStyle:", 10)) {
track->WrapStyle = atoi(str + 10);
} else if (!strncmp(str, "ScaledBorderAndShadow:", 22)) {
track->ScaledBorderAndShadow = parse_bool(str + 22);
+ } else if (!strncmp(str, "Kerning:", 8)) {
+ track->Kerning = parse_bool(str + 8);
+ } else if (!strncmp(str, "Language:", 9)) {
+ char *p = str + 9;
+ while (*p && isspace(*p)) p++;
+ track->Language = malloc(3);
+ strncpy(track->Language, p, 2);
+ track->Language[2] = 0;
}
return 0;
}
{
track->parser_priv->state = PST_EVENTS;
if (track->track_type == TRACK_TYPE_SSA)
- track->event_format = strdup("Format: Marked, Start, End, Style, "
+ track->event_format = strdup("Marked, Start, End, Style, "
"Name, MarginL, MarginR, MarginV, Effect, Text");
else
- track->event_format = strdup("Format: Layer, Start, End, Style, "
+ track->event_format = strdup("Layer, Start, End, Style, "
"Actor, MarginL, MarginR, MarginV, Effect, Text");
ass_msg(track->library, MSGL_V,
"No event format found, using fallback");
if (!strncmp(str, "Format:", 7)) {
char *p = str + 7;
skip_spaces(&p);
+ free(track->event_format);
track->event_format = strdup(p);
ass_msg(track->library, MSGL_DBG2, "Event format: %s", track->event_format);
} else if (!strncmp(str, "Dialogue:", 9)) {
process_event_tail(track, event, str, 0);
} else {
- ass_msg(track->library, MSGL_V, "Not understood: '%s'", str);
+ ass_msg(track->library, MSGL_V, "Not understood: '%.30s'", str);
}
return 0;
}
if (track->library->extract_fonts) {
ass_add_font(track->library, track->parser_priv->fontname,
(char *) buf, dsize);
- buf = 0;
}
- error_decode_font:
- if (buf)
- free(buf);
+error_decode_font:
+ free(buf);
free(track->parser_priv->fontname);
free(track->parser_priv->fontdata);
track->parser_priv->fontname = 0;
free(str);
}
+/**
+ * \brief Flush buffered events.
+ * \param track track
+*/
+void ass_flush_events(ASS_Track *track)
+{
+ if (track->events) {
+ int eid;
+ for (eid = 0; eid < track->n_events; eid++)
+ ass_free_event(track, eid);
+ track->n_events = 0;
+ }
+}
+
#ifdef CONFIG_ICONV
/** \brief recode buffer to utf-8
* constraint: codepage != 0
oleft += size;
} else {
ass_msg(library, MSGL_WARN, "Error recoding file");
- return NULL;
+ free(outbuf);
+ outbuf = NULL;
+ goto out;
}
} else if (clear)
break;
outbuf[osize - oleft - 1] = 0;
}
+out:
if (icdsc != (iconv_t) (-1)) {
(void) iconv_close(icdsc);
icdsc = (iconv_t) (-1);
sz = ftell(fp);
rewind(fp);
- if (sz > 10 * 1024 * 1024) {
- ass_msg(library, MSGL_INFO,
- "ass_read_file(%s): Refusing to load subtitles "
- "larger than 10MiB", fname);
- fclose(fp);
- return 0;
- }
-
ass_msg(library, MSGL_V, "File size: %ld", sz);
buf = malloc(sz + 1);
return 0;
#ifdef CONFIG_ICONV
- if (codepage)
+ if (codepage) {
buf = sub_recode(library, buf, bufsize, codepage);
- if (!buf)
- return 0;
- else
- need_free = 1;
+ if (!buf)
+ return 0;
+ else
+ need_free = 1;
+ }
#endif
track = parse_memory(library, buf);
if (need_free)
track->parser_priv = calloc(1, sizeof(ASS_ParserPriv));
return track;
}
+
+/**
+ * \brief Prepare track for rendering
+ */
+void ass_lazy_track_init(ASS_Library *lib, ASS_Track *track)
+{
+ if (track->PlayResX && track->PlayResY)
+ return;
+ if (!track->PlayResX && !track->PlayResY) {
+ ass_msg(lib, MSGL_WARN,
+ "Neither PlayResX nor PlayResY defined. Assuming 384x288");
+ track->PlayResX = 384;
+ track->PlayResY = 288;
+ } else {
+ if (!track->PlayResY && track->PlayResX == 1280) {
+ track->PlayResY = 1024;
+ ass_msg(lib, MSGL_WARN,
+ "PlayResY undefined, setting to %d", track->PlayResY);
+ } else if (!track->PlayResY) {
+ track->PlayResY = track->PlayResX * 3 / 4;
+ ass_msg(lib, MSGL_WARN,
+ "PlayResY undefined, setting to %d", track->PlayResY);
+ } else if (!track->PlayResX && track->PlayResY == 1024) {
+ track->PlayResX = 1280;
+ ass_msg(lib, MSGL_WARN,
+ "PlayResX undefined, setting to %d", track->PlayResX);
+ } else if (!track->PlayResX) {
+ track->PlayResX = track->PlayResY * 4 / 3;
+ ass_msg(lib, MSGL_WARN,
+ "PlayResX undefined, setting to %d", track->PlayResX);
+ }
+ }
+}