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:
parent
1e3694d859
commit
41843bf292
22 changed files with 6272 additions and 1 deletions
|
@ -47,7 +47,14 @@ extern "C" {
|
||||||
///////////
|
///////////
|
||||||
// Library
|
// Library
|
||||||
#ifdef __VISUALC__
|
#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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
10
libass/Makefile.am
Normal file
10
libass/Makefile.am
Normal 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
498
libass/Makefile.in
Normal 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
1077
libass/ass.c
Normal file
File diff suppressed because it is too large
Load diff
198
libass/ass.h
Normal file
198
libass/ass.h
Normal 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
272
libass/ass_bitmap.c
Normal 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
49
libass/ass_bitmap.h
Normal 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
220
libass/ass_cache.c
Normal 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
62
libass/ass_cache.h
Normal 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
327
libass/ass_font.c
Normal 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
57
libass/ass_font.h
Normal 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
428
libass/ass_fontconfig.c
Normal 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
39
libass/ass_fontconfig.h
Normal 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
93
libass/ass_library.c
Normal 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
40
libass/ass_library.h
Normal 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
2340
libass/ass_render.c
Normal file
File diff suppressed because it is too large
Load diff
114
libass/ass_types.h
Normal file
114
libass/ass_types.h
Normal 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
83
libass/ass_utils.c
Normal 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
55
libass/ass_utils.h
Normal 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
55
libass/help_mp.h
Normal 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
218
libass/mputils.c
Normal 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
29
libass/mputils.h
Normal 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
|
Loading…
Reference in a new issue