/*
* Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
*
* This file is part of libass.
*
* 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.
*
* 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 "ass_compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
#ifdef CONFIG_ICONV
#include <iconv.h>
#endif
#include "ass.h"
#include "ass_utils.h"
#include "ass_library.h"
#include "ass_priv.h"
#include "ass_shaper.h"
#include "ass_string.h"
#define ass_atof(STR) (ass_strtod((STR),NULL))
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)
{
return LIBASS_VERSION;
}
void ass_free_track(ASS_Track *track)
{
int i;
if (!track)
return;
if (track->parser_priv) {
free(track->parser_priv->read_order_bitmap);
free(track->parser_priv->fontname);
free(track->parser_priv->fontdata);
free(track->parser_priv);
}
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);
if (track->events) {
for (i = 0; i < track->n_events; ++i)
ass_free_event(track, i);
}
free(track->events);
free(track->name);
free(track);
}
/// \brief Allocate a new style struct
/// \param track track
/// \return style id or negative value on failure
int ass_alloc_style(ASS_Track *track)
{
int sid;
assert(track->n_styles <= track->max_styles);
if (track->n_styles == track->max_styles) {
if (track->max_styles >= FFMIN(SIZE_MAX, INT_MAX) - ASS_STYLES_ALLOC)
return -1;
int new_max = track->max_styles + ASS_STYLES_ALLOC;
if (!ASS_REALLOC_ARRAY(track->styles, new_max))
return -1;
track->max_styles = new_max;
}
sid = track->n_styles++;
memset(track->styles + sid, 0, sizeof(ASS_Style));
return sid;
}
/// \brief Allocate a new event struct
/// \param track track
/// \return event id or negative value on failure
int ass_alloc_event(ASS_Track *track)
{
int eid;
assert(track->n_events <= track->max_events);
if (track->n_events == track->max_events) {
if (track->max_events >= FFMIN(SIZE_MAX, INT_MAX) / 2)
return -1;
int new_max = track->max_events * 2 + 1;
if (!ASS_REALLOC_ARRAY(track->events, new_max))
return -1;
track->max_events = new_max;
}
eid = track->n_events++;
memset(track->events + eid, 0, sizeof(ASS_Event));
return eid;
}
void ass_free_event(ASS_Track *track, int eid)
{
ASS_Event *event = track->events + eid;
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;
free(style->Name);
free(style->FontName);
}
static int resize_read_order_bitmap(ASS_Track *track, int max_id)
{
// Don't allow malicious files to OOM us easily. Also avoids int overflows.
if (max_id < 0 || max_id >= 10 * 1024 * 1024 * 8)
goto fail;
assert(track->parser_priv->read_order_bitmap || !track->parser_priv->read_order_elems);
if (max_id >= track->parser_priv->read_order_elems * 32) {
int oldelems = track->parser_priv->read_order_elems;
int elems = ((max_id + 31) / 32 + 1) * 2;
assert(elems >= oldelems);
track->parser_priv->read_order_elems = elems;
void *new_bitmap =
realloc(track->parser_priv->read_order_bitmap, elems * 4);
if (!new_bitmap)
goto fail;
track->parser_priv->read_order_bitmap = new_bitmap;
memset(track->parser_priv->read_order_bitmap + oldelems, 0,
(elems - oldelems) * 4);
}
return 0;
fail:
free(track->parser_priv->read_order_bitmap);
track->parser_priv->read_order_bitmap = NULL;
track->parser_priv->read_order_elems = 0;
return -1;
}
static int test_and_set_read_order_bit(ASS_Track *track, int id)
{
if (resize_read_order_bitmap(track, id) < 0)
return -1;
int index = id / 32;
uint32_t bit = 1u << (id % 32);
if (track->parser_priv->read_order_bitmap[index] & bit)
return 1;
track->parser_priv->read_order_bitmap[index] |= bit;
return 0;
}
// ==============================================================================================
/**
* \brief Set up default style
* \param style style to edit to defaults
* The parameters are mostly taken directly from VSFilter source for
* best compatibility.
|