diff -Nru libass-0.13.2/aclocal.m4 libass-0.13.4/aclocal.m4 --- libass-0.13.2/aclocal.m4 2016-02-20 19:47:08.000000000 +0000 +++ libass-0.13.4/aclocal.m4 2016-10-04 23:12:16.000000000 +0000 @@ -20,32 +20,63 @@ If you have problems, you may need to regenerate the build system entirely. To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- -# serial 1 (pkg-config-0.24) -# -# Copyright © 2004 Scott James Remnant . -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# PKG_PROG_PKG_CONFIG([MIN-VERSION]) -# ---------------------------------- +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) @@ -67,18 +98,19 @@ PKG_CONFIG="" fi fi[]dnl -])# PKG_PROG_PKG_CONFIG +])dnl PKG_PROG_PKG_CONFIG -# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# -# Check to see whether a particular set of modules exists. Similar -# to PKG_CHECK_MODULES(), but does not set variables or print errors. -# -# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) -# only at the first occurence in configure.ac, so if the first place -# it's called might be skipped (such as if it is within an "if", you -# have to call PKG_CHECK_EXISTS manually -# -------------------------------------------------------------- +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ @@ -88,8 +120,10 @@ $3])dnl fi]) -# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) -# --------------------------------------------- +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" @@ -101,10 +135,11 @@ else pkg_failed=untried fi[]dnl -])# _PKG_CONFIG +])dnl _PKG_CONFIG -# _PKG_SHORT_ERRORS_SUPPORTED -# ----------------------------- +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then @@ -112,19 +147,17 @@ else _pkg_short_errors_supported=no fi[]dnl -])# _PKG_SHORT_ERRORS_SUPPORTED +])dnl _PKG_SHORT_ERRORS_SUPPORTED -# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], -# [ACTION-IF-NOT-FOUND]) -# -# -# Note that if there is a possibility the first call to -# PKG_CHECK_MODULES might not happen, you should be sure to include an -# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac -# -# -# -------------------------------------------------------------- +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl @@ -178,16 +211,40 @@ AC_MSG_RESULT([yes]) $3 fi[]dnl -])# PKG_CHECK_MODULES +])dnl PKG_CHECK_MODULES -# PKG_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable pkgconfigdir as the location where a module -# should install pkg-config .pc files. By default the directory is -# $libdir/pkgconfig, but the default can be changed by passing -# DIRECTORY. The user can override through the --with-pkgconfigdir -# parameter. +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -198,16 +255,18 @@ AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_INSTALLDIR +])dnl PKG_INSTALLDIR -# PKG_NOARCH_INSTALLDIR(DIRECTORY) -# ------------------------- -# Substitutes the variable noarch_pkgconfigdir as the location where a -# module should install arch-independent pkg-config .pc files. By -# default the directory is $datadir/pkgconfig, but the default can be -# changed by passing DIRECTORY. The user can override through the -# --with-noarch-pkgconfigdir parameter. +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], @@ -218,13 +277,15 @@ AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) -]) dnl PKG_NOARCH_INSTALLDIR +])dnl PKG_NOARCH_INSTALLDIR -# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, -# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) -# ------------------------------------------- -# Retrieves the value of the pkg-config variable for the given module. +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl @@ -233,7 +294,7 @@ AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl -])# PKG_CHECK_VAR +])dnl PKG_CHECK_VAR # Copyright (C) 2002-2014 Free Software Foundation, Inc. # diff -Nru libass-0.13.2/Changelog libass-0.13.4/Changelog --- libass-0.13.2/Changelog 2016-02-20 19:36:25.000000000 +0000 +++ libass-0.13.4/Changelog 2016-10-04 23:10:16.000000000 +0000 @@ -1,3 +1,19 @@ +libass (0.13.4) + * Bug fixes found with fuzzing + * Fix memory reallocation in the shaper. + * Fix two small memory leaks in the parser and test program. + * Fix illegal read in Gaussian blur coefficient calculations. + * Fix mode 0/3 line wrapping equalization in specific cases which could + result in illegal reads while laying out and shaping text. + +libass (0.13.3) + * Improve compatibility/portablility of build system, + should fix e.g. compilation on Solaris. + * Fix memory leak in DirectWrite font provider. + * Fix the rasterizer when rendering some large outlines. + * Remove hack that forced RTL base direction depending on font encoding. + * Greatly improve the internal caches with refcounting and gradual clearing. + libass (0.13.2) * Add ass_set_check_readorder() API function to disable use of the ReadOrder field for duplicate checking in ass_process_chunk(). diff -Nru libass-0.13.2/config.guess libass-0.13.4/config.guess --- libass-0.13.2/config.guess 2016-02-20 19:47:11.000000000 +0000 +++ libass-0.13.4/config.guess 2016-10-04 23:12:17.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2015 Free Software Foundation, Inc. -timestamp='2014-11-04' +timestamp='2015-08-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -50,7 +50,7 @@ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -168,20 +168,27 @@ # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + /sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || \ + echo unknown)` case "${UNAME_MACHINE_ARCH}" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; + earmv*) + arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'` + machine=${arch}${endian}-unknown + ;; *) machine=${UNAME_MACHINE_ARCH}-unknown ;; esac # The Operating System including object format, if it has switched # to ELF recently, or will in the future. case "${UNAME_MACHINE_ARCH}" in - arm*|i386|m68k|ns32k|sh3*|sparc|vax) + arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ | grep -q __ELF__ @@ -197,6 +204,13 @@ os=netbsd ;; esac + # Determine ABI tags. + case "${UNAME_MACHINE_ARCH}" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"` + ;; + esac # The OS release # Debian GNU/NetBSD machines have a different userland, and # thus, need a distinct triplet. However, they do not need @@ -207,13 +221,13 @@ release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "${machine}-${os}${release}${abi}" exit ;; *:Bitrig:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` @@ -235,6 +249,9 @@ *:MirBSD:*:*) echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} exit ;; + *:Sortix:*:*) + echo ${UNAME_MACHINE}-unknown-sortix + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) @@ -933,6 +950,9 @@ crisv32:Linux:*:*) echo ${UNAME_MACHINE}-axis-linux-${LIBC} exit ;; + e2k:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + exit ;; frv:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} exit ;; @@ -1021,7 +1041,7 @@ echo ${UNAME_MACHINE}-dec-linux-${LIBC} exit ;; x86_64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-${LIBC} + echo ${UNAME_MACHINE}-pc-linux-${LIBC} exit ;; xtensa*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-${LIBC} diff -Nru libass-0.13.2/config.sub libass-0.13.4/config.sub --- libass-0.13.2/config.sub 2016-02-20 19:47:11.000000000 +0000 +++ libass-0.13.4/config.sub 2016-10-04 23:12:17.000000000 +0000 @@ -1,8 +1,8 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright 1992-2014 Free Software Foundation, Inc. +# Copyright 1992-2015 Free Software Foundation, Inc. -timestamp='2014-12-03' +timestamp='2015-08-20' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -68,7 +68,7 @@ version="\ GNU config.sub ($timestamp) -Copyright 1992-2014 Free Software Foundation, Inc. +Copyright 1992-2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -117,7 +117,7 @@ case $maybe_os in nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ - knetbsd*-gnu* | netbsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ kopensolaris*-gnu* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os @@ -255,12 +255,13 @@ | arc | arceb \ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ | avr | avr32 \ + | ba \ | be32 | be64 \ | bfin \ | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | epiphany \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | hexagon \ | i370 | i860 | i960 | ia64 \ @@ -305,7 +306,7 @@ | riscv32 | riscv64 \ | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ @@ -376,12 +377,13 @@ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ | be32-* | be64-* \ | bfin-* | bs2000-* \ | c[123]* | c30-* | [cjt]90-* | c4x-* \ | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ @@ -428,12 +430,13 @@ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ | pyramid-* \ + | riscv32-* | riscv64-* \ | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ | tahoe-* \ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | tile*-* \ @@ -518,6 +521,9 @@ basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -1373,7 +1379,7 @@ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ diff -Nru libass-0.13.2/configure libass-0.13.4/configure --- libass-0.13.2/configure 2016-02-20 19:47:09.000000000 +0000 +++ libass-0.13.4/configure 2016-10-04 23:12:16.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for libass 0.13.2. +# Generated by GNU Autoconf 2.69 for libass 0.13.4. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. @@ -587,8 +587,8 @@ # Identity of this package. PACKAGE_NAME='libass' PACKAGE_TARNAME='libass' -PACKAGE_VERSION='0.13.2' -PACKAGE_STRING='libass 0.13.2' +PACKAGE_VERSION='0.13.4' +PACKAGE_STRING='libass 0.13.4' PACKAGE_BUGREPORT='' PACKAGE_URL='' @@ -772,6 +772,7 @@ docdir oldincludedir includedir +runstatedir localstatedir sharedstatedir sysconfdir @@ -878,6 +879,7 @@ sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1130,6 +1132,15 @@ | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1267,7 +1278,7 @@ for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir + libdir localedir mandir runstatedir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1380,7 +1391,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libass 0.13.2 to adapt to many kinds of systems. +\`configure' configures libass 0.13.4 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1420,6 +1431,7 @@ --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -1450,7 +1462,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libass 0.13.2:";; + short | recursive ) echo "Configuration of libass 0.13.4:";; esac cat <<\_ACEOF @@ -1601,7 +1613,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libass configure 0.13.2 +libass configure 0.13.4 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2020,7 +2032,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libass $as_me 0.13.2, which was +It was created by libass $as_me 0.13.4, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2883,7 +2895,7 @@ # Define the identity of the package. PACKAGE='libass' - VERSION='0.13.2' + VERSION='0.13.4' cat >>confdefs.h <<_ACEOF @@ -5327,7 +5339,7 @@ lt_cv_deplibs_check_method=pass_all ;; -netbsd*) +netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' else @@ -9020,6 +9032,9 @@ openbsd* | bitrig*) with_gnu_ld=no ;; + linux* | k*bsd*-gnu | gnu*) + link_all_deplibs=no + ;; esac ld_shlibs=yes @@ -9274,7 +9289,7 @@ fi ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= @@ -9944,6 +9959,7 @@ if test yes = "$lt_cv_irix_exported_symbol"; then archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi + link_all_deplibs=no else archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' @@ -9965,7 +9981,7 @@ esac ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else @@ -11080,6 +11096,18 @@ dynamic_linker='GNU/Linux ld.so' ;; +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + netbsd*) version_type=sunos need_lib_prefix=no @@ -13572,7 +13600,7 @@ *darwin*) : ASFLAGS="$ASFLAGS -f macho$BITS -DPREFIX -DHAVE_ALIGNED_STACK=1" ;; #( - *linux*|*dragonfly*|*bsd*) : + *linux*|*dragonfly*|*bsd*|*solaris*) : ASFLAGS="$ASFLAGS -f elf -DHAVE_ALIGNED_STACK=1" ;; #( *cygwin*|*mingw*) : @@ -14454,6 +14482,10 @@ $as_echo "#define CONFIG_ICONV 1" >>confdefs.h + if test x"$ac_cv_search_libiconv_open" != x"none required" && + test x"$ac_cv_search_iconv_open" != x"none required"; then + pkg_libs="${pkg_libs} -liconv" + fi fi pkg_requires="freetype2 >= 9.10.3" pkg_requires="fribidi >= 0.19.0, ${pkg_requires}" @@ -14470,8 +14502,8 @@ test x$coretext != xtrue then as_fn_error $? "\ -Either DirectWrite (on Windows), CoreText (on OSX), or Fontconfig\ -(Linux, other) is required. If you really want to compile without\ +Either DirectWrite (on Windows), CoreText (on OSX), or Fontconfig \ +(Linux, other) is required. If you really want to compile without \ a system font provider, add --disable-require-system-font-provider" "$LINENO" 5 fi @@ -15105,7 +15137,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libass $as_me 0.13.2, which was +This file was extended by libass $as_me 0.13.4, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -15171,7 +15203,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libass config.status 0.13.2 +libass config.status 0.13.4 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru libass-0.13.2/configure.ac libass-0.13.4/configure.ac --- libass-0.13.2/configure.ac 2016-02-20 19:36:25.000000000 +0000 +++ libass-0.13.4/configure.ac 2016-10-04 23:07:37.000000000 +0000 @@ -1,4 +1,4 @@ -AC_INIT(libass, 0.13.2) +AC_INIT(libass, 0.13.4) AM_INIT_AUTOMAKE AC_CONFIG_MACRO_DIR([m4]) # Disable Fortran checks @@ -78,7 +78,7 @@ AS_CASE([$host], [*darwin*], [ ASFLAGS="$ASFLAGS -f macho$BITS -DPREFIX -DHAVE_ALIGNED_STACK=1" ], - [*linux*|*dragonfly*|*bsd*], [ + [*linux*|*dragonfly*|*bsd*|*solaris*], [ ASFLAGS="$ASFLAGS -f elf -DHAVE_ALIGNED_STACK=1" ], [*cygwin*|*mingw*], [ ASFLAGS="$ASFLAGS -f win$BITS" @@ -227,6 +227,10 @@ # add packages to pkg-config for static linking if test "$use_libiconv" = true; then AC_DEFINE(CONFIG_ICONV, 1, [use iconv]) + if test x"$ac_cv_search_libiconv_open" != x"none required" && + test x"$ac_cv_search_iconv_open" != x"none required"; then + pkg_libs="${pkg_libs} -liconv" + fi fi pkg_requires="freetype2 >= 9.10.3" pkg_requires="fribidi >= 0.19.0, ${pkg_requires}" @@ -243,8 +247,8 @@ test x$coretext != xtrue then AC_MSG_ERROR([\ -Either DirectWrite (on Windows), CoreText (on OSX), or Fontconfig\ -(Linux, other) is required. If you really want to compile without\ +Either DirectWrite (on Windows), CoreText (on OSX), or Fontconfig \ +(Linux, other) is required. If you really want to compile without \ a system font provider, add --disable-require-system-font-provider]) fi diff -Nru libass-0.13.2/COPYING libass-0.13.4/COPYING --- libass-0.13.2/COPYING 2015-03-04 15:20:48.000000000 +0000 +++ libass-0.13.4/COPYING 2016-10-04 00:15:27.000000000 +0000 @@ -1,3 +1,7 @@ +ISC License + +Copyright (C) 2006-2016 libass contributors + Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. diff -Nru libass-0.13.2/debian/changelog libass-0.13.4/debian/changelog --- libass-0.13.2/debian/changelog 2016-03-22 14:27:14.000000000 +0000 +++ libass-0.13.4/debian/changelog 2016-11-01 23:20:19.000000000 +0000 @@ -1,4 +1,10 @@ -libass (0.13.2-1~xenial) xenial; urgency=low +libass (0.13.4-1~xenial) xenial; urgency=low + + * New upstream release + + -- Marshall Banana Wed, 02 Nov 2016 00:18:56 +0100 + +libass (0.13.2-1~trusty) trusty; urgency=low * New upstream release diff -Nru libass-0.13.2/install-sh libass-0.13.4/install-sh --- libass-0.13.2/install-sh 2016-02-20 19:47:11.000000000 +0000 +++ libass-0.13.4/install-sh 2016-10-04 23:12:17.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2013-12-25.23; # UTC +scriptversion=2014-09-12.12; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -324,34 +324,41 @@ # is incompatible with FreeBSD 'install' when (umask & 300) != 0. ;; *) + # $RANDOM is not portable (e.g. dash); use it when possible to + # lower collision chance tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ - trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + trap 'ret=$?; rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null; exit $ret' 0 + # As "mkdir -p" follows symlinks and we work in /tmp possibly; so + # create the $tmpdir first (and fail if unsuccessful) to make sure + # that nobody tries to guess the $tmpdir name. if (umask $mkdir_umask && - exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + $mkdirprog $mkdir_mode "$tmpdir" && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { # Check for POSIX incompatibilities with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. - ls_ld_tmpdir=`ls -ld "$tmpdir"` + test_tmpdir="$tmpdir/a" + ls_ld_tmpdir=`ls -ld "$test_tmpdir"` case $ls_ld_tmpdir in d????-?r-*) different_mode=700;; d????-?--*) different_mode=755;; *) false;; esac && - $mkdirprog -m$different_mode -p -- "$tmpdir" && { - ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + $mkdirprog -m$different_mode -p -- "$test_tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"` test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" } } then posix_mkdir=: fi - rmdir "$tmpdir/d" "$tmpdir" + rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" else # Remove any dirs left behind by ancient mkdir implementations. - rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null fi trap '' 0;; esac;; diff -Nru libass-0.13.2/libass/ass_bitmap.c libass-0.13.4/libass/ass_bitmap.c --- libass-0.13.2/libass/ass_bitmap.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_bitmap.c 2016-10-04 19:52:56.000000000 +0000 @@ -82,7 +82,7 @@ if (blur_g) size_g = sizeof(uint16_t) * bm_g->stride * 2; size_t size = FFMAX(size_o, size_g); - uint16_t *tmp = size ? ass_aligned_alloc(32, size) : NULL; + uint16_t *tmp = size ? ass_aligned_alloc(32, size, false) : NULL; if (!tmp) return; if (bm_o) { @@ -127,14 +127,15 @@ } } -static bool alloc_bitmap_buffer(const BitmapEngine *engine, Bitmap *bm, int w, int h) +static bool alloc_bitmap_buffer(const BitmapEngine *engine, Bitmap *bm, int w, int h, + bool zero) { unsigned align = 1 << engine->align_order; size_t s = ass_align(align, w); // Too often we use ints as offset for bitmaps => use INT_MAX. if (s > (INT_MAX - 32) / FFMAX(h, 1)) return false; - uint8_t *buf = ass_aligned_alloc(align, s * h + 32); + uint8_t *buf = ass_aligned_alloc(align, s * h + 32, zero); if (!buf) return false; bm->w = w; @@ -144,24 +145,15 @@ return true; } -static Bitmap *alloc_bitmap_raw(const BitmapEngine *engine, int w, int h) +Bitmap *alloc_bitmap(const BitmapEngine *engine, int w, int h, bool zero) { Bitmap *bm = malloc(sizeof(Bitmap)); if (!bm) return NULL; - if (!alloc_bitmap_buffer(engine, bm, w, h)) { + if (!alloc_bitmap_buffer(engine, bm, w, h, zero)) { free(bm); return NULL; } - return bm; -} - -Bitmap *alloc_bitmap(const BitmapEngine *engine, int w, int h) -{ - Bitmap *bm = alloc_bitmap_raw(engine, w, h); - if(!bm) - return NULL; - memset(bm->buffer, 0, bm->stride * bm->h + 32); bm->left = bm->top = 0; return bm; } @@ -169,7 +161,7 @@ bool realloc_bitmap(const BitmapEngine *engine, Bitmap *bm, int w, int h) { uint8_t *old = bm->buffer; - if (!alloc_bitmap_buffer(engine, bm, w, h)) + if (!alloc_bitmap_buffer(engine, bm, w, h, false)) return false; ass_aligned_free(old); return true; @@ -184,7 +176,7 @@ Bitmap *copy_bitmap(const BitmapEngine *engine, const Bitmap *src) { - Bitmap *dst = alloc_bitmap_raw(engine, src->w, src->h); + Bitmap *dst = alloc_bitmap(engine, src->w, src->h, false); if (!dst) return NULL; dst->left = src->left; @@ -208,7 +200,7 @@ return NULL; if (rst->x_min >= rst->x_max || rst->y_min >= rst->y_max) { - Bitmap *bm = alloc_bitmap(render_priv->engine, 2 * bord, 2 * bord); + Bitmap *bm = alloc_bitmap(render_priv->engine, 2 * bord, 2 * bord, true); if (!bm) return NULL; bm->left = bm->top = -bord; @@ -236,7 +228,7 @@ int tile_w = (w + 2 * bord + mask) & ~mask; int tile_h = (h + 2 * bord + mask) & ~mask; - Bitmap *bm = alloc_bitmap_raw(render_priv->engine, tile_w, tile_h); + Bitmap *bm = alloc_bitmap(render_priv->engine, tile_w, tile_h, false); if (!bm) return NULL; bm->left = x_min - bord; @@ -266,7 +258,7 @@ FT_Outline_Get_CBox(outline, &bbox); if (bbox.xMin >= bbox.xMax || bbox.yMin >= bbox.yMax) { - bm = alloc_bitmap(render_priv->engine, 2 * bord, 2 * bord); + bm = alloc_bitmap(render_priv->engine, 2 * bord, 2 * bord, true); if (!bm) return NULL; bm->left = bm->top = -bord; @@ -296,7 +288,7 @@ } // allocate and set up bitmap - bm = alloc_bitmap(render_priv->engine, w + 2 * bord, h + 2 * bord); + bm = alloc_bitmap(render_priv->engine, w + 2 * bord, h + 2 * bord, true); if (!bm) return NULL; bm->left = bbox.xMin - bord; diff -Nru libass-0.13.2/libass/ass_bitmap.h libass-0.13.4/libass/ass_bitmap.h --- libass-0.13.2/libass/ass_bitmap.h 2016-02-08 17:55:08.000000000 +0000 +++ libass-0.13.4/libass/ass_bitmap.h 2016-10-04 00:15:27.000000000 +0000 @@ -107,7 +107,7 @@ unsigned char *buffer; // h * stride buffer } Bitmap; -Bitmap *alloc_bitmap(const BitmapEngine *engine, int w, int h); +Bitmap *alloc_bitmap(const BitmapEngine *engine, int w, int h, bool zero); bool realloc_bitmap(const BitmapEngine *engine, Bitmap *bm, int w, int h); Bitmap *copy_bitmap(const BitmapEngine *engine, const Bitmap *src); void ass_free_bitmap(Bitmap *bm); diff -Nru libass-0.13.2/libass/ass_blur.c libass-0.13.4/libass/ass_blur.c --- libass-0.13.2/libass/ass_blur.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_blur.c 2016-10-04 20:56:28.000000000 +0000 @@ -744,7 +744,7 @@ ( 17 - 126 * mul + 273 * mul2 - 164 * mul3) / 12096, }; - double mat_freq[13]; + double mat_freq[14]; memcpy(mat_freq, kernel, sizeof(kernel)); memset(mat_freq + 4, 0, sizeof(mat_freq) - sizeof(kernel)); int n = 6; @@ -851,7 +851,7 @@ const int stripe_width = 1 << (engine->align_order - 1); int size = end_h * ((end_w + stripe_width - 1) & ~(stripe_width - 1)); - int16_t *tmp = ass_aligned_alloc(2 * stripe_width, 4 * size); + int16_t *tmp = ass_aligned_alloc(2 * stripe_width, 4 * size, false); if (!tmp) return false; diff -Nru libass-0.13.2/libass/ass.c libass-0.13.4/libass/ass.c --- libass-0.13.2/libass/ass.c 2016-02-20 18:20:05.000000000 +0000 +++ libass-0.13.4/libass/ass.c 2016-10-04 20:56:28.000000000 +0000 @@ -590,6 +590,7 @@ if (!strncmp(str, "Format:", 7)) { char *p = str + 7; skip_spaces(&p); + free(track->style_format); track->style_format = strdup(p); ass_msg(track->library, MSGL_DBG2, "Style format: %s", track->style_format); diff -Nru libass-0.13.2/libass/ass_cache.c libass-0.13.4/libass/ass_cache.c --- libass-0.13.2/libass/ass_cache.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_cache.c 2016-10-04 00:15:27.000000000 +0000 @@ -63,38 +63,32 @@ return 1; } -static void font_destruct(void *key, void *value) +static bool font_key_move(void *dst, void *src, size_t key_size) { - ass_font_free(value); - free(key); + ASS_FontDesc *k = src; + if (dst) + memcpy(dst, src, key_size); + else + free(k->family); + return true; } -// bitmap cache -static void bitmap_destruct(void *key, void *value) +static void font_destruct(void *key, void *value) { - BitmapHashValue *v = value; - BitmapHashKey *k = key; - if (v->bm) - ass_free_bitmap(v->bm); - if (v->bm_o) - ass_free_bitmap(v->bm_o); - if (k->type == BITMAP_CLIP) - free(k->u.clip.text); - free(key); - free(value); + ass_font_clear(value); } -static size_t bitmap_size(void *value, size_t value_size) -{ - BitmapHashValue *val = value; - size_t size = sizeof(BitmapHashKey) + sizeof(BitmapHashValue); - if (val->bm) - size += sizeof(Bitmap) + val->bm->stride * val->bm->h; - if (val->bm_o) - size += sizeof(Bitmap) + val->bm_o->stride * val->bm_o->h; - return size; -} +const CacheDesc font_cache_desc = { + .hash_func = font_hash, + .compare_func = font_compare, + .key_move_func = font_key_move, + .destruct_func = font_destruct, + .key_size = sizeof(ASS_FontDesc), + .value_size = sizeof(ASS_Font) +}; + +// bitmap cache static unsigned bitmap_hash(void *key, size_t key_size) { BitmapHashKey *k = key; @@ -105,7 +99,7 @@ } } -static unsigned bitmap_compare (void *a, void *b, size_t key_size) +static unsigned bitmap_compare(void *a, void *b, size_t key_size) { BitmapHashKey *ak = a; BitmapHashKey *bk = b; @@ -117,40 +111,51 @@ } } -// composite cache -static void composite_destruct(void *key, void *value) +static bool bitmap_key_move(void *dst, void *src, size_t key_size) { - CompositeHashValue *v = value; - CompositeHashKey *k = key; + BitmapHashKey *d = dst, *s = src; + if (!dst) { + if (s->type == BITMAP_OUTLINE) + ass_cache_dec_ref(s->u.outline.outline); + return true; + } + memcpy(dst, src, key_size); + if (s->type != BITMAP_CLIP) + return true; + d->u.clip.text = strdup(s->u.clip.text); + return d->u.clip.text; +} + +static void bitmap_destruct(void *key, void *value) +{ + BitmapHashValue *v = value; + BitmapHashKey *k = key; if (v->bm) ass_free_bitmap(v->bm); if (v->bm_o) ass_free_bitmap(v->bm_o); - if (v->bm_s) - ass_free_bitmap(v->bm_s); - free(k->bitmaps); - free(key); - free(value); + switch (k->type) { + case BITMAP_OUTLINE: ass_cache_dec_ref(k->u.outline.outline); break; + case BITMAP_CLIP: free(k->u.clip.text); break; + } } -static size_t composite_size(void *value, size_t value_size) -{ - CompositeHashValue *val = value; - size_t size = sizeof(CompositeHashKey) + sizeof(CompositeHashValue); - if (val->bm) - size += sizeof(Bitmap) + val->bm->stride * val->bm->h; - if (val->bm_o) - size += sizeof(Bitmap) + val->bm_o->stride * val->bm_o->h; - if (val->bm_s) - size += sizeof(Bitmap) + val->bm_s->stride * val->bm_s->h; - return size; -} +const CacheDesc bitmap_cache_desc = { + .hash_func = bitmap_hash, + .compare_func = bitmap_compare, + .key_move_func = bitmap_key_move, + .destruct_func = bitmap_destruct, + .key_size = sizeof(BitmapHashKey), + .value_size = sizeof(BitmapHashValue) +}; + +// composite cache static unsigned composite_hash(void *key, size_t key_size) { CompositeHashKey *k = key; unsigned hval = filter_hash(&k->filter, key_size); - for (size_t i = 0; i < k->bitmap_count; ++i) { + for (size_t i = 0; i < k->bitmap_count; i++) { hval = fnv_32a_buf(&k->bitmaps[i].image, sizeof(k->bitmaps[i].image), hval); hval = fnv_32a_buf(&k->bitmaps[i].x, sizeof(k->bitmaps[i].x), hval); hval = fnv_32a_buf(&k->bitmaps[i].y, sizeof(k->bitmaps[i].y), hval); @@ -164,7 +169,7 @@ CompositeHashKey *bk = b; if (ak->bitmap_count != bk->bitmap_count) return 0; - for (size_t i = 0; i < ak->bitmap_count; ++i) { + for (size_t i = 0; i < ak->bitmap_count; i++) { if (ak->bitmaps[i].image != bk->bitmaps[i].image || ak->bitmaps[i].x != bk->bitmaps[i].x || ak->bitmaps[i].y != bk->bitmaps[i].y) @@ -173,8 +178,45 @@ return filter_compare(&ak->filter, &bk->filter, key_size); } -// outline cache +static bool composite_key_move(void *dst, void *src, size_t key_size) +{ + if (dst) { + memcpy(dst, src, key_size); + return true; + } + CompositeHashKey *k = src; + for (size_t i = 0; i < k->bitmap_count; i++) + ass_cache_dec_ref(k->bitmaps[i].image); + free(k->bitmaps); + return true; +} + +static void composite_destruct(void *key, void *value) +{ + CompositeHashValue *v = value; + CompositeHashKey *k = key; + if (v->bm) + ass_free_bitmap(v->bm); + if (v->bm_o) + ass_free_bitmap(v->bm_o); + if (v->bm_s) + ass_free_bitmap(v->bm_s); + for (size_t i = 0; i < k->bitmap_count; i++) + ass_cache_dec_ref(k->bitmaps[i].image); + free(k->bitmaps); +} + +const CacheDesc composite_cache_desc = { + .hash_func = composite_hash, + .compare_func = composite_compare, + .key_move_func = composite_key_move, + .destruct_func = composite_destruct, + .key_size = sizeof(CompositeHashKey), + .value_size = sizeof(CompositeHashValue) +}; + +// outline cache static unsigned outline_hash(void *key, size_t key_size) { OutlineHashKey *k = key; @@ -197,6 +239,21 @@ } } +static bool outline_key_move(void *dst, void *src, size_t key_size) +{ + OutlineHashKey *d = dst, *s = src; + if (!dst) { + if (s->type == OUTLINE_GLYPH) + ass_cache_dec_ref(s->u.glyph.font); + return true; + } + memcpy(dst, src, key_size); + if (s->type != OUTLINE_DRAWING) + return true; + d->u.drawing.text = strdup(s->u.drawing.text); + return d->u.drawing.text; +} + static void outline_destruct(void *key, void *value) { OutlineHashValue *v = value; @@ -205,31 +262,65 @@ free(v->outline); outline_free(v->border); free(v->border); - if (k->type == OUTLINE_DRAWING) - free(k->u.drawing.text); - free(key); - free(value); + switch (k->type) { + case OUTLINE_GLYPH: ass_cache_dec_ref(k->u.glyph.font); break; + case OUTLINE_DRAWING: free(k->u.drawing.text); break; + } } +const CacheDesc outline_cache_desc = { + .hash_func = outline_hash, + .compare_func = outline_compare, + .key_move_func = outline_key_move, + .destruct_func = outline_destruct, + .key_size = sizeof(OutlineHashKey), + .value_size = sizeof(OutlineHashValue) +}; + + +// glyph metric cache +static bool glyph_metrics_key_move(void *dst, void *src, size_t key_size) +{ + if (!dst) + return true; + memcpy(dst, src, key_size); + GlyphMetricsHashKey *k = src; + ass_cache_inc_ref(k->font); + return true; +} + +static void glyph_metrics_destruct(void *key, void *value) +{ + GlyphMetricsHashKey *k = key; + ass_cache_dec_ref(k->font); +} + +const CacheDesc glyph_metrics_cache_desc = { + .hash_func = glyph_metrics_hash, + .compare_func = glyph_metrics_compare, + .key_move_func = glyph_metrics_key_move, + .destruct_func = glyph_metrics_destruct, + .key_size = sizeof(GlyphMetricsHashKey), + .value_size = sizeof(GlyphMetricsHashValue) +}; + // Cache data typedef struct cache_item { - void *key; - void *value; - struct cache_item *next; + Cache *cache; + const CacheDesc *desc; + struct cache_item *next, **prev; + struct cache_item *queue_next, **queue_prev; + size_t size, ref_count; } CacheItem; struct cache { unsigned buckets; CacheItem **map; + CacheItem *queue_first, **queue_last; - HashFunction hash_func; - ItemSize size_func; - HashCompare compare_func; - CacheItemDestructor destruct_func; - size_t key_size; - size_t value_size; + const CacheDesc *desc; size_t cache_size; unsigned hits; @@ -237,47 +328,29 @@ unsigned items; }; -// Hash for a simple (single value or array) type -static unsigned hash_simple(void *key, size_t key_size) -{ - return fnv_32a_buf(key, key_size, FNV1_32A_INIT); -} +#define CACHE_ALIGN 8 +#define CACHE_ITEM_SIZE ((sizeof(CacheItem) + (CACHE_ALIGN - 1)) & ~(CACHE_ALIGN - 1)) -// Comparison of a simple type -static unsigned compare_simple(void *a, void *b, size_t key_size) +static inline size_t align_cache(size_t size) { - return memcmp(a, b, key_size) == 0; + return (size + (CACHE_ALIGN - 1)) & ~(CACHE_ALIGN - 1); } -// Default destructor -static void destruct_simple(void *key, void *value) +static inline CacheItem *value_to_item(void *value) { - free(key); - free(value); + return (CacheItem *) ((char *) value - CACHE_ITEM_SIZE); } // Create a cache with type-specific hash/compare/destruct/size functions -Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, - CacheItemDestructor destruct_func, ItemSize size_func, - size_t key_size, size_t value_size) +Cache *ass_cache_create(const CacheDesc *desc) { Cache *cache = calloc(1, sizeof(*cache)); if (!cache) return NULL; cache->buckets = 0xFFFF; - cache->hash_func = hash_simple; - cache->compare_func = compare_simple; - cache->destruct_func = destruct_simple; - cache->size_func = size_func; - if (hash_func) - cache->hash_func = hash_func; - if (compare_func) - cache->compare_func = compare_func; - if (destruct_func) - cache->destruct_func = destruct_func; - cache->key_size = key_size; - cache->value_size = value_size; + cache->queue_last = &cache->queue_first; + cache->desc = desc; cache->map = calloc(cache->buckets, sizeof(CacheItem *)); if (!cache->map) { free(cache); @@ -287,73 +360,154 @@ return cache; } -void *ass_cache_put(Cache *cache, void *key, void *value) +bool ass_cache_get(Cache *cache, void *key, void *value_ptr) { - unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets; - CacheItem **bucketptr = &cache->map[bucket]; + char **value = (char **) value_ptr; + const CacheDesc *desc = cache->desc; + size_t key_offs = CACHE_ITEM_SIZE + align_cache(desc->value_size); + unsigned bucket = desc->hash_func(key, desc->key_size) % cache->buckets; + CacheItem *item = cache->map[bucket]; + while (item) { + if (desc->compare_func(key, (char *) item + key_offs, desc->key_size)) { + assert(item->size); + if (!item->queue_prev || item->queue_next) { + if (item->queue_prev) { + item->queue_next->queue_prev = item->queue_prev; + *item->queue_prev = item->queue_next; + } else + item->ref_count++; + *cache->queue_last = item; + item->queue_prev = cache->queue_last; + cache->queue_last = &item->queue_next; + item->queue_next = NULL; + } + cache->hits++; + desc->key_move_func(NULL, key, desc->key_size); + *value = (char *) item + CACHE_ITEM_SIZE; + item->ref_count++; + return true; + } + item = item->next; + } + cache->misses++; - CacheItem *item = calloc(1, sizeof(CacheItem)); - if (!item) - return NULL; - item->key = malloc(cache->key_size); - item->value = malloc(cache->value_size); - if (!item->key || !item->value) { - free(item->key); - free(item->value); + item = malloc(key_offs + desc->key_size); + if (!item) { + desc->key_move_func(NULL, key, desc->key_size); + *value = NULL; + return false; + } + item->size = 0; + item->cache = cache; + item->desc = desc; + if (!desc->key_move_func((char *) item + key_offs, key, desc->key_size)) { free(item); - return NULL; + *value = NULL; + return false; } - memcpy(item->key, key, cache->key_size); - memcpy(item->value, value, cache->value_size); + *value = (char *) item + CACHE_ITEM_SIZE; + CacheItem **bucketptr = &cache->map[bucket]; + if (*bucketptr) + (*bucketptr)->prev = &item->next; + item->prev = bucketptr; item->next = *bucketptr; *bucketptr = item; + item->queue_prev = NULL; + item->queue_next = NULL; + item->ref_count = 1; + return false; +} + +void *ass_cache_key(void *value) +{ + CacheItem *item = value_to_item(value); + return (char *) value + align_cache(item->desc->value_size); +} + +void ass_cache_commit(void *value, size_t item_size) +{ + CacheItem *item = value_to_item(value); + assert(!item->size && item_size); + item->size = item_size; + Cache *cache = item->cache; + cache->cache_size += item_size; cache->items++; - if (cache->size_func) - cache->cache_size += cache->size_func(value, cache->value_size); - else - cache->cache_size++; - return item->value; + *cache->queue_last = item; + item->queue_prev = cache->queue_last; + cache->queue_last = &item->queue_next; + item->ref_count++; } -void *ass_cache_get(Cache *cache, void *key) +static inline void destroy_item(const CacheDesc *desc, CacheItem *item) { - unsigned bucket = cache->hash_func(key, cache->key_size) % cache->buckets; - CacheItem *item = cache->map[bucket]; - while (item) { - if (cache->compare_func(key, item->key, cache->key_size)) { - cache->hits++; - return item->value; - } - item = item->next; - } - cache->misses++; - return NULL; + assert(item->desc == desc); + char *value = (char *) item + CACHE_ITEM_SIZE; + desc->destruct_func(value + align_cache(desc->value_size), value); + free(item); } -int ass_cache_empty(Cache *cache, size_t max_size) +void ass_cache_inc_ref(void *value) { - int i; + if (!value) + return; + CacheItem *item = value_to_item(value); + assert(item->size && item->ref_count); + item->ref_count++; +} - if (cache->cache_size < max_size) - return 0; +void ass_cache_dec_ref(void *value) +{ + if (!value) + return; + CacheItem *item = value_to_item(value); + assert(item->size && item->ref_count); + if (--item->ref_count) + return; - for (i = 0; i < cache->buckets; i++) { - CacheItem *item = cache->map[i]; - while (item) { - CacheItem *next = item->next; - cache->destruct_func(item->key, item->value); - free(item); - item = next; - } - cache->map[i] = NULL; + Cache *cache = item->cache; + if (cache) { + if (item->next) + item->next->prev = item->prev; + *item->prev = item->next; + + cache->items--; + cache->cache_size -= item->size; } + destroy_item(item->desc, item); +} - cache->items = cache->hits = cache->misses = cache->cache_size = 0; +void ass_cache_cut(Cache *cache, size_t max_size) +{ + if (cache->cache_size <= max_size) + return; - return 1; + do { + CacheItem *item = cache->queue_first; + if (!item) + break; + assert(item->size); + + cache->queue_first = item->queue_next; + if (--item->ref_count) { + item->queue_prev = NULL; + continue; + } + + if (item->next) + item->next->prev = item->prev; + *item->prev = item->next; + + cache->items--; + cache->cache_size -= item->size; + destroy_item(cache->desc, item); + } while (cache->cache_size > max_size); + if (cache->queue_first) + cache->queue_first->queue_prev = &cache->queue_first; + else + cache->queue_last = &cache->queue_first; } void ass_cache_stats(Cache *cache, size_t *size, unsigned *hits, @@ -369,9 +523,32 @@ *count = cache->items; } +void ass_cache_empty(Cache *cache) +{ + for (int i = 0; i < cache->buckets; i++) { + CacheItem *item = cache->map[i]; + while (item) { + assert(item->size); + CacheItem *next = item->next; + if (item->queue_prev) + item->ref_count--; + if (item->ref_count) + item->cache = NULL; + else + destroy_item(cache->desc, item); + item = next; + } + cache->map[i] = NULL; + } + + cache->queue_first = NULL; + cache->queue_last = &cache->queue_first; + cache->items = cache->hits = cache->misses = cache->cache_size = 0; +} + void ass_cache_done(Cache *cache) { - ass_cache_empty(cache, 0); + ass_cache_empty(cache); free(cache->map); free(cache); } @@ -379,32 +556,25 @@ // Type-specific creation function Cache *ass_font_cache_create(void) { - return ass_cache_create(font_hash, font_compare, font_destruct, - (ItemSize)NULL, sizeof(ASS_FontDesc), sizeof(ASS_Font)); + return ass_cache_create(&font_cache_desc); } Cache *ass_outline_cache_create(void) { - return ass_cache_create(outline_hash, outline_compare, outline_destruct, - NULL, sizeof(OutlineHashKey), sizeof(OutlineHashValue)); + return ass_cache_create(&outline_cache_desc); } Cache *ass_glyph_metrics_cache_create(void) { - return ass_cache_create(glyph_metrics_hash, glyph_metrics_compare, NULL, - (ItemSize) NULL, sizeof(GlyphMetricsHashKey), - sizeof(GlyphMetricsHashValue)); + return ass_cache_create(&glyph_metrics_cache_desc); } Cache *ass_bitmap_cache_create(void) { - return ass_cache_create(bitmap_hash, bitmap_compare, bitmap_destruct, - bitmap_size, sizeof(BitmapHashKey), sizeof(BitmapHashValue)); + return ass_cache_create(&bitmap_cache_desc); } Cache *ass_composite_cache_create(void) { - return ass_cache_create(composite_hash, composite_compare, - composite_destruct, composite_size, sizeof(CompositeHashKey), - sizeof(CompositeHashValue)); + return ass_cache_create(&composite_cache_desc); } diff -Nru libass-0.13.2/libass/ass_cache.h libass-0.13.4/libass/ass_cache.h --- libass-0.13.2/libass/ass_cache.h 2015-07-29 20:15:19.000000000 +0000 +++ libass-0.13.4/libass/ass_cache.h 2016-07-11 21:29:00.000000000 +0000 @@ -57,8 +57,8 @@ // Type-specific function pointers typedef unsigned(*HashFunction)(void *key, size_t key_size); -typedef size_t(*ItemSize)(void *value, size_t value_size); typedef unsigned(*HashCompare)(void *a, void *b, size_t key_size); +typedef bool(*CacheKeyMove)(void *dst, void *src, size_t key_size); typedef void(*CacheItemDestructor)(void *key, void *value); // cache hash keys @@ -103,14 +103,26 @@ BitmapRef *bitmaps; } CompositeHashKey; -Cache *ass_cache_create(HashFunction hash_func, HashCompare compare_func, - CacheItemDestructor destruct_func, ItemSize size_func, - size_t key_size, size_t value_size); -void *ass_cache_put(Cache *cache, void *key, void *value); -void *ass_cache_get(Cache *cache, void *key); -int ass_cache_empty(Cache *cache, size_t max_size); +typedef struct +{ + HashFunction hash_func; + HashCompare compare_func; + CacheKeyMove key_move_func; + CacheItemDestructor destruct_func; + size_t key_size; + size_t value_size; +} CacheDesc; + +Cache *ass_cache_create(const CacheDesc *desc); +bool ass_cache_get(Cache *cache, void *key, void *value_ptr); +void *ass_cache_key(void *value); +void ass_cache_commit(void *value, size_t item_size); +void ass_cache_inc_ref(void *value); +void ass_cache_dec_ref(void *value); +void ass_cache_cut(Cache *cache, size_t max_size); void ass_cache_stats(Cache *cache, size_t *size, unsigned *hits, unsigned *misses, unsigned *count); +void ass_cache_empty(Cache *cache); void ass_cache_done(Cache *cache); Cache *ass_font_cache_create(void); Cache *ass_outline_cache_create(void); diff -Nru libass-0.13.2/libass/ass_directwrite.c libass-0.13.4/libass/ass_directwrite.c --- libass-0.13.2/libass/ass_directwrite.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_directwrite.c 2016-07-11 21:29:00.000000000 +0000 @@ -693,7 +693,11 @@ add_font(font, fontFamily, provider); } + + IDWriteFontFamily_Release(fontFamily); } + + IDWriteFontCollection_Release(fontCollection); } static void get_substitutions(void *priv, const char *name, diff -Nru libass-0.13.2/libass/ass_font.c libass-0.13.4/libass/ass_font.c --- libass-0.13.2/libass/ass_font.c 2016-02-20 18:20:05.000000000 +0000 +++ libass-0.13.4/libass/ass_font.c 2016-07-11 21:29:00.000000000 +0000 @@ -84,6 +84,9 @@ uint32_t ass_font_index_magic(FT_Face face, uint32_t symbol) { + if (!face->charmap) + return symbol; + switch(face->charmap->encoding){ case FT_ENCODING_MS_SYMBOL: return 0xF000 | symbol; @@ -225,33 +228,39 @@ FT_Library ftlibrary, ASS_FontSelector *fontsel, ASS_FontDesc *desc) { - int error; - ASS_Font *fontp; - ASS_Font font; + ASS_Font *font; + if (ass_cache_get(font_cache, desc, &font)) { + if (font->desc.family) + return font; + ass_cache_dec_ref(font); + return NULL; + } + if (!font) + return NULL; - fontp = ass_cache_get(font_cache, desc); - if (fontp) - return fontp; - - font.library = library; - font.ftlibrary = ftlibrary; - font.shaper_priv = NULL; - font.n_faces = 0; - font.desc.family = strdup(desc->family); - font.desc.bold = desc->bold; - font.desc.italic = desc->italic; - font.desc.vertical = desc->vertical; - - font.scale_x = font.scale_y = 1.; - font.v.x = font.v.y = 0; - font.size = 0.; + font->library = library; + font->ftlibrary = ftlibrary; + font->shaper_priv = NULL; + font->n_faces = 0; + ASS_FontDesc *new_desc = ass_cache_key(font); + font->desc.family = new_desc->family; + font->desc.bold = desc->bold; + font->desc.italic = desc->italic; + font->desc.vertical = desc->vertical; + + font->scale_x = font->scale_y = 1.; + font->v.x = font->v.y = 0; + font->size = 0.; - error = add_face(fontsel, &font, 0); + int error = add_face(fontsel, font, 0); if (error == -1) { - free(font.desc.family); - return 0; - } else - return ass_cache_put(font_cache, &font.desc, &font); + font->desc.family = NULL; + ass_cache_commit(font, 1); + ass_cache_dec_ref(font); + return NULL; + } + ass_cache_commit(font, 1); + return font; } /** @@ -671,9 +680,9 @@ } /** - * \brief Deallocate ASS_Font + * \brief Deallocate ASS_Font internals **/ -void ass_font_free(ASS_Font *font) +void ass_font_clear(ASS_Font *font) { int i; if (font->shaper_priv) @@ -683,7 +692,6 @@ FT_Done_Face(font->faces[i]); } free(font->desc.family); - free(font); } /** diff -Nru libass-0.13.2/libass/ass_font.h libass-0.13.4/libass/ass_font.h --- libass-0.13.2/libass/ass_font.h 2016-02-20 18:20:05.000000000 +0000 +++ libass-0.13.4/libass/ass_font.h 2016-07-11 21:29:00.000000000 +0000 @@ -74,7 +74,7 @@ FT_Glyph ass_font_get_glyph(ASS_Font *font, uint32_t ch, int face_index, int index, ASS_Hinting hinting, int deco); -void ass_font_free(ASS_Font *font); +void ass_font_clear(ASS_Font *font); void outline_translate(const ASS_Outline *outline, FT_Pos dx, FT_Pos dy); void outline_transform(const ASS_Outline *outline, const FT_Matrix *matrix); diff -Nru libass-0.13.2/libass/ass_fontselect.c libass-0.13.4/libass/ass_fontselect.c --- libass-0.13.2/libass/ass_fontselect.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_fontselect.c 2016-07-11 21:29:00.000000000 +0000 @@ -175,7 +175,7 @@ char fullname[4096]; snprintf(fullname, sizeof(fullname), "%s/%s", dir, entry->d_name); size_t bufsize = 0; - ass_msg(library, MSGL_WARN, "Loading font file '%s'", fullname); + ass_msg(library, MSGL_INFO, "Loading font file '%s'", fullname); void *data = read_file(library, fullname, &bufsize); if (data) { ass_add_font(library, entry->d_name, data, bufsize); diff -Nru libass-0.13.2/libass/ass.h libass-0.13.4/libass/ass.h --- libass-0.13.2/libass/ass.h 2016-02-20 19:36:25.000000000 +0000 +++ libass-0.13.4/libass/ass.h 2016-10-04 23:08:24.000000000 +0000 @@ -24,7 +24,7 @@ #include #include "ass_types.h" -#define LIBASS_VERSION 0x01302000 +#define LIBASS_VERSION 0x01304000 #ifdef __cplusplus extern "C" { diff -Nru libass-0.13.2/libass/ass_parse.c libass-0.13.4/libass/ass_parse.c --- libass-0.13.2/libass/ass_parse.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_parse.c 2016-07-11 21:29:00.000000000 +0000 @@ -127,11 +127,11 @@ val = 0; // normal desc.italic = val; + ass_cache_dec_ref(render_priv->state.font); render_priv->state.font = ass_font_new(render_priv->cache.font_cache, render_priv->library, render_priv->ftlibrary, render_priv->fontselect, &desc); - free(desc.family); if (render_priv->state.font) change_font_size(render_priv, render_priv->state.font_size); diff -Nru libass-0.13.2/libass/ass_rasterizer.c libass-0.13.4/libass/ass_rasterizer.c --- libass-0.13.2/libass/ass_rasterizer.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_rasterizer.c 2016-07-11 21:29:00.000000000 +0000 @@ -272,6 +272,11 @@ if (j > last) return 0; + if (path->points[j].x < -(1 << 28) || path->points[j].x >= (1 << 28)) + return 0; + if (path->points[j].y <= -(1 << 28) || path->points[j].y > (1 << 28)) + return 0; + switch (FT_CURVE_TAG(path->tags[j])) { case FT_CURVE_TAG_ON: p[0].x = path->points[j].x; @@ -309,7 +314,12 @@ return 0; } - for (j++; j <= last; ++j) + for (j++; j <= last; j++) { + if (path->points[j].x < -(1 << 28) || path->points[j].x >= (1 << 28)) + return 0; + if (path->points[j].y <= -(1 << 28) || path->points[j].y > (1 << 28)) + return 0; + switch (FT_CURVE_TAG(path->tags[j])) { case FT_CURVE_TAG_ON: switch (st) { @@ -390,6 +400,7 @@ default: return 0; } + } if (process_end) switch (st) { diff -Nru libass-0.13.2/libass/ass_render_api.c libass-0.13.4/libass/ass_render_api.c --- libass-0.13.2/libass/ass_render_api.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_render_api.c 2016-07-11 21:29:00.000000000 +0000 @@ -27,11 +27,11 @@ ASS_Settings *settings = &priv->settings; priv->render_id++; - ass_cache_empty(priv->cache.outline_cache, 0); - ass_cache_empty(priv->cache.bitmap_cache, 0); - ass_cache_empty(priv->cache.composite_cache, 0); - ass_free_images(priv->prev_images_root); - priv->prev_images_root = 0; + ass_frame_unref(priv->images_root); + ass_cache_empty(priv->cache.composite_cache); + ass_cache_empty(priv->cache.bitmap_cache); + ass_cache_empty(priv->cache.outline_cache); + priv->images_root = NULL; priv->width = settings->frame_width; priv->height = settings->frame_height; diff -Nru libass-0.13.2/libass/ass_render.c libass-0.13.4/libass/ass_render.c --- libass-0.13.2/libass/ass_render.c 2016-02-20 18:19:55.000000000 +0000 +++ libass-0.13.4/libass/ass_render.c 2016-10-04 22:39:06.000000000 +0000 @@ -114,29 +114,16 @@ return priv; } -static void free_list_clear(ASS_Renderer *render_priv) -{ - if (render_priv->free_head) { - FreeList *item = render_priv->free_head; - while(item) { - FreeList *oi = item; - ass_aligned_free(item->object); - item = item->next; - free(oi); - } - render_priv->free_head = NULL; - } -} - void ass_renderer_done(ASS_Renderer *render_priv) { - ass_cache_done(render_priv->cache.font_cache); - ass_cache_done(render_priv->cache.bitmap_cache); + ass_frame_unref(render_priv->images_root); + ass_frame_unref(render_priv->prev_images_root); + ass_cache_done(render_priv->cache.composite_cache); + ass_cache_done(render_priv->cache.bitmap_cache); ass_cache_done(render_priv->cache.outline_cache); - - ass_free_images(render_priv->images_root); - ass_free_images(render_priv->prev_images_root); + ass_shaper_free(render_priv->shaper); + ass_cache_done(render_priv->cache.font_cache); #if CONFIG_RASTERIZER rasterizer_done(&render_priv->rasterizer); @@ -148,7 +135,6 @@ } if (render_priv->fontselect) ass_fontselect_free(render_priv->fontselect); - ass_shaper_free(render_priv->shaper); if (render_priv->ftlibrary) FT_Done_FreeType(render_priv->ftlibrary); free(render_priv->eimg); @@ -162,7 +148,6 @@ free(render_priv->user_override_style.FontName); - free_list_clear(render_priv); free(render_priv); } @@ -172,21 +157,29 @@ */ static ASS_Image *my_draw_bitmap(unsigned char *bitmap, int bitmap_w, int bitmap_h, int stride, int dst_x, - int dst_y, uint32_t color) + int dst_y, uint32_t color, + CompositeHashValue *source) { - ASS_Image *img = malloc(sizeof(ASS_Image)); - - if (img) { - img->w = bitmap_w; - img->h = bitmap_h; - img->stride = stride; - img->bitmap = bitmap; - img->color = color; - img->dst_x = dst_x; - img->dst_y = dst_y; - } + ASS_ImagePriv *img = malloc(sizeof(ASS_ImagePriv)); + if (!img) { + if (!source) + ass_aligned_free(bitmap); + return NULL; + } + + img->result.w = bitmap_w; + img->result.h = bitmap_h; + img->result.stride = stride; + img->result.bitmap = bitmap; + img->result.color = color; + img->result.dst_x = dst_x; + img->result.dst_y = dst_y; + + img->source = source; + ass_cache_inc_ref(source); + img->ref_count = 0; - return img; + return &img->result; } /** @@ -280,7 +273,8 @@ static ASS_Image **render_glyph_i(ASS_Renderer *render_priv, Bitmap *bm, int dst_x, int dst_y, uint32_t color, uint32_t color2, int brk, - ASS_Image **tail, unsigned int type) + ASS_Image **tail, unsigned type, + CompositeHashValue *source) { int i, j, x0, y0, x1, y1, cx0, cy0, cx1, cy1, sx, sy, zx, zy; Rect r[4]; @@ -345,8 +339,8 @@ if (lbrk > r[j].x0) { if (lbrk > r[j].x1) lbrk = r[j].x1; img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->stride + r[j].x0, - lbrk - r[j].x0, r[j].y1 - r[j].y0, - bm->stride, dst_x + r[j].x0, dst_y + r[j].y0, color); + lbrk - r[j].x0, r[j].y1 - r[j].y0, bm->stride, + dst_x + r[j].x0, dst_y + r[j].y0, color, source); if (!img) break; img->type = type; *tail = img; @@ -355,8 +349,8 @@ if (lbrk < r[j].x1) { if (lbrk < r[j].x0) lbrk = r[j].x0; img = my_draw_bitmap(bm->buffer + r[j].y0 * bm->stride + lbrk, - r[j].x1 - lbrk, r[j].y1 - r[j].y0, - bm->stride, dst_x + lbrk, dst_y + r[j].y0, color2); + r[j].x1 - lbrk, r[j].y1 - r[j].y0, bm->stride, + dst_x + lbrk, dst_y + r[j].y0, color2, source); if (!img) break; img->type = type; *tail = img; @@ -381,12 +375,13 @@ */ static ASS_Image ** render_glyph(ASS_Renderer *render_priv, Bitmap *bm, int dst_x, int dst_y, - uint32_t color, uint32_t color2, int brk, ASS_Image **tail, unsigned int type) + uint32_t color, uint32_t color2, int brk, ASS_Image **tail, + unsigned type, CompositeHashValue *source) { // Inverse clipping in use? if (render_priv->state.clip_mode) return render_glyph_i(render_priv, bm, dst_x, dst_y, color, color2, - brk, tail, type); + brk, tail, type, source); // brk is relative to dst_x // color = color left of brk @@ -439,7 +434,7 @@ brk = b_x1; img = my_draw_bitmap(bm->buffer + bm->stride * b_y0 + b_x0, brk - b_x0, b_y1 - b_y0, bm->stride, - dst_x + b_x0, dst_y + b_y0, color); + dst_x + b_x0, dst_y + b_y0, color, source); if (!img) return tail; img->type = type; *tail = img; @@ -450,7 +445,7 @@ brk = b_x0; img = my_draw_bitmap(bm->buffer + bm->stride * b_y0 + brk, b_x1 - brk, b_y1 - b_y0, bm->stride, - dst_x + brk, dst_y + b_y0, color2); + dst_x + brk, dst_y + b_y0, color2, source); if (!img) return tail; img->type = type; *tail = img; @@ -459,24 +454,10 @@ return tail; } -// Return true if the object could be added, and the object is not NULL. -static bool free_list_add(ASS_Renderer *render_priv, void *object) +// Calculate bitmap memory footprint +static inline size_t bitmap_size(Bitmap *bm) { - if (!object) - return false; - FreeList *l = calloc(1, sizeof(FreeList)); - if (!l) - return false; - if (!render_priv->free_head) { - render_priv->free_head = l; - render_priv->free_head->object = object; - render_priv->free_tail = render_priv->free_head; - } else { - l->object = object; - render_priv->free_tail->next = l; - render_priv->free_tail = render_priv->free_tail->next; - } - return true; + return bm ? sizeof(Bitmap) + bm->stride * bm->h : 0; } /** @@ -487,31 +468,29 @@ static void blend_vector_clip(ASS_Renderer *render_priv, ASS_Image *head) { - Bitmap *clip_bm = NULL; - ASS_Image *cur; ASS_Drawing *drawing = render_priv->state.clip_drawing; - BitmapHashKey key; - BitmapHashValue *val; - if (!drawing) return; // Try to get mask from cache + BitmapHashKey key; memset(&key, 0, sizeof(key)); key.type = BITMAP_CLIP; key.u.clip.text = drawing->text; - val = ass_cache_get(render_priv->cache.bitmap_cache, &key); - if (val) { - clip_bm = val->bm; - } else { - BitmapHashValue v; + BitmapHashValue *val; + if (!ass_cache_get(render_priv->cache.bitmap_cache, &key, &val)) { + if (!val) + return; + val->bm = val->bm_o = NULL; // Not found in cache, parse and rasterize it ASS_Outline *outline = ass_drawing_parse(drawing, 1); if (!outline) { ass_msg(render_priv->library, MSGL_WARN, "Clip vector parsing failed. Skipping."); + ass_cache_commit(val, sizeof(BitmapHashKey) + sizeof(BitmapHashValue)); + ass_cache_dec_ref(val); return; } @@ -525,19 +504,19 @@ outline_translate(outline, trans.x, trans.y); } - clip_bm = outline_to_bitmap(render_priv, outline, 0); - - // Add to cache - memset(&v, 0, sizeof(v)); - key.u.clip.text = strdup(drawing->text); - v.bm = clip_bm; - ass_cache_put(render_priv->cache.bitmap_cache, &key, &v); + val->bm = outline_to_bitmap(render_priv, outline, 0); + ass_cache_commit(val, bitmap_size(val->bm) + + sizeof(BitmapHashKey) + sizeof(BitmapHashValue)); } - if (!clip_bm) return; + Bitmap *clip_bm = val->bm; + if (!clip_bm) { + ass_cache_dec_ref(val); + return; + } // Iterate through bitmaps and blend/clip them - for (cur = head; cur; cur = cur->next) { + for (ASS_Image *cur = head; cur; cur = cur->next) { int left, top, right, bottom, w, h; int ax, ay, aw, ah, as; int bx, by, bw, bh, bs; @@ -579,11 +558,9 @@ } // Allocate new buffer and add to free list - nbuffer = ass_aligned_alloc(32, as * ah); - if (!free_list_add(render_priv, nbuffer)) { - ass_aligned_free(nbuffer); - return; - } + nbuffer = ass_aligned_alloc(32, as * ah, false); + if (!nbuffer) + break; // Blend together memcpy(nbuffer, abuffer, ((ah - 1) * as) + aw); @@ -601,11 +578,9 @@ // Allocate new buffer and add to free list unsigned align = (w >= 16) ? 16 : ((w >= 8) ? 8 : 1); unsigned ns = ass_align(align, w); - nbuffer = ass_aligned_alloc(align, ns * h); - if (!free_list_add(render_priv, nbuffer)) { - ass_aligned_free(nbuffer); - return; - } + nbuffer = ass_aligned_alloc(align, ns * h, false); + if (!nbuffer) + break; // Blend together render_priv->engine->mul_bitmaps(nbuffer, ns, @@ -618,8 +593,14 @@ cur->h = h; cur->stride = ns; } + cur->bitmap = nbuffer; + ASS_ImagePriv *priv = (ASS_ImagePriv *) cur; + ass_cache_dec_ref(priv->source); + priv->source = NULL; } + + ass_cache_dec_ref(val); } /** @@ -630,20 +611,21 @@ { ASS_Image *head; ASS_Image **tail = &head; - TextInfo *text_info = &render_priv->text_info; + unsigned n_bitmaps = render_priv->text_info.n_bitmaps; + CombinedBitmapInfo *bitmaps = render_priv->text_info.combined_bitmaps; - for (int i = 0; i < text_info->n_bitmaps; ++i) { - CombinedBitmapInfo *info = &text_info->combined_bitmaps[i]; + for (unsigned i = 0; i < n_bitmaps; i++) { + CombinedBitmapInfo *info = &bitmaps[i]; if (!info->bm_s || render_priv->state.border_style == 4) continue; tail = render_glyph(render_priv, info->bm_s, info->x, info->y, info->c[3], 0, - 1000000, tail, IMAGE_TYPE_SHADOW); + 1000000, tail, IMAGE_TYPE_SHADOW, info->image); } - for (int i = 0; i < text_info->n_bitmaps; ++i) { - CombinedBitmapInfo *info = &text_info->combined_bitmaps[i]; + for (unsigned i = 0; i < n_bitmaps; i++) { + CombinedBitmapInfo *info = &bitmaps[i]; if (!info->bm_o) continue; @@ -653,12 +635,12 @@ } else { tail = render_glyph(render_priv, info->bm_o, info->x, info->y, info->c[2], - 0, 1000000, tail, IMAGE_TYPE_OUTLINE); + 0, 1000000, tail, IMAGE_TYPE_OUTLINE, info->image); } } - for (int i = 0; i < text_info->n_bitmaps; ++i) { - CombinedBitmapInfo *info = &text_info->combined_bitmaps[i]; + for (unsigned i = 0; i < n_bitmaps; i++) { + CombinedBitmapInfo *info = &bitmaps[i]; if (!info->bm) continue; @@ -667,21 +649,27 @@ if (info->effect_timing > info->first_pos_x) tail = render_glyph(render_priv, info->bm, info->x, info->y, - info->c[0], 0, 1000000, tail, IMAGE_TYPE_CHARACTER); + info->c[0], 0, 1000000, tail, + IMAGE_TYPE_CHARACTER, info->image); else tail = render_glyph(render_priv, info->bm, info->x, info->y, - info->c[1], 0, 1000000, tail, IMAGE_TYPE_CHARACTER); + info->c[1], 0, 1000000, tail, + IMAGE_TYPE_CHARACTER, info->image); } else if (info->effect_type == EF_KARAOKE_KF) { tail = render_glyph(render_priv, info->bm, info->x, info->y, info->c[0], - info->c[1], info->effect_timing, tail, IMAGE_TYPE_CHARACTER); + info->c[1], info->effect_timing, tail, + IMAGE_TYPE_CHARACTER, info->image); } else tail = render_glyph(render_priv, info->bm, info->x, info->y, info->c[0], - 0, 1000000, tail, IMAGE_TYPE_CHARACTER); + 0, 1000000, tail, IMAGE_TYPE_CHARACTER, info->image); } + for (unsigned i = 0; i < n_bitmaps; i++) + ass_cache_dec_ref(bitmaps[i].image); + *tail = 0; blend_vector_clip(render_priv, head); @@ -921,9 +909,11 @@ static void free_render_context(ASS_Renderer *render_priv) { + ass_cache_dec_ref(render_priv->state.font); free(render_priv->state.family); ass_drawing_free(render_priv->state.clip_drawing); + render_priv->state.font = NULL; render_priv->state.family = NULL; render_priv->state.clip_drawing = NULL; @@ -1153,29 +1143,29 @@ static void get_outline_glyph(ASS_Renderer *priv, GlyphInfo *info) { - OutlineHashValue *val; - OutlineHashKey key; - memset(&info->hash_key, 0, sizeof(info->hash_key)); + OutlineHashKey key; + OutlineHashValue *val; fill_glyph_hash(priv, &key, info); - val = ass_cache_get(priv->cache.outline_cache, &key); - - if (!val) { - OutlineHashValue v; - memset(&v, 0, sizeof(v)); + if (!ass_cache_get(priv->cache.outline_cache, &key, &val)) { + if (!val) + return; + memset(val, 0, sizeof(*val)); if (info->drawing) { ASS_Drawing *drawing = info->drawing; ass_drawing_hash(drawing); - if(!ass_drawing_parse(drawing, 0)) + if(!ass_drawing_parse(drawing, 0)) { + ass_cache_commit(val, 1); + ass_cache_dec_ref(val); return; - v.outline = outline_copy(&drawing->outline); - v.advance.x = drawing->advance.x; - v.advance.y = drawing->advance.y; - v.asc = drawing->asc; - v.desc = drawing->desc; - key.u.drawing.text = strdup(drawing->text); + } + val->outline = outline_copy(&drawing->outline); + val->advance.x = drawing->advance.x; + val->advance.y = drawing->advance.y; + val->asc = drawing->asc; + val->desc = drawing->desc; } else { ass_face_set_size(info->font->faces[info->face_index], info->font_size); @@ -1186,35 +1176,45 @@ info->symbol, info->face_index, info->glyph_index, priv->settings.hinting, info->flags); if (glyph != NULL) { - v.outline = outline_convert(&((FT_OutlineGlyph)glyph)->outline); + val->outline = outline_convert(&((FT_OutlineGlyph) glyph)->outline); if (priv->settings.shaper == ASS_SHAPING_SIMPLE) { - v.advance.x = d16_to_d6(glyph->advance.x); - v.advance.y = d16_to_d6(glyph->advance.y); + val->advance.x = d16_to_d6(glyph->advance.x); + val->advance.y = d16_to_d6(glyph->advance.y); } FT_Done_Glyph(glyph); ass_font_get_asc_desc(info->font, info->symbol, - &v.asc, &v.desc); - v.asc *= info->scale_y; - v.desc *= info->scale_y; + &val->asc, &val->desc); + val->asc *= info->scale_y; + val->desc *= info->scale_y; } } - if (!v.outline) + if (!val->outline) { + ass_cache_commit(val, 1); + ass_cache_dec_ref(val); return; + } - outline_get_cbox(v.outline, &v.bbox_scaled); + outline_get_cbox(val->outline, &val->bbox_scaled); if (info->border_style == 3) { - FT_Vector advance; - - v.border = calloc(1, sizeof(ASS_Outline)); + val->border = calloc(1, sizeof(ASS_Outline)); + if (!val->border) { + outline_free(val->outline); + free(val->outline); + val->outline = NULL; + ass_cache_commit(val, 1); + ass_cache_dec_ref(val); + return; + } + FT_Vector advance; if (priv->settings.shaper == ASS_SHAPING_SIMPLE || info->drawing) - advance = v.advance; + advance = val->advance; else advance = info->advance; - draw_opaque_box(priv, info, v.asc, v.desc, v.border, advance, + draw_opaque_box(priv, info, val->asc, val->desc, val->border, advance, double_to_d6(info->border_x * priv->border_scale), double_to_d6(info->border_y * priv->border_scale)); @@ -1222,13 +1222,18 @@ && double_to_d6(info->scale_x) && double_to_d6(info->scale_y)) { change_border(priv, info->border_x, info->border_y); - v.border = outline_copy(v.outline); - stroke_outline(priv, v.border, + val->border = outline_copy(val->outline); + stroke_outline(priv, val->border, double_to_d6(info->border_x * priv->border_scale), double_to_d6(info->border_y * priv->border_scale)); } - val = ass_cache_put(priv->cache.outline_cache, &key, &v); + ass_cache_commit(val, 1); + } + + if (!val->outline) { + ass_cache_dec_ref(val); + return; } info->hash_key.u.outline.outline = val; @@ -1329,70 +1334,63 @@ static void get_bitmap_glyph(ASS_Renderer *render_priv, GlyphInfo *info) { - BitmapHashValue *val; - OutlineBitmapHashKey *key = &info->hash_key.u.outline; - if (!info->outline || info->symbol == '\n' || info->symbol == 0 || info->skip) return; - val = ass_cache_get(render_priv->cache.bitmap_cache, &info->hash_key); - - if (!val) { - FT_Vector shift; - BitmapHashValue hash_val; - int error; - double fax_scaled, fay_scaled; - double scale_x = render_priv->font_scale_x; - - hash_val.bm = hash_val.bm_o = NULL; - - ASS_Outline *outline = outline_copy(info->outline); - ASS_Outline *border = outline_copy(info->border); - - // calculating rotation shift vector (from rotation origin to the glyph basepoint) - shift.x = key->shift_x; - shift.y = key->shift_y; - fax_scaled = info->fax / info->scale_y * info->scale_x; - fay_scaled = info->fay / info->scale_x * info->scale_y; - - // apply rotation - // use blur_scale because, like blurs, VSFilter forgets to scale this - transform_3d(shift, outline, border, - info->frx, info->fry, info->frz, fax_scaled, - fay_scaled, render_priv->blur_scale, info->asc); - - // PAR correction scaling - FT_Matrix m = { double_to_d16(scale_x), 0, - 0, double_to_d16(1.0) }; - - // subpixel shift - if (outline) { - if (scale_x != 1.0) - outline_transform(outline, &m); - outline_translate(outline, key->advance.x, -key->advance.y); - } - if (border) { - if (scale_x != 1.0) - outline_transform(border, &m); - outline_translate(border, key->advance.x, -key->advance.y); - } - - // render glyph - error = outline_to_bitmap2(render_priv, outline, border, - &hash_val.bm, &hash_val.bm_o); - if (error) - info->symbol = 0; + BitmapHashValue *val; + OutlineBitmapHashKey *key = &info->hash_key.u.outline; + if (ass_cache_get(render_priv->cache.bitmap_cache, &info->hash_key, &val)) { + info->image = val; + return; + } + if (!val) + return; - val = ass_cache_put(render_priv->cache.bitmap_cache, &info->hash_key, - &hash_val); + ASS_Outline *outline = outline_copy(info->outline); + ASS_Outline *border = outline_copy(info->border); - outline_free(outline); - free(outline); - outline_free(border); - free(border); - } + // calculating rotation shift vector (from rotation origin to the glyph basepoint) + FT_Vector shift = { key->shift_x, key->shift_y }; + double scale_x = render_priv->font_scale_x; + double fax_scaled = info->fax / info->scale_y * info->scale_x; + double fay_scaled = info->fay / info->scale_x * info->scale_y; + + // apply rotation + // use blur_scale because, like blurs, VSFilter forgets to scale this + transform_3d(shift, outline, border, + info->frx, info->fry, info->frz, fax_scaled, + fay_scaled, render_priv->blur_scale, info->asc); + + // PAR correction scaling + FT_Matrix m = { double_to_d16(scale_x), 0, + 0, double_to_d16(1.0) }; + + // subpixel shift + if (outline) { + if (scale_x != 1.0) + outline_transform(outline, &m); + outline_translate(outline, key->advance.x, -key->advance.y); + } + if (border) { + if (scale_x != 1.0) + outline_transform(border, &m); + outline_translate(border, key->advance.x, -key->advance.y); + } + + // render glyph + int error = outline_to_bitmap2(render_priv, outline, border, + &val->bm, &val->bm_o); + if (error) + info->symbol = 0; + ass_cache_commit(val, bitmap_size(val->bm) + bitmap_size(val->bm_o) + + sizeof(BitmapHashKey) + sizeof(BitmapHashValue)); info->image = val; + + outline_free(outline); + free(outline); + outline_free(border); + free(border); } /** @@ -1520,7 +1518,6 @@ double pen_shift_x; double pen_shift_y; int cur_line; - int run_offset; TextInfo *text_info = &render_priv->text_info; last_space = -1; @@ -1610,7 +1607,10 @@ (w->bbox.xMin + w->pos.x)); if (DIFF(l1_new, l2_new) < DIFF(l1, l2)) { - w->linebreak = 1; + if (w->linebreak || w == text_info->glyphs) + text_info->n_lines--; + if (w != text_info->glyphs) + w->linebreak = 1; s2->linebreak = 0; exit = 0; } @@ -1628,7 +1628,6 @@ trim_whitespace(render_priv); cur_line = 1; - run_offset = 0; i = 0; cur = text_info->glyphs + i; @@ -1649,7 +1648,6 @@ text_info->lines[cur_line - 1].offset; text_info->lines[cur_line].offset = i; cur_line++; - run_offset++; pen_shift_x = d6_to_double(-cur->pos.x); pen_shift_y += height + render_priv->settings.line_spacing; } @@ -1900,6 +1898,8 @@ // Fill glyph information info->symbol = code; info->font = render_priv->state.font; + if (!info->drawing) + ass_cache_inc_ref(info->font); for (i = 0; i < 4; ++i) { uint32_t clr = render_priv->state.c[i]; // VSFilter compatibility: apply fade only when it's positive @@ -2163,10 +2163,14 @@ CombinedBitmapInfo *combined_info = text_info->combined_bitmaps; CombinedBitmapInfo *current_info = NULL; GlyphInfo *last_info = NULL; - for (int i = 0; i < text_info->length; ++i) { + for (int i = 0; i < text_info->length; i++) { GlyphInfo *info = text_info->glyphs + i; if (info->linebreak) linebreak = 1; - if (info->skip) continue; + if (info->skip) { + for (; info; info = info->next) + ass_cache_dec_ref(info->hash_key.u.outline.outline); + continue; + } for (; info; info = info->next) { OutlineBitmapHashKey *key = &info->hash_key.u.outline; @@ -2182,8 +2186,10 @@ last_info = NULL; if (nb_bitmaps >= text_info->max_bitmaps) { size_t new_size = 2 * text_info->max_bitmaps; - if (!ASS_REALLOC_ARRAY(text_info->combined_bitmaps, new_size)) + if (!ASS_REALLOC_ARRAY(text_info->combined_bitmaps, new_size)) { + ass_cache_dec_ref(info->image); continue; + } text_info->max_bitmaps = new_size; combined_info = text_info->combined_bitmaps; } @@ -2214,69 +2220,76 @@ current_info->x = current_info->y = INT_MAX; rectangle_reset(¤t_info->rect); rectangle_reset(¤t_info->rect_o); - current_info->bm = current_info->bm_o = current_info->bm_s = NULL; current_info->n_bm = current_info->n_bm_o = 0; + current_info->bm = current_info->bm_o = current_info->bm_s = NULL; + current_info->image = NULL; current_info->bitmap_count = current_info->max_bitmap_count = 0; current_info->bitmaps = malloc(MAX_SUB_BITMAPS_INITIAL * sizeof(BitmapRef)); - if (!current_info->bitmaps) + if (!current_info->bitmaps) { + ass_cache_dec_ref(info->image); continue; + } current_info->max_bitmap_count = MAX_SUB_BITMAPS_INITIAL; - ++nb_bitmaps; + nb_bitmaps++; } last_info = info; - if (!info->image || !current_info) + if (!info->image || !current_info) { + ass_cache_dec_ref(info->image); continue; + } if (current_info->bitmap_count >= current_info->max_bitmap_count) { size_t new_size = 2 * current_info->max_bitmap_count; - if (!ASS_REALLOC_ARRAY(current_info->bitmaps, new_size)) + if (!ASS_REALLOC_ARRAY(current_info->bitmaps, new_size)) { + ass_cache_dec_ref(info->image); continue; + } current_info->max_bitmap_count = new_size; } current_info->bitmaps[current_info->bitmap_count].image = info->image; current_info->bitmaps[current_info->bitmap_count].x = x; current_info->bitmaps[current_info->bitmap_count].y = y; - ++current_info->bitmap_count; + current_info->bitmap_count++; current_info->x = FFMIN(current_info->x, x); current_info->y = FFMIN(current_info->y, y); if (info->image->bm) { rectangle_combine(¤t_info->rect, info->image->bm, x, y); - ++current_info->n_bm; + current_info->n_bm++; } if (info->image->bm_o) { rectangle_combine(¤t_info->rect_o, info->image->bm_o, x, y); - ++current_info->n_bm_o; + current_info->n_bm_o++; } } } - CompositeHashKey hk; - CompositeHashValue *hv; - for (int i = 0; i < nb_bitmaps; ++i) { + for (int i = 0; i < nb_bitmaps; i++) { CombinedBitmapInfo *info = &combined_info[i]; - for (int j = 0; j < info->bitmap_count; ++j) { + for (int j = 0; j < info->bitmap_count; j++) { info->bitmaps[j].x -= info->x; info->bitmaps[j].y -= info->y; } + CompositeHashKey hk; + CompositeHashValue *hv; fill_composite_hash(&hk, info); - - hv = ass_cache_get(render_priv->cache.composite_cache, &hk); - if (hv) { + if (ass_cache_get(render_priv->cache.composite_cache, &hk, &hv)) { info->bm = hv->bm; info->bm_o = hv->bm_o; info->bm_s = hv->bm_s; - free(info->bitmaps); + info->image = hv; continue; } + if (!hv) + continue; int bord = be_padding(info->filter.be); if (!bord && info->n_bm == 1) { - for (int j = 0; j < info->bitmap_count; ++j) { + for (int j = 0; j < info->bitmap_count; j++) { if (!info->bitmaps[j].image->bm) continue; info->bm = copy_bitmap(render_priv->engine, info->bitmaps[j].image->bm); @@ -2289,12 +2302,12 @@ } else if (info->n_bm) { info->bm = alloc_bitmap(render_priv->engine, info->rect.x_max - info->rect.x_min + 2 * bord, - info->rect.y_max - info->rect.y_min + 2 * bord); + info->rect.y_max - info->rect.y_min + 2 * bord, true); Bitmap *dst = info->bm; if (dst) { dst->left = info->rect.x_min - info->x - bord; dst->top = info->rect.y_min - info->y - bord; - for (int j = 0; j < info->bitmap_count; ++j) { + for (int j = 0; j < info->bitmap_count; j++) { Bitmap *src = info->bitmaps[j].image->bm; if (!src) continue; @@ -2310,7 +2323,7 @@ } } if (!bord && info->n_bm_o == 1) { - for (int j = 0; j < info->bitmap_count; ++j) { + for (int j = 0; j < info->bitmap_count; j++) { if (!info->bitmaps[j].image->bm_o) continue; info->bm_o = copy_bitmap(render_priv->engine, info->bitmaps[j].image->bm_o); @@ -2323,12 +2336,13 @@ } else if (info->n_bm_o) { info->bm_o = alloc_bitmap(render_priv->engine, info->rect_o.x_max - info->rect_o.x_min + 2 * bord, - info->rect_o.y_max - info->rect_o.y_min + 2 * bord); + info->rect_o.y_max - info->rect_o.y_min + 2 * bord, + true); Bitmap *dst = info->bm_o; if (dst) { dst->left = info->rect_o.x_min - info->x - bord; dst->top = info->rect_o.y_min - info->y - bord; - for (int j = 0; j < info->bitmap_count; ++j) { + for (int j = 0; j < info->bitmap_count; j++) { Bitmap *src = info->bitmaps[j].image->bm_o; if (!src) continue; @@ -2344,19 +2358,20 @@ } } - if(info->bm || info->bm_o){ + if (info->bm || info->bm_o) { ass_synth_blur(render_priv->engine, info->filter.flags & FILTER_BORDER_STYLE_3, info->filter.be, info->filter.blur, info->bm, info->bm_o); if (info->filter.flags & FILTER_DRAW_SHADOW) make_shadow_bitmap(info, render_priv); } - CompositeHashValue chv; - chv.bm = info->bm; - chv.bm_o = info->bm_o; - chv.bm_s = info->bm_s; - - ass_cache_put(render_priv->cache.composite_cache, &hk, &chv); + hv->bm = info->bm; + hv->bm_o = info->bm_o; + hv->bm_s = info->bm_s; + ass_cache_commit(hv, bitmap_size(hv->bm) + + bitmap_size(hv->bm_o) + bitmap_size(hv->bm_s) + + sizeof(CompositeHashKey) + sizeof(CompositeHashValue)); + info->image = hv; } text_info->n_bitmaps = nb_bitmaps; @@ -2364,21 +2379,19 @@ static void add_background(ASS_Renderer *render_priv, EventImages *event_images) { - void *nbuffer = ass_aligned_alloc(1, event_images->width * event_images->height); - if (!free_list_add(render_priv, nbuffer)) { - ass_aligned_free(nbuffer); - } else { - memset(nbuffer, 0xFF, event_images->width * event_images->height); - ASS_Image *img = my_draw_bitmap(nbuffer, event_images->width, - event_images->height, - event_images->width, - event_images->left, - event_images->top, - render_priv->state.c[3]); - if (img) { - img->next = event_images->imgs; - event_images->imgs = img; - } + void *nbuffer = ass_aligned_alloc(1, event_images->width * event_images->height, false); + if (!nbuffer) + return; + memset(nbuffer, 0xFF, event_images->width * event_images->height); + ASS_Image *img = my_draw_bitmap(nbuffer, event_images->width, + event_images->height, + event_images->width, + event_images->left, + event_images->top, + render_priv->state.c[3], NULL); + if (img) { + img->next = event_images->imgs; + event_images->imgs = img; } } @@ -2622,41 +2635,13 @@ } /** - * \brief deallocate image list - * \param img list pointer - */ -void ass_free_images(ASS_Image *img) -{ - while (img) { - ASS_Image *next = img->next; - free(img); - img = next; - } -} - -/** * \brief Check cache limits and reset cache if they are exceeded */ static void check_cache_limits(ASS_Renderer *priv, CacheStore *cache) { - if (ass_cache_empty(cache->bitmap_cache, cache->bitmap_max_size)) { - ass_cache_empty(cache->composite_cache, 0); - ass_free_images(priv->prev_images_root); - priv->prev_images_root = 0; - priv->cache_cleared = 1; - } - if (ass_cache_empty(cache->outline_cache, cache->glyph_max)) { - ass_cache_empty(cache->bitmap_cache, 0); - ass_cache_empty(cache->composite_cache, 0); - ass_free_images(priv->prev_images_root); - priv->prev_images_root = 0; - priv->cache_cleared = 1; - } - if (ass_cache_empty(cache->composite_cache, cache->composite_max_size)) { - ass_free_images(priv->prev_images_root); - priv->prev_images_root = 0; - priv->cache_cleared = 1; - } + ass_cache_cut(cache->composite_cache, cache->composite_max_size); + ass_cache_cut(cache->bitmap_cache, cache->bitmap_max_size); + ass_cache_cut(cache->outline_cache, cache->glyph_max); } /** @@ -2678,8 +2663,6 @@ if (render_priv->library != track->library) return 1; - free_list_clear(render_priv); - if (track->n_events == 0) return 1; // nothing to do @@ -2708,7 +2691,7 @@ render_priv->font_scale_x = par; render_priv->prev_images_root = render_priv->images_root; - render_priv->images_root = 0; + render_priv->images_root = NULL; check_cache_limits(render_priv, &render_priv->cache); @@ -2928,7 +2911,7 @@ ASS_Image *img, *img2; int diff; - if (priv->cache_cleared || priv->state.has_clips) + if (priv->state.has_clips) return 2; img = priv->prev_images_root; @@ -2980,7 +2963,7 @@ if (detect_change) { *detect_change = 2; } - return 0; + return NULL; } // render events separately @@ -3024,14 +3007,44 @@ cur = cur->next; } } + ass_frame_ref(priv->images_root); if (detect_change) *detect_change = ass_detect_change(priv); // free the previous image list - ass_free_images(priv->prev_images_root); - priv->prev_images_root = 0; - priv->cache_cleared = 0; + ass_frame_unref(priv->prev_images_root); + priv->prev_images_root = NULL; return priv->images_root; } + +/** + * \brief Add reference to a frame image list. + * \param image_list image list returned by ass_render_frame() + */ +void ass_frame_ref(ASS_Image *img) +{ + if (!img) + return; + ((ASS_ImagePriv *) img)->ref_count++; +} + +/** + * \brief Release reference to a frame image list. + * \param image_list image list returned by ass_render_frame() + */ +void ass_frame_unref(ASS_Image *img) +{ + if (!img || --((ASS_ImagePriv *) img)->ref_count) + return; + do { + ASS_ImagePriv *priv = (ASS_ImagePriv *) img; + img = img->next; + if (priv->source) + ass_cache_dec_ref(priv->source); + else + ass_aligned_free(priv->result.bitmap); + free(priv); + } while (img); +} diff -Nru libass-0.13.2/libass/ass_render.h libass-0.13.4/libass/ass_render.h --- libass-0.13.2/libass/ass_render.h 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_render.h 2016-07-11 21:29:00.000000000 +0000 @@ -42,8 +42,8 @@ #include "ass_rasterizer.h" #define GLYPH_CACHE_MAX 10000 -#define BITMAP_CACHE_MAX_SIZE 500 * 1048576 -#define COMPOSITE_CACHE_MAX_SIZE 500 * 1048576 +#define BITMAP_CACHE_MAX_SIZE 128 * 1048576 +#define COMPOSITE_CACHE_MAX_SIZE 64 * 1048576 #define PARSED_FADE (1<<0) #define PARSED_A (1<<1) @@ -60,10 +60,11 @@ double y; } DVector; -typedef struct free_list { - void *object; - struct free_list *next; -} FreeList; +typedef struct { + ASS_Image result; + CompositeHashValue *source; + size_t ref_count; +} ASS_ImagePriv; typedef struct { int frame_width; @@ -125,8 +126,10 @@ int x, y; Rectangle rect, rect_o; - Bitmap *bm, *bm_o, *bm_s; // glyphs, outline, shadow bitmaps size_t n_bm, n_bm_o; + + Bitmap *bm, *bm_o, *bm_s; // glyphs, outline, shadow bitmaps + CompositeHashValue *image; } CombinedBitmapInfo; // describes a glyph @@ -300,7 +303,6 @@ ASS_Image *images_root; // rendering result is stored here ASS_Image *prev_images_root; - int cache_cleared; EventImages *eimg; // temporary buffer for sorting rendered events int eimg_size; // allocated buffer size @@ -327,9 +329,6 @@ RasterizerData rasterizer; #endif - FreeList *free_head; - FreeList *free_tail; - ASS_Style user_override_style; }; @@ -351,7 +350,8 @@ } Segment; void reset_render_context(ASS_Renderer *render_priv, ASS_Style *style); -void ass_free_images(ASS_Image *img); +void ass_frame_ref(ASS_Image *img); +void ass_frame_unref(ASS_Image *img); // XXX: this is actually in ass.c, includes should be fixed later on void ass_lazy_track_init(ASS_Library *lib, ASS_Track *track); diff -Nru libass-0.13.2/libass/ass_shaper.c libass-0.13.4/libass/ass_shaper.c --- libass-0.13.2/libass/ass_shaper.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_shaper.c 2016-10-04 20:56:28.000000000 +0000 @@ -100,6 +100,7 @@ !ASS_REALLOC_ARRAY(shaper->emblevels, new_size) || !ASS_REALLOC_ARRAY(shaper->cmap, new_size)) return false; + shaper->n_glyphs = new_size; } return true; } @@ -207,28 +208,34 @@ hb_codepoint_t unicode, hb_codepoint_t glyph) { GlyphMetricsHashValue *val; - metrics->hash_key.glyph_index = glyph; - val = ass_cache_get(metrics->metrics_cache, &metrics->hash_key); - - if (!val) { - int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH - | FT_LOAD_IGNORE_TRANSFORM; - GlyphMetricsHashValue new_val; + if (ass_cache_get(metrics->metrics_cache, &metrics->hash_key, &val)) { + if (val->metrics.width >= 0) + return val; + ass_cache_dec_ref(val); + return NULL; + } + if (!val) + return NULL; - if (FT_Load_Glyph(face, glyph, load_flags)) - return NULL; + int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH + | FT_LOAD_IGNORE_TRANSFORM; - memcpy(&new_val.metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics)); + if (FT_Load_Glyph(face, glyph, load_flags)) { + val->metrics.width = -1; + ass_cache_commit(val, 1); + ass_cache_dec_ref(val); + return NULL; + } - // if @font rendering is enabled and the glyph should be rotated, - // make cached_h_advance pick up the right advance later - if (metrics->vertical && unicode >= VERTICAL_LOWER_BOUND) - new_val.metrics.horiAdvance = new_val.metrics.vertAdvance; + memcpy(&val->metrics, &face->glyph->metrics, sizeof(FT_Glyph_Metrics)); - val = ass_cache_put(metrics->metrics_cache, &metrics->hash_key, &new_val); - } + // if @font rendering is enabled and the glyph should be rotated, + // make cached_h_advance pick up the right advance later + if (metrics->vertical && unicode >= VERTICAL_LOWER_BOUND) + val->metrics.horiAdvance = val->metrics.vertAdvance; + ass_cache_commit(val, 1); return val; } @@ -243,12 +250,13 @@ *glyph = FT_Face_GetCharVariantIndex(face, ass_font_index_magic(face, unicode), variation); else *glyph = FT_Get_Char_Index(face, ass_font_index_magic(face, unicode)); + if (!*glyph) + return false; // rotate glyph advances for @fonts while we still know the Unicode codepoints - if (*glyph != 0) - get_cached_metrics(metrics_priv, face, unicode, *glyph); - - return *glyph != 0; + GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, unicode, *glyph); + ass_cache_dec_ref(metrics); + return true; } static hb_position_t @@ -258,11 +266,12 @@ FT_Face face = font_data; struct ass_shaper_metrics_data *metrics_priv = user_data; GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph); - if (!metrics) return 0; - return metrics->metrics.horiAdvance; + hb_position_t advance = metrics->metrics.horiAdvance; + ass_cache_dec_ref(metrics); + return advance; } static hb_position_t @@ -272,19 +281,19 @@ FT_Face face = font_data; struct ass_shaper_metrics_data *metrics_priv = user_data; GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph); - if (!metrics) return 0; - return metrics->metrics.vertAdvance; - + hb_position_t advance = metrics->metrics.vertAdvance; + ass_cache_dec_ref(metrics); + return advance; } static hb_bool_t cached_h_origin(hb_font_t *font, void *font_data, hb_codepoint_t glyph, hb_position_t *x, hb_position_t *y, void *user_data) { - return 1; + return true; } static hb_bool_t @@ -294,14 +303,13 @@ FT_Face face = font_data; struct ass_shaper_metrics_data *metrics_priv = user_data; GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph); - if (!metrics) - return 0; + return false; *x = metrics->metrics.horiBearingX - metrics->metrics.vertBearingX; *y = metrics->metrics.horiBearingY - (-metrics->metrics.vertBearingY); - - return 1; + ass_cache_dec_ref(metrics); + return true; } static hb_position_t @@ -311,7 +319,7 @@ FT_Face face = font_data; FT_Vector kern; - if (FT_Get_Kerning (face, first, second, FT_KERNING_DEFAULT, &kern)) + if (FT_Get_Kerning(face, first, second, FT_KERNING_DEFAULT, &kern)) return 0; return kern.x; @@ -331,16 +339,15 @@ FT_Face face = font_data; struct ass_shaper_metrics_data *metrics_priv = user_data; GlyphMetricsHashValue *metrics = get_cached_metrics(metrics_priv, face, 0, glyph); - if (!metrics) - return 0; + return false; extents->x_bearing = metrics->metrics.horiBearingX; extents->y_bearing = metrics->metrics.horiBearingY; extents->width = metrics->metrics.width; extents->height = -metrics->metrics.height; - - return 1; + ass_cache_dec_ref(metrics); + return true; } static hb_bool_t @@ -353,15 +360,14 @@ | FT_LOAD_IGNORE_TRANSFORM; if (FT_Load_Glyph(face, glyph, load_flags)) - return 0; + return false; if (point_index >= (unsigned)face->glyph->outline.n_points) - return 0; + return false; *x = face->glyph->outline.points[point_index].x; *y = face->glyph->outline.points[point_index].y; - - return 1; + return true; } /** @@ -560,6 +566,7 @@ info->next = malloc(sizeof(GlyphInfo)); if (info->next) { memcpy(info->next, info, sizeof(GlyphInfo)); + ass_cache_inc_ref(info->font); info = info->next; info->next = NULL; } @@ -965,11 +972,10 @@ } /** - * \brief Resolve a Windows font charset number to a suitable - * base direction. 177 and 178 are Hebrew and Arabic respectively, and - * they map to RTL. Everything else maps to LTR for compatibility - * reasons. The special value -1, which is not a legal Windows font charset - * number, can be used for autodetection. + * \brief Resolve a Windows font charset number to a suitable base + * direction. Generally, use LTR for compatibility with VSFilter. The + * special value -1, which is not a legal Windows font charset number, + * can be used for autodetection. * \param enc Windows font encoding */ FriBidiParType resolve_base_direction(int enc) @@ -977,9 +983,6 @@ switch (enc) { case -1: return FRIBIDI_PAR_ON; - case 177: - case 178: - return FRIBIDI_PAR_RTL; default: return FRIBIDI_PAR_LTR; } diff -Nru libass-0.13.2/libass/ass_utils.c libass-0.13.4/libass/ass_utils.c --- libass-0.13.2/libass/ass_utils.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_utils.c 2016-10-04 00:15:27.000000000 +0000 @@ -79,12 +79,13 @@ } #endif -void *ass_aligned_alloc(size_t alignment, size_t size) +void *ass_aligned_alloc(size_t alignment, size_t size, bool zero) { assert(!(alignment & (alignment - 1))); // alignment must be power of 2 if (size >= SIZE_MAX - alignment - sizeof(void *)) return NULL; - char *allocation = malloc(size + sizeof(void *) + alignment - 1); + char *allocation = zero ? calloc(size + sizeof(void *) + alignment - 1, 1) + : malloc(size + sizeof(void *) + alignment - 1); if (!allocation) return NULL; char *ptr = allocation + sizeof(void *); diff -Nru libass-0.13.2/libass/ass_utils.h libass-0.13.4/libass/ass_utils.h --- libass-0.13.2/libass/ass_utils.h 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/libass/ass_utils.h 2016-10-04 00:15:27.000000000 +0000 @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -56,7 +57,7 @@ #define strndup ass_strndup #endif -void *ass_aligned_alloc(size_t alignment, size_t size); +void *ass_aligned_alloc(size_t alignment, size_t size, bool zero); void ass_aligned_free(void *ptr); void *ass_realloc_array(void *ptr, size_t nmemb, size_t size); diff -Nru libass-0.13.2/libass/Makefile.am libass-0.13.4/libass/Makefile.am --- libass-0.13.2/libass/Makefile.am 2016-02-20 19:36:25.000000000 +0000 +++ libass-0.13.4/libass/Makefile.am 2016-10-04 23:08:08.000000000 +0000 @@ -3,7 +3,7 @@ -Wpointer-arith -Wredundant-decls -D_GNU_SOURCE LIBASS_LT_CURRENT = 8 -LIBASS_LT_REVISION = 0 +LIBASS_LT_REVISION = 2 LIBASS_LT_AGE = 3 yasm_verbose = $(yasm_verbose_$(V)) diff -Nru libass-0.13.2/libass/Makefile.in libass-0.13.4/libass/Makefile.in --- libass-0.13.2/libass/Makefile.in 2016-02-20 19:47:11.000000000 +0000 +++ libass-0.13.4/libass/Makefile.in 2016-10-04 23:12:17.000000000 +0000 @@ -374,6 +374,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ @@ -388,7 +389,7 @@ -Wpointer-arith -Wredundant-decls -D_GNU_SOURCE LIBASS_LT_CURRENT = 8 -LIBASS_LT_REVISION = 0 +LIBASS_LT_REVISION = 2 LIBASS_LT_AGE = 3 yasm_verbose = $(yasm_verbose_$(V)) yasm_verbose_ = $(yasm_verbose_$(AM_DEFAULT_VERBOSITY)) diff -Nru libass-0.13.2/ltmain.sh libass-0.13.4/ltmain.sh --- libass-0.13.2/ltmain.sh 2016-02-20 19:47:04.000000000 +0000 +++ libass-0.13.4/ltmain.sh 2016-10-04 23:12:09.000000000 +0000 @@ -31,7 +31,7 @@ PROGRAM=libtool PACKAGE=libtool -VERSION=2.4.6 +VERSION="2.4.6 Debian-2.4.6-0.1" package_revision=2.4.6 @@ -2073,7 +2073,7 @@ autoconf: `($AUTOCONF --version) 2>/dev/null |$SED 1q` Report bugs to . -GNU libtool home page: . +GNU libtool home page: . General help using GNU software: ." exit 0 } @@ -7272,10 +7272,13 @@ # -tp=* Portland pgcc target processor selection # --sysroot=* for sysroot support # -O*, -g*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + # -specs=* GCC specs files # -stdlib=* select c++ std lib with clang + # -fsanitize=* Clang/GCC memory and address sanitizer -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ - -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*) + -O*|-g*|-flto*|-fwhopr*|-fuse-linker-plugin|-fstack-protector*|-stdlib=*| \ + -specs=*|-fsanitize=*) func_quote_for_eval "$arg" arg=$func_quote_for_eval_result func_append compile_command " $arg" @@ -7568,7 +7571,10 @@ case $pass in dlopen) libs=$dlfiles ;; dlpreopen) libs=$dlprefiles ;; - link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + link) + libs="$deplibs %DEPLIBS%" + test "X$link_all_deplibs" != Xno && libs="$libs $dependency_libs" + ;; esac fi if test lib,dlpreopen = "$linkmode,$pass"; then @@ -7887,19 +7893,19 @@ # It is a libtool convenience library, so add in its objects. func_append convenience " $ladir/$objdir/$old_library" func_append old_convenience " $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done elif test prog != "$linkmode" && test lib != "$linkmode"; then func_fatal_error "'$lib' is not a convenience library" fi - tmp_libs= - for deplib in $dependency_libs; do - deplibs="$deplib $deplibs" - if $opt_preserve_dup_deps; then - case "$tmp_libs " in - *" $deplib "*) func_append specialdeplibs " $deplib" ;; - esac - fi - func_append tmp_libs " $deplib" - done continue fi # $pass = conv @@ -8823,6 +8829,9 @@ revision=$number_minor lt_irix_increment=no ;; + *) + func_fatal_configuration "$modename: unknown library version type '$version_type'" + ;; esac ;; no) diff -Nru libass-0.13.2/m4/libtool.m4 libass-0.13.4/m4/libtool.m4 --- libass-0.13.2/m4/libtool.m4 2016-02-20 19:47:04.000000000 +0000 +++ libass-0.13.4/m4/libtool.m4 2016-10-04 23:12:09.000000000 +0000 @@ -2887,6 +2887,18 @@ dynamic_linker='GNU/Linux ld.so' ;; +netbsdelf*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='NetBSD ld.elf_so' + ;; + netbsd*) version_type=sunos need_lib_prefix=no @@ -3546,7 +3558,7 @@ lt_cv_deplibs_check_method=pass_all ;; -netbsd*) +netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' else @@ -4424,7 +4436,7 @@ ;; esac ;; - netbsd*) + netbsd* | netbsdelf*-gnu) ;; *qnx* | *nto*) # QNX uses GNU C++, but need to define -shared option too, otherwise @@ -4936,6 +4948,9 @@ ;; esac ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; *) _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' ;; @@ -4998,6 +5013,9 @@ openbsd* | bitrig*) with_gnu_ld=no ;; + linux* | k*bsd*-gnu | gnu*) + _LT_TAGVAR(link_all_deplibs, $1)=no + ;; esac _LT_TAGVAR(ld_shlibs, $1)=yes @@ -5252,7 +5270,7 @@ fi ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= @@ -5773,6 +5791,7 @@ if test yes = "$lt_cv_irix_exported_symbol"; then _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' fi + _LT_TAGVAR(link_all_deplibs, $1)=no else _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' @@ -5794,7 +5813,7 @@ esac ;; - netbsd*) + netbsd* | netbsdelf*-gnu) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out else diff -Nru libass-0.13.2/Makefile.in libass-0.13.4/Makefile.in --- libass-0.13.2/Makefile.in 2016-02-20 19:47:11.000000000 +0000 +++ libass-0.13.4/Makefile.in 2016-10-04 23:12:17.000000000 +0000 @@ -364,6 +364,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff -Nru libass-0.13.2/profile/Makefile.in libass-0.13.4/profile/Makefile.in --- libass-0.13.2/profile/Makefile.in 2016-02-20 19:47:11.000000000 +0000 +++ libass-0.13.4/profile/Makefile.in 2016-10-04 23:12:17.000000000 +0000 @@ -304,6 +304,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff -Nru libass-0.13.2/test/Makefile.in libass-0.13.4/test/Makefile.in --- libass-0.13.2/test/Makefile.in 2016-02-20 19:47:11.000000000 +0000 +++ libass-0.13.4/test/Makefile.in 2016-10-04 23:12:17.000000000 +0000 @@ -304,6 +304,7 @@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ +runstatedir = @runstatedir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ diff -Nru libass-0.13.2/test/test.c libass-0.13.4/test/test.c --- libass-0.13.2/test/test.c 2016-02-11 21:36:38.000000000 +0000 +++ libass-0.13.4/test/test.c 2016-10-04 20:56:28.000000000 +0000 @@ -186,6 +186,7 @@ printf("%s'%s'", separator, font_provider_labels[providers[i]]); } printf(".\n"); + free(providers); } int main(int argc, char *argv[])