aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorSébastien Brochet <blinkseb@xbmc.org>2013-10-12 14:21:47 +0200
committerSébastien Brochet <blinkseb@xbmc.org>2013-11-02 10:06:53 +0100
commitcbc97145fb8f5ca75c6fca78997330ff03d1f7f2 (patch)
tree6958d12671206d9b6229e4c7faceedcc7bacdb5c /lib
parent9b3ff6654e94394a4a5ddef356e6ffbdb63548d6 (diff)
Remove libass from repository
Diffstat (limited to 'lib')
-rw-r--r--lib/libass/COPYING11
-rw-r--r--lib/libass/Changelog109
-rw-r--r--lib/libass/Makefile.am13
-rw-r--r--lib/libass/configure.ac118
-rw-r--r--lib/libass/libass.pc.in13
-rw-r--r--lib/libass/libass/Makefile.am21
-rw-r--r--lib/libass/libass/ass.c1320
-rw-r--r--lib/libass/libass/ass.h403
-rw-r--r--lib/libass/libass/ass_bitmap.c526
-rw-r--r--lib/libass/libass/ass_bitmap.h58
-rw-r--r--lib/libass/libass/ass_cache.c352
-rw-r--r--lib/libass/libass/ass_cache.h104
-rw-r--r--lib/libass/libass/ass_cache_template.h144
-rw-r--r--lib/libass/libass/ass_drawing.c462
-rw-r--r--lib/libass/libass/ass_drawing.h78
-rw-r--r--lib/libass/libass/ass_font.c776
-rw-r--r--lib/libass/libass/ass_font.h80
-rw-r--r--lib/libass/libass/ass_fontconfig.c534
-rw-r--r--lib/libass/libass/ass_fontconfig.h45
-rw-r--r--lib/libass/libass/ass_library.c147
-rw-r--r--lib/libass/libass/ass_library.h41
-rw-r--r--lib/libass/libass/ass_parse.c1039
-rw-r--r--lib/libass/libass/ass_parse.h40
-rw-r--r--lib/libass/libass/ass_render.c2539
-rw-r--r--lib/libass/libass/ass_render.h298
-rw-r--r--lib/libass/libass/ass_render_api.c147
-rw-r--r--lib/libass/libass/ass_shaper.c733
-rw-r--r--lib/libass/libass/ass_shaper.h43
-rw-r--r--lib/libass/libass/ass_strtod.c249
-rw-r--r--lib/libass/libass/ass_types.h124
-rw-r--r--lib/libass/libass/ass_utils.c215
-rw-r--r--lib/libass/libass/ass_utils.h155
-rw-r--r--lib/libass/libass/libass.sym37
-rw-r--r--lib/libass/m4/.gitignore0
-rw-r--r--lib/libass/test/Makefile.am7
-rw-r--r--lib/libass/test/test.c201
-rw-r--r--lib/libass/xbmc/libass_win32/config.h183
-rw-r--r--lib/libass/xbmc/libass_win32/getopt.h193
-rw-r--r--lib/libass/xbmc/libass_win32/inttypes.h306
-rw-r--r--lib/libass/xbmc/libass_win32/libass.def38
-rw-r--r--lib/libass/xbmc/libass_win32/libass_win32_vs2008.sln20
-rw-r--r--lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj178
-rw-r--r--lib/libass/xbmc/libass_win32/stdint.h222
-rw-r--r--lib/libass/xbmc/libass_win32/unistd.h47
44 files changed, 0 insertions, 12369 deletions
diff --git a/lib/libass/COPYING b/lib/libass/COPYING
deleted file mode 100644
index 8351a30e3a..0000000000
--- a/lib/libass/COPYING
+++ /dev/null
@@ -1,11 +0,0 @@
-Permission to use, copy, modify, and/or 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.
diff --git a/lib/libass/Changelog b/lib/libass/Changelog
deleted file mode 100644
index ef31e60586..0000000000
--- a/lib/libass/Changelog
+++ /dev/null
@@ -1,109 +0,0 @@
-libass (0.10.0)
- * Bidirectional layout and Arabic shaping via FriBidi (GC #13)
- * OpenType shaping via HarfBuzz-ng (GC #13)
- * Add API for shaper configuration
- * Add support for `Language' Script Info property, this can be used for
- hinting the text language
- * Vertical layout improvements
- * Use `vert' and `vkna' OpenType features for vertical glyph variants
- * Position rotated glyphs onto baseline
- * Parse font encoding property for base text direction hinting
- * Refactor cache system
- * Use generic outlines in place of FreeType glyphs
- * Direct outline bitmap rendering
- * Fix whitespace trimming (GC #35)
- * Do not render border if there's no shadow or glyph (GC #29)
- * Adjust spacing after a italic to non-italic style change (GC #37)
- * Fix fade timing
- * Fix x positioning with borders (GC #27)
- * Build system tweaks
-
-libass (0.9.12)
- * Switch to permissive (ISC) license
- * Support \fs+ and \fs- syntax for modifying font size
- * Fix word-wrapping
- * Improved charmap fallback matching
- * Handle a few more VSFilter quirks correctly
- * Add a sensible default style
- * Fix compilation against libpng 1.5
-
-libass (0.9.11)
- * Fix serious memory leaks
- * Reduce frame/drawing initialization overhead
-
-libass (0.9.10)
- * Basic (incorrect, but working) support for @font vertical text layout
- * Fix multiple faces per font attachment
- * charmap selection fixes
- * Add ass_flush_events API function
- * Improve fullname font matching
- * Better PAR correction if text transforms are used
- * Calculate drawing bounding box like VSFilter
- * Performance improvements
- * Cache vector clip masks
- * Avoid unnecessary glyph copies
- * Various rendering fixes
-
-libass (0.9.9)
- * Parse numbers in a locale-independent way
- * Remove support for freetype < 2.2.1, fontconfig < 2.4.1; this especially
- means libass will not extract fonts into the file system anymore
- * Disable script file size limit
- * Match fonts against the full name ("name for humans")
- * Reset clip mode after \iclip
- * Improve VSFilter compatibility
- * Update API documentation
- * A couple of smaller fixes and cleanups
-
-libass (0.9.8)
- * Support \q override tag
- * Support wrap style 1 (i.e. wrap, but do not equalize line lengths)
- * Support border style 3 (opaque box)
- * Use the event bounding box (instead of vertical position and height) for
- collision detection
- * Embold glyphs if no bold variant is available, but was requested
- * Modify \fax to be similar to VSFilter
- * Trim spaces after line wrapping
- * Fix border/shadow overlap combining in some cases
- * Disable kerning by default. Use "Kerning=yes" style override or
- "Kerning: yes" in [Script Info] to enable it
- * Slight bitmap handling optimizations
- * Various bugfixes
-
-libass (0.9.7)
- * Build system fixes
- * Fixed cache lookup and overload problems
- * All globals have been eliminated, libass is reentrant
- * Dynamically allocate glyph and line buffers
- * Fix up stroking of big borders
- * Support empty lines (\N\N)
- * Support for the following override tags:
- \fax, \fay, \xshad, \yshad, \ybord, \xbord, \iclip, \u, \s, \p, \pbo
- * Full subpixel accuracy for positioning
- * PAR and rotation correction for EOSD rendering
- * Drawing mode (including vector \clip and \iclip)
- * Fixed a few memory leaks
- * Removed MPlayer compatibility code
- * Introduced message handling callback
- * Various fixes to match VSFilter quirks and Windows font metrics
- * Lots of bugfixes
-
-LibASS (0.9.6)
- * Various fixes and updates to match VSFilter renderer.
- * Support \blur tag and ScaledBordersAndShadow property.
- * Fractional arguments and subpixel accuracy.
- * Keep positions when pan-and-scan is used.
- * Lots of bugfixes and other changes.
-
-LibASS (0.9.5)
- * Support '=' and '.' in style name in arguments to ass_set_style_overrides().
- * Allow overriding [Script Info] parameters with ass_set_style_overrides().
- * Add workarounds for some buggy fonts.
- * Remove buggy workarounds for some other fonts.
- * Fixed ass_set_line_spacing() (was broken before).
- * Negative margin sizes are now used for image cropping.
- * Better handling of behind-the-camera objects.
- * Case insensitive parsing of SSA/ASS section headers.
- * Improved font matching.
- * When 2 styles have the same name, the later one is used.
- * Fixed several other bugs.
diff --git a/lib/libass/Makefile.am b/lib/libass/Makefile.am
deleted file mode 100644
index 5a17a08309..0000000000
--- a/lib/libass/Makefile.am
+++ /dev/null
@@ -1,13 +0,0 @@
-ACLOCAL_AMFLAGS = -I m4
-AUTOMAKE_OPTIONS = foreign
-EXTRA_DIST = libass.pc.in Changelog
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = libass.pc
-
-if HAVE_LIBPNG
- test = test
-endif
-
-SUBDIRS = libass $(test)
-
diff --git a/lib/libass/configure.ac b/lib/libass/configure.ac
deleted file mode 100644
index 35548c6291..0000000000
--- a/lib/libass/configure.ac
+++ /dev/null
@@ -1,118 +0,0 @@
-AC_INIT(libass, 0.10.0)
-AM_INIT_AUTOMAKE
-AC_CONFIG_MACRO_DIR([m4])
-# Disable C++/Fortran checks
-define([AC_LIBTOOL_LANG_CXX_CONFIG], [:])
-define([AC_LIBTOOL_LANG_F77_CONFIG], [:])
-AC_PROG_LIBTOOL
-AC_CONFIG_SRCDIR([libass/ass.c])
-AC_CONFIG_HEADER([config.h])
-
-# Checks for programs.
-AC_PROG_CC
-AC_PROG_CPP
-AM_PROG_CC_C_O
-
-# Checks for header files.
-AC_HEADER_STDC
-AC_HEADER_STDBOOL
-AC_CHECK_HEADERS([inttypes.h stdint.h stdlib.h string.h sys/time.h unistd.h iconv.h])
-
-# Checks for typedefs, structures, and compiler characteristics.
-AC_C_CONST
-AC_C_INLINE
-AC_TYPE_INT64_T
-AC_TYPE_SIZE_T
-AC_TYPE_UINT32_T
-AC_TYPE_UINT8_T
-
-# Checks for library functions.
-AC_CHECK_FUNCS([mkdir strcasecmp strdup strtol])
-
-# Checks for libraries.
-AC_SEARCH_LIBS([iconv_open], [iconv], AC_DEFINE(CONFIG_ICONV, 1, [use iconv]))
-AC_CHECK_LIB([m], [fabs])
-
-# Check for libraries via pkg-config
-AC_ARG_ENABLE([test], AS_HELP_STRING([--enable-test],
- [enable test program (requires libpng) @<:@default=no@:>@]))
-AC_ARG_ENABLE([enca], AS_HELP_STRING([--disable-enca],
- [disable enca (charset autodetect) support @<:@default=check@:>@]))
-AC_ARG_ENABLE([fontconfig], AS_HELP_STRING([--disable-fontconfig],
- [disable fontconfig support @<:@default=enabled@:>@]))
-AC_ARG_ENABLE([harfbuzz], AS_HELP_STRING([--disable-harfbuzz],
- [disable HarfBuzz support @<:@default=check@:>@]))
-
-PKG_CHECK_MODULES([FREETYPE], freetype2 >= 9.10.3, [
- CFLAGS="$CFLAGS $FREETYPE_CFLAGS"
- LIBS="$LIBS $FREETYPE_LIBS"
- AC_DEFINE(CONFIG_FREETYPE, 1, [found freetype2 via pkg-config])
- ])
-
-PKG_CHECK_MODULES([FRIBIDI], fribidi >= 0.19.0, [
- CFLAGS="$CFLAGS $FRIBIDI_CFLAGS"
- LIBS="$LIBS $FRIBIDI_LIBS"
- AC_DEFINE(CONFIG_FRIBIDI, 1, [found fribidi via pkg-config])
- ])
-
-if test x$enable_fontconfig != xno; then
-PKG_CHECK_MODULES([FONTCONFIG], fontconfig >= 2.4.2, [
- CFLAGS="$CFLAGS $FONTCONFIG_CFLAGS"
- LIBS="$LIBS $FONTCONFIG_LIBS"
- AC_DEFINE(CONFIG_FONTCONFIG, 1, [found fontconfig via pkg-config])
- fontconfig=true
- ])
-fi
-
-if test x$enable_harfbuzz != xno; then
-PKG_CHECK_MODULES([HARFBUZZ], harfbuzz >= 0.7.0, [
- CFLAGS="$CFLAGS $HARFBUZZ_CFLAGS"
- LIBS="$LIBS $HARFBUZZ_LIBS"
- AC_DEFINE(CONFIG_HARFBUZZ, 1, [found harfbuzz-ng via pkg-config])
- harfbuzz=true
- ], [harfbuzz=false])
-fi
-
-if test x$enable_enca != xno; then
-PKG_CHECK_MODULES([ENCA], enca, [
- CFLAGS="$CFLAGS $ENCA_CFLAGS"
- LIBS="$LIBS $ENCA_LIBS"
- AC_DEFINE(CONFIG_ENCA, 1, [found enca via pkg-config])
- enca=true
- ], [enca=false])
-fi
-
-libpng=false
-if test x$enable_test = xyes; then
-PKG_CHECK_MODULES([LIBPNG], libpng >= 1.2.0, [
- CFLAGS="$CFLAGS $LIBPNG_CFLAGS"
- AC_DEFINE(CONFIG_LIBPNG, 1, [found libpng via pkg-config])
- libpng=true])
-fi
-
-AM_CONDITIONAL([HAVE_LIBPNG], [test x$libpng = xtrue])
-
-# add libraries/packages to pkg-config for static linking
-pkg_libs="-lm"
-pkg_requires="freetype2 >= 9.6.3"
-pkg_requires="fribidi >= 0.19.0, ${pkg_requires}"
-if test x$enca = xtrue; then
- pkg_requires="enca, ${pkg_requires}"
-fi
-if test x$fontconfig = xtrue; then
- pkg_requires="fontconfig >= 2.2.0, ${pkg_requires}"
-fi
-if test x$harfbuzz = xtrue; then
- pkg_requires="harfbuzz >= 0.7.0, ${pkg_requires}"
-fi
-
-AC_SUBST([PKG_LIBS_DEFAULT], [$(test x$enable_shared = xno && echo ${pkg_libs})])
-AC_SUBST([PKG_REQUIRES_DEFAULT], [$(test x$enable_shared = xno && echo ${pkg_requires})])
-AC_SUBST([PKG_LIBS_PRIVATE], [$(test x$enable_shared = xno || echo ${pkg_libs})])
-AC_SUBST([PKG_REQUIRES_PRIVATE], [$(test x$enable_shared = xno || echo ${pkg_requires})])
-
-# Setup output beautifier.
-m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
-
-AC_CONFIG_FILES([Makefile libass/Makefile test/Makefile libass.pc])
-AC_OUTPUT
diff --git a/lib/libass/libass.pc.in b/lib/libass/libass.pc.in
deleted file mode 100644
index e08783516b..0000000000
--- a/lib/libass/libass.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: libass
-Description: LibASS is an SSA/ASS subtitles rendering library
-Version: @PACKAGE_VERSION@
-Requires: @PKG_REQUIRES_DEFAULT@
-Requires.private: @PKG_REQUIRES_PRIVATE@
-Libs: -L${libdir} -lass @PKG_LIBS_DEFAULT@
-Libs.private: @PKG_LIBS_PRIVATE@
-Cflags: -I${includedir}
diff --git a/lib/libass/libass/Makefile.am b/lib/libass/libass/Makefile.am
deleted file mode 100644
index 142de68fbb..0000000000
--- a/lib/libass/libass/Makefile.am
+++ /dev/null
@@ -1,21 +0,0 @@
-AM_CFLAGS = -Wall
-
-LIBASS_LT_CURRENT = 5
-LIBASS_LT_REVISION = 0
-LIBASS_LT_AGE = 1
-
-lib_LTLIBRARIES = libass.la
-libass_la_SOURCES = ass.c ass_cache.c ass_font.c ass_fontconfig.c ass_render.c \
- ass_utils.c ass_bitmap.c ass_library.c ass_bitmap.h \
- ass_cache.h ass_fontconfig.h ass_font.h ass.h \
- ass_library.h ass_types.h ass_utils.h ass_drawing.c \
- ass_drawing.h ass_cache_template.h ass_render.h \
- ass_parse.c ass_parse.h ass_render_api.c ass_shaper.c \
- ass_shaper.h ass_strtod.c
-libass_la_LDFLAGS = -version-info $(LIBASS_LT_CURRENT):$(LIBASS_LT_REVISION):$(LIBASS_LT_AGE)
-libass_la_LDFLAGS += -export-symbols $(srcdir)/libass.sym
-
-assheadersdir = $(includedir)/ass
-dist_assheaders_HEADERS = ass.h ass_types.h
-
-EXTRA_DIST = libass.sym
diff --git a/lib/libass/libass/ass.c b/lib/libass/libass/ass.c
deleted file mode 100644
index 66868f27f5..0000000000
--- a/lib/libass/libass/ass.c
+++ /dev/null
@@ -1,1320 +0,0 @@
-/*
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef _WIN32
-#include <strings.h>
-#endif
-#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>
-#endif
-
-#include "ass.h"
-#include "ass_utils.h"
-#include "ass_library.h"
-
-#ifdef _WIN32
-#pragma comment(lib, "libiconv.lib")
-#pragma comment(lib, "freetype246MT.lib")
-#pragma comment(lib, "libfribidi.lib")
-#endif
-
-#define ass_atof(STR) (ass_strtod((STR),NULL))
-
-typedef enum {
- PST_UNKNOWN = 0,
- PST_INFO,
- PST_STYLES,
- PST_EVENTS,
- PST_FONTS
-} ParserState;
-
-struct parser_priv {
- ParserState state;
- char *fontname;
- char *fontdata;
- int fontdata_size;
- int fontdata_used;
-};
-
-#define ASS_STYLES_ALLOC 20
-#define ASS_EVENTS_ALLOC 200
-
-void ass_free_track(ASS_Track *track)
-{
- int i;
-
- if (track->parser_priv) {
- 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
-int ass_alloc_style(ASS_Track *track)
-{
- int sid;
-
- assert(track->n_styles <= track->max_styles);
-
- if (track->n_styles == track->max_styles) {
- track->max_styles += ASS_STYLES_ALLOC;
- track->styles =
- (ASS_Style *) realloc(track->styles,
- sizeof(ASS_Style) *
- track->max_styles);
- }
-
- 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
-int ass_alloc_event(ASS_Track *track)
-{
- int eid;
-
- assert(track->n_events <= track->max_events);
-
- if (track->n_events == track->max_events) {
- track->max_events += ASS_EVENTS_ALLOC;
- track->events =
- (ASS_Event *) realloc(track->events,
- sizeof(ASS_Event) *
- track->max_events);
- }
-
- 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 void skip_spaces(char **str)
-{
- char *p = *str;
- while ((*p == ' ') || (*p == '\t'))
- ++p;
- *str = p;
-}
-
-static void rskip_spaces(char **str, char *limit)
-{
- char *p = *str;
- while ((p >= limit) && ((*p == ' ') || (*p == '\t')))
- --p;
- *str = p;
-}
-
-/**
- * \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 void set_default_style(ASS_Style *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;
-}
-
-/**
- * \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.
- */
-static int lookup_style(ASS_Track *track, char *name)
-{
- int i;
- if (*name == '*')
- ++name; // FIXME: what does '*' really mean ?
- for (i = track->n_styles - 1; i >= 0; --i) {
- 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
-}
-
-static uint32_t string2color(ASS_Library *library, char *p)
-{
- uint32_t tmp;
- (void) strtocolor(library, &p, &tmp, 0);
- return tmp;
-}
-
-static long long string2timecode(ASS_Library *library, char *p)
-{
- unsigned h, m, s, ms;
- long long tm;
- int res = sscanf(p, "%1d:%2d:%2d.%2d", &h, &m, &s, &ms);
- if (res < 4) {
- ass_msg(library, MSGL_WARN, "Bad timestamp");
- return 0;
- }
- tm = ((h * 60 + m) * 60 + s) * 1000 + ms * 10;
- return tm;
-}
-
-/**
- * \brief converts numpad-style align to align.
- */
-static int numpad2align(int val)
-{
- int res, v;
- v = (val - 1) / 3; // 0, 1 or 2 for vertical alignment
- if (v != 0)
- v = 3 - v;
- res = ((val - 1) % 3) + 1; // horizontal alignment
- res += v * 4;
- return res;
-}
-
-#define NEXT(str,token) \
- token = next_token(&str); \
- if (!token) break;
-
-#define ANYVAL(name,func) \
- } else if (strcasecmp(tname, #name) == 0) { \
- target->name = func(token); \
- ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
-
-#define STRVAL(name) \
- } else if (strcasecmp(tname, #name) == 0) { \
- if (target->name != NULL) free(target->name); \
- target->name = strdup(token); \
- ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
-
-#define COLORVAL(name) \
- } else if (strcasecmp(tname, #name) == 0) { \
- target->name = string2color(track->library, token); \
- ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
-
-#define INTVAL(name) ANYVAL(name,atoi)
-#define FPVAL(name) ANYVAL(name,ass_atof)
-#define TIMEVAL(name) \
- } else if (strcasecmp(tname, #name) == 0) { \
- target->name = string2timecode(track->library, token); \
- ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
-
-#define STYLEVAL(name) \
- } else if (strcasecmp(tname, #name) == 0) { \
- target->name = lookup_style(track, token); \
- ass_msg(track->library, MSGL_DBG2, "%s = %s", #name, token);
-
-#define ALIAS(alias,name) \
- if (strcasecmp(tname, #alias) == 0) {tname = #name;}
-
-static char *next_token(char **str)
-{
- char *p = *str;
- char *start;
- skip_spaces(&p);
- if (*p == '\0') {
- *str = p;
- 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)
- }
- --p; // end of current token
- rskip_spaces(&p, start);
- if (p < start)
- p = start; // empty token
- else
- ++p; // the first space character, or '\0'
- *p = '\0';
- return start;
-}
-
-/**
- * \brief Parse the tail of Dialogue line
- * \param track track
- * \param event parsed data goes here
- * \param str string to parse, zero-terminated
- * \param n_ignored number of format options to skip at the beginning
-*/
-static int process_event_tail(ASS_Track *track, ASS_Event *event,
- char *str, int n_ignored)
-{
- char *token;
- char *tname;
- char *p = str;
- int i;
- ASS_Event *target = event;
-
- char *format = strdup(track->event_format);
- char *q = format; // format scanning pointer
-
- if (track->n_styles == 0) {
- // 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);
- set_default_style(&track->styles[sid]);
- track->default_style = sid;
- }
-
- for (i = 0; i < n_ignored; ++i) {
- NEXT(q, tname);
- }
-
- while (1) {
- NEXT(q, tname);
- if (strcasecmp(tname, "Text") == 0) {
- char *last;
- event->Text = strdup(p);
- if (*event->Text != 0) {
- last = event->Text + strlen(event->Text) - 1;
- if (last >= event->Text && *last == '\r')
- *last = 0;
- }
- ass_msg(track->library, MSGL_DBG2, "Text = %s", event->Text);
- event->Duration -= event->Start;
- free(format);
- return 0; // "Text" is always the last
- }
- NEXT(p, token);
-
- ALIAS(End, Duration) // temporarily store end timecode in event->Duration
- if (0) { // cool ;)
- INTVAL(Layer)
- STYLEVAL(Style)
- STRVAL(Name)
- STRVAL(Effect)
- INTVAL(MarginL)
- INTVAL(MarginR)
- INTVAL(MarginV)
- TIMEVAL(Start)
- TIMEVAL(Duration)
- }
- }
- free(format);
- return 1;
-}
-
-/**
- * \brief Parse command line style overrides (--ass-force-style option)
- * \param track track to apply overrides to
- * The format for overrides is [StyleName.]Field=Value
- */
-void ass_process_force_style(ASS_Track *track)
-{
- char **fs, *eq, *dt, *style, *tname, *token;
- ASS_Style *target;
- int sid;
- char **list = track->library->style_overrides;
-
- if (!list)
- return;
-
- for (fs = list; *fs; ++fs) {
- eq = strrchr(*fs, '=');
- if (!eq)
- continue;
- *eq = '\0';
- token = eq + 1;
-
- if (!strcasecmp(*fs, "PlayResX"))
- track->PlayResX = atoi(token);
- else if (!strcasecmp(*fs, "PlayResY"))
- track->PlayResY = atoi(token);
- else if (!strcasecmp(*fs, "Timer"))
- 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) {
- *dt = '\0';
- style = *fs;
- tname = dt + 1;
- } else {
- style = NULL;
- tname = *fs;
- }
- for (sid = 0; sid < track->n_styles; ++sid) {
- if (style == NULL
- || strcasecmp(track->styles[sid].Name, style) == 0) {
- target = track->styles + sid;
- if (0) {
- STRVAL(FontName)
- COLORVAL(PrimaryColour)
- COLORVAL(SecondaryColour)
- COLORVAL(OutlineColour)
- COLORVAL(BackColour)
- FPVAL(FontSize)
- INTVAL(Bold)
- INTVAL(Italic)
- INTVAL(Underline)
- INTVAL(StrikeOut)
- FPVAL(Spacing)
- INTVAL(Angle)
- INTVAL(BorderStyle)
- INTVAL(Alignment)
- INTVAL(MarginL)
- INTVAL(MarginR)
- INTVAL(MarginV)
- INTVAL(Encoding)
- FPVAL(ScaleX)
- FPVAL(ScaleY)
- FPVAL(Outline)
- FPVAL(Shadow)
- }
- }
- }
- *eq = '=';
- if (dt)
- *dt = '.';
- }
-}
-
-/**
- * \brief Parse the Style line
- * \param track track
- * \param str string to parse, zero-terminated
- * Allocates a new style struct.
-*/
-static int process_style(ASS_Track *track, char *str)
-{
-
- char *token;
- char *tname;
- char *p = str;
- char *format;
- char *q; // format scanning pointer
- int sid;
- ASS_Style *style;
- ASS_Style *target;
-
- if (!track->style_format) {
- // 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");
- 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");
- }
-
- 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);
-
- style = track->styles + sid;
- target = style;
-
- // fill style with some default values
- style->ScaleX = 100.;
- style->ScaleY = 100.;
-
- while (1) {
- NEXT(q, tname);
- NEXT(p, token);
-
- if (0) { // cool ;)
- STRVAL(Name)
- if ((strcmp(target->Name, "Default") == 0)
- || (strcmp(target->Name, "*Default") == 0))
- track->default_style = sid;
- STRVAL(FontName)
- COLORVAL(PrimaryColour)
- COLORVAL(SecondaryColour)
- COLORVAL(OutlineColour) // TertiaryColor
- COLORVAL(BackColour)
- // SSA uses BackColour for both outline and shadow
- // this will destroy SSA's TertiaryColour, but i'm not going to use it anyway
- if (track->track_type == TRACK_TYPE_SSA)
- target->OutlineColour = target->BackColour;
- FPVAL(FontSize)
- INTVAL(Bold)
- INTVAL(Italic)
- INTVAL(Underline)
- INTVAL(StrikeOut)
- FPVAL(Spacing)
- INTVAL(Angle)
- INTVAL(BorderStyle)
- INTVAL(Alignment)
- if (track->track_type == TRACK_TYPE_ASS)
- target->Alignment = numpad2align(target->Alignment);
- INTVAL(MarginL)
- INTVAL(MarginR)
- INTVAL(MarginV)
- INTVAL(Encoding)
- FPVAL(ScaleX)
- FPVAL(ScaleY)
- FPVAL(Outline)
- FPVAL(Shadow)
- }
- }
- style->ScaleX /= 100.;
- style->ScaleY /= 100.;
- style->Bold = !!style->Bold;
- style->Italic = !!style->Italic;
- style->Underline = !!style->Underline;
- if (!style->Name)
- style->Name = strdup("Default");
- if (!style->FontName)
- style->FontName = strdup("Arial");
- free(format);
- return 0;
-
-}
-
-static int process_styles_line(ASS_Track *track, char *str)
-{
- if (!strncmp(str, "Format:", 7)) {
- char *p = str + 7;
- skip_spaces(&p);
- track->style_format = strdup(p);
- ass_msg(track->library, MSGL_DBG2, "Style format: %s",
- track->style_format);
- } else if (!strncmp(str, "Style:", 6)) {
- char *p = str + 6;
- skip_spaces(&p);
- process_style(track, p);
- }
- return 0;
-}
-
-static int process_info_line(ASS_Track *track, char *str)
-{
- if (!strncmp(str, "PlayResX:", 9)) {
- track->PlayResX = atoi(str + 9);
- } else if (!strncmp(str, "PlayResY:", 9)) {
- track->PlayResY = atoi(str + 9);
- } else if (!strncmp(str, "Timer:", 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;
-}
-
-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("Format: Marked, Start, End, Style, "
- "Name, MarginL, MarginR, MarginV, Effect, Text");
- else
- track->event_format = strdup("Format: Layer, Start, End, Style, "
- "Actor, MarginL, MarginR, MarginV, Effect, Text");
- ass_msg(track->library, MSGL_V,
- "No event format found, using fallback");
-}
-
-static int process_events_line(ASS_Track *track, char *str)
-{
- 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)) {
- // This should never be reached for embedded subtitles.
- // They have slightly different format and are parsed in ass_process_chunk,
- // called directly from demuxer
- int eid;
- ASS_Event *event;
-
- str += 9;
- skip_spaces(&str);
-
- eid = ass_alloc_event(track);
- event = track->events + eid;
-
- // We can't parse events with event_format
- if (!track->event_format)
- event_format_fallback(track);
-
- process_event_tail(track, event, str, 0);
- } else {
- ass_msg(track->library, MSGL_V, "Not understood: '%.30s'", str);
- }
- return 0;
-}
-
-// Copied from mkvtoolnix
-static unsigned char *decode_chars(unsigned char c1, unsigned char c2,
- unsigned char c3, unsigned char c4,
- unsigned char *dst, int cnt)
-{
- uint32_t value;
- unsigned char bytes[3];
- int i;
-
- value =
- ((c1 - 33) << 18) + ((c2 - 33) << 12) + ((c3 - 33) << 6) + (c4 -
- 33);
- bytes[2] = value & 0xff;
- bytes[1] = (value & 0xff00) >> 8;
- bytes[0] = (value & 0xff0000) >> 16;
-
- for (i = 0; i < cnt; ++i)
- *dst++ = bytes[i];
- return dst;
-}
-
-static int decode_font(ASS_Track *track)
-{
- unsigned char *p;
- unsigned char *q;
- int i;
- int size; // original size
- int dsize; // decoded size
- unsigned char *buf = 0;
-
- ass_msg(track->library, MSGL_V, "Font: %d bytes encoded data",
- track->parser_priv->fontdata_used);
- size = track->parser_priv->fontdata_used;
- if (size % 4 == 1) {
- ass_msg(track->library, MSGL_ERR, "Bad encoded data size");
- goto error_decode_font;
- }
- buf = malloc(size / 4 * 3 + 2);
- q = buf;
- for (i = 0, p = (unsigned char *) track->parser_priv->fontdata;
- i < size / 4; i++, p += 4) {
- q = decode_chars(p[0], p[1], p[2], p[3], q, 3);
- }
- if (size % 4 == 2) {
- q = decode_chars(p[0], p[1], 0, 0, q, 1);
- } else if (size % 4 == 3) {
- q = decode_chars(p[0], p[1], p[2], 0, q, 2);
- }
- dsize = q - buf;
- assert(dsize <= size / 4 * 3 + 2);
-
- if (track->library->extract_fonts) {
- ass_add_font(track->library, track->parser_priv->fontname,
- (char *) buf, dsize);
- }
-
-error_decode_font:
- free(buf);
- free(track->parser_priv->fontname);
- free(track->parser_priv->fontdata);
- track->parser_priv->fontname = 0;
- track->parser_priv->fontdata = 0;
- track->parser_priv->fontdata_size = 0;
- track->parser_priv->fontdata_used = 0;
- return 0;
-}
-
-static int process_fonts_line(ASS_Track *track, char *str)
-{
- int len;
-
- if (!strncmp(str, "fontname:", 9)) {
- char *p = str + 9;
- skip_spaces(&p);
- if (track->parser_priv->fontname) {
- decode_font(track);
- }
- track->parser_priv->fontname = strdup(p);
- ass_msg(track->library, MSGL_V, "Fontname: %s",
- track->parser_priv->fontname);
- return 0;
- }
-
- if (!track->parser_priv->fontname) {
- ass_msg(track->library, MSGL_V, "Not understood: '%s'", str);
- return 0;
- }
-
- len = strlen(str);
- if (len > 80) {
- ass_msg(track->library, MSGL_WARN, "Font line too long: %d, %s",
- len, str);
- return 0;
- }
- if (track->parser_priv->fontdata_used + len >
- track->parser_priv->fontdata_size) {
- track->parser_priv->fontdata_size += 100 * 1024;
- track->parser_priv->fontdata =
- realloc(track->parser_priv->fontdata,
- track->parser_priv->fontdata_size);
- }
- memcpy(track->parser_priv->fontdata + track->parser_priv->fontdata_used,
- str, len);
- track->parser_priv->fontdata_used += len;
-
- return 0;
-}
-
-/**
- * \brief Parse a header line
- * \param track track
- * \param str string to parse, zero-terminated
-*/
-static int process_line(ASS_Track *track, char *str)
-{
- if (!strncasecmp(str, "[Script Info]", 13)) {
- track->parser_priv->state = PST_INFO;
- } else if (!strncasecmp(str, "[V4 Styles]", 11)) {
- track->parser_priv->state = PST_STYLES;
- track->track_type = TRACK_TYPE_SSA;
- } else if (!strncasecmp(str, "[V4+ Styles]", 12)) {
- track->parser_priv->state = PST_STYLES;
- track->track_type = TRACK_TYPE_ASS;
- } else if (!strncasecmp(str, "[Events]", 8)) {
- track->parser_priv->state = PST_EVENTS;
- } else if (!strncasecmp(str, "[Fonts]", 7)) {
- track->parser_priv->state = PST_FONTS;
- } else {
- switch (track->parser_priv->state) {
- case PST_INFO:
- process_info_line(track, str);
- break;
- case PST_STYLES:
- process_styles_line(track, str);
- break;
- case PST_EVENTS:
- process_events_line(track, str);
- break;
- case PST_FONTS:
- process_fonts_line(track, str);
- break;
- default:
- break;
- }
- }
-
- // there is no explicit end-of-font marker in ssa/ass
- if ((track->parser_priv->state != PST_FONTS)
- && (track->parser_priv->fontname))
- decode_font(track);
-
- return 0;
-}
-
-static int process_text(ASS_Track *track, char *str)
-{
- char *p = str;
- while (1) {
- char *q;
- while (1) {
- if ((*p == '\r') || (*p == '\n'))
- ++p;
- else if (p[0] == '\xef' && p[1] == '\xbb' && p[2] == '\xbf')
- p += 3; // U+FFFE (BOM)
- else
- break;
- }
- for (q = p; ((*q != '\0') && (*q != '\r') && (*q != '\n')); ++q) {
- };
- if (q == p)
- break;
- if (*q != '\0')
- *(q++) = '\0';
- process_line(track, p);
- if (*q == '\0')
- break;
- p = q;
- }
- return 0;
-}
-
-/**
- * \brief Process a chunk of subtitle stream data.
- * \param track track
- * \param data string to parse
- * \param size length of data
-*/
-void ass_process_data(ASS_Track *track, char *data, int size)
-{
- char *str = malloc(size + 1);
-
- memcpy(str, data, size);
- str[size] = '\0';
-
- ass_msg(track->library, MSGL_V, "Event: %s", str);
- process_text(track, str);
- free(str);
-}
-
-/**
- * \brief Process CodecPrivate section of subtitle stream
- * \param track track
- * \param data string to parse
- * \param size length of data
- CodecPrivate section contains [Stream Info] and [V4+ Styles] ([V4 Styles] for SSA) sections
-*/
-void ass_process_codec_private(ASS_Track *track, char *data, int size)
-{
- ass_process_data(track, data, size);
-
- // probably an mkv produced by ancient mkvtoolnix
- // such files don't have [Events] and Format: headers
- if (!track->event_format)
- event_format_fallback(track);
-
- ass_process_force_style(track);
-}
-
-static int check_duplicate_event(ASS_Track *track, int ReadOrder)
-{
- int i;
- for (i = 0; i < track->n_events - 1; ++i) // ignoring last event, it is the one we are comparing with
- if (track->events[i].ReadOrder == ReadOrder)
- return 1;
- return 0;
-}
-
-/**
- * \brief Process a chunk of subtitle stream data. In Matroska, this contains exactly 1 event (or a commentary).
- * \param track track
- * \param data string to parse
- * \param size length of data
- * \param timecode starting time of the event (milliseconds)
- * \param duration duration of the event (milliseconds)
-*/
-void ass_process_chunk(ASS_Track *track, char *data, int size,
- long long timecode, long long duration)
-{
- char *str;
- int eid;
- char *p;
- char *token;
- ASS_Event *event;
-
- if (!track->event_format) {
- ass_msg(track->library, MSGL_WARN, "Event format header missing");
- return;
- }
-
- str = malloc(size + 1);
- memcpy(str, data, size);
- str[size] = '\0';
- ass_msg(track->library, MSGL_V, "Event at %" PRId64 ", +%" PRId64 ": %s",
- (int64_t) timecode, (int64_t) duration, str);
-
- eid = ass_alloc_event(track);
- event = track->events + eid;
-
- p = str;
-
- do {
- NEXT(p, token);
- event->ReadOrder = atoi(token);
- if (check_duplicate_event(track, event->ReadOrder))
- break;
-
- NEXT(p, token);
- event->Layer = atoi(token);
-
- process_event_tail(track, event, p, 3);
-
- event->Start = timecode;
- event->Duration = duration;
-
- free(str);
- return;
-// dump_events(tid);
- } while (0);
- // some error
- ass_free_event(track, eid);
- track->n_events--;
- 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
- * \param data pointer to text buffer
- * \param size buffer size
- * \return a pointer to recoded buffer, caller is responsible for freeing it
-**/
-static char *sub_recode(ASS_Library *library, char *data, size_t size,
- char *codepage)
-{
- iconv_t icdsc;
- char *tocp = "UTF-8";
- char *outbuf;
- assert(codepage);
-
- {
- const char *cp_tmp = codepage;
-#ifdef CONFIG_ENCA
- char enca_lang[3], enca_fallback[100];
- if (sscanf(codepage, "enca:%2s:%99s", enca_lang, enca_fallback) == 2
- || sscanf(codepage, "ENCA:%2s:%99s", enca_lang,
- enca_fallback) == 2) {
- cp_tmp =
- ass_guess_buffer_cp(library, (unsigned char *) data, size,
- enca_lang, enca_fallback);
- }
-#endif
- if ((icdsc = iconv_open(tocp, cp_tmp)) != (iconv_t) (-1)) {
- ass_msg(library, MSGL_V, "Opened iconv descriptor");
- } else
- ass_msg(library, MSGL_ERR, "Error opening iconv descriptor");
- }
-
- {
- size_t osize = size;
- size_t ileft = size;
- size_t oleft = size - 1;
- char *ip;
- char *op;
- size_t rc;
- int clear = 0;
-
- outbuf = malloc(osize);
- ip = data;
- op = outbuf;
-
- while (1) {
- if (ileft)
- rc = iconv(icdsc, &ip, &ileft, &op, &oleft);
- else { // clear the conversion state and leave
- clear = 1;
- rc = iconv(icdsc, NULL, NULL, &op, &oleft);
- }
- if (rc == (size_t) (-1)) {
- if (errno == E2BIG) {
- size_t offset = op - outbuf;
- outbuf = (char *) realloc(outbuf, osize + size);
- op = outbuf + offset;
- osize += size;
- oleft += size;
- } else {
- ass_msg(library, MSGL_WARN, "Error recoding file");
- return NULL;
- }
- } else if (clear)
- break;
- }
- outbuf[osize - oleft - 1] = 0;
- }
-
- if (icdsc != (iconv_t) (-1)) {
- (void) iconv_close(icdsc);
- icdsc = (iconv_t) (-1);
- ass_msg(library, MSGL_V, "Closed iconv descriptor");
- }
-
- return outbuf;
-}
-#endif // ICONV
-
-/**
- * \brief read file contents into newly allocated buffer
- * \param fname file name
- * \param bufsize out: file size
- * \return pointer to file contents. Caller is responsible for its deallocation.
- */
-static char *read_file(ASS_Library *library, char *fname, size_t *bufsize)
-{
- int res;
- long sz;
- long bytes_read;
- char *buf;
-
- FILE *fp = fopen(fname, "rb");
- if (!fp) {
- ass_msg(library, MSGL_WARN,
- "ass_read_file(%s): fopen failed", fname);
- return 0;
- }
- res = fseek(fp, 0, SEEK_END);
- if (res == -1) {
- ass_msg(library, MSGL_WARN,
- "ass_read_file(%s): fseek failed", fname);
- fclose(fp);
- return 0;
- }
-
- sz = ftell(fp);
- rewind(fp);
-
- ass_msg(library, MSGL_V, "File size: %ld", sz);
-
- buf = malloc(sz + 1);
- assert(buf);
- bytes_read = 0;
- do {
- res = fread(buf + bytes_read, 1, sz - bytes_read, fp);
- if (res <= 0) {
- ass_msg(library, MSGL_INFO, "Read failed, %d: %s", errno,
- strerror(errno));
- fclose(fp);
- free(buf);
- return 0;
- }
- bytes_read += res;
- } while (sz - bytes_read > 0);
- buf[sz] = '\0';
- fclose(fp);
-
- if (bufsize)
- *bufsize = sz;
- return buf;
-}
-
-/*
- * \param buf pointer to subtitle text in utf-8
- */
-static ASS_Track *parse_memory(ASS_Library *library, char *buf)
-{
- ASS_Track *track;
- int i;
-
- track = ass_new_track(library);
-
- // process header
- process_text(track, buf);
-
- // external SSA/ASS subs does not have ReadOrder field
- for (i = 0; i < track->n_events; ++i)
- track->events[i].ReadOrder = i;
-
- // there is no explicit end-of-font marker in ssa/ass
- if (track->parser_priv->fontname)
- decode_font(track);
-
- if (track->track_type == TRACK_TYPE_UNKNOWN) {
- ass_free_track(track);
- return 0;
- }
-
- ass_process_force_style(track);
-
- return track;
-}
-
-/**
- * \brief Read subtitles from memory.
- * \param library libass library object
- * \param buf pointer to subtitles text
- * \param bufsize size of buffer
- * \param codepage recode buffer contents from given codepage
- * \return newly allocated track
-*/
-ASS_Track *ass_read_memory(ASS_Library *library, char *buf,
- size_t bufsize, char *codepage)
-{
- ASS_Track *track;
- int need_free = 0;
-
- if (!buf)
- return 0;
-
-#ifdef CONFIG_ICONV
- if (codepage) {
- buf = sub_recode(library, buf, bufsize, codepage);
- if (!buf)
- return 0;
- else
- need_free = 1;
- }
-#endif
- track = parse_memory(library, buf);
- if (need_free)
- free(buf);
- if (!track)
- return 0;
-
- ass_msg(library, MSGL_INFO, "Added subtitle file: "
- "<memory> (%d styles, %d events)",
- track->n_styles, track->n_events);
- return track;
-}
-
-static char *read_file_recode(ASS_Library *library, char *fname,
- char *codepage, size_t *size)
-{
- char *buf;
- size_t bufsize;
-
- buf = read_file(library, fname, &bufsize);
- if (!buf)
- return 0;
-#ifdef CONFIG_ICONV
- if (codepage) {
- char *tmpbuf = sub_recode(library, buf, bufsize, codepage);
- free(buf);
- buf = tmpbuf;
- }
- if (!buf)
- return 0;
-#endif
- *size = bufsize;
- return buf;
-}
-
-/**
- * \brief Read subtitles from file.
- * \param library libass library object
- * \param fname file name
- * \param codepage recode buffer contents from given codepage
- * \return newly allocated track
-*/
-ASS_Track *ass_read_file(ASS_Library *library, char *fname,
- char *codepage)
-{
- char *buf;
- ASS_Track *track;
- size_t bufsize;
-
- buf = read_file_recode(library, fname, codepage, &bufsize);
- if (!buf)
- return 0;
- track = parse_memory(library, buf);
- free(buf);
- if (!track)
- return 0;
-
- track->name = strdup(fname);
-
- ass_msg(library, MSGL_INFO,
- "Added subtitle file: '%s' (%d styles, %d events)",
- fname, track->n_styles, track->n_events);
-
- return track;
-}
-
-/**
- * \brief read styles from file into already initialized track
- */
-int ass_read_styles(ASS_Track *track, char *fname, char *codepage)
-{
- char *buf;
- ParserState old_state;
- size_t sz;
-
- buf = read_file(track->library, fname, &sz);
- if (!buf)
- return 1;
-#ifdef CONFIG_ICONV
- if (codepage) {
- char *tmpbuf;
- tmpbuf = sub_recode(track->library, buf, sz, codepage);
- free(buf);
- buf = tmpbuf;
- }
- if (!buf)
- return 0;
-#endif
-
- old_state = track->parser_priv->state;
- track->parser_priv->state = PST_STYLES;
- process_text(track, buf);
- track->parser_priv->state = old_state;
-
- return 0;
-}
-
-long long ass_step_sub(ASS_Track *track, long long now, int movement)
-{
- int i;
-
- if (movement == 0)
- return 0;
- if (track->n_events == 0)
- return 0;
-
- if (movement < 0)
- for (i = 0;
- (i < track->n_events)
- &&
- ((long long) (track->events[i].Start +
- track->events[i].Duration) <= now); ++i) {
- } else
- for (i = track->n_events - 1;
- (i >= 0) && ((long long) (track->events[i].Start) > now);
- --i) {
- }
-
- // -1 and n_events are ok
- assert(i >= -1);
- assert(i <= track->n_events);
- i += movement;
- if (i < 0)
- i = 0;
- if (i >= track->n_events)
- i = track->n_events - 1;
- return ((long long) track->events[i].Start) - now;
-}
-
-ASS_Track *ass_new_track(ASS_Library *library)
-{
- ASS_Track *track = calloc(1, sizeof(ASS_Track));
- track->library = library;
- track->ScaledBorderAndShadow = 1;
- 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);
- }
- }
-}
diff --git a/lib/libass/libass/ass.h b/lib/libass/libass/ass.h
deleted file mode 100644
index 5aef92e3e5..0000000000
--- a/lib/libass/libass/ass.h
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LIBASS_ASS_H
-#define LIBASS_ASS_H
-
-#include <stdio.h>
-#include <stdarg.h>
-#include "ass_types.h"
-
-#define LIBASS_VERSION 0x01000000
-
-/*
- * A linked list of images produced by an ass renderer.
- *
- * These images have to be rendered in-order for the correct screen
- * composition. The libass renderer clips these bitmaps to the frame size.
- * w/h can be zero, in this case the bitmap should not be rendered at all.
- * The last bitmap row is not guaranteed to be padded up to stride size,
- * e.g. in the worst case a bitmap has the size stride * (h - 1) + w.
- */
-typedef struct ass_image {
- int w, h; // Bitmap width/height
- int stride; // Bitmap stride
- unsigned char *bitmap; // 1bpp stride*h alpha buffer
- // Note: the last row may not be padded to
- // bitmap stride!
- uint32_t color; // Bitmap color and alpha, RGBA
- int dst_x, dst_y; // Bitmap placement inside the video frame
-
- struct ass_image *next; // Next image, or NULL
-} ASS_Image;
-
-/*
- * Hinting type. (see ass_set_hinting below)
- *
- * FreeType's native hinter is still buggy sometimes and it is recommended
- * to use the light autohinter, ASS_HINTING_LIGHT, instead. For best
- * compatibility with problematic fonts, disable hinting.
- */
-typedef enum {
- ASS_HINTING_NONE = 0,
- ASS_HINTING_LIGHT,
- ASS_HINTING_NORMAL,
- ASS_HINTING_NATIVE
-} ASS_Hinting;
-
-/**
- * \brief Text shaping levels.
- *
- * SIMPLE is a fast, font-agnostic shaper that can do only substitutions.
- * COMPLEX is a slower shaper using OpenType for substitutions and positioning.
- *
- * libass uses the best shaper available by default.
- */
-typedef enum {
- ASS_SHAPING_SIMPLE = 0,
- ASS_SHAPING_COMPLEX
-} ASS_ShapingLevel;
-
-/**
- * \brief Initialize the library.
- * \return library handle or NULL if failed
- */
-ASS_Library *ass_library_init(void);
-
-/**
- * \brief Finalize the library
- * \param priv library handle
- */
-void ass_library_done(ASS_Library *priv);
-
-/**
- * \brief Set additional fonts directory.
- * Optional directory that will be scanned for fonts recursively. The fonts
- * found are used for font lookup.
- * NOTE: A valid font directory is not needed to support embedded fonts.
- *
- * \param priv library handle
- * \param fonts_dir directory with additional fonts
- */
-void ass_set_fonts_dir(ASS_Library *priv, const char *fonts_dir);
-
-/**
- * \brief Whether fonts should be extracted from track data.
- * \param priv library handle
- * \param extract whether to extract fonts
- */
-void ass_set_extract_fonts(ASS_Library *priv, int extract);
-
-/**
- * \brief Register style overrides with a library instance.
- * The overrides should have the form [Style.]Param=Value, e.g.
- * SomeStyle.Font=Arial
- * ScaledBorderAndShadow=yes
- *
- * \param priv library handle
- * \param list NULL-terminated list of strings
- */
-void ass_set_style_overrides(ASS_Library *priv, char **list);
-
-/**
- * \brief Explicitly process style overrides for a track.
- * \param track track handle
- */
-void ass_process_force_style(ASS_Track *track);
-
-/**
- * \brief Register a callback for debug/info messages.
- * If a callback is registered, it is called for every message emitted by
- * libass. The callback receives a format string and a list of arguments,
- * to be used for the printf family of functions. Additionally, a log level
- * from 0 (FATAL errors) to 7 (verbose DEBUG) is passed. Usually, level 5
- * should be used by applications.
- * If no callback is set, all messages level < 5 are printed to stderr,
- * prefixed with [ass].
- *
- * \param priv library handle
- * \param msg_cb pointer to callback function
- * \param data additional data, will be passed to callback
- */
-void ass_set_message_cb(ASS_Library *priv, void (*msg_cb)
- (int level, const char *fmt, va_list args, void *data),
- void *data);
-
-/**
- * \brief Initialize the renderer.
- * \param priv library handle
- * \return renderer handle or NULL if failed
- */
-ASS_Renderer *ass_renderer_init(ASS_Library *);
-
-/**
- * \brief Finalize the renderer.
- * \param priv renderer handle
- */
-void ass_renderer_done(ASS_Renderer *priv);
-
-/**
- * \brief Set the frame size in pixels, including margins.
- * \param priv renderer handle
- * \param w width
- * \param h height
- */
-void ass_set_frame_size(ASS_Renderer *priv, int w, int h);
-
-/**
- * \brief Set shaping level. This is merely a hint, the renderer will use
- * whatever is available if the request cannot be fulfilled.
- * \param level shaping level
- */
-void ass_set_shaper(ASS_Renderer *priv, ASS_ShapingLevel level);
-
-/**
- * \brief Set frame margins. These values may be negative if pan-and-scan
- * is used.
- * \param priv renderer handle
- * \param t top margin
- * \param b bottom margin
- * \param l left margin
- * \param r right margin
- */
-void ass_set_margins(ASS_Renderer *priv, int t, int b, int l, int r);
-
-/**
- * \brief Whether margins should be used for placing regular events.
- * \param priv renderer handle
- * \param use whether to use the margins
- */
-void ass_set_use_margins(ASS_Renderer *priv, int use);
-
-/**
- * \brief Set aspect ratio parameters.
- * \param priv renderer handle
- * \param dar display aspect ratio (DAR), prescaled for output PAR
- * \param sar storage aspect ratio (SAR)
- */
-void ass_set_aspect_ratio(ASS_Renderer *priv, double dar, double sar);
-
-/**
- * \brief Set a fixed font scaling factor.
- * \param priv renderer handle
- * \param font_scale scaling factor, default is 1.0
- */
-void ass_set_font_scale(ASS_Renderer *priv, double font_scale);
-
-/**
- * \brief Set font hinting method.
- * \param priv renderer handle
- * \param ht hinting method
- */
-void ass_set_hinting(ASS_Renderer *priv, ASS_Hinting ht);
-
-/**
- * \brief Set line spacing. Will not be scaled with frame size.
- * \param priv renderer handle
- * \param line_spacing line spacing in pixels
- */
-void ass_set_line_spacing(ASS_Renderer *priv, double line_spacing);
-
-/**
- * \brief Set font lookup defaults.
- * \param default_font path to default font to use. Must be supplied if
- * fontconfig is disabled or unavailable.
- * \param default_family fallback font family for fontconfig, or NULL
- * \param fc whether to use fontconfig
- * \param config path to fontconfig configuration file, or NULL. Only relevant
- * if fontconfig is used.
- * \param update whether fontconfig cache should be built/updated now. Only
- * relevant if fontconfig is used.
- *
- * NOTE: font lookup must be configured before an ASS_Renderer can be used.
- */
-void ass_set_fonts(ASS_Renderer *priv, const char *default_font,
- const char *default_family, int fc, const char *config,
- int update);
-
-/**
- * \brief Update/build font cache. This needs to be called if it was
- * disabled when ass_set_fonts was set.
- *
- * \param priv renderer handle
- * \return success
- */
-int ass_fonts_update(ASS_Renderer *priv);
-
-/**
- * \brief Set hard cache limits. Do not set, or set to zero, for reasonable
- * defaults.
- *
- * \param priv renderer handle
- * \param glyph_max maximum number of cached glyphs
- * \param bitmap_max_size maximum bitmap cache size (in MB)
- */
-void ass_set_cache_limits(ASS_Renderer *priv, int glyph_max,
- int bitmap_max_size);
-
-/**
- * \brief Render a frame, producing a list of ASS_Image.
- * \param priv renderer handle
- * \param track subtitle track
- * \param now video timestamp in milliseconds
- * \param detect_change will be set to 1 if a change occured compared
- * to the last invocation
- */
-ASS_Image *ass_render_frame(ASS_Renderer *priv, ASS_Track *track,
- long long now, int *detect_change);
-
-
-/*
- * The following functions operate on track objects and do not need
- * an ass_renderer
- */
-
-/**
- * \brief Allocate a new empty track object.
- * \param library handle
- * \return pointer to empty track
- */
-ASS_Track *ass_new_track(ASS_Library *);
-
-/**
- * \brief Deallocate track and all its child objects (styles and events).
- * \param track track to deallocate
- */
-void ass_free_track(ASS_Track *track);
-
-/**
- * \brief Allocate new style.
- * \param track track
- * \return newly allocated style id
- */
-int ass_alloc_style(ASS_Track *track);
-
-/**
- * \brief Allocate new event.
- * \param track track
- * \return newly allocated event id
- */
-int ass_alloc_event(ASS_Track *track);
-
-/**
- * \brief Delete a style.
- * \param track track
- * \param sid style id
- * Deallocates style data. Does not modify track->n_styles.
- */
-void ass_free_style(ASS_Track *track, int sid);
-
-/**
- * \brief Delete an event.
- * \param track track
- * \param eid event id
- * Deallocates event data. Does not modify track->n_events.
- */
-void ass_free_event(ASS_Track *track, int eid);
-
-/**
- * \brief Parse a chunk of subtitle stream data.
- * \param track track
- * \param data string to parse
- * \param size length of data
- */
-void ass_process_data(ASS_Track *track, char *data, int size);
-
-/**
- * \brief Parse Codec Private section of the subtitle stream, in Matroska
- * format. See the Matroska specification for details.
- * \param track target track
- * \param data string to parse
- * \param size length of data
- */
-void ass_process_codec_private(ASS_Track *track, char *data, int size);
-
-/**
- * \brief Parse a chunk of subtitle stream data. A chunk contains exactly one
- * event in Matroska format. See the Matroska specification for details.
- * \param track track
- * \param data string to parse
- * \param size length of data
- * \param timecode starting time of the event (milliseconds)
- * \param duration duration of the event (milliseconds)
- */
-void ass_process_chunk(ASS_Track *track, char *data, int size,
- long long timecode, long long duration);
-
-/**
- * \brief Flush buffered events.
- * \param track track
-*/
-void ass_flush_events(ASS_Track *track);
-
-/**
- * \brief Read subtitles from file.
- * \param library library handle
- * \param fname file name
- * \param codepage encoding (iconv format)
- * \return newly allocated track
-*/
-ASS_Track *ass_read_file(ASS_Library *library, char *fname,
- char *codepage);
-
-/**
- * \brief Read subtitles from memory.
- * \param library library handle
- * \param buf pointer to subtitles text
- * \param bufsize size of buffer
- * \param codepage encoding (iconv format)
- * \return newly allocated track
-*/
-ASS_Track *ass_read_memory(ASS_Library *library, char *buf,
- size_t bufsize, char *codepage);
-/**
- * \brief Read styles from file into already initialized track.
- * \param fname file name
- * \param codepage encoding (iconv format)
- * \return 0 on success
- */
-int ass_read_styles(ASS_Track *track, char *fname, char *codepage);
-
-/**
- * \brief Add a memory font.
- * \param library library handle
- * \param name attachment name
- * \param data binary font data
- * \param data_size data size
-*/
-void ass_add_font(ASS_Library *library, char *name, char *data,
- int data_size);
-
-/**
- * \brief Remove all fonts stored in an ass_library object.
- * \param library library handle
- */
-void ass_clear_fonts(ASS_Library *library);
-
-/**
- * \brief Calculates timeshift from now to the start of some other subtitle
- * event, depending on movement parameter.
- * \param track subtitle track
- * \param now current time in milliseconds
- * \param movement how many events to skip from the one currently displayed
- * +2 means "the one after the next", -1 means "previous"
- * \return timeshift in milliseconds
- */
-long long ass_step_sub(ASS_Track *track, long long now, int movement);
-
-#endif /* LIBASS_ASS_H */
diff --git a/lib/libass/libass/ass_bitmap.c b/lib/libass/libass/ass_bitmap.c
deleted file mode 100644
index 6afe05d2f0..0000000000
--- a/lib/libass/libass/ass_bitmap.c
+++ /dev/null
@@ -1,526 +0,0 @@
-/*
- * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
- * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
- *
- * 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 <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <assert.h>
-#include <ft2build.h>
-#include FT_GLYPH_H
-#include FT_OUTLINE_H
-
-#include "ass_utils.h"
-#include "ass_bitmap.h"
-
-struct ass_synth_priv {
- int tmp_w, tmp_h;
- unsigned short *tmp;
-
- int g_r;
- int g_w;
-
- unsigned *g;
- unsigned *gt2;
-
- double radius;
-};
-
-static const unsigned int maxcolor = 255;
-static const unsigned base = 256;
-
-static int generate_tables(ASS_SynthPriv *priv, double radius)
-{
- double A = log(1.0 / base) / (radius * radius * 2);
- int mx, i;
- double volume_diff, volume_factor = 0;
- unsigned volume;
-
- if (priv->radius == radius)
- return 0;
- else
- priv->radius = radius;
-
- priv->g_r = ceil(radius);
- priv->g_w = 2 * priv->g_r + 1;
-
- if (priv->g_r) {
- priv->g = realloc(priv->g, priv->g_w * sizeof(unsigned));
- priv->gt2 = realloc(priv->gt2, 256 * priv->g_w * sizeof(unsigned));
- if (priv->g == NULL || priv->gt2 == NULL) {
- return -1;
- }
- }
-
- if (priv->g_r) {
- // gaussian curve with volume = 256
- for (volume_diff = 10000000; volume_diff > 0.0000001;
- volume_diff *= 0.5) {
- volume_factor += volume_diff;
- volume = 0;
- for (i = 0; i < priv->g_w; ++i) {
- priv->g[i] =
- (unsigned) (exp(A * (i - priv->g_r) * (i - priv->g_r)) *
- volume_factor + .5);
- volume += priv->g[i];
- }
- if (volume > 256)
- volume_factor -= volume_diff;
- }
- volume = 0;
- for (i = 0; i < priv->g_w; ++i) {
- priv->g[i] =
- (unsigned) (exp(A * (i - priv->g_r) * (i - priv->g_r)) *
- volume_factor + .5);
- volume += priv->g[i];
- }
-
- // gauss table:
- for (mx = 0; mx < priv->g_w; mx++) {
- for (i = 0; i < 256; i++) {
- priv->gt2[mx + i * priv->g_w] = i * priv->g[mx];
- }
- }
- }
-
- return 0;
-}
-
-static void resize_tmp(ASS_SynthPriv *priv, int w, int h)
-{
- if (priv->tmp_w >= w && priv->tmp_h >= h)
- return;
- if (priv->tmp_w == 0)
- priv->tmp_w = 64;
- if (priv->tmp_h == 0)
- priv->tmp_h = 64;
- while (priv->tmp_w < w)
- priv->tmp_w *= 2;
- while (priv->tmp_h < h)
- priv->tmp_h *= 2;
- free(priv->tmp);
- priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short));
-}
-
-ASS_SynthPriv *ass_synth_init(double radius)
-{
- ASS_SynthPriv *priv = calloc(1, sizeof(ASS_SynthPriv));
- generate_tables(priv, radius);
- return priv;
-}
-
-void ass_synth_done(ASS_SynthPriv *priv)
-{
- free(priv->tmp);
- free(priv->g);
- free(priv->gt2);
- free(priv);
-}
-
-static Bitmap *alloc_bitmap(int w, int h)
-{
- Bitmap *bm;
- unsigned s = w; // XXX: alignment
- bm = malloc(sizeof(Bitmap));
- bm->buffer = calloc(s, h);
- bm->w = w;
- bm->h = h;
- bm->stride = s;
- bm->left = bm->top = 0;
- return bm;
-}
-
-void ass_free_bitmap(Bitmap *bm)
-{
- if (bm)
- free(bm->buffer);
- free(bm);
-}
-
-static Bitmap *copy_bitmap(const Bitmap *src)
-{
- Bitmap *dst = alloc_bitmap(src->w, src->h);
- dst->left = src->left;
- dst->top = src->top;
- memcpy(dst->buffer, src->buffer, src->stride * src->h);
- return dst;
-}
-
-Bitmap *outline_to_bitmap(ASS_Library *library, FT_Library ftlib,
- FT_Outline *outline, int bord)
-{
- Bitmap *bm;
- int w, h;
- int error;
- FT_BBox bbox;
- FT_Bitmap bitmap;
-
- FT_Outline_Get_CBox(outline, &bbox);
- // move glyph to origin (0, 0)
- bbox.xMin &= ~63;
- bbox.yMin &= ~63;
- FT_Outline_Translate(outline, -bbox.xMin, -bbox.yMin);
- // bitmap size
- bbox.xMax = (bbox.xMax + 63) & ~63;
- bbox.yMax = (bbox.yMax + 63) & ~63;
- w = (bbox.xMax - bbox.xMin) >> 6;
- h = (bbox.yMax - bbox.yMin) >> 6;
- // pen offset
- bbox.xMin >>= 6;
- bbox.yMax >>= 6;
-
- if (w * h > 8000000) {
- ass_msg(library, MSGL_WARN, "Glyph bounding box too large: %dx%dpx",
- w, h);
- return NULL;
- }
-
- // allocate and set up bitmap
- bm = alloc_bitmap(w + 2 * bord, h + 2 * bord);
- bm->left = bbox.xMin - bord;
- bm->top = -bbox.yMax - bord;
- bitmap.width = w;
- bitmap.rows = h;
- bitmap.pitch = bm->stride;
- bitmap.buffer = bm->buffer + bord + bm->stride * bord;
- bitmap.num_grays = 256;
- bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
-
- // render into target bitmap
- if ((error = FT_Outline_Get_Bitmap(ftlib, outline, &bitmap))) {
- ass_msg(library, MSGL_WARN, "Failed to rasterize glyph: %d\n", error);
- ass_free_bitmap(bm);
- return NULL;
- }
-
- return bm;
-}
-
-/**
- * \brief fix outline bitmap
- *
- * The glyph bitmap is subtracted from outline bitmap. This way looks much
- * better in some cases.
- */
-static void fix_outline(Bitmap *bm_g, Bitmap *bm_o)
-{
- int x, y;
- const int l = bm_o->left > bm_g->left ? bm_o->left : bm_g->left;
- const int t = bm_o->top > bm_g->top ? bm_o->top : bm_g->top;
- const int r =
- bm_o->left + bm_o->stride <
- bm_g->left + bm_g->stride ? bm_o->left + bm_o->stride : bm_g->left + bm_g->stride;
- const int b =
- bm_o->top + bm_o->h <
- bm_g->top + bm_g->h ? bm_o->top + bm_o->h : bm_g->top + bm_g->h;
-
- unsigned char *g =
- bm_g->buffer + (t - bm_g->top) * bm_g->stride + (l - bm_g->left);
- unsigned char *o =
- bm_o->buffer + (t - bm_o->top) * bm_o->stride + (l - bm_o->left);
-
- for (y = 0; y < b - t; ++y) {
- for (x = 0; x < r - l; ++x) {
- unsigned char c_g, c_o;
- c_g = g[x];
- c_o = o[x];
- o[x] = (c_o > c_g) ? c_o - (c_g / 2) : 0;
- }
- g += bm_g->stride;
- o += bm_o->stride;
- }
-}
-
-/**
- * \brief Shift a bitmap by the fraction of a pixel in x and y direction
- * expressed in 26.6 fixed point
- */
-static void shift_bitmap(Bitmap *bm, int shift_x, int shift_y)
-{
- int x, y, b;
- int w = bm->w;
- int h = bm->h;
- int s = bm->stride;
- unsigned char *buf = bm->buffer;
-
- // Shift in x direction
- if (shift_x > 0) {
- for (y = 0; y < h; y++) {
- for (x = w - 1; x > 0; x--) {
- b = (buf[x + y * s - 1] * shift_x) >> 6;
- buf[x + y * s - 1] -= b;
- buf[x + y * s] += b;
- }
- }
- } else if (shift_x < 0) {
- shift_x = -shift_x;
- for (y = 0; y < h; y++) {
- for (x = 0; x < w - 1; x++) {
- b = (buf[x + y * s + 1] * shift_x) >> 6;
- buf[x + y * s + 1] -= b;
- buf[x + y * s] += b;
- }
- }
- }
-
- // Shift in y direction
- if (shift_y > 0) {
- for (x = 0; x < w; x++) {
- for (y = h - 1; y > 0; y--) {
- b = (buf[x + (y - 1) * s] * shift_y) >> 6;
- buf[x + (y - 1) * s] -= b;
- buf[x + y * s] += b;
- }
- }
- } else if (shift_y < 0) {
- shift_y = -shift_y;
- for (x = 0; x < w; x++) {
- for (y = 0; y < h - 1; y++) {
- b = (buf[x + (y + 1) * s] * shift_y) >> 6;
- buf[x + (y + 1) * s] -= b;
- buf[x + y * s] += b;
- }
- }
- }
-}
-
-/*
- * Gaussian blur. An fast pure C implementation from MPlayer.
- */
-static void ass_gauss_blur(unsigned char *buffer, unsigned short *tmp2,
- int width, int height, int stride, int *m2,
- int r, int mwidth)
-{
-
- int x, y;
-
- unsigned char *s = buffer;
- unsigned short *t = tmp2 + 1;
- for (y = 0; y < height; y++) {
- memset(t - 1, 0, (width + 1) * sizeof(short));
-
- for (x = 0; x < r; x++) {
- const int src = s[x];
- if (src) {
- register unsigned short *dstp = t + x - r;
- int mx;
- unsigned *m3 = (unsigned *) (m2 + src * mwidth);
- for (mx = r - x; mx < mwidth; mx++) {
- dstp[mx] += m3[mx];
- }
- }
- }
-
- for (; x < width - r; x++) {
- const int src = s[x];
- if (src) {
- register unsigned short *dstp = t + x - r;
- int mx;
- unsigned *m3 = (unsigned *) (m2 + src * mwidth);
- for (mx = 0; mx < mwidth; mx++) {
- dstp[mx] += m3[mx];
- }
- }
- }
-
- for (; x < width; x++) {
- const int src = s[x];
- if (src) {
- register unsigned short *dstp = t + x - r;
- int mx;
- const int x2 = r + width - x;
- unsigned *m3 = (unsigned *) (m2 + src * mwidth);
- for (mx = 0; mx < x2; mx++) {
- dstp[mx] += m3[mx];
- }
- }
- }
-
- s += stride;
- t += width + 1;
- }
-
- t = tmp2;
- for (x = 0; x < width; x++) {
- for (y = 0; y < r; y++) {
- unsigned short *srcp = t + y * (width + 1) + 1;
- int src = *srcp;
- if (src) {
- register unsigned short *dstp = srcp - 1 + width + 1;
- const int src2 = (src + 128) >> 8;
- unsigned *m3 = (unsigned *) (m2 + src2 * mwidth);
-
- int mx;
- *srcp = 128;
- for (mx = r - 1; mx < mwidth; mx++) {
- *dstp += m3[mx];
- dstp += width + 1;
- }
- }
- }
- for (; y < height - r; y++) {
- unsigned short *srcp = t + y * (width + 1) + 1;
- int src = *srcp;
- if (src) {
- register unsigned short *dstp = srcp - 1 - r * (width + 1);
- const int src2 = (src + 128) >> 8;
- unsigned *m3 = (unsigned *) (m2 + src2 * mwidth);
-
- int mx;
- *srcp = 128;
- for (mx = 0; mx < mwidth; mx++) {
- *dstp += m3[mx];
- dstp += width + 1;
- }
- }
- }
- for (; y < height; y++) {
- unsigned short *srcp = t + y * (width + 1) + 1;
- int src = *srcp;
- if (src) {
- const int y2 = r + height - y;
- register unsigned short *dstp = srcp - 1 - r * (width + 1);
- const int src2 = (src + 128) >> 8;
- unsigned *m3 = (unsigned *) (m2 + src2 * mwidth);
-
- int mx;
- *srcp = 128;
- for (mx = 0; mx < y2; mx++) {
- *dstp += m3[mx];
- dstp += width + 1;
- }
- }
- }
- t++;
- }
-
- t = tmp2;
- s = buffer;
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- s[x] = t[x] >> 8;
- }
- s += stride;
- t += width + 1;
- }
-}
-
-/**
- * \brief Blur with [[1,2,1]. [2,4,2], [1,2,1]] kernel
- * This blur is the same as the one employed by vsfilter.
- */
-static void be_blur(Bitmap *bm)
-{
- int w = bm->w;
- int h = bm->h;
- int s = bm->stride;
- unsigned char *buf = bm->buffer;
- unsigned int x, y;
- unsigned int old_sum, new_sum;
-
- for (y = 0; y < h; y++) {
- old_sum = 2 * buf[y * s];
- for (x = 0; x < w - 1; x++) {
- new_sum = buf[y * s + x] + buf[y * s + x + 1];
- buf[y * s + x] = (old_sum + new_sum) >> 2;
- old_sum = new_sum;
- }
- }
-
- for (x = 0; x < w; x++) {
- old_sum = 2 * buf[x];
- for (y = 0; y < h - 1; y++) {
- new_sum = buf[y * s + x] + buf[(y + 1) * s + x];
- buf[y * s + x] = (old_sum + new_sum) >> 2;
- old_sum = new_sum;
- }
- }
-}
-
-int outline_to_bitmap3(ASS_Library *library, ASS_SynthPriv *priv_blur,
- FT_Library ftlib, FT_Outline *outline, FT_Outline *border,
- Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s,
- int be, double blur_radius, FT_Vector shadow_offset,
- int border_style)
-{
- int bord, bbord, gbord;
- blur_radius *= 2;
- bbord = be > 0 ? sqrt(2 * be) : 0;
- gbord = blur_radius > 0.0 ? blur_radius + 1 : 0;
- bord = FFMAX(bbord, gbord);
- if (bord == 0 && (shadow_offset.x || shadow_offset.y))
- bord = 1;
-
- assert(bm_g && bm_o && bm_s);
-
- *bm_g = *bm_o = *bm_s = 0;
-
- if (outline)
- *bm_g = outline_to_bitmap(library, ftlib, outline, bord);
- if (!*bm_g)
- return 1;
-
- if (border) {
- *bm_o = outline_to_bitmap(library, ftlib, border, bord);
- if (!*bm_o) {
- return 1;
- }
- }
-
- // Apply box blur (multiple passes, if requested)
- while (be--) {
- if (*bm_o)
- be_blur(*bm_o);
- else
- be_blur(*bm_g);
- }
-
- // Apply gaussian blur
- if (blur_radius > 0.0) {
- if (*bm_o)
- resize_tmp(priv_blur, (*bm_o)->w, (*bm_o)->h);
- else
- resize_tmp(priv_blur, (*bm_g)->w, (*bm_g)->h);
- generate_tables(priv_blur, blur_radius);
- if (*bm_o)
- ass_gauss_blur((*bm_o)->buffer, priv_blur->tmp,
- (*bm_o)->w, (*bm_o)->h, (*bm_o)->stride,
- (int *) priv_blur->gt2, priv_blur->g_r,
- priv_blur->g_w);
- else
- ass_gauss_blur((*bm_g)->buffer, priv_blur->tmp,
- (*bm_g)->w, (*bm_g)->h, (*bm_g)->stride,
- (int *) priv_blur->gt2, priv_blur->g_r,
- priv_blur->g_w);
- }
-
- // Create shadow and fix outline as needed
- if (*bm_o && border_style != 3) {
- *bm_s = copy_bitmap(*bm_o);
- fix_outline(*bm_g, *bm_o);
- } else if (*bm_o) {
- *bm_s = copy_bitmap(*bm_o);
- } else
- *bm_s = copy_bitmap(*bm_g);
-
- assert(bm_s);
-
- shift_bitmap(*bm_s, shadow_offset.x, shadow_offset.y);
-
- return 0;
-}
diff --git a/lib/libass/libass/ass_bitmap.h b/lib/libass/libass/ass_bitmap.h
deleted file mode 100644
index 2a46aec447..0000000000
--- a/lib/libass/libass/ass_bitmap.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LIBASS_BITMAP_H
-#define LIBASS_BITMAP_H
-
-#include <ft2build.h>
-#include FT_GLYPH_H
-
-#include "ass.h"
-
-typedef struct ass_synth_priv ASS_SynthPriv;
-
-ASS_SynthPriv *ass_synth_init(double);
-void ass_synth_done(ASS_SynthPriv *priv);
-
-typedef struct {
- int left, top;
- int w, h; // width, height
- int stride;
- unsigned char *buffer; // w x h buffer
-} Bitmap;
-
-Bitmap *outline_to_bitmap(ASS_Library *library, FT_Library ftlib,
- FT_Outline *outline, int bord);
-/**
- * \brief perform glyph rendering
- * \param glyph original glyph
- * \param outline_glyph "border" glyph, produced from original by FreeType's glyph stroker
- * \param bm_g out: pointer to the bitmap of original glyph is returned here
- * \param bm_o out: pointer to the bitmap of outline (border) glyph is returned here
- * \param bm_g out: pointer to the bitmap of glyph shadow is returned here
- * \param be 1 = produces blurred bitmaps, 0 = normal bitmaps
- */
-int outline_to_bitmap3(ASS_Library *library, ASS_SynthPriv *priv_blur,
- FT_Library ftlib, FT_Outline *outline, FT_Outline *border,
- Bitmap **bm_g, Bitmap **bm_o, Bitmap **bm_s,
- int be, double blur_radius, FT_Vector shadow_offset,
- int border_style);
-
-void ass_free_bitmap(Bitmap *bm);
-
-#endif /* LIBASS_BITMAP_H */
diff --git a/lib/libass/libass/ass_cache.c b/lib/libass/libass/ass_cache.c
deleted file mode 100644
index 91801a0abc..0000000000
--- a/lib/libass/libass/ass_cache.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
- * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
- *
- * 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 <inttypes.h>
-#include <ft2build.h>
-#include FT_OUTLINE_H
-#include <assert.h>
-
-#include "ass_utils.h"
-#include "ass_font.h"
-#include "ass_cache.h"
-
-// type-specific functions
-// create hash/compare functions for bitmap, outline and composite cache
-#define CREATE_HASH_FUNCTIONS
-#include "ass_cache_template.h"
-#define CREATE_COMPARISON_FUNCTIONS
-#include "ass_cache_template.h"
-
-// font cache
-static unsigned font_hash(void *buf, size_t len)
-{
- ASS_FontDesc *desc = buf;
- unsigned hval;
- hval = fnv_32a_str(desc->family, FNV1_32A_INIT);
- hval = fnv_32a_buf(&desc->bold, sizeof(desc->bold), hval);
- hval = fnv_32a_buf(&desc->italic, sizeof(desc->italic), hval);
- hval = fnv_32a_buf(&desc->treat_family_as_pattern,
- sizeof(desc->treat_family_as_pattern), hval);
- hval = fnv_32a_buf(&desc->vertical, sizeof(desc->vertical), hval);
- return hval;
-}
-
-static unsigned font_compare(void *key1, void *key2, size_t key_size)
-{
- ASS_FontDesc *a = key1;
- ASS_FontDesc *b = key2;
- if (strcmp(a->family, b->family) != 0)
- return 0;
- if (a->bold != b->bold)
- return 0;
- if (a->italic != b->italic)
- return 0;
- if (a->treat_family_as_pattern != b->treat_family_as_pattern)
- return 0;
- if (a->vertical != b->vertical)
- return 0;
- return 1;
-}
-
-static void font_destruct(void *key, void *value)
-{
- ass_font_free(value);
- free(key);
-}
-
-// bitmap cache
-static void bitmap_destruct(void *key, void *value)
-{
- BitmapHashValue *v = value;
- BitmapHashKey *k = key;
- if (v->bm)
- ass_free_bitmap(v->bm);
- if (v->bm_o)
- ass_free_bitmap(v->bm_o);
- if (v->bm_s)
- ass_free_bitmap(v->bm_s);
- if (k->type == BITMAP_CLIP)
- free(k->u.clip.text);
- free(key);
- free(value);
-}
-
-static size_t bitmap_size(void *value, size_t value_size)
-{
- BitmapHashValue *val = value;
- if (val->bm_o)
- return val->bm_o->w * val->bm_o->h * 3;
- else if (val->bm)
- return val->bm->w * val->bm->h * 3;
- return 0;
-}
-
-static unsigned bitmap_hash(void *key, size_t key_size)
-{
- BitmapHashKey *k = key;
- switch (k->type) {
- case BITMAP_OUTLINE: return outline_bitmap_hash(&k->u, key_size);
- case BITMAP_CLIP: return clip_bitmap_hash(&k->u, key_size);
- default: return 0;
- }
-}
-
-static unsigned bitmap_compare (void *a, void *b, size_t key_size)
-{
- BitmapHashKey *ak = a;
- BitmapHashKey *bk = b;
- if (ak->type != bk->type) return 0;
- switch (ak->type) {
- case BITMAP_OUTLINE: return outline_bitmap_compare(&ak->u, &bk->u, key_size);
- case BITMAP_CLIP: return clip_bitmap_compare(&ak->u, &bk->u, key_size);
- default: return 0;
- }
-}
-
-// composite cache
-static void composite_destruct(void *key, void *value)
-{
- CompositeHashValue *v = value;
- free(v->a);
- free(v->b);
- free(key);
- free(value);
-}
-
-// outline cache
-
-static unsigned outline_hash(void *key, size_t key_size)
-{
- OutlineHashKey *k = key;
- switch (k->type) {
- case OUTLINE_GLYPH: return glyph_hash(&k->u, key_size);
- case OUTLINE_DRAWING: return drawing_hash(&k->u, key_size);
- default: return 0;
- }
-}
-
-static unsigned outline_compare(void *a, void *b, size_t key_size)
-{
- OutlineHashKey *ak = a;
- OutlineHashKey *bk = b;
- if (ak->type != bk->type) return 0;
- switch (ak->type) {
- case OUTLINE_GLYPH: return glyph_compare(&ak->u, &bk->u, key_size);
- case OUTLINE_DRAWING: return drawing_compare(&ak->u, &bk->u, key_size);
- default: return 0;
- }
-}
-
-static void outline_destruct(void *key, void *value)
-{
- OutlineHashValue *v = value;
- OutlineHashKey *k = key;
- if (v->outline)
- outline_free(v->lib, v->outline);
- if (v->border)
- outline_free(v->lib, v->border);
- if (k->type == OUTLINE_DRAWING)
- free(k->u.drawing.text);
- free(key);
- free(value);
-}
-
-
-
-// Cache data
-typedef struct cache_item {
- void *key;
- void *value;
- struct cache_item *next;
-} CacheItem;
-
-struct cache {
- unsigned buckets;
- CacheItem **map;
-
- HashFunction hash_func;
- ItemSize size_func;
- HashCompare compare_func;
- CacheItemDestructor destruct_func;
- size_t key_size;
- size_t value_size;
-
- size_t cache_size;
- unsigned hits;
- unsigned misses;
- unsigned items;
-};
-
-// Hash for a simple (single value or array) type
-static unsigned hash_simple(void *key, size_t key_size)
-{
- return fnv_32a_buf(key, key_size, FNV1_32A_INIT);
-}
-
-// Comparison of a simple type
-static unsigned compare_simple(void *a, void *b, size_t key_size)
-{
- return memcmp(a, b, key_size) == 0;
-}
-
-// Default destructor
-static void destruct_simple(void *key, void *value)
-{
- free(key);
- free(value);
-}
-
-
-// Create a cache with type-specific hash/compare/destruct/size functions
-Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func,
- CacheItemDestructor destruct_func, ItemSize size_func,
- size_t key_size, size_t value_size)
-{
- Cache *cache = calloc(1, sizeof(*cache));
- cache->buckets = 0xFFFF;
- cache->hash_func = hash_simple;
- cache->compare_func = compare_simple;
- cache->destruct_func = destruct_simple;
- cache->size_func = size_func;
- if (hash_func)
- cache->hash_func = hash_func;
- if (compare_func)
- cache->compare_func = compare_func;
- if (destruct_func)
- cache->destruct_func = destruct_func;
- cache->key_size = key_size;
- cache->value_size = value_size;
- cache->map = calloc(cache->buckets, sizeof(CacheItem *));
-
- return cache;
-}
-
-void *ass_cache_put(Cache *cache, void *key, void *value)
-{
- unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets;
- CacheItem **item = &cache->map[bucket];
- while (*item)
- item = &(*item)->next;
- (*item) = calloc(1, sizeof(CacheItem));
- (*item)->key = malloc(cache->key_size);
- (*item)->value = malloc(cache->value_size);
- memcpy((*item)->key, key, cache->key_size);
- memcpy((*item)->value, value, cache->value_size);
-
- cache->items++;
- if (cache->size_func)
- cache->cache_size += cache->size_func(value, cache->value_size);
- else
- cache->cache_size++;
-
- return (*item)->value;
-}
-
-void *ass_cache_get(Cache *cache, void *key)
-{
- unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets;
- CacheItem *item = cache->map[bucket];
- while (item) {
- if (cache->compare_func(key, item->key, cache->key_size)) {
- cache->hits++;
- return item->value;
- }
- item = item->next;
- }
- cache->misses++;
- return NULL;
-}
-
-int ass_cache_empty(Cache *cache, size_t max_size)
-{
- int i;
-
- if (cache->cache_size < max_size)
- return 0;
-
- for (i = 0; i < cache->buckets; i++) {
- CacheItem *item = cache->map[i];
- while (item) {
- CacheItem *next = item->next;
- cache->destruct_func(item->key, item->value);
- free(item);
- item = next;
- }
- cache->map[i] = NULL;
- }
-
- cache->items = cache->hits = cache->misses = cache->cache_size = 0;
-
- return 1;
-}
-
-void ass_cache_stats(Cache *cache, size_t *size, unsigned *hits,
- unsigned *misses, unsigned *count)
-{
- if (size)
- *size = cache->cache_size;
- if (hits)
- *hits = cache->hits;
- if (misses)
- *misses = cache->misses;
- if (count)
- *count = cache->items;
-}
-
-void ass_cache_done(Cache *cache)
-{
- ass_cache_empty(cache, 0);
- free(cache->map);
- free(cache);
-}
-
-// Type-specific creation function
-Cache *ass_font_cache_create(void)
-{
- return ass_cache_create(font_hash, font_compare, font_destruct,
- (ItemSize)NULL, sizeof(ASS_FontDesc), sizeof(ASS_Font));
-}
-
-Cache *ass_outline_cache_create(void)
-{
- return ass_cache_create(outline_hash, outline_compare, outline_destruct,
- NULL, sizeof(OutlineHashKey), sizeof(OutlineHashValue));
-}
-
-Cache *ass_glyph_metrics_cache_create(void)
-{
- return ass_cache_create(glyph_metrics_hash, glyph_metrics_compare, NULL,
- (ItemSize) NULL, sizeof(GlyphMetricsHashKey),
- sizeof(GlyphMetricsHashValue));
-}
-
-Cache *ass_bitmap_cache_create(void)
-{
- return ass_cache_create(bitmap_hash, bitmap_compare, bitmap_destruct,
- bitmap_size, sizeof(BitmapHashKey), sizeof(BitmapHashValue));
-}
-
-Cache *ass_composite_cache_create(void)
-{
- return ass_cache_create(composite_hash, composite_compare,
- composite_destruct, (ItemSize)NULL, sizeof(CompositeHashKey),
- sizeof(CompositeHashValue));
-}
diff --git a/lib/libass/libass/ass_cache.h b/lib/libass/libass/ass_cache.h
deleted file mode 100644
index 7375f04343..0000000000
--- a/lib/libass/libass/ass_cache.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
- * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
- *
- * 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.
- */
-
-#ifndef LIBASS_CACHE_H
-#define LIBASS_CACHE_H
-
-#include "ass.h"
-#include "ass_font.h"
-#include "ass_bitmap.h"
-
-typedef struct cache Cache;
-
-// cache values
-
-typedef struct {
- Bitmap *bm; // the actual bitmaps
- Bitmap *bm_o;
- Bitmap *bm_s;
-} BitmapHashValue;
-
-typedef struct {
- unsigned char *a;
- unsigned char *b;
-} CompositeHashValue;
-
-typedef struct {
- FT_Library lib;
- FT_Outline *outline;
- FT_Outline *border;
- FT_BBox bbox_scaled; // bbox after scaling, but before rotation
- FT_Vector advance; // 26.6, advance distance to the next outline in line
- int asc, desc; // ascender/descender
-} OutlineHashValue;
-
-typedef struct {
- FT_Glyph_Metrics metrics;
-} GlyphMetricsHashValue;
-
-// Create definitions for bitmap, outline and composite hash keys
-#define CREATE_STRUCT_DEFINITIONS
-#include "ass_cache_template.h"
-
-// Type-specific function pointers
-typedef unsigned(*HashFunction)(void *key, size_t key_size);
-typedef size_t(*ItemSize)(void *value, size_t value_size);
-typedef unsigned(*HashCompare)(void *a, void *b, size_t key_size);
-typedef void(*CacheItemDestructor)(void *key, void *value);
-
-// cache hash keys
-
-typedef struct outline_hash_key {
- enum {
- OUTLINE_GLYPH,
- OUTLINE_DRAWING,
- } type;
- union {
- GlyphHashKey glyph;
- DrawingHashKey drawing;
- } u;
-} OutlineHashKey;
-
-typedef struct bitmap_hash_key {
- enum {
- BITMAP_OUTLINE,
- BITMAP_CLIP,
- } type;
- union {
- OutlineBitmapHashKey outline;
- ClipMaskHashKey clip;
- } u;
-} BitmapHashKey;
-
-Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func,
- CacheItemDestructor destruct_func, ItemSize size_func,
- size_t key_size, size_t value_size);
-void *ass_cache_put(Cache *cache, void *key, void *value);
-void *ass_cache_get(Cache *cache, void *key);
-int ass_cache_empty(Cache *cache, size_t max_size);
-void ass_cache_stats(Cache *cache, size_t *size, unsigned *hits,
- unsigned *misses, unsigned *count);
-void ass_cache_done(Cache *cache);
-Cache *ass_font_cache_create(void);
-Cache *ass_outline_cache_create(void);
-Cache *ass_glyph_metrics_cache_create(void);
-Cache *ass_bitmap_cache_create(void);
-Cache *ass_composite_cache_create(void);
-
-#endif /* LIBASS_CACHE_H */
diff --git a/lib/libass/libass/ass_cache_template.h b/lib/libass/libass/ass_cache_template.h
deleted file mode 100644
index f9aab77919..0000000000
--- a/lib/libass/libass/ass_cache_template.h
+++ /dev/null
@@ -1,144 +0,0 @@
-#ifdef CREATE_STRUCT_DEFINITIONS
-#undef CREATE_STRUCT_DEFINITIONS
-#define START(funcname, structname) \
- typedef struct structname {
-#define GENERIC(type, member) \
- type member;
-#define STRING(member) \
- char *member;
-#define FTVECTOR(member) \
- FT_Vector member;
-#define BITMAPHASHKEY(member) \
- BitmapHashKey member;
-#define END(typedefnamename) \
- } typedefnamename;
-
-#elif defined(CREATE_COMPARISON_FUNCTIONS)
-#undef CREATE_COMPARISON_FUNCTIONS
-#define START(funcname, structname) \
- static unsigned funcname##_compare(void *key1, void *key2, size_t key_size) \
- { \
- struct structname *a = key1; \
- struct structname *b = key2; \
- return // conditions follow
-#define GENERIC(type, member) \
- a->member == b->member &&
-#define STRING(member) \
- strcmp(a->member, b->member) == 0 &&
-#define FTVECTOR(member) \
- a->member.x == b->member.x && a->member.y == b->member.y &&
-#define BITMAPHASHKEY(member) \
- bitmap_compare(&a->member, &b->member, sizeof(a->member)) &&
-#define END(typedefname) \
- 1; \
- }
-
-#elif defined(CREATE_HASH_FUNCTIONS)
-#undef CREATE_HASH_FUNCTIONS
-#define START(funcname, structname) \
- static unsigned funcname##_hash(void *buf, size_t len) \
- { \
- struct structname *p = buf; \
- unsigned hval = FNV1_32A_INIT;
-#define GENERIC(type, member) \
- hval = fnv_32a_buf(&p->member, sizeof(p->member), hval);
-#define STRING(member) \
- hval = fnv_32a_str(p->member, hval);
-#define FTVECTOR(member) GENERIC(, member.x); GENERIC(, member.y);
-#define BITMAPHASHKEY(member) { \
- unsigned temp = bitmap_hash(&p->member, sizeof(p->member)); \
- hval = fnv_32a_buf(&temp, sizeof(temp), hval); \
- }
-#define END(typedefname) \
- return hval; \
- }
-
-#else
-#error missing defines
-#endif
-
-
-
-// describes an outline bitmap
-START(outline_bitmap, outline_bitmap_hash_key)
- GENERIC(OutlineHashValue *, outline)
- GENERIC(char, be) // blur edges
- GENERIC(double, blur) // gaussian blur
- GENERIC(int, frx) // signed 16.16
- GENERIC(int, fry) // signed 16.16
- GENERIC(int, frz) // signed 16.16
- GENERIC(int, fax) // signed 16.16
- GENERIC(int, fay) // signed 16.16
- // shift vector that was added to glyph before applying rotation
- // = 0, if frx = fry = frx = 0
- // = (glyph base point) - (rotation origin), otherwise
- GENERIC(int, shift_x)
- GENERIC(int, shift_y)
- FTVECTOR(advance) // subpixel shift vector
- FTVECTOR(shadow_offset) // shadow subpixel shift
-END(OutlineBitmapHashKey)
-
-// describe a clip mask bitmap
-START(clip_bitmap, clip_bitmap_hash_key)
- STRING(text)
-END(ClipMaskHashKey)
-
-// describes an outline glyph
-START(glyph, glyph_hash_key)
- GENERIC(ASS_Font *, font)
- GENERIC(double, size) // font size
- GENERIC(int, face_index)
- GENERIC(int, glyph_index)
- GENERIC(int, bold)
- GENERIC(int, italic)
- GENERIC(unsigned, scale_x) // 16.16
- GENERIC(unsigned, scale_y) // 16.16
- FTVECTOR(outline) // border width, 16.16
- GENERIC(unsigned, flags) // glyph decoration flags
- GENERIC(unsigned, border_style)
-END(GlyphHashKey)
-
-START(glyph_metrics, glyph_metrics_hash_key)
- GENERIC(ASS_Font *, font)
- GENERIC(double, size)
- GENERIC(int, face_index)
- GENERIC(int, glyph_index)
- GENERIC(unsigned, scale_x)
- GENERIC(unsigned, scale_y)
-END(GlyphMetricsHashKey)
-
-// describes an outline drawing
-START(drawing, drawing_hash_key)
- GENERIC(unsigned, scale_x)
- GENERIC(unsigned, scale_y)
- GENERIC(int, pbo)
- FTVECTOR(outline)
- GENERIC(unsigned, border_style)
- GENERIC(int, scale)
- GENERIC(unsigned, hash)
- STRING(text)
-END(DrawingHashKey)
-
-// Cache for composited bitmaps
-START(composite, composite_hash_key)
- GENERIC(int, aw)
- GENERIC(int, ah)
- GENERIC(int, bw)
- GENERIC(int, bh)
- GENERIC(int, ax)
- GENERIC(int, ay)
- GENERIC(int, bx)
- GENERIC(int, by)
- GENERIC(int, as)
- GENERIC(int, bs)
- GENERIC(unsigned char *, a)
- GENERIC(unsigned char *, b)
-END(CompositeHashKey)
-
-
-#undef START
-#undef GENERIC
-#undef STRING
-#undef FTVECTOR
-#undef BITMAPHASHKEY
-#undef END
diff --git a/lib/libass/libass/ass_drawing.c b/lib/libass/libass/ass_drawing.c
deleted file mode 100644
index 764e6f66b0..0000000000
--- a/lib/libass/libass/ass_drawing.c
+++ /dev/null
@@ -1,462 +0,0 @@
-/*
- * Copyright (C) 2009 Grigori Goronzy <greg@geekmind.org>
- *
- * 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 <ft2build.h>
-#include FT_OUTLINE_H
-#include FT_BBOX_H
-#include <math.h>
-
-#include "ass_utils.h"
-#include "ass_drawing.h"
-
-#define CURVE_ACCURACY 64.0
-#define GLYPH_INITIAL_POINTS 100
-#define GLYPH_INITIAL_CONTOURS 5
-
-/*
- * \brief Add a single point to a contour.
- */
-static inline void drawing_add_point(ASS_Drawing *drawing,
- FT_Vector *point)
-{
- FT_Outline *ol = &drawing->outline;
-
- if (ol->n_points >= drawing->max_points) {
- drawing->max_points *= 2;
- ol->points = realloc(ol->points, sizeof(FT_Vector) *
- drawing->max_points);
- ol->tags = realloc(ol->tags, drawing->max_points);
- }
-
- ol->points[ol->n_points].x = point->x;
- ol->points[ol->n_points].y = point->y;
- ol->tags[ol->n_points] = 1;
- ol->n_points++;
-}
-
-/*
- * \brief Close a contour and check outline size overflow.
- */
-static inline void drawing_close_shape(ASS_Drawing *drawing)
-{
- FT_Outline *ol = &drawing->outline;
-
- if (ol->n_contours >= drawing->max_contours) {
- drawing->max_contours *= 2;
- ol->contours = realloc(ol->contours, sizeof(short) *
- drawing->max_contours);
- }
-
- if (ol->n_points) {
- ol->contours[ol->n_contours] = ol->n_points - 1;
- ol->n_contours++;
- }
-}
-
-/*
- * \brief Prepare drawing for parsing. This just sets a few parameters.
- */
-static void drawing_prepare(ASS_Drawing *drawing)
-{
- // Scaling parameters
- drawing->point_scale_x = drawing->scale_x *
- 64.0 / (1 << (drawing->scale - 1));
- drawing->point_scale_y = drawing->scale_y *
- 64.0 / (1 << (drawing->scale - 1));
-}
-
-/*
- * \brief Finish a drawing. This only sets the horizontal advance according
- * to the outline's bbox at the moment.
- */
-static void drawing_finish(ASS_Drawing *drawing, int raw_mode)
-{
- int i, offset;
- FT_BBox bbox = drawing->cbox;
- FT_Outline *ol = &drawing->outline;
-
- // Close the last contour
- drawing_close_shape(drawing);
-
- if (drawing->library)
- ass_msg(drawing->library, MSGL_V,
- "Parsed drawing with %d points and %d contours", ol->n_points,
- ol->n_contours);
-
- if (raw_mode)
- return;
-
- drawing->advance.x = bbox.xMax - bbox.xMin;
-
- drawing->desc = double_to_d6(-drawing->pbo * drawing->scale_y);
- drawing->asc = bbox.yMax - bbox.yMin + drawing->desc;
-
- // Place it onto the baseline
- offset = (bbox.yMax - bbox.yMin) + double_to_d6(-drawing->pbo *
- drawing->scale_y);
- for (i = 0; i < ol->n_points; i++)
- ol->points[i].y += offset;
-}
-
-/*
- * \brief Check whether a number of items on the list is available
- */
-static int token_check_values(ASS_DrawingToken *token, int i, int type)
-{
- int j;
- for (j = 0; j < i; j++) {
- if (!token || token->type != type) return 0;
- token = token->next;
- }
-
- return 1;
-}
-
-/*
- * \brief Tokenize a drawing string into a list of ASS_DrawingToken
- * This also expands points for closing b-splines
- */
-static ASS_DrawingToken *drawing_tokenize(char *str)
-{
- char *p = str;
- int i, val, type = -1, is_set = 0;
- FT_Vector point = {0, 0};
-
- ASS_DrawingToken *root = NULL, *tail = NULL, *spline_start = NULL;
-
- while (*p) {
- if (*p == 'c' && spline_start) {
- // Close b-splines: add the first three points of the b-spline
- // back to the end
- if (token_check_values(spline_start->next, 2, TOKEN_B_SPLINE)) {
- for (i = 0; i < 3; i++) {
- tail->next = calloc(1, sizeof(ASS_DrawingToken));
- tail->next->prev = tail;
- tail = tail->next;
- tail->type = TOKEN_B_SPLINE;
- tail->point = spline_start->point;
- spline_start = spline_start->next;
- }
- spline_start = NULL;
- }
- } else if (!is_set && mystrtoi(&p, &val)) {
- point.x = val;
- is_set = 1;
- p--;
- } else if (is_set == 1 && mystrtoi(&p, &val)) {
- point.y = val;
- is_set = 2;
- p--;
- } else if (*p == 'm')
- type = TOKEN_MOVE;
- else if (*p == 'n')
- type = TOKEN_MOVE_NC;
- else if (*p == 'l')
- type = TOKEN_LINE;
- else if (*p == 'b')
- type = TOKEN_CUBIC_BEZIER;
- else if (*p == 'q')
- type = TOKEN_CONIC_BEZIER;
- else if (*p == 's')
- type = TOKEN_B_SPLINE;
- // We're simply ignoring TOKEN_EXTEND_B_SPLINE here.
- // This is not harmful at all, since it can be ommitted with
- // similar result (the spline is extended anyway).
-
- if (type != -1 && is_set == 2) {
- if (root) {
- tail->next = calloc(1, sizeof(ASS_DrawingToken));
- tail->next->prev = tail;
- tail = tail->next;
- } else
- root = tail = calloc(1, sizeof(ASS_DrawingToken));
- tail->type = type;
- tail->point = point;
- is_set = 0;
- if (type == TOKEN_B_SPLINE && !spline_start)
- spline_start = tail->prev;
- }
- p++;
- }
-
- return root;
-}
-
-/*
- * \brief Free a list of tokens
- */
-static void drawing_free_tokens(ASS_DrawingToken *token)
-{
- while (token) {
- ASS_DrawingToken *at = token;
- token = token->next;
- free(at);
- }
-}
-
-/*
- * \brief Update drawing cbox
- */
-static inline void update_cbox(ASS_Drawing *drawing, FT_Vector *point)
-{
- FT_BBox *box = &drawing->cbox;
-
- box->xMin = FFMIN(box->xMin, point->x);
- box->xMax = FFMAX(box->xMax, point->x);
- box->yMin = FFMIN(box->yMin, point->y);
- box->yMax = FFMAX(box->yMax, point->y);
-}
-
-/*
- * \brief Translate and scale a point coordinate according to baseline
- * offset and scale.
- */
-static inline void translate_point(ASS_Drawing *drawing, FT_Vector *point)
-{
- point->x = drawing->point_scale_x * point->x;
- point->y = drawing->point_scale_y * -point->y;
-
- update_cbox(drawing, point);
-}
-
-/*
- * \brief Evaluate a curve into lines
- * This curve evaluator is also used in VSFilter (RTS.cpp); it's a simple
- * implementation of the De Casteljau algorithm.
- */
-static void drawing_evaluate_curve(ASS_Drawing *drawing,
- ASS_DrawingToken *token, char spline,
- int started)
-{
- double cx3, cx2, cx1, cx0, cy3, cy2, cy1, cy0;
- double t, h, max_accel, max_accel1, max_accel2;
- int x0, y0, x1, y1, x2, y2, x3, y3;
- FT_Vector cur = {0, 0};
-
- cur = token->point;
- translate_point(drawing, &cur);
- x0 = cur.x;
- y0 = cur.y;
- token = token->next;
- cur = token->point;
- translate_point(drawing, &cur);
- x1 = cur.x;
- y1 = cur.y;
- token = token->next;
- cur = token->point;
- translate_point(drawing, &cur);
- x2 = cur.x;
- y2 = cur.y;
- token = token->next;
- cur = token->point;
- translate_point(drawing, &cur);
- x3 = cur.x;
- y3 = cur.y;
-
- if (spline) {
- // 1 [-1 +3 -3 +1]
- // - * [+3 -6 +3 0]
- // 6 [-3 0 +3 0]
- // [+1 +4 +1 0]
-
- double div6 = 1.0/6.0;
-
- cx3 = div6*(- x0+3*x1-3*x2+x3);
- cx2 = div6*( 3*x0-6*x1+3*x2);
- cx1 = div6*(-3*x0 +3*x2);
- cx0 = div6*( x0+4*x1+1*x2);
-
- cy3 = div6*(- y0+3*y1-3*y2+y3);
- cy2 = div6*( 3*y0-6*y1+3*y2);
- cy1 = div6*(-3*y0 +3*y2);
- cy0 = div6*( y0+4*y1+1*y2);
- } else {
- // [-1 +3 -3 +1]
- // [+3 -6 +3 0]
- // [-3 +3 0 0]
- // [+1 0 0 0]
-
- cx3 = - x0+3*x1-3*x2+x3;
- cx2 = 3*x0-6*x1+3*x2;
- cx1 = -3*x0+3*x1;
- cx0 = x0;
-
- cy3 = - y0+3*y1-3*y2+y3;
- cy2 = 3*y0-6*y1+3*y2;
- cy1 = -3*y0+3*y1;
- cy0 = y0;
- }
-
- max_accel1 = fabs(2 * cy2) + fabs(6 * cy3);
- max_accel2 = fabs(2 * cx2) + fabs(6 * cx3);
-
- max_accel = FFMAX(max_accel1, max_accel2);
- h = 1.0;
-
- if (max_accel > CURVE_ACCURACY)
- h = sqrt(CURVE_ACCURACY / max_accel);
-
- if (!started) {
- cur.x = cx0;
- cur.y = cy0;
- drawing_add_point(drawing, &cur);
- }
-
- for (t = 0; t < 1.0; t += h) {
- cur.x = cx0 + t * (cx1 + t * (cx2 + t * cx3));
- cur.y = cy0 + t * (cy1 + t * (cy2 + t * cy3));
- drawing_add_point(drawing, &cur);
- }
-
- cur.x = cx0 + cx1 + cx2 + cx3;
- cur.y = cy0 + cy1 + cy2 + cy3;
- drawing_add_point(drawing, &cur);
-}
-
-/*
- * \brief Create and initialize a new drawing and return it
- */
-ASS_Drawing *ass_drawing_new(ASS_Library *lib, FT_Library ftlib)
-{
- ASS_Drawing *drawing;
-
- drawing = calloc(1, sizeof(*drawing));
- drawing->text = calloc(1, DRAWING_INITIAL_SIZE);
- drawing->size = DRAWING_INITIAL_SIZE;
- drawing->cbox.xMin = drawing->cbox.yMin = INT_MAX;
- drawing->cbox.xMax = drawing->cbox.yMax = INT_MIN;
- drawing->ftlibrary = ftlib;
- drawing->library = lib;
- drawing->scale_x = 1.;
- drawing->scale_y = 1.;
- drawing->max_contours = GLYPH_INITIAL_CONTOURS;
- drawing->max_points = GLYPH_INITIAL_POINTS;
-
- FT_Outline_New(drawing->ftlibrary, GLYPH_INITIAL_POINTS,
- GLYPH_INITIAL_CONTOURS, &drawing->outline);
- drawing->outline.n_contours = 0;
- drawing->outline.n_points = 0;
-
- return drawing;
-}
-
-/*
- * \brief Free a drawing
- */
-void ass_drawing_free(ASS_Drawing* drawing)
-{
- if (drawing) {
- free(drawing->text);
- FT_Outline_Done(drawing->ftlibrary, &drawing->outline);
- }
- free(drawing);
-}
-
-/*
- * \brief Add one ASCII character to the drawing text buffer
- */
-void ass_drawing_add_char(ASS_Drawing* drawing, char symbol)
-{
- drawing->text[drawing->i++] = symbol;
- drawing->text[drawing->i] = 0;
-
- if (drawing->i + 1 >= drawing->size) {
- drawing->size *= 2;
- drawing->text = realloc(drawing->text, drawing->size);
- }
-}
-
-/*
- * \brief Create a hashcode for the drawing
- * XXX: To avoid collisions a better hash algorithm might be useful.
- */
-void ass_drawing_hash(ASS_Drawing* drawing)
-{
- drawing->hash = fnv_32a_str(drawing->text, FNV1_32A_INIT);
-}
-
-/*
- * \brief Convert token list to outline. Calls the line and curve evaluators.
- */
-FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode)
-{
- int started = 0;
- ASS_DrawingToken *token;
- FT_Vector pen = {0, 0};
-
- drawing->tokens = drawing_tokenize(drawing->text);
- drawing_prepare(drawing);
-
- token = drawing->tokens;
- while (token) {
- // Draw something according to current command
- switch (token->type) {
- case TOKEN_MOVE_NC:
- pen = token->point;
- translate_point(drawing, &pen);
- token = token->next;
- break;
- case TOKEN_MOVE:
- pen = token->point;
- translate_point(drawing, &pen);
- if (started) {
- drawing_close_shape(drawing);
- started = 0;
- }
- token = token->next;
- break;
- case TOKEN_LINE: {
- FT_Vector to;
- to = token->point;
- translate_point(drawing, &to);
- if (!started) drawing_add_point(drawing, &pen);
- drawing_add_point(drawing, &to);
- started = 1;
- token = token->next;
- break;
- }
- case TOKEN_CUBIC_BEZIER:
- if (token_check_values(token, 3, TOKEN_CUBIC_BEZIER) &&
- token->prev) {
- drawing_evaluate_curve(drawing, token->prev, 0, started);
- token = token->next;
- token = token->next;
- token = token->next;
- started = 1;
- } else
- token = token->next;
- break;
- case TOKEN_B_SPLINE:
- if (token_check_values(token, 3, TOKEN_B_SPLINE) &&
- token->prev) {
- drawing_evaluate_curve(drawing, token->prev, 1, started);
- token = token->next;
- started = 1;
- } else
- token = token->next;
- break;
- default:
- token = token->next;
- break;
- }
- }
-
- drawing_finish(drawing, raw_mode);
- drawing_free_tokens(drawing->tokens);
- return &drawing->outline;
-}
diff --git a/lib/libass/libass/ass_drawing.h b/lib/libass/libass/ass_drawing.h
deleted file mode 100644
index b17d7e3bea..0000000000
--- a/lib/libass/libass/ass_drawing.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2009 Grigori Goronzy <greg@geekmind.org>
- *
- * 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.
- */
-
-#ifndef LIBASS_DRAWING_H
-#define LIBASS_DRAWING_H
-
-#include <ft2build.h>
-#include FT_OUTLINE_H
-
-#include "ass.h"
-
-#define DRAWING_INITIAL_SIZE 256
-
-typedef enum {
- TOKEN_MOVE,
- TOKEN_MOVE_NC,
- TOKEN_LINE,
- TOKEN_CUBIC_BEZIER,
- TOKEN_CONIC_BEZIER,
- TOKEN_B_SPLINE,
- TOKEN_EXTEND_SPLINE,
- TOKEN_CLOSE
-} ASS_TokenType;
-
-typedef struct ass_drawing_token {
- ASS_TokenType type;
- FT_Vector point;
- struct ass_drawing_token *next;
- struct ass_drawing_token *prev;
-} ASS_DrawingToken;
-
-typedef struct {
- char *text; // drawing string
- int i; // text index
- int scale; // scale (1-64) for subpixel accuracy
- double pbo; // drawing will be shifted in y direction by this amount
- double scale_x; // FontScaleX
- double scale_y; // FontScaleY
- int asc; // ascender
- int desc; // descender
- FT_Outline outline; // target outline
- FT_Vector advance; // advance (from cbox)
- int hash; // hash value (for caching)
-
- // private
- FT_Library ftlibrary; // needed for font ops
- ASS_Library *library;
- int size; // current buffer size
- ASS_DrawingToken *tokens; // tokenized drawing
- int max_points; // current maximum size
- int max_contours;
- double point_scale_x;
- double point_scale_y;
- FT_BBox cbox; // bounding box, or let's say... VSFilter's idea of it
-} ASS_Drawing;
-
-ASS_Drawing *ass_drawing_new(ASS_Library *lib, FT_Library ftlib);
-void ass_drawing_free(ASS_Drawing* drawing);
-void ass_drawing_add_char(ASS_Drawing* drawing, char symbol);
-void ass_drawing_hash(ASS_Drawing* drawing);
-FT_Outline *ass_drawing_parse(ASS_Drawing *drawing, int raw_mode);
-
-#endif /* LIBASS_DRAWING_H */
diff --git a/lib/libass/libass/ass_font.c b/lib/libass/libass/ass_font.c
deleted file mode 100644
index 4b6a71b6d5..0000000000
--- a/lib/libass/libass/ass_font.c
+++ /dev/null
@@ -1,776 +0,0 @@
-/*
- * 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 <inttypes.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_SYNTHESIS_H
-#include FT_GLYPH_H
-#include FT_TRUETYPE_TABLES_H
-#include FT_OUTLINE_H
-#ifndef _WIN32
-#include <strings.h>
-#endif
-
-#include "ass.h"
-#include "ass_library.h"
-#include "ass_font.h"
-#include "ass_fontconfig.h"
-#include "ass_utils.h"
-#include "ass_shaper.h"
-
-/**
- * Select a good charmap, prefer Microsoft Unicode charmaps.
- * Otherwise, let FreeType decide.
- */
-static void charmap_magic(ASS_Library *library, FT_Face face)
-{
- int i;
- int ms_cmap = -1;
-
- // Search for a Microsoft Unicode cmap
- for (i = 0; i < face->num_charmaps; ++i) {
- FT_CharMap cmap = face->charmaps[i];
- unsigned pid = cmap->platform_id;
- unsigned eid = cmap->encoding_id;
- if (pid == 3 /*microsoft */
- && (eid == 1 /*unicode bmp */
- || eid == 10 /*full unicode */ )) {
- FT_Set_Charmap(face, cmap);
- return;
- } else if (pid == 3 && ms_cmap < 0)
- ms_cmap = i;
- }
-
- // Try the first Microsoft cmap if no Microsoft Unicode cmap was found
- if (ms_cmap >= 0) {
- FT_CharMap cmap = face->charmaps[ms_cmap];
- FT_Set_Charmap(face, cmap);
- return;
- }
-
- if (!face->charmap) {
- if (face->num_charmaps == 0) {
- ass_msg(library, MSGL_WARN, "Font face with no charmaps");
- return;
- }
- ass_msg(library, MSGL_WARN,
- "No charmap autodetected, trying the first one");
- FT_Set_Charmap(face, face->charmaps[0]);
- return;
- }
-}
-
-/**
- * \brief find a memory font by name
- */
-static int find_font(ASS_Library *library, char *name)
-{
- int i;
- for (i = 0; i < library->num_fontdata; ++i)
- if (strcasecmp(name, library->fontdata[i].name) == 0)
- return i;
- return -1;
-}
-
-static void buggy_font_workaround(FT_Face face)
-{
- // Some fonts have zero Ascender/Descender fields in 'hhea' table.
- // In this case, get the information from 'os2' table or, as
- // a last resort, from face.bbox.
- if (face->ascender + face->descender == 0 || face->height == 0) {
- TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- if (os2) {
- face->ascender = os2->sTypoAscender;
- face->descender = os2->sTypoDescender;
- face->height = face->ascender - face->descender;
- } else {
- face->ascender = face->bbox.yMax;
- face->descender = face->bbox.yMin;
- face->height = face->ascender - face->descender;
- }
- }
-}
-
-/**
- * \brief Select a face with the given charcode and add it to ASS_Font
- * \return index of the new face in font->faces, -1 if failed
- */
-static int add_face(void *fc_priv, ASS_Font *font, uint32_t ch)
-{
- char *path;
- int index;
- FT_Face face;
- int error;
- int mem_idx;
-
- if (font->n_faces == ASS_FONT_MAX_FACES)
- return -1;
-
- path =
- fontconfig_select(font->library, fc_priv, font->desc.family,
- font->desc.treat_family_as_pattern,
- font->desc.bold, font->desc.italic, &index, ch);
- if (!path)
- return -1;
-
- mem_idx = find_font(font->library, path);
- if (mem_idx >= 0) {
- error =
- FT_New_Memory_Face(font->ftlibrary,
- (unsigned char *) font->library->
- fontdata[mem_idx].data,
- font->library->fontdata[mem_idx].size, index,
- &face);
- if (error) {
- ass_msg(font->library, MSGL_WARN,
- "Error opening memory font: '%s'", path);
- free(path);
- return -1;
- }
- } else {
- error = FT_New_Face(font->ftlibrary, path, index, &face);
- if (error) {
- ass_msg(font->library, MSGL_WARN,
- "Error opening font: '%s', %d", path, index);
- free(path);
- return -1;
- }
- }
- charmap_magic(font->library, face);
- buggy_font_workaround(face);
-
- font->faces[font->n_faces++] = face;
- ass_face_set_size(face, font->size);
- free(path);
- return font->n_faces - 1;
-}
-
-/**
- * \brief Create a new ASS_Font according to "desc" argument
- */
-ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
- FT_Library ftlibrary, void *fc_priv,
- ASS_FontDesc *desc)
-{
- int error;
- ASS_Font *fontp;
- ASS_Font font;
-
- fontp = ass_cache_get(font_cache, desc);
- if (fontp)
- return fontp;
-
- font.library = library;
- font.ftlibrary = ftlibrary;
- font.shaper_priv = NULL;
- font.n_faces = 0;
- font.desc.family = strdup(desc->family);
- font.desc.treat_family_as_pattern = desc->treat_family_as_pattern;
- font.desc.bold = desc->bold;
- font.desc.italic = desc->italic;
- font.desc.vertical = desc->vertical;
-
- font.scale_x = font.scale_y = 1.;
- font.v.x = font.v.y = 0;
- font.size = 0.;
-
- error = add_face(fc_priv, &font, 0);
- if (error == -1) {
- free(font.desc.family);
- return 0;
- } else
- return ass_cache_put(font_cache, &font.desc, &font);
-}
-
-/**
- * \brief Set font transformation matrix and shift vector
- **/
-void ass_font_set_transform(ASS_Font *font, double scale_x,
- double scale_y, FT_Vector *v)
-{
- font->scale_x = scale_x;
- font->scale_y = scale_y;
- if (v) {
- font->v.x = v->x;
- font->v.y = v->y;
- }
-}
-
-void ass_face_set_size(FT_Face face, double size)
-{
- TT_HoriHeader *hori = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);
- TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- double mscale = 1.;
- FT_Size_RequestRec rq;
- FT_Size_Metrics *m = &face->size->metrics;
- // VSFilter uses metrics from TrueType OS/2 table
- // The idea was borrowed from asa (http://asa.diac24.net)
- if (hori && os2) {
- int hori_height = hori->Ascender - hori->Descender;
- int os2_height = os2->usWinAscent + os2->usWinDescent;
- if (hori_height && os2_height)
- mscale = (double) hori_height / os2_height;
- }
- memset(&rq, 0, sizeof(rq));
- rq.type = FT_SIZE_REQUEST_TYPE_REAL_DIM;
- rq.width = 0;
- rq.height = double_to_d6(size * mscale);
- rq.horiResolution = rq.vertResolution = 0;
- FT_Request_Size(face, &rq);
- m->ascender /= mscale;
- m->descender /= mscale;
- m->height /= mscale;
-}
-
-/**
- * \brief Set font size
- **/
-void ass_font_set_size(ASS_Font *font, double size)
-{
- int i;
- if (font->size != size) {
- font->size = size;
- for (i = 0; i < font->n_faces; ++i)
- ass_face_set_size(font->faces[i], size);
- }
-}
-
-/**
- * \brief Get maximal font ascender and descender.
- * \param ch character code
- * The values are extracted from the font face that provides glyphs for the given character
- **/
-void ass_font_get_asc_desc(ASS_Font *font, uint32_t ch, int *asc,
- int *desc)
-{
- int i;
- for (i = 0; i < font->n_faces; ++i) {
- FT_Face face = font->faces[i];
- TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- if (FT_Get_Char_Index(face, ch)) {
- int y_scale = face->size->metrics.y_scale;
- if (os2) {
- *asc = FT_MulFix(os2->usWinAscent, y_scale);
- *desc = FT_MulFix(os2->usWinDescent, y_scale);
- } else {
- *asc = FT_MulFix(face->ascender, y_scale);
- *desc = FT_MulFix(-face->descender, y_scale);
- }
- return;
- }
- }
-
- *asc = *desc = 0;
-}
-
-/*
- * Strike a glyph with a horizontal line; it's possible to underline it
- * and/or strike through it. For the line's position and size, truetype
- * tables are consulted. Obviously this relies on the data in the tables
- * being accurate.
- *
- */
-static int ass_strike_outline_glyph(FT_Face face, ASS_Font *font,
- FT_Glyph glyph, int under, int through)
-{
- TT_OS2 *os2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- TT_Postscript *ps = FT_Get_Sfnt_Table(face, ft_sfnt_post);
- FT_Outline *ol = &((FT_OutlineGlyph) glyph)->outline;
- FT_Vector points[4];
- int bear, advance, y_scale, i, dir;
-
- if (!under && !through)
- return 0;
-
- // Grow outline
- i = (under ? 4 : 0) + (through ? 4 : 0);
- ol->points = (FT_Vector *) realloc(ol->points, sizeof(FT_Vector) *
- (ol->n_points + i));
- ol->tags = (char *) realloc(ol->tags, ol->n_points + i);
- i = !!under + !!through;
- ol->contours = (short *) realloc(ol->contours, sizeof(short) *
- (ol->n_contours + i));
-
- // If the bearing is negative, the glyph starts left of the current
- // pen position
- bear = FFMIN(face->glyph->metrics.horiBearingX, 0);
- // We're adding half a pixel to avoid small gaps
- advance = d16_to_d6(glyph->advance.x) + 32;
- y_scale = face->size->metrics.y_scale;
-
- // Reverse drawing direction for non-truetype fonts
- dir = FT_Outline_Get_Orientation(ol);
-
- // Add points to the outline
- if (under && ps) {
- int pos, size;
- pos = FT_MulFix(ps->underlinePosition, y_scale * font->scale_y);
- size = FT_MulFix(ps->underlineThickness,
- y_scale * font->scale_y / 2);
-
- if (pos > 0 || size <= 0)
- return 1;
-
- points[0].x = bear;
- points[0].y = pos + size;
- points[1].x = advance;
- points[1].y = pos + size;
- points[2].x = advance;
- points[2].y = pos - size;
- points[3].x = bear;
- points[3].y = pos - size;
-
- if (dir == FT_ORIENTATION_TRUETYPE) {
- for (i = 0; i < 4; i++) {
- ol->points[ol->n_points] = points[i];
- ol->tags[ol->n_points++] = 1;
- }
- } else {
- for (i = 3; i >= 0; i--) {
- ol->points[ol->n_points] = points[i];
- ol->tags[ol->n_points++] = 1;
- }
- }
-
- ol->contours[ol->n_contours++] = ol->n_points - 1;
- }
-
- if (through && os2) {
- int pos, size;
- pos = FT_MulFix(os2->yStrikeoutPosition, y_scale * font->scale_y);
- size = FT_MulFix(os2->yStrikeoutSize, y_scale * font->scale_y / 2);
-
- if (pos < 0 || size <= 0)
- return 1;
-
- points[0].x = bear;
- points[0].y = pos + size;
- points[1].x = advance;
- points[1].y = pos + size;
- points[2].x = advance;
- points[2].y = pos - size;
- points[3].x = bear;
- points[3].y = pos - size;
-
- if (dir == FT_ORIENTATION_TRUETYPE) {
- for (i = 0; i < 4; i++) {
- ol->points[ol->n_points] = points[i];
- ol->tags[ol->n_points++] = 1;
- }
- } else {
- for (i = 3; i >= 0; i--) {
- ol->points[ol->n_points] = points[i];
- ol->tags[ol->n_points++] = 1;
- }
- }
-
- ol->contours[ol->n_contours++] = ol->n_points - 1;
- }
-
- return 0;
-}
-
-void outline_copy(FT_Library lib, FT_Outline *source, FT_Outline **dest)
-{
- if (source == NULL) {
- *dest = NULL;
- return;
- }
- *dest = calloc(1, sizeof(**dest));
-
- FT_Outline_New(lib, source->n_points, source->n_contours, *dest);
- FT_Outline_Copy(source, *dest);
-}
-
-void outline_free(FT_Library lib, FT_Outline *outline)
-{
- if (outline)
- FT_Outline_Done(lib, outline);
- free(outline);
-}
-
-/**
- * Slightly embold a glyph without touching its metrics
- */
-static void ass_glyph_embolden(FT_GlyphSlot slot)
-{
- int str;
-
- if (slot->format != FT_GLYPH_FORMAT_OUTLINE)
- return;
-
- str = FT_MulFix(slot->face->units_per_EM,
- slot->face->size->metrics.y_scale) / 64;
-
- FT_Outline_Embolden(&slot->outline, str);
-}
-
-/**
- * \brief Get glyph and face index
- * Finds a face that has the requested codepoint and returns both face
- * and glyph index.
- */
-int ass_font_get_index(void *fcpriv, ASS_Font *font, uint32_t symbol,
- int *face_index, int *glyph_index)
-{
- int index = 0;
- int i;
- FT_Face face = 0;
-
- *glyph_index = 0;
-
- if (symbol < 0x20) {
- *face_index = 0;
- return 0;
- }
- // Handle NBSP like a regular space when rendering the glyph
- if (symbol == 0xa0)
- symbol = ' ';
- if (font->n_faces == 0) {
- *face_index = 0;
- return 0;
- }
-
- // try with the requested face
- if (*face_index < font->n_faces) {
- face = font->faces[*face_index];
- index = FT_Get_Char_Index(face, symbol);
- }
-
- // not found in requested face, try all others
- for (i = 0; i < font->n_faces && index == 0; ++i) {
- face = font->faces[i];
- index = FT_Get_Char_Index(face, symbol);
- if (index)
- *face_index = i;
- }
-
-#ifdef CONFIG_FONTCONFIG
- if (index == 0) {
- int face_idx;
- ass_msg(font->library, MSGL_INFO,
- "Glyph 0x%X not found, selecting one more "
- "font for (%s, %d, %d)", symbol, font->desc.family,
- font->desc.bold, font->desc.italic);
- face_idx = *face_index = add_face(fcpriv, font, symbol);
- if (face_idx >= 0) {
- face = font->faces[face_idx];
- index = FT_Get_Char_Index(face, symbol);
- if (index == 0 && face->num_charmaps > 0) {
- int i;
- ass_msg(font->library, MSGL_WARN,
- "Glyph 0x%X not found, broken font? Trying all charmaps", symbol);
- for (i = 0; i < face->num_charmaps; i++) {
- FT_Set_Charmap(face, face->charmaps[i]);
- if ((index = FT_Get_Char_Index(face, symbol)) != 0) break;
- }
- }
- if (index == 0) {
- ass_msg(font->library, MSGL_ERR,
- "Glyph 0x%X not found in font for (%s, %d, %d)",
- symbol, font->desc.family, font->desc.bold,
- font->desc.italic);
- }
- }
- }
-#endif
- // FIXME: make sure we have a valid face_index. this is a HACK.
- *face_index = FFMAX(*face_index, 0);
- *glyph_index = index;
-
- return 1;
-}
-
-/**
- * \brief Get a glyph
- * \param ch character code
- **/
-FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ASS_Font *font,
- uint32_t ch, int face_index, int index,
- ASS_Hinting hinting, int deco)
-{
- int error;
- FT_Glyph glyph;
- FT_Matrix scale;
- FT_Outline *outl = NULL;
- FT_Face face = font->faces[face_index];
- int flags = 0;
- int vertical = font->desc.vertical;
-
- flags = FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
- | FT_LOAD_IGNORE_TRANSFORM;
- switch (hinting) {
- case ASS_HINTING_NONE:
- flags |= FT_LOAD_NO_HINTING;
- break;
- case ASS_HINTING_LIGHT:
- flags |= FT_LOAD_FORCE_AUTOHINT | FT_LOAD_TARGET_LIGHT;
- break;
- case ASS_HINTING_NORMAL:
- flags |= FT_LOAD_FORCE_AUTOHINT;
- break;
- case ASS_HINTING_NATIVE:
- break;
- }
-
- error = FT_Load_Glyph(face, index, flags);
- if (error) {
- ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d",
- index);
- return 0;
- }
- if (!(face->style_flags & FT_STYLE_FLAG_ITALIC) &&
- (font->desc.italic > 55)) {
- FT_GlyphSlot_Oblique(face->glyph);
- }
-
- if (!(face->style_flags & FT_STYLE_FLAG_BOLD) &&
- (font->desc.bold > 80)) {
- ass_glyph_embolden(face->glyph);
- }
- error = FT_Get_Glyph(face->glyph, &glyph);
- if (error) {
- ass_msg(font->library, MSGL_WARN, "Error loading glyph, index %d",
- index);
- return 0;
- }
-
- // Rotate glyph, if needed
- if (vertical && ch >= VERTICAL_LOWER_BOUND) {
- FT_Matrix m = { 0, double_to_d16(-1.0), double_to_d16(1.0), 0 };
- TT_OS2 *os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
- int desc = 0;
-
- if (os2)
- desc = FT_MulFix(os2->sTypoDescender, face->size->metrics.y_scale);
-
- FT_Outline_Translate(&((FT_OutlineGlyph) glyph)->outline, 0, -desc);
- FT_Outline_Transform(&((FT_OutlineGlyph) glyph)->outline, &m);
- FT_Outline_Translate(&((FT_OutlineGlyph) glyph)->outline,
- face->glyph->metrics.vertAdvance, desc);
- glyph->advance.x = face->glyph->linearVertAdvance;
- }
-
- // Apply scaling and shift
- scale.xx = double_to_d16(font->scale_x);
- scale.xy = 0;
- scale.yx = 0;
- scale.yy = double_to_d16(font->scale_y);
-
- outl = &((FT_OutlineGlyph) glyph)->outline;
- FT_Outline_Transform(outl, &scale);
- FT_Outline_Translate(outl, font->v.x, font->v.y);
- glyph->advance.x *= font->scale_x;
-
- ass_strike_outline_glyph(face, font, glyph, deco & DECO_UNDERLINE,
- deco & DECO_STRIKETHROUGH);
-
- return glyph;
-}
-
-/**
- * \brief Get kerning for the pair of glyphs.
- **/
-FT_Vector ass_font_get_kerning(ASS_Font *font, uint32_t c1, uint32_t c2)
-{
- FT_Vector v = { 0, 0 };
- int i;
-
- if (font->desc.vertical)
- return v;
-
- for (i = 0; i < font->n_faces; ++i) {
- FT_Face face = font->faces[i];
- int i1 = FT_Get_Char_Index(face, c1);
- int i2 = FT_Get_Char_Index(face, c2);
- if (i1 && i2) {
- if (FT_HAS_KERNING(face))
- FT_Get_Kerning(face, i1, i2, FT_KERNING_DEFAULT, &v);
- return v;
- }
- if (i1 || i2) // these glyphs are from different font faces, no kerning information
- return v;
- }
- return v;
-}
-
-/**
- * \brief Deallocate ASS_Font
- **/
-void ass_font_free(ASS_Font *font)
-{
- int i;
- for (i = 0; i < font->n_faces; ++i)
- if (font->faces[i])
- FT_Done_Face(font->faces[i]);
- if (font->shaper_priv)
- ass_shaper_font_data_free(font->shaper_priv);
- free(font->desc.family);
- free(font);
-}
-
-/**
- * \brief Calculate the cbox of a series of points
- */
-static void
-get_contour_cbox(FT_BBox *box, FT_Vector *points, int start, int end)
-{
- int i;
- box->xMin = box->yMin = INT_MAX;
- box->xMax = box->yMax = INT_MIN;
-
- for (i = start; i <= end; i++) {
- box->xMin = (points[i].x < box->xMin) ? points[i].x : box->xMin;
- box->xMax = (points[i].x > box->xMax) ? points[i].x : box->xMax;
- box->yMin = (points[i].y < box->yMin) ? points[i].y : box->yMin;
- box->yMax = (points[i].y > box->yMax) ? points[i].y : box->yMax;
- }
-}
-
-/**
- * \brief Determine winding direction of a contour
- * \return direction; 0 = clockwise
- */
-static int get_contour_direction(FT_Vector *points, int start, int end)
-{
- int i;
- long long sum = 0;
- int x = points[start].x;
- int y = points[start].y;
- for (i = start + 1; i <= end; i++) {
- sum += x * (points[i].y - y) - y * (points[i].x - x);
- x = points[i].x;
- y = points[i].y;
- }
- sum += x * (points[start].y - y) - y * (points[start].x - x);
- return sum > 0;
-}
-
-/**
- * \brief Apply fixups to please the FreeType stroker and improve the
- * rendering result, especially in case the outline has some anomalies.
- * At the moment, the following fixes are done:
- *
- * 1. Reverse contours that have "inside" winding direction but are not
- * contained in any other contours' cbox.
- * 2. Remove "inside" contours depending on border size, so that large
- * borders do not reverse the winding direction, which leads to "holes"
- * inside the border. The inside will be filled by the border of the
- * outside contour anyway in this case.
- *
- * \param outline FreeType outline, modified in-place
- * \param border_x border size, x direction, d6 format
- * \param border_x border size, y direction, d6 format
- */
-void fix_freetype_stroker(FT_Outline *outline, int border_x, int border_y)
-{
- int nc = outline->n_contours;
- int begin, stop;
- char modified = 0;
- char *valid_cont = malloc(nc);
- int start = 0;
- int end = -1;
- FT_BBox *boxes = malloc(nc * sizeof(FT_BBox));
- int i, j;
- int inside_direction;
-
- inside_direction = FT_Outline_Get_Orientation(outline) ==
- FT_ORIENTATION_TRUETYPE;
-
- // create a list of cboxes of the contours
- for (i = 0; i < nc; i++) {
- start = end + 1;
- end = outline->contours[i];
- get_contour_cbox(&boxes[i], outline->points, start, end);
- }
-
- // for each contour, check direction and whether it's "outside"
- // or contained in another contour
- end = -1;
- for (i = 0; i < nc; i++) {
- int dir;
- start = end + 1;
- end = outline->contours[i];
- dir = get_contour_direction(outline->points, start, end);
- valid_cont[i] = 1;
- if (dir == inside_direction) {
- for (j = 0; j < nc; j++) {
- if (i == j)
- continue;
- if (boxes[i].xMin >= boxes[j].xMin &&
- boxes[i].xMax <= boxes[j].xMax &&
- boxes[i].yMin >= boxes[j].yMin &&
- boxes[i].yMax <= boxes[j].yMax)
- goto check_inside;
- }
- /* "inside" contour but we can't find anything it could be
- * inside of - assume the font is buggy and it should be
- * an "outside" contour, and reverse it */
- for (j = 0; j < (end + 1 - start) / 2; j++) {
- FT_Vector temp = outline->points[start + j];
- char temp2 = outline->tags[start + j];
- outline->points[start + j] = outline->points[end - j];
- outline->points[end - j] = temp;
- outline->tags[start + j] = outline->tags[end - j];
- outline->tags[end - j] = temp2;
- }
- dir ^= 1;
- }
- check_inside:
- if (dir == inside_direction) {
- FT_BBox box;
- int width, height;
- get_contour_cbox(&box, outline->points, start, end);
- width = box.xMax - box.xMin;
- height = box.yMax - box.yMin;
- if (width < border_x * 2 || height < border_y * 2) {
- valid_cont[i] = 0;
- modified = 1;
- }
- }
- }
-
- // if we need to modify the outline, rewrite it and skip
- // the contours that we determined should be removed.
- if (modified) {
- int p = 0, c = 0;
- for (i = 0; i < nc; i++) {
- if (!valid_cont[i])
- continue;
- begin = (i == 0) ? 0 : outline->contours[i - 1] + 1;
- stop = outline->contours[i];
- for (j = begin; j <= stop; j++) {
- outline->points[p].x = outline->points[j].x;
- outline->points[p].y = outline->points[j].y;
- outline->tags[p] = outline->tags[j];
- p++;
- }
- outline->contours[c] = p - 1;
- c++;
- }
- outline->n_points = p;
- outline->n_contours = c;
- }
-
- free(boxes);
- free(valid_cont);
-}
-
diff --git a/lib/libass/libass/ass_font.h b/lib/libass/libass/ass_font.h
deleted file mode 100644
index 481a63015f..0000000000
--- a/lib/libass/libass/ass_font.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LIBASS_FONT_H
-#define LIBASS_FONT_H
-
-#include <stdint.h>
-#include <ft2build.h>
-#include FT_GLYPH_H
-#include FT_OUTLINE_H
-
-#include "ass.h"
-#include "ass_types.h"
-
-#define VERTICAL_LOWER_BOUND 0x02f1
-
-#define ASS_FONT_MAX_FACES 10
-#define DECO_UNDERLINE 1
-#define DECO_STRIKETHROUGH 2
-
-typedef struct ass_shaper_font_data ASS_ShaperFontData;
-
-typedef struct {
- char *family;
- unsigned bold;
- unsigned italic;
- int treat_family_as_pattern;
- int vertical; // @font vertical layout
-} ASS_FontDesc;
-
-typedef struct {
- ASS_FontDesc desc;
- ASS_Library *library;
- FT_Library ftlibrary;
- FT_Face faces[ASS_FONT_MAX_FACES];
- ASS_ShaperFontData *shaper_priv;
- int n_faces;
- double scale_x, scale_y; // current transform
- FT_Vector v; // current shift
- double size;
-} ASS_Font;
-
-#include "ass_cache.h"
-
-ASS_Font *ass_font_new(Cache *font_cache, ASS_Library *library,
- FT_Library ftlibrary, void *fc_priv,
- ASS_FontDesc *desc);
-void ass_font_set_transform(ASS_Font *font, double scale_x,
- double scale_y, FT_Vector *v);
-void ass_face_set_size(FT_Face face, double size);
-void ass_font_set_size(ASS_Font *font, double size);
-void ass_font_get_asc_desc(ASS_Font *font, uint32_t ch, int *asc,
- int *desc);
-int ass_font_get_index(void *fcpriv, ASS_Font *font, uint32_t symbol,
- int *face_index, int *glyph_index);
-FT_Glyph ass_font_get_glyph(void *fontconfig_priv, ASS_Font *font,
- uint32_t ch, int face_index, int index,
- ASS_Hinting hinting, int deco);
-FT_Vector ass_font_get_kerning(ASS_Font *font, uint32_t c1, uint32_t c2);
-void ass_font_free(ASS_Font *font);
-void fix_freetype_stroker(FT_Outline *outline, int border_x, int border_y);
-void outline_copy(FT_Library lib, FT_Outline *source, FT_Outline **dest);
-void outline_free(FT_Library lib, FT_Outline *outline);
-
-#endif /* LIBASS_FONT_H */
diff --git a/lib/libass/libass/ass_fontconfig.c b/lib/libass/libass/ass_fontconfig.c
deleted file mode 100644
index 76ca045940..0000000000
--- a/lib/libass/libass/ass_fontconfig.c
+++ /dev/null
@@ -1,534 +0,0 @@
-/*
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#ifndef _WIN32
-#include <strings.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <inttypes.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#include "ass_utils.h"
-#include "ass.h"
-#include "ass_library.h"
-#include "ass_fontconfig.h"
-
-#ifdef CONFIG_FONTCONFIG
-#include <fontconfig/fontconfig.h>
-#include <fontconfig/fcfreetype.h>
-#endif
-
-struct fc_instance {
-#ifdef CONFIG_FONTCONFIG
- FcConfig *config;
-#endif
- char *family_default;
- char *path_default;
- int index_default;
-};
-
-#ifdef CONFIG_FONTCONFIG
-
-/**
- * \brief Case-insensitive match ASS/SSA font family against full name. (also
- * known as "name for humans")
- *
- * \param lib library instance
- * \param priv fontconfig instance
- * \param family font fullname
- * \param bold weight attribute
- * \param italic italic attribute
- * \return font set
- */
-static FcFontSet *
-match_fullname(ASS_Library *lib, FCInstance *priv, const char *family,
- unsigned bold, unsigned italic)
-{
- FcFontSet *sets[2];
- FcFontSet *result = FcFontSetCreate();
- int nsets = 0;
- int i, fi;
-
- if ((sets[nsets] = FcConfigGetFonts(priv->config, FcSetSystem)))
- nsets++;
- if ((sets[nsets] = FcConfigGetFonts(priv->config, FcSetApplication)))
- nsets++;
-
- // Run over font sets and patterns and try to match against full name
- for (i = 0; i < nsets; i++) {
- FcFontSet *set = sets[i];
- for (fi = 0; fi < set->nfont; fi++) {
- FcPattern *pat = set->fonts[fi];
- char *fullname;
- int pi = 0, at;
- FcBool ol;
- while (FcPatternGetString(pat, FC_FULLNAME, pi++,
- (FcChar8 **) &fullname) == FcResultMatch) {
- if (FcPatternGetBool(pat, FC_OUTLINE, 0, &ol) != FcResultMatch
- || ol != FcTrue)
- continue;
- if (FcPatternGetInteger(pat, FC_SLANT, 0, &at) != FcResultMatch
- || at < italic)
- continue;
- if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &at) != FcResultMatch
- || at < bold)
- continue;
- if (strcasecmp(fullname, family) == 0) {
- FcFontSetAdd(result, FcPatternDuplicate(pat));
- break;
- }
- }
- }
- }
-
- return result;
-}
-
-/**
- * \brief Low-level font selection.
- * \param priv private data
- * \param family font family
- * \param treat_family_as_pattern treat family as fontconfig pattern
- * \param bold font weight value
- * \param italic font slant value
- * \param index out: font index inside a file
- * \param code: the character that should be present in the font, can be 0
- * \return font file path
-*/
-static char *select_font(ASS_Library *library, FCInstance *priv,
- const char *family, int treat_family_as_pattern,
- unsigned bold, unsigned italic, int *index,
- uint32_t code)
-{
- FcBool rc;
- FcResult result;
- FcPattern *pat = NULL, *rpat = NULL;
- int r_index, r_slant, r_weight;
- FcChar8 *r_family, *r_style, *r_file, *r_fullname;
- FcBool r_outline, r_embolden;
- FcCharSet *r_charset;
- FcFontSet *ffullname = NULL, *fsorted = NULL, *fset = NULL;
- int curf;
- char *retval = NULL;
- int family_cnt = 0;
-
- *index = 0;
-
- if (treat_family_as_pattern)
- pat = FcNameParse((const FcChar8 *) family);
- else
- pat = FcPatternCreate();
-
- if (!pat)
- goto error;
-
- if (!treat_family_as_pattern) {
- FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) family);
-
- // In SSA/ASS fonts are sometimes referenced by their "full name",
- // which is usually a concatenation of family name and font
- // style (ex. Ottawa Bold). Full name is available from
- // FontConfig pattern element FC_FULLNAME, but it is never
- // used for font matching.
- // Therefore, I'm removing words from the end of the name one
- // by one, and adding shortened names to the pattern. It seems
- // that the first value (full name in this case) has
- // precedence in matching.
- // An alternative approach could be to reimplement FcFontSort
- // using FC_FULLNAME instead of FC_FAMILY.
- family_cnt = 1;
- {
- char *s = strdup(family);
- char *p = s + strlen(s);
- while (--p > s)
- if (*p == ' ' || *p == '-') {
- *p = '\0';
- FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) s);
- ++family_cnt;
- }
- free(s);
- }
- }
- FcPatternAddBool(pat, FC_OUTLINE, FcTrue);
- FcPatternAddInteger(pat, FC_SLANT, italic);
- FcPatternAddInteger(pat, FC_WEIGHT, bold);
-
- FcDefaultSubstitute(pat);
-
- rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern);
- if (!rc)
- goto error;
-
- fsorted = FcFontSort(priv->config, pat, FcTrue, NULL, &result);
- ffullname = match_fullname(library, priv, family, bold, italic);
- if (!fsorted || !ffullname)
- goto error;
-
- fset = FcFontSetCreate();
- for (curf = 0; curf < ffullname->nfont; ++curf) {
- FcPattern *curp = ffullname->fonts[curf];
- FcPatternReference(curp);
- FcFontSetAdd(fset, curp);
- }
- for (curf = 0; curf < fsorted->nfont; ++curf) {
- FcPattern *curp = fsorted->fonts[curf];
- FcPatternReference(curp);
- FcFontSetAdd(fset, curp);
- }
-
- for (curf = 0; curf < fset->nfont; ++curf) {
- FcPattern *curp = fset->fonts[curf];
-
- result = FcPatternGetBool(curp, FC_OUTLINE, 0, &r_outline);
- if (result != FcResultMatch)
- continue;
- if (r_outline != FcTrue)
- continue;
- if (!code)
- break;
- result = FcPatternGetCharSet(curp, FC_CHARSET, 0, &r_charset);
- if (result != FcResultMatch)
- continue;
- if (FcCharSetHasChar(r_charset, code))
- break;
- }
-
- if (curf >= fset->nfont)
- goto error;
-
- if (!treat_family_as_pattern) {
- // Remove all extra family names from original pattern.
- // After this, FcFontRenderPrepare will select the most relevant family
- // name in case there are more than one of them.
- for (; family_cnt > 1; --family_cnt)
- FcPatternRemove(pat, FC_FAMILY, family_cnt - 1);
- }
-
- rpat = FcFontRenderPrepare(priv->config, pat, fset->fonts[curf]);
- if (!rpat)
- goto error;
-
- result = FcPatternGetInteger(rpat, FC_INDEX, 0, &r_index);
- if (result != FcResultMatch)
- goto error;
- *index = r_index;
-
- result = FcPatternGetString(rpat, FC_FILE, 0, &r_file);
- if (result != FcResultMatch)
- goto error;
- retval = strdup((const char *) r_file);
-
- result = FcPatternGetString(rpat, FC_FAMILY, 0, &r_family);
- if (result != FcResultMatch)
- r_family = NULL;
-
- result = FcPatternGetString(rpat, FC_FULLNAME, 0, &r_fullname);
- if (result != FcResultMatch)
- r_fullname = NULL;
-
- if (!treat_family_as_pattern &&
- !(r_family && strcasecmp((const char *) r_family, family) == 0) &&
- !(r_fullname && strcasecmp((const char *) r_fullname, family) == 0))
- ass_msg(library, MSGL_WARN,
- "fontconfig: Selected font is not the requested one: "
- "'%s' != '%s'",
- (const char *) (r_fullname ? r_fullname : r_family), family);
-
- result = FcPatternGetString(rpat, FC_STYLE, 0, &r_style);
- if (result != FcResultMatch)
- r_style = NULL;
-
- result = FcPatternGetInteger(rpat, FC_SLANT, 0, &r_slant);
- if (result != FcResultMatch)
- r_slant = 0;
-
- result = FcPatternGetInteger(rpat, FC_WEIGHT, 0, &r_weight);
- if (result != FcResultMatch)
- r_weight = 0;
-
- result = FcPatternGetBool(rpat, FC_EMBOLDEN, 0, &r_embolden);
- if (result != FcResultMatch)
- r_embolden = 0;
-
- ass_msg(library, MSGL_V,
- "Font info: family '%s', style '%s', fullname '%s',"
- " slant %d, weight %d%s", (const char *) r_family,
- (const char *) r_style, (const char *) r_fullname, r_slant,
- r_weight, r_embolden ? ", embolden" : "");
-
- error:
- if (pat)
- FcPatternDestroy(pat);
- if (rpat)
- FcPatternDestroy(rpat);
- if (fsorted)
- FcFontSetDestroy(fsorted);
- if (ffullname)
- FcFontSetDestroy(ffullname);
- if (fset)
- FcFontSetDestroy(fset);
- return retval;
-}
-
-/**
- * \brief Find a font. Use default family or path if necessary.
- * \param priv_ private data
- * \param family font family
- * \param treat_family_as_pattern treat family as fontconfig pattern
- * \param bold font weight value
- * \param italic font slant value
- * \param index out: font index inside a file
- * \param code: the character that should be present in the font, can be 0
- * \return font file path
-*/
-char *fontconfig_select(ASS_Library *library, FCInstance *priv,
- const char *family, int treat_family_as_pattern,
- unsigned bold, unsigned italic, int *index,
- uint32_t code)
-{
- char *res = 0;
- if (!priv->config) {
- *index = priv->index_default;
- res = priv->path_default ? strdup(priv->path_default) : 0;
- return res;
- }
- if (family && *family)
- res =
- select_font(library, priv, family, treat_family_as_pattern,
- bold, italic, index, code);
- if (!res && priv->family_default) {
- res =
- select_font(library, priv, priv->family_default, 0, bold,
- italic, index, code);
- if (res)
- ass_msg(library, MSGL_WARN, "fontconfig_select: Using default "
- "font family: (%s, %d, %d) -> %s, %d",
- family, bold, italic, res, *index);
- }
- if (!res && priv->path_default) {
- res = strdup(priv->path_default);
- *index = priv->index_default;
- ass_msg(library, MSGL_WARN, "fontconfig_select: Using default font: "
- "(%s, %d, %d) -> %s, %d", family, bold, italic,
- res, *index);
- }
- if (!res) {
- res = select_font(library, priv, "Arial", 0, bold, italic,
- index, code);
- if (res)
- ass_msg(library, MSGL_WARN, "fontconfig_select: Using 'Arial' "
- "font family: (%s, %d, %d) -> %s, %d", family, bold,
- italic, res, *index);
- }
- if (res)
- ass_msg(library, MSGL_V,
- "fontconfig_select: (%s, %d, %d) -> %s, %d", family, bold,
- italic, res, *index);
- return res;
-}
-
-/**
- * \brief Process memory font.
- * \param priv private data
- * \param library library object
- * \param ftlibrary freetype library object
- * \param idx index of the processed font in library->fontdata
- *
- * Builds a font pattern in memory via FT_New_Memory_Face/FcFreeTypeQueryFace.
-*/
-static void process_fontdata(FCInstance *priv, ASS_Library *library,
- FT_Library ftlibrary, int idx)
-{
- int rc;
- const char *name = library->fontdata[idx].name;
- const char *data = library->fontdata[idx].data;
- int data_size = library->fontdata[idx].size;
-
- FT_Face face;
- FcPattern *pattern;
- FcFontSet *fset;
- FcBool res;
- int face_index, num_faces = 1;
-
- for (face_index = 0; face_index < num_faces; ++face_index) {
- rc = FT_New_Memory_Face(ftlibrary, (unsigned char *) data,
- data_size, face_index, &face);
- if (rc) {
- ass_msg(library, MSGL_WARN, "Error opening memory font: %s",
- name);
- return;
- }
- num_faces = face->num_faces;
-
- pattern =
- FcFreeTypeQueryFace(face, (unsigned char *) name, face_index,
- FcConfigGetBlanks(priv->config));
- if (!pattern) {
- ass_msg(library, MSGL_WARN, "%s failed", "FcFreeTypeQueryFace");
- FT_Done_Face(face);
- return;
- }
-
- fset = FcConfigGetFonts(priv->config, FcSetSystem); // somehow it failes when asked for FcSetApplication
- if (!fset) {
- ass_msg(library, MSGL_WARN, "%s failed", "FcConfigGetFonts");
- FT_Done_Face(face);
- return;
- }
-
- res = FcFontSetAdd(fset, pattern);
- if (!res) {
- ass_msg(library, MSGL_WARN, "%s failed", "FcFontSetAdd");
- FT_Done_Face(face);
- return;
- }
-
- FT_Done_Face(face);
- }
-}
-
-/**
- * \brief Init fontconfig.
- * \param library libass library object
- * \param ftlibrary freetype library object
- * \param family default font family
- * \param path default font path
- * \param fc whether fontconfig should be used
- * \param config path to a fontconfig configuration file, or NULL
- * \param update whether the fontconfig cache should be built/updated
- * \return pointer to fontconfig private data
-*/
-FCInstance *fontconfig_init(ASS_Library *library,
- FT_Library ftlibrary, const char *family,
- const char *path, int fc, const char *config,
- int update)
-{
- int rc;
- FCInstance *priv = calloc(1, sizeof(FCInstance));
- const char *dir = library->fonts_dir;
- int i;
-
- if (!fc) {
- ass_msg(library, MSGL_WARN,
- "Fontconfig disabled, only default font will be used.");
- goto exit;
- }
-
- priv->config = FcConfigCreate();
- rc = FcConfigParseAndLoad(priv->config, (unsigned char *) config, FcTrue);
- if (!rc) {
- ass_msg(library, MSGL_WARN, "No usable fontconfig configuration "
- "file found, using fallback.");
- FcConfigDestroy(priv->config);
- priv->config = FcInitLoadConfig();
- rc++;
- }
- if (rc && update) {
- FcConfigBuildFonts(priv->config);
- }
-
- if (!rc || !priv->config) {
- ass_msg(library, MSGL_FATAL,
- "No valid fontconfig configuration found!");
- FcConfigDestroy(priv->config);
- goto exit;
- }
-
- for (i = 0; i < library->num_fontdata; ++i)
- process_fontdata(priv, library, ftlibrary, i);
-
- if (dir) {
- ass_msg(library, MSGL_V, "Updating font cache");
-
- rc = FcConfigAppFontAddDir(priv->config, (const FcChar8 *) dir);
- if (!rc) {
- ass_msg(library, MSGL_WARN, "%s failed", "FcConfigAppFontAddDir");
- }
- }
-
- priv->family_default = family ? strdup(family) : NULL;
-exit:
- priv->path_default = path ? strdup(path) : NULL;
- priv->index_default = 0;
-
- return priv;
-}
-
-int fontconfig_update(FCInstance *priv)
-{
- return FcConfigBuildFonts(priv->config);
-}
-
-#else /* CONFIG_FONTCONFIG */
-
-char *fontconfig_select(ASS_Library *library, FCInstance *priv,
- const char *family, int treat_family_as_pattern,
- unsigned bold, unsigned italic, int *index,
- uint32_t code)
-{
- *index = priv->index_default;
- char* res = priv->path_default ? strdup(priv->path_default) : 0;
- return res;
-}
-
-FCInstance *fontconfig_init(ASS_Library *library,
- FT_Library ftlibrary, const char *family,
- const char *path, int fc, const char *config,
- int update)
-{
- FCInstance *priv;
-
- ass_msg(library, MSGL_WARN,
- "Fontconfig disabled, only default font will be used.");
-
- priv = calloc(1, sizeof(FCInstance));
-
- priv->path_default = path ? strdup(path) : 0;
- priv->index_default = 0;
- return priv;
-}
-
-int fontconfig_update(FCInstance *priv)
-{
- // Do nothing
- return 1;
-}
-
-#endif
-
-void fontconfig_done(FCInstance *priv)
-{
-
- if (priv) {
-#ifdef CONFIG_FONTCONFIG
- if (priv->config)
- FcConfigDestroy(priv->config);
-#endif
- free(priv->path_default);
- free(priv->family_default);
- }
- free(priv);
-}
diff --git a/lib/libass/libass/ass_fontconfig.h b/lib/libass/libass/ass_fontconfig.h
deleted file mode 100644
index 396fb72d0d..0000000000
--- a/lib/libass/libass/ass_fontconfig.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LIBASS_FONTCONFIG_H
-#define LIBASS_FONTCONFIG_H
-
-#include <stdint.h>
-#include "ass_types.h"
-#include "ass.h"
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef CONFIG_FONTCONFIG
-#include <fontconfig/fontconfig.h>
-#endif
-
-typedef struct fc_instance FCInstance;
-
-FCInstance *fontconfig_init(ASS_Library *library,
- FT_Library ftlibrary, const char *family,
- const char *path, int fc, const char *config,
- int update);
-char *fontconfig_select(ASS_Library *library, FCInstance *priv,
- const char *family, int treat_family_as_pattern,
- unsigned bold, unsigned italic, int *index,
- uint32_t code);
-void fontconfig_done(FCInstance *priv);
-int fontconfig_update(FCInstance *priv);
-
-#endif /* LIBASS_FONTCONFIG_H */
diff --git a/lib/libass/libass/ass_library.c b/lib/libass/libass/ass_library.c
deleted file mode 100644
index b33ca551b0..0000000000
--- a/lib/libass/libass/ass_library.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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 <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#include "ass.h"
-#include "ass_library.h"
-#include "ass_utils.h"
-
-static void ass_msg_handler(int level, const char *fmt, va_list va, void *data)
-{
- if (level > MSGL_INFO)
- return;
- fprintf(stderr, "[ass] ");
- vfprintf(stderr, fmt, va);
- fprintf(stderr, "\n");
-}
-
-ASS_Library *ass_library_init(void)
-{
- ASS_Library* lib = calloc(1, sizeof(*lib));
- lib->msg_callback = ass_msg_handler;
-
- return lib;
-}
-
-void ass_library_done(ASS_Library *priv)
-{
- if (priv) {
- ass_set_fonts_dir(priv, NULL);
- ass_set_style_overrides(priv, NULL);
- ass_clear_fonts(priv);
- free(priv);
- }
-}
-
-void ass_set_fonts_dir(ASS_Library *priv, const char *fonts_dir)
-{
- free(priv->fonts_dir);
-
- priv->fonts_dir = fonts_dir ? strdup(fonts_dir) : 0;
-}
-
-void ass_set_extract_fonts(ASS_Library *priv, int extract)
-{
- priv->extract_fonts = !!extract;
-}
-
-void ass_set_style_overrides(ASS_Library *priv, char **list)
-{
- char **p;
- char **q;
- int cnt;
-
- if (priv->style_overrides) {
- for (p = priv->style_overrides; *p; ++p)
- free(*p);
- }
- free(priv->style_overrides);
- priv->style_overrides = NULL;
-
- if (!list)
- return;
-
- for (p = list, cnt = 0; *p; ++p, ++cnt) {
- }
-
- priv->style_overrides = malloc((cnt + 1) * sizeof(char *));
- for (p = list, q = priv->style_overrides; *p; ++p, ++q)
- *q = strdup(*p);
- priv->style_overrides[cnt] = NULL;
-}
-
-static void grow_array(void **array, int nelem, size_t elsize)
-{
- if (!(nelem & 31))
- *array = realloc(*array, (nelem + 32) * elsize);
-}
-
-void ass_add_font(ASS_Library *priv, char *name, char *data, int size)
-{
- int idx = priv->num_fontdata;
- if (!name || !data || !size)
- return;
- grow_array((void **) &priv->fontdata, priv->num_fontdata,
- sizeof(*priv->fontdata));
-
- priv->fontdata[idx].name = strdup(name);
-
- priv->fontdata[idx].data = malloc(size);
- memcpy(priv->fontdata[idx].data, data, size);
-
- priv->fontdata[idx].size = size;
-
- priv->num_fontdata++;
-}
-
-void ass_clear_fonts(ASS_Library *priv)
-{
- int i;
- for (i = 0; i < priv->num_fontdata; ++i) {
- free(priv->fontdata[i].name);
- free(priv->fontdata[i].data);
- }
- free(priv->fontdata);
- priv->fontdata = NULL;
- priv->num_fontdata = 0;
-}
-
-/*
- * Register a message callback function with libass. Without setting one,
- * a default handler is used which prints everything with MSGL_INFO or
- * higher to the standard output.
- *
- * \param msg_cb the callback function
- * \param data additional data that will be passed to the callback
- */
-void ass_set_message_cb(ASS_Library *priv,
- void (*msg_cb)(int, const char *, va_list, void *),
- void *data)
-{
- if (msg_cb) {
- priv->msg_callback = msg_cb;
- priv->msg_callback_data = data;
- }
-}
diff --git a/lib/libass/libass/ass_library.h b/lib/libass/libass/ass_library.h
deleted file mode 100644
index 8faf15e93f..0000000000
--- a/lib/libass/libass/ass_library.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LIBASS_LIBRARY_H
-#define LIBASS_LIBRARY_H
-
-#include <stdarg.h>
-
-typedef struct {
- char *name;
- char *data;
- int size;
-} ASS_Fontdata;
-
-struct ass_library {
- char *fonts_dir;
- int extract_fonts;
- char **style_overrides;
-
- ASS_Fontdata *fontdata;
- int num_fontdata;
- void (*msg_callback)(int, const char *, va_list, void *);
- void *msg_callback_data;
-};
-
-#endif /* LIBASS_LIBRARY_H */
diff --git a/lib/libass/libass/ass_parse.c b/lib/libass/libass/ass_parse.c
deleted file mode 100644
index 92a47b3aeb..0000000000
--- a/lib/libass/libass/ass_parse.c
+++ /dev/null
@@ -1,1039 +0,0 @@
-/*
- * Copyright (C) 2009 Grigori Goronzy <greg@geekmind.org>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "ass_render.h"
-#include "ass_parse.h"
-
-#define MAX_BE 127
-#define NBSP 0xa0 // unicode non-breaking space character
-
-#define skip_to(x) while ((*p != (x)) && (*p != '}') && (*p != 0)) { ++p;}
-#define skip(x) if (*p == (x)) ++p; else { return p; }
-#define skipopt(x) if (*p == (x)) { ++p; }
-
-/**
- * \brief Check if starting part of (*p) matches sample.
- * If true, shift p to the first symbol after the matching part.
- */
-static inline int mystrcmp(char **p, const char *sample)
-{
- int len = strlen(sample);
- if (strncmp(*p, sample, len) == 0) {
- (*p) += len;
- return 1;
- } else
- return 0;
-}
-
-double ensure_font_size(ASS_Renderer *priv, double size)
-{
- if (size < 1)
- size = 1;
- else if (size > priv->height * 2)
- size = priv->height * 2;
-
- return size;
-}
-
-static void change_font_size(ASS_Renderer *render_priv, double sz)
-{
- render_priv->state.font_size = sz;
-}
-
-/**
- * \brief Change current font, using setting from render_priv->state.
- */
-void update_font(ASS_Renderer *render_priv)
-{
- unsigned val;
- ASS_FontDesc desc;
- desc.treat_family_as_pattern = render_priv->state.treat_family_as_pattern;
-
- if (render_priv->state.family[0] == '@') {
- desc.vertical = 1;
- desc.family = strdup(render_priv->state.family + 1);
- } else {
- desc.vertical = 0;
- desc.family = strdup(render_priv->state.family);
- }
-
- val = render_priv->state.bold;
- // 0 = normal, 1 = bold, >1 = exact weight
- if (val == 1 || val == -1)
- val = 200; // bold
- else if (val <= 0)
- val = 80; // normal
- desc.bold = val;
-
- val = render_priv->state.italic;
- if (val == 1 || val == -1)
- val = 110; // italic
- else if (val <= 0)
- val = 0; // normal
- desc.italic = val;
-
- render_priv->state.font =
- ass_font_new(render_priv->cache.font_cache, render_priv->library,
- render_priv->ftlibrary, render_priv->fontconfig_priv,
- &desc);
- free(desc.family);
-
- if (render_priv->state.font)
- change_font_size(render_priv, render_priv->state.font_size);
-}
-
-/**
- * \brief Change border width
- * negative value resets border to style value
- */
-void change_border(ASS_Renderer *render_priv, double border_x,
- double border_y)
-{
- int bord;
- if (!render_priv->state.font)
- return;
-
- if (border_x < 0 && border_y < 0) {
- if (render_priv->state.style->BorderStyle == 1 ||
- render_priv->state.style->BorderStyle == 3)
- border_x = border_y = render_priv->state.style->Outline;
- else
- border_x = border_y = 1.;
- }
-
- render_priv->state.border_x = border_x;
- render_priv->state.border_y = border_y;
-
- bord = 64 * border_x * render_priv->border_scale;
- if (bord > 0 && border_x == border_y) {
- if (!render_priv->state.stroker) {
- int error;
- error =
- FT_Stroker_New(render_priv->ftlibrary,
- &render_priv->state.stroker);
- if (error) {
- ass_msg(render_priv->library, MSGL_V,
- "failed to get stroker");
- render_priv->state.stroker = 0;
- }
- }
- if (render_priv->state.stroker)
- FT_Stroker_Set(render_priv->state.stroker, bord,
- FT_STROKER_LINECAP_ROUND,
- FT_STROKER_LINEJOIN_ROUND, 0);
- } else {
- FT_Stroker_Done(render_priv->state.stroker);
- render_priv->state.stroker = 0;
- }
-}
-
-/**
- * \brief Calculate a weighted average of two colors
- * calculates c1*(1-a) + c2*a, but separately for each component except alpha
- */
-static void change_color(uint32_t *var, uint32_t new, double pwr)
-{
- (*var) = ((uint32_t) (_r(*var) * (1 - pwr) + _r(new) * pwr) << 24) +
- ((uint32_t) (_g(*var) * (1 - pwr) + _g(new) * pwr) << 16) +
- ((uint32_t) (_b(*var) * (1 - pwr) + _b(new) * pwr) << 8) + _a(*var);
-}
-
-// like change_color, but for alpha component only
-inline void change_alpha(uint32_t *var, uint32_t new, double pwr)
-{
- *var =
- (_r(*var) << 24) + (_g(*var) << 16) + (_b(*var) << 8) +
- (uint32_t) (_a(*var) * (1 - pwr) + _a(new) * pwr);
-}
-
-/**
- * \brief Multiply two alpha values
- * \param a first value
- * \param b second value
- * \return result of multiplication
- * Parameters and result are limited by 0xFF.
- */
-inline uint32_t mult_alpha(uint32_t a, uint32_t b)
-{
- return 0xFF - (0xFF - a) * (0xFF - b) / 0xFF;
-}
-
-/**
- * \brief Calculate alpha value by piecewise linear function
- * Used for \fad, \fade implementation.
- */
-static unsigned
-interpolate_alpha(long long now, long long t1, long long t2, long long t3,
- long long t4, unsigned a1, unsigned a2, unsigned a3)
-{
- unsigned a;
- double cf;
-
- if (now < t1) {
- a = a1;
- } else if (now >= t4) {
- a = a3;
- } else if (now < t2 && t2 > t1) {
- cf = ((double) (now - t1)) / (t2 - t1);
- a = a1 * (1 - cf) + a2 * cf;
- } else if (now >= t3 && t4 > t3) {
- cf = ((double) (now - t3)) / (t4 - t3);
- a = a2 * (1 - cf) + a3 * cf;
- } else { // t2 <= now < t3
- a = a2;
- }
-
- return a;
-}
-
-/**
- * Parse a vector clip into an outline, using the proper scaling
- * parameters. Translate it to correct for screen borders, if needed.
- */
-static char *parse_vector_clip(ASS_Renderer *render_priv, char *p)
-{
- int scale = 1;
- int res = 0;
- ASS_Drawing *drawing = render_priv->state.clip_drawing;
-
- ass_drawing_free(drawing);
- render_priv->state.clip_drawing =
- ass_drawing_new(render_priv->library, render_priv->ftlibrary);
- drawing = render_priv->state.clip_drawing;
- skipopt('(');
- res = mystrtoi(&p, &scale);
- skipopt(',')
- if (!res)
- scale = 1;
- drawing->scale = scale;
- drawing->scale_x = render_priv->font_scale_x * render_priv->font_scale;
- drawing->scale_y = render_priv->font_scale;
- while (*p != ')' && *p != '}' && p != 0)
- ass_drawing_add_char(drawing, *p++);
- skipopt(')');
-
- return p;
-}
-
-/**
- * \brief Parse style override tag.
- * \param p string to parse
- * \param pwr multiplier for some tag effects (comes from \t tags)
- */
-static char *parse_tag(ASS_Renderer *render_priv, char *p, double pwr)
-{
- skip_to('\\');
- skip('\\');
- if ((*p == '}') || (*p == 0))
- return p;
-
- // New tags introduced in vsfilter 2.39
- if (mystrcmp(&p, "xbord")) {
- double val;
- if (mystrtod(&p, &val))
- val = render_priv->state.border_x * (1 - pwr) + val * pwr;
- else
- val = -1.;
- change_border(render_priv, val, render_priv->state.border_y);
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "ybord")) {
- double val;
- if (mystrtod(&p, &val))
- val = render_priv->state.border_y * (1 - pwr) + val * pwr;
- else
- val = -1.;
- change_border(render_priv, render_priv->state.border_x, val);
- } else if (mystrcmp(&p, "xshad")) {
- double val;
- if (mystrtod(&p, &val))
- val = render_priv->state.shadow_x * (1 - pwr) + val * pwr;
- else
- val = 0.;
- render_priv->state.shadow_x = val;
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "yshad")) {
- double val;
- if (mystrtod(&p, &val))
- val = render_priv->state.shadow_y * (1 - pwr) + val * pwr;
- else
- val = 0.;
- render_priv->state.shadow_y = val;
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "fax")) {
- double val;
- if (mystrtod(&p, &val))
- render_priv->state.fax =
- val * pwr + render_priv->state.fax * (1 - pwr);
- else
- render_priv->state.fax = 0.;
- } else if (mystrcmp(&p, "fay")) {
- double val;
- if (mystrtod(&p, &val))
- render_priv->state.fay =
- val * pwr + render_priv->state.fay * (1 - pwr);
- else
- render_priv->state.fay = 0.;
- } else if (mystrcmp(&p, "iclip")) {
- int x0, y0, x1, y1;
- int res = 1;
- char *start = p;
- skipopt('(');
- res &= mystrtoi(&p, &x0);
- skipopt(',');
- res &= mystrtoi(&p, &y0);
- skipopt(',');
- res &= mystrtoi(&p, &x1);
- skipopt(',');
- res &= mystrtoi(&p, &y1);
- skipopt(')');
- if (res) {
- render_priv->state.clip_x0 =
- render_priv->state.clip_x0 * (1 - pwr) + x0 * pwr;
- render_priv->state.clip_x1 =
- render_priv->state.clip_x1 * (1 - pwr) + x1 * pwr;
- render_priv->state.clip_y0 =
- render_priv->state.clip_y0 * (1 - pwr) + y0 * pwr;
- render_priv->state.clip_y1 =
- render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr;
- render_priv->state.clip_mode = 1;
- } else if (!render_priv->state.clip_drawing) {
- p = parse_vector_clip(render_priv, start);
- render_priv->state.clip_drawing_mode = 1;
- } else
- render_priv->state.clip_mode = 0;
- } else if (mystrcmp(&p, "blur")) {
- double val;
- if (mystrtod(&p, &val)) {
- val = render_priv->state.blur * (1 - pwr) + val * pwr;
- val = (val < 0) ? 0 : val;
- val = (val > BLUR_MAX_RADIUS) ? BLUR_MAX_RADIUS : val;
- render_priv->state.blur = val;
- } else
- render_priv->state.blur = 0.0;
- render_priv->state.bm_run_id++;
- // ASS standard tags
- } else if (mystrcmp(&p, "fsc")) {
- char tp = *p++;
- double val;
- if (tp == 'x') {
- if (mystrtod(&p, &val)) {
- val /= 100;
- render_priv->state.scale_x =
- render_priv->state.scale_x * (1 - pwr) + val * pwr;
- } else
- render_priv->state.scale_x =
- render_priv->state.style->ScaleX;
- } else if (tp == 'y') {
- if (mystrtod(&p, &val)) {
- val /= 100;
- render_priv->state.scale_y =
- render_priv->state.scale_y * (1 - pwr) + val * pwr;
- } else
- render_priv->state.scale_y =
- render_priv->state.style->ScaleY;
- }
- } else if (mystrcmp(&p, "fsp")) {
- double val;
- if (mystrtod(&p, &val))
- render_priv->state.hspacing =
- render_priv->state.hspacing * (1 - pwr) + val * pwr;
- else
- render_priv->state.hspacing = render_priv->state.style->Spacing;
- } else if (mystrcmp(&p, "fs+")) {
- double val;
- if (mystrtod(&p, &val)) {
- val = render_priv->state.font_size + pwr * val;
- } else
- val = render_priv->state.style->FontSize;
- if (render_priv->state.font)
- change_font_size(render_priv, val);
- } else if (mystrcmp(&p, "fs-")) {
- double val;
- if (mystrtod(&p, &val))
- val = render_priv->state.font_size - pwr * val;
- else
- val = render_priv->state.style->FontSize;
- if (render_priv->state.font)
- change_font_size(render_priv, val);
- } else if (mystrcmp(&p, "fs")) {
- double val;
- if (mystrtod(&p, &val))
- val = render_priv->state.font_size * (1 - pwr) + val * pwr;
- else
- val = render_priv->state.style->FontSize;
- if (render_priv->state.font)
- change_font_size(render_priv, val);
- } else if (mystrcmp(&p, "bord")) {
- double val;
- if (mystrtod(&p, &val)) {
- if (render_priv->state.border_x == render_priv->state.border_y)
- val = render_priv->state.border_x * (1 - pwr) + val * pwr;
- } else
- val = -1.; // reset to default
- change_border(render_priv, val, val);
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "move")) {
- double x1, x2, y1, y2;
- long long t1, t2, delta_t, t;
- double x, y;
- double k;
- skip('(');
- mystrtod(&p, &x1);
- skip(',');
- mystrtod(&p, &y1);
- skip(',');
- mystrtod(&p, &x2);
- skip(',');
- mystrtod(&p, &y2);
- if (*p == ',') {
- skip(',');
- mystrtoll(&p, &t1);
- skip(',');
- mystrtoll(&p, &t2);
- ass_msg(render_priv->library, MSGL_DBG2,
- "movement6: (%f, %f) -> (%f, %f), (%" PRId64 " .. %"
- PRId64 ")\n", x1, y1, x2, y2, (int64_t) t1,
- (int64_t) t2);
- } else {
- t1 = 0;
- t2 = render_priv->state.event->Duration;
- ass_msg(render_priv->library, MSGL_DBG2,
- "movement: (%f, %f) -> (%f, %f)", x1, y1, x2, y2);
- }
- skip(')');
- delta_t = t2 - t1;
- t = render_priv->time - render_priv->state.event->Start;
- if (t < t1)
- k = 0.;
- else if (t > t2)
- k = 1.;
- else
- k = ((double) (t - t1)) / delta_t;
- x = k * (x2 - x1) + x1;
- y = k * (y2 - y1) + y1;
- if (render_priv->state.evt_type != EVENT_POSITIONED) {
- render_priv->state.pos_x = x;
- render_priv->state.pos_y = y;
- render_priv->state.detect_collisions = 0;
- render_priv->state.evt_type = EVENT_POSITIONED;
- }
- } else if (mystrcmp(&p, "frx")) {
- double val;
- if (mystrtod(&p, &val)) {
- val *= M_PI / 180;
- render_priv->state.frx =
- val * pwr + render_priv->state.frx * (1 - pwr);
- } else
- render_priv->state.frx = 0.;
- } else if (mystrcmp(&p, "fry")) {
- double val;
- if (mystrtod(&p, &val)) {
- val *= M_PI / 180;
- render_priv->state.fry =
- val * pwr + render_priv->state.fry * (1 - pwr);
- } else
- render_priv->state.fry = 0.;
- } else if (mystrcmp(&p, "frz") || mystrcmp(&p, "fr")) {
- double val;
- if (mystrtod(&p, &val)) {
- val *= M_PI / 180;
- render_priv->state.frz =
- val * pwr + render_priv->state.frz * (1 - pwr);
- } else
- render_priv->state.frz =
- M_PI * render_priv->state.style->Angle / 180.;
- } else if (mystrcmp(&p, "fn")) {
- char *start = p;
- char *family;
- skip_to('\\');
- if (p > start) {
- family = malloc(p - start + 1);
- strncpy(family, start, p - start);
- family[p - start] = '\0';
- } else
- family = strdup(render_priv->state.style->FontName);
- free(render_priv->state.family);
- render_priv->state.family = family;
- update_font(render_priv);
- } else if (mystrcmp(&p, "alpha")) {
- uint32_t val;
- int i;
- int hex = render_priv->track->track_type == TRACK_TYPE_ASS;
- if (strtocolor(render_priv->library, &p, &val, hex)) {
- unsigned char a = val >> 24;
- for (i = 0; i < 4; ++i)
- change_alpha(&render_priv->state.c[i], a, pwr);
- } else {
- change_alpha(&render_priv->state.c[0],
- render_priv->state.style->PrimaryColour, pwr);
- change_alpha(&render_priv->state.c[1],
- render_priv->state.style->SecondaryColour, pwr);
- change_alpha(&render_priv->state.c[2],
- render_priv->state.style->OutlineColour, pwr);
- change_alpha(&render_priv->state.c[3],
- render_priv->state.style->BackColour, pwr);
- }
- render_priv->state.bm_run_id++;
- // FIXME: simplify
- } else if (mystrcmp(&p, "an")) {
- int val;
- if (mystrtoi(&p, &val) && val) {
- int v = (val - 1) / 3; // 0, 1 or 2 for vertical alignment
- ass_msg(render_priv->library, MSGL_DBG2, "an %d", val);
- if (v != 0)
- v = 3 - v;
- val = ((val - 1) % 3) + 1; // horizontal alignment
- val += v * 4;
- ass_msg(render_priv->library, MSGL_DBG2, "align %d", val);
- if ((render_priv->state.parsed_tags & PARSED_A) == 0) {
- render_priv->state.alignment = val;
- render_priv->state.parsed_tags |= PARSED_A;
- }
- } else
- render_priv->state.alignment =
- render_priv->state.style->Alignment;
- } else if (mystrcmp(&p, "a")) {
- int val;
- if (mystrtoi(&p, &val) && val) {
- if ((render_priv->state.parsed_tags & PARSED_A) == 0) {
- // take care of a vsfilter quirk: handle illegal \a8 like \a5
- render_priv->state.alignment = (val == 8) ? 5 : val;
- render_priv->state.parsed_tags |= PARSED_A;
- }
- } else
- render_priv->state.alignment =
- render_priv->state.style->Alignment;
- } else if (mystrcmp(&p, "pos")) {
- double v1, v2;
- skip('(');
- mystrtod(&p, &v1);
- skip(',');
- mystrtod(&p, &v2);
- skip(')');
- ass_msg(render_priv->library, MSGL_DBG2, "pos(%f, %f)", v1, v2);
- if (render_priv->state.evt_type == EVENT_POSITIONED) {
- ass_msg(render_priv->library, MSGL_V, "Subtitle has a new \\pos "
- "after \\move or \\pos, ignoring");
- } else {
- render_priv->state.evt_type = EVENT_POSITIONED;
- render_priv->state.detect_collisions = 0;
- render_priv->state.pos_x = v1;
- render_priv->state.pos_y = v2;
- }
- } else if (mystrcmp(&p, "fad")) {
- int a1, a2, a3;
- long long t1, t2, t3, t4;
- if (*p == 'e')
- ++p; // either \fad or \fade
- skip('(');
- mystrtoi(&p, &a1);
- skip(',');
- mystrtoi(&p, &a2);
- if (*p == ')') {
- // 2-argument version (\fad, according to specs)
- // a1 and a2 are fade-in and fade-out durations
- t1 = 0;
- t4 = render_priv->state.event->Duration;
- t2 = a1;
- t3 = t4 - a2;
- a1 = 0xFF;
- a2 = 0;
- a3 = 0xFF;
- } else {
- // 6-argument version (\fade)
- // a1 and a2 (and a3) are opacity values
- skip(',');
- mystrtoi(&p, &a3);
- skip(',');
- mystrtoll(&p, &t1);
- skip(',');
- mystrtoll(&p, &t2);
- skip(',');
- mystrtoll(&p, &t3);
- skip(',');
- mystrtoll(&p, &t4);
- }
- skip(')');
- if ((render_priv->state.parsed_tags & PARSED_FADE) == 0) {
- render_priv->state.fade =
- interpolate_alpha(render_priv->time -
- render_priv->state.event->Start, t1, t2,
- t3, t4, a1, a2, a3);
- render_priv->state.parsed_tags |= PARSED_FADE;
- }
- } else if (mystrcmp(&p, "org")) {
- int v1, v2;
- skip('(');
- mystrtoi(&p, &v1);
- skip(',');
- mystrtoi(&p, &v2);
- skip(')');
- ass_msg(render_priv->library, MSGL_DBG2, "org(%d, %d)", v1, v2);
- if (!render_priv->state.have_origin) {
- render_priv->state.org_x = v1;
- render_priv->state.org_y = v2;
- render_priv->state.have_origin = 1;
- render_priv->state.detect_collisions = 0;
- }
- } else if (mystrcmp(&p, "t")) {
- double v[3];
- int v1, v2;
- double v3;
- int cnt;
- long long t1, t2, t, delta_t;
- double k;
- skip('(');
- for (cnt = 0; cnt < 3; ++cnt) {
- if (*p == '\\')
- break;
- mystrtod(&p, &v[cnt]);
- skip(',');
- }
- if (cnt == 3) {
- v1 = v[0];
- v2 = (v[1] < v1) ? render_priv->state.event->Duration : v[1];
- v3 = v[2];
- } else if (cnt == 2) {
- v1 = v[0];
- v2 = (v[1] < v1) ? render_priv->state.event->Duration : v[1];
- v3 = 1.;
- } else if (cnt == 1) {
- v1 = 0;
- v2 = render_priv->state.event->Duration;
- v3 = v[0];
- } else { // cnt == 0
- v1 = 0;
- v2 = render_priv->state.event->Duration;
- v3 = 1.;
- }
- render_priv->state.detect_collisions = 0;
- t1 = v1;
- t2 = v2;
- delta_t = v2 - v1;
- if (v3 < 0.)
- v3 = 0.;
- t = render_priv->time - render_priv->state.event->Start; // FIXME: move to render_context
- if (t <= t1)
- k = 0.;
- else if (t >= t2)
- k = 1.;
- else {
- assert(delta_t != 0.);
- k = pow(((double) (t - t1)) / delta_t, v3);
- }
- while (*p == '\\')
- p = parse_tag(render_priv, p, k); // maybe k*pwr ? no, specs forbid nested \t's
- skip_to(')'); // in case there is some unknown tag or a comment
- skip(')');
- } else if (mystrcmp(&p, "clip")) {
- char *start = p;
- int x0, y0, x1, y1;
- int res = 1;
- skipopt('(');
- res &= mystrtoi(&p, &x0);
- skipopt(',');
- res &= mystrtoi(&p, &y0);
- skipopt(',');
- res &= mystrtoi(&p, &x1);
- skipopt(',');
- res &= mystrtoi(&p, &y1);
- skipopt(')');
- if (res) {
- render_priv->state.clip_x0 =
- render_priv->state.clip_x0 * (1 - pwr) + x0 * pwr;
- render_priv->state.clip_x1 =
- render_priv->state.clip_x1 * (1 - pwr) + x1 * pwr;
- render_priv->state.clip_y0 =
- render_priv->state.clip_y0 * (1 - pwr) + y0 * pwr;
- render_priv->state.clip_y1 =
- render_priv->state.clip_y1 * (1 - pwr) + y1 * pwr;
- // Might be a vector clip
- } else if (!render_priv->state.clip_drawing) {
- p = parse_vector_clip(render_priv, start);
- render_priv->state.clip_drawing_mode = 0;
- } else {
- render_priv->state.clip_x0 = 0;
- render_priv->state.clip_y0 = 0;
- render_priv->state.clip_x1 = render_priv->track->PlayResX;
- render_priv->state.clip_y1 = render_priv->track->PlayResY;
- }
- } else if (mystrcmp(&p, "c")) {
- uint32_t val;
- int hex = render_priv->track->track_type == TRACK_TYPE_ASS;
- if (!strtocolor(render_priv->library, &p, &val, hex))
- val = render_priv->state.style->PrimaryColour;
- ass_msg(render_priv->library, MSGL_DBG2, "color: %X", val);
- change_color(&render_priv->state.c[0], val, pwr);
- render_priv->state.bm_run_id++;
- } else if ((*p >= '1') && (*p <= '4') && (++p)
- && (mystrcmp(&p, "c") || mystrcmp(&p, "a"))) {
- char n = *(p - 2);
- int cidx = n - '1';
- char cmd = *(p - 1);
- uint32_t val;
- int hex = render_priv->track->track_type == TRACK_TYPE_ASS;
- assert((n >= '1') && (n <= '4'));
- if (!strtocolor(render_priv->library, &p, &val, hex))
- switch (n) {
- case '1':
- val = render_priv->state.style->PrimaryColour;
- break;
- case '2':
- val = render_priv->state.style->SecondaryColour;
- break;
- case '3':
- val = render_priv->state.style->OutlineColour;
- break;
- case '4':
- val = render_priv->state.style->BackColour;
- break;
- default:
- val = 0;
- break; // impossible due to assert; avoid compilation warning
- }
- switch (cmd) {
- case 'c':
- change_color(render_priv->state.c + cidx, val, pwr);
- render_priv->state.bm_run_id++;
- break;
- case 'a':
- change_alpha(render_priv->state.c + cidx, val >> 24, pwr);
- render_priv->state.bm_run_id++;
- break;
- default:
- ass_msg(render_priv->library, MSGL_WARN, "Bad command: %c%c",
- n, cmd);
- break;
- }
- ass_msg(render_priv->library, MSGL_DBG2, "single c/a at %f: %c%c = %X",
- pwr, n, cmd, render_priv->state.c[cidx]);
- } else if (mystrcmp(&p, "r")) {
- reset_render_context(render_priv);
- } else if (mystrcmp(&p, "be")) {
- int val;
- if (mystrtoi(&p, &val)) {
- // Clamp to a safe upper limit, since high values need excessive CPU
- val = (val < 0) ? 0 : val;
- val = (val > MAX_BE) ? MAX_BE : val;
- render_priv->state.be = val;
- } else
- render_priv->state.be = 0;
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "b")) {
- int b;
- if (mystrtoi(&p, &b)) {
- if (pwr >= .5)
- render_priv->state.bold = b;
- } else
- render_priv->state.bold = render_priv->state.style->Bold;
- update_font(render_priv);
- } else if (mystrcmp(&p, "i")) {
- int i;
- if (mystrtoi(&p, &i)) {
- if (pwr >= .5)
- render_priv->state.italic = i;
- } else
- render_priv->state.italic = render_priv->state.style->Italic;
- update_font(render_priv);
- } else if (mystrcmp(&p, "kf") || mystrcmp(&p, "K")) {
- int val = 0;
- mystrtoi(&p, &val);
- render_priv->state.effect_type = EF_KARAOKE_KF;
- if (render_priv->state.effect_timing)
- render_priv->state.effect_skip_timing +=
- render_priv->state.effect_timing;
- render_priv->state.effect_timing = val * 10;
- } else if (mystrcmp(&p, "ko")) {
- int val = 0;
- mystrtoi(&p, &val);
- render_priv->state.effect_type = EF_KARAOKE_KO;
- if (render_priv->state.effect_timing)
- render_priv->state.effect_skip_timing +=
- render_priv->state.effect_timing;
- render_priv->state.effect_timing = val * 10;
- } else if (mystrcmp(&p, "k")) {
- int val = 0;
- mystrtoi(&p, &val);
- render_priv->state.effect_type = EF_KARAOKE;
- if (render_priv->state.effect_timing)
- render_priv->state.effect_skip_timing +=
- render_priv->state.effect_timing;
- render_priv->state.effect_timing = val * 10;
- } else if (mystrcmp(&p, "shad")) {
- double val;
- if (mystrtod(&p, &val)) {
- if (render_priv->state.shadow_x == render_priv->state.shadow_y)
- val = render_priv->state.shadow_x * (1 - pwr) + val * pwr;
- } else
- val = 0.;
- render_priv->state.shadow_x = render_priv->state.shadow_y = val;
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "s")) {
- int val;
- if (mystrtoi(&p, &val) && val)
- render_priv->state.flags |= DECO_STRIKETHROUGH;
- else
- render_priv->state.flags &= ~DECO_STRIKETHROUGH;
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "u")) {
- int val;
- if (mystrtoi(&p, &val) && val)
- render_priv->state.flags |= DECO_UNDERLINE;
- else
- render_priv->state.flags &= ~DECO_UNDERLINE;
- render_priv->state.bm_run_id++;
- } else if (mystrcmp(&p, "pbo")) {
- double val = 0;
- if (mystrtod(&p, &val))
- render_priv->state.drawing->pbo = val;
- } else if (mystrcmp(&p, "p")) {
- int val;
- if (!mystrtoi(&p, &val))
- val = 0;
- if (val)
- render_priv->state.drawing->scale = val;
- render_priv->state.drawing_mode = !!val;
- } else if (mystrcmp(&p, "q")) {
- int val;
- if (!mystrtoi(&p, &val))
- val = render_priv->track->WrapStyle;
- render_priv->state.wrap_style = val;
- } else if (mystrcmp(&p, "fe")) {
- int val;
- if (!mystrtoi(&p, &val))
- val = render_priv->state.style->Encoding;
- render_priv->state.font_encoding = val;
- }
-
- return p;
-}
-
-void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event)
-{
- int v[4];
- int cnt;
- char *p = event->Effect;
-
- if (!p || !*p)
- return;
-
- cnt = 0;
- while (cnt < 4 && (p = strchr(p, ';'))) {
- v[cnt++] = atoi(++p);
- }
-
- if (strncmp(event->Effect, "Banner;", 7) == 0) {
- int delay;
- if (cnt < 1) {
- ass_msg(render_priv->library, MSGL_V,
- "Error parsing effect: '%s'", event->Effect);
- return;
- }
- if (cnt >= 2 && v[1] == 0) // right-to-left
- render_priv->state.scroll_direction = SCROLL_RL;
- else // left-to-right
- render_priv->state.scroll_direction = SCROLL_LR;
-
- delay = v[0];
- if (delay == 0)
- delay = 1; // ?
- render_priv->state.scroll_shift =
- (render_priv->time - render_priv->state.event->Start) / delay;
- render_priv->state.evt_type = EVENT_HSCROLL;
- return;
- }
-
- if (strncmp(event->Effect, "Scroll up;", 10) == 0) {
- render_priv->state.scroll_direction = SCROLL_BT;
- } else if (strncmp(event->Effect, "Scroll down;", 12) == 0) {
- render_priv->state.scroll_direction = SCROLL_TB;
- } else {
- ass_msg(render_priv->library, MSGL_DBG2,
- "Unknown transition effect: '%s'", event->Effect);
- return;
- }
- // parse scroll up/down parameters
- {
- int delay;
- int y0, y1;
- if (cnt < 3) {
- ass_msg(render_priv->library, MSGL_V,
- "Error parsing effect: '%s'", event->Effect);
- return;
- }
- delay = v[2];
- if (delay == 0)
- delay = 1; // ?
- render_priv->state.scroll_shift =
- (render_priv->time - render_priv->state.event->Start) / delay;
- if (v[0] < v[1]) {
- y0 = v[0];
- y1 = v[1];
- } else {
- y0 = v[1];
- y1 = v[0];
- }
- if (y1 == 0)
- y1 = render_priv->track->PlayResY; // y0=y1=0 means fullscreen scrolling
- render_priv->state.clip_y0 = y0;
- render_priv->state.clip_y1 = y1;
- render_priv->state.evt_type = EVENT_VSCROLL;
- render_priv->state.detect_collisions = 0;
- }
-
-}
-
-/**
- * \brief determine karaoke effects
- * Karaoke effects cannot be calculated during parse stage (get_next_char()),
- * so they are done in a separate step.
- * Parse stage: when karaoke style override is found, its parameters are stored in the next glyph's
- * (the first glyph of the karaoke word)'s effect_type and effect_timing.
- * This function:
- * 1. sets effect_type for all glyphs in the word (_karaoke_ word)
- * 2. sets effect_timing for all glyphs to x coordinate of the border line between the left and right karaoke parts
- * (left part is filled with PrimaryColour, right one - with SecondaryColour).
- */
-void process_karaoke_effects(ASS_Renderer *render_priv)
-{
- GlyphInfo *cur, *cur2;
- GlyphInfo *s1, *e1; // start and end of the current word
- GlyphInfo *s2; // start of the next word
- int i;
- int timing; // current timing
- int tm_start, tm_end; // timings at start and end of the current word
- int tm_current;
- double dt;
- int x;
- int x_start, x_end;
-
- tm_current = render_priv->time - render_priv->state.event->Start;
- timing = 0;
- s1 = s2 = 0;
- for (i = 0; i <= render_priv->text_info.length; ++i) {
- cur = render_priv->text_info.glyphs + i;
- if ((i == render_priv->text_info.length)
- || (cur->effect_type != EF_NONE)) {
- s1 = s2;
- s2 = cur;
- if (s1) {
- e1 = s2 - 1;
- tm_start = timing + s1->effect_skip_timing;
- tm_end = tm_start + s1->effect_timing;
- timing = tm_end;
- x_start = 1000000;
- x_end = -1000000;
- for (cur2 = s1; cur2 <= e1; ++cur2) {
- x_start = FFMIN(x_start, d6_to_int(cur2->bbox.xMin + cur2->pos.x));
- x_end = FFMAX(x_end, d6_to_int(cur2->bbox.xMax + cur2->pos.x));
- }
-
- dt = (tm_current - tm_start);
- if ((s1->effect_type == EF_KARAOKE)
- || (s1->effect_type == EF_KARAOKE_KO)) {
- if (dt > 0)
- x = x_end + 1;
- else
- x = x_start;
- } else if (s1->effect_type == EF_KARAOKE_KF) {
- dt /= (tm_end - tm_start);
- x = x_start + (x_end - x_start) * dt;
- } else {
- ass_msg(render_priv->library, MSGL_ERR,
- "Unknown effect type");
- continue;
- }
-
- for (cur2 = s1; cur2 <= e1; ++cur2) {
- cur2->effect_type = s1->effect_type;
- cur2->effect_timing = x - d6_to_int(cur2->pos.x);
- }
- }
- }
- }
-}
-
-
-/**
- * \brief Get next ucs4 char from string, parsing and executing style overrides
- * \param str string pointer
- * \return ucs4 code of the next char
- * On return str points to the unparsed part of the string
- */
-unsigned get_next_char(ASS_Renderer *render_priv, char **str)
-{
- char *p = *str;
- unsigned chr;
- if (*p == '{') { // '\0' goes here
- p++;
- while (1) {
- p = parse_tag(render_priv, p, 1.);
- if (*p == '}') { // end of tag
- p++;
- if (*p == '{') {
- p++;
- continue;
- } else
- break;
- } else if (*p != '\\')
- ass_msg(render_priv->library, MSGL_V,
- "Unable to parse: '%.30s'", p);
- if (*p == 0)
- break;
- }
- }
- if (*p == '\t') {
- ++p;
- *str = p;
- return ' ';
- }
- if (*p == '\\') {
- if ((p[1] == 'N') || ((p[1] == 'n') &&
- (render_priv->state.wrap_style == 2))) {
- p += 2;
- *str = p;
- return '\n';
- } else if (p[1] == 'n') {
- p += 2;
- *str = p;
- return ' ';
- } else if (p[1] == 'h') {
- p += 2;
- *str = p;
- return NBSP;
- } else if (p[1] == '{') {
- p += 2;
- *str = p;
- return '{';
- } else if (p[1] == '}') {
- p += 2;
- *str = p;
- return '}';
- }
- }
- chr = ass_utf8_get_char((char **) &p);
- *str = p;
- return chr;
-}
diff --git a/lib/libass/libass/ass_parse.h b/lib/libass/libass/ass_parse.h
deleted file mode 100644
index 2e145dcbfa..0000000000
--- a/lib/libass/libass/ass_parse.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2009 Grigori Goronzy <greg@geekmind.org>
- *
- * 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.
- */
-
-#ifndef LIBASS_PARSE_H
-#define LIBASS_PARSE_H
-
-#define BLUR_MAX_RADIUS 100.0
-
-#define _r(c) ((c) >> 24)
-#define _g(c) (((c) >> 16) & 0xFF)
-#define _b(c) (((c) >> 8) & 0xFF)
-#define _a(c) ((c) & 0xFF)
-
-void update_font(ASS_Renderer *render_priv);
-double ensure_font_size(ASS_Renderer *priv, double size);
-void change_border(ASS_Renderer *render_priv, double border_x,
- double border_y);
-void apply_transition_effects(ASS_Renderer *render_priv, ASS_Event *event);
-void process_karaoke_effects(ASS_Renderer *render_priv);
-unsigned get_next_char(ASS_Renderer *render_priv, char **str);
-extern void change_alpha(uint32_t *var, uint32_t new, double pwr);
-extern uint32_t mult_alpha(uint32_t a, uint32_t b);
-
-
-#endif /* LIBASS_PARSE_H */
diff --git a/lib/libass/libass/ass_render.c b/lib/libass/libass/ass_render.c
deleted file mode 100644
index 97befdded1..0000000000
--- a/lib/libass/libass/ass_render.c
+++ /dev/null
@@ -1,2539 +0,0 @@
-/*
- * 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 <assert.h>
-#include <math.h>
-
-#include "ass_render.h"
-#include "ass_parse.h"
-#include "ass_shaper.h"
-
-#define MAX_GLYPHS_INITIAL 1024
-#define MAX_LINES_INITIAL 64
-#define SUBPIXEL_MASK 63
-#define SUBPIXEL_ACCURACY 7
-
-ASS_Renderer *ass_renderer_init(ASS_Library *library)
-{
- int error;
- FT_Library ft;
- ASS_Renderer *priv = 0;
- int vmajor, vminor, vpatch;
-
- error = FT_Init_FreeType(&ft);
- if (error) {
- ass_msg(library, MSGL_FATAL, "%s failed", "FT_Init_FreeType");
- goto ass_init_exit;
- }
-
- FT_Library_Version(ft, &vmajor, &vminor, &vpatch);
- ass_msg(library, MSGL_V, "Raster: FreeType %d.%d.%d",
- vmajor, vminor, vpatch);
-
- priv = calloc(1, sizeof(ASS_Renderer));
- if (!priv) {
- FT_Done_FreeType(ft);
- goto ass_init_exit;
- }
-
- priv->synth_priv = ass_synth_init(BLUR_MAX_RADIUS);
-
- priv->library = library;
- priv->ftlibrary = ft;
- // images_root and related stuff is zero-filled in calloc
-
- priv->cache.font_cache = ass_font_cache_create();
- priv->cache.bitmap_cache = ass_bitmap_cache_create();
- priv->cache.composite_cache = ass_composite_cache_create();
- priv->cache.outline_cache = ass_outline_cache_create();
- priv->cache.glyph_max = GLYPH_CACHE_MAX;
- priv->cache.bitmap_max_size = BITMAP_CACHE_MAX_SIZE;
-
- priv->text_info.max_glyphs = MAX_GLYPHS_INITIAL;
- priv->text_info.max_lines = MAX_LINES_INITIAL;
- priv->text_info.glyphs = calloc(MAX_GLYPHS_INITIAL, sizeof(GlyphInfo));
- priv->text_info.lines = calloc(MAX_LINES_INITIAL, sizeof(LineInfo));
-
- priv->settings.font_size_coeff = 1.;
-
- priv->shaper = ass_shaper_new(0);
- ass_shaper_info(library);
-#ifdef CONFIG_HARFBUZZ
- priv->settings.shaper = ASS_SHAPING_COMPLEX;
-#else
- priv->settings.shaper = ASS_SHAPING_SIMPLE;
-#endif
-
- ass_init_exit:
- if (priv)
- ass_msg(library, MSGL_V, "Initialized");
- else
- ass_msg(library, MSGL_ERR, "Initialization failed");
-
- return priv;
-}
-
-static void free_list_clear(ASS_Renderer *render_priv)
-{
- if (render_priv->free_head) {
- FreeList *item = render_priv->free_head;
- while(item) {
- FreeList *oi = item;
- free(item->object);
- item = item->next;
- free(oi);
- }
- render_priv->free_head = NULL;
- }
-}
-
-void ass_renderer_done(ASS_Renderer *render_priv)
-{
- ass_cache_done(render_priv->cache.font_cache);
- ass_cache_done(render_priv->cache.bitmap_cache);
- ass_cache_done(render_priv->cache.composite_cache);
- ass_cache_done(render_priv->cache.outline_cache);
-
- ass_free_images(render_priv->images_root);
- ass_free_images(render_priv->prev_images_root);
-
- if (render_priv->state.stroker) {
- FT_Stroker_Done(render_priv->state.stroker);
- render_priv->state.stroker = 0;
- }
- if (render_priv->ftlibrary)
- FT_Done_FreeType(render_priv->ftlibrary);
- if (render_priv->fontconfig_priv)
- fontconfig_done(render_priv->fontconfig_priv);
- if (render_priv->synth_priv)
- ass_synth_done(render_priv->synth_priv);
- ass_shaper_free(render_priv->shaper);
- free(render_priv->eimg);
- free(render_priv->text_info.glyphs);
- free(render_priv->text_info.lines);
-
- free(render_priv->settings.default_font);
- free(render_priv->settings.default_family);
-
- free_list_clear(render_priv);
- free(render_priv);
-}
-
-/**
- * \brief Create a new ASS_Image
- * Parameters are the same as ASS_Image fields.
- */
-static ASS_Image *my_draw_bitmap(unsigned char *bitmap, int bitmap_w,
- int bitmap_h, int stride, int dst_x,
- int dst_y, uint32_t color)
-{
- ASS_Image *img = malloc(sizeof(ASS_Image));
-
- if (img) {
- img->w = bitmap_w;
- img->h = bitmap_h;
- img->stride = stride;
- img->bitmap = bitmap;
- img->color = color;
- img->dst_x = dst_x;
- img->dst_y = dst_y;
- }
-
- return img;
-}
-
-/**
- * \brief Mapping between script and screen coordinates
- */
-static double x2scr(ASS_Renderer *render_priv, double x)
-{
- return x * render_priv->orig_width_nocrop / render_priv->font_scale_x /
- render_priv->track->PlayResX +
- FFMAX(render_priv->settings.left_margin, 0);
-}
-static double x2scr_pos(ASS_Renderer *render_priv, double x)
-{
- return x * render_priv->orig_width / render_priv->font_scale_x / render_priv->track->PlayResX +
- render_priv->settings.left_margin;
-}
-static double x2scr_scaled(ASS_Renderer *render_priv, double x)
-{
- return x * render_priv->orig_width_nocrop /
- render_priv->track->PlayResX +
- FFMAX(render_priv->settings.left_margin, 0);
-}
-static double x2scr_pos_scaled(ASS_Renderer *render_priv, double x)
-{
- return x * render_priv->orig_width / render_priv->track->PlayResX +
- render_priv->settings.left_margin;
-}
-/**
- * \brief Mapping between script and screen coordinates
- */
-static double y2scr(ASS_Renderer *render_priv, double y)
-{
- return y * render_priv->orig_height_nocrop /
- render_priv->track->PlayResY +
- FFMAX(render_priv->settings.top_margin, 0);
-}
-static double y2scr_pos(ASS_Renderer *render_priv, double y)
-{
- return y * render_priv->orig_height / render_priv->track->PlayResY +
- render_priv->settings.top_margin;
-}
-
-// the same for toptitles
-static double y2scr_top(ASS_Renderer *render_priv, double y)
-{
- if (render_priv->settings.use_margins)
- return y * render_priv->orig_height_nocrop /
- render_priv->track->PlayResY;
- else
- return y * render_priv->orig_height_nocrop /
- render_priv->track->PlayResY +
- FFMAX(render_priv->settings.top_margin, 0);
-}
-// the same for subtitles
-static double y2scr_sub(ASS_Renderer *render_priv, double y)
-{
- if (render_priv->settings.use_margins)
- return y * render_priv->orig_height_nocrop /
- render_priv->track->PlayResY +
- FFMAX(render_priv->settings.top_margin, 0)
- + FFMAX(render_priv->settings.bottom_margin, 0);
- else
- return y * render_priv->orig_height_nocrop /
- render_priv->track->PlayResY +
- FFMAX(render_priv->settings.top_margin, 0);
-}
-
-/*
- * \brief Convert bitmap glyphs into ASS_Image list with inverse clipping
- *
- * Inverse clipping with the following strategy:
- * - find rectangle from (x0, y0) to (cx0, y1)
- * - find rectangle from (cx0, y0) to (cx1, cy0)
- * - find rectangle from (cx0, cy1) to (cx1, y1)
- * - find rectangle from (cx1, y0) to (x1, y1)
- * These rectangles can be invalid and in this case are discarded.
- * Afterwards, they are clipped against the screen coordinates.
- * In an additional pass, the rectangles need to be split up left/right for
- * karaoke effects. This can result in a lot of bitmaps (6 to be exact).
- */
-static ASS_Image **render_glyph_i(ASS_Renderer *render_priv,
- Bitmap *bm, int dst_x, int dst_y,
- uint32_t color, uint32_t color2, int brk,
- ASS_Image **tail)
-{
- int i, j, x0, y0, x1, y1, cx0, cy0, cx1, cy1, sx, sy, zx, zy;
- Rect r[4];
- ASS_Image *img;
-
- dst_x += bm->left;
- dst_y += bm->top;
-
- // we still need to clip against screen boundaries
- zx = x2scr_pos_scaled(render_priv, 0);
- zy = y2scr_pos(render_priv, 0);
- sx = x2scr_pos_scaled(render_priv, render_priv->track->PlayResX);
- sy = y2scr_pos(render_priv, render_priv->track->PlayResY);
-
- x0 = 0;
- y0 = 0;
- x1 = bm->w;
- y1 = bm->h;
- cx0 = render_priv->state.clip_x0 - dst_x;
- cy0 = render_priv->state.clip_y0 - dst_y;
- cx1 = render_priv->state.clip_x1 - dst_x;
- cy1 = render_priv->state.clip_y1 - dst_y;
-
- // calculate rectangles and discard invalid ones while we're at it.
- i = 0;
- r[i].x0 = x0;
- r[i].y0 = y0;
- r[i].x1 = (cx0 > x1) ? x1 : cx0;
- r[i].y1 = y1;
- if (r[i].x1 > r[i].x0 && r[i].y1 > r[i].y0) i++;
- r[i].x0 = (cx0 < 0) ? x0 : cx0;
- r[i].y0 = y0;
- r[i].x1 = (cx1 > x1) ? x1 : cx1;
- r[i].y1 = (cy0 > y1) ? y1 : cy0;
- if (r[i].x1 > r[i].x0 && r[i].y1 > r[i].y0) i++;
- r[i].x0 = (cx0 < 0) ? x0 : cx0;
- r[i].y0 = (cy1 < 0) ? y0 : cy1;
- r[i].x1 = (cx1 > x1) ? x1 : cx1;
- r[i].y1 = y1;
- if (r[i].x1 > r[i].x0 && r[i].y1 > r[i].y0) i++;
- r[i].x0 = (cx1 < 0) ? x0 : cx1;
- r[i].y0 = y0;
- r[i].x1 = x1;
- r[i].y1 = y1;
- if (r[i].x1 > r[i].x0 && r[i].y1 > r[i].y0) i++;
-
- // clip each rectangle to screen coordinates
- for (j = 0; j < i; j++) {
- r[j].x0 = (r[j].x0 + dst_x < zx) ? zx - dst_x : r[j].x0;
- r[j].y0 = (r[j].y0 + dst_y < zy) ? zy - dst_y : r[j].y0;
- r[j].x1 = (r[j].x1 + dst_x > sx) ? sx - dst_x : r[j].x1;
- r[j].y1 = (r[j].y1 + dst_y > sy) ? sy - dst_y : r[j].y1;
- }
-
- // draw the rectangles
- for (j = 0; j < i; j++) {
- int lbrk = brk;
- // kick out rectangles that are invalid now
- if (r[j].x1 <= r[j].x0 || r[j].y1 <= r[j].y0)
- continue;
- // split up into left and right for karaoke, if needed
- if (lbrk > r[j].x0) {
- if (lbrk > r[j].x1) lbrk = r[j].x1;
- img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->stride + r[j].x0,
- lbrk - r[j].x0, r[j].y1 - r[j].y0,
- bm->stride, dst_x + r[j].x0, dst_y + r[j].y0, color);
- if (!img) break;
- *tail = img;
- tail = &img->next;
- }
- if (lbrk < r[j].x1) {
- if (lbrk < r[j].x0) lbrk = r[j].x0;
- img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->stride + lbrk,
- r[j].x1 - lbrk, r[j].y1 - r[j].y0,
- bm->stride, dst_x + lbrk, dst_y + r[j].y0, color2);
- if (!img) break;
- *tail = img;
- tail = &img->next;
- }
- }
-
- return tail;
-}
-
-/**
- * \brief convert bitmap glyph into ASS_Image struct(s)
- * \param bit freetype bitmap glyph, FT_PIXEL_MODE_GRAY
- * \param dst_x bitmap x coordinate in video frame
- * \param dst_y bitmap y coordinate in video frame
- * \param color first color, RGBA
- * \param color2 second color, RGBA
- * \param brk x coordinate relative to glyph origin, color is used to the left of brk, color2 - to the right
- * \param tail pointer to the last image's next field, head of the generated list should be stored here
- * \return pointer to the new list tail
- * Performs clipping. Uses my_draw_bitmap for actual bitmap convertion.
- */
-static ASS_Image **
-render_glyph(ASS_Renderer *render_priv, Bitmap *bm, int dst_x, int dst_y,
- uint32_t color, uint32_t color2, int brk, ASS_Image **tail)
-{
-
- // brk is relative to dst_x
- // color = color left of brk
- // color2 = color right of brk
- int b_x0, b_y0, b_x1, b_y1; // visible part of the bitmap
- int clip_x0, clip_y0, clip_x1, clip_y1;
- int tmp;
- ASS_Image *img;
-
- // Inverse clipping in use?
- if (render_priv->state.clip_mode)
- return render_glyph_i(render_priv, bm, dst_x, dst_y, color, color2,
- brk, tail);
-
- dst_x += bm->left;
- dst_y += bm->top;
- brk -= bm->left;
-
- // clipping
- clip_x0 = FFMINMAX(render_priv->state.clip_x0, 0, render_priv->width);
- clip_y0 = FFMINMAX(render_priv->state.clip_y0, 0, render_priv->height);
- clip_x1 = FFMINMAX(render_priv->state.clip_x1, 0, render_priv->width);
- clip_y1 = FFMINMAX(render_priv->state.clip_y1, 0, render_priv->height);
- b_x0 = 0;
- b_y0 = 0;
- b_x1 = bm->w;
- b_y1 = bm->h;
-
- tmp = dst_x - clip_x0;
- if (tmp < 0) {
- ass_msg(render_priv->library, MSGL_DBG2, "clip left");
- b_x0 = -tmp;
- }
- tmp = dst_y - clip_y0;
- if (tmp < 0) {
- ass_msg(render_priv->library, MSGL_DBG2, "clip top");
- b_y0 = -tmp;
- }
- tmp = clip_x1 - dst_x - bm->w;
- if (tmp < 0) {
- ass_msg(render_priv->library, MSGL_DBG2, "clip right");
- b_x1 = bm->w + tmp;
- }
- tmp = clip_y1 - dst_y - bm->h;
- if (tmp < 0) {
- ass_msg(render_priv->library, MSGL_DBG2, "clip bottom");
- b_y1 = bm->h + tmp;
- }
-
- if ((b_y0 >= b_y1) || (b_x0 >= b_x1))
- return tail;
-
- if (brk > b_x0) { // draw left part
- if (brk > b_x1)
- brk = b_x1;
- img = my_draw_bitmap(bm->buffer + bm->stride * b_y0 + b_x0,
- brk - b_x0, b_y1 - b_y0, bm->stride,
- dst_x + b_x0, dst_y + b_y0, color);
- if (!img) return tail;
- *tail = img;
- tail = &img->next;
- }
- if (brk < b_x1) { // draw right part
- if (brk < b_x0)
- brk = b_x0;
- img = my_draw_bitmap(bm->buffer + bm->stride * b_y0 + brk,
- b_x1 - brk, b_y1 - b_y0, bm->stride,
- dst_x + brk, dst_y + b_y0, color2);
- if (!img) return tail;
- *tail = img;
- tail = &img->next;
- }
- return tail;
-}
-
-/**
- * \brief Replace the bitmap buffer in ASS_Image with a copy
- * \param img ASS_Image to operate on
- * \return pointer to old bitmap buffer
- */
-static unsigned char *clone_bitmap_buffer(ASS_Image *img)
-{
- unsigned char *old_bitmap = img->bitmap;
- int size = img->stride * (img->h - 1) + img->w;
- img->bitmap = malloc(size);
- memcpy(img->bitmap, old_bitmap, size);
- return old_bitmap;
-}
-
-/**
- * \brief Calculate overlapping area of two consecutive bitmaps and in case they
- * overlap, blend them together
- * Mainly useful for translucent glyphs and especially borders, to avoid the
- * luminance adding up where they overlap (which looks ugly)
- */
-static void
-render_overlap(ASS_Renderer *render_priv, ASS_Image **last_tail,
- ASS_Image **tail)
-{
- int left, top, bottom, right;
- int old_left, old_top, w, h, cur_left, cur_top;
- int x, y, opos, cpos;
- char m;
- CompositeHashKey hk;
- CompositeHashValue *hv;
- CompositeHashValue chv;
- int ax = (*last_tail)->dst_x;
- int ay = (*last_tail)->dst_y;
- int aw = (*last_tail)->w;
- int as = (*last_tail)->stride;
- int ah = (*last_tail)->h;
- int bx = (*tail)->dst_x;
- int by = (*tail)->dst_y;
- int bw = (*tail)->w;
- int bs = (*tail)->stride;
- int bh = (*tail)->h;
- unsigned char *a;
- unsigned char *b;
-
- if ((*last_tail)->bitmap == (*tail)->bitmap)
- return;
-
- if ((*last_tail)->color != (*tail)->color)
- return;
-
- // Calculate overlap coordinates
- left = (ax > bx) ? ax : bx;
- top = (ay > by) ? ay : by;
- right = ((ax + aw) < (bx + bw)) ? (ax + aw) : (bx + bw);
- bottom = ((ay + ah) < (by + bh)) ? (ay + ah) : (by + bh);
- if ((right <= left) || (bottom <= top))
- return;
- old_left = left - ax;
- old_top = top - ay;
- w = right - left;
- h = bottom - top;
- cur_left = left - bx;
- cur_top = top - by;
-
- // Query cache
- hk.a = (*last_tail)->bitmap;
- hk.b = (*tail)->bitmap;
- hk.aw = aw;
- hk.ah = ah;
- hk.bw = bw;
- hk.bh = bh;
- hk.ax = ax;
- hk.ay = ay;
- hk.bx = bx;
- hk.by = by;
- hk.as = as;
- hk.bs = bs;
- hv = ass_cache_get(render_priv->cache.composite_cache, &hk);
- if (hv) {
- (*last_tail)->bitmap = hv->a;
- (*tail)->bitmap = hv->b;
- return;
- }
- // Allocate new bitmaps and copy over data
- a = clone_bitmap_buffer(*last_tail);
- b = clone_bitmap_buffer(*tail);
-
- // Blend overlapping area
- for (y = 0; y < h; y++)
- for (x = 0; x < w; x++) {
- opos = (old_top + y) * (as) + (old_left + x);
- cpos = (cur_top + y) * (bs) + (cur_left + x);
- m = FFMIN(a[opos] + b[cpos], 0xff);
- (*last_tail)->bitmap[opos] = 0;
- (*tail)->bitmap[cpos] = m;
- }
-
- // Insert bitmaps into the cache
- chv.a = (*last_tail)->bitmap;
- chv.b = (*tail)->bitmap;
- ass_cache_put(render_priv->cache.composite_cache, &hk, &chv);
-}
-
-static void free_list_add(ASS_Renderer *render_priv, void *object)
-{
- if (!render_priv->free_head) {
- render_priv->free_head = calloc(1, sizeof(FreeList));
- render_priv->free_head->object = object;
- render_priv->free_tail = render_priv->free_head;
- } else {
- FreeList *l = calloc(1, sizeof(FreeList));
- l->object = object;
- render_priv->free_tail->next = l;
- render_priv->free_tail = render_priv->free_tail->next;
- }
-}
-
-/**
- * Iterate through a list of bitmaps and blend with clip vector, if
- * applicable. The blended bitmaps are added to a free list which is freed
- * at the start of a new frame.
- */
-static void blend_vector_clip(ASS_Renderer *render_priv,
- ASS_Image *head)
-{
- FT_Outline *outline;
- Bitmap *clip_bm = NULL;
- ASS_Image *cur;
- ASS_Drawing *drawing = render_priv->state.clip_drawing;
- BitmapHashKey key;
- BitmapHashValue *val;
-
- if (!drawing)
- return;
-
- // Try to get mask from cache
- memset(&key, 0, sizeof(key));
- key.type = BITMAP_CLIP;
- key.u.clip.text = drawing->text;
- val = ass_cache_get(render_priv->cache.bitmap_cache, &key);
-
- if (val) {
- clip_bm = val->bm;
- } else {
- BitmapHashValue v;
-
- // Not found in cache, parse and rasterize it
- outline = ass_drawing_parse(drawing, 1);
- if (!outline) {
- ass_msg(render_priv->library, MSGL_WARN,
- "Clip vector parsing failed. Skipping.");
- goto blend_vector_error;
- }
-
- // We need to translate the clip according to screen borders
- if (render_priv->settings.left_margin != 0 ||
- render_priv->settings.top_margin != 0) {
- FT_Vector trans;
- trans.x = int_to_d6(render_priv->settings.left_margin);
- trans.y = -int_to_d6(render_priv->settings.top_margin);
- FT_Outline_Translate(outline, trans.x, trans.y);
- }
-
- ass_msg(render_priv->library, MSGL_DBG2,
- "Parsed vector clip: scales (%f, %f) string [%s]\n",
- drawing->scale_x, drawing->scale_y, drawing->text);
-
- clip_bm = outline_to_bitmap(render_priv->library,
- render_priv->ftlibrary, outline, 0);
- if (clip_bm == NULL) {
- ass_msg(render_priv->library, MSGL_WARN,
- "Clip vector rasterization failed. Skipping.");
- }
-
- // Add to cache
- memset(&v, 0, sizeof(v));
- key.u.clip.text = strdup(drawing->text);
- v.bm = clip_bm;
- ass_cache_put(render_priv->cache.bitmap_cache, &key, &v);
- }
-blend_vector_error:
-
- if (!clip_bm) goto blend_vector_exit;
-
- // Iterate through bitmaps and blend/clip them
- for (cur = head; cur; cur = cur->next) {
- int left, top, right, bottom, apos, bpos, y, x, w, h;
- int ax, ay, aw, ah, as;
- int bx, by, bw, bh, bs;
- int aleft, atop, bleft, btop;
- unsigned char *abuffer, *bbuffer, *nbuffer;
-
- abuffer = cur->bitmap;
- bbuffer = clip_bm->buffer;
- ax = cur->dst_x;
- ay = cur->dst_y;
- aw = cur->w;
- ah = cur->h;
- as = cur->stride;
- bx = clip_bm->left;
- by = clip_bm->top;
- bw = clip_bm->w;
- bh = clip_bm->h;
- bs = clip_bm->stride;
-
- // Calculate overlap coordinates
- left = (ax > bx) ? ax : bx;
- top = (ay > by) ? ay : by;
- right = ((ax + aw) < (bx + bw)) ? (ax + aw) : (bx + bw);
- bottom = ((ay + ah) < (by + bh)) ? (ay + ah) : (by + bh);
- aleft = left - ax;
- atop = top - ay;
- w = right - left;
- h = bottom - top;
- bleft = left - bx;
- btop = top - by;
-
- if (render_priv->state.clip_drawing_mode) {
- // Inverse clip
- if (ax + aw < bx || ay + ah < by || ax > bx + bw ||
- ay > by + bh) {
- continue;
- }
-
- // Allocate new buffer and add to free list
- nbuffer = malloc(as * ah);
- if (!nbuffer) goto blend_vector_exit;
- free_list_add(render_priv, nbuffer);
-
- // Blend together
- memcpy(nbuffer, abuffer, as * (ah - 1) + aw);
- for (y = 0; y < h; y++)
- for (x = 0; x < w; x++) {
- apos = (atop + y) * as + aleft + x;
- bpos = (btop + y) * bs + bleft + x;
- nbuffer[apos] = FFMAX(0, abuffer[apos] - bbuffer[bpos]);
- }
- } else {
- // Regular clip
- if (ax + aw < bx || ay + ah < by || ax > bx + bw ||
- ay > by + bh) {
- cur->w = cur->h = 0;
- continue;
- }
-
- // Allocate new buffer and add to free list
- nbuffer = calloc(as, ah);
- if (!nbuffer) goto blend_vector_exit;
- free_list_add(render_priv, nbuffer);
-
- // Blend together
- for (y = 0; y < h; y++)
- for (x = 0; x < w; x++) {
- apos = (atop + y) * as + aleft + x;
- bpos = (btop + y) * bs + bleft + x;
- nbuffer[apos] = (abuffer[apos] * bbuffer[bpos] + 255) >> 8;
- }
- }
- cur->bitmap = nbuffer;
- }
-
-blend_vector_exit:
- ass_drawing_free(render_priv->state.clip_drawing);
- render_priv->state.clip_drawing = 0;
-}
-
-/**
- * \brief Convert TextInfo struct to ASS_Image list
- * Splits glyphs in halves when needed (for \kf karaoke).
- */
-static ASS_Image *render_text(ASS_Renderer *render_priv, int dst_x, int dst_y)
-{
- int pen_x, pen_y;
- int i;
- Bitmap *bm;
- ASS_Image *head;
- ASS_Image **tail = &head;
- ASS_Image **last_tail = 0;
- ASS_Image **here_tail = 0;
- TextInfo *text_info = &render_priv->text_info;
-
- for (i = 0; i < text_info->length; ++i) {
- GlyphInfo *info = text_info->glyphs + i;
- if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_s
- || (info->shadow_x == 0 && info->shadow_y == 0) || info->skip)
- continue;
-
- while (info) {
- if (!info->bm_s) {
- info = info->next;
- continue;
- }
-
- pen_x =
- dst_x + (info->pos.x >> 6) +
- (int) (info->shadow_x * render_priv->border_scale);
- pen_y =
- dst_y + (info->pos.y >> 6) +
- (int) (info->shadow_y * render_priv->border_scale);
- bm = info->bm_s;
-
- here_tail = tail;
- tail =
- render_glyph(render_priv, bm, pen_x, pen_y, info->c[3], 0,
- 1000000, tail);
-
- if (last_tail && tail != here_tail && ((info->c[3] & 0xff) > 0))
- render_overlap(render_priv, last_tail, here_tail);
- last_tail = here_tail;
-
- info = info->next;
- }
- }
-
- last_tail = 0;
- for (i = 0; i < text_info->length; ++i) {
- GlyphInfo *info = text_info->glyphs + i;
- if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm_o
- || info->skip)
- continue;
-
- while (info) {
- if (!info->bm_o) {
- info = info->next;
- continue;
- }
-
- pen_x = dst_x + (info->pos.x >> 6);
- pen_y = dst_y + (info->pos.y >> 6);
- bm = info->bm_o;
-
- if ((info->effect_type == EF_KARAOKE_KO)
- && (info->effect_timing <= (info->bbox.xMax >> 6))) {
- // do nothing
- } else {
- here_tail = tail;
- tail =
- render_glyph(render_priv, bm, pen_x, pen_y, info->c[2],
- 0, 1000000, tail);
- if (last_tail && tail != here_tail && ((info->c[2] & 0xff) > 0))
- render_overlap(render_priv, last_tail, here_tail);
-
- last_tail = here_tail;
- }
- info = info->next;
- }
- }
-
- for (i = 0; i < text_info->length; ++i) {
- GlyphInfo *info = text_info->glyphs + i;
- if ((info->symbol == 0) || (info->symbol == '\n') || !info->bm
- || info->skip)
- continue;
-
- while (info) {
- if (!info->bm) {
- info = info->next;
- continue;
- }
-
- pen_x = dst_x + (info->pos.x >> 6);
- pen_y = dst_y + (info->pos.y >> 6);
- bm = info->bm;
-
- if ((info->effect_type == EF_KARAOKE)
- || (info->effect_type == EF_KARAOKE_KO)) {
- if (info->effect_timing > (info->bbox.xMax >> 6))
- tail =
- render_glyph(render_priv, bm, pen_x, pen_y,
- info->c[0], 0, 1000000, tail);
- else
- tail =
- render_glyph(render_priv, bm, pen_x, pen_y,
- info->c[1], 0, 1000000, tail);
- } else if (info->effect_type == EF_KARAOKE_KF) {
- tail =
- render_glyph(render_priv, bm, pen_x, pen_y, info->c[0],
- info->c[1], info->effect_timing, tail);
- } else
- tail =
- render_glyph(render_priv, bm, pen_x, pen_y, info->c[0],
- 0, 1000000, tail);
- info = info->next;
- }
- }
-
- *tail = 0;
- blend_vector_clip(render_priv, head);
-
- return head;
-}
-
-static void compute_string_bbox(TextInfo *text, DBBox *bbox)
-{
- int i;
-
- if (text->length > 0) {
- bbox->xMin = 32000;
- bbox->xMax = -32000;
- bbox->yMin = -1 * text->lines[0].asc + d6_to_double(text->glyphs[0].pos.y);
- bbox->yMax = text->height - text->lines[0].asc +
- d6_to_double(text->glyphs[0].pos.y);
-
- for (i = 0; i < text->length; ++i) {
- GlyphInfo *info = text->glyphs + i;
- if (info->skip) continue;
- while (info) {
- double s = d6_to_double(info->pos.x);
- double e = s + d6_to_double(info->advance.x);
- bbox->xMin = FFMIN(bbox->xMin, s);
- bbox->xMax = FFMAX(bbox->xMax, e);
- info = info->next;
- }
- }
- } else
- bbox->xMin = bbox->xMax = bbox->yMin = bbox->yMax = 0.;
-}
-
-/**
- * \brief partially reset render_context to style values
- * Works like {\r}: resets some style overrides
- */
-void reset_render_context(ASS_Renderer *render_priv)
-{
- render_priv->state.c[0] = render_priv->state.style->PrimaryColour;
- render_priv->state.c[1] = render_priv->state.style->SecondaryColour;
- render_priv->state.c[2] = render_priv->state.style->OutlineColour;
- render_priv->state.c[3] = render_priv->state.style->BackColour;
- render_priv->state.flags =
- (render_priv->state.style->Underline ? DECO_UNDERLINE : 0) |
- (render_priv->state.style->StrikeOut ? DECO_STRIKETHROUGH : 0);
- render_priv->state.font_size = render_priv->state.style->FontSize;
-
- free(render_priv->state.family);
- render_priv->state.family = NULL;
- render_priv->state.family = strdup(render_priv->state.style->FontName);
- render_priv->state.treat_family_as_pattern =
- render_priv->state.style->treat_fontname_as_pattern;
- render_priv->state.bold = render_priv->state.style->Bold;
- render_priv->state.italic = render_priv->state.style->Italic;
- update_font(render_priv);
-
- change_border(render_priv, -1., -1.);
- render_priv->state.scale_x = render_priv->state.style->ScaleX;
- render_priv->state.scale_y = render_priv->state.style->ScaleY;
- render_priv->state.hspacing = render_priv->state.style->Spacing;
- render_priv->state.be = 0;
- render_priv->state.blur = 0.0;
- render_priv->state.shadow_x = render_priv->state.style->Shadow;
- render_priv->state.shadow_y = render_priv->state.style->Shadow;
- render_priv->state.frx = render_priv->state.fry = 0.;
- render_priv->state.frz = M_PI * render_priv->state.style->Angle / 180.;
- render_priv->state.fax = render_priv->state.fay = 0.;
- render_priv->state.wrap_style = render_priv->track->WrapStyle;
- render_priv->state.font_encoding = render_priv->state.style->Encoding;
-}
-
-/**
- * \brief Start new event. Reset render_priv->state.
- */
-static void
-init_render_context(ASS_Renderer *render_priv, ASS_Event *event)
-{
- render_priv->state.event = event;
- render_priv->state.style = render_priv->track->styles + event->Style;
- render_priv->state.parsed_tags = 0;
-
- reset_render_context(render_priv);
-
- render_priv->state.evt_type = EVENT_NORMAL;
- render_priv->state.alignment = render_priv->state.style->Alignment;
- render_priv->state.pos_x = 0;
- render_priv->state.pos_y = 0;
- render_priv->state.org_x = 0;
- render_priv->state.org_y = 0;
- render_priv->state.have_origin = 0;
- render_priv->state.clip_x0 = 0;
- render_priv->state.clip_y0 = 0;
- render_priv->state.clip_x1 = render_priv->track->PlayResX;
- render_priv->state.clip_y1 = render_priv->track->PlayResY;
- render_priv->state.clip_mode = 0;
- render_priv->state.detect_collisions = 1;
- render_priv->state.fade = 0;
- render_priv->state.drawing_mode = 0;
- render_priv->state.effect_type = EF_NONE;
- render_priv->state.effect_timing = 0;
- render_priv->state.effect_skip_timing = 0;
- render_priv->state.bm_run_id = 0;
- ass_drawing_free(render_priv->state.drawing);
- render_priv->state.drawing = ass_drawing_new(render_priv->library,
- render_priv->ftlibrary);
-
- apply_transition_effects(render_priv, event);
-}
-
-static void free_render_context(ASS_Renderer *render_priv)
-{
- free(render_priv->state.family);
- ass_drawing_free(render_priv->state.drawing);
-
- render_priv->state.family = NULL;
- render_priv->state.drawing = NULL;
-}
-
-/*
- * Replace the outline of a glyph by a contour which makes up a simple
- * opaque rectangle.
- */
-static void draw_opaque_box(ASS_Renderer *render_priv, int asc, int desc,
- FT_Outline *ol, FT_Vector advance, int sx, int sy)
-{
- int i;
- int adv = advance.x;
- double scale_y = render_priv->state.scale_y;
- double scale_x = render_priv->state.scale_x;
- FT_Vector points[4];
-
- // to avoid gaps
- sx = FFMAX(64, sx);
- sy = FFMAX(64, sy);
-
- // Emulate the WTFish behavior of VSFilter, i.e. double-scale
- // the sizes of the opaque box.
- adv += double_to_d6(render_priv->state.hspacing * render_priv->font_scale
- * scale_x);
- adv *= scale_x;
- sx *= scale_x;
- sy *= scale_y;
- desc *= scale_y;
- desc += asc * (scale_y - 1.0);
-
- points[0].x = -sx;
- points[0].y = asc + sy;
- points[1].x = adv + sx;
- points[1].y = asc + sy;
- points[2].x = adv + sx;
- points[2].y = -desc - sy;
- points[3].x = -sx;
- points[3].y = -desc - sy;
-
- FT_Outline_New(render_priv->ftlibrary, 4, 1, ol);
-
- ol->n_points = ol->n_contours = 0;
- for (i = 0; i < 4; i++) {
- ol->points[ol->n_points] = points[i];
- ol->tags[ol->n_points++] = 1;
- }
- ol->contours[ol->n_contours++] = ol->n_points - 1;
-}
-
-/*
- * Stroke an outline glyph in x/y direction. Applies various fixups to get
- * around limitations of the FreeType stroker.
- */
-static void stroke_outline(ASS_Renderer *render_priv, FT_Outline *outline,
- int sx, int sy)
-{
- if (sx <= 0 && sy <= 0)
- return;
-
- fix_freetype_stroker(outline, sx, sy);
-
- // Borders are equal; use the regular stroker
- if (sx == sy && render_priv->state.stroker) {
- int error;
- unsigned n_points, n_contours;
-
- FT_StrokerBorder border = FT_Outline_GetOutsideBorder(outline);
- error = FT_Stroker_ParseOutline(render_priv->state.stroker, outline, 0);
- if (error) {
- ass_msg(render_priv->library, MSGL_WARN,
- "FT_Stroker_ParseOutline failed, error: %d", error);
- }
- error = FT_Stroker_GetBorderCounts(render_priv->state.stroker, border,
- &n_points, &n_contours);
- if (error) {
- ass_msg(render_priv->library, MSGL_WARN,
- "FT_Stroker_GetBorderCounts failed, error: %d", error);
- }
- FT_Outline_Done(render_priv->ftlibrary, outline);
- FT_Outline_New(render_priv->ftlibrary, n_points, n_contours, outline);
- outline->n_points = outline->n_contours = 0;
- FT_Stroker_ExportBorder(render_priv->state.stroker, border, outline);
-
- // "Stroke" with the outline emboldener in two passes.
- // The outlines look uglier, but the emboldening never adds any points
- } else {
- int i;
- FT_Outline nol;
-
- FT_Outline_New(render_priv->ftlibrary, outline->n_points,
- outline->n_contours, &nol);
- FT_Outline_Copy(outline, &nol);
-
- FT_Outline_Embolden(outline, sx * 2);
- FT_Outline_Translate(outline, -sx, -sx);
- FT_Outline_Embolden(&nol, sy * 2);
- FT_Outline_Translate(&nol, -sy, -sy);
-
- for (i = 0; i < outline->n_points; i++)
- outline->points[i].y = nol.points[i].y;
-
- FT_Outline_Done(render_priv->ftlibrary, &nol);
- }
-}
-
-/**
- * \brief Prepare glyph hash
- */
-static void
-fill_glyph_hash(ASS_Renderer *priv, OutlineHashKey *outline_key,
- GlyphInfo *info)
-{
- if (info->drawing) {
- DrawingHashKey *key = &outline_key->u.drawing;
- outline_key->type = OUTLINE_DRAWING;
- key->scale_x = double_to_d16(info->scale_x);
- key->scale_y = double_to_d16(info->scale_y);
- key->outline.x = double_to_d16(info->border_x);
- key->outline.y = double_to_d16(info->border_y);
- key->border_style = priv->state.style->BorderStyle;
- key->hash = info->drawing->hash;
- key->text = info->drawing->text;
- key->pbo = info->drawing->pbo;
- key->scale = info->drawing->scale;
- } else {
- GlyphHashKey *key = &outline_key->u.glyph;
- outline_key->type = OUTLINE_GLYPH;
- key->font = info->font;
- key->size = info->font_size;
- key->face_index = info->face_index;
- key->glyph_index = info->glyph_index;
- key->bold = info->bold;
- key->italic = info->italic;
- key->scale_x = double_to_d16(info->scale_x);
- key->scale_y = double_to_d16(info->scale_y);
- key->outline.x = double_to_d16(info->border_x);
- key->outline.y = double_to_d16(info->border_y);
- key->flags = info->flags;
- key->border_style = priv->state.style->BorderStyle;
- }
-}
-
-/**
- * \brief Get normal and outline (border) glyphs
- * \param info out: struct filled with extracted data
- * Tries to get both glyphs from cache.
- * If they can't be found, gets a glyph from font face, generates outline with FT_Stroker,
- * and add them to cache.
- * The glyphs are returned in info->glyph and info->outline_glyph
- */
-static void
-get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info)
-{
- OutlineHashValue *val;
- OutlineHashKey key;
-
- memset(&info->hash_key, 0, sizeof(key));
-
- fill_glyph_hash(priv, &key, info);
- val = ass_cache_get(priv->cache.outline_cache, &key);
-
- if (!val) {
- OutlineHashValue v;
- memset(&v, 0, sizeof(v));
-
- if (info->drawing) {
- ASS_Drawing *drawing = info->drawing;
- ass_drawing_hash(drawing);
- if(!ass_drawing_parse(drawing, 0))
- return;
- outline_copy(priv->ftlibrary, &drawing->outline,
- &v.outline);
- v.advance.x = drawing->advance.x;
- v.advance.y = drawing->advance.y;
- v.asc = drawing->asc;
- v.desc = drawing->desc;
- key.u.drawing.text = strdup(drawing->text);
- } else {
- FT_Glyph glyph;
- ass_face_set_size(info->font->faces[info->face_index],
- info->font_size);
- ass_font_set_transform(info->font, info->scale_x,
- info->scale_y, NULL);
- glyph =
- ass_font_get_glyph(priv->fontconfig_priv, info->font,
- info->symbol, info->face_index, info->glyph_index,
- priv->settings.hinting, info->flags);
- if (glyph != NULL) {
- outline_copy(priv->ftlibrary,
- &((FT_OutlineGlyph)glyph)->outline, &v.outline);
- if (priv->settings.shaper == ASS_SHAPING_SIMPLE) {
- v.advance.x = d16_to_d6(glyph->advance.x);
- v.advance.y = d16_to_d6(glyph->advance.y);
- }
- FT_Done_Glyph(glyph);
- ass_font_get_asc_desc(info->font, info->symbol,
- &v.asc, &v.desc);
- v.asc *= info->scale_y;
- v.desc *= info->scale_y;
- }
- }
-
- if (!v.outline)
- return;
-
- FT_Outline_Get_CBox(v.outline, &v.bbox_scaled);
-
- if (priv->state.style->BorderStyle == 3 &&
- (info->border_x > 0 || info->border_y > 0)) {
- FT_Vector advance;
-
- v.border = calloc(1, sizeof(FT_Outline));
-
- if (priv->settings.shaper == ASS_SHAPING_SIMPLE || info->drawing)
- advance = v.advance;
- else
- advance = info->advance;
-
- draw_opaque_box(priv, v.asc, v.desc, v.border, advance,
- double_to_d6(info->border_x * priv->border_scale),
- double_to_d6(info->border_y * priv->border_scale));
-
- } else if ((info->border_x > 0 || info->border_y > 0)
- && double_to_d6(info->scale_x) && double_to_d6(info->scale_y)) {
-
- outline_copy(priv->ftlibrary, v.outline, &v.border);
- stroke_outline(priv, v.border,
- double_to_d6(info->border_x * priv->border_scale),
- double_to_d6(info->border_y * priv->border_scale));
- }
-
- v.lib = priv->ftlibrary;
- val = ass_cache_put(priv->cache.outline_cache, &key, &v);
- }
-
- info->hash_key.u.outline.outline = val;
- info->outline = val->outline;
- info->border = val->border;
- info->bbox = val->bbox_scaled;
- if (info->drawing || priv->settings.shaper == ASS_SHAPING_SIMPLE) {
- info->cluster_advance.x = info->advance.x = val->advance.x;
- info->cluster_advance.y = info->advance.y = val->advance.y;
- }
- info->asc = val->asc;
- info->desc = val->desc;
-
- ass_drawing_free(info->drawing);
-}
-
-/**
- * \brief Apply transformation to outline points of a glyph
- * Applies rotations given by frx, fry and frz and projects the points back
- * onto the screen plane.
- */
-static void
-transform_3d_points(FT_Vector shift, FT_Outline *outline, double frx, double fry,
- double frz, double fax, double fay, double scale,
- int yshift)
-{
- double sx = sin(frx);
- double sy = sin(fry);
- double sz = sin(frz);
- double cx = cos(frx);
- double cy = cos(fry);
- double cz = cos(frz);
- FT_Vector *p = outline->points;
- double x, y, z, xx, yy, zz;
- int i, dist;
-
- dist = 20000 * scale;
- for (i = 0; i < outline->n_points; i++) {
- x = (double) p[i].x + shift.x + (fax * (yshift - p[i].y));
- y = (double) p[i].y + shift.y + (-fay * p[i].x);
- z = 0.;
-
- xx = x * cz + y * sz;
- yy = -(x * sz - y * cz);
- zz = z;
-
- x = xx;
- y = yy * cx + zz * sx;
- z = yy * sx - zz * cx;
-
- xx = x * cy + z * sy;
- yy = y;
- zz = x * sy - z * cy;
-
- zz = FFMAX(zz, 1000 - dist);
-
- x = (xx * dist) / (zz + dist);
- y = (yy * dist) / (zz + dist);
- p[i].x = x - shift.x + 0.5;
- p[i].y = y - shift.y + 0.5;
- }
-}
-
-/**
- * \brief Apply 3d transformation to several objects
- * \param shift FreeType vector
- * \param glyph FreeType glyph
- * \param glyph2 FreeType glyph
- * \param frx x-axis rotation angle
- * \param fry y-axis rotation angle
- * \param frz z-axis rotation angle
- * Rotates both glyphs by frx, fry and frz. Shift vector is added before rotation and subtracted after it.
- */
-static void
-transform_3d(FT_Vector shift, FT_Outline *outline, FT_Outline *border,
- double frx, double fry, double frz, double fax, double fay,
- double scale, int yshift)
-{
- frx = -frx;
- frz = -frz;
- if (frx != 0. || fry != 0. || frz != 0. || fax != 0. || fay != 0.) {
- if (outline)
- transform_3d_points(shift, outline, frx, fry, frz,
- fax, fay, scale, yshift);
-
- if (border)
- transform_3d_points(shift, border, frx, fry, frz,
- fax, fay, scale, yshift);
- }
-}
-
-/**
- * \brief Get bitmaps for a glyph
- * \param info glyph info
- * Tries to get glyph bitmaps from bitmap cache.
- * If they can't be found, they are generated by rotating and rendering the glyph.
- * After that, bitmaps are added to the cache.
- * They are returned in info->bm (glyph), info->bm_o (outline) and info->bm_s (shadow).
- */
-static void
-get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info)
-{
- BitmapHashValue *val;
- OutlineBitmapHashKey *key = &info->hash_key.u.outline;
-
- if (!info->outline || info->symbol == '\n' || info->symbol == 0 || info->skip)
- return;
-
- val = ass_cache_get(render_priv->cache.bitmap_cache, &info->hash_key);
-
- if (!val) {
- FT_Vector shift;
- BitmapHashValue hash_val;
- int error;
- double fax_scaled, fay_scaled;
- FT_Outline *outline, *border;
- double scale_x = render_priv->font_scale_x;
- FT_Matrix m;
-
- hash_val.bm = hash_val.bm_o = hash_val.bm_s = 0;
-
- outline_copy(render_priv->ftlibrary, info->outline, &outline);
- outline_copy(render_priv->ftlibrary, info->border, &border);
-
- // calculating rotation shift vector (from rotation origin to the glyph basepoint)
- shift.x = key->shift_x;
- shift.y = key->shift_y;
- fax_scaled = info->fax * render_priv->state.scale_x;
- fay_scaled = info->fay * render_priv->state.scale_y;
-
- // apply rotation
- transform_3d(shift, outline, border,
- info->frx, info->fry, info->frz, fax_scaled,
- fay_scaled, render_priv->font_scale, info->asc);
-
- // PAR correction scaling
- m.xx = double_to_d16(scale_x);
- m.xy = 0;
- m.yx = 0;
- m.yy = double_to_d16(1.0);
-
- // subpixel shift
- if (outline) {
- if (scale_x != 1.0)
- FT_Outline_Transform(outline, &m);
- FT_Outline_Translate(outline, key->advance.x, -key->advance.y);
- }
- if (border) {
- if (scale_x != 1.0)
- FT_Outline_Transform(border, &m);
- FT_Outline_Translate(border, key->advance.x, -key->advance.y);
- }
-
- // render glyph
- error = outline_to_bitmap3(render_priv->library,
- render_priv->synth_priv,
- render_priv->ftlibrary,
- outline, border,
- &hash_val.bm, &hash_val.bm_o,
- &hash_val.bm_s, info->be,
- info->blur * render_priv->border_scale,
- key->shadow_offset,
- render_priv->state.style->BorderStyle);
- if (error)
- info->symbol = 0;
-
- val = ass_cache_put(render_priv->cache.bitmap_cache, &info->hash_key,
- &hash_val);
-
- outline_free(render_priv->ftlibrary, outline);
- outline_free(render_priv->ftlibrary, border);
- }
-
- info->bm = val->bm;
- info->bm_o = val->bm_o;
- info->bm_s = val->bm_s;
-
- // VSFilter compatibility: invisible fill and no border?
- // In this case no shadow is supposed to be rendered.
- if (!info->border && (info->c[0] & 0xFF) == 0xFF)
- info->bm_s = 0;
-}
-
-/**
- * This function goes through text_info and calculates text parameters.
- * The following text_info fields are filled:
- * height
- * lines[].height
- * lines[].asc
- * lines[].desc
- */
-static void measure_text(ASS_Renderer *render_priv)
-{
- TextInfo *text_info = &render_priv->text_info;
- int cur_line = 0;
- double max_asc = 0., max_desc = 0.;
- GlyphInfo *last = NULL;
- int i;
- int empty_line = 1;
- text_info->height = 0.;
- for (i = 0; i < text_info->length + 1; ++i) {
- if ((i == text_info->length) || text_info->glyphs[i].linebreak) {
- if (empty_line && cur_line > 0 && last && i < text_info->length) {
- max_asc = d6_to_double(last->asc) / 2.0;
- max_desc = d6_to_double(last->desc) / 2.0;
- }
- text_info->lines[cur_line].asc = max_asc;
- text_info->lines[cur_line].desc = max_desc;
- text_info->height += max_asc + max_desc;
- cur_line++;
- max_asc = max_desc = 0.;
- empty_line = 1;
- } else
- empty_line = 0;
- if (i < text_info->length) {
- GlyphInfo *cur = text_info->glyphs + i;
- if (d6_to_double(cur->asc) > max_asc)
- max_asc = d6_to_double(cur->asc);
- if (d6_to_double(cur->desc) > max_desc)
- max_desc = d6_to_double(cur->desc);
- if (cur->symbol != '\n' && cur->symbol != 0)
- last = cur;
- }
- }
- text_info->height +=
- (text_info->n_lines -
- 1) * render_priv->settings.line_spacing;
-}
-
-/**
- * Mark extra whitespace for later removal.
- */
-#define IS_WHITESPACE(x) ((x->symbol == ' ' || x->symbol == '\n') \
- && !x->linebreak)
-static void trim_whitespace(ASS_Renderer *render_priv)
-{
- int i, j;
- GlyphInfo *cur;
- TextInfo *ti = &render_priv->text_info;
-
- // Mark trailing spaces
- i = ti->length - 1;
- cur = ti->glyphs + i;
- while (i && IS_WHITESPACE(cur)) {
- cur->skip++;
- cur = ti->glyphs + --i;
- }
-
- // Mark leading whitespace
- i = 0;
- cur = ti->glyphs;
- while (i < ti->length && IS_WHITESPACE(cur)) {
- cur->skip++;
- cur = ti->glyphs + ++i;
- }
-
- // Mark all extraneous whitespace inbetween
- for (i = 0; i < ti->length; ++i) {
- cur = ti->glyphs + i;
- if (cur->linebreak) {
- // Mark whitespace before
- j = i - 1;
- cur = ti->glyphs + j;
- while (j && IS_WHITESPACE(cur)) {
- cur->skip++;
- cur = ti->glyphs + --j;
- }
- // A break itself can contain a whitespace, too
- cur = ti->glyphs + i;
- if (cur->symbol == ' ') {
- cur->skip++;
- // Mark whitespace after
- j = i + 1;
- cur = ti->glyphs + j;
- while (j < ti->length && IS_WHITESPACE(cur)) {
- cur->skip++;
- cur = ti->glyphs + ++j;
- }
- i = j - 1;
- }
- }
- }
-}
-#undef IS_WHITESPACE
-
-/**
- * \brief rearrange text between lines
- * \param max_text_width maximal text line width in pixels
- * The algo is similar to the one in libvo/sub.c:
- * 1. Place text, wrapping it when current line is full
- * 2. Try moving words from the end of a line to the beginning of the next one while it reduces
- * the difference in lengths between this two lines.
- * The result may not be optimal, but usually is good enough.
- *
- * FIXME: implement style 0 and 3 correctly
- */
-static void
-wrap_lines_smart(ASS_Renderer *render_priv, double max_text_width)
-{
- int i;
- GlyphInfo *cur, *s1, *e1, *s2, *s3, *w;
- int last_space;
- int break_type;
- int exit;
- double pen_shift_x;
- double pen_shift_y;
- int cur_line;
- int run_offset;
- TextInfo *text_info = &render_priv->text_info;
-
- last_space = -1;
- text_info->n_lines = 1;
- break_type = 0;
- s1 = text_info->glyphs; // current line start
- for (i = 0; i < text_info->length; ++i) {
- int break_at = -1;
- double s_offset, len;
- cur = text_info->glyphs + i;
- s_offset = d6_to_double(s1->bbox.xMin + s1->pos.x);
- len = d6_to_double(cur->bbox.xMax + cur->pos.x) - s_offset;
-
- if (cur->symbol == '\n') {
- break_type = 2;
- break_at = i;
- ass_msg(render_priv->library, MSGL_DBG2,
- "forced line break at %d", break_at);
- } else if (cur->symbol == ' ') {
- last_space = i;
- } else if (len >= max_text_width
- && (render_priv->state.wrap_style != 2)) {
- break_type = 1;
- break_at = last_space;
- if (break_at >= 0)
- ass_msg(render_priv->library, MSGL_DBG2, "line break at %d",
- break_at);
- }
-
- if (break_at != -1) {
- // need to use one more line
- // marking break_at+1 as start of a new line
- int lead = break_at + 1; // the first symbol of the new line
- if (text_info->n_lines >= text_info->max_lines) {
- // Raise maximum number of lines
- text_info->max_lines *= 2;
- text_info->lines = realloc(text_info->lines,
- sizeof(LineInfo) *
- text_info->max_lines);
- }
- if (lead < text_info->length) {
- text_info->glyphs[lead].linebreak = break_type;
- last_space = -1;
- s1 = text_info->glyphs + lead;
- s_offset = d6_to_double(s1->bbox.xMin + s1->pos.x);
- text_info->n_lines++;
- }
- }
- }
-#define DIFF(x,y) (((x) < (y)) ? (y - x) : (x - y))
- exit = 0;
- while (!exit && render_priv->state.wrap_style != 1) {
- exit = 1;
- w = s3 = text_info->glyphs;
- s1 = s2 = 0;
- for (i = 0; i <= text_info->length; ++i) {
- cur = text_info->glyphs + i;
- if ((i == text_info->length) || cur->linebreak) {
- s1 = s2;
- s2 = s3;
- s3 = cur;
- if (s1 && (s2->linebreak == 1)) { // have at least 2 lines, and linebreak is 'soft'
- double l1, l2, l1_new, l2_new;
-
- w = s2;
- do {
- --w;
- } while ((w > s1) && (w->symbol == ' '));
- while ((w > s1) && (w->symbol != ' ')) {
- --w;
- }
- e1 = w;
- while ((e1 > s1) && (e1->symbol == ' ')) {
- --e1;
- }
- if (w->symbol == ' ')
- ++w;
-
- l1 = d6_to_double(((s2 - 1)->bbox.xMax + (s2 - 1)->pos.x) -
- (s1->bbox.xMin + s1->pos.x));
- l2 = d6_to_double(((s3 - 1)->bbox.xMax + (s3 - 1)->pos.x) -
- (s2->bbox.xMin + s2->pos.x));
- l1_new = d6_to_double(
- (e1->bbox.xMax + e1->pos.x) -
- (s1->bbox.xMin + s1->pos.x));
- l2_new = d6_to_double(
- ((s3 - 1)->bbox.xMax + (s3 - 1)->pos.x) -
- (w->bbox.xMin + w->pos.x));
-
- if (DIFF(l1_new, l2_new) < DIFF(l1, l2)) {
- w->linebreak = 1;
- s2->linebreak = 0;
- exit = 0;
- }
- }
- }
- if (i == text_info->length)
- break;
- }
-
- }
- assert(text_info->n_lines >= 1);
-#undef DIFF
-
- measure_text(render_priv);
- trim_whitespace(render_priv);
-
- pen_shift_x = 0.;
- pen_shift_y = 0.;
- cur_line = 1;
- run_offset = 0;
-
- i = 0;
- cur = text_info->glyphs + i;
- while (i < text_info->length && cur->skip)
- cur = text_info->glyphs + ++i;
- pen_shift_x = d6_to_double(-cur->pos.x);
-
- for (i = 0; i < text_info->length; ++i) {
- cur = text_info->glyphs + i;
- if (cur->linebreak) {
- double height;
- while (i < text_info->length && cur->skip && cur->symbol != '\n')
- cur = text_info->glyphs + ++i;
- height =
- text_info->lines[cur_line - 1].desc +
- text_info->lines[cur_line].asc;
- text_info->lines[cur_line - 1].len = i -
- text_info->lines[cur_line - 1].offset;
- text_info->lines[cur_line].offset = i;
- cur_line++;
- run_offset++;
- pen_shift_x = d6_to_double(-cur->pos.x);
- pen_shift_y += height + render_priv->settings.line_spacing;
- ass_msg(render_priv->library, MSGL_DBG2,
- "shifting from %d to %d by (%f, %f)", i,
- text_info->length - 1, pen_shift_x, pen_shift_y);
- }
- cur->bm_run_id += run_offset;
- cur->pos.x += double_to_d6(pen_shift_x);
- cur->pos.y += double_to_d6(pen_shift_y);
- }
- text_info->lines[cur_line - 1].len =
- text_info->length - text_info->lines[cur_line - 1].offset;
-
-#if 0
- // print line info
- for (i = 0; i < text_info->n_lines; i++) {
- printf("line %d offset %d length %d\n", i, text_info->lines[i].offset,
- text_info->lines[i].len);
- }
-#endif
-}
-
-/**
- * \brief Calculate base point for positioning and rotation
- * \param bbox text bbox
- * \param alignment alignment
- * \param bx, by out: base point coordinates
- */
-static void get_base_point(DBBox *bbox, int alignment, double *bx, double *by)
-{
- const int halign = alignment & 3;
- const int valign = alignment & 12;
- if (bx)
- switch (halign) {
- case HALIGN_LEFT:
- *bx = bbox->xMin;
- break;
- case HALIGN_CENTER:
- *bx = (bbox->xMax + bbox->xMin) / 2.0;
- break;
- case HALIGN_RIGHT:
- *bx = bbox->xMax;
- break;
- }
- if (by)
- switch (valign) {
- case VALIGN_TOP:
- *by = bbox->yMin;
- break;
- case VALIGN_CENTER:
- *by = (bbox->yMax + bbox->yMin) / 2.0;
- break;
- case VALIGN_SUB:
- *by = bbox->yMax;
- break;
- }
-}
-
-/**
- * Prepare bitmap hash key of a glyph
- */
-static void
-fill_bitmap_hash(ASS_Renderer *priv, GlyphInfo *info,
- OutlineBitmapHashKey *hash_key)
-{
- hash_key->frx = rot_key(info->frx);
- hash_key->fry = rot_key(info->fry);
- hash_key->frz = rot_key(info->frz);
- hash_key->fax = double_to_d16(info->fax);
- hash_key->fay = double_to_d16(info->fay);
- hash_key->be = info->be;
- hash_key->blur = info->blur;
- hash_key->shadow_offset.x = double_to_d6(
- info->shadow_x * priv->border_scale -
- (int) (info->shadow_x * priv->border_scale));
- hash_key->shadow_offset.y = double_to_d6(
- info->shadow_y * priv->border_scale -
- (int) (info->shadow_y * priv->border_scale));
-}
-
-/**
- * \brief Main ass rendering function, glues everything together
- * \param event event to render
- * \param event_images struct containing resulting images, will also be initialized
- * Process event, appending resulting ASS_Image's to images_root.
- */
-static int
-ass_render_event(ASS_Renderer *render_priv, ASS_Event *event,
- EventImages *event_images)
-{
- char *p;
- FT_UInt previous;
- FT_UInt num_glyphs;
- FT_Vector pen;
- unsigned code;
- DBBox bbox;
- int i, j;
- int MarginL, MarginR, MarginV;
- int last_break;
- int alignment, halign, valign;
- double device_x = 0;
- double device_y = 0;
- TextInfo *text_info = &render_priv->text_info;
- GlyphInfo *glyphs = render_priv->text_info.glyphs;
- ASS_Drawing *drawing;
- double max_text_width = 0;
- FriBidiStrIndex *cmap = NULL;
- int lineno = 1;
- int left = 0;
-
- if (event->Style >= render_priv->track->n_styles) {
- ass_msg(render_priv->library, MSGL_WARN, "No style found");
- return 1;
- }
- if (!event->Text) {
- ass_msg(render_priv->library, MSGL_WARN, "Empty event");
- return 1;
- }
-
- init_render_context(render_priv, event);
-
- drawing = render_priv->state.drawing;
- text_info->length = 0;
- num_glyphs = 0;
- p = event->Text;
-
- // Event parsing.
- while (1) {
- // get next char, executing style override
- // this affects render_context
- do {
- code = get_next_char(render_priv, &p);
- if (render_priv->state.drawing_mode && code)
- ass_drawing_add_char(drawing, (char) code);
- } while (code && render_priv->state.drawing_mode); // skip everything in drawing mode
-
- if (text_info->length >= text_info->max_glyphs) {
- // Raise maximum number of glyphs
- text_info->max_glyphs *= 2;
- text_info->glyphs = glyphs =
- realloc(text_info->glyphs,
- sizeof(GlyphInfo) * text_info->max_glyphs);
- }
-
- // Clear current GlyphInfo
- memset(&glyphs[text_info->length], 0, sizeof(GlyphInfo));
-
- // Parse drawing
- if (drawing->i) {
- drawing->scale_x = render_priv->state.scale_x *
- render_priv->font_scale;
- drawing->scale_y = render_priv->state.scale_y *
- render_priv->font_scale;
- p--;
- code = 0xfffc; // object replacement character
- glyphs[text_info->length].drawing = drawing;
- }
-
- // face could have been changed in get_next_char
- if (!render_priv->state.font) {
- free_render_context(render_priv);
- return 1;
- }
-
- if (code == 0)
- break;
-
- // Fill glyph information
- glyphs[text_info->length].symbol = code;
- glyphs[text_info->length].font = render_priv->state.font;
- for (i = 0; i < 4; ++i) {
- uint32_t clr = render_priv->state.c[i];
- change_alpha(&clr,
- mult_alpha(_a(clr), render_priv->state.fade), 1.);
- glyphs[text_info->length].c[i] = clr;
- }
- glyphs[text_info->length].effect_type = render_priv->state.effect_type;
- glyphs[text_info->length].effect_timing =
- render_priv->state.effect_timing;
- glyphs[text_info->length].effect_skip_timing =
- render_priv->state.effect_skip_timing;
- glyphs[text_info->length].font_size = ensure_font_size(render_priv,
- render_priv->state.font_size * render_priv->font_scale);
- glyphs[text_info->length].be = render_priv->state.be;
- glyphs[text_info->length].blur = render_priv->state.blur;
- glyphs[text_info->length].shadow_x = render_priv->state.shadow_x;
- glyphs[text_info->length].shadow_y = render_priv->state.shadow_y;
- glyphs[text_info->length].scale_x= render_priv->state.scale_x;
- glyphs[text_info->length].scale_y = render_priv->state.scale_y;
- glyphs[text_info->length].border_x= render_priv->state.border_x;
- glyphs[text_info->length].border_y = render_priv->state.border_y;
- glyphs[text_info->length].bold = render_priv->state.bold;
- glyphs[text_info->length].italic = render_priv->state.italic;
- glyphs[text_info->length].flags = render_priv->state.flags;
- glyphs[text_info->length].frx = render_priv->state.frx;
- glyphs[text_info->length].fry = render_priv->state.fry;
- glyphs[text_info->length].frz = render_priv->state.frz;
- glyphs[text_info->length].fax = render_priv->state.fax;
- glyphs[text_info->length].fay = render_priv->state.fay;
- glyphs[text_info->length].bm_run_id = render_priv->state.bm_run_id;
-
- if (glyphs[text_info->length].drawing) {
- drawing = render_priv->state.drawing =
- ass_drawing_new(render_priv->library, render_priv->ftlibrary);
- }
-
- text_info->length++;
-
- render_priv->state.effect_type = EF_NONE;
- render_priv->state.effect_timing = 0;
- render_priv->state.effect_skip_timing = 0;
-
- }
-
- if (text_info->length == 0) {
- // no valid symbols in the event; this can be smth like {comment}
- free_render_context(render_priv);
- return 1;
- }
-
- // Find shape runs and shape text
- ass_shaper_set_base_direction(render_priv->shaper,
- resolve_base_direction(render_priv->state.font_encoding));
- ass_shaper_find_runs(render_priv->shaper, render_priv, glyphs,
- text_info->length);
- ass_shaper_shape(render_priv->shaper, text_info);
-
- // Retrieve glyphs
- for (i = 0; i < text_info->length; i++) {
- GlyphInfo *info = glyphs + i;
- while (info) {
- get_outline_glyph(render_priv, info);
- info = info->next;
- }
- info = glyphs + i;
-
- // Add additional space after italic to non-italic style changes
- if (i && glyphs[i - 1].italic && !info->italic) {
- int back = i - 1;
- GlyphInfo *og = &glyphs[back];
- while (back && og->bbox.xMax - og->bbox.xMin == 0
- && og->italic)
- og = &glyphs[--back];
- if (og->bbox.xMax > og->cluster_advance.x)
- og->cluster_advance.x = og->bbox.xMax;
- }
-
- // add horizontal letter spacing
- info->cluster_advance.x += double_to_d6(render_priv->state.hspacing *
- render_priv->font_scale * info->scale_x);
-
- // add displacement for vertical shearing
- info->cluster_advance.y += (info->fay * info->scale_y) * info->cluster_advance.x;
-
- }
-
- // Preliminary layout (for line wrapping)
- previous = 0;
- pen.x = 0;
- pen.y = 0;
- for (i = 0; i < text_info->length; i++) {
- GlyphInfo *info = glyphs + i;
- FT_Vector cluster_pen = pen;
- while (info) {
- info->pos.x = cluster_pen.x;
- info->pos.y = cluster_pen.y;
-
- cluster_pen.x += info->advance.x;
- cluster_pen.y += info->advance.y;
-
- // fill bitmap hash
- info->hash_key.type = BITMAP_OUTLINE;
- fill_bitmap_hash(render_priv, info, &info->hash_key.u.outline);
-
- info = info->next;
- }
- info = glyphs + i;
- pen.x += info->cluster_advance.x;
- pen.y += info->cluster_advance.y;
- previous = info->symbol;
- }
-
-
- // depends on glyph x coordinates being monotonous, so it should be done before line wrap
- process_karaoke_effects(render_priv);
-
- // alignments
- alignment = render_priv->state.alignment;
- halign = alignment & 3;
- valign = alignment & 12;
-
- MarginL =
- (event->MarginL) ? event->MarginL : render_priv->state.style->MarginL;
- MarginR =
- (event->MarginR) ? event->MarginR : render_priv->state.style->MarginR;
- MarginV =
- (event->MarginV) ? event->MarginV : render_priv->state.style->MarginV;
-
- // calculate max length of a line
- max_text_width =
- x2scr(render_priv, render_priv->track->PlayResX - MarginR) -
- x2scr(render_priv, MarginL);
-
- // wrap lines
- if (render_priv->state.evt_type != EVENT_HSCROLL) {
- // rearrange text in several lines
- wrap_lines_smart(render_priv, max_text_width);
- } else {
- // no breaking or wrapping, everything in a single line
- text_info->lines[0].offset = 0;
- text_info->lines[0].len = text_info->length;
- text_info->n_lines = 1;
- measure_text(render_priv);
- }
-
- // Reorder text into visual order
- cmap = ass_shaper_reorder(render_priv->shaper, text_info);
-
- // Reposition according to the map
- pen.x = 0;
- pen.y = 0;
- for (i = 0; i < text_info->length; i++) {
- GlyphInfo *info = glyphs + cmap[i];
- FT_Vector cluster_pen;
- if (glyphs[i].linebreak) {
- pen.x = 0;
- pen.y += double_to_d6(text_info->lines[lineno-1].desc);
- pen.y += double_to_d6(text_info->lines[lineno].asc);
- pen.y += double_to_d6(render_priv->settings.line_spacing);
- lineno++;
- }
- if (info->skip) continue;
- cluster_pen = pen;
- while (info) {
- info->pos.x = info->offset.x + cluster_pen.x;
- info->pos.y = info->offset.y + cluster_pen.y;
- cluster_pen.x += info->advance.x;
- cluster_pen.y += info->advance.y;
- info = info->next;
- }
- info = glyphs + cmap[i];
- pen.x += info->cluster_advance.x;
- pen.y += info->cluster_advance.y;
- }
-
- // align lines
- if (render_priv->state.evt_type != EVENT_HSCROLL) {
- double width = 0;
- last_break = -1;
- for (i = 0; i <= text_info->length; ++i) { // (text_info->length + 1) is the end of the last line
- if ((i == text_info->length) || glyphs[i].linebreak) {
- double shift = 0;
- // remove letter spacing (which is included in cluster_advance)
- if (i > 0)
- width -= render_priv->state.hspacing * render_priv->font_scale *
- glyphs[i-1].scale_x;
- if (halign == HALIGN_LEFT) { // left aligned, no action
- shift = 0;
- } else if (halign == HALIGN_RIGHT) { // right aligned
- shift = max_text_width - width;
- } else if (halign == HALIGN_CENTER) { // centered
- shift = (max_text_width - width) / 2.0;
- }
- for (j = last_break + 1; j < i; ++j) {
- GlyphInfo *info = glyphs + j;
- while (info) {
- info->pos.x += double_to_d6(shift);
- info = info->next;
- }
- }
- last_break = i - 1;
- width = 0;
- }
- if (i < text_info->length && !glyphs[i].skip &&
- glyphs[i].symbol != '\n' && glyphs[i].symbol != 0) {
- width += d6_to_double(glyphs[i].cluster_advance.x);
- }
- }
- }
-
- // determing text bounding box
- compute_string_bbox(text_info, &bbox);
-
- // determine device coordinates for text
-
- // x coordinate for everything except positioned events
- if (render_priv->state.evt_type == EVENT_NORMAL ||
- render_priv->state.evt_type == EVENT_VSCROLL) {
- device_x = x2scr(render_priv, MarginL);
- } else if (render_priv->state.evt_type == EVENT_HSCROLL) {
- if (render_priv->state.scroll_direction == SCROLL_RL)
- device_x =
- x2scr(render_priv,
- render_priv->track->PlayResX -
- render_priv->state.scroll_shift);
- else if (render_priv->state.scroll_direction == SCROLL_LR)
- device_x =
- x2scr(render_priv,
- render_priv->state.scroll_shift) - (bbox.xMax -
- bbox.xMin);
- }
-
- // y coordinate for everything except positioned events
- if (render_priv->state.evt_type == EVENT_NORMAL ||
- render_priv->state.evt_type == EVENT_HSCROLL) {
- if (valign == VALIGN_TOP) { // toptitle
- device_y =
- y2scr_top(render_priv,
- MarginV) + text_info->lines[0].asc;
- } else if (valign == VALIGN_CENTER) { // midtitle
- double scr_y =
- y2scr(render_priv, render_priv->track->PlayResY / 2.0);
- device_y = scr_y - (bbox.yMax + bbox.yMin) / 2.0;
- } else { // subtitle
- double scr_y;
- if (valign != VALIGN_SUB)
- ass_msg(render_priv->library, MSGL_V,
- "Invalid valign, assuming 0 (subtitle)");
- scr_y =
- y2scr_sub(render_priv,
- render_priv->track->PlayResY - MarginV);
- device_y = scr_y;
- device_y -= text_info->height;
- device_y += text_info->lines[0].asc;
- }
- } else if (render_priv->state.evt_type == EVENT_VSCROLL) {
- if (render_priv->state.scroll_direction == SCROLL_TB)
- device_y =
- y2scr(render_priv,
- render_priv->state.clip_y0 +
- render_priv->state.scroll_shift) - (bbox.yMax -
- bbox.yMin);
- else if (render_priv->state.scroll_direction == SCROLL_BT)
- device_y =
- y2scr(render_priv,
- render_priv->state.clip_y1 -
- render_priv->state.scroll_shift);
- }
-
- // positioned events are totally different
- if (render_priv->state.evt_type == EVENT_POSITIONED) {
- double base_x = 0;
- double base_y = 0;
- ass_msg(render_priv->library, MSGL_DBG2, "positioned event at %f, %f",
- render_priv->state.pos_x, render_priv->state.pos_y);
- get_base_point(&bbox, alignment, &base_x, &base_y);
- device_x =
- x2scr_pos(render_priv, render_priv->state.pos_x) - base_x;
- device_y =
- y2scr_pos(render_priv, render_priv->state.pos_y) - base_y;
- }
-
- // fix clip coordinates (they depend on alignment)
- if (render_priv->state.evt_type == EVENT_NORMAL ||
- render_priv->state.evt_type == EVENT_HSCROLL ||
- render_priv->state.evt_type == EVENT_VSCROLL) {
- render_priv->state.clip_x0 =
- x2scr_scaled(render_priv, render_priv->state.clip_x0);
- render_priv->state.clip_x1 =
- x2scr_scaled(render_priv, render_priv->state.clip_x1);
- if (valign == VALIGN_TOP) {
- render_priv->state.clip_y0 =
- y2scr_top(render_priv, render_priv->state.clip_y0);
- render_priv->state.clip_y1 =
- y2scr_top(render_priv, render_priv->state.clip_y1);
- } else if (valign == VALIGN_CENTER) {
- render_priv->state.clip_y0 =
- y2scr(render_priv, render_priv->state.clip_y0);
- render_priv->state.clip_y1 =
- y2scr(render_priv, render_priv->state.clip_y1);
- } else if (valign == VALIGN_SUB) {
- render_priv->state.clip_y0 =
- y2scr_sub(render_priv, render_priv->state.clip_y0);
- render_priv->state.clip_y1 =
- y2scr_sub(render_priv, render_priv->state.clip_y1);
- }
- } else if (render_priv->state.evt_type == EVENT_POSITIONED) {
- render_priv->state.clip_x0 =
- x2scr_pos_scaled(render_priv, render_priv->state.clip_x0);
- render_priv->state.clip_x1 =
- x2scr_pos_scaled(render_priv, render_priv->state.clip_x1);
- render_priv->state.clip_y0 =
- y2scr_pos(render_priv, render_priv->state.clip_y0);
- render_priv->state.clip_y1 =
- y2scr_pos(render_priv, render_priv->state.clip_y1);
- }
-
- // calculate rotation parameters
- {
- DVector center;
-
- if (render_priv->state.have_origin) {
- center.x = x2scr(render_priv, render_priv->state.org_x);
- center.y = y2scr(render_priv, render_priv->state.org_y);
- } else {
- double bx = 0., by = 0.;
- get_base_point(&bbox, alignment, &bx, &by);
- center.x = device_x + bx;
- center.y = device_y + by;
- }
-
- for (i = 0; i < text_info->length; ++i) {
- GlyphInfo *info = glyphs + i;
- while (info) {
- OutlineBitmapHashKey *key = &info->hash_key.u.outline;
-
- if (key->frx || key->fry || key->frz || key->fax || key->fay) {
- key->shift_x = info->pos.x + double_to_d6(device_x - center.x);
- key->shift_y = -(info->pos.y + double_to_d6(device_y - center.y));
- } else {
- key->shift_x = 0;
- key->shift_y = 0;
- }
- info = info->next;
- }
- }
- }
-
- // convert glyphs to bitmaps
- left = render_priv->settings.left_margin;
- device_x = (device_x - left) * render_priv->font_scale_x + left;
- for (i = 0; i < text_info->length; ++i) {
- GlyphInfo *info = glyphs + i;
- while (info) {
- OutlineBitmapHashKey *key = &info->hash_key.u.outline;
- info->pos.x *= render_priv->font_scale_x;
- key->advance.x =
- double_to_d6(device_x - (int) device_x +
- d6_to_double(info->pos.x & SUBPIXEL_MASK)) & ~SUBPIXEL_ACCURACY;
- key->advance.y =
- double_to_d6(device_y - (int) device_y +
- d6_to_double(info->pos.y & SUBPIXEL_MASK)) & ~SUBPIXEL_ACCURACY;
- get_bitmap_glyph(render_priv, info);
- info = info->next;
- }
- }
-
- memset(event_images, 0, sizeof(*event_images));
- event_images->top = device_y - text_info->lines[0].asc;
- event_images->height = text_info->height;
- event_images->left =
- (device_x + bbox.xMin * render_priv->font_scale_x) + 0.5;
- event_images->width =
- (bbox.xMax - bbox.xMin) * render_priv->font_scale_x + 0.5;
- event_images->detect_collisions = render_priv->state.detect_collisions;
- event_images->shift_direction = (valign == VALIGN_TOP) ? 1 : -1;
- event_images->event = event;
- event_images->imgs = render_text(render_priv, (int) device_x, (int) device_y);
-
- ass_shaper_cleanup(render_priv->shaper, text_info);
- free_render_context(render_priv);
-
- return 0;
-}
-
-/**
- * \brief deallocate image list
- * \param img list pointer
- */
-void ass_free_images(ASS_Image *img)
-{
- while (img) {
- ASS_Image *next = img->next;
- free(img);
- img = next;
- }
-}
-
-/**
- * \brief Check cache limits and reset cache if they are exceeded
- */
-static void check_cache_limits(ASS_Renderer *priv, CacheStore *cache)
-{
- if (ass_cache_empty(cache->bitmap_cache, cache->bitmap_max_size)) {
- ass_cache_empty(cache->composite_cache, 0);
- ass_free_images(priv->prev_images_root);
- priv->prev_images_root = 0;
- }
- if (ass_cache_empty(cache->outline_cache, cache->glyph_max)) {
- ass_cache_empty(cache->bitmap_cache, 0);
- ass_cache_empty(cache->composite_cache, 0);
- ass_free_images(priv->prev_images_root);
- priv->prev_images_root = 0;
- }
-}
-
-/**
- * \brief Start a new frame
- */
-static int
-ass_start_frame(ASS_Renderer *render_priv, ASS_Track *track,
- long long now)
-{
- ASS_Settings *settings_priv = &render_priv->settings;
-
- if (!render_priv->settings.frame_width
- && !render_priv->settings.frame_height)
- return 1; // library not initialized
-
- if (render_priv->library != track->library)
- return 1;
-
- if (!render_priv->fontconfig_priv)
- return 1;
-
- free_list_clear(render_priv);
-
- if (track->n_events == 0)
- return 1; // nothing to do
-
- render_priv->track = track;
- render_priv->time = now;
-
- ass_lazy_track_init(render_priv->library, render_priv->track);
-
- render_priv->font_scale = settings_priv->font_size_coeff *
- render_priv->orig_height / render_priv->track->PlayResY;
- if (render_priv->track->ScaledBorderAndShadow)
- render_priv->border_scale =
- ((double) render_priv->orig_height) /
- render_priv->track->PlayResY;
- else
- render_priv->border_scale = 1.;
-
- ass_shaper_set_kerning(render_priv->shaper, track->Kerning);
- if (track->Language)
- ass_shaper_set_language(render_priv->shaper, track->Language);
- ass_shaper_set_level(render_priv->shaper, render_priv->settings.shaper);
-
- // PAR correction
- render_priv->font_scale_x = render_priv->settings.aspect /
- render_priv->settings.storage_aspect;
-
- render_priv->prev_images_root = render_priv->images_root;
- render_priv->images_root = 0;
-
- check_cache_limits(render_priv, &render_priv->cache);
-
- return 0;
-}
-
-static int cmp_event_layer(const void *p1, const void *p2)
-{
- ASS_Event *e1 = ((EventImages *) p1)->event;
- ASS_Event *e2 = ((EventImages *) p2)->event;
- if (e1->Layer < e2->Layer)
- return -1;
- if (e1->Layer > e2->Layer)
- return 1;
- if (e1->ReadOrder < e2->ReadOrder)
- return -1;
- if (e1->ReadOrder > e2->ReadOrder)
- return 1;
- return 0;
-}
-
-static ASS_RenderPriv *get_render_priv(ASS_Renderer *render_priv,
- ASS_Event *event)
-{
- if (!event->render_priv)
- event->render_priv = calloc(1, sizeof(ASS_RenderPriv));
- if (render_priv->render_id != event->render_priv->render_id) {
- memset(event->render_priv, 0, sizeof(ASS_RenderPriv));
- event->render_priv->render_id = render_priv->render_id;
- }
-
- return event->render_priv;
-}
-
-static int overlap(Segment *s1, Segment *s2)
-{
- if (s1->a >= s2->b || s2->a >= s1->b ||
- s1->ha >= s2->hb || s2->ha >= s1->hb)
- return 0;
- return 1;
-}
-
-static int cmp_segment(const void *p1, const void *p2)
-{
- return ((Segment *) p1)->a - ((Segment *) p2)->a;
-}
-
-static void
-shift_event(ASS_Renderer *render_priv, EventImages *ei, int shift)
-{
- ASS_Image *cur = ei->imgs;
- while (cur) {
- cur->dst_y += shift;
- // clip top and bottom
- if (cur->dst_y < 0) {
- int clip = -cur->dst_y;
- cur->h -= clip;
- cur->bitmap += clip * cur->stride;
- cur->dst_y = 0;
- }
- if (cur->dst_y + cur->h >= render_priv->height) {
- int clip = cur->dst_y + cur->h - render_priv->height;
- cur->h -= clip;
- }
- if (cur->h <= 0) {
- cur->h = 0;
- cur->dst_y = 0;
- }
- cur = cur->next;
- }
- ei->top += shift;
-}
-
-// dir: 1 - move down
-// -1 - move up
-static int fit_segment(Segment *s, Segment *fixed, int *cnt, int dir)
-{
- int i;
- int shift = 0;
-
- if (dir == 1) // move down
- for (i = 0; i < *cnt; ++i) {
- if (s->b + shift <= fixed[i].a || s->a + shift >= fixed[i].b ||
- s->hb <= fixed[i].ha || s->ha >= fixed[i].hb)
- continue;
- shift = fixed[i].b - s->a;
- } else // dir == -1, move up
- for (i = *cnt - 1; i >= 0; --i) {
- if (s->b + shift <= fixed[i].a || s->a + shift >= fixed[i].b ||
- s->hb <= fixed[i].ha || s->ha >= fixed[i].hb)
- continue;
- shift = fixed[i].a - s->b;
- }
-
- fixed[*cnt].a = s->a + shift;
- fixed[*cnt].b = s->b + shift;
- fixed[*cnt].ha = s->ha;
- fixed[*cnt].hb = s->hb;
- (*cnt)++;
- qsort(fixed, *cnt, sizeof(Segment), cmp_segment);
-
- return shift;
-}
-
-static void
-fix_collisions(ASS_Renderer *render_priv, EventImages *imgs, int cnt)
-{
- Segment *used = malloc(cnt * sizeof(*used));
- int cnt_used = 0;
- int i, j;
-
- // fill used[] with fixed events
- for (i = 0; i < cnt; ++i) {
- ASS_RenderPriv *priv;
- if (!imgs[i].detect_collisions)
- continue;
- priv = get_render_priv(render_priv, imgs[i].event);
- if (priv->height > 0) { // it's a fixed event
- Segment s;
- s.a = priv->top;
- s.b = priv->top + priv->height;
- s.ha = priv->left;
- s.hb = priv->left + priv->width;
- if (priv->height != imgs[i].height) { // no, it's not
- ass_msg(render_priv->library, MSGL_WARN,
- "Event height has changed");
- priv->top = 0;
- priv->height = 0;
- priv->left = 0;
- priv->width = 0;
- }
- for (j = 0; j < cnt_used; ++j)
- if (overlap(&s, used + j)) { // no, it's not
- priv->top = 0;
- priv->height = 0;
- priv->left = 0;
- priv->width = 0;
- }
- if (priv->height > 0) { // still a fixed event
- used[cnt_used].a = priv->top;
- used[cnt_used].b = priv->top + priv->height;
- used[cnt_used].ha = priv->left;
- used[cnt_used].hb = priv->left + priv->width;
- cnt_used++;
- shift_event(render_priv, imgs + i, priv->top - imgs[i].top);
- }
- }
- }
- qsort(used, cnt_used, sizeof(Segment), cmp_segment);
-
- // try to fit other events in free spaces
- for (i = 0; i < cnt; ++i) {
- ASS_RenderPriv *priv;
- if (!imgs[i].detect_collisions)
- continue;
- priv = get_render_priv(render_priv, imgs[i].event);
- if (priv->height == 0) { // not a fixed event
- int shift;
- Segment s;
- s.a = imgs[i].top;
- s.b = imgs[i].top + imgs[i].height;
- s.ha = imgs[i].left;
- s.hb = imgs[i].left + imgs[i].width;
- shift = fit_segment(&s, used, &cnt_used, imgs[i].shift_direction);
- if (shift)
- shift_event(render_priv, imgs + i, shift);
- // make it fixed
- priv->top = imgs[i].top;
- priv->height = imgs[i].height;
- priv->left = imgs[i].left;
- priv->width = imgs[i].width;
- }
-
- }
-
- free(used);
-}
-
-/**
- * \brief compare two images
- * \param i1 first image
- * \param i2 second image
- * \return 0 if identical, 1 if different positions, 2 if different content
- */
-static int ass_image_compare(ASS_Image *i1, ASS_Image *i2)
-{
- if (i1->w != i2->w)
- return 2;
- if (i1->h != i2->h)
- return 2;
- if (i1->stride != i2->stride)
- return 2;
- if (i1->color != i2->color)
- return 2;
- if (i1->bitmap != i2->bitmap)
- return 2;
- if (i1->dst_x != i2->dst_x)
- return 1;
- if (i1->dst_y != i2->dst_y)
- return 1;
- return 0;
-}
-
-/**
- * \brief compare current and previous image list
- * \param priv library handle
- * \return 0 if identical, 1 if different positions, 2 if different content
- */
-static int ass_detect_change(ASS_Renderer *priv)
-{
- ASS_Image *img, *img2;
- int diff;
-
- img = priv->prev_images_root;
- img2 = priv->images_root;
- diff = 0;
- while (img && diff < 2) {
- ASS_Image *next, *next2;
- next = img->next;
- if (img2) {
- int d = ass_image_compare(img, img2);
- if (d > diff)
- diff = d;
- next2 = img2->next;
- } else {
- // previous list is shorter
- diff = 2;
- break;
- }
- img = next;
- img2 = next2;
- }
-
- // is the previous list longer?
- if (img2)
- diff = 2;
-
- return diff;
-}
-
-/**
- * \brief render a frame
- * \param priv library handle
- * \param track track
- * \param now current video timestamp (ms)
- * \param detect_change a value describing how the new images differ from the previous ones will be written here:
- * 0 if identical, 1 if different positions, 2 if different content.
- * Can be NULL, in that case no detection is performed.
- */
-ASS_Image *ass_render_frame(ASS_Renderer *priv, ASS_Track *track,
- long long now, int *detect_change)
-{
- int i, cnt, rc;
- EventImages *last;
- ASS_Image **tail;
-
- // init frame
- rc = ass_start_frame(priv, track, now);
- if (rc != 0)
- return 0;
-
- // render events separately
- cnt = 0;
- for (i = 0; i < track->n_events; ++i) {
- ASS_Event *event = track->events + i;
- if ((event->Start <= now)
- && (now < (event->Start + event->Duration))) {
- if (cnt >= priv->eimg_size) {
- priv->eimg_size += 100;
- priv->eimg =
- realloc(priv->eimg,
- priv->eimg_size * sizeof(EventImages));
- }
- rc = ass_render_event(priv, event, priv->eimg + cnt);
- if (!rc)
- ++cnt;
- }
- }
-
- // sort by layer
- qsort(priv->eimg, cnt, sizeof(EventImages), cmp_event_layer);
-
- // call fix_collisions for each group of events with the same layer
- last = priv->eimg;
- for (i = 1; i < cnt; ++i)
- if (last->event->Layer != priv->eimg[i].event->Layer) {
- fix_collisions(priv, last, priv->eimg + i - last);
- last = priv->eimg + i;
- }
- if (cnt > 0)
- fix_collisions(priv, last, priv->eimg + cnt - last);
-
- // concat lists
- tail = &priv->images_root;
- for (i = 0; i < cnt; ++i) {
- ASS_Image *cur = priv->eimg[i].imgs;
- while (cur) {
- *tail = cur;
- tail = &cur->next;
- cur = cur->next;
- }
- }
-
- if (detect_change)
- *detect_change = ass_detect_change(priv);
-
- // free the previous image list
- ass_free_images(priv->prev_images_root);
- priv->prev_images_root = 0;
-
- return priv->images_root;
-}
diff --git a/lib/libass/libass/ass_render.h b/lib/libass/libass/ass_render.h
deleted file mode 100644
index d3c1bbbfc3..0000000000
--- a/lib/libass/libass/ass_render.h
+++ /dev/null
@@ -1,298 +0,0 @@
-/*
- * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
- * Copyright (C) 2009 Grigori Goronzy <greg@geekmind.org>
- *
- * 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.
- */
-
-#ifndef LIBASS_RENDER_H
-#define LIBASS_RENDER_H
-
-#include <inttypes.h>
-#include <ft2build.h>
-#include FT_FREETYPE_H
-#include FT_STROKER_H
-#include FT_GLYPH_H
-#include FT_SYNTHESIS_H
-
-// XXX: fix the inclusion mess so we can avoid doing this here
-typedef struct ass_shaper ASS_Shaper;
-
-#include "ass.h"
-#include "ass_font.h"
-#include "ass_bitmap.h"
-#include "ass_cache.h"
-#include "ass_utils.h"
-#include "ass_fontconfig.h"
-#include "ass_library.h"
-#include "ass_drawing.h"
-
-#define GLYPH_CACHE_MAX 1000
-#define BITMAP_CACHE_MAX_SIZE 30 * 1048576
-
-#define PARSED_FADE (1<<0)
-#define PARSED_A (1<<1)
-
-typedef struct {
- double xMin;
- double xMax;
- double yMin;
- double yMax;
-} DBBox;
-
-typedef struct {
- double x;
- double y;
-} DVector;
-
-typedef struct free_list {
- void *object;
- struct free_list *next;
-} FreeList;
-
-typedef struct {
- int frame_width;
- int frame_height;
- double font_size_coeff; // font size multiplier
- double line_spacing; // additional line spacing (in frame pixels)
- int top_margin; // height of top margin. Everything except toptitles is shifted down by top_margin.
- int bottom_margin; // height of bottom margin. (frame_height - top_margin - bottom_margin) is original video height.
- int left_margin;
- int right_margin;
- int use_margins; // 0 - place all subtitles inside original frame
- // 1 - use margins for placing toptitles and subtitles
- double aspect; // frame aspect ratio, d_width / d_height.
- double storage_aspect; // pixel ratio of the source image
- ASS_Hinting hinting;
- ASS_ShapingLevel shaper;
-
- char *default_font;
- char *default_family;
-} ASS_Settings;
-
-// a rendered event
-typedef struct {
- ASS_Image *imgs;
- int top, height, left, width;
- int detect_collisions;
- int shift_direction;
- ASS_Event *event;
-} EventImages;
-
-typedef enum {
- EF_NONE = 0,
- EF_KARAOKE,
- EF_KARAOKE_KF,
- EF_KARAOKE_KO
-} Effect;
-
-// describes a glyph
-// GlyphInfo and TextInfo are used for text centering and word-wrapping operations
-typedef struct glyph_info {
- unsigned symbol;
- unsigned skip; // skip glyph when layouting text
- ASS_Font *font;
- int face_index;
- int glyph_index;
- double font_size;
- ASS_Drawing *drawing;
- FT_Outline *outline;
- FT_Outline *border;
- Bitmap *bm; // glyph bitmap
- Bitmap *bm_o; // outline bitmap
- Bitmap *bm_s; // shadow bitmap
- FT_BBox bbox;
- FT_Vector pos;
- FT_Vector offset;
- char linebreak; // the first (leading) glyph of some line ?
- uint32_t c[4]; // colors
- FT_Vector advance; // 26.6
- FT_Vector cluster_advance;
- Effect effect_type;
- int effect_timing; // time duration of current karaoke word
- // after process_karaoke_effects: distance in pixels from the glyph origin.
- // part of the glyph to the left of it is displayed in a different color.
- int effect_skip_timing; // delay after the end of last karaoke word
- int asc, desc; // font max ascender and descender
- int be; // blur edges
- double blur; // gaussian blur
- double shadow_x;
- double shadow_y;
- double frx, fry, frz; // rotation
- double fax, fay; // text shearing
- double scale_x, scale_y;
- double border_x, border_y;
- unsigned italic;
- unsigned bold;
- int flags;
-
- int bm_run_id;
- int shape_run_id;
-
- BitmapHashKey hash_key;
-
- // next glyph in this cluster
- struct glyph_info *next;
-} GlyphInfo;
-
-typedef struct {
- double asc, desc;
- int offset, len;
-} LineInfo;
-
-typedef struct {
- GlyphInfo *glyphs;
- int length;
- LineInfo *lines;
- int n_lines;
- double height;
- int max_glyphs;
- int max_lines;
-} TextInfo;
-
-// Renderer state.
-// Values like current font face, color, screen position, clipping and so on are stored here.
-typedef struct {
- ASS_Event *event;
- ASS_Style *style;
- int parsed_tags;
-
- ASS_Font *font;
- double font_size;
- int flags; // decoration flags (underline/strike-through)
-
- FT_Stroker stroker;
- int alignment; // alignment overrides go here; if zero, style value will be used
- double frx, fry, frz;
- double fax, fay; // text shearing
- enum {
- EVENT_NORMAL, // "normal" top-, sub- or mid- title
- EVENT_POSITIONED, // happens after pos(,), margins are ignored
- EVENT_HSCROLL, // "Banner" transition effect, text_width is unlimited
- EVENT_VSCROLL // "Scroll up", "Scroll down" transition effects
- } evt_type;
- double pos_x, pos_y; // position
- double org_x, org_y; // origin
- char have_origin; // origin is explicitly defined; if 0, get_base_point() is used
- double scale_x, scale_y;
- double hspacing; // distance between letters, in pixels
- double border_x; // outline width
- double border_y;
- uint32_t c[4]; // colors(Primary, Secondary, so on) in RGBA
- int clip_x0, clip_y0, clip_x1, clip_y1;
- char clip_mode; // 1 = iclip
- char detect_collisions;
- uint32_t fade; // alpha from \fad
- char be; // blur edges
- double blur; // gaussian blur
- double shadow_x;
- double shadow_y;
- int drawing_mode; // not implemented; when != 0 text is discarded, except for style override tags
- ASS_Drawing *drawing; // current drawing
- ASS_Drawing *clip_drawing; // clip vector
- int clip_drawing_mode; // 0 = regular clip, 1 = inverse clip
-
- Effect effect_type;
- int effect_timing;
- int effect_skip_timing;
-
- // bitmap run id (used for final bitmap rendering)
- int bm_run_id;
-
- enum {
- SCROLL_LR, // left-to-right
- SCROLL_RL,
- SCROLL_TB, // top-to-bottom
- SCROLL_BT
- } scroll_direction; // for EVENT_HSCROLL, EVENT_VSCROLL
- int scroll_shift;
-
- // face properties
- char *family;
- unsigned bold;
- unsigned italic;
- int treat_family_as_pattern;
- int wrap_style;
- int font_encoding;
-} RenderContext;
-
-typedef struct {
- Cache *font_cache;
- Cache *outline_cache;
- Cache *bitmap_cache;
- Cache *composite_cache;
- size_t glyph_max;
- size_t bitmap_max_size;
-} CacheStore;
-
-struct ass_renderer {
- ASS_Library *library;
- FT_Library ftlibrary;
- FCInstance *fontconfig_priv;
- ASS_Settings settings;
- int render_id;
- ASS_SynthPriv *synth_priv;
- ASS_Shaper *shaper;
-
- ASS_Image *images_root; // rendering result is stored here
- ASS_Image *prev_images_root;
-
- EventImages *eimg; // temporary buffer for sorting rendered events
- int eimg_size; // allocated buffer size
-
- // frame-global data
- int width, height; // screen dimensions
- int orig_height; // frame height ( = screen height - margins )
- int orig_width; // frame width ( = screen width - margins )
- int orig_height_nocrop; // frame height ( = screen height - margins + cropheight)
- int orig_width_nocrop; // frame width ( = screen width - margins + cropwidth)
- ASS_Track *track;
- long long time; // frame's timestamp, ms
- double font_scale;
- double font_scale_x; // x scale applied to all glyphs to preserve text aspect ratio
- double border_scale;
-
- RenderContext state;
- TextInfo text_info;
- CacheStore cache;
-
- FreeList *free_head;
- FreeList *free_tail;
-};
-
-typedef struct render_priv {
- int top, height, left, width;
- int render_id;
-} RenderPriv;
-
-typedef struct {
- int x0;
- int y0;
- int x1;
- int y1;
-} Rect;
-
-typedef struct {
- int a, b; // top and height
- int ha, hb; // left and width
-} Segment;
-
-void reset_render_context(ASS_Renderer *render_priv);
-void ass_free_images(ASS_Image *img);
-
-// XXX: this is actually in ass.c, includes should be fixed later on
-void ass_lazy_track_init(ASS_Library *lib, ASS_Track *track);
-
-#endif /* LIBASS_RENDER_H */
diff --git a/lib/libass/libass/ass_render_api.c b/lib/libass/libass/ass_render_api.c
deleted file mode 100644
index 8bf9e5db6f..0000000000
--- a/lib/libass/libass/ass_render_api.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
- * Copyright (C) 2010 Grigori Goronzy <greg@geekmind.org>
- *
- * 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_render.h"
-
-static void ass_reconfigure(ASS_Renderer *priv)
-{
- ASS_Settings *settings = &priv->settings;
-
- priv->render_id++;
- ass_cache_empty(priv->cache.outline_cache, 0);
- ass_cache_empty(priv->cache.bitmap_cache, 0);
- ass_cache_empty(priv->cache.composite_cache, 0);
- ass_free_images(priv->prev_images_root);
- priv->prev_images_root = 0;
-
- priv->width = settings->frame_width;
- priv->height = settings->frame_height;
- priv->orig_width = settings->frame_width - settings->left_margin -
- settings->right_margin;
- priv->orig_height = settings->frame_height - settings->top_margin -
- settings->bottom_margin;
- priv->orig_width_nocrop =
- settings->frame_width - FFMAX(settings->left_margin, 0) -
- FFMAX(settings->right_margin, 0);
- priv->orig_height_nocrop =
- settings->frame_height - FFMAX(settings->top_margin, 0) -
- FFMAX(settings->bottom_margin, 0);
-}
-
-void ass_set_frame_size(ASS_Renderer *priv, int w, int h)
-{
- if (priv->settings.frame_width != w || priv->settings.frame_height != h) {
- priv->settings.frame_width = w;
- priv->settings.frame_height = h;
- if (priv->settings.aspect == 0.) {
- priv->settings.aspect = ((double) w) / h;
- priv->settings.storage_aspect = ((double) w) / h;
- }
- ass_reconfigure(priv);
- }
-}
-
-void ass_set_shaper(ASS_Renderer *priv, ASS_ShapingLevel level)
-{
-#ifdef CONFIG_HARFBUZZ
- // select the complex shaper for illegal values
- if (level == ASS_SHAPING_SIMPLE || level == ASS_SHAPING_COMPLEX)
- priv->settings.shaper = level;
- else
- priv->settings.shaper = ASS_SHAPING_COMPLEX;
-#endif
-}
-
-void ass_set_margins(ASS_Renderer *priv, int t, int b, int l, int r)
-{
- if (priv->settings.left_margin != l || priv->settings.right_margin != r ||
- priv->settings.top_margin != t || priv->settings.bottom_margin != b) {
- priv->settings.left_margin = l;
- priv->settings.right_margin = r;
- priv->settings.top_margin = t;
- priv->settings.bottom_margin = b;
- ass_reconfigure(priv);
- }
-}
-
-void ass_set_use_margins(ASS_Renderer *priv, int use)
-{
- priv->settings.use_margins = use;
-}
-
-void ass_set_aspect_ratio(ASS_Renderer *priv, double dar, double sar)
-{
- if (priv->settings.aspect != dar || priv->settings.storage_aspect != sar) {
- priv->settings.aspect = dar;
- priv->settings.storage_aspect = sar;
- ass_reconfigure(priv);
- }
-}
-
-void ass_set_font_scale(ASS_Renderer *priv, double font_scale)
-{
- if (priv->settings.font_size_coeff != font_scale) {
- priv->settings.font_size_coeff = font_scale;
- ass_reconfigure(priv);
- }
-}
-
-void ass_set_hinting(ASS_Renderer *priv, ASS_Hinting ht)
-{
- if (priv->settings.hinting != ht) {
- priv->settings.hinting = ht;
- ass_reconfigure(priv);
- }
-}
-
-void ass_set_line_spacing(ASS_Renderer *priv, double line_spacing)
-{
- priv->settings.line_spacing = line_spacing;
-}
-
-void ass_set_fonts(ASS_Renderer *priv, const char *default_font,
- const char *default_family, int fc, const char *config,
- int update)
-{
- free(priv->settings.default_font);
- free(priv->settings.default_family);
- priv->settings.default_font = default_font ? strdup(default_font) : 0;
- priv->settings.default_family =
- default_family ? strdup(default_family) : 0;
-
- if (priv->fontconfig_priv)
- fontconfig_done(priv->fontconfig_priv);
- priv->fontconfig_priv =
- fontconfig_init(priv->library, priv->ftlibrary, default_family,
- default_font, fc, config, update);
-}
-
-int ass_fonts_update(ASS_Renderer *render_priv)
-{
- return fontconfig_update(render_priv->fontconfig_priv);
-}
-
-void ass_set_cache_limits(ASS_Renderer *render_priv, int glyph_max,
- int bitmap_max)
-{
- render_priv->cache.glyph_max = glyph_max ? glyph_max : GLYPH_CACHE_MAX;
- render_priv->cache.bitmap_max_size = bitmap_max ? 1048576 * bitmap_max :
- BITMAP_CACHE_MAX_SIZE;
-}
diff --git a/lib/libass/libass/ass_shaper.c b/lib/libass/libass/ass_shaper.c
deleted file mode 100644
index 6adfc78f92..0000000000
--- a/lib/libass/libass/ass_shaper.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
- *
- * 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 <fribidi/fribidi.h>
-
-#include "ass_shaper.h"
-#include "ass_render.h"
-#include "ass_font.h"
-#include "ass_parse.h"
-#include "ass_cache.h"
-
-#define MAX_RUNS 50
-
-#ifdef CONFIG_HARFBUZZ
-#include <hb-ft.h>
-enum {
- VERT = 0,
- VKNA,
- KERN
-};
-#define NUM_FEATURES 3
-#endif
-
-struct ass_shaper {
- ASS_ShapingLevel shaping_level;
-
- // FriBidi log2vis
- int n_glyphs;
- FriBidiChar *event_text;
- FriBidiCharType *ctypes;
- FriBidiLevel *emblevels;
- FriBidiStrIndex *cmap;
- FriBidiParType base_direction;
-
-#ifdef CONFIG_HARFBUZZ
- // OpenType features
- int n_features;
- hb_feature_t *features;
- hb_language_t language;
-
- // Glyph metrics cache, to speed up shaping
- Cache *metrics_cache;
-#endif
-};
-
-#ifdef CONFIG_HARFBUZZ
-struct ass_shaper_metrics_data {
- Cache *metrics_cache;
- GlyphMetricsHashKey hash_key;
- int vertical;
-};
-
-struct ass_shaper_font_data {
- hb_font_t *fonts[ASS_FONT_MAX_FACES];
- hb_font_funcs_t *font_funcs[ASS_FONT_MAX_FACES];
- struct ass_shaper_metrics_data *metrics_data[ASS_FONT_MAX_FACES];
-};
-#endif
-
-/**
- * \brief Print version information
- */
-void ass_shaper_info(ASS_Library *lib)
-{
- ass_msg(lib, MSGL_V, "Shaper: FriBidi "
- FRIBIDI_VERSION " (SIMPLE)"
-#ifdef CONFIG_HARFBUZZ
- " HarfBuzz-ng %s (COMPLEX)", hb_version_string()
-#endif
- );
-}
-
-/**
- * \brief grow arrays, if needed
- * \param new_size requested size
- */
-static void check_allocations(ASS_Shaper *shaper, size_t new_size)
-{
- if (new_size > shaper->n_glyphs) {
- shaper->event_text = realloc(shaper->event_text, sizeof(FriBidiChar) * new_size);
- shaper->ctypes = realloc(shaper->ctypes, sizeof(FriBidiCharType) * new_size);
- shaper->emblevels = realloc(shaper->emblevels, sizeof(FriBidiLevel) * new_size);
- shaper->cmap = realloc(shaper->cmap, sizeof(FriBidiStrIndex) * new_size);
- }
-}
-
-/**
- * \brief Free shaper and related data
- */
-void ass_shaper_free(ASS_Shaper *shaper)
-{
-#ifdef CONFIG_HARFBUZZ
- ass_cache_done(shaper->metrics_cache);
- free(shaper->features);
-#endif
- free(shaper->event_text);
- free(shaper->ctypes);
- free(shaper->emblevels);
- free(shaper->cmap);
- free(shaper);
-}
-
-void ass_shaper_font_data_free(ASS_ShaperFontData *priv)
-{
-#ifdef CONFIG_HARFBUZZ
- int i;
- for (i = 0; i < ASS_FONT_MAX_FACES; i++)
- if (priv->fonts[i]) {
- free(priv->metrics_data[i]);
- hb_font_destroy(priv->fonts[i]);
- hb_font_funcs_destroy(priv->font_funcs[i]);
- }
- free(priv);
-#endif
-}
-
-#ifdef CONFIG_HARFBUZZ
-/**
- * \brief set up the HarfBuzz OpenType feature list with some
- * standard features.
- */
-static void init_features(ASS_Shaper *shaper)
-{
- shaper->features = calloc(sizeof(hb_feature_t), NUM_FEATURES);
-
- shaper->n_features = NUM_FEATURES;
- shaper->features[VERT].tag = HB_TAG('v', 'e', 'r', 't');
- shaper->features[VERT].end = INT_MAX;
- shaper->features[VKNA].tag = HB_TAG('v', 'k', 'n', 'a');
- shaper->features[VKNA].end = INT_MAX;
- shaper->features[KERN].tag = HB_TAG('k', 'e', 'r', 'n');
- shaper->features[KERN].end = INT_MAX;
-}
-
-/**
- * \brief Set features depending on properties of the run
- */
-static void set_run_features(ASS_Shaper *shaper, GlyphInfo *info)
-{
- // enable vertical substitutions for @font runs
- if (info->font->desc.vertical)
- shaper->features[VERT].value = shaper->features[VKNA].value = 1;
- else
- shaper->features[VERT].value = shaper->features[VKNA].value = 0;
-}
-
-/**
- * \brief Update HarfBuzz's idea of font metrics
- * \param hb_font HarfBuzz font
- * \param face associated FreeType font face
- */
-static void update_hb_size(hb_font_t *hb_font, FT_Face face)
-{
- hb_font_set_scale (hb_font,
- ((uint64_t) face->size->metrics.x_scale * (uint64_t) face->units_per_EM) >> 16,
- ((uint64_t) face->size->metrics.y_scale * (uint64_t) face->units_per_EM) >> 16);
- hb_font_set_ppem (hb_font, face->size->metrics.x_ppem,
- face->size->metrics.y_ppem);
-}
-
-
-/*
- * Cached glyph metrics getters follow
- *
- * These functions replace HarfBuzz' standard FreeType font functions
- * and provide cached access to essential glyph metrics. This usually
- * speeds up shaping a lot. It also allows us to use custom load flags.
- *
- */
-
-GlyphMetricsHashValue *
-get_cached_metrics(struct ass_shaper_metrics_data *metrics, FT_Face face,
- hb_codepoint_t glyph)
-{
- GlyphMetricsHashValue *val;
-
- metrics->hash_key.glyph_index = glyph;
- val = ass_cache_get(metrics->metrics_cache, &metrics->hash_key);
-
- if (!val) {
- int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
- | FT_LOAD_IGNORE_TRANSFORM;
- GlyphMetricsHashValue new_val;
-
- if (FT_Load_Glyph(face, glyph, load_flags))
- return NULL;
-
- memcpy(&new_val.metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics));
- val = ass_cache_put(metrics->metrics_cache, &metrics->hash_key, &new_val);
- }
-
- return val;
-}
-
-static hb_bool_t
-get_glyph(hb_font_t *font, void *font_data, hb_codepoint_t unicode,
- hb_codepoint_t variation, hb_codepoint_t *glyph, void *user_data)
-{
- FT_Face face = font_data;
-
- if (variation)
- *glyph = FT_Face_GetCharVariantIndex(face, unicode, variation);
- else
- *glyph = FT_Get_Char_Index(face, unicode);
-
- return *glyph != 0;
-}
-
-static hb_position_t
-cached_h_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
- void *user_data)
-{
- FT_Face face = font_data;
- struct ass_shaper_metrics_data *metrics_priv = user_data;
- GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
-
- if (!metrics)
- return 0;
-
- if (metrics_priv->vertical && glyph > VERTICAL_LOWER_BOUND)
- return metrics->metrics.vertAdvance;
-
- return metrics->metrics.horiAdvance;
-}
-
-static hb_position_t
-cached_v_advance(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
- void *user_data)
-{
- FT_Face face = font_data;
- struct ass_shaper_metrics_data *metrics_priv = user_data;
- GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
-
- if (!metrics)
- return 0;
-
- return metrics->metrics.vertAdvance;
-
-}
-
-static hb_bool_t
-cached_h_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
- hb_position_t *x, hb_position_t *y, void *user_data)
-{
- return 1;
-}
-
-static hb_bool_t
-cached_v_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
- hb_position_t *x, hb_position_t *y, void *user_data)
-{
- FT_Face face = font_data;
- struct ass_shaper_metrics_data *metrics_priv = user_data;
- GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
-
- if (!metrics)
- return 0;
-
- *x = metrics->metrics.horiBearingX - metrics->metrics.vertBearingX;
- *y = metrics->metrics.horiBearingY - (-metrics->metrics.vertBearingY);
-
- return 1;
-}
-
-static hb_position_t
-get_h_kerning(hb_font_t *font, void *font_data, hb_codepoint_t first,
- hb_codepoint_t second, void *user_data)
-{
- FT_Face face = font_data;
- FT_Vector kern;
-
- if (FT_Get_Kerning (face, first, second, FT_KERNING_DEFAULT, &kern))
- return 0;
-
- return kern.x;
-}
-
-static hb_position_t
-get_v_kerning(hb_font_t *font, void *font_data, hb_codepoint_t first,
- hb_codepoint_t second, void *user_data)
-{
- return 0;
-}
-
-static hb_bool_t
-cached_extents(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
- hb_glyph_extents_t *extents, void *user_data)
-{
- FT_Face face = font_data;
- struct ass_shaper_metrics_data *metrics_priv = user_data;
- GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, glyph);
-
- if (!metrics)
- return 0;
-
- extents->x_bearing = metrics->metrics.horiBearingX;
- extents->y_bearing = metrics->metrics.horiBearingY;
- extents->width = metrics->metrics.width;
- extents->height = metrics->metrics.height;
-
- return 1;
-}
-
-static hb_bool_t
-get_contour_point(hb_font_t *font, void *font_data, hb_codepoint_t glyph,
- unsigned int point_index, hb_position_t *x,
- hb_position_t *y, void *user_data)
-{
- FT_Face face = font_data;
- int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
- | FT_LOAD_IGNORE_TRANSFORM;
-
- if (FT_Load_Glyph(face, glyph, load_flags))
- return 0;
-
- if (point_index >= (unsigned)face->glyph->outline.n_points)
- return 0;
-
- *x = face->glyph->outline.points[point_index].x;
- *y = face->glyph->outline.points[point_index].y;
-
- return 1;
-}
-
-/**
- * \brief Retrieve HarfBuzz font from cache.
- * Create it from FreeType font, if needed.
- * \param info glyph cluster
- * \return HarfBuzz font
- */
-static hb_font_t *get_hb_font(ASS_Shaper *shaper, GlyphInfo *info)
-{
- ASS_Font *font = info->font;
- hb_font_t **hb_fonts;
- struct ass_shaper_metrics_data *metrics;
- hb_font_funcs_t *funcs;
-
- if (!font->shaper_priv)
- font->shaper_priv = (ASS_ShaperFontData *) calloc(sizeof(ASS_ShaperFontData), 1);
-
-
- hb_fonts = font->shaper_priv->fonts;
- if (!hb_fonts[info->face_index]) {
- hb_fonts[info->face_index] =
- hb_ft_font_create(font->faces[info->face_index], NULL);
-
- // set up cached metrics access
- font->shaper_priv->metrics_data[info->face_index] = (struct ass_shaper_metrics_data *)
- calloc(sizeof(struct ass_shaper_metrics_data), 1);
- metrics = font->shaper_priv->metrics_data[info->face_index];
- metrics->metrics_cache = shaper->metrics_cache;
- metrics->vertical = info->font->desc.vertical;
-
- funcs = hb_font_funcs_create();
- font->shaper_priv->font_funcs[info->face_index] = funcs;
- hb_font_funcs_set_glyph_func(funcs, get_glyph,
- metrics, NULL);
- hb_font_funcs_set_glyph_h_advance_func(funcs, cached_h_advance,
- metrics, NULL);
- hb_font_funcs_set_glyph_v_advance_func(funcs, cached_v_advance,
- metrics, NULL);
- hb_font_funcs_set_glyph_h_origin_func(funcs, cached_h_origin,
- metrics, NULL);
- hb_font_funcs_set_glyph_v_origin_func(funcs, cached_v_origin,
- metrics, NULL);
- hb_font_funcs_set_glyph_h_kerning_func(funcs, get_h_kerning,
- metrics, NULL);
- hb_font_funcs_set_glyph_v_kerning_func(funcs, get_v_kerning,
- metrics, NULL);
- hb_font_funcs_set_glyph_extents_func(funcs, cached_extents,
- metrics, NULL);
- hb_font_funcs_set_glyph_contour_point_func(funcs, get_contour_point,
- metrics, NULL);
- hb_font_set_funcs(hb_fonts[info->face_index], funcs,
- font->faces[info->face_index], NULL);
- }
-
- ass_face_set_size(font->faces[info->face_index], info->font_size);
- update_hb_size(hb_fonts[info->face_index], font->faces[info->face_index]);
-
- // update hash key for cached metrics
- metrics = font->shaper_priv->metrics_data[info->face_index];
- metrics->hash_key.font = info->font;
- metrics->hash_key.face_index = info->face_index;
- metrics->hash_key.size = info->font_size;
- metrics->hash_key.scale_x = double_to_d6(info->scale_x);
- metrics->hash_key.scale_y = double_to_d6(info->scale_y);
-
- return hb_fonts[info->face_index];
-}
-
-/**
- * \brief Shape event text with HarfBuzz. Full OpenType shaping.
- * \param glyphs glyph clusters
- * \param len number of clusters
- */
-static void shape_harfbuzz(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
-{
- int i, j;
- int run = 0;
- struct {
- int offset;
- int end;
- hb_buffer_t *buf;
- hb_font_t *font;
- } runs[MAX_RUNS];
-
-
- for (i = 0; i < len && run < MAX_RUNS; i++, run++) {
- // get length and level of the current run
- int k = i;
- int level = glyphs[i].shape_run_id;
- int direction = shaper->emblevels[k] % 2;
- while (i < (len - 1) && level == glyphs[i+1].shape_run_id)
- i++;
- runs[run].offset = k;
- runs[run].end = i;
- runs[run].buf = hb_buffer_create();
- runs[run].font = get_hb_font(shaper, glyphs + k);
- set_run_features(shaper, glyphs + k);
- hb_buffer_pre_allocate(runs[run].buf, i - k + 1);
- hb_buffer_set_direction(runs[run].buf, direction ? HB_DIRECTION_RTL :
- HB_DIRECTION_LTR);
- hb_buffer_set_language(runs[run].buf, shaper->language);
- hb_buffer_add_utf32(runs[run].buf, shaper->event_text + k, i - k + 1,
- 0, i - k + 1);
- hb_shape(runs[run].font, runs[run].buf, shaper->features,
- shaper->n_features);
- }
-
- // Initialize: skip all glyphs, this is undone later as needed
- for (i = 0; i < len; i++)
- glyphs[i].skip = 1;
-
- // Update glyph indexes, positions and advances from the shaped runs
- for (i = 0; i < run; i++) {
- int num_glyphs = hb_buffer_get_length(runs[i].buf);
- hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(runs[i].buf, NULL);
- hb_glyph_position_t *pos = hb_buffer_get_glyph_positions(runs[i].buf, NULL);
-
- for (j = 0; j < num_glyphs; j++) {
- int idx = glyph_info[j].cluster + runs[i].offset;
- GlyphInfo *info = glyphs + idx;
- GlyphInfo *root = info;
-
- // if we have more than one glyph per cluster, allocate a new one
- // and attach to the root glyph
- if (info->skip == 0) {
- while (info->next)
- info = info->next;
- info->next = malloc(sizeof(GlyphInfo));
- memcpy(info->next, info, sizeof(GlyphInfo));
- info = info->next;
- info->next = NULL;
- }
-
- // set position and advance
- info->skip = 0;
- info->glyph_index = glyph_info[j].codepoint;
- info->offset.x = pos[j].x_offset * info->scale_x;
- info->offset.y = -pos[j].y_offset * info->scale_y;
- info->advance.x = pos[j].x_advance * info->scale_x;
- info->advance.y = -pos[j].y_advance * info->scale_y;
-
- // accumulate advance in the root glyph
- root->cluster_advance.x += info->advance.x;
- root->cluster_advance.y += info->advance.y;
- }
- }
-
- // Free runs and associated data
- for (i = 0; i < run; i++) {
- hb_buffer_destroy(runs[i].buf);
- }
-
-}
-#endif
-
-/**
- * \brief Shape event text with FriBidi. Does mirroring and simple
- * Arabic shaping.
- * \param len number of clusters
- */
-static void shape_fribidi(ASS_Shaper *shaper, GlyphInfo *glyphs, size_t len)
-{
- int i;
- FriBidiJoiningType *joins = calloc(sizeof(*joins), len);
-
- // shape on codepoint level
- fribidi_get_joining_types(shaper->event_text, len, joins);
- fribidi_join_arabic(shaper->ctypes, len, shaper->emblevels, joins);
- fribidi_shape(FRIBIDI_FLAGS_DEFAULT | FRIBIDI_FLAGS_ARABIC,
- shaper->emblevels, len, joins, shaper->event_text);
-
- // update indexes
- for (i = 0; i < len; i++) {
- GlyphInfo *info = glyphs + i;
- FT_Face face = info->font->faces[info->face_index];
- info->symbol = shaper->event_text[i];
- info->glyph_index = FT_Get_Char_Index(face, shaper->event_text[i]);
- }
-
- free(joins);
-}
-
-/**
- * \brief Toggle kerning for HarfBuzz shaping.
- * NOTE: currently only works with OpenType fonts, the TrueType fallback *always*
- * kerns. It's a bug in HarfBuzz.
- */
-void ass_shaper_set_kerning(ASS_Shaper *shaper, int kern)
-{
-#ifdef CONFIG_HARFBUZZ
- shaper->features[KERN].value = !!kern;
-#endif
-}
-
-/**
- * \brief Find shape runs according to the event's selected fonts
- */
-void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv,
- GlyphInfo *glyphs, size_t len)
-{
- int i;
- int shape_run = 0;
-
- for (i = 0; i < len; i++) {
- GlyphInfo *last = glyphs + i - 1;
- GlyphInfo *info = glyphs + i;
- // skip drawings
- if (info->symbol == 0xfffc)
- continue;
- // set size and get glyph index
- ass_font_get_index(render_priv->fontconfig_priv, info->font,
- info->symbol, &info->face_index, &info->glyph_index);
- // shape runs share the same font face and size
- if (i > 0 && (last->font != info->font ||
- last->font_size != info->font_size ||
- last->face_index != info->face_index))
- shape_run++;
- info->shape_run_id = shape_run;
- }
-
-}
-
-/**
- * \brief Set base direction (paragraph direction) of the text.
- * \param dir base direction
- */
-void ass_shaper_set_base_direction(ASS_Shaper *shaper, FriBidiParType dir)
-{
- shaper->base_direction = dir;
-}
-
-/**
- * \brief Set language hint. Some languages have specific character variants,
- * like Serbian Cyrillic.
- * \param lang ISO 639-1 two-letter language code
- */
-void ass_shaper_set_language(ASS_Shaper *shaper, const char *code)
-{
-#ifdef CONFIG_HARFBUZZ
- shaper->language = hb_language_from_string(code, -1);
-#endif
-}
-
-/**
- * Set shaping level. Essentially switches between FriBidi and HarfBuzz.
- */
-void ass_shaper_set_level(ASS_Shaper *shaper, ASS_ShapingLevel level)
-{
- shaper->shaping_level = level;
-}
-
-/**
- * \brief Shape an event's text. Calculates directional runs and shapes them.
- * \param text_info event's text
- */
-void ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info)
-{
- int i, last_break;
- FriBidiParType dir;
- GlyphInfo *glyphs = text_info->glyphs;
-
- check_allocations(shaper, text_info->length);
-
- // Get bidi character types and embedding levels
- last_break = 0;
- for (i = 0; i < text_info->length; i++) {
- shaper->event_text[i] = glyphs[i].symbol;
- // embedding levels should be calculated paragraph by paragraph
- if (glyphs[i].symbol == '\n' || i == text_info->length - 1) {
- dir = shaper->base_direction;
- fribidi_get_bidi_types(shaper->event_text + last_break,
- i - last_break + 1, shaper->ctypes + last_break);
- fribidi_get_par_embedding_levels(shaper->ctypes + last_break,
- i - last_break + 1, &dir, shaper->emblevels + last_break);
- last_break = i + 1;
- }
- }
-
- // add embedding levels to shape runs for final runs
- for (i = 0; i < text_info->length; i++) {
- glyphs[i].shape_run_id += shaper->emblevels[i];
- }
-
-#ifdef CONFIG_HARFBUZZ
- switch (shaper->shaping_level) {
- case ASS_SHAPING_SIMPLE:
- shape_fribidi(shaper, glyphs, text_info->length);
- break;
- case ASS_SHAPING_COMPLEX:
- shape_harfbuzz(shaper, glyphs, text_info->length);
- break;
- }
-#else
- shape_fribidi(shaper, glyphs, text_info->length);
-#endif
-
-
- // clean up
- for (i = 0; i < text_info->length; i++) {
- // Skip direction override control characters
- // NOTE: Behdad said HarfBuzz is supposed to remove these, but this hasn't
- // been implemented yet
- if (glyphs[i].symbol <= 0x202F && glyphs[i].symbol >= 0x202a) {
- glyphs[i].symbol = 0;
- glyphs[i].skip++;
- }
- }
-}
-
-/**
- * \brief Create a new shaper instance and preallocate data structures
- * \param prealloc preallocation size
- */
-ASS_Shaper *ass_shaper_new(size_t prealloc)
-{
- ASS_Shaper *shaper = calloc(sizeof(*shaper), 1);
-
- shaper->base_direction = FRIBIDI_PAR_ON;
- check_allocations(shaper, prealloc);
-
-#ifdef CONFIG_HARFBUZZ
- init_features(shaper);
- shaper->metrics_cache = ass_glyph_metrics_cache_create();
-#endif
-
- return shaper;
-}
-
-
-/**
- * \brief clean up additional data temporarily needed for shaping and
- * (e.g. additional glyphs allocated)
- */
-void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info)
-{
- int i;
-
- for (i = 0; i < text_info->length; i++) {
- GlyphInfo *info = text_info->glyphs + i;
- info = info->next;
- while (info) {
- GlyphInfo *next = info->next;
- free(info);
- info = next;
- }
- }
-}
-
-/**
- * \brief Calculate reorder map to render glyphs in visual order
- */
-FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info)
-{
- int i;
-
- // Initialize reorder map
- for (i = 0; i < text_info->length; i++)
- shaper->cmap[i] = i;
-
- // Create reorder map line-by-line
- for (i = 0; i < text_info->n_lines; i++) {
- LineInfo *line = text_info->lines + i;
- int level;
- FriBidiParType dir = FRIBIDI_PAR_ON;
-
- level = fribidi_reorder_line(0,
- shaper->ctypes + line->offset, line->len, 0, dir,
- shaper->emblevels + line->offset, NULL,
- shaper->cmap + line->offset);
- }
-
- return shaper->cmap;
-}
-
-/**
- * \brief Resolve a Windows font encoding number to a suitable
- * base direction. 177 and 178 are Hebrew and Arabic respectively, and
- * they map to RTL. 1 is autodetection and is mapped to just that.
- * Everything else is mapped to LTR.
- * \param enc Windows font encoding
- */
-FriBidiParType resolve_base_direction(int enc)
-{
- switch (enc) {
- case 1:
- return FRIBIDI_PAR_ON;
- case 177:
- case 178:
- return FRIBIDI_PAR_RTL;
- default:
- return FRIBIDI_PAR_LTR;
- }
-}
diff --git a/lib/libass/libass/ass_shaper.h b/lib/libass/libass/ass_shaper.h
deleted file mode 100644
index 81499dde8e..0000000000
--- a/lib/libass/libass/ass_shaper.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright (C) 2011 Grigori Goronzy <greg@chown.ath.cx>
- *
- * 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.
- */
-
-#ifndef LIBASS_SHAPER_H
-#define LIBASS_SHAPER_H
-
-#include "config.h"
-
-#include <fribidi/fribidi.h>
-#include "ass_render.h"
-
-void ass_shaper_info(ASS_Library *lib);
-ASS_Shaper *ass_shaper_new(size_t prealloc);
-void ass_shaper_free(ASS_Shaper *shaper);
-void ass_shaper_set_kerning(ASS_Shaper *shaper, int kern);
-void ass_shaper_find_runs(ASS_Shaper *shaper, ASS_Renderer *render_priv,
- GlyphInfo *glyphs, size_t len);
-void ass_shaper_set_base_direction(ASS_Shaper *shaper, FriBidiParType dir);
-void ass_shaper_set_language(ASS_Shaper *shaper, const char *code);
-void ass_shaper_set_level(ASS_Shaper *shaper, ASS_ShapingLevel level);
-void ass_shaper_shape(ASS_Shaper *shaper, TextInfo *text_info);
-void ass_shaper_cleanup(ASS_Shaper *shaper, TextInfo *text_info);
-FriBidiStrIndex *ass_shaper_reorder(ASS_Shaper *shaper, TextInfo *text_info);
-FriBidiParType resolve_base_direction(int font_encoding);
-
-void ass_shaper_font_data_free(ASS_ShaperFontData *priv);
-
-#endif
diff --git a/lib/libass/libass/ass_strtod.c b/lib/libass/libass/ass_strtod.c
deleted file mode 100644
index f55b37ae12..0000000000
--- a/lib/libass/libass/ass_strtod.c
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 1988-1993 The Regents of the University of California.
- * Copyright (c) 1994 Sun Microsystems, Inc.
- *
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- *
- */
-
-#include <stdlib.h>
-#include <ctype.h>
-#include <errno.h>
-
-const
-static int maxExponent = 511; /* Largest possible base 10 exponent. Any
- * exponent larger than this will already
- * produce underflow or overflow, so there's
- * no need to worry about additional digits.
- */
-
-const
-static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
- 10., /* is 10^2^i. Used to convert decimal */
- 100., /* exponents into floating-point numbers. */
- 1.0e4,
- 1.0e8,
- 1.0e16,
- 1.0e32,
- 1.0e64,
- 1.0e128,
- 1.0e256
-};
-
-/*
- *----------------------------------------------------------------------
- *
- * strtod --
- *
- * This procedure converts a floating-point number from an ASCII
- * decimal representation to internal double-precision format.
- *
- * Results:
- * The return value is the double-precision floating-point
- * representation of the characters in string. If endPtr isn't
- * NULL, then *endPtr is filled in with the address of the
- * next character after the last one that was part of the
- * floating-point number.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-double
-ass_strtod(string, endPtr)
- const char *string; /* A decimal ASCII floating-point number,
- * optionally preceded by white space.
- * Must have form "-I.FE-X", where I is the
- * integer part of the mantissa, F is the
- * fractional part of the mantissa, and X
- * is the exponent. Either of the signs
- * may be "+", "-", or omitted. Either I
- * or F may be omitted, or both. The decimal
- * point isn't necessary unless F is present.
- * The "E" may actually be an "e". E and X
- * may both be omitted (but not just one).
- */
- char **endPtr; /* If non-NULL, store terminating character's
- * address here. */
-{
- int sign, expSign = 0;
- double fraction, dblExp, *d;
- register const char *p;
- register int c;
- int exp = 0; /* Exponent read from "EX" field. */
- int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstatnces, it is
- * the negative of the number of digits in F.
- * However, if I is very long, the last digits
- * of I get dropped (otherwise a long I with a
- * large negative exponent could cause an
- * unnecessary overflow on I alone). In this
- * case, fracExp is incremented one for each
- * dropped digit. */
- int mantSize; /* Number of digits in mantissa. */
- int decPt; /* Number of mantissa digits BEFORE decimal
- * point. */
- const char *pExp; /* Temporarily holds location of exponent
- * in string. */
-
- /*
- * Strip off leading blanks and check for a sign.
- */
-
- p = string;
- while (isspace(*p)) {
- p += 1;
- }
- if (*p == '-') {
- sign = 1;
- p += 1;
- } else {
- if (*p == '+') {
- p += 1;
- }
- sign = 0;
- }
-
- /*
- * Count the number of digits in the mantissa (including the decimal
- * point), and also locate the decimal point.
- */
-
- decPt = -1;
- for (mantSize = 0; ; mantSize += 1)
- {
- c = *p;
- if (!isdigit(c)) {
- if ((c != '.') || (decPt >= 0)) {
- break;
- }
- decPt = mantSize;
- }
- p += 1;
- }
-
- /*
- * Now suck up the digits in the mantissa. Use two integers to
- * collect 9 digits each (this is faster than using floating-point).
- * If the mantissa has more than 18 digits, ignore the extras, since
- * they can't affect the value anyway.
- */
-
- pExp = p;
- p -= mantSize;
- if (decPt < 0) {
- decPt = mantSize;
- } else {
- mantSize -= 1; /* One of the digits was the point. */
- }
- if (mantSize > 18) {
- fracExp = decPt - 18;
- mantSize = 18;
- } else {
- fracExp = decPt - mantSize;
- }
- if (mantSize == 0) {
- fraction = 0.0;
- p = string;
- goto done;
- } else {
- int frac1, frac2;
- frac1 = 0;
- for ( ; mantSize > 9; mantSize -= 1)
- {
- c = *p;
- p += 1;
- if (c == '.') {
- c = *p;
- p += 1;
- }
- frac1 = 10*frac1 + (c - '0');
- }
- frac2 = 0;
- for (; mantSize > 0; mantSize -= 1)
- {
- c = *p;
- p += 1;
- if (c == '.') {
- c = *p;
- p += 1;
- }
- frac2 = 10*frac2 + (c - '0');
- }
- fraction = (1.0e9 * frac1) + frac2;
- }
-
- /*
- * Skim off the exponent.
- */
-
- p = pExp;
- if ((*p == 'E') || (*p == 'e')) {
- p += 1;
- if (*p == '-') {
- expSign = 1;
- p += 1;
- } else {
- if (*p == '+') {
- p += 1;
- }
- expSign = 0;
- }
- while (isdigit(*p)) {
- exp = exp * 10 + (*p - '0');
- p += 1;
- }
- }
- if (expSign) {
- exp = fracExp - exp;
- } else {
- exp = fracExp + exp;
- }
-
- /*
- * Generate a floating-point number that represents the exponent.
- * Do this by processing the exponent one bit at a time to combine
- * many powers of 2 of 10. Then combine the exponent with the
- * fraction.
- */
-
- if (exp < 0) {
- expSign = 1;
- exp = -exp;
- } else {
- expSign = 0;
- }
- if (exp > maxExponent) {
- exp = maxExponent;
- errno = ERANGE;
- }
- dblExp = 1.0;
- for (d = (double *) powersOf10; exp != 0; exp >>= 1, d += 1) {
- if (exp & 01) {
- dblExp *= *d;
- }
- }
- if (expSign) {
- fraction /= dblExp;
- } else {
- fraction *= dblExp;
- }
-
-done:
- if (endPtr != NULL) {
- *endPtr = (char *) p;
- }
-
- if (sign) {
- return -fraction;
- }
- return fraction;
-}
diff --git a/lib/libass/libass/ass_types.h b/lib/libass/libass/ass_types.h
deleted file mode 100644
index 20fd825ef1..0000000000
--- a/lib/libass/libass/ass_types.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LIBASS_TYPES_H
-#define LIBASS_TYPES_H
-
-#include <stdint.h>
-
-#define VALIGN_SUB 0
-#define VALIGN_CENTER 8
-#define VALIGN_TOP 4
-#define HALIGN_LEFT 1
-#define HALIGN_CENTER 2
-#define HALIGN_RIGHT 3
-
-/* Opaque objects internally used by libass. Contents are private. */
-typedef struct ass_renderer ASS_Renderer;
-typedef struct render_priv ASS_RenderPriv;
-typedef struct parser_priv ASS_ParserPriv;
-typedef struct ass_library ASS_Library;
-
-/* ASS Style: line */
-typedef struct ass_style {
- char *Name;
- char *FontName;
- double FontSize;
- uint32_t PrimaryColour;
- uint32_t SecondaryColour;
- uint32_t OutlineColour;
- uint32_t BackColour;
- int Bold;
- int Italic;
- int Underline;
- int StrikeOut;
- double ScaleX;
- double ScaleY;
- double Spacing;
- int Angle;
- int BorderStyle;
- double Outline;
- double Shadow;
- int Alignment;
- int MarginL;
- int MarginR;
- int MarginV;
- int Encoding;
- int treat_fontname_as_pattern;
-} ASS_Style;
-
-/*
- * ASS_Event corresponds to a single Dialogue line;
- * text is stored as-is, style overrides will be parsed later.
- */
-typedef struct ass_event {
- long long Start; // ms
- long long Duration; // ms
-
- int ReadOrder;
- int Layer;
- int Style;
- char *Name;
- int MarginL;
- int MarginR;
- int MarginV;
- char *Effect;
- char *Text;
-
- ASS_RenderPriv *render_priv;
-} ASS_Event;
-
-/*
- * ass track represent either an external script or a matroska subtitle stream
- * (no real difference between them); it can be used in rendering after the
- * headers are parsed (i.e. events format line read).
- */
-typedef struct ass_track {
- int n_styles; // amount used
- int max_styles; // amount allocated
- int n_events;
- int max_events;
- ASS_Style *styles; // array of styles, max_styles length, n_styles used
- ASS_Event *events; // the same as styles
-
- char *style_format; // style format line (everything after "Format: ")
- char *event_format; // event format line
-
- enum {
- TRACK_TYPE_UNKNOWN = 0,
- TRACK_TYPE_ASS,
- TRACK_TYPE_SSA
- } track_type;
-
- // Script header fields
- int PlayResX;
- int PlayResY;
- double Timer;
- int WrapStyle;
- int ScaledBorderAndShadow;
- int Kerning;
- char *Language;
-
- int default_style; // index of default style
- char *name; // file name in case of external subs, 0 for streams
-
- ASS_Library *library;
- ASS_ParserPriv *parser_priv;
-} ASS_Track;
-
-#endif /* LIBASS_TYPES_H */
diff --git a/lib/libass/libass/ass_utils.c b/lib/libass/libass/ass_utils.c
deleted file mode 100644
index 2fd46c4b45..0000000000
--- a/lib/libass/libass/ass_utils.c
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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 <stdlib.h>
-#include <stdio.h>
-#include <inttypes.h>
-#include <ft2build.h>
-#include FT_GLYPH_H
-#ifndef _WIN32
-#include <strings.h>
-#endif
-
-#include "ass_library.h"
-#include "ass.h"
-#include "ass_utils.h"
-
-#ifdef _WIN32
-FILE *fopen_utf8(const char *_Filename, const char *_Mode)
-{
- return fopen(_Filename, _Mode);
-}
-#endif
-
-int mystrtoi(char **p, int *res)
-{
- double temp_res;
- char *start = *p;
- temp_res = ass_strtod(*p, p);
- *res = (int) (temp_res + (temp_res > 0 ? 0.5 : -0.5));
- if (*p != start)
- return 1;
- else
- return 0;
-}
-
-int mystrtoll(char **p, long long *res)
-{
- double temp_res;
- char *start = *p;
- temp_res = ass_strtod(*p, p);
- *res = (int) (temp_res + (temp_res > 0 ? 0.5 : -0.5));
- if (*p != start)
- return 1;
- else
- return 0;
-}
-
-int mystrtou32(char **p, int base, uint32_t *res)
-{
- char *start = *p;
- *res = strtoll(*p, p, base);
- if (*p != start)
- return 1;
- else
- return 0;
-}
-
-int mystrtod(char **p, double *res)
-{
- char *start = *p;
- *res = ass_strtod(*p, p);
- if (*p != start)
- return 1;
- else
- return 0;
-}
-
-int strtocolor(ASS_Library *library, char **q, uint32_t *res, int hex)
-{
- uint32_t color = 0;
- int result;
- char *p = *q;
- int base = hex ? 16 : 10;
-
- if (*p == '&')
- ++p;
- else
- ass_msg(library, MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
-
- if (*p == 'H' || *p == 'h') {
- ++p;
- result = mystrtou32(&p, 16, &color);
- } else {
- result = mystrtou32(&p, base, &color);
- }
-
- {
- unsigned char *tmp = (unsigned char *) (&color);
- unsigned char b;
- b = tmp[0];
- tmp[0] = tmp[3];
- tmp[3] = b;
- b = tmp[1];
- tmp[1] = tmp[2];
- tmp[2] = b;
- }
- if (*p == '&')
- ++p;
- *q = p;
-
- *res = color;
- return result;
-}
-
-// Return a boolean value for a string
-char parse_bool(char *str)
-{
- while (*str == ' ' || *str == '\t')
- str++;
- if (!strncasecmp(str, "yes", 3))
- return 1;
- else if (strtol(str, NULL, 10) > 0)
- return 1;
- return 0;
-}
-
-void ass_msg(ASS_Library *priv, int lvl, char *fmt, ...)
-{
- va_list va;
- va_start(va, fmt);
- priv->msg_callback(lvl, fmt, va, priv->msg_callback_data);
- va_end(va);
-}
-
-unsigned ass_utf8_get_char(char **str)
-{
- uint8_t *strp = (uint8_t *) * str;
- unsigned c = *strp++;
- unsigned mask = 0x80;
- int len = -1;
- while (c & mask) {
- mask >>= 1;
- len++;
- }
- if (len <= 0 || len > 4)
- goto no_utf8;
- c &= mask - 1;
- while ((*strp & 0xc0) == 0x80) {
- if (len-- <= 0)
- goto no_utf8;
- c = (c << 6) | (*strp++ & 0x3f);
- }
- if (len)
- goto no_utf8;
- *str = (char *) strp;
- return c;
-
- no_utf8:
- strp = (uint8_t *) * str;
- c = *strp++;
- *str = (char *) strp;
- return c;
-}
-
-#ifdef CONFIG_ENCA
-void *ass_guess_buffer_cp(ASS_Library *library, unsigned char *buffer,
- int buflen, char *preferred_language,
- char *fallback)
-{
- const char **languages;
- size_t langcnt;
- EncaAnalyser analyser;
- EncaEncoding encoding;
- char *detected_sub_cp = NULL;
- int i;
-
- languages = enca_get_languages(&langcnt);
- ass_msg(library, MSGL_V, "ENCA supported languages");
- for (i = 0; i < langcnt; i++) {
- ass_msg(library, MSGL_V, "lang %s", languages[i]);
- }
-
- for (i = 0; i < langcnt; i++) {
- const char *tmp;
-
- if (strcasecmp(languages[i], preferred_language) != 0)
- continue;
- analyser = enca_analyser_alloc(languages[i]);
- encoding = enca_analyse_const(analyser, buffer, buflen);
- tmp = enca_charset_name(encoding.charset, ENCA_NAME_STYLE_ICONV);
- if (tmp && encoding.charset != ENCA_CS_UNKNOWN) {
- detected_sub_cp = strdup(tmp);
- ass_msg(library, MSGL_INFO, "ENCA detected charset: %s", tmp);
- }
- enca_analyser_free(analyser);
- }
-
- free(languages);
-
- if (!detected_sub_cp) {
- detected_sub_cp = strdup(fallback);
- ass_msg(library, MSGL_INFO,
- "ENCA detection failed: fallback to %s", fallback);
- }
-
- return detected_sub_cp;
-}
-#endif
diff --git a/lib/libass/libass/ass_utils.h b/lib/libass/libass/ass_utils.h
deleted file mode 100644
index f0093973da..0000000000
--- a/lib/libass/libass/ass_utils.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef LIBASS_UTILS_H
-#define LIBASS_UTILS_H
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-
-#ifdef CONFIG_ENCA
-#include <enca.h>
-#endif
-
-#include "ass.h"
-
-#ifdef _WIN32
-#include "config.h"
-// This is needed in debug build. Without those defines, those 3 symbols are taken from msvcr100.dll, and free() from msvcr100d.dll
-// This cause a heap corruption each time a strdup is freed
-// See http://www.altdevblogaday.com/2011/08/02/a-journey-into-linker-hell-and-a-mistake/
-#define strdup _strdup
-#define stricmp _stricmp
-#define strnicmp _strnicmp
-#endif
-
-#define MSGL_FATAL 0
-#define MSGL_ERR 1
-#define MSGL_WARN 2
-#define MSGL_INFO 4
-#define MSGL_V 6
-#define MSGL_DBG2 7
-
-#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
-#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
-#define FFMINMAX(c,a,b) FFMIN(FFMAX(c, a), b)
-
-int mystrtoi(char **p, int *res);
-int mystrtoll(char **p, long long *res);
-int mystrtou32(char **p, int base, uint32_t *res);
-int mystrtod(char **p, double *res);
-int strtocolor(ASS_Library *library, char **q, uint32_t *res, int hex);
-char parse_bool(char *str);
-unsigned ass_utf8_get_char(char **str);
-void ass_msg(ASS_Library *priv, int lvl, char *fmt, ...);
-#ifdef CONFIG_ENCA
-void *ass_guess_buffer_cp(ASS_Library *library, unsigned char *buffer,
- int buflen, char *preferred_language,
- char *fallback);
-#endif
-
-/* defined in ass_strtod.c */
-double ass_strtod(const char *string, char **endPtr);
-
-static inline int d6_to_int(int x)
-{
- return (x + 32) >> 6;
-}
-static inline int d16_to_int(int x)
-{
- return (x + 32768) >> 16;
-}
-static inline int int_to_d6(int x)
-{
- return x << 6;
-}
-static inline int int_to_d16(int x)
-{
- return x << 16;
-}
-static inline int d16_to_d6(int x)
-{
- return (x + 512) >> 10;
-}
-static inline int d6_to_d16(int x)
-{
- return x << 10;
-}
-static inline double d6_to_double(int x)
-{
- return x / 64.;
-}
-static inline int double_to_d6(double x)
-{
- return (int) (x * 64);
-}
-static inline double d16_to_double(int x)
-{
- return ((double) x) / 0x10000;
-}
-static inline int double_to_d16(double x)
-{
- return (int) (x * 0x10000);
-}
-static inline double d22_to_double(int x)
-{
- return ((double) x) / 0x400000;
-}
-static inline int double_to_d22(double x)
-{
- return (int) (x * 0x400000);
-}
-
-// Calculate cache key for a rotational angle in degrees
-static inline int rot_key(double a)
-{
- const int m = double_to_d22(360.0);
- return double_to_d22(a) % m;
-}
-
-#define FNV1_32A_INIT (unsigned)0x811c9dc5
-
-static inline unsigned fnv_32a_buf(void *buf, size_t len, unsigned hval)
-{
- unsigned char *bp = buf;
- unsigned char *be = bp + len;
- while (bp < be) {
- hval ^= (unsigned) *bp++;
- hval +=
- (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) +
- (hval << 24);
- }
- return hval;
-}
-static inline unsigned fnv_32a_str(char *str, unsigned hval)
-{
- unsigned char *s = (unsigned char *) str;
- while (*s) {
- hval ^= (unsigned) *s++;
- hval +=
- (hval << 1) + (hval << 4) + (hval << 7) + (hval << 8) +
- (hval << 24);
- }
- return hval;
-}
-
-#endif /* LIBASS_UTILS_H */
diff --git a/lib/libass/libass/libass.sym b/lib/libass/libass/libass.sym
deleted file mode 100644
index f8fa1458a1..0000000000
--- a/lib/libass/libass/libass.sym
+++ /dev/null
@@ -1,37 +0,0 @@
-ass_library_init
-ass_library_done
-ass_set_fonts_dir
-ass_set_extract_fonts
-ass_set_style_overrides
-ass_renderer_init
-ass_renderer_done
-ass_set_frame_size
-ass_set_margins
-ass_set_use_margins
-ass_set_aspect_ratio
-ass_set_font_scale
-ass_set_hinting
-ass_set_line_spacing
-ass_set_fonts
-ass_render_frame
-ass_new_track
-ass_free_track
-ass_alloc_style
-ass_alloc_event
-ass_free_style
-ass_free_event
-ass_process_data
-ass_process_codec_private
-ass_process_chunk
-ass_read_file
-ass_read_memory
-ass_read_styles
-ass_add_font
-ass_clear_fonts
-ass_step_sub
-ass_process_force_style
-ass_set_message_cb
-ass_fonts_update
-ass_set_cache_limits
-ass_flush_events
-ass_set_shaper
diff --git a/lib/libass/m4/.gitignore b/lib/libass/m4/.gitignore
deleted file mode 100644
index e69de29bb2..0000000000
--- a/lib/libass/m4/.gitignore
+++ /dev/null
diff --git a/lib/libass/test/Makefile.am b/lib/libass/test/Makefile.am
deleted file mode 100644
index 208c9cf37b..0000000000
--- a/lib/libass/test/Makefile.am
+++ /dev/null
@@ -1,7 +0,0 @@
-AM_CFLAGS = -Wall
-
-noinst_PROGRAMS = test
-test_SOURCES = test.c
-test_CPPFLAGS = -I../libass
-test_LDADD = ../libass/libass.la
-test_LDFLAGS = $(AM_LDFLAGS) $(LIBPNG_LIBS)
diff --git a/lib/libass/test/test.c b/lib/libass/test/test.c
deleted file mode 100644
index d6cd9b8672..0000000000
--- a/lib/libass/test/test.c
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
- * Copyright (C) 2009 Grigori Goronzy <greg@geekmind.org>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ass.h>
-#include <png.h>
-
-typedef struct image_s {
- int width, height, stride;
- unsigned char *buffer; // RGB24
-} image_t;
-
-ASS_Library *ass_library;
-ASS_Renderer *ass_renderer;
-
-void msg_callback(int level, const char *fmt, va_list va, void *data)
-{
- if (level > 6)
- return;
- printf("libass: ");
- vprintf(fmt, va);
- printf("\n");
-}
-
-static void write_png(char *fname, image_t *img)
-{
- FILE *fp;
- png_structp png_ptr;
- png_infop info_ptr;
- png_byte **row_pointers;
- int k;
-
- png_ptr =
- png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
- info_ptr = png_create_info_struct(png_ptr);
- fp = NULL;
-
- if (setjmp(png_jmpbuf(png_ptr))) {
- png_destroy_write_struct(&png_ptr, &info_ptr);
- fclose(fp);
- return;
- }
-
- fp = fopen(fname, "wb");
- if (fp == NULL) {
- printf("PNG Error opening %s for writing!\n", fname);
- return;
- }
-
- png_init_io(png_ptr, fp);
- png_set_compression_level(png_ptr, 0);
-
- png_set_IHDR(png_ptr, info_ptr, img->width, img->height,
- 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
-
- png_write_info(png_ptr, info_ptr);
-
- png_set_bgr(png_ptr);
-
- row_pointers = (png_byte **) malloc(img->height * sizeof(png_byte *));
- for (k = 0; k < img->height; k++)
- row_pointers[k] = img->buffer + img->stride * k;
-
- png_write_image(png_ptr, row_pointers);
- png_write_end(png_ptr, info_ptr);
- png_destroy_write_struct(&png_ptr, &info_ptr);
-
- free(row_pointers);
-
- fclose(fp);
-}
-
-static void init(int frame_w, int frame_h)
-{
- ass_library = ass_library_init();
- if (!ass_library) {
- printf("ass_library_init failed!\n");
- exit(1);
- }
-
- ass_set_message_cb(ass_library, msg_callback, NULL);
-
- ass_renderer = ass_renderer_init(ass_library);
- if (!ass_renderer) {
- printf("ass_renderer_init failed!\n");
- exit(1);
- }
-
- ass_set_frame_size(ass_renderer, frame_w, frame_h);
- ass_set_fonts(ass_renderer, NULL, "Sans", 1, NULL, 1);
-}
-
-static image_t *gen_image(int width, int height)
-{
- image_t *img = malloc(sizeof(image_t));
- img->width = width;
- img->height = height;
- img->stride = width * 3;
- img->buffer = (unsigned char *) calloc(1, height * width * 3);
- memset(img->buffer, 63, img->stride * img->height);
- //for (int i = 0; i < height * width * 3; ++i)
- // img->buffer[i] = (i/3/50) % 100;
- return img;
-}
-
-#define _r(c) ((c)>>24)
-#define _g(c) (((c)>>16)&0xFF)
-#define _b(c) (((c)>>8)&0xFF)
-#define _a(c) ((c)&0xFF)
-
-static void blend_single(image_t * frame, ASS_Image *img)
-{
- int x, y;
- unsigned char opacity = 255 - _a(img->color);
- unsigned char r = _r(img->color);
- unsigned char g = _g(img->color);
- unsigned char b = _b(img->color);
-
- unsigned char *src;
- unsigned char *dst;
-
- src = img->bitmap;
- dst = frame->buffer + img->dst_y * frame->stride + img->dst_x * 3;
- for (y = 0; y < img->h; ++y) {
- for (x = 0; x < img->w; ++x) {
- unsigned k = ((unsigned) src[x]) * opacity / 255;
- // possible endianness problems
- dst[x * 3] = (k * b + (255 - k) * dst[x * 3]) / 255;
- dst[x * 3 + 1] = (k * g + (255 - k) * dst[x * 3 + 1]) / 255;
- dst[x * 3 + 2] = (k * r + (255 - k) * dst[x * 3 + 2]) / 255;
- }
- src += img->stride;
- dst += frame->stride;
- }
-}
-
-static void blend(image_t * frame, ASS_Image *img)
-{
- int cnt = 0;
- while (img) {
- blend_single(frame, img);
- ++cnt;
- img = img->next;
- }
- printf("%d images blended\n", cnt);
-}
-
-int main(int argc, char *argv[])
-{
- const int frame_w = 640;
- const int frame_h = 480;
-
- if (argc < 4) {
- printf("usage: %s <image file> <subtitle file> <time>\n", argv[0]);
- exit(1);
- }
- char *imgfile = argv[1];
- char *subfile = argv[2];
- double tm = strtod(argv[3], 0);
-
- init(frame_w, frame_h);
- ASS_Track *track = ass_read_file(ass_library, subfile, NULL);
- if (!track) {
- printf("track init failed!\n");
- return 1;
- }
-
- ASS_Image *img =
- ass_render_frame(ass_renderer, track, (int) (tm * 1000), NULL);
- image_t *frame = gen_image(frame_w, frame_h);
- blend(frame, img);
-
- ass_free_track(track);
- ass_renderer_done(ass_renderer);
- ass_library_done(ass_library);
-
- write_png(imgfile, frame);
- free(frame->buffer);
- free(frame);
-
- return 0;
-}
diff --git a/lib/libass/xbmc/libass_win32/config.h b/lib/libass/xbmc/libass_win32/config.h
deleted file mode 100644
index ad0bc866fe..0000000000
--- a/lib/libass/xbmc/libass_win32/config.h
+++ /dev/null
@@ -1,183 +0,0 @@
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#undef HAVE_DLFCN_H
-
-/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
-#undef HAVE_DOPRNT
-
-/* use enca */
-#define CONFIG_ENCA 1
-
-/* Define to 1 if you have the <enca.h> header file. */
-#undef HAVE_ENCA_H
-
-/* found fontconfig via pkg-config */
-#define CONFIG_FONTCONFIG
-
-/* found freetype2 via pkg-config */
-#undef HAVE_FREETYPE
-
-/* Define to 1 if you have the <iconv.h> header file. */
-#undef HAVE_ICONV_H
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#undef HAVE_INTTYPES_H
-
-/* use libpng */
-#undef HAVE_LIBPNG
-
-/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
- to 0 otherwise. */
-#undef HAVE_MALLOC
-
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
-/* Define to 1 if you have the `memset' function. */
-#undef HAVE_MEMSET
-
-/* Define to 1 if you have the `mkdir' function. */
-#undef HAVE_MKDIR
-
-/* Define to 1 if your system has a GNU libc compatible `realloc' function,
- and to 0 otherwise. */
-#undef HAVE_REALLOC
-
-/* Define to 1 if `stat' has the bug that it succeeds when given the
- zero-length file name argument. */
-#undef HAVE_STAT_EMPTY_STRING_BUG
-
-/* Define to 1 if stdbool.h conforms to C99. */
-#undef HAVE_STDBOOL_H
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#undef HAVE_STDINT_H
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#undef HAVE_STDLIB_H
-
-/* Define to 1 if you have the `strcasecmp' function. */
-#undef HAVE_STRCASECMP
-
-/* Define to 1 if you have the `strchr' function. */
-#undef HAVE_STRCHR
-
-/* Define to 1 if you have the `strdup' function. */
-#undef HAVE_STRDUP
-
-/* Define to 1 if you have the `strerror' function. */
-#undef HAVE_STRERROR
-
-/* Define to 1 if you have the <strings.h> header file. */
-#undef HAVE_STRINGS_H
-
-/* Define to 1 if you have the <string.h> header file. */
-#undef HAVE_STRING_H
-
-/* Define to 1 if you have the `strstr' function. */
-#undef HAVE_STRSTR
-
-/* Define to 1 if you have the `strtol' function. */
-#undef HAVE_STRTOL
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#undef HAVE_SYS_STAT_H
-
-/* Define to 1 if you have the <sys/time.h> header file. */
-#undef HAVE_SYS_TIME_H
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#undef HAVE_SYS_TYPES_H
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#undef HAVE_UNISTD_H
-
-/* Define to 1 if you have the `vprintf' function. */
-#undef HAVE_VPRINTF
-
-/* Define to 1 if the system has the type `_Bool'. */
-#undef HAVE__BOOL
-
-/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
- slash. */
-#undef LSTAT_FOLLOWS_SLASHED_SYMLINK
-
-/* Name of package */
-#undef PACKAGE
-
-/* Define to the address where bug reports for this package should be sent. */
-#undef PACKAGE_BUGREPORT
-
-/* Define to the full name of this package. */
-#undef PACKAGE_NAME
-
-/* Define to the full name and version of this package. */
-#undef PACKAGE_STRING
-
-/* Define to the one symbol short name of this package. */
-#undef PACKAGE_TARNAME
-
-/* Define to the version of this package. */
-#undef PACKAGE_VERSION
-
-/* Define to 1 if you have the ANSI C header files. */
-#undef STDC_HEADERS
-
-/* Define to 1 if your <sys/time.h> declares `struct tm'. */
-#undef TM_IN_SYS_TIME
-
-/* use iconv */
-#define CONFIG_ICONV 1
-
-/* Version number of package */
-#undef VERSION
-
-/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
- <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
- #define below would cause a syntax error. */
-#undef _UINT32_T
-
-/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
- <pthread.h>, or <semaphore.h> is not used. If the typedef was allowed, the
- #define below would cause a syntax error. */
-#undef _UINT8_T
-
-/* Define to empty if `const' does not conform to ANSI C. */
-#undef const
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-#define inline __inline
-#endif
-
-/* Define to the type of a signed integer type of width exactly 64 bits if
- such a type exists and the standard includes do not define it. */
-#undef int64_t
-
-/* Define to rpl_malloc if the replacement function should be used. */
-#undef malloc
-
-/* Define to rpl_realloc if the replacement function should be used. */
-#undef realloc
-
-/* Define to `unsigned int' if <sys/types.h> does not define. */
-#undef size_t
-
-/* Define to the type of an unsigned integer type of width exactly 32 bits if
- such a type exists and the standard includes do not define it. */
-#undef uint32_t
-
-/* Define to the type of an unsigned integer type of width exactly 8 bits if
- such a type exists and the standard includes do not define it. */
-#undef uint8_t
-
-#ifndef M_PI
-#define M_PI 3.1415926535897932384626433832795
-#endif
-
-#define strncasecmp strnicmp
-#define strcasecmp stricmp
-
-#define strtoll(p, e, b) _strtoi64(p, e, b)
diff --git a/lib/libass/xbmc/libass_win32/getopt.h b/lib/libass/xbmc/libass_win32/getopt.h
deleted file mode 100644
index ff0251dec0..0000000000
--- a/lib/libass/xbmc/libass_win32/getopt.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/* Declarations for getopt.
- Copyright (C) 1989-1994,1996-1999,2001,2003,2004,2009
- Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA. */
-
-#ifndef _GETOPT_H
-
-#ifndef __need_getopt
-# define _GETOPT_H 1
-#endif
-
-/* If __GNU_LIBRARY__ is not already defined, either we are being used
- standalone, or this is the first header included in the source file.
- If we are being used with glibc, we need to include <features.h>, but
- that does not exist if we are standalone. So: if __GNU_LIBRARY__ is
- not defined, include <ctype.h>, which will pull in <features.h> for us
- if it's from glibc. (Why ctype.h? It's guaranteed to exist and it
- doesn't flood the namespace with stuff the way some other headers do.) */
-#if !defined __GNU_LIBRARY__
-# include <ctype.h>
-#endif
-
-#ifndef __THROW
-# ifndef __GNUC_PREREQ
-# define __GNUC_PREREQ(maj, min) (0)
-# endif
-# if defined __cplusplus && __GNUC_PREREQ (2,8)
-# define __THROW throw ()
-# else
-# define __THROW
-# endif
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* For communication from `getopt' to the caller.
- When `getopt' finds an option that takes an argument,
- the argument value is returned here.
- Also, when `ordering' is RETURN_IN_ORDER,
- each non-option ARGV-element is returned here. */
-
-extern char *optarg;
-
-/* Index in ARGV of the next element to be scanned.
- This is used for communication to and from the caller
- and for communication between successive calls to `getopt'.
-
- On entry to `getopt', zero means this is the first call; initialize.
-
- When `getopt' returns -1, this is the index of the first of the
- non-option elements that the caller should itself scan.
-
- Otherwise, `optind' communicates from one call to the next
- how much of ARGV has been scanned so far. */
-
-extern int optind;
-
-/* Callers store zero here to inhibit the error message `getopt' prints
- for unrecognized options. */
-
-extern int opterr;
-
-/* Set to an option character which was unrecognized. */
-
-extern int optopt;
-
-#ifndef __need_getopt
-/* Describe the long-named options requested by the application.
- The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
- of `struct option' terminated by an element containing a name which is
- zero.
-
- The field `has_arg' is:
- no_argument (or 0) if the option does not take an argument,
- required_argument (or 1) if the option requires an argument,
- optional_argument (or 2) if the option takes an optional argument.
-
- If the field `flag' is not NULL, it points to a variable that is set
- to the value given in the field `val' when the option is found, but
- left unchanged if the option is not found.
-
- To have a long-named option do something other than set an `int' to
- a compiled-in constant, such as set a value from `optarg', set the
- option's `flag' field to zero and its `val' field to a nonzero
- value (the equivalent single-letter option character, if there is
- one). For long options that have a zero `flag' field, `getopt'
- returns the contents of the `val' field. */
-
-struct option
-{
- const char *name;
- /* has_arg can't be an enum because some compilers complain about
- type mismatches in all the code that assumes it is an int. */
- int has_arg;
- int *flag;
- int val;
-};
-
-/* Names for the values of the `has_arg' field of `struct option'. */
-
-# define no_argument 0
-# define required_argument 1
-# define optional_argument 2
-#endif /* need getopt */
-
-
-/* Get definitions and prototypes for functions to process the
- arguments in ARGV (ARGC of them, minus the program name) for
- options given in OPTS.
-
- Return the option character from OPTS just read. Return -1 when
- there are no more options. For unrecognized options, or options
- missing arguments, `optopt' is set to the option letter, and '?' is
- returned.
-
- The OPTS string is a list of characters which are recognized option
- letters, optionally followed by colons, specifying that that letter
- takes an argument, to be placed in `optarg'.
-
- If a letter in OPTS is followed by two colons, its argument is
- optional. This behavior is specific to the GNU `getopt'.
-
- The argument `--' causes premature termination of argument
- scanning, explicitly telling `getopt' that there are no more
- options.
-
- If OPTS begins with `--', then non-option arguments are treated as
- arguments to the option '\0'. This behavior is specific to the GNU
- `getopt'. */
-
-#ifdef __GNU_LIBRARY__
-/* Many other libraries have conflicting prototypes for getopt, with
- differences in the consts, in stdlib.h. To avoid compilation
- errors, only prototype getopt for the GNU C library. */
-extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
- __THROW;
-
-# if defined __need_getopt && defined __USE_POSIX2 \
- && !defined __USE_POSIX_IMPLICITLY && !defined __USE_GNU
-/* The GNU getopt has more functionality than the standard version. The
- additional functionality can be disable at runtime. This redirection
- helps to also do this at runtime. */
-# ifdef __REDIRECT
- extern int __REDIRECT (getopt, (int ___argc, char *const *___argv,
- const char *__shortopts),
- __posix_getopt) __THROW;
-# else
-extern int __posix_getopt (int ___argc, char *const *___argv,
- const char *__shortopts) __THROW;
-# define getopt __posix_getopt
-# endif
-# endif
-#else /* not __GNU_LIBRARY__ */
-extern int getopt ();
-#endif /* __GNU_LIBRARY__ */
-
-#ifndef __need_getopt
-extern int getopt_long (int ___argc, char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind)
- __THROW;
-extern int getopt_long_only (int ___argc, char *const *___argv,
- const char *__shortopts,
- const struct option *__longopts, int *__longind)
- __THROW;
-
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-/* Make sure we later can get all the definitions and declarations. */
-#undef __need_getopt
-
-#endif /* getopt.h */
diff --git a/lib/libass/xbmc/libass_win32/inttypes.h b/lib/libass/xbmc/libass_win32/inttypes.h
deleted file mode 100644
index 880d5329aa..0000000000
--- a/lib/libass/xbmc/libass_win32/inttypes.h
+++ /dev/null
@@ -1,306 +0,0 @@
-// ISO C9x compliant inttypes.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The name of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_INTTYPES_H_ // [
-#define _MSC_INTTYPES_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include <stdint.h>
-
-// 7.8 Format conversion of integer types
-
-typedef struct {
- intmax_t quot;
- intmax_t rem;
-} imaxdiv_t;
-
-// 7.8.1 Macros for format specifiers
-
-#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) // [ See footnote 185 at page 198
-
-// The fprintf macros for signed integers are:
-#define PRId8 "d"
-#define PRIi8 "i"
-#define PRIdLEAST8 "d"
-#define PRIiLEAST8 "i"
-#define PRIdFAST8 "d"
-#define PRIiFAST8 "i"
-
-#define PRId16 "hd"
-#define PRIi16 "hi"
-#define PRIdLEAST16 "hd"
-#define PRIiLEAST16 "hi"
-#define PRIdFAST16 "hd"
-#define PRIiFAST16 "hi"
-
-#define PRId32 "I32d"
-#define PRIi32 "I32i"
-#define PRIdLEAST32 "I32d"
-#define PRIiLEAST32 "I32i"
-#define PRIdFAST32 "I32d"
-#define PRIiFAST32 "I32i"
-
-#define PRId64 "I64d"
-#define PRIi64 "I64i"
-#define PRIdLEAST64 "I64d"
-#define PRIiLEAST64 "I64i"
-#define PRIdFAST64 "I64d"
-#define PRIiFAST64 "I64i"
-
-#define PRIdMAX "I64d"
-#define PRIiMAX "I64i"
-
-#define PRIdPTR "Id"
-#define PRIiPTR "Ii"
-
-// The fprintf macros for unsigned integers are:
-#define PRIo8 "o"
-#define PRIu8 "u"
-#define PRIx8 "x"
-#define PRIX8 "X"
-#define PRIoLEAST8 "o"
-#define PRIuLEAST8 "u"
-#define PRIxLEAST8 "x"
-#define PRIXLEAST8 "X"
-#define PRIoFAST8 "o"
-#define PRIuFAST8 "u"
-#define PRIxFAST8 "x"
-#define PRIXFAST8 "X"
-
-#define PRIo16 "ho"
-#define PRIu16 "hu"
-#define PRIx16 "hx"
-#define PRIX16 "hX"
-#define PRIoLEAST16 "ho"
-#define PRIuLEAST16 "hu"
-#define PRIxLEAST16 "hx"
-#define PRIXLEAST16 "hX"
-#define PRIoFAST16 "ho"
-#define PRIuFAST16 "hu"
-#define PRIxFAST16 "hx"
-#define PRIXFAST16 "hX"
-
-#define PRIo32 "I32o"
-#define PRIu32 "I32u"
-#define PRIx32 "I32x"
-#define PRIX32 "I32X"
-#define PRIoLEAST32 "I32o"
-#define PRIuLEAST32 "I32u"
-#define PRIxLEAST32 "I32x"
-#define PRIXLEAST32 "I32X"
-#define PRIoFAST32 "I32o"
-#define PRIuFAST32 "I32u"
-#define PRIxFAST32 "I32x"
-#define PRIXFAST32 "I32X"
-
-#define PRIo64 "I64o"
-#define PRIu64 "I64u"
-#define PRIx64 "I64x"
-#define PRIX64 "I64X"
-#define PRIoLEAST64 "I64o"
-#define PRIuLEAST64 "I64u"
-#define PRIxLEAST64 "I64x"
-#define PRIXLEAST64 "I64X"
-#define PRIoFAST64 "I64o"
-#define PRIuFAST64 "I64u"
-#define PRIxFAST64 "I64x"
-#define PRIXFAST64 "I64X"
-
-#define PRIoMAX "I64o"
-#define PRIuMAX "I64u"
-#define PRIxMAX "I64x"
-#define PRIXMAX "I64X"
-
-#define PRIoPTR "Io"
-#define PRIuPTR "Iu"
-#define PRIxPTR "Ix"
-#define PRIXPTR "IX"
-
-// The fscanf macros for signed integers are:
-#define SCNd8 "d"
-#define SCNi8 "i"
-#define SCNdLEAST8 "d"
-#define SCNiLEAST8 "i"
-#define SCNdFAST8 "d"
-#define SCNiFAST8 "i"
-
-#define SCNd16 "hd"
-#define SCNi16 "hi"
-#define SCNdLEAST16 "hd"
-#define SCNiLEAST16 "hi"
-#define SCNdFAST16 "hd"
-#define SCNiFAST16 "hi"
-
-#define SCNd32 "ld"
-#define SCNi32 "li"
-#define SCNdLEAST32 "ld"
-#define SCNiLEAST32 "li"
-#define SCNdFAST32 "ld"
-#define SCNiFAST32 "li"
-
-#define SCNd64 "I64d"
-#define SCNi64 "I64i"
-#define SCNdLEAST64 "I64d"
-#define SCNiLEAST64 "I64i"
-#define SCNdFAST64 "I64d"
-#define SCNiFAST64 "I64i"
-
-#define SCNdMAX "I64d"
-#define SCNiMAX "I64i"
-
-#ifdef _WIN64 // [
-# define SCNdPTR "I64d"
-# define SCNiPTR "I64i"
-#else // _WIN64 ][
-# define SCNdPTR "ld"
-# define SCNiPTR "li"
-#endif // _WIN64 ]
-
-// The fscanf macros for unsigned integers are:
-#define SCNo8 "o"
-#define SCNu8 "u"
-#define SCNx8 "x"
-#define SCNX8 "X"
-#define SCNoLEAST8 "o"
-#define SCNuLEAST8 "u"
-#define SCNxLEAST8 "x"
-#define SCNXLEAST8 "X"
-#define SCNoFAST8 "o"
-#define SCNuFAST8 "u"
-#define SCNxFAST8 "x"
-#define SCNXFAST8 "X"
-
-#define SCNo16 "ho"
-#define SCNu16 "hu"
-#define SCNx16 "hx"
-#define SCNX16 "hX"
-#define SCNoLEAST16 "ho"
-#define SCNuLEAST16 "hu"
-#define SCNxLEAST16 "hx"
-#define SCNXLEAST16 "hX"
-#define SCNoFAST16 "ho"
-#define SCNuFAST16 "hu"
-#define SCNxFAST16 "hx"
-#define SCNXFAST16 "hX"
-
-#define SCNo32 "lo"
-#define SCNu32 "lu"
-#define SCNx32 "lx"
-#define SCNX32 "lX"
-#define SCNoLEAST32 "lo"
-#define SCNuLEAST32 "lu"
-#define SCNxLEAST32 "lx"
-#define SCNXLEAST32 "lX"
-#define SCNoFAST32 "lo"
-#define SCNuFAST32 "lu"
-#define SCNxFAST32 "lx"
-#define SCNXFAST32 "lX"
-
-#define SCNo64 "I64o"
-#define SCNu64 "I64u"
-#define SCNx64 "I64x"
-#define SCNX64 "I64X"
-#define SCNoLEAST64 "I64o"
-#define SCNuLEAST64 "I64u"
-#define SCNxLEAST64 "I64x"
-#define SCNXLEAST64 "I64X"
-#define SCNoFAST64 "I64o"
-#define SCNuFAST64 "I64u"
-#define SCNxFAST64 "I64x"
-#define SCNXFAST64 "I64X"
-
-#define SCNoMAX "I64o"
-#define SCNuMAX "I64u"
-#define SCNxMAX "I64x"
-#define SCNXMAX "I64X"
-
-#ifdef _WIN64 // [
-# define SCNoPTR "I64o"
-# define SCNuPTR "I64u"
-# define SCNxPTR "I64x"
-# define SCNXPTR "I64X"
-#else // _WIN64 ][
-# define SCNoPTR "lo"
-# define SCNuPTR "lu"
-# define SCNxPTR "lx"
-# define SCNXPTR "lX"
-#endif // _WIN64 ]
-
-#endif // __STDC_FORMAT_MACROS ]
-
-// 7.8.2 Functions for greatest-width integer types
-
-// 7.8.2.1 The imaxabs function
-#define imaxabs _abs64
-
-// 7.8.2.2 The imaxdiv function
-
-// This is modified version of div() function from Microsoft's div.c found
-// in %MSVC.NET%\crt\src\div.c
-#ifdef STATIC_IMAXDIV // [
-static
-#else // STATIC_IMAXDIV ][
-_inline
-#endif // STATIC_IMAXDIV ]
-imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom)
-{
- imaxdiv_t result;
-
- result.quot = numer / denom;
- result.rem = numer % denom;
-
- if (numer < 0 && result.rem > 0) {
- // did division wrong; must fix up
- ++result.quot;
- result.rem -= denom;
- }
-
- return result;
-}
-
-// 7.8.2.3 The strtoimax and strtoumax functions
-#define strtoimax _strtoi64
-#define strtoumax _strtoui64
-
-// 7.8.2.4 The wcstoimax and wcstoumax functions
-#define wcstoimax _wcstoi64
-#define wcstoumax _wcstoui64
-
-#define ssize_t int
-
-#endif // _MSC_INTTYPES_H_ ]
diff --git a/lib/libass/xbmc/libass_win32/libass.def b/lib/libass/xbmc/libass_win32/libass.def
deleted file mode 100644
index 07faca3f60..0000000000
--- a/lib/libass/xbmc/libass_win32/libass.def
+++ /dev/null
@@ -1,38 +0,0 @@
-LIBRARY libass.dll
-EXPORTS
-
-ass_library_init @1
-ass_library_done @2
-ass_set_fonts_dir @3
-ass_set_extract_fonts @4
-ass_set_style_overrides @5
-ass_process_force_style @6
-ass_set_message_cb @7
-ass_renderer_init @8
-ass_renderer_done @9
-ass_set_frame_size @10
-ass_set_margins @11
-ass_set_use_margins @12
-ass_set_aspect_ratio @13
-ass_set_font_scale @14
-ass_set_hinting @15
-ass_set_line_spacing @16
-ass_set_fonts @17
-ass_fonts_update @18
-ass_set_cache_limits @19
-ass_render_frame @20
-ass_new_track @21
-ass_free_track @22
-ass_alloc_style @23
-ass_alloc_event @24
-ass_free_style @25
-ass_free_event @26
-ass_process_data @27
-ass_process_codec_private @28
-ass_process_chunk @29
-ass_read_file @30
-ass_read_memory @31
-ass_read_styles @32
-ass_add_font @33
-ass_clear_fonts @34
-ass_step_sub @35 \ No newline at end of file
diff --git a/lib/libass/xbmc/libass_win32/libass_win32_vs2008.sln b/lib/libass/xbmc/libass_win32/libass_win32_vs2008.sln
deleted file mode 100644
index 5e22aa1cac..0000000000
--- a/lib/libass/xbmc/libass_win32/libass_win32_vs2008.sln
+++ /dev/null
@@ -1,20 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 10.00
-# Visual C++ Express 2008
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libass_win32", "libass_win32_vs2008.vcproj", "{BA5B08FC-2ECB-4571-9F25-F8054522FC65}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug|Win32.ActiveCfg = Debug|Win32
- {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug|Win32.Build.0 = Debug|Win32
- {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release|Win32.ActiveCfg = Release|Win32
- {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj b/lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj
deleted file mode 100644
index 0b226a1605..0000000000
--- a/lib/libass/xbmc/libass_win32/libass_win32_vs2010.vcxproj
+++ /dev/null
@@ -1,178 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <ItemGroup Label="ProjectConfigurations">
- <ProjectConfiguration Include="Debug|Win32">
- <Configuration>Debug</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- <ProjectConfiguration Include="Release|Win32">
- <Configuration>Release</Configuration>
- <Platform>Win32</Platform>
- </ProjectConfiguration>
- </ItemGroup>
- <PropertyGroup Label="Globals">
- <ProjectName>libass_dll</ProjectName>
- <ProjectGuid>{BA5B08FC-2ECB-4571-9F25-F8054522FC65}</ProjectGuid>
- <RootNamespace>libass_win32</RootNamespace>
- <Keyword>Win32Proj</Keyword>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>false</UseDebugLibraries>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
- <ConfigurationType>DynamicLibrary</ConfigurationType>
- <UseDebugLibraries>true</UseDebugLibraries>
- <CharacterSet>Unicode</CharacterSet>
- </PropertyGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
- <ImportGroup Label="ExtensionSettings">
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\..\project\VS2010Express\XBMC for Windows.props" />
- </ImportGroup>
- <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
- <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
- <Import Project="..\..\..\..\project\VS2010Express\XBMC for Windows.props" />
- </ImportGroup>
- <PropertyGroup Label="UserMacros" />
- <PropertyGroup>
- <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
- <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)libs\$(TargetName)\$(Configuration)\</OutDir>
- <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(SolutionDir)objs\$(TargetName)\$(Configuration)\</IntDir>
- <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">libass</TargetName>
- <TargetName Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">libass</TargetName>
- <CustomBuildAfterTargets Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Build</CustomBuildAfterTargets>
- <CustomBuildAfterTargets Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Build</CustomBuildAfterTargets>
- </PropertyGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
- <ClCompile>
- <Optimization>Disabled</Optimization>
- <AdditionalIncludeDirectories>.\;..\..\..\enca\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LIBASS_WIN32_EXPORTS;CONFIG_HARFBUZZ;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <MinimalRebuild>true</MinimalRebuild>
- <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
- <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
- <DisableSpecificWarnings>4001;4996;4244;4267;4018;4005;%(DisableSpecificWarnings)</DisableSpecificWarnings>
- <CompileAs>CompileAsC</CompileAs>
- <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
- </ClCompile>
- <Link>
- <AdditionalDependencies>fontconfig.lib;zlib.lib;harfbuzz.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <IgnoreSpecificDefaultLibraries>libcmt;libcmtd;msvcrt;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <ProgramDatabaseFile>Debug/libass_win32.pdb</ProgramDatabaseFile>
- <SubSystem>Windows</SubSystem>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- <DataExecutionPrevention>
- </DataExecutionPrevention>
- <ImportLibrary>$(Configuration)\vs2010\$(TargetName)_win32.lib</ImportLibrary>
- <TargetMachine>MachineX86</TargetMachine>
- <AdditionalLibraryDirectories>
- </AdditionalLibraryDirectories>
- <ModuleDefinitionFile>libass.def</ModuleDefinitionFile>
- </Link>
- <CustomBuildStep>
- <Command>copy /B /Y "$(TargetPath)" "$(SolutionDir)..\..\system\players\dvdplayer\$(TargetFileName)"</Command>
- <Message>Copy Output</Message>
- <Outputs>$(SolutionDir)..\..\system\players\dvdplayer\$(TargetFileName)</Outputs>
- <Inputs>$(TargetPath)</Inputs>
- </CustomBuildStep>
- </ItemDefinitionGroup>
- <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
- <ClCompile>
- <Optimization>Full</Optimization>
- <AdditionalIncludeDirectories>.\;..\..\..\enca\lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
- <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LIBASS_WIN32_EXPORTS;CONFIG_HARFBUZZ;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
- <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
- <PrecompiledHeader>
- </PrecompiledHeader>
- <WarningLevel>Level3</WarningLevel>
- <DebugInformationFormat>
- </DebugInformationFormat>
- <DisableSpecificWarnings>4001;4996;4244;4267;4018;4005;%(DisableSpecificWarnings)</DisableSpecificWarnings>
- <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
- </ClCompile>
- <Link>
- <AdditionalDependencies>fontconfig.lib;zlib.lib;harfbuzz.lib;%(AdditionalDependencies)</AdditionalDependencies>
- <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile>
- <IgnoreSpecificDefaultLibraries>libcmt;libcmtd;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
- <GenerateDebugInformation>true</GenerateDebugInformation>
- <ProgramDatabaseFile>Release/$(TargetName).pdb</ProgramDatabaseFile>
- <SubSystem>Windows</SubSystem>
- <OptimizeReferences>true</OptimizeReferences>
- <EnableCOMDATFolding>true</EnableCOMDATFolding>
- <RandomizedBaseAddress>false</RandomizedBaseAddress>
- <DataExecutionPrevention>
- </DataExecutionPrevention>
- <ImportLibrary>$(Configuration)\vs2010\$(TargetName)_win32.lib</ImportLibrary>
- <TargetMachine>MachineX86</TargetMachine>
- <AdditionalLibraryDirectories>
- </AdditionalLibraryDirectories>
- <ModuleDefinitionFile>libass.def</ModuleDefinitionFile>
- </Link>
- <CustomBuildStep>
- <Command>copy /B /Y "$(TargetPath)" "$(SolutionDir)..\..\system\players\dvdplayer\$(TargetFileName)"</Command>
- <Message>Copy Output</Message>
- <Inputs>$(TargetPath)</Inputs>
- <Outputs>$(SolutionDir)..\..\system\players\dvdplayer\$(TargetFileName)</Outputs>
- </CustomBuildStep>
- </ItemDefinitionGroup>
- <ItemGroup>
- <ClInclude Include="..\..\libass\ass.h" />
- <ClInclude Include="..\..\libass\ass_bitmap.h" />
- <ClInclude Include="..\..\libass\ass_cache.h" />
- <ClInclude Include="..\..\libass\ass_cache_template.h" />
- <ClInclude Include="..\..\libass\ass_drawing.h" />
- <ClInclude Include="..\..\libass\ass_font.h" />
- <ClInclude Include="..\..\libass\ass_fontconfig.h" />
- <ClInclude Include="..\..\libass\ass_library.h" />
- <ClInclude Include="..\..\libass\ass_parse.h" />
- <ClInclude Include="..\..\libass\ass_render.h" />
- <ClInclude Include="..\..\libass\ass_shaper.h" />
- <ClInclude Include="..\..\libass\ass_types.h" />
- <ClInclude Include="..\..\libass\ass_utils.h" />
- <ClInclude Include="config.h" />
- </ItemGroup>
- <ItemGroup>
- <ClCompile Include="..\..\libass\ass.c" />
- <ClCompile Include="..\..\libass\ass_bitmap.c" />
- <ClCompile Include="..\..\libass\ass_cache.c" />
- <ClCompile Include="..\..\libass\ass_drawing.c" />
- <ClCompile Include="..\..\libass\ass_font.c" />
- <ClCompile Include="..\..\libass\ass_fontconfig.c" />
- <ClCompile Include="..\..\libass\ass_library.c" />
- <ClCompile Include="..\..\libass\ass_parse.c" />
- <ClCompile Include="..\..\libass\ass_render.c" />
- <ClCompile Include="..\..\libass\ass_render_api.c" />
- <ClCompile Include="..\..\libass\ass_shaper.c" />
- <ClCompile Include="..\..\libass\ass_strtod.c" />
- <ClCompile Include="..\..\libass\ass_utils.c">
- <CompileAs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Default</CompileAs>
- </ClCompile>
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\..\..\enca\libenca_win32\libenca_win32.vcxproj">
- <Project>{22b25aec-7223-46fc-8356-4418327efde1}</Project>
- <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <None Include="libass.def" />
- </ItemGroup>
- <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
- <ImportGroup Label="ExtensionTargets">
- </ImportGroup>
-</Project>
diff --git a/lib/libass/xbmc/libass_win32/stdint.h b/lib/libass/xbmc/libass_win32/stdint.h
deleted file mode 100644
index b23840f1d5..0000000000
--- a/lib/libass/xbmc/libass_win32/stdint.h
+++ /dev/null
@@ -1,222 +0,0 @@
-// ISO C9x compliant stdint.h for Microsoft Visual Studio
-// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
-//
-// Copyright (c) 2006 Alexander Chemeris
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright
-// notice, this list of conditions and the following disclaimer in the
-// documentation and/or other materials provided with the distribution.
-//
-// 3. The name of the author may be used to endorse or promote products
-// derived from this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
-// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
-// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef _MSC_VER // [
-#error "Use this header only with Microsoft Visual C++ compilers!"
-#endif // _MSC_VER ]
-
-#ifndef _MSC_STDINT_H_ // [
-#define _MSC_STDINT_H_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif
-
-#include <limits.h>
-
-// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
-// or compiler give many errors like this:
-// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
-#if (_MSC_VER < 1300) && defined(__cplusplus)
- extern "C++" {
-#endif
-# include <wchar.h>
-#if (_MSC_VER < 1300) && defined(__cplusplus)
- }
-#endif
-
-// 7.18.1 Integer types
-
-// 7.18.1.1 Exact-width integer types
-typedef __int8 int8_t;
-typedef __int16 int16_t;
-typedef __int32 int32_t;
-typedef __int64 int64_t;
-typedef unsigned __int8 uint8_t;
-typedef unsigned __int16 uint16_t;
-typedef unsigned __int32 uint32_t;
-typedef unsigned __int64 uint64_t;
-
-// 7.18.1.2 Minimum-width integer types
-typedef int8_t int_least8_t;
-typedef int16_t int_least16_t;
-typedef int32_t int_least32_t;
-typedef int64_t int_least64_t;
-typedef uint8_t uint_least8_t;
-typedef uint16_t uint_least16_t;
-typedef uint32_t uint_least32_t;
-typedef uint64_t uint_least64_t;
-
-// 7.18.1.3 Fastest minimum-width integer types
-typedef int8_t int_fast8_t;
-typedef int16_t int_fast16_t;
-typedef int32_t int_fast32_t;
-typedef int64_t int_fast64_t;
-typedef uint8_t uint_fast8_t;
-typedef uint16_t uint_fast16_t;
-typedef uint32_t uint_fast32_t;
-typedef uint64_t uint_fast64_t;
-
-// 7.18.1.4 Integer types capable of holding object pointers
-#ifdef _WIN64 // [
- typedef __int64 intptr_t;
- typedef unsigned __int64 uintptr_t;
-#else // _WIN64 ][
- typedef int intptr_t;
- typedef unsigned int uintptr_t;
-#endif // _WIN64 ]
-
-// 7.18.1.5 Greatest-width integer types
-typedef int64_t intmax_t;
-typedef uint64_t uintmax_t;
-
-
-// 7.18.2 Limits of specified-width integer types
-
-#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
-
-// 7.18.2.1 Limits of exact-width integer types
-#define INT8_MIN ((int8_t)_I8_MIN)
-#define INT8_MAX _I8_MAX
-#define INT16_MIN ((int16_t)_I16_MIN)
-#define INT16_MAX _I16_MAX
-#define INT32_MIN ((int32_t)_I32_MIN)
-#define INT32_MAX _I32_MAX
-#define INT64_MIN ((int64_t)_I64_MIN)
-#define INT64_MAX _I64_MAX
-#define UINT8_MAX _UI8_MAX
-#define UINT16_MAX _UI16_MAX
-#define UINT32_MAX _UI32_MAX
-#define UINT64_MAX _UI64_MAX
-
-// 7.18.2.2 Limits of minimum-width integer types
-#define INT_LEAST8_MIN INT8_MIN
-#define INT_LEAST8_MAX INT8_MAX
-#define INT_LEAST16_MIN INT16_MIN
-#define INT_LEAST16_MAX INT16_MAX
-#define INT_LEAST32_MIN INT32_MIN
-#define INT_LEAST32_MAX INT32_MAX
-#define INT_LEAST64_MIN INT64_MIN
-#define INT_LEAST64_MAX INT64_MAX
-#define UINT_LEAST8_MAX UINT8_MAX
-#define UINT_LEAST16_MAX UINT16_MAX
-#define UINT_LEAST32_MAX UINT32_MAX
-#define UINT_LEAST64_MAX UINT64_MAX
-
-// 7.18.2.3 Limits of fastest minimum-width integer types
-#define INT_FAST8_MIN INT8_MIN
-#define INT_FAST8_MAX INT8_MAX
-#define INT_FAST16_MIN INT16_MIN
-#define INT_FAST16_MAX INT16_MAX
-#define INT_FAST32_MIN INT32_MIN
-#define INT_FAST32_MAX INT32_MAX
-#define INT_FAST64_MIN INT64_MIN
-#define INT_FAST64_MAX INT64_MAX
-#define UINT_FAST8_MAX UINT8_MAX
-#define UINT_FAST16_MAX UINT16_MAX
-#define UINT_FAST32_MAX UINT32_MAX
-#define UINT_FAST64_MAX UINT64_MAX
-
-// 7.18.2.4 Limits of integer types capable of holding object pointers
-#ifdef _WIN64 // [
-# define INTPTR_MIN INT64_MIN
-# define INTPTR_MAX INT64_MAX
-# define UINTPTR_MAX UINT64_MAX
-#else // _WIN64 ][
-# define INTPTR_MIN INT32_MIN
-# define INTPTR_MAX INT32_MAX
-# define UINTPTR_MAX UINT32_MAX
-#endif // _WIN64 ]
-
-// 7.18.2.5 Limits of greatest-width integer types
-#define INTMAX_MIN INT64_MIN
-#define INTMAX_MAX INT64_MAX
-#define UINTMAX_MAX UINT64_MAX
-
-// 7.18.3 Limits of other integer types
-
-#ifdef _WIN64 // [
-# define PTRDIFF_MIN _I64_MIN
-# define PTRDIFF_MAX _I64_MAX
-#else // _WIN64 ][
-# define PTRDIFF_MIN _I32_MIN
-# define PTRDIFF_MAX _I32_MAX
-#endif // _WIN64 ]
-
-#define SIG_ATOMIC_MIN INT_MIN
-#define SIG_ATOMIC_MAX INT_MAX
-
-#ifndef SIZE_MAX // [
-# ifdef _WIN64 // [
-# define SIZE_MAX _UI64_MAX
-# else // _WIN64 ][
-# define SIZE_MAX _UI32_MAX
-# endif // _WIN64 ]
-#endif // SIZE_MAX ]
-
-// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
-#ifndef WCHAR_MIN // [
-# define WCHAR_MIN 0
-#endif // WCHAR_MIN ]
-#ifndef WCHAR_MAX // [
-# define WCHAR_MAX _UI16_MAX
-#endif // WCHAR_MAX ]
-
-#define WINT_MIN 0
-#define WINT_MAX _UI16_MAX
-
-#endif // __STDC_LIMIT_MACROS ]
-
-
-// 7.18.4 Limits of other integer types
-
-#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
-
-// 7.18.4.1 Macros for minimum-width integer constants
-
-#define INT8_C(val) val##i8
-#define INT16_C(val) val##i16
-#define INT32_C(val) val##i32
-//#define INT64_C(val) val##i64
-
-#define UINT8_C(val) val##ui8
-#define UINT16_C(val) val##ui16
-#define UINT32_C(val) val##ui32
-//#define UINT64_C(val) val##ui64
-
-// 7.18.4.2 Macros for greatest-width integer constants
-#define INTMAX_C INT64_C
-#define UINTMAX_C UINT64_C
-
-#endif // __STDC_CONSTANT_MACROS ]
-
-
-#endif // _MSC_STDINT_H_ ]
diff --git a/lib/libass/xbmc/libass_win32/unistd.h b/lib/libass/xbmc/libass_win32/unistd.h
deleted file mode 100644
index 4799c2bffe..0000000000
--- a/lib/libass/xbmc/libass_win32/unistd.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * This file is part of the Mingw32 package.
- *
- * unistd.h maps (roughly) to io.h
- */
-
-#ifndef _UNISTD_H
-#define _UNISTD_H
-
-#include <io.h>
-#include <process.h>
-
-#define __UNISTD_GETOPT__
-#include <getopt.h>
-#undef __UNISTD_GETOPT__
-
-/* These are also defined in stdio.h. */
-#ifndef SEEK_SET
-#define SEEK_SET 0
-#endif
-
-#ifndef SEEK_CUR
-#define SEEK_CUR 1
-#endif
-
-#ifndef SEEK_END
-#define SEEK_END 2
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/* This is defined as a real library function to allow autoconf
- to verify its existence. */
-//int ftruncate(int, off_t);
-//__CRT_INLINE int ftruncate(int __fd, off_t __length)
-//{
-// return _chsize (__fd, __length);
-//}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _UNISTD_H */