Added libass 0.9.3try2 as is to repository (patched for MSVC on next revision)

Originally committed to SVN as r1035.
This commit is contained in:
Rodrigo Braz Monteiro 2007-04-09 02:02:40 +00:00
parent 1e3694d859
commit 41843bf292
22 changed files with 6272 additions and 1 deletions

View file

@ -47,7 +47,14 @@ extern "C" {
///////////
// Library
#ifdef __VISUALC__
#pragma comment(lib,"libass.dll.a")
#ifdef __WXDEBUG__
//#pragma comment(lib,"libassd.lib")
#pragma comment(lib,"freetype233MT_D.lib")
#else
//#pragma comment(lib,"libass.lib")
#pragma comment(lib,"freetype233MT.lib")
#endif
#pragma comment(lib,"libfontconfig.lib")
#endif

10
libass/Makefile.am Normal file
View file

@ -0,0 +1,10 @@
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 mputils.c \
ass_bitmap.h ass_cache.h ass_fontconfig.h ass_font.h ass.h \
ass_library.h ass_types.h ass_utils.h help_mp.h mputils.h
assheadersdir = $(includedir)/ass
dist_assheaders_HEADERS = ass.h ass_types.h

498
libass/Makefile.in Normal file
View file

@ -0,0 +1,498 @@
# Makefile.in generated by automake 1.9.6 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
subdir = libass
DIST_COMMON = $(dist_assheaders_HEADERS) $(srcdir)/Makefile.am \
$(srcdir)/Makefile.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = `echo $$p | sed -e 's|^.*/||'`;
am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(assheadersdir)"
libLTLIBRARIES_INSTALL = $(INSTALL)
LTLIBRARIES = $(lib_LTLIBRARIES)
libass_la_LIBADD =
am_libass_la_OBJECTS = ass.lo ass_cache.lo ass_font.lo \
ass_fontconfig.lo ass_render.lo ass_utils.lo ass_bitmap.lo \
ass_library.lo mputils.lo
libass_la_OBJECTS = $(am_libass_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(libass_la_SOURCES)
DIST_SOURCES = $(libass_la_SOURCES)
dist_assheadersHEADERS_INSTALL = $(INSTALL_HEADER)
HEADERS = $(dist_assheaders_HEADERS)
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
FREETYPE_LIBS = @FREETYPE_LIBS@
GREP = @GREP@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
POW_LIB = @POW_LIB@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
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 mputils.c \
ass_bitmap.h ass_cache.h ass_fontconfig.h ass_font.h ass.h \
ass_library.h ass_types.h ass_utils.h help_mp.h mputils.h
assheadersdir = $(includedir)/ass
dist_assheaders_HEADERS = ass.h ass_types.h
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libass/Makefile'; \
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu libass/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
install-libLTLIBRARIES: $(lib_LTLIBRARIES)
@$(NORMAL_INSTALL)
test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
if test -f $$p; then \
f=$(am__strip_dir) \
echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
$(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
else :; fi; \
done
uninstall-libLTLIBRARIES:
@$(NORMAL_UNINSTALL)
@set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
p=$(am__strip_dir) \
echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
$(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
done
clean-libLTLIBRARIES:
-test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
@list='$(lib_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libass.la: $(libass_la_OBJECTS) $(libass_la_DEPENDENCIES)
$(LINK) -rpath $(libdir) $(libass_la_LDFLAGS) $(libass_la_OBJECTS) $(libass_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass_bitmap.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass_font.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass_fontconfig.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass_library.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass_render.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ass_utils.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mputils.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c $<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
install-dist_assheadersHEADERS: $(dist_assheaders_HEADERS)
@$(NORMAL_INSTALL)
test -z "$(assheadersdir)" || $(mkdir_p) "$(DESTDIR)$(assheadersdir)"
@list='$(dist_assheaders_HEADERS)'; for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=$(am__strip_dir) \
echo " $(dist_assheadersHEADERS_INSTALL) '$$d$$p' '$(DESTDIR)$(assheadersdir)/$$f'"; \
$(dist_assheadersHEADERS_INSTALL) "$$d$$p" "$(DESTDIR)$(assheadersdir)/$$f"; \
done
uninstall-dist_assheadersHEADERS:
@$(NORMAL_UNINSTALL)
@list='$(dist_assheaders_HEADERS)'; for p in $$list; do \
f=$(am__strip_dir) \
echo " rm -f '$(DESTDIR)$(assheadersdir)/$$f'"; \
rm -f "$(DESTDIR)$(assheadersdir)/$$f"; \
done
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkdir_p) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(assheadersdir)"; do \
test -z "$$dir" || $(mkdir_p) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
info: info-am
info-am:
install-data-am: install-dist_assheadersHEADERS
install-exec-am: install-libLTLIBRARIES
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-dist_assheadersHEADERS uninstall-info-am \
uninstall-libLTLIBRARIES
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libLTLIBRARIES clean-libtool ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am \
install-dist_assheadersHEADERS install-exec install-exec-am \
install-info install-info-am install-libLTLIBRARIES \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-dist_assheadersHEADERS \
uninstall-info-am uninstall-libLTLIBRARIES
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

1077
libass/ass.c Normal file

File diff suppressed because it is too large Load diff

198
libass/ass.h Normal file
View file

@ -0,0 +1,198 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_H__
#define __ASS_H__
#include "ass_types.h"
/// Libass renderer object. Contents are private.
typedef struct ass_renderer_s ass_renderer_t;
/// a linked list of images produced by ass renderer
typedef struct ass_image_s {
int w, h; // bitmap width/height
int stride; // bitmap stride
unsigned char* bitmap; // 1bpp stride*h alpha buffer
uint32_t color; // RGBA
int dst_x, dst_y; // bitmap placement inside the video frame
struct ass_image_s* next; // linked list
} ass_image_t;
/**
* \brief initialize the library
* \return library handle or NULL if failed
*/
ass_library_t* ass_library_init(void);
/**
* \brief finalize the library
* \param priv library handle
*/
void ass_library_done(ass_library_t*);
/**
* \brief set private font directory
* It is used for saving embedded fonts and also in font lookup.
*/
void ass_set_fonts_dir(ass_library_t* priv, const char* fonts_dir);
void ass_set_extract_fonts(ass_library_t* priv, int extract);
void ass_set_style_overrides(ass_library_t* priv, char** list);
/**
* \brief initialize the renderer
* \param priv library handle
* \return renderer handle or NULL if failed
*/
ass_renderer_t* ass_renderer_init(ass_library_t*);
/**
* \brief finalize the renderer
* \param priv renderer handle
*/
void ass_renderer_done(ass_renderer_t* priv);
void ass_set_frame_size(ass_renderer_t* priv, int w, int h);
void ass_set_margins(ass_renderer_t* priv, int t, int b, int l, int r);
void ass_set_use_margins(ass_renderer_t* priv, int use);
void ass_set_aspect_ratio(ass_renderer_t* priv, double ar);
void ass_set_font_scale(ass_renderer_t* priv, double font_scale);
/**
* \brief set font lookup defaults
*/
int ass_set_fonts(ass_renderer_t* priv, const char* default_font, const char* default_family);
/**
* \brief render a frame, producing a list of ass_image_t
* \param priv library
* \param track subtitle track
* \param now video timestamp in milliseconds
*/
ass_image_t* ass_render_frame(ass_renderer_t *priv, ass_track_t* 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
* \return pointer to empty track
*/
ass_track_t* ass_new_track(ass_library_t*);
/**
* \brief deallocate track and all its child objects (styles and events)
* \param track track to deallocate
*/
void ass_free_track(ass_track_t* track);
/**
* \brief allocate new style
* \param track track
* \return newly allocated style id
*/
int ass_alloc_style(ass_track_t* track);
/**
* \brief allocate new event
* \param track track
* \return newly allocated event id
*/
int ass_alloc_event(ass_track_t* 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_t* 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_t* track, int eid);
/**
* \brief Process Codec Private section of subtitle stream
* \param track target track
* \param data string to parse
* \param size length of data
*/
void ass_process_codec_private(ass_track_t* track, char *data, int size);
/**
* \brief Process a chunk of subtitle stream data. In matroska, this containes 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_t* track, char *data, int size, long long timecode, long long duration);
/**
* \brief Read subtitles from file.
* \param fname file name
* \return newly allocated track
*/
ass_track_t* ass_read_file(ass_library_t* library, char* fname, char* codepage);
/**
* \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_t* ass_read_memory(ass_library_t* library, char* buf, size_t bufsize, char* codepage);
/**
* \brief read styles from file into already initialized track
* \return 0 on success
*/
int ass_read_styles(ass_track_t* track, char* fname, char* codepage);
/**
* \brief Add a memory font.
* \param name attachment name
* \param data binary font data
* \param data_size data size
*/
void ass_add_font(ass_library_t* library, char* name, char* data, int data_size);
/**
* \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, ms
* \param movement how many events to skip from the one currently displayed
* +2 means "the one after the next", -1 means "previous"
* \return timeshift, ms
*/
long long ass_step_sub(ass_track_t* track, long long now, int movement);
#endif

272
libass/ass_bitmap.c Normal file
View file

@ -0,0 +1,272 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include <ft2build.h>
#include FT_GLYPH_H
#include "mputils.h"
#include "ass_bitmap.h"
struct ass_synth_priv_s {
int tmp_w, tmp_h;
unsigned short* tmp;
int g_r;
int g_w;
unsigned *g;
unsigned *gt2;
};
static const unsigned int maxcolor = 255;
static const unsigned base = 256;
static const double blur_radius = 1.5;
static int generate_tables(ass_synth_priv_t* priv, double radius)
{
double A = log(1.0/base)/(radius*radius*2);
int mx, i;
double volume_diff, volume_factor = 0;
unsigned volume;
priv->g_r = ceil(radius);
priv->g_w = 2*priv->g_r+1;
if (priv->g_r) {
priv->g = malloc(priv->g_w * sizeof(unsigned));
priv->gt2 = malloc(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_synth_priv_t* 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;
if (priv->tmp)
free(priv->tmp);
priv->tmp = malloc((priv->tmp_w + 1) * priv->tmp_h * sizeof(short));
}
ass_synth_priv_t* ass_synth_init()
{
ass_synth_priv_t* priv = calloc(1, sizeof(ass_synth_priv_t));
generate_tables(priv, blur_radius);
return priv;
}
void ass_synth_done(ass_synth_priv_t* priv)
{
if (priv->tmp)
free(priv->tmp);
if (priv->g)
free(priv->g);
if (priv->gt2)
free(priv->gt2);
free(priv);
}
static bitmap_t* alloc_bitmap(int w, int h)
{
bitmap_t* bm;
bm = calloc(1, sizeof(bitmap_t));
bm->buffer = malloc(w*h);
bm->w = w;
bm->h = h;
bm->left = bm->top = 0;
return bm;
}
void ass_free_bitmap(bitmap_t* bm)
{
if (bm) {
if (bm->buffer) free(bm->buffer);
free(bm);
}
}
static bitmap_t* copy_bitmap(const bitmap_t* src)
{
bitmap_t* dst = alloc_bitmap(src->w, src->h);
dst->left = src->left;
dst->top = src->top;
memcpy(dst->buffer, src->buffer, src->w * src->h);
return dst;
}
static bitmap_t* glyph_to_bitmap_internal(FT_Glyph glyph, int bord)
{
FT_BitmapGlyph bg;
FT_Bitmap* bit;
bitmap_t* bm;
int w, h;
unsigned char* src;
unsigned char* dst;
int i;
int error;
error = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 0);
if (error) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FT_Glyph_To_BitmapError, error);
return 0;
}
bg = (FT_BitmapGlyph)glyph;
bit = &(bg->bitmap);
if (bit->pixel_mode != FT_PIXEL_MODE_GRAY) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UnsupportedPixelMode, (int)(bit->pixel_mode));
FT_Done_Glyph(glyph);
return 0;
}
w = bit->width;
h = bit->rows;
bm = alloc_bitmap(w + 2*bord, h + 2*bord);
memset(bm->buffer, 0, bm->w * bm->h);
bm->left = bg->left - bord;
bm->top = - bg->top - bord;
src = bit->buffer;
dst = bm->buffer + bord + bm->w * bord;
for (i = 0; i < h; ++i) {
memcpy(dst, src, w);
src += bit->pitch;
dst += bm->w;
}
return bm;
}
/**
* \brief fix outline bitmap and generate shadow bitmap
* Two things are done here:
* 1. Glyph bitmap is subtracted from outline bitmap. This way looks much better in some cases.
* 2. Shadow bitmap is created as a sum of glyph and outline bitmaps.
*/
static bitmap_t* fix_outline_and_shadow(bitmap_t* bm_g, bitmap_t* 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->w < bm_g->left + bm_g->w ? bm_o->left + bm_o->w : bm_g->left + bm_g->w;
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;
bitmap_t* bm_s = copy_bitmap(bm_o);
unsigned char* g = bm_g->buffer + (t - bm_g->top) * bm_g->w + (l - bm_g->left);
unsigned char* o = bm_o->buffer + (t - bm_o->top) * bm_o->w + (l - bm_o->left);
unsigned char* s = bm_s->buffer + (t - bm_s->top) * bm_s->w + (l - bm_s->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 : 0;
s[x] = (c_o < 0xFF - c_g) ? c_o + c_g : 0xFF;
}
g += bm_g->w;
o += bm_o->w;
s += bm_s->w;
}
assert(bm_s);
return bm_s;
}
int glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph,
bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be)
{
const int bord = be ? ceil(blur_radius) : 0;
assert(bm_g && bm_o && bm_s);
*bm_g = *bm_o = *bm_s = 0;
if (glyph)
*bm_g = glyph_to_bitmap_internal(glyph, bord);
if (!*bm_g)
return 1;
if (outline_glyph) {
*bm_o = glyph_to_bitmap_internal(outline_glyph, bord);
if (!*bm_o) {
ass_free_bitmap(*bm_g);
return 1;
}
}
if (*bm_o)
resize_tmp(priv, (*bm_o)->w, (*bm_o)->h);
resize_tmp(priv, (*bm_g)->w, (*bm_g)->h);
if (be) {
blur((*bm_g)->buffer, priv->tmp, (*bm_g)->w, (*bm_g)->h, (*bm_g)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
if (*bm_o)
blur((*bm_o)->buffer, priv->tmp, (*bm_o)->w, (*bm_o)->h, (*bm_o)->w, (int*)priv->gt2, priv->g_r, priv->g_w);
}
if (*bm_o)
*bm_s = fix_outline_and_shadow(*bm_g, *bm_o);
else
*bm_s = copy_bitmap(*bm_g);
assert(bm_s);
return 0;
}

49
libass/ass_bitmap.h Normal file
View file

@ -0,0 +1,49 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_BITMAP_H__
#define __ASS_BITMAP_H__
typedef struct ass_synth_priv_s ass_synth_priv_t;
ass_synth_priv_t* ass_synth_init();
void ass_synth_done(ass_synth_priv_t* priv);
typedef struct bitmap_s {
int left, top;
int w, h; // width, height
unsigned char* buffer; // w x h buffer
} bitmap_t;
/**
* \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 glyph_to_bitmap(ass_synth_priv_t* priv, FT_Glyph glyph, FT_Glyph outline_glyph, bitmap_t** bm_g, bitmap_t** bm_o, bitmap_t** bm_s, int be);
void ass_free_bitmap(bitmap_t* bm);
#endif

220
libass/ass_cache.c Normal file
View file

@ -0,0 +1,220 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <inttypes.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include <assert.h>
#include "mputils.h"
#include "ass.h"
#include "ass_fontconfig.h"
#include "ass_font.h"
#include "ass_bitmap.h"
#include "ass_cache.h"
#define MAX_FONT_CACHE_SIZE 100
static ass_font_t** font_cache;
static int font_cache_size;
static int font_compare(ass_font_desc_t* a, ass_font_desc_t* b) {
if (strcmp(a->family, b->family) != 0)
return 0;
if (a->bold != b->bold)
return 0;
if (a->italic != b->italic)
return 0;
return 1;
}
/**
* \brief Get a face struct from cache.
* \param desc required face description
* \return font struct
*/
ass_font_t* ass_font_cache_find(ass_font_desc_t* desc)
{
int i;
for (i=0; i<font_cache_size; ++i)
if (font_compare(desc, &(font_cache[i]->desc)))
return font_cache[i];
return 0;
}
/**
* \brief Add a face struct to cache.
* \param font font struct
*/
void ass_font_cache_add(ass_font_t* font)
{
if (font_cache_size == MAX_FONT_CACHE_SIZE) {
mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_TooManyFonts);
// FIXME: possible memory leak
return;
}
font_cache[font_cache_size] = font;
font_cache_size++;
}
void ass_font_cache_init(void)
{
font_cache = calloc(MAX_FONT_CACHE_SIZE, sizeof(ass_font_t*));
font_cache_size = 0;
}
void ass_font_cache_done(void)
{
int i;
for (i = 0; i < font_cache_size; ++i) {
ass_font_t* item = font_cache[i];
ass_font_free(item);
}
free(font_cache);
font_cache_size = 0;
}
//---------------------------------
// glyph cache
#define GLYPH_HASH_SIZE (0xFFFF + 13)
typedef struct glyph_hash_item_s {
glyph_hash_key_t key;
glyph_hash_val_t val;
struct glyph_hash_item_s* next;
} glyph_hash_item_t;
typedef glyph_hash_item_t* glyph_hash_item_p;
static glyph_hash_item_p* glyph_hash_root;
static int glyph_hash_size;
static int glyph_compare(glyph_hash_key_t* a, glyph_hash_key_t* b) {
if (memcmp(a, b, sizeof(glyph_hash_key_t)) == 0)
return 1;
else
return 0;
}
static unsigned glyph_hash(glyph_hash_key_t* key) {
unsigned val = 0;
unsigned i;
for (i = 0; i < sizeof(key->font); ++i)
val += *(unsigned char *)(&(key->font) + i);
val <<= 21;
if (key->bitmap) val &= 0x80000000;
if (key->be) val &= 0x40000000;
val += key->ch;
val += key->size << 8;
val += key->outline << 3;
val += key->advance.x << 10;
val += key->advance.y << 16;
val += key->bold << 1;
val += key->italic << 20;
val += key->frx;
val += key->fry << 1;
val += key->frz << 2;
return val;
}
/**
* \brief Add a glyph to glyph cache.
* \param key hash key
* \param val hash val: 2 bitmap glyphs + some additional info
*/
void cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val)
{
unsigned hash = glyph_hash(key);
glyph_hash_item_t** next = glyph_hash_root + (hash % GLYPH_HASH_SIZE);
while (*next) {
if (glyph_compare(key, &((*next)->key)))
return;
next = &((*next)->next);
assert(next);
}
(*next) = malloc(sizeof(glyph_hash_item_t));
// (*next)->desc = glyph_key_copy(key, &((*next)->key));
memcpy(&((*next)->key), key, sizeof(glyph_hash_key_t));
memcpy(&((*next)->val), val, sizeof(glyph_hash_val_t));
(*next)->next = 0;
glyph_hash_size ++;
/* if (glyph_hash_size && (glyph_hash_size % 25 == 0)) {
printf("\nGlyph cache: %d entries, %d bytes\n", glyph_hash_size, glyph_hash_size * sizeof(glyph_hash_item_t));
} */
}
/**
* \brief Get a glyph from glyph cache.
* \param key hash key
* \return requested hash val or 0 if not found
*/
glyph_hash_val_t* cache_find_glyph(glyph_hash_key_t* key)
{
unsigned hash = glyph_hash(key);
glyph_hash_item_t* item = glyph_hash_root[hash % GLYPH_HASH_SIZE];
while (item) {
if (glyph_compare(key, &(item->key))) {
return &(item->val);
}
item = item->next;
}
return 0;
}
void ass_glyph_cache_init(void)
{
glyph_hash_root = calloc(GLYPH_HASH_SIZE, sizeof(glyph_hash_item_p));
glyph_hash_size = 0;
}
void ass_glyph_cache_done(void)
{
int i;
for (i = 0; i < GLYPH_HASH_SIZE; ++i) {
glyph_hash_item_t* item = glyph_hash_root[i];
while (item) {
glyph_hash_item_t* next = item->next;
if (item->val.bm) ass_free_bitmap(item->val.bm);
if (item->val.bm_o) ass_free_bitmap(item->val.bm_o);
if (item->val.bm_s) ass_free_bitmap(item->val.bm_s);
free(item);
item = next;
}
}
free(glyph_hash_root);
glyph_hash_size = 0;
}
void ass_glyph_cache_reset(void)
{
ass_glyph_cache_done();
ass_glyph_cache_init();
}

62
libass/ass_cache.h Normal file
View file

@ -0,0 +1,62 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_CACHE_H__
#define __ASS_CACHE_H__
void ass_font_cache_init(void);
ass_font_t* ass_font_cache_find(ass_font_desc_t* desc);
void ass_font_cache_add(ass_font_t* font);
void ass_font_cache_done(void);
// describes a glyph; glyphs with equivalents structs are considered identical
typedef struct glyph_hash_key_s {
char bitmap; // bool : true = bitmap, false = outline
ass_font_t* font;
int size; // font size
uint32_t ch; // character code
unsigned outline; // border width, 16.16 fixed point value
int bold, italic;
char be; // blur edges
// the following affects bitmap glyphs only
unsigned scale_x, scale_y; // 16.16
int frx, fry, frz; // signed 16.16
FT_Vector advance; // subpixel shift vector
} glyph_hash_key_t;
typedef struct glyph_hash_val_s {
bitmap_t* bm; // the actual glyph bitmaps
bitmap_t* bm_o;
bitmap_t* bm_s;
FT_BBox bbox_scaled; // bbox after scaling, but before rotation
FT_Vector advance; // 26.6, advance distance to the next glyph in line
} glyph_hash_val_t;
void ass_glyph_cache_init(void);
void cache_add_glyph(glyph_hash_key_t* key, glyph_hash_val_t* val);
glyph_hash_val_t* cache_find_glyph(glyph_hash_key_t* key);
void ass_glyph_cache_reset(void);
void ass_glyph_cache_done(void);
#endif

327
libass/ass_font.c Normal file
View file

@ -0,0 +1,327 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <inttypes.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_SYNTHESIS_H
#include FT_GLYPH_H
#include "ass.h"
#include "ass_library.h"
#include "ass_font.h"
#include "ass_bitmap.h"
#include "ass_cache.h"
#include "ass_fontconfig.h"
#include "mputils.h"
/**
* Select Microfost Unicode CharMap, if the font has one.
* Otherwise, let FreeType decide.
*/
static void charmap_magic(FT_Face face)
{
int i;
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;
}
}
if (!face->charmap) {
if (face->num_charmaps == 0) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmaps);
return;
}
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NoCharmapAutodetected);
FT_Set_Charmap(face, face->charmaps[0]);
return;
}
}
/**
* \brief find a memory font by name
*/
static int find_font(ass_library_t* 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;
}
/**
* \brief Create a new ass_font_t according to "desc" argument
*/
ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc)
{
char* path;
int index;
FT_Face face;
int error;
ass_font_t* font;
int mem_idx;
font = ass_font_cache_find(desc);
if (font)
return font;
path = fontconfig_select(fc_priv, desc->family, desc->bold, desc->italic, &index);
mem_idx = find_font(library, path);
if (mem_idx >= 0) {
error = FT_New_Memory_Face(ftlibrary, (unsigned char*)library->fontdata[mem_idx].data,
library->fontdata[mem_idx].size, 0, &face);
if (error) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningMemoryFont, path);
return 0;
}
} else {
error = FT_New_Face(ftlibrary, path, index, &face);
if (error) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningFont, path, index);
return 0;
}
}
charmap_magic(face);
font = calloc(1, sizeof(ass_font_t));
font->ftlibrary = ftlibrary;
font->faces[0] = face;
font->n_faces = 1;
font->desc.family = strdup(desc->family);
font->desc.bold = desc->bold;
font->desc.italic = desc->italic;
font->m.xx = font->m.yy = (FT_Fixed)0x10000L;
font->m.xy = font->m.yy = 0;
font->v.x = font->v.y = 0;
font->size = 0;
#ifdef HAVE_FONTCONFIG
font->charset = FcCharSetCreate();
#endif
ass_font_cache_add(font);
return font;
}
/**
* \brief Set font transformation matrix and shift vector
**/
void ass_font_set_transform(ass_font_t* font, FT_Matrix* m, FT_Vector* v)
{
int i;
font->m.xx = m->xx;
font->m.xy = m->xy;
font->m.yx = m->yx;
font->m.yy = m->yy;
font->v.x = v->x;
font->v.y = v->y;
for (i = 0; i < font->n_faces; ++i)
FT_Set_Transform(font->faces[i], &font->m, &font->v);
}
/**
* \brief Set font size
**/
void ass_font_set_size(ass_font_t* font, int size)
{
int i;
if (font->size != size) {
font->size = size;
for (i = 0; i < font->n_faces; ++i)
FT_Set_Pixel_Sizes(font->faces[i], 0, size);
}
}
#ifdef HAVE_FONTCONFIG
/**
* \brief Select a new FT_Face with the given character
* The new face is added to the end of font->faces.
**/
static void ass_font_reselect(void* fontconfig_priv, ass_font_t* font, uint32_t ch)
{
char* path;
int index;
FT_Face face;
int error;
if (font->n_faces == ASS_FONT_MAX_FACES)
return;
path = fontconfig_select_with_charset(fontconfig_priv, font->desc.family, font->desc.bold,
font->desc.italic, &index, font->charset);
error = FT_New_Face(font->ftlibrary, path, index, &face);
if (error) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningFont, path, index);
return;
}
charmap_magic(face);
error = FT_Get_Char_Index(face, ch);
if (error == 0) { // the new font face is not better then the old one
FT_Done_Face(face);
return;
}
font->faces[font->n_faces++] = face;
FT_Set_Transform(face, &font->m, &font->v);
FT_Set_Pixel_Sizes(face, 0, font->size);
}
#endif
/**
* \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_t* font, uint32_t ch, int* asc, int* desc)
{
int i;
for (i = 0; i < font->n_faces; ++i) {
FT_Face face = font->faces[i];
if (FT_Get_Char_Index(face, ch)) {
int v, v2;
v = face->size->metrics.ascender;
v2 = FT_MulFix(face->bbox.yMax, face->size->metrics.y_scale);
*asc = (v > v2 * 0.9) ? v : v2;
v = - face->size->metrics.descender;
v2 = - FT_MulFix(face->bbox.yMin, face->size->metrics.y_scale);
*desc = (v > v2 * 0.9) ? v : v2;
return;
}
}
*asc = *desc = 0;
}
/**
* \brief Get a glyph
* \param ch character code
**/
FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch)
{
int error;
int index = 0;
int i;
FT_Glyph glyph;
FT_Face face = 0;
if (ch < 0x20)
return 0;
if (font->n_faces == 0)
return 0;
for (i = 0; i < font->n_faces; ++i) {
face = font->faces[i];
index = FT_Get_Char_Index(face, ch);
if (index)
break;
}
#ifdef HAVE_FONTCONFIG
FcCharSetAddChar(font->charset, ch);
if (index == 0) {
mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_GlyphNotFoundReselectingFont,
ch, font->desc.family, font->desc.bold, font->desc.italic);
ass_font_reselect(fontconfig_priv, font, ch);
face = font->faces[font->n_faces - 1];
index = FT_Get_Char_Index(face, ch);
if (index == 0) {
mp_msg(MSGT_ASS, MSGL_ERR, MSGTR_LIBASS_GlyphNotFound,
ch, font->desc.family, font->desc.bold, font->desc.italic);
}
}
#endif
error = FT_Load_Glyph(face, index, FT_LOAD_NO_BITMAP );
if (error) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph);
return 0;
}
#if (FREETYPE_MAJOR > 2) || \
((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR >= 2)) || \
((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 1) && (FREETYPE_PATCH >= 10))
// FreeType >= 2.1.10 required
if (!(face->style_flags & FT_STYLE_FLAG_ITALIC) &&
(font->desc.italic > 55)) {
FT_GlyphSlot_Oblique(face->glyph);
}
#endif
error = FT_Get_Glyph(face->glyph, &glyph);
if (error) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorLoadingGlyph);
return 0;
}
return glyph;
}
/**
* \brief Get kerning for the pair of glyphs.
**/
FT_Vector ass_font_get_kerning(ass_font_t* font, uint32_t c1, uint32_t c2)
{
FT_Vector v = {0, 0};
int i;
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_t
**/
void ass_font_free(ass_font_t* font)
{
int i;
for (i = 0; i < font->n_faces; ++i)
if (font->faces[i]) FT_Done_Face(font->faces[i]);
if (font->desc.family) free(font->desc.family);
#ifdef HAVE_FONTCONFIG
if (font->charset) FcCharSetDestroy(font->charset);
#endif
free(font);
}

57
libass/ass_font.h Normal file
View file

@ -0,0 +1,57 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_FONT_H__
#define __ASS_FONT_H__
#ifdef HAVE_FONTCONFIG
#include <fontconfig/fontconfig.h>
#endif
typedef struct ass_font_desc_s {
char* family;
unsigned bold;
unsigned italic;
} ass_font_desc_t;
#define ASS_FONT_MAX_FACES 10
typedef struct ass_font_s {
ass_font_desc_t desc;
FT_Library ftlibrary;
FT_Face faces[ASS_FONT_MAX_FACES];
int n_faces;
FT_Matrix m; // current transformation
FT_Vector v; // current shift
int size;
#ifdef HAVE_FONTCONFIG
FcCharSet* charset;
#endif
} ass_font_t;
ass_font_t* ass_font_new(ass_library_t* library, FT_Library ftlibrary, void* fc_priv, ass_font_desc_t* desc);
void ass_font_set_transform(ass_font_t* font, FT_Matrix* m, FT_Vector* v);
void ass_font_set_size(ass_font_t* font, int size);
void ass_font_get_asc_desc(ass_font_t* font, uint32_t ch, int* asc, int* desc);
FT_Glyph ass_font_get_glyph(void* fontconfig_priv, ass_font_t* font, uint32_t ch);
FT_Vector ass_font_get_kerning(ass_font_t* font, uint32_t c1, uint32_t c2);
void ass_font_free(ass_font_t* font);
#endif

428
libass/ass_fontconfig.c Normal file
View file

@ -0,0 +1,428 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <inttypes.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include "mputils.h"
#include "ass.h"
#include "ass_library.h"
#include "ass_fontconfig.h"
#ifdef HAVE_FONTCONFIG
#include <fontconfig/fontconfig.h>
#include <fontconfig/fcfreetype.h>
#endif
struct fc_instance_s {
#ifdef HAVE_FONTCONFIG
FcConfig* config;
#endif
char* family_default;
char* path_default;
int index_default;
};
#ifdef HAVE_FONTCONFIG
/**
* \brief Low-level font selection.
* \param priv private data
* \param family font family
* \param bold font weight value
* \param italic font slant value
* \param index out: font index inside a file
* \param charset: contains the characters that should be present in the font, can be NULL
* \return font file path
*/
static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index,
FcCharSet* charset)
{
FcBool rc;
FcResult result;
FcPattern *pat, *rpat;
int val_i;
FcChar8* val_s;
FcBool val_b;
FcCharSet* val_cs;
FcFontSet* fset;
int curf, bestf, bestdiff = 0;
*index = 0;
pat = FcPatternCreate();
if (!pat)
return 0;
FcPatternAddString(pat, FC_FAMILY, (const FcChar8*)family);
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)
return 0;
fset = FcFontSort(priv->config, pat, FcTrue, NULL, &result);
bestf = -1;
if (charset)
bestdiff = FcCharSetCount(charset) + 1;
for (curf = 0; curf < fset->nfont; ++curf) {
rpat = fset->fonts[curf];
result = FcPatternGetBool(rpat, FC_OUTLINE, 0, &val_b);
if (result != FcResultMatch)
continue;
if (val_b != FcTrue)
continue;
if (charset) {
int diff;
result = FcPatternGetCharSet(rpat, FC_CHARSET, 0, &val_cs);
if (result != FcResultMatch)
continue;
diff = FcCharSetSubtractCount(charset, val_cs);
if (diff < bestdiff) {
bestdiff = diff;
bestf = curf;
}
if (diff == 0)
break;
} else {
bestf = curf;
break;
}
}
if (bestf < 0)
return 0;
rpat = fset->fonts[bestf];
result = FcPatternGetInteger(rpat, FC_INDEX, 0, &val_i);
if (result != FcResultMatch)
return 0;
*index = val_i;
result = FcPatternGetString(rpat, FC_FAMILY, 0, &val_s);
if (result != FcResultMatch)
return 0;
if (strcasecmp((const char*)val_s, family) != 0)
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_SelectedFontFamilyIsNotTheRequestedOne,
(const char*)val_s, family);
result = FcPatternGetString(rpat, FC_FILE, 0, &val_s);
if (result != FcResultMatch)
return 0;
return strdup((const char*)val_s);
}
/**
* \brief Find a font. Use default family or path if necessary.
* \param priv_ private data
* \param family font family
* \param bold font weight value
* \param italic font slant value
* \param index out: font index inside a file
* \param charset: contains the characters that should be present in the font, can be NULL
* \return font file path
*/
char* fontconfig_select_with_charset(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index,
FcCharSet* charset)
{
char* res = 0;
if (family && *family)
res = _select_font(priv, family, bold, italic, index, charset);
if (!res && priv->family_default) {
res = _select_font(priv, priv->family_default, bold, italic, index, charset);
if (res)
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UsingDefaultFontFamily,
family, bold, italic, res, *index);
}
if (!res && priv->path_default) {
res = priv->path_default;
*index = priv->index_default;
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UsingDefaultFont,
family, bold, italic, res, *index);
}
if (!res) {
res = _select_font(priv, "Arial", bold, italic, index, charset);
if (res)
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_UsingArialFontFamily,
family, bold, italic, res, *index);
}
if (res)
mp_msg(MSGT_ASS, MSGL_V, "fontconfig_select: (%s, %d, %d) -> %s, %d\n",
family, bold, italic, res, *index);
return res;
}
char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index)
{
return fontconfig_select_with_charset(priv, family, bold, italic, index, 0);
}
static char* validate_fname(char* name)
{
char* fname;
char* p;
char* q;
unsigned code;
int sz = strlen(name);
q = fname = malloc(sz + 1);
p = name;
while (*p) {
code = utf8_get_char(&p);
if (code == 0)
break;
if ( (code > 0x7F) ||
(code == '\\') ||
(code == '/') ||
(code == ':') ||
(code == '*') ||
(code == '?') ||
(code == '<') ||
(code == '>') ||
(code == '|') ||
(code == 0))
{
*q++ = '_';
} else {
*q++ = code;
}
if (p - name > sz)
break;
}
*q = 0;
return fname;
}
/**
* \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
* With FontConfig >= 2.4.2, builds a font pattern in memory via FT_New_Memory_Face/FcFreeTypeQueryFace.
* With older FontConfig versions, save the font to ~/.mplayer/fonts.
*/
static void process_fontdata(fc_instance_t* priv, ass_library_t* library, FT_Library ftlibrary, int idx)
{
char buf[1000];
FILE* fp = 0;
int rc;
struct stat st;
char* fname;
const char* name = library->fontdata[idx].name;
const char* data = library->fontdata[idx].data;
int data_size = library->fontdata[idx].size;
const char* fonts_dir = library->fonts_dir;
FT_Face face;
FcPattern* pattern;
FcFontSet* fset;
FcBool res;
#if (FC_VERSION < 20402)
if (!fonts_dir)
return;
rc = stat(fonts_dir, &st);
if (rc) {
int res;
#ifndef __MINGW32__
res = mkdir(fonts_dir, 0700);
#else
res = mkdir(fonts_dir);
#endif
if (res) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FailedToCreateDirectory, fonts_dir);
}
} else if (!S_ISDIR(st.st_mode)) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_NotADirectory, fonts_dir);
}
fname = validate_fname((char*)name);
snprintf(buf, 1000, "%s/%s", fonts_dir, fname);
free(fname);
fp = fopen(buf, "wb");
if (!fp) return;
fwrite(data, data_size, 1, fp);
fclose(fp);
#else // (FC_VERSION >= 20402)
rc = FT_New_Memory_Face(ftlibrary, (unsigned char*)data, data_size, 0, &face);
if (rc) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_ErrorOpeningMemoryFont, name);
return;
}
pattern = FcFreeTypeQueryFace(face, (unsigned char*)name, 0, FcConfigGetBlanks(priv->config));
if (!pattern) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcFreeTypeQueryFace");
FT_Done_Face(face);
return;
}
fset = FcConfigGetFonts(priv->config, FcSetSystem); // somehow it failes when asked for FcSetApplication
if (!fset) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcConfigGetFonts");
FT_Done_Face(face);
return;
}
res = FcFontSetAdd(fset, pattern);
if (!res) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FunctionCallFailed, "FcFontSetAdd");
FT_Done_Face(face);
return;
}
FT_Done_Face(face);
#endif
}
/**
* \brief Init fontconfig.
* \param library libass library object
* \param ftlibrary freetype library object
* \param family default font family
* \param path default font path
* \return pointer to fontconfig private data
*/
fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path)
{
int rc;
struct stat st;
fc_instance_t* priv = calloc(1, sizeof(fc_instance_t));
const char* dir = library->fonts_dir;
int i;
rc = FcInit();
assert(rc);
priv->config = FcConfigGetCurrent();
if (!priv->config) {
mp_msg(MSGT_ASS, MSGL_FATAL, MSGTR_LIBASS_FcInitLoadConfigAndFontsFailed);
return 0;
}
for (i = 0; i < library->num_fontdata; ++i)
process_fontdata(priv, library, ftlibrary, i);
if (FcDirCacheValid((const FcChar8 *)dir) == FcFalse)
{
mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_LIBASS_UpdatingFontCache);
if (FcGetVersion() >= 20390 && FcGetVersion() < 20400)
mp_msg(MSGT_ASS, MSGL_WARN,
MSGTR_LIBASS_BetaVersionsOfFontconfigAreNotSupported);
// FontConfig >= 2.4.0 updates cache automatically in FcConfigAppFontAddDir()
if (FcGetVersion() < 20390) {
FcFontSet* fcs;
FcStrSet* fss;
fcs = FcFontSetCreate();
fss = FcStrSetCreate();
rc = FcStrSetAdd(fss, (const FcChar8*)dir);
if (!rc) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcStrSetAddFailed);
goto ErrorFontCache;
}
rc = FcDirScan(fcs, fss, NULL, FcConfigGetBlanks(priv->config), (const FcChar8 *)dir, FcFalse);
if (!rc) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcDirScanFailed);
goto ErrorFontCache;
}
rc = FcDirSave(fcs, fss, (const FcChar8 *)dir);
if (!rc) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcDirSave);
goto ErrorFontCache;
}
ErrorFontCache:
;
}
}
rc = FcConfigAppFontAddDir(priv->config, (const FcChar8*)dir);
if (!rc) {
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FcConfigAppFontAddDirFailed);
}
priv->family_default = family ? strdup(family) : 0;
priv->index_default = 0;
rc = stat(path, &st);
if (!rc && S_ISREG(st.st_mode))
priv->path_default = path ? strdup(path) : 0;
else
priv->path_default = 0;
return priv;
}
#else // HAVE_FONTCONFIG
char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index)
{
*index = priv->index_default;
return priv->path_default;
}
fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path)
{
fc_instance_t* priv;
mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_LIBASS_FontconfigDisabledDefaultFontWillBeUsed);
priv = calloc(1, sizeof(fc_instance_t));
priv->path_default = strdup(path);
priv->index_default = 0;
return priv;
}
#endif
void fontconfig_done(fc_instance_t* priv)
{
// don't call FcFini() here, library can still be used by some code
if (priv && priv->path_default) free(priv->path_default);
if (priv && priv->family_default) free(priv->family_default);
if (priv) free(priv);
}

39
libass/ass_fontconfig.h Normal file
View file

@ -0,0 +1,39 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_FONTCONFIG_H__
#define __ASS_FONTCONFIG_H__
#ifdef HAVE_FONTCONFIG
#include <fontconfig/fontconfig.h>
#endif
typedef struct fc_instance_s fc_instance_t;
fc_instance_t* fontconfig_init(ass_library_t* library, FT_Library ftlibrary, const char* family, const char* path);
char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index);
void fontconfig_done(fc_instance_t* priv);
#ifdef HAVE_FONTCONFIG
char* fontconfig_select_with_charset(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index, FcCharSet* charset);
#endif
#endif

93
libass/ass_library.c Normal file
View file

@ -0,0 +1,93 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ass.h"
#include "ass_library.h"
ass_library_t* ass_library_init(void)
{
return calloc(1, sizeof(ass_library_t));
}
void ass_library_done(ass_library_t* priv)
{
if (priv) {
ass_set_fonts_dir(priv, NULL);
ass_set_style_overrides(priv, NULL);
free(priv);
}
}
void ass_set_fonts_dir(ass_library_t* priv, const char* fonts_dir)
{
if (priv->fonts_dir)
free(priv->fonts_dir);
priv->fonts_dir = fonts_dir ? strdup(fonts_dir) : 0;
}
void ass_set_extract_fonts(ass_library_t* priv, int extract)
{
priv->extract_fonts = !!extract;
}
void ass_set_style_overrides(ass_library_t* 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);
}
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_t* priv, char* name, char* data, int size)
{
grow_array((void**)&priv->fontdata, priv->num_fontdata, sizeof(*priv->fontdata));
priv->fontdata[priv->num_fontdata].name = name;
priv->fontdata[priv->num_fontdata].data = data;
priv->fontdata[priv->num_fontdata].size = size;
priv->num_fontdata ++;
}

40
libass/ass_library.h Normal file
View file

@ -0,0 +1,40 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_LIBRARY_H__
#define __ASS_LIBRARY_H__
typedef struct ass_fontdata_s {
char* name;
char* data;
int size;
} ass_fontdata_t;
struct ass_library_s {
char* fonts_dir;
int extract_fonts;
char** style_overrides;
ass_fontdata_t* fontdata;
int num_fontdata;
};
#endif

2340
libass/ass_render.c Normal file

File diff suppressed because it is too large Load diff

114
libass/ass_types.h Normal file
View file

@ -0,0 +1,114 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_TYPES_H__
#define __ASS_TYPES_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
/// ass Style: line
typedef struct ass_style_s {
char* Name;
char* FontName;
int 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 AlphaLevel;
int Encoding;
} ass_style_t;
typedef struct render_priv_s render_priv_t;
/// ass_event_t corresponds to a single Dialogue line
/// Text is stored as-is, style overrides will be parsed later
typedef struct ass_event_s {
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;
render_priv_t* render_priv;
} ass_event_t;
typedef struct parser_priv_s parser_priv_t;
typedef struct ass_library_s ass_library_t;
/// 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_s {
int n_styles; // amount used
int max_styles; // amount allocated
int n_events;
int max_events;
ass_style_t* styles; // array of styles, max_styles length, n_styles used
ass_event_t* 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 default_style; // index of default style
char* name; // file name in case of external subs, 0 for streams
ass_library_t* library;
parser_priv_t* parser_priv;
} ass_track_t;
#endif

83
libass/ass_utils.c Normal file
View file

@ -0,0 +1,83 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "config.h"
#include <stdlib.h>
#include <inttypes.h>
#include <sys/time.h>
#include <time.h>
#include "mputils.h"
#include "ass_utils.h"
int mystrtoi(char** p, int base, int* res)
{
char* start = *p;
*res = strtol(*p, p, base);
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 = strtod(*p, p);
if (*p != start) return 1;
else return 0;
}
int strtocolor(char** q, uint32_t* res)
{
uint32_t color = 0;
int result;
char* p = *q;
if (*p == '&') ++p;
else mp_msg(MSGT_ASS, MSGL_DBG2, "suspicious color format: \"%s\"\n", p);
if (*p == 'H' || *p == 'h') {
++p;
result = mystrtou32(&p, 16, &color);
} else {
result = mystrtou32(&p, 0, &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;
}

55
libass/ass_utils.h Normal file
View file

@ -0,0 +1,55 @@
// -*- c-basic-offset: 8; indent-tabs-mode: t -*-
// vim:ts=8:sw=8:noet:ai:
/*
Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef __ASS_UTILS_H__
#define __ASS_UTILS_H__
int mystrtoi(char** p, int base, int* res);
int mystrtou32(char** p, int base, uint32_t* res);
int mystrtod(char** p, double* res);
int strtocolor(char** q, uint32_t* res);
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);
}
#endif

55
libass/help_mp.h Normal file
View file

@ -0,0 +1,55 @@
#ifndef __LIBASS_HELP_MP_H__
#define __LIBASS_HELP_MP_H__
#define MSGTR_LIBASS_FT_Glyph_To_BitmapError "[ass] FT_Glyph_To_Bitmap error %d \n"
#define MSGTR_LIBASS_UnsupportedPixelMode "[ass] Unsupported pixel mode: %d\n"
#define MSGTR_LIBASS_NoStyleNamedXFoundUsingY "[ass] [%p] Warning: no style named '%s' found, using '%s'\n"
#define MSGTR_LIBASS_BadTimestamp "[ass] bad timestamp\n"
#define MSGTR_LIBASS_BadEncodedDataSize "[ass] bad encoded data size\n"
#define MSGTR_LIBASS_FontLineTooLong "[ass] Font line too long: %d, %s\n"
#define MSGTR_LIBASS_EventFormatHeaderMissing "[ass] Event format header missing\n"
#define MSGTR_LIBASS_ErrorOpeningIconvDescriptor "[ass] error opening iconv descriptor.\n"
#define MSGTR_LIBASS_ErrorRecodingFile "[ass] error recoding file.\n"
#define MSGTR_LIBASS_FopenFailed "[ass] ass_read_file(%s): fopen failed\n"
#define MSGTR_LIBASS_FseekFailed "[ass] ass_read_file(%s): fseek failed\n"
#define MSGTR_LIBASS_RefusingToLoadSubtitlesLargerThan10M "[ass] ass_read_file(%s): Refusing to load subtitles larger than 10M\n"
#define MSGTR_LIBASS_ReadFailed "Read failed, %d: %s\n"
#define MSGTR_LIBASS_AddedSubtitleFileMemory "[ass] Added subtitle file: <memory> (%d styles, %d events)\n"
#define MSGTR_LIBASS_AddedSubtitleFileFname "[ass] Added subtitle file: %s (%d styles, %d events)\n"
#define MSGTR_LIBASS_FailedToCreateDirectory "[ass] Failed to create directory %s\n"
#define MSGTR_LIBASS_NotADirectory "[ass] Not a directory: %s\n"
#define MSGTR_LIBASS_TooManyFonts "[ass] Too many fonts\n"
#define MSGTR_LIBASS_ErrorOpeningFont "[ass] Error opening font: %s, %d\n"
#define MSGTR_LIBASS_SelectedFontFamilyIsNotTheRequestedOne "[ass] fontconfig: Selected font family is not the requested one: '%s' != '%s'\n"
#define MSGTR_LIBASS_UsingDefaultFontFamily "[ass] fontconfig_select: Using default font family: (%s, %d, %d) -> %s, %d\n"
#define MSGTR_LIBASS_UsingDefaultFont "[ass] fontconfig_select: Using default font: (%s, %d, %d) -> %s, %d\n"
#define MSGTR_LIBASS_UsingArialFontFamily "[ass] fontconfig_select: Using 'Arial' font family: (%s, %d, %d) -> %s, %d\n"
#define MSGTR_LIBASS_FcInitLoadConfigAndFontsFailed "[ass] FcInitLoadConfigAndFonts failed.\n"
#define MSGTR_LIBASS_UpdatingFontCache "[ass] Updating font cache.\n"
#define MSGTR_LIBASS_BetaVersionsOfFontconfigAreNotSupported "[ass] Beta versions of fontconfig are not supported.\n[ass] Update before reporting any bugs.\n"
#define MSGTR_LIBASS_FcStrSetAddFailed "[ass] FcStrSetAdd failed.\n"
#define MSGTR_LIBASS_FcDirScanFailed "[ass] FcDirScan failed.\n"
#define MSGTR_LIBASS_FcDirSave "[ass] FcDirSave failed.\n"
#define MSGTR_LIBASS_FcConfigAppFontAddDirFailed "[ass] FcConfigAppFontAddDir failed\n"
#define MSGTR_LIBASS_FontconfigDisabledDefaultFontWillBeUsed "[ass] Fontconfig disabled, only default font will be used.\n"
#define MSGTR_LIBASS_FunctionCallFailed "[ass] %s failed\n"
#define MSGTR_LIBASS_NeitherPlayResXNorPlayResYDefined "[ass] Neither PlayResX nor PlayResY defined. Assuming 384x288.\n"
#define MSGTR_LIBASS_PlayResYUndefinedSettingY "[ass] PlayResY undefined, setting %d.\n"
#define MSGTR_LIBASS_PlayResXUndefinedSettingX "[ass] PlayResX undefined, setting %d.\n"
#define MSGTR_LIBASS_FT_Init_FreeTypeFailed "[ass] FT_Init_FreeType failed.\n"
#define MSGTR_LIBASS_Init "[ass] Init\n"
#define MSGTR_LIBASS_InitFailed "[ass] Init failed.\n"
#define MSGTR_LIBASS_BadCommand "[ass] Bad command: %c%c\n"
#define MSGTR_LIBASS_ErrorLoadingGlyph "[ass] Error loading glyph.\n"
#define MSGTR_LIBASS_FT_Glyph_Stroke_Error "[ass] FT_Glyph_Stroke error %d \n"
#define MSGTR_LIBASS_UnknownEffectType_InternalError "[ass] Unknown effect type (internal error)\n"
#define MSGTR_LIBASS_NoStyleFound "[ass] No style found!\n"
#define MSGTR_LIBASS_EmptyEvent "[ass] Empty event!\n"
#define MSGTR_LIBASS_MAX_GLYPHS_Reached "[ass] MAX_GLYPHS reached: event %d, start = %llu, duration = %llu\n Text = %s\n"
#define MSGTR_LIBASS_EventHeightHasChanged "[ass] Warning! Event height has changed! \n"
#define MSGTR_LIBASS_GlyphNotFoundReselectingFont "[ass] Glyph 0x%X not found, reselecting font for (%s, %d, %d)\n"
#define MSGTR_LIBASS_GlyphNotFound "[ass] Glyph 0x%X not found in font for (%s, %d, %d)\n"
#define MSGTR_LIBASS_ErrorOpeningMemoryFont "[ass] Error opening memory font: %s\n"
#define MSGTR_LIBASS_NoCharmaps "[ass] font face with no charmaps\n"
#define MSGTR_LIBASS_NoCharmapAutodetected "[ass] no charmap autodetected, trying the first one\n"
#endif

218
libass/mputils.c Normal file
View file

@ -0,0 +1,218 @@
#include "config.h"
#include "mputils.h"
#include <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef HAVE_ENCA
#include <enca.h>
#endif
void my_mp_msg(int lvl, char *lvl_str, char *fmt, ...) {
if(lvl > MSGL_V) return;
printf("[ass] **%s**: ", lvl_str);
va_list va;
va_start(va, fmt);
vprintf(fmt, va);
va_end(va);
}
unsigned 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;
}
// gaussian blur
void 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= 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= 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= 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= 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= 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= 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;
}
}
#ifdef HAVE_ENCA
void* guess_buffer_cp(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);
mp_msg(MSGT_ASS, MSGL_V, "ENCA supported languages: ");
for (i = 0; i < langcnt; i++) {
mp_msg(MSGT_ASS, MSGL_V, "%s ", languages[i]);
}
mp_msg(MSGT_ASS, MSGL_V, "\n");
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);
mp_msg(MSGT_ASS, MSGL_INFO, "ENCA detected charset: %s\n", tmp);
}
enca_analyser_free(analyser);
}
free(languages);
if (!detected_sub_cp) {
detected_sub_cp = strdup(fallback);
mp_msg(MSGT_ASS, MSGL_INFO, "ENCA detection failed: fallback to %s\n", fallback);
}
return detected_sub_cp;
}
#endif

29
libass/mputils.h Normal file
View file

@ -0,0 +1,29 @@
#ifndef __MPUTILS_H__
#define __MPUTILS_H__
#include "help_mp.h"
unsigned utf8_get_char(char **str);
void my_mp_msg(int lvl, char *lvl_str, char *fmt, ...);
#define mp_msg(mod, level, args...) my_mp_msg(level, #level, args)
#define MSGT_ASS 43
#define MSGL_FATAL 0
#define MSGL_ERR 1
#define MSGL_WARN 2
#define MSGL_INFO 4
#define MSGL_V 6
#define MSGL_DBG2 7
void blur(unsigned char *buffer, unsigned short *tmp2, int width, int height,
int stride, int *m2, int r, int mwidth);
void* guess_buffer_cp(unsigned char* buffer, int buflen, char *preferred_language, char *fallback);
#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
#endif